aboutsummaryrefslogtreecommitdiffstats
path: root/icebox/icebox.py
diff options
context:
space:
mode:
Diffstat (limited to 'icebox/icebox.py')
-rw-r--r--icebox/icebox.py269
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()