1#!/usr/bin/env python3 2 3import re, sys, os 4 5device_class = os.getenv("ICEDEVICE") 6 7def sort_bits_key(a): 8 if a[0] == "!": a = a[1:] 9 return re.sub(r"\d+", lambda m: "%02d" % int(m.group(0)), a) 10 11def read_database(filename, tile_type): 12 raw_db = list() 13 route_to_buffer = set() 14 add_mux_bits = dict() 15 16 with open(filename, "r") as f: 17 for line in f: 18 line = line.strip() 19 m = re.match(r"\s*\((\d+)\s+(\d+)\)\s+(.*)", line) 20 assert m 21 bit = "B%d[%d]" % (int(m.group(2)), int(m.group(1))) 22 line = m.group(3) 23 line = re.sub(r"^Enable bit of Mux", "MuxEn", line) 24 line = re.sub(r"^IO control bit:", "IoCtrl", line) 25 line = re.sub(r"^Column buffer control bit:", "ColBufCtrl", line) 26 line = re.sub(r"^Negative Clock bit", "NegClk", line) 27 line = re.sub(r"^Cascade (buffer Enable )?bit:", "Cascade", line) 28 line = re.sub(r"^Ram config bit:", "RamConfig", line) 29 line = re.sub(r"^PLL config bit:", "PLL", line) 30 line = re.sub(r"^Icegate Enable bit:", "Icegate", line) 31 line = re.sub(r"^MAC16 functional bit:", "IpConfig", line) 32 line = re.sub(r"^Hard IP config bit:", "IpConfig", line) 33 34 line = line.split() 35 if line[0] == "routing": 36 if line[3] == "wire_gbuf/in": line[3] = "fabout" 37 raw_db.append((bit, (line[0], line[1], line[3]))) 38 elif line[0] == "IoCtrl": 39 line[1] = re.sub(r"^.*?_", "", line[1]).replace("_en", "") 40 # LP384 chips have reversed IE_0/IE_1 and REN_0/REN_1 bit assignments 41 # we simply use the assignments for 1k/8k for all chips and fix it in ieren_db 42 if bit == "B6[3]" and line == ['IoCtrl', 'IE_0']: continue 43 if bit == "B9[3]" and line == ['IoCtrl', 'IE_1']: continue 44 if bit == "B1[3]" and line == ['IoCtrl', 'REN_0']: continue 45 if bit == "B6[2]" and line == ['IoCtrl', 'REN_1']: continue 46 # Ignore some additional configuration bits that sneaked in via ice5k fuzzing 47 if line[0] == "IoCtrl" and line[1].startswith("cf_bit_"): continue 48 if line[0] == "IoCtrl" and line[1].startswith("extra_padeb_test_"): continue 49 raw_db.append((bit, (line[0], line[1]))) 50 elif line[0] in ("IOB_0", "IOB_1"): 51 if line[1] != "IO": 52 raw_db.append((bit, (line[0], line[1]))) 53 elif line[0] == "PLL": 54 line[1] = re.sub(r"CLOCK_T_\d+_\d+_IO(LEFT|RIGHT|UP|DOWN)_", "pll_", line[1]) 55 line[1] = re.sub(r"pll_cf_bit_", "PLLCONFIG_", line[1]) 56 raw_db.append((bit, (line[0], line[1]))) 57 elif line[0] == "ColBufCtrl": 58 line[1] = re.sub(r"B?IO(LEFT|RIGHT)_", "IO_", line[1]) 59 line[1] = re.sub(r"IO_half_column_clock_enable_", "glb_netwk_", line[1]) 60 line[1] = re.sub(r"(LH|MEM[BT]|MULT\d|IPCON)_colbuf_cntl_", "glb_netwk_", line[1]) 61 if m.group(1) == "7": 62 line[1] = re.sub(r"glb_netwk_", "8k_glb_netwk_", line[1]) 63 elif m.group(1) in ["1", "2"]: 64 line[1] = re.sub(r"glb_netwk_", "1k_glb_netwk_", line[1]) 65 raw_db.append((bit, (line[0], line[1]))) 66 elif line[0] == "Cascade": 67 match = re.match("LH_LC0(\d)_inmux02_5", line[1]) 68 if match: 69 raw_db.append((bit, ("buffer", "wire_logic_cluster/lc_%d/lout" % (int(match.group(1))-1), "input_2_%s" % match.group(1)))) 70 else: 71 match = re.match("MEMT_LC\d+_inmux\d+_bram_cbit_(\d+)", line[1]) 72 if match: 73 raw_db.append((bit, ("RamCascade", "CBIT_%d" % int(match.group(1))))) 74 else: 75 raw_db.append((bit, (line[0], line[1]))) 76 elif line[0] == "RamConfig": 77 if line[1] == "MEMB_Power_Up_Control": line[1] = "PowerUp" 78 line[1] = re.sub(r"MEMT_bram_cbit_", "CBIT_", line[1]) 79 raw_db.append((bit, (line[0], line[1]))) 80 elif line[0] == "MuxEn": 81 if line[4] == "wire_gbuf/in": line[4] = "fabout" 82 if line[3].startswith("logic_op_"): 83 for prefix in ["IO_L.", "IO_R.", "IO_T.", "IO_B."]: 84 route_to_buffer.add((prefix + line[3], line[4])) 85 add_mux_bits.setdefault(prefix + line[3], set()).add((bit, ("buffer", prefix + line[3], line[4]))) 86 else: 87 raw_db.append((bit, ("buffer", line[3], line[4]))) 88 route_to_buffer.add((line[3], line[4])) 89 elif line[0] == "NegClk" or line[0] == "Icegate" or re.match(r"LC_\d+", line[0]): 90 raw_db.append((bit, (line[0],))) 91 elif line[0] == "Carry_In_Mux": 92 continue 93 elif line[0] == "IpConfig": 94 line[1] = re.sub(r"MULT\d_bram_cbit_", "CBIT_", line[1]) #not a typo, sometimes IP config bits are in DSP tiles and use a MULT prefix... 95 line[1] = re.sub(r"IPCON_bram_cbit_", "CBIT_", line[1]) 96 raw_db.append((bit, (line[0], line[1]))) 97 else: 98 print("unsupported statement: %s: %s" % (bit, line)) 99 assert False 100 101 for i in range(len(raw_db)): 102 if raw_db[i][1][0] == "routing" and (raw_db[i][1][1], raw_db[i][1][2]) in route_to_buffer: 103 if raw_db[i][1][1] in add_mux_bits: 104 for entry in add_mux_bits[raw_db[i][1][1]]: 105 raw_db.append(entry) 106 raw_db[i] = (raw_db[i][0], ("buffer", raw_db[i][1][1], raw_db[i][1][2])) 107 108 func_to_bits = dict() 109 for entry in raw_db: 110 func_to_bits.setdefault(entry[1], set()).add(entry[0]) 111 112 bit_groups = dict() 113 for func, bits in list(func_to_bits.items()): 114 for bit in bits: 115 bit_groups[bit] = bit_groups.setdefault(bit, set()).union(bits) 116 117 for func in func_to_bits: 118 new_bits = set() 119 for bit2 in func_to_bits[func]: 120 for bit in bit_groups[bit2]: 121 if bit in func_to_bits[func]: 122 new_bits.add(bit) 123 else: 124 new_bits.add("!" + bit) 125 func_to_bits[func] = new_bits 126 127 database = list() 128 for func in sorted(func_to_bits): 129 bits = func_to_bits[func] 130 entry = (",".join(sorted(bits, key=sort_bits_key)),) + func 131 database.append(entry) 132 133 return database 134 135with open("database_io.txt", "w") as f: 136 for entry in read_database("bitdata_io.txt", "io"): 137 print("\t".join(entry), file=f) 138 139with open("database_logic.txt", "w") as f: 140 for entry in read_database("bitdata_logic.txt", "logic"): 141 print("\t".join(entry), file=f) 142 143with open("database_ramb.txt", "w") as f: 144 for entry in read_database("bitdata_ramb.txt", "ramb"): 145 print("\t".join(entry), file=f) 146 147with open("database_ramt.txt", "w") as f: 148 for entry in read_database("bitdata_ramt.txt", "ramt"): 149 print("\t".join(entry), file=f) 150 151for device_class in ["8k"]: 152 with open("database_ramb_%s.txt" % (device_class, ), "w") as f: 153 for entry in read_database("bitdata_ramb_%s.txt" % (device_class, ), "ramb_" + device_class): 154 print("\t".join(entry), file=f) 155 156 with open("database_ramt_%s.txt" % (device_class, ), "w") as f: 157 for entry in read_database("bitdata_ramt_%s.txt" % (device_class, ), "ramt_" + device_class): 158 print("\t".join(entry), file=f) 159 160for dsp_idx in range(4): 161 with open("database_dsp%d_5k.txt" % (dsp_idx, ), "w") as f: 162 for entry in read_database("bitdata_dsp%d_5k.txt" % (dsp_idx, ), "dsp%d_5" % (dsp_idx, )): 163 print("\t".join(entry), file=f) 164with open("database_ipcon_5k.txt", "w") as f: 165 for entry in read_database("bitdata_ipcon_5k.txt", "ipcon"): 166 print("\t".join(entry), file=f) 167