mirror of https://github.com/YosysHQ/icestorm.git
Import of icestorm-snapshot-150413.zip
This commit is contained in:
parent
0347c37d56
commit
c41701ca3a
269
icebox/icebox.py
269
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()
|
||||
|
|
|
|||
|
|
@ -40,10 +40,22 @@ print("""#
|
|||
# Quick File Format Reference:
|
||||
# ----------------------------
|
||||
#
|
||||
# .device DEVICE
|
||||
#
|
||||
# declares the device type (e.g. "1k")
|
||||
#
|
||||
#
|
||||
# .pins PACKAGE
|
||||
# PIN_NUM TILE_X TILE_Y PIO_NUM PADIN_NUM
|
||||
# ...
|
||||
#
|
||||
# associates a package pin with an IO tile and block
|
||||
#
|
||||
#
|
||||
# .io_tile X Y
|
||||
# .logic_tile X Y
|
||||
# .ram_tile X Y
|
||||
# .ramb_tile X Y
|
||||
# .ramt_tile X Y
|
||||
#
|
||||
# declares the existence of a IO/LOGIC/RAM tile with the given coordinates
|
||||
#
|
||||
|
|
@ -73,6 +85,18 @@ print("""#
|
|||
#
|
||||
""")
|
||||
|
||||
print(".device 1k")
|
||||
print()
|
||||
|
||||
print(".pins tq144")
|
||||
pio_to_padin = dict()
|
||||
for padin, pio in enumerate(ic.padin_pio_db()):
|
||||
pio_to_padin[pio] = padin
|
||||
for entry in sorted(ic.pinloc_db()):
|
||||
pio = (entry[1], entry[2], entry[3])
|
||||
print("%d %d %d %d %d" % tuple(entry + [pio_to_padin[pio] if pio in pio_to_padin else -1]))
|
||||
print()
|
||||
|
||||
for idx in sorted(ic.io_tiles):
|
||||
print(".io_tile %d %d" % idx)
|
||||
print()
|
||||
|
|
@ -81,8 +105,12 @@ for idx in sorted(ic.logic_tiles):
|
|||
print(".logic_tile %d %d" % idx)
|
||||
print()
|
||||
|
||||
for idx in sorted(ic.ram_tiles):
|
||||
print(".ram_tile %d %d" % idx)
|
||||
for idx in sorted(ic.ramb_tiles):
|
||||
print(".ramb_tile %d %d" % idx)
|
||||
print()
|
||||
|
||||
for idx in sorted(ic.ramt_tiles):
|
||||
print(".ramt_tile %d %d" % idx)
|
||||
print()
|
||||
|
||||
for group in sorted(ic.group_segments(all_tiles)):
|
||||
|
|
|
|||
|
|
@ -53,5 +53,6 @@ def diff_tiles(stmt, tiles1, tiles2):
|
|||
|
||||
diff_tiles(".io_tile", ic1.io_tiles, ic2.io_tiles)
|
||||
diff_tiles(".logic_tile", ic1.logic_tiles, ic2.logic_tiles)
|
||||
diff_tiles(".ram_tile", ic1.ram_tiles, ic2.ram_tiles)
|
||||
diff_tiles(".ramb_tile", ic1.ramb_tiles, ic2.ramb_tiles)
|
||||
diff_tiles(".ramt_tile", ic1.ramt_tiles, ic2.ramt_tiles)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,11 @@ import getopt, sys, re
|
|||
print_bits = False
|
||||
print_map = False
|
||||
single_tile = None
|
||||
print_all = False
|
||||
|
||||
def usage():
|
||||
print("""
|
||||
Usage: icebox_explain [options] <bitmap.txt>
|
||||
Usage: icebox_explain [options] [bitmap.txt]
|
||||
|
||||
-b
|
||||
print config bit names for each config statement
|
||||
|
|
@ -35,13 +36,16 @@ Usage: icebox_explain [options] <bitmap.txt>
|
|||
-m
|
||||
print tile config bitmaps
|
||||
|
||||
-A
|
||||
don't skip uninteresting tiles
|
||||
|
||||
-t '<x-coordinate> <y-coordinate>'
|
||||
print only the specified tile
|
||||
""")
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "bmt:")
|
||||
opts, args = getopt.getopt(sys.argv[1:], "bmAt:")
|
||||
except:
|
||||
usage()
|
||||
|
||||
|
|
@ -50,11 +54,19 @@ for o, a in opts:
|
|||
print_bits = True
|
||||
elif o == "-m":
|
||||
print_map = True
|
||||
elif o == "-A":
|
||||
print_all = True
|
||||
elif o == "-t":
|
||||
single_tile = tuple([int(s) for s in a.split()])
|
||||
else:
|
||||
usage()
|
||||
|
||||
if len(args) == 0:
|
||||
args.append("/dev/stdin")
|
||||
|
||||
if len(args) != 1:
|
||||
usage()
|
||||
|
||||
print("Reading file '%s'.." % args[0])
|
||||
ic = icebox.iceconfig()
|
||||
ic.read_file(args[0])
|
||||
|
|
@ -96,7 +108,7 @@ def print_tile(stmt, ic, x, y, tile, db):
|
|||
text_default_mask |= 1
|
||||
if entry[1] == "IoCtrl" and entry[2] == "IE_1":
|
||||
text_default_mask |= 2
|
||||
if entry[1] == "RamConfig" and entry[2] == "MEMB_Power_Up_Control":
|
||||
if entry[1] == "RamConfig" and entry[2] == "PowerUp":
|
||||
text_default_mask |= 4
|
||||
if print_bits:
|
||||
text.add("<%s> %s" % (" ".join(entry[0]), " ".join(entry[1:])))
|
||||
|
|
@ -130,12 +142,12 @@ def print_tile(stmt, ic, x, y, tile, db):
|
|||
if lutff_options[2] == "1": lutff_options += " Set_NoReset"
|
||||
if lutff_options[3] == "1": lutff_options += " AsyncSetReset"
|
||||
text.add("LC_%d %s %s" % (lcidx, "".join(icebox.get_lutff_lut_bits(tile, lcidx)), lutff_options))
|
||||
if not print_bitinfo:
|
||||
if not print_bitinfo and not print_all:
|
||||
if text_default_mask == 3 and len(text) == 2:
|
||||
return
|
||||
if text_default_mask == 4 and len(text) == 1:
|
||||
return
|
||||
if len(text) or print_bitinfo:
|
||||
if len(text) or print_bitinfo or print_all:
|
||||
print("\n%s" % stmt)
|
||||
if print_bitinfo:
|
||||
print("Warning: No DB entries for some bits:")
|
||||
|
|
@ -151,8 +163,11 @@ for idx in ic.io_tiles:
|
|||
for idx in ic.logic_tiles:
|
||||
print_tile(".logic_tile %d %d" % idx, ic, idx[0], idx[1], ic.logic_tiles[idx], ic.tile_db(idx[0], idx[1]))
|
||||
|
||||
for idx in ic.ram_tiles:
|
||||
print_tile(".ram_tile %d %d" % idx, ic, idx[0], idx[1], ic.ram_tiles[idx], ic.tile_db(idx[0], idx[1]))
|
||||
for idx in ic.ramb_tiles:
|
||||
print_tile(".ramb_tile %d %d" % idx, ic, idx[0], idx[1], ic.ramb_tiles[idx], ic.tile_db(idx[0], idx[1]))
|
||||
|
||||
for idx in ic.ramt_tiles:
|
||||
print_tile(".ramt_tile %d %d" % idx, ic, idx[0], idx[1], ic.ramt_tiles[idx], ic.tile_db(idx[0], idx[1]))
|
||||
|
||||
for bit in ic.extra_bits:
|
||||
print()
|
||||
|
|
|
|||
|
|
@ -47,12 +47,15 @@ for o, a in opts:
|
|||
else:
|
||||
usage()
|
||||
|
||||
if len(args) != 0:
|
||||
usage()
|
||||
|
||||
ic = icebox.iceconfig()
|
||||
ic.setup_empty_1k()
|
||||
|
||||
mktiles = set()
|
||||
|
||||
for x in range(1, 6) + range(8, 13):
|
||||
for x in range(1, 13):
|
||||
mktiles.add((x, 0))
|
||||
mktiles.add((x, 17))
|
||||
|
||||
|
|
@ -64,6 +67,10 @@ for x in range(0, 5) + range(9, 14):
|
|||
mktiles.add((x, 2))
|
||||
mktiles.add((x, 15))
|
||||
|
||||
for y in range(7, 11):
|
||||
mktiles.add((0, y))
|
||||
mktiles.add((13, y))
|
||||
|
||||
for x in range(6, 8):
|
||||
for y in range(8, 10):
|
||||
mktiles.add((x, y))
|
||||
|
|
@ -94,7 +101,7 @@ A machine-readable form of the database can be downloaded <a href="chipdb.txt">h
|
|||
print("""<p>The iCE40 FPGA fabric is organized into tiles. The configuration bits
|
||||
themself have the same meaning in all tiles of the same type. But the way the tiles
|
||||
are connected to each other depends on the types of neighbouring cells. Furthermore,
|
||||
some wire names are different for (e.g.) a IO tile on the left border and an IO tile on
|
||||
some wire names are different for e.g. an IO tile on the left border and an IO tile on
|
||||
the top border.</p>""")
|
||||
|
||||
print("""<p>Click on a highlighted tile below to view the bitstream details for the
|
||||
|
|
@ -111,12 +118,14 @@ in iCE40 FPGAs.</p>""")
|
|||
elif (x, y) in mktiles:
|
||||
if ic.tile_type(x, y) == "IO": color = "#aee"
|
||||
if ic.tile_type(x, y) == "LOGIC": color = "#eae"
|
||||
if ic.tile_type(x, y) == "RAM": color = "#eea"
|
||||
if ic.tile_type(x, y) == "RAMB": color = "#eea"
|
||||
if ic.tile_type(x, y) == "RAMT": color = "#eea"
|
||||
print('bgcolor="%s"><small><a style="color:#000; text-decoration:none" href="tile_%d_%d.html"><b>%s<br/>(%d %d)</b></a></small></td>' % (color, x, y, ic.tile_type(x, y), x, y))
|
||||
else:
|
||||
if ic.tile_type(x, y) == "IO": color = "#8aa"
|
||||
if ic.tile_type(x, y) == "LOGIC": color = "#a8a"
|
||||
if ic.tile_type(x, y) == "RAM": color = "#aa8"
|
||||
if ic.tile_type(x, y) == "RAMB": color = "#aa8"
|
||||
if ic.tile_type(x, y) == "RAMT": color = "#aa8"
|
||||
print('bgcolor="%s"><small>%s<br/>(%d %d)</small></td>' % (color, ic.tile_type(x, y), x, y))
|
||||
print("</tr>")
|
||||
print("</table></p>")
|
||||
|
|
@ -147,12 +156,14 @@ configuration bits it has and how it is connected to its neighbourhood.</p>""" %
|
|||
if (x, y) in mktiles:
|
||||
if ic.tile_type(x, y) == "IO": color = "#aee"
|
||||
if ic.tile_type(x, y) == "LOGIC": color = "#eae"
|
||||
if ic.tile_type(x, y) == "RAM": color = "#eea"
|
||||
if ic.tile_type(x, y) == "RAMB": color = "#eea"
|
||||
if ic.tile_type(x, y) == "RAMT": color = "#eea"
|
||||
print('bgcolor="%s"><a style="color:#000; text-decoration:none" href="tile_%d_%d.html"><b>%s Tile<br/>(%d %d)</b></a></td>' % (color, x, y, ic.tile_type(x, y), x, y))
|
||||
else:
|
||||
if ic.tile_type(x, y) == "IO": color = "#8aa"
|
||||
if ic.tile_type(x, y) == "LOGIC": color = "#a8a"
|
||||
if ic.tile_type(x, y) == "RAM": color = "#aa8"
|
||||
if ic.tile_type(x, y) == "RAMB": color = "#aa8"
|
||||
if ic.tile_type(x, y) == "RAMT": color = "#aa8"
|
||||
print('bgcolor="%s">%s Tile<br/>(%d %d)</td>' % (color, ic.tile_type(x, y), x, y))
|
||||
visible_tiles.add((x, y))
|
||||
print("</tr>")
|
||||
|
|
@ -200,11 +211,13 @@ configuration bits it has and how it is connected to its neighbourhood.</p>""" %
|
|||
elif entry[1].startswith("IOB_"):
|
||||
bitmap_cells[idx1][idx2]["label"] = "I"
|
||||
elif entry[1].startswith("IoCtrl"):
|
||||
bitmap_cells[idx1][idx2]["label"] = "I"
|
||||
bitmap_cells[idx1][idx2]["label"] = "T"
|
||||
elif entry[1] == "Icegate":
|
||||
bitmap_cells[idx1][idx2]["label"] = "G"
|
||||
elif entry[1].startswith("Cascade"):
|
||||
bitmap_cells[idx1][idx2]["label"] = "A"
|
||||
elif entry[1].startswith("RamConfig"):
|
||||
bitmap_cells[idx1][idx2]["label"] = "R"
|
||||
bitmap_cells[idx1][idx2]["label"] = "M"
|
||||
else:
|
||||
assert False
|
||||
bitmap_cells[idx1][idx2]["label"] = '<a style="color:#666; text-decoration:none" href="#B.%d.%d">%s</a>' % (idx1, idx2, bitmap_cells[idx1][idx2]["label"])
|
||||
|
|
@ -264,6 +277,7 @@ nets are connected with nets from cells in its neighbourhood.</p>""")
|
|||
if netname.startswith("local_"): cat = (20, "Local Tracks")
|
||||
if netname.startswith("carry_in"): cat = (25, "Logic Block")
|
||||
if netname.startswith("io_"): cat = (25, "IO Block")
|
||||
if netname.startswith("ram"): cat = (25, "RAM Block")
|
||||
if netname.startswith("lutff_"): cat = (25, "Logic Block")
|
||||
if netname.startswith("lutff_0"): cat = (30, "Logic Unit 0")
|
||||
if netname.startswith("lutff_1"): cat = (30, "Logic Unit 1")
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ def usage():
|
|||
print(" icebox_maps -m io_tile_nets_t")
|
||||
print(" icebox_maps -m io_tile_nets_b")
|
||||
print(" icebox_maps -m logic_tile_nets")
|
||||
print(" icebox_maps -m ram_tile_nets")
|
||||
print(" icebox_maps -m ramb_tile_nets")
|
||||
print(" icebox_maps -m ramt_tile_nets")
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
|
|
@ -45,6 +46,9 @@ for o, a in opts:
|
|||
else:
|
||||
usage()
|
||||
|
||||
if len(args) != 0:
|
||||
usage()
|
||||
|
||||
def get_bit_group(x, y, db):
|
||||
bit = "B%d[%d]" % (y, x)
|
||||
nbit = "!B%d[%d]" % (y, x)
|
||||
|
|
@ -113,7 +117,8 @@ if mode == "bitmaps":
|
|||
print_tilemap(".io_tile_bitmap_t", icebox.iotile_t_db, 18)
|
||||
print_tilemap(".io_tile_bitmap_b", icebox.iotile_b_db, 18)
|
||||
print_tilemap(".logic_tile_bitmap", icebox.logictile_db, 54)
|
||||
print_tilemap(".ram_tile_bitmap", icebox.ramtile_db, 42)
|
||||
print_tilemap(".ramb_tile_bitmap", icebox.rambtile_db, 42)
|
||||
print_tilemap(".ramt_tile_bitmap", icebox.ramttile_db, 42)
|
||||
print()
|
||||
print(".bitmap_legend")
|
||||
print("- ... unknown bit")
|
||||
|
|
@ -144,8 +149,11 @@ elif mode == "io_tile_nets_b":
|
|||
elif mode == "logic_tile_nets":
|
||||
print_db_nets(".logic_tile_nets", icebox.logictile_db, "c")
|
||||
|
||||
elif mode == "ram_tile_nets":
|
||||
print_db_nets(".ram_tile_nets", icebox.ramtile_db, "c")
|
||||
elif mode == "ramb_tile_nets":
|
||||
print_db_nets(".ramb_tile_nets", icebox.ramtile_db, "c")
|
||||
|
||||
elif mode == "ramt_tile_nets":
|
||||
print_db_nets(".ramt_tile_nets", icebox.ramtile_db, "c")
|
||||
|
||||
else:
|
||||
usage()
|
||||
|
|
|
|||
|
|
@ -24,15 +24,16 @@ import getopt, sys, re
|
|||
strip_comments = False
|
||||
strip_interconn = False
|
||||
lookup_pins = False
|
||||
check_ieren = False
|
||||
check_driver = False
|
||||
pcf_data = dict()
|
||||
portnames = set()
|
||||
unmatched_ports = set()
|
||||
auto_clk = False
|
||||
auto_en = False
|
||||
modname = "chip"
|
||||
|
||||
def usage():
|
||||
print("""
|
||||
Usage: icebox_vlog [options] <bitmap.txt>
|
||||
Usage: icebox_vlog [options] [bitmap.txt]
|
||||
|
||||
-s
|
||||
strip comments from output
|
||||
|
|
@ -40,24 +41,29 @@ Usage: icebox_vlog [options] <bitmap.txt>
|
|||
-S
|
||||
strip comments about interconn wires from output
|
||||
|
||||
-a
|
||||
auto-detect global clock and enable signals
|
||||
(require ports "clk" and "en" in pcf file)
|
||||
|
||||
-l
|
||||
convert io tile port names to chip pin numbers
|
||||
|
||||
-n <module-name>
|
||||
name for the exported module (default: "chip")
|
||||
|
||||
-p <pcf-file>
|
||||
use the set_io command from the specified pcf file
|
||||
|
||||
-P <pcf-file>
|
||||
like -p, enable some hacks for pcf files created
|
||||
by the iCEcube2 placer.
|
||||
|
||||
-R
|
||||
enable IeRen database checks
|
||||
|
||||
-D
|
||||
enable exactly-one-driver checks
|
||||
""")
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "sSlap:P:")
|
||||
opts, args = getopt.getopt(sys.argv[1:], "sSlap:P:n:RD")
|
||||
except:
|
||||
usage()
|
||||
|
||||
|
|
@ -68,18 +74,22 @@ for o, a in opts:
|
|||
strip_interconn = True
|
||||
elif o == "-l":
|
||||
lookup_pins = True
|
||||
elif o == "-n":
|
||||
modname = a
|
||||
elif o == "-a":
|
||||
auto_clk = True
|
||||
auto_en = True
|
||||
pass # ignored for backward compatibility
|
||||
elif o in ("-p", "-P"):
|
||||
with open(a, "r") as f:
|
||||
for line in f:
|
||||
if o == "-P" and not re.search(" # ICE_(GB_)?IO", line):
|
||||
continue
|
||||
line = re.sub(r"#.*", "", line.strip()).split()
|
||||
if len(line) and line[0] == "set_io":
|
||||
p = line[1]
|
||||
if o == "-P":
|
||||
p = p.lower()
|
||||
p = p.replace("_ibuf", "")
|
||||
p = p.replace("_obuft", "")
|
||||
p = p.replace("_obuf", "")
|
||||
p = p.replace("_gb_io", "")
|
||||
portnames.add(p)
|
||||
|
|
@ -88,9 +98,19 @@ for o, a in opts:
|
|||
unmatched_ports.add(p)
|
||||
pinloc = tuple([int(s) for s in line[2:]])
|
||||
pcf_data[pinloc] = p
|
||||
elif o == "-R":
|
||||
check_ieren = True
|
||||
elif o == "-D":
|
||||
check_driver = True
|
||||
else:
|
||||
usage()
|
||||
|
||||
if len(args) == 0:
|
||||
args.append("/dev/stdin")
|
||||
|
||||
if len(args) != 1:
|
||||
usage()
|
||||
|
||||
if not strip_comments:
|
||||
print("// Reading file '%s'.." % args[0])
|
||||
ic = icebox.iceconfig()
|
||||
|
|
@ -102,13 +122,19 @@ text_ports = list()
|
|||
|
||||
luts_queue = set()
|
||||
text_func = list()
|
||||
failed_drivers_check = list()
|
||||
|
||||
netidx = [0]
|
||||
nets = dict()
|
||||
seg2net = dict()
|
||||
|
||||
auto_clk_nets = set()
|
||||
auto_en_nets = set()
|
||||
iocells = set()
|
||||
iocells_in = set()
|
||||
iocells_out = set()
|
||||
iocells_special = set()
|
||||
iocells_type = dict()
|
||||
iocells_negclk = set()
|
||||
iocells_inbufs = set()
|
||||
|
||||
def is_interconn(netname):
|
||||
if netname.startswith("sp4_"): return True
|
||||
|
|
@ -120,27 +146,93 @@ def is_interconn(netname):
|
|||
if netname.startswith("local_"): return True
|
||||
return False
|
||||
|
||||
extra_connections = list()
|
||||
extra_segments = list()
|
||||
|
||||
for bit in ic.extra_bits:
|
||||
entry = ic.lookup_extra_bit(bit)
|
||||
if entry[0] == "padin_glb_netwk":
|
||||
glb = int(entry[1])
|
||||
pin_entry = ic.padin_pio_db()[glb]
|
||||
iocells.add((pin_entry[0], pin_entry[1], pin_entry[2]))
|
||||
iocells_in.add((pin_entry[0], pin_entry[1], pin_entry[2]))
|
||||
s1 = (pin_entry[0], pin_entry[1], "io_%d/PAD" % pin_entry[2])
|
||||
s2 = (pin_entry[0], pin_entry[1], "wire_gbuf/padin_%d" % pin_entry[2])
|
||||
extra_connections.append((s1, s2))
|
||||
|
||||
for idx, tile in ic.io_tiles.items():
|
||||
tc = icebox.tileconfig(tile)
|
||||
iocells_type[(idx[0], idx[1], 0)] = ["0" for i in range(6)]
|
||||
iocells_type[(idx[0], idx[1], 1)] = ["0" for i in range(6)]
|
||||
for entry in ic.tile_db(idx[0], idx[1]):
|
||||
if check_ieren and entry[1] == "IoCtrl" and entry[2].startswith("IE_") and not tc.match(entry[0]):
|
||||
iren_idx = (idx[0], idx[1], 0 if entry[2] == "IE_0" else 1)
|
||||
for iren_entry in ic.ieren_db():
|
||||
if iren_idx[0] == iren_entry[3] and iren_idx[1] == iren_entry[4] and iren_idx[2] == iren_entry[5]:
|
||||
iocells_inbufs.add((iren_entry[0], iren_entry[1], iren_entry[2]))
|
||||
if entry[1] == "NegClk" and tc.match(entry[0]):
|
||||
iocells_negclk.add((idx[0], idx[1], 0))
|
||||
iocells_negclk.add((idx[0], idx[1], 1))
|
||||
if entry[1].startswith("IOB_") and entry[2].startswith("PINTYPE_") and tc.match(entry[0]):
|
||||
match1 = re.match("IOB_(\d+)", entry[1])
|
||||
match2 = re.match("PINTYPE_(\d+)", entry[2])
|
||||
assert match1 and match2
|
||||
iocells_type[(idx[0], idx[1], int(match1.group(1)))][int(match2.group(1))] = "1"
|
||||
iocells_type[(idx[0], idx[1], 0)] = "".join(iocells_type[(idx[0], idx[1], 0)])
|
||||
iocells_type[(idx[0], idx[1], 1)] = "".join(iocells_type[(idx[0], idx[1], 1)])
|
||||
|
||||
for segs in sorted(ic.group_segments()):
|
||||
for seg in segs:
|
||||
if ic.tile_type(seg[0], seg[1]) == "IO":
|
||||
match = re.match("io_(\d+)/D_(IN|OUT)_(\d+)", seg[2])
|
||||
if match:
|
||||
cell = (seg[0], seg[1], int(match.group(1)))
|
||||
iocells.add(cell)
|
||||
if match.group(2) == "IN":
|
||||
if check_ieren:
|
||||
assert cell in iocells_inbufs
|
||||
if iocells_type[cell] != "100000" or match.group(3) != "0":
|
||||
iocells_special.add(cell)
|
||||
iocells_in.add(cell)
|
||||
if match.group(2) == "OUT" and iocells_type[cell][2:6] != "0000":
|
||||
if iocells_type[cell] != "100110" or match.group(3) != "0":
|
||||
iocells_special.add(cell)
|
||||
iocells_out.add(cell)
|
||||
extra_segments.append((seg[0], seg[1], "io_%d/PAD" % int(match.group(1))))
|
||||
|
||||
for cell in iocells:
|
||||
if iocells_type[cell] == "100110" and not cell in iocells_special:
|
||||
s1 = (cell[0], cell[1], "io_%d/PAD" % cell[2])
|
||||
s2 = (cell[0], cell[1], "io_%d/D_OUT_0" % cell[2])
|
||||
extra_connections.append((s1, s2))
|
||||
del iocells_type[cell]
|
||||
elif iocells_type[cell] == "100000" and not cell in iocells_special:
|
||||
s1 = (cell[0], cell[1], "io_%d/PAD" % cell[2])
|
||||
s2 = (cell[0], cell[1], "io_%d/D_IN_0" % cell[2])
|
||||
extra_connections.append((s1, s2))
|
||||
del iocells_type[cell]
|
||||
|
||||
def next_netname():
|
||||
while True:
|
||||
netidx[0] += 1
|
||||
n = "n%d" % netidx[0]
|
||||
if n not in portnames: break
|
||||
if n not in portnames:
|
||||
return n
|
||||
|
||||
for segs in sorted(ic.group_segments(extra_connections=extra_connections, extra_segments=extra_segments)):
|
||||
n = next_netname()
|
||||
net_segs = set()
|
||||
renamed_net_to_port = False
|
||||
|
||||
for s in segs:
|
||||
match = re.match("io_(\d+)/D_(IN|OUT)_(\d+)$", s[2])
|
||||
match = re.match("io_(\d+)/PAD", s[2])
|
||||
if match:
|
||||
if match.group(2) == "IN":
|
||||
p = "io_%d_%d_%s_din_%s" % (s[0], s[1], match.group(1), match.group(3))
|
||||
net_segs.add(p)
|
||||
else:
|
||||
p = "io_%d_%d_%s_dout_%s" % (s[0], s[1], match.group(1), match.group(3))
|
||||
net_segs.add(p)
|
||||
idx = (s[0], s[1], int(match.group(1)))
|
||||
p = "io_%d_%d_%d" % idx
|
||||
net_segs.add(p)
|
||||
if lookup_pins or pcf_data:
|
||||
for entry in icebox.pinloc_db:
|
||||
if s[0] == entry[1] and s[1] == entry[2] and int(match.group(1)) == entry[3]:
|
||||
if idx[0] == entry[1] and idx[1] == entry[2] and idx[2] == entry[3]:
|
||||
if (entry[0],) in pcf_data:
|
||||
p = pcf_data[(entry[0],)]
|
||||
unmatched_ports.discard(p)
|
||||
|
|
@ -149,24 +241,25 @@ for segs in sorted(ic.group_segments()):
|
|||
unmatched_ports.discard(p)
|
||||
elif lookup_pins:
|
||||
p = "pin_%d" % entry[0]
|
||||
if p == "clk":
|
||||
auto_clk = False
|
||||
if p == "en":
|
||||
auto_en = False
|
||||
if not renamed_net_to_port:
|
||||
n = p
|
||||
if match.group(2) == "IN":
|
||||
if idx in iocells_in and idx not in iocells_out:
|
||||
text_ports.append("input %s" % p)
|
||||
else:
|
||||
elif idx not in iocells_in and idx in iocells_out:
|
||||
text_ports.append("output %s" % p)
|
||||
else:
|
||||
text_ports.append("inout %s" % p)
|
||||
text_wires.append("wire %s;" % n)
|
||||
renamed_net_to_port = True
|
||||
elif match.group(2) == "IN":
|
||||
elif idx in iocells_in and idx not in iocells_out:
|
||||
text_ports.append("input %s" % p)
|
||||
text_wires.append("assign %s = %s;" % (n, p))
|
||||
else:
|
||||
elif idx not in iocells_in and idx in iocells_out:
|
||||
text_ports.append("output %s" % p)
|
||||
text_wires.append("assign %s = %s;" % (p, n))
|
||||
else:
|
||||
text_ports.append("inout %s" % p)
|
||||
text_wires.append("assign %s = %s;" % (p, n))
|
||||
|
||||
match = re.match("lutff_(\d+)/", s[2])
|
||||
if match:
|
||||
|
|
@ -187,60 +280,27 @@ for segs in sorted(ic.group_segments()):
|
|||
else:
|
||||
net_segs.add(s)
|
||||
|
||||
if not renamed_net_to_port:
|
||||
has_clk = False
|
||||
has_cen = False
|
||||
has_global = False
|
||||
has_driver = False
|
||||
for s in sorted(net_segs):
|
||||
if s[2].startswith("glb_netwk_"):
|
||||
has_global = True
|
||||
elif re.search(r"/out", s[2]):
|
||||
has_driver = True
|
||||
elif s[2] == "lutff_global/clk":
|
||||
has_clk = True
|
||||
elif s[2] == "lutff_global/cen":
|
||||
has_cen = True
|
||||
if has_global and not has_driver:
|
||||
if has_clk:
|
||||
auto_clk_nets.add(n)
|
||||
if has_cen and not has_clk:
|
||||
auto_en_nets.add(n)
|
||||
count_drivers = 0
|
||||
for s in segs:
|
||||
if re.match(r"ram/RDATA_", s[2]): count_drivers += 1
|
||||
if re.match(r"io_./D_IN_", s[2]): count_drivers += 1
|
||||
if re.match(r"lutff_./out", s[2]): count_drivers += 1
|
||||
|
||||
if count_drivers != 1 and check_driver:
|
||||
failed_drivers_check.append(n)
|
||||
|
||||
if not strip_comments:
|
||||
for s in sorted(net_segs):
|
||||
text_wires.append("// %s" % (s,))
|
||||
if count_drivers != 1 and check_driver:
|
||||
text_wires.append("// Number of drivers: %d" % count_drivers)
|
||||
text_wires.append("")
|
||||
|
||||
for p in unmatched_ports:
|
||||
text_ports.append("input %s" % p)
|
||||
|
||||
if auto_clk and auto_clk_nets and "clk" in unmatched_ports:
|
||||
assert len(auto_clk_nets) == 1
|
||||
if not strip_comments:
|
||||
text_wires.append("// automatically detected clock network")
|
||||
text_wires.append("assign %s = clk;" % auto_clk_nets.pop())
|
||||
if not strip_comments:
|
||||
text_wires.append("")
|
||||
unmatched_ports.remove("clk")
|
||||
|
||||
if auto_en and auto_en_nets and "en" in unmatched_ports:
|
||||
assert len(auto_en_nets) == 1
|
||||
if not strip_comments:
|
||||
text_wires.append("// automatically detected enable network")
|
||||
text_wires.append("assign %s = en;" % auto_en_nets.pop())
|
||||
if not strip_comments:
|
||||
text_wires.append("")
|
||||
unmatched_ports.remove("en")
|
||||
|
||||
def seg_to_net(seg, default=None):
|
||||
if seg not in seg2net:
|
||||
if default is not None:
|
||||
return default
|
||||
while True:
|
||||
netidx[0] += 1
|
||||
n = "n%d" % netidx[0]
|
||||
if n not in portnames: break
|
||||
n = next_netname()
|
||||
nets[n] = set([seg])
|
||||
seg2net[seg] = n
|
||||
text_wires.append("wire %s;" % n)
|
||||
|
|
@ -250,6 +310,134 @@ def seg_to_net(seg, default=None):
|
|||
text_wires.append("")
|
||||
return seg2net[seg]
|
||||
|
||||
for cell in iocells:
|
||||
if cell in iocells_type:
|
||||
net_pad = seg_to_net((cell[0], cell[1], "io_%d/PAD" % cell[2]))
|
||||
net_din0 = seg_to_net((cell[0], cell[1], "io_%d/D_IN_0" % cell[2]), "")
|
||||
net_din1 = seg_to_net((cell[0], cell[1], "io_%d/D_IN_1" % cell[2]), "")
|
||||
net_dout0 = seg_to_net((cell[0], cell[1], "io_%d/D_OUT_0" % cell[2]), "0")
|
||||
net_dout1 = seg_to_net((cell[0], cell[1], "io_%d/D_OUT_1" % cell[2]), "0")
|
||||
net_oen = seg_to_net((cell[0], cell[1], "io_%d/OUT_ENB" % cell[2]), "1")
|
||||
net_cen = seg_to_net((cell[0], cell[1], "io_global/cen"), "1")
|
||||
net_iclk = seg_to_net((cell[0], cell[1], "io_global/inclk"), "0")
|
||||
net_oclk = seg_to_net((cell[0], cell[1], "io_global/outclk"), "0")
|
||||
net_latch = seg_to_net((cell[0], cell[1], "io_global/latch"), "0")
|
||||
iotype = iocells_type[cell]
|
||||
|
||||
if cell in iocells_negclk:
|
||||
posedge = "negedge"
|
||||
negedge = "posedge"
|
||||
else:
|
||||
posedge = "posedge"
|
||||
negedge = "negedge"
|
||||
|
||||
text_func.append("// IO Cell %s" % (cell,))
|
||||
if not strip_comments:
|
||||
text_func.append("// PAD = %s" % net_pad)
|
||||
text_func.append("// D_IN_0 = %s" % net_din0)
|
||||
text_func.append("// D_IN_1 = %s" % net_din1)
|
||||
text_func.append("// D_OUT_0 = %s" % net_dout0)
|
||||
text_func.append("// D_OUT_1 = %s" % net_dout1)
|
||||
text_func.append("// OUT_ENB = %s" % net_oen)
|
||||
text_func.append("// CLK_EN = %s" % net_cen)
|
||||
text_func.append("// IN_CLK = %s" % net_iclk)
|
||||
text_func.append("// OUT_CLK = %s" % net_oclk)
|
||||
text_func.append("// LATCH = %s" % net_latch)
|
||||
text_func.append("// TYPE = %s (LSB:MSB)" % iotype)
|
||||
|
||||
if net_din0 != "" or net_din1 != "":
|
||||
if net_cen == "1":
|
||||
icen_cond = ""
|
||||
else:
|
||||
icen_cond = "if (%s) " % net_cen
|
||||
|
||||
if net_din0 != "":
|
||||
if iotype[1] == "0" and iotype[0] == "0":
|
||||
reg_din0 = next_netname()
|
||||
text_func.append("reg %s;" % reg_din0)
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (posedge, net_iclk, icen_cond, reg_din0, net_pad))
|
||||
text_func.append("assign %s = %s;" % (net_din0, reg_din0))
|
||||
|
||||
if iotype[1] == "0" and iotype[0] == "1":
|
||||
text_func.append("assign %s = %s;" % (net_din0, net_pad))
|
||||
|
||||
if iotype[1] == "1" and iotype[0] == "0":
|
||||
reg_din0 = next_netname()
|
||||
reg_din0_latched = next_netname()
|
||||
text_func.append("reg %s, %s;" % (reg_din0, reg_din0_latched))
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (posedge, net_iclk, icen_cond, reg_din0, net_pad))
|
||||
text_func.append("always @* if (!%s) %s = %s;" % (net_latch, reg_din0_latched, reg_din0))
|
||||
text_func.append("assign %s = %s;" % (net_din0, reg_din0_latched))
|
||||
|
||||
if iotype[1] == "1" and iotype[0] == "1":
|
||||
reg_din0 = next_netname()
|
||||
text_func.append("reg %s;" % reg_din0)
|
||||
text_func.append("always @* if (!%s) %s = %s;" % (net_latch, reg_din0, net_pad))
|
||||
text_func.append("assign %s = %s;" % (net_din0, reg_din0))
|
||||
|
||||
if net_din1 != "":
|
||||
reg_din1 = next_netname()
|
||||
text_func.append("reg %s;" % reg_din1)
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (negedge, net_iclk, icen_cond, reg_din1, net_pad))
|
||||
text_func.append("assign %s = %s;" % (net_din1, reg_din1))
|
||||
|
||||
if iotype[5] != "0" or iotype[4] != "0":
|
||||
if net_cen == "1":
|
||||
ocen_cond = ""
|
||||
else:
|
||||
ocen_cond = "if (%s) " % net_cen
|
||||
|
||||
# effective OEN: iotype[4], iotype[5]
|
||||
|
||||
if iotype[5] == "0" and iotype[4] == "1":
|
||||
eff_oen = "1"
|
||||
|
||||
if iotype[5] == "1" and iotype[4] == "0":
|
||||
eff_oen = net_oen
|
||||
|
||||
if iotype[5] == "1" and iotype[4] == "1":
|
||||
eff_oen = next_netname()
|
||||
text_func.append("reg %s;" % eff_oen)
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (posedge, net_oclk, ocen_cond, eff_oen, net_oen))
|
||||
|
||||
# effective DOUT: iotype[2], iotype[3]
|
||||
|
||||
if iotype[2] == "0" and iotype[3] == "0":
|
||||
ddr_posedge = next_netname()
|
||||
ddr_negedge = next_netname()
|
||||
text_func.append("reg %s, %s;" % (ddr_posedge, ddr_negedge))
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (posedge, net_oclk, ocen_cond, ddr_posedge, net_dout0))
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (negedge, net_oclk, ocen_cond, ddr_negedge, net_dout1))
|
||||
eff_dout = next_netname()
|
||||
text_func.append("wire %s;" % (eff_dout))
|
||||
if cell in iocells_negclk:
|
||||
text_func.append("assign %s = %s ? %s : %s;" % (eff_dout, net_oclk, ddr_negedge, ddr_posedge))
|
||||
else:
|
||||
text_func.append("assign %s = %s ? %s : %s;" % (eff_dout, net_oclk, ddr_posedge, ddr_negedge))
|
||||
|
||||
if iotype[2] == "0" and iotype[3] == "1":
|
||||
eff_dout = net_dout0
|
||||
|
||||
if iotype[2] == "1" and iotype[3] == "0":
|
||||
eff_dout = next_netname()
|
||||
text_func.append("reg %s;" % eff_dout)
|
||||
text_func.append("always @(%s %s) %s%s <= %s;" % (posedge, net_oclk, ocen_cond, eff_dout, net_dout0))
|
||||
|
||||
if iotype[2] == "1" and iotype[3] == "1":
|
||||
eff_dout = next_netname()
|
||||
text_func.append("reg %s;" % eff_dout)
|
||||
text_func.append("always @(%s %s) %s%s <= !%s;" % (posedge, net_oclk, ocen_cond, eff_dout, net_dout0))
|
||||
|
||||
if eff_oen == "1":
|
||||
text_func.append("assign %s = %s;" % (net_pad, eff_dout))
|
||||
else:
|
||||
text_func.append("assign %s = %s ? %s : 1'bz;" % (net_pad, eff_oen, eff_dout))
|
||||
|
||||
text_func.append("")
|
||||
|
||||
for p in unmatched_ports:
|
||||
text_ports.append("input %s" % p)
|
||||
|
||||
wire_to_reg = set()
|
||||
lut_assigns = list()
|
||||
const_assigns = list()
|
||||
|
|
@ -288,10 +476,7 @@ for lut in luts_queue:
|
|||
carry_assigns.append([net_cout, "/* CARRY %2d %2d %2d */ (%s & %s) | ((%s | %s) & %s)" %
|
||||
(lut[0], lut[1], lut[2], net_in1, net_in2, net_in1, net_in2, net_cin)])
|
||||
if seq_bits[1] == "1":
|
||||
while True:
|
||||
netidx[0] += 1
|
||||
n = "n%d" % netidx[0]
|
||||
if n not in portnames: break
|
||||
n = next_netname()
|
||||
text_wires.append("wire %s;" % n)
|
||||
if not strip_comments:
|
||||
text_wires.append("// FF %s" % (lut,))
|
||||
|
|
@ -332,7 +517,7 @@ for lut in luts_queue:
|
|||
for a in const_assigns + lut_assigns + carry_assigns:
|
||||
text_func.append("assign %-*s = %s;" % (max_net_len, a[0], a[1]))
|
||||
|
||||
print("module chip (%s);\n" % ", ".join(text_ports))
|
||||
print("module %s (%s);\n" % (modname, ", ".join(text_ports)))
|
||||
|
||||
new_text_wires = list()
|
||||
for line in text_wires:
|
||||
|
|
@ -365,3 +550,8 @@ if unmatched_ports:
|
|||
print("endmodule")
|
||||
print()
|
||||
|
||||
if failed_drivers_check:
|
||||
print("// Single-driver-check failed for %d nets:" % len(failed_drivers_check))
|
||||
print("// %s" % " ".join(failed_drivers_check))
|
||||
assert False
|
||||
|
||||
|
|
|
|||
2575
icebox/iceboxdb.py
2575
icebox/iceboxdb.py
File diff suppressed because it is too large
Load Diff
|
|
@ -599,7 +599,7 @@ void FpgaConfig::read_ascii(std::istream &ifs)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (command == ".io_tile" || command == ".logic_tile" || command == ".ram_tile")
|
||||
if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile")
|
||||
{
|
||||
if (!got_device)
|
||||
error("Missing .device statement before %s.\n", command.c_str());
|
||||
|
|
@ -766,7 +766,7 @@ string FpgaConfig::tile_type(int x, int y) const
|
|||
if (this->device == "1k") {
|
||||
if ((x == 0 || x == this->chip_width()+1) && (y == 0 || y == this->chip_height()+1)) return "corner";
|
||||
if ((x == 0 || x == this->chip_width()+1) || (y == 0 || y == this->chip_height()+1)) return "io";
|
||||
if (x == 3 || x == 10) return "ram";
|
||||
if (x == 3 || x == 10) return y % 2 == 1 ? "ramb" : "ramt";
|
||||
return "logic";
|
||||
}
|
||||
panic("Unkown chip type '%s'.\n", this->device.c_str());
|
||||
|
|
@ -776,7 +776,8 @@ int FpgaConfig::tile_width(const string &type) const
|
|||
{
|
||||
if (type == "corner") return 0;
|
||||
if (type == "logic") return 54;
|
||||
if (type == "ram") return 42;
|
||||
if (type == "ramb") return 42;
|
||||
if (type == "ramt") return 42;
|
||||
if (type == "io") return 18;
|
||||
panic("Unkown tile type '%s'.\n", type.c_str());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue