diff options
Diffstat (limited to 'icebox/icebox.py')
-rw-r--r-- | icebox/icebox.py | 269 |
1 files changed, 246 insertions, 23 deletions
diff --git a/icebox/icebox.py b/icebox/icebox.py index 01cda0d..60b5dc2 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -30,19 +30,23 @@ class iceconfig: self.device = "" self.logic_tiles = dict() self.io_tiles = dict() - self.ram_tiles = dict() - self.ram_init = dict() + self.ramb_tiles = dict() + self.ramt_tiles = dict() self.extra_bits = set() def setup_empty_1k(self): self.clear() + self.device = "1k" self.max_x = 13 self.max_y = 17 for x in range(1, self.max_x): for y in range(1, self.max_y): if x in (3, 10): - self.ram_tiles[(x, y)] = ["0" * 42 for i in range(16)] + if y % 2 == 1: + self.ramb_tiles[(x, y)] = ["0" * 42 for i in range(16)] + else: + self.ramt_tiles[(x, y)] = ["0" * 42 for i in range(16)] else: self.logic_tiles[(x, y)] = ["0" * 54 for i in range(16)] @@ -63,15 +67,36 @@ class iceconfig: def tile(self, x, y): if (x, y) in self.io_tiles: return self.io_tiles[(x, y)] if (x, y) in self.logic_tiles: return self.logic_tiles[(x, y)] - if (x, y) in self.ram_tiles: return self.ram_tiles[(x, y)] + if (x, y) in self.ramb_tiles: return self.ramb_tiles[(x, y)] + if (x, y) in self.ramt_tiles: return self.ramt_tiles[(x, y)] return None + def pinloc_db(self): + assert self.device == "1k" + return pinloc_db + + def gbufin_db(self): + return gbufin_db[self.device] + + def icegate_db(self): + return icegate_db[self.device] + + def padin_pio_db(self): + return padin_pio_db[self.device] + + def extra_bits_db(self): + return extra_bits_db[self.device] + + def ieren_db(self): + return ieren_db[self.device] + def tile_db(self, x, y): if x == 0: return iotile_l_db if y == 0: return iotile_b_db if x == self.max_x: return iotile_r_db if y == self.max_y: return iotile_t_db - if (x, y) in self.ram_tiles: return ramtile_db + if (x, y) in self.ramb_tiles: return rambtile_db + if (x, y) in self.ramt_tiles: return ramttile_db if (x, y) in self.logic_tiles: return logictile_db assert False @@ -80,7 +105,8 @@ class iceconfig: if y == 0: return "IO" if x == self.max_x: return "IO" if y == self.max_y: return "IO" - if (x, y) in self.ram_tiles: return "RAM" + if (x, y) in self.ramb_tiles: return "RAMB" + if (x, y) in self.ramt_tiles: return "RAMT" if (x, y) in self.logic_tiles: return "LOGIC" assert False @@ -96,7 +122,6 @@ class iceconfig: if entry[1] in ("routing", "buffer"): return self.tile_has_net(x, y, entry[2]) and self.tile_has_net(x, y, entry[3]) return True - def tile_has_net(self, x, y, netname): if netname.startswith("logic_op_"): @@ -161,7 +186,12 @@ class iceconfig: if npos is not None and pos is not None: if npos == "x": - return (nx, ny, "lutff_%d/out" % func) + if (nx, ny) in self.logic_tiles: + return (nx, ny, "lutff_%d/out" % func) + if (nx, ny) in self.ramb_tiles: + return (nx, ny, "ram/RDATA_%d" % func) + if (nx, ny) in self.ramt_tiles: + return (nx, ny, "ram/RDATA_%d" % (8+func)) elif pos == "x" and npos in ("l", "r", "t", "b"): if func in (0, 4): return (nx, ny, "io_0/D_IN_0") @@ -194,6 +224,10 @@ class iceconfig: if match: funcnets |= self.follow_funcnet(x, y, int(match.group(1))) + match = re.match(r"ram/RDATA_(\d+)", netname) + if match: + funcnets |= self.follow_funcnet(x, y, int(match.group(1)) % 8) + return funcnets def follow_net(self, netspec): @@ -273,12 +307,22 @@ class iceconfig: neighbours.add((s[0], s[1], s[2])) return neighbours - def group_segments(self, all_from_tiles=set()): + def group_segments(self, all_from_tiles=set(), extra_connections=list(), extra_segments=list()): seed_segments = set() seen_segments = set() connected_segments = dict() grouped_segments = set() + for seg in extra_segments: + seed_segments.add(seg) + + for conn in extra_connections: + s1, s2 = conn + connected_segments.setdefault(s1, set()).add(s2) + connected_segments.setdefault(s2, set()).add(s1) + seed_segments.add(s1) + seed_segments.add(s2) + for idx, tile in self.io_tiles.items(): tc = tileconfig(tile) pintypes = [ list("000000"), list("000000") ] @@ -314,8 +358,44 @@ class iceconfig: seed_segments.add((idx[0], idx[1], "lutff_7/cout")) add_seed_segments(idx, tile, logictile_db) - for idx, tile in self.ram_tiles.items(): - add_seed_segments(idx, tile, ramtile_db) + for idx, tile in self.ramb_tiles.items(): + add_seed_segments(idx, tile, rambtile_db) + + for idx, tile in self.ramt_tiles.items(): + add_seed_segments(idx, tile, ramttile_db) + + for padin, pio in enumerate(self.padin_pio_db()): + s1 = (pio[0], pio[1], "wire_gbuf/padin_%d" % pio[2]) + s2 = (pio[0], pio[1], "glb_netwk_%d" % padin) + if s1 in seed_segments or (pio[0], pio[1]) in all_from_tiles: + connected_segments.setdefault(s1, set()).add(s2) + connected_segments.setdefault(s2, set()).add(s1) + seed_segments.add(s1) + seed_segments.add(s2) + + for entry in self.icegate_db(): + if entry[0] == 0 or entry[0] == self.max_x: + iocells = [(entry[0], i) for i in range(1, self.max_y)] + if entry[1] == 0 or entry[1] == self.max_y: + iocells = [(i, entry[1]) for i in range(1, self.max_x)] + for cell in iocells: + s1 = (entry[0], entry[1], "wire_gbuf/in") + s2 = (cell[0], cell[1], "io_global/latch") + if s1 in seed_segments or s2 in seed_segments or \ + (entry[0], entry[1]) in all_from_tiles or (cell[0], cell[1]) in all_from_tiles: + connected_segments.setdefault(s1, set()).add(s2) + connected_segments.setdefault(s2, set()).add(s1) + seed_segments.add(s1) + seed_segments.add(s2) + + for entry in self.gbufin_db(): + s1 = (entry[0], entry[1], "wire_gbuf/in") + s2 = (entry[0], entry[1], "glb_netwk_%d" % entry[2]) + if s1 in seed_segments or (pio[0], pio[1]) in all_from_tiles: + connected_segments.setdefault(s1, set()).add(s2) + connected_segments.setdefault(s2, set()).add(s1) + seed_segments.add(s1) + seed_segments.add(s2) while seed_segments: queue = set() @@ -373,7 +453,7 @@ class iceconfig: expected_data_lines -= 1 continue assert expected_data_lines <= 0 - if line[0] in (".io_tile", ".logic_tile", ".ram_tile"): + if line[0] in (".io_tile", ".logic_tile", ".ramb_tile", ".ramt_tile"): current_data = list() expected_data_lines = 16 self.max_x = max(self.max_x, int(line[1])) @@ -384,8 +464,11 @@ class iceconfig: if line[0] == ".logic_tile": self.logic_tiles[(int(line[1]), int(line[2]))] = current_data continue - if line[0] == ".ram_tile": - self.ram_tiles[(int(line[1]), int(line[2]))] = current_data + if line[0] == ".ramb_tile": + self.ramb_tiles[(int(line[1]), int(line[2]))] = current_data + continue + if line[0] == ".ramt_tile": + self.ramt_tiles[(int(line[1]), int(line[2]))] = current_data continue if line[0] == ".extra_bit": self.extra_bits.add((int(line[1]), int(line[2]), int(line[3]))) @@ -394,7 +477,7 @@ class iceconfig: assert line[1] in ["1k"] self.device = line[1] continue - if line[0] == ".comment": + if line[0] in [".comment", ".sym"]: expected_data_lines = -1 continue print("%sWarning: ignoring line %d: %s" % (logprefix, linenum, linetext.strip())) @@ -532,7 +615,7 @@ def sp12v_normalize(netname, edge=""): return netname -def netname_normalize(netname, edge=""): +def netname_normalize(netname, edge="", ramb=False, ramt=False): if netname.startswith("sp4_v_"): return sp4v_normalize(netname, edge) if netname.startswith("sp4_h_"): return sp4h_normalize(netname, edge) if netname.startswith("sp12_v_"): return sp12v_normalize(netname, edge) @@ -542,6 +625,12 @@ def netname_normalize(netname, edge=""): netname = netname.replace("lc_", "lutff_") netname = netname.replace("wire_logic_cluster/", "") netname = netname.replace("wire_io_cluster/", "") + netname = netname.replace("wire_bram/", "") + if (ramb or ramt) and netname.startswith("input"): + match = re.match(r"input(\d)_(\d)", netname) + idx1, idx2 = (int(match.group(1)), int(match.group(2))) + if ramb: netname="ram/WADDR_%d" % (idx1*4 + idx2) + if ramt: netname="ram/RADDR_%d" % (idx1*4 + idx2) match = re.match(r"(...)_op_(.*)", netname) if match: netname = "neigh_op_%s_%s" % (match.group(1), match.group(2)) @@ -739,8 +828,7 @@ def cmp_netnames(a, b): def run_checks_neigh(): print("Running consistency checks on neighbour finder..") ic = iceconfig() - ic.max_x = 6 - ic.max_y = 6 + ic.setup_empty_1k() all_segments = set() @@ -758,6 +846,10 @@ def run_checks_neigh(): continue if x in (0, ic.max_x) or y in (0, ic.max_y): add_segments((x, y), ic.tile_db(x, y)) + elif (x, y) in ic.ramb_tiles: + add_segments((x, y), ic.tile_db(x, y)) + elif (x, y) in ic.ramt_tiles: + add_segments((x, y), ic.tile_db(x, y)) else: add_segments((x, y), logictile_db) all_segments.add((x, y, "lutff_7/cout")) @@ -789,13 +881,144 @@ def parse_db(text): extra_bits_db = { "1k": { - (0, 331, 142): ("routing", "padin_1", "glb_netwk_1") + (0, 330, 142): ("padin_glb_netwk", "0"), + (0, 331, 142): ("padin_glb_netwk", "1"), + (1, 330, 143): ("padin_glb_netwk", "2"), + (1, 331, 143): ("padin_glb_netwk", "3"), + (1, 330, 142): ("padin_glb_netwk", "4"), + (1, 331, 142): ("padin_glb_netwk", "5"), + (0, 330, 143): ("padin_glb_netwk", "6"), + (0, 331, 143): ("padin_glb_netwk", "7"), } } +gbufin_db = { + "1k": [ + (13, 8, 7), + ( 0, 8, 6), + ( 7, 17, 1), + ( 7, 0, 0), + ( 0, 9, 3), + (13, 9, 2), + ( 6, 0, 5), + ( 6, 17, 4), + ] +} + +icegate_db = { + "1k": [ + ( 0, 7), + (13, 10), + ( 5, 0), + ( 8, 17) + ] +} + +padin_pio_db = { + "1k": [ + (13, 8, 1), # glb_netwk_0 + ( 0, 8, 1), # glb_netwk_1 + ( 7, 17, 0), # glb_netwk_2 + ( 7, 0, 0), # glb_netwk_3 + ( 0, 9, 0), # glb_netwk_4 + (13, 9, 0), # glb_netwk_5 + ( 6, 0, 1), # glb_netwk_6 + ( 6, 17, 1), # glb_netwk_7 + ] +} + +ieren_db = { + "1k": [ + # IO-block (X, Y, Z) <-> IeRen-block (X, Y, Z) + ( 0, 14, 1, 0, 14, 0), + ( 0, 14, 0, 0, 14, 1), + ( 0, 13, 1, 0, 13, 0), + ( 0, 13, 0, 0, 13, 1), + ( 0, 12, 1, 0, 12, 0), + ( 0, 12, 0, 0, 12, 1), + ( 0, 11, 1, 0, 11, 0), + ( 0, 11, 0, 0, 11, 1), + ( 0, 10, 1, 0, 10, 0), + ( 0, 10, 0, 0, 10, 1), + ( 0, 9, 1, 0, 9, 0), + ( 0, 8, 0, 0, 8, 1), + ( 0, 6, 1, 0, 6, 0), + ( 0, 6, 0, 0, 6, 1), + ( 0, 5, 1, 0, 5, 0), + ( 0, 5, 0, 0, 5, 1), + ( 0, 4, 1, 0, 4, 0), + ( 0, 4, 0, 0, 4, 1), + ( 0, 3, 1, 0, 3, 0), + ( 0, 3, 0, 0, 3, 1), + ( 0, 2, 1, 0, 2, 0), + ( 0, 2, 0, 0, 2, 1), + ( 1, 0, 0, 1, 0, 0), + ( 1, 0, 1, 1, 0, 1), + ( 2, 0, 1, 2, 0, 1), + ( 3, 0, 0, 3, 0, 0), + ( 3, 0, 1, 3, 0, 1), + ( 4, 0, 0, 4, 0, 0), + ( 4, 0, 1, 4, 0, 1), + ( 5, 0, 0, 5, 0, 0), + ( 5, 0, 1, 5, 0, 1), + ( 6, 0, 0, 7, 0, 0), + ( 7, 0, 1, 7, 0, 1), + ( 8, 0, 0, 8, 0, 0), + ( 8, 0, 1, 8, 0, 1), + ( 9, 0, 0, 9, 0, 0), + ( 9, 0, 1, 9, 0, 1), + (10, 0, 0, 10, 0, 0), + (10, 0, 1, 10, 0, 1), + (13, 1, 0, 13, 1, 0), + (13, 1, 1, 13, 1, 1), + (13, 2, 0, 13, 2, 0), + (13, 2, 1, 13, 2, 1), + (13, 3, 1, 13, 3, 1), + (13, 4, 0, 13, 4, 0), + (13, 4, 1, 13, 4, 1), + (13, 6, 0, 13, 6, 0), + (13, 6, 1, 13, 6, 1), + (13, 7, 0, 13, 7, 0), + (13, 7, 1, 13, 7, 1), + (13, 8, 0, 13, 8, 0), + (13, 9, 1, 13, 9, 1), + (13, 11, 0, 13, 10, 0), + (13, 11, 1, 13, 10, 1), + (13, 12, 0, 13, 11, 0), + (13, 13, 0, 13, 13, 0), + (13, 13, 1, 13, 13, 1), + (13, 14, 0, 13, 14, 0), + (13, 14, 1, 13, 14, 1), + (13, 15, 0, 13, 15, 0), + (13, 15, 1, 13, 15, 1), + (12, 17, 1, 12, 17, 1), + (12, 17, 0, 12, 17, 0), + (11, 17, 1, 11, 17, 1), + (11, 17, 0, 11, 17, 0), + (10, 17, 1, 9, 17, 1), + (10, 17, 0, 9, 17, 0), + ( 9, 17, 1, 10, 17, 1), + ( 9, 17, 0, 10, 17, 0), + ( 8, 17, 1, 8, 17, 1), + ( 8, 17, 0, 8, 17, 0), + ( 7, 17, 1, 7, 17, 1), + ( 5, 17, 1, 5, 17, 1), + ( 5, 17, 0, 5, 17, 0), + ( 4, 17, 1, 4, 17, 1), + ( 4, 17, 0, 4, 17, 0), + ( 3, 17, 1, 3, 17, 1), + ( 3, 17, 0, 3, 17, 0), + ( 2, 17, 1, 2, 17, 1), + ( 2, 17, 0, 2, 17, 0), + ( 1, 17, 1, 1, 17, 1), + ( 1, 17, 0, 1, 17, 0) + ] +} + iotile_full_db = parse_db(iceboxdb.database_io_txt) logictile_db = parse_db(iceboxdb.database_logic_txt) -ramtile_db = parse_db(iceboxdb.database_ram_txt) +rambtile_db = parse_db(iceboxdb.database_ramb_txt) +ramttile_db = parse_db(iceboxdb.database_ramt_txt) pinloc_db = [[int(s) for s in line.split()] for line in iceboxdb.pinloc_txt.split("\n") if line != ""] iotile_l_db = list() @@ -829,11 +1052,11 @@ for entry in iotile_full_db: logictile_db.append([["B1[49]"], "buffer", "carry_in", "carry_in_mux"]) logictile_db.append([["B1[50]"], "CarryInSet"]) -for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, logictile_db, ramtile_db]: +for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, logictile_db, rambtile_db, ramttile_db]: for entry in db: if entry[1] in ("buffer", "routing"): - entry[2] = netname_normalize(entry[2]) - entry[3] = netname_normalize(entry[3]) + entry[2] = netname_normalize(entry[2], ramb=(db == rambtile_db), ramt=(db == ramttile_db)) + entry[3] = netname_normalize(entry[3], ramb=(db == rambtile_db), ramt=(db == ramttile_db)) unique_entries = dict() while db: entry = db.pop() |