aboutsummaryrefslogtreecommitdiffstats
path: root/icebox/icebox.py
diff options
context:
space:
mode:
Diffstat (limited to 'icebox/icebox.py')
-rw-r--r--icebox/icebox.py251
1 files changed, 149 insertions, 102 deletions
diff --git a/icebox/icebox.py b/icebox/icebox.py
index 25e01e4..198b5f2 100644
--- a/icebox/icebox.py
+++ b/icebox/icebox.py
@@ -318,8 +318,8 @@ class iceconfig:
if (x, y) in self.ramt_tiles: return ramttile_db
elif self.device == "5k":
if (x, y) in self.logic_tiles: return logictile_5k_db
- if (x, y) in self.ramb_tiles: return rambtile_5k_db
- if (x, y) in self.ramt_tiles: return ramttile_5k_db
+ if (x, y) in self.ramb_tiles: return rambtile_8k_db
+ if (x, y) in self.ramt_tiles: return ramttile_8k_db
if (x, y) in self.ipcon_tiles: return ipcon_5k_db
if (x, y) in self.dsp_tiles[0]: return dsp0_5k_db
if (x, y) in self.dsp_tiles[1]: return dsp1_5k_db
@@ -419,7 +419,7 @@ class iceconfig:
def do_direction(name, nx, ny):
if (0 < nx < self.max_x or self.is_ultra()) and 0 < ny < self.max_y:
neighbours.add((nx, ny, "neigh_op_%s_%d" % (name, func)))
- if nx in (0, self.max_x) and 0 < ny < self.max_y and nx != x:
+ if nx in (0, self.max_x) and 0 < ny < self.max_y and nx != x and (not self.is_ultra()):
neighbours.add((nx, ny, "logic_op_%s_%d" % (name, func)))
if ny in (0, self.max_y) and 0 < nx < self.max_x and ny != y:
neighbours.add((nx, ny, "logic_op_%s_%d" % (name, func)))
@@ -463,7 +463,7 @@ class iceconfig:
else:
assert False
- elif pos == "x" and npos in ("l", "r", "t", "b"):
+ elif pos == "x" and ((npos in ("t", "b")) or ((not self.is_ultra()) and (npos in ("l", "r")))):
if func in (0, 4): return (nx, ny, "io_0/D_IN_0")
if func in (1, 5): return (nx, ny, "io_0/D_IN_1")
if func in (2, 6): return (nx, ny, "io_1/D_IN_0")
@@ -507,34 +507,52 @@ class iceconfig:
return funcnets
+ def ultraplus_follow_corner(self, corner, direction, netname):
+ m = re.match("span4_(horz|vert)_([lrtb])_(\d+)$", netname)
+ if not m:
+ return None
+ cur_edge = m.group(2)
+ cur_index = int(m.group(3))
+ if direction not in corner:
+ return None
+ if direction != cur_edge:
+ return None
+ h_idx, v_idx = self.ultraplus_trace_corner_idx(corner, cur_index)
+ if h_idx is None and (direction == "b" or direction == "t"):
+ return None
+ if v_idx is None and (direction == "l" or direction == "r"):
+ return None
+ if corner == "bl" and direction == "l":
+ return (0, 1, sp4v_normalize("sp4_v_b_%d" % v_idx))
+ if corner == "bl" and direction == "b":
+ return (1, 0, ultra_span4_horz_normalize("span4_horz_l_%d" % h_idx))
+ if corner == "br" and direction == "r":
+ return (self.max_x, 1, sp4v_normalize("sp4_v_b_%d" % v_idx))
+ if corner == "br" and direction == "b":
+ return (self.max_x-1, 0, ultra_span4_horz_normalize("span4_horz_r_%d" % h_idx))
+ if corner == "tl" and direction == "l":
+ return (0, self.max_y-1, sp4v_normalize("sp4_v_t_%d" % v_idx))
+ if corner == "tl" and direction == "t":
+ return (1, self.max_y, ultra_span4_horz_normalize("span4_horz_l_%d" % h_idx))
+ if corner == "tr" and direction == "r":
+ return (self.max_x, self.max_y-1, sp4v_normalize("sp4_v_t_%d" % v_idx))
+ if corner == "tr" and direction == "t":
+ return (self.max_x-1, self.max_y, ultra_span4_horz_normalize("span4_horz_r_%d" % h_idx))
+ assert False
#UltraPlus corner routing: given the corner name and net index,
#return a tuple containing H and V indexes, or none if NA
- def ultraplus_trace_corner(self, corner, idx):
+ def ultraplus_trace_corner_idx(self, corner, idx):
h_idx = None
v_idx = None
- if corner == "bl":
- if idx >= 4:
- v_idx = idx + 28
- if idx >= 32 and idx < 48:
- h_idx = idx - 28
- elif corner == "tl":
- #TODO: bounds check for v_idx case?
- if idx >= 4:
- v_idx = (idx + 8) ^ 1
- if idx >= 12 and idx < 28:
- h_idx = (idx ^ 1) - 8
- elif corner == "tr":
- #TODO: bounds check for v_idx case?
- if idx <= 16:
- v_idx = (idx + 12) ^ 1
- if idx >= 12 and idx < 28:
- h_idx = (idx ^ 1) - 12
- elif corner == "br":
- #TODO: bounds check for v_idx case?
- if idx <= 16:
+ if corner == "bl" or corner == "br":
+ if idx < 16:
v_idx = idx + 32
- if idx >= 32 and idx < 48: #check
+ if idx >= 32 and idx < 48:
h_idx = idx - 32
+ elif corner == "tl" or corner == "tr":
+ if idx >= 0 and idx < 16:
+ v_idx = idx
+ h_idx = idx
return (h_idx, v_idx)
def get_corner(self, x, y):
@@ -551,7 +569,7 @@ class iceconfig:
corner += "r"
else:
corner += "x"
- return corner
+ return corner
def follow_net(self, netspec):
x, y, netname = netspec
@@ -608,37 +626,16 @@ class iceconfig:
if direction == "b": s = (x, y-1, n)
if s[0] in (0, self.max_x) and s[1] in (0, self.max_y):
- if re.match("span4_(vert|horz)_[lrtb]_\d+$", n):
- m = re.match("span4_(vert|horz)_([lrtb])_\d+$", n)
- #We ignore L and T edges when performing the Ultra/UltraPlus corner algorithm
- if self.is_ultra() and (m.group(2) == "l" or m.group(2) == "t"):
+ if self.is_ultra():
+ s = self.ultraplus_follow_corner(self.get_corner(s[0], s[1]), direction, n)
+ if s is None:
continue
+ elif re.match("span4_(vert|horz)_[lrtb]_\d+$", n) and not self.is_ultra():
+ m = re.match("span4_(vert|horz)_([lrtb])_\d+$", n)
+
vert_net = n.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")
horz_net = n.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_")
-
- if self.is_ultra(): #Convert between span4 and sp4, and perform U/UP corner tracing
- m = re.match("span4_vert_([lrtb])_(\d+)$", vert_net)
- assert m
- idx = int(m.group(2))
- h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
- if v_idx is None:
- if (s[0] == 0 and s[1] == 0 and direction == "l") or (s[0] == self.max_x and s[1] == self.max_y and direction == "r"):
- continue #Not routed, skip
- else:
- vert_net = "sp4_v_%s_%d" % (m.group(1), v_idx)
-
- m = re.match("span4_horz_([lrtb])_(\d+)$", horz_net)
- assert m
- idx = int(m.group(2))
- h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
- if h_idx is None:
- if (s[0] == 0 and s[1] == 0 and direction == "b") or (s[0] == self.max_x and s[1] == self.max_y and direction == "t"):
- continue #Not routed, skip
- else:
- horz_net = "span4_horz_%s_%d" % (m.group(1), h_idx)
-
-
-
+
if s[0] == 0 and s[1] == 0:
if direction == "l": s = (0, 1, vert_net)
if direction == "b": s = (1, 0, horz_net)
@@ -649,30 +646,6 @@ class iceconfig:
vert_net = netname.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")
horz_net = netname.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_")
-
- if self.is_ultra():
- # Might have sp4 not span4 here
- vert_net = vert_net.replace("_h_", "_v_")
- horz_net = horz_net.replace("_v_", "_h_")
- m = re.match("(span4_vert|sp4_v)_([lrtb])_(\d+)$", vert_net)
- assert m
- idx = int(m.group(3))
- h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
- if v_idx is None:
- if (s[0] == 0 and s[1] == self.max_y and direction == "l") or (s[0] == self.max_x and s[1] == 0 and direction == "r"):
- continue
- else:
- vert_net = "sp4_v_%s_%d" % (m.group(2), v_idx)
-
- m = re.match("(span4_horz|sp4_h)_([lrtb])_(\d+)$", horz_net)
- assert m
- idx = int(m.group(3))
- h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
- if h_idx is None:
- if (s[0] == 0 and s[1] == self.max_y and direction == "t") or (s[0] == self.max_x and s[1] == 0 and direction == "b"):
- continue
- else:
- horz_net = "span4_horz_%s_%d" % (m.group(2), h_idx)
if s[0] == 0 and s[1] == self.max_y:
if direction == "l": s = (0, self.max_y-1, vert_net)
@@ -752,7 +725,7 @@ class iceconfig:
if self.device == "1k":
add_seed_segments(idx, tile, rambtile_db)
elif self.device == "5k":
- add_seed_segments(idx, tile, rambtile_5k_db)
+ add_seed_segments(idx, tile, rambtile_8k_db)
elif self.device == "8k":
add_seed_segments(idx, tile, rambtile_8k_db)
else:
@@ -762,7 +735,7 @@ class iceconfig:
if self.device == "1k":
add_seed_segments(idx, tile, ramttile_db)
elif self.device == "5k":
- add_seed_segments(idx, tile, ramttile_5k_db)
+ add_seed_segments(idx, tile, ramttile_8k_db)
elif self.device == "8k":
add_seed_segments(idx, tile, ramttile_8k_db)
else:
@@ -1008,7 +981,34 @@ def sp4h_normalize(netname, edge=""):
return "sp4_h_r_%d" % ((cur_index+12)^1)
return netname
-
+# "Normalization" of span4 (not just sp4) is needed during Ultra/UltraPlus
+# corner tracing
+def ultra_span4_horz_normalize(netname, edge=""):
+ m = re.match("span4_horz_([rl])_(\d+)$", netname)
+ assert m
+ if not m: return None
+ cur_edge = m.group(1)
+ cur_index = int(m.group(2))
+ if cur_edge == edge:
+ return netname
+ if edge == "":
+ if cur_edge == "l" and cur_index < 12:
+ return "span4_horz_r_%d" % (cur_index + 4)
+ else:
+ return netname
+ elif edge == "l" and cur_edge == "r":
+ if cur_index < 4:
+ return None
+ else:
+ cur_index -= 4
+ return "span4_horz_l_%d" % cur_index
+ elif edge == "r" and cur_edge == "l":
+ if cur_index < 12:
+ return "span4_horz_r_%d" % (cur_index + 4)
+ else:
+ return None
+ assert False
+
def sp4v_normalize(netname, edge=""):
m = re.match("sp4_v_([bt])_(\d+)$", netname)
assert m
@@ -1141,11 +1141,11 @@ def pos_follow_net(pos, direction, netname, is_ultra):
m = re.match("sp4_v_[tb]_(\d+)$", netname)
if m and direction in ("t", "T"):
- if is_ultra and direction == "T" and pos in ("l", "r"):
- return re.sub("sp4_v_", "span4_vert_", netname)
n = sp4v_normalize(netname, "t")
if n is not None:
- if direction == "t":
+ if is_ultra and direction == "T" and pos in ("l", "r"):
+ return re.sub("sp4_v_", "span4_vert_", n)
+ elif direction == "t":
n = re.sub("_t_", "_b_", n)
n = sp4v_normalize(n)
else:
@@ -1153,11 +1153,11 @@ def pos_follow_net(pos, direction, netname, is_ultra):
n = re.sub("sp4_v_", "span4_vert_", n)
return n
if m and direction in ("b", "B"):
- if is_ultra and direction == "B" and pos in ("l", "r"):
- return re.sub("sp4_v_", "span4_vert_", netname)
n = sp4v_normalize(netname, "b")
if n is not None:
- if direction == "b":
+ if is_ultra and direction == "B" and pos in ("l", "r"):
+ return re.sub("sp4_v_", "span4_vert_", n)
+ elif direction == "b":
n = re.sub("_b_", "_t_", n)
n = sp4v_normalize(n)
else:
@@ -1194,6 +1194,8 @@ def pos_follow_net(pos, direction, netname, is_ultra):
if direction == "t":
n = re.sub("_t_", "_b_", n)
n = sp12v_normalize(n)
+ elif direction == "T" and pos in ("l", "r"):
+ pass
else:
n = re.sub("_t_", "_", n)
n = re.sub("sp12_v_", "span12_vert_", n)
@@ -1204,6 +1206,8 @@ def pos_follow_net(pos, direction, netname, is_ultra):
if direction == "b":
n = re.sub("_b_", "_t_", n)
n = sp12v_normalize(n)
+ elif direction == "B" and pos in ("l", "r"):
+ pass
else:
n = re.sub("_b_", "_", n)
n = re.sub("sp12_v_", "span12_vert_", n)
@@ -1226,8 +1230,10 @@ def pos_follow_net(pos, direction, netname, is_ultra):
m = re.match("span4_horz_([rl])_(\d+)$", netname)
if m:
case, idx = direction + m.group(1), int(m.group(2))
- if direction == "L" or direction == "R":
- return netname
+ if direction == "L":
+ return ultra_span4_horz_normalize(netname, "l")
+ elif direction == "R":
+ return ultra_span4_horz_normalize(netname, "r")
if case == "ll":
return "span4_horz_r_%d" % idx
if case == "lr" and idx >= 4:
@@ -1316,9 +1322,6 @@ def run_checks_neigh():
# Skip the corners.
if x in (0, ic.max_x) and y in (0, ic.max_y):
continue
- # Skip the sides of a 5k device.
- if self.is_ultra() and x in (0, ic.max_x):
- continue
add_segments((x, y), ic.tile_db(x, y))
if (x, y) in ic.logic_tiles:
all_segments.add((x, y, "lutff_7/cout"))
@@ -2344,7 +2347,11 @@ ieren_db = {
( 7, 0, 1, 7, 0, 0),
( 5, 0, 0, 5, 0, 1),
( 6, 0, 0, 6, 0, 1),
- ( 7, 0, 0, 7, 0, 1)
+ ( 7, 0, 0, 7, 0, 1),
+ (12, 31, 0, 12, 31, 1),
+ (12, 0, 0, 12, 0, 1),
+ (13, 0, 0, 13, 0, 1),
+ (12, 0, 1, 12, 0, 0)
]
}
@@ -4396,6 +4403,29 @@ pinloc_db = {
( "47", 6, 0, 0),
( "48", 7, 0, 0),
],
+ "5k-uwg30": [
+ ( "A1", 19, 31, 1),
+ ( "A2", 19, 31, 0),
+ ( "A4", 12, 31, 0),
+ ( "A5", 4, 31, 0),
+ ( "B1", 19, 0, 0),
+ ( "B3", 12, 31, 1),
+ ( "B5", 5, 31, 0),
+ ( "C1", 24, 0, 1),
+ ( "C3", 12, 0, 0),
+ ( "C5", 6, 31, 0),
+ ( "D1", 24, 0, 0),
+ ( "D3", 13, 0, 0),
+ ( "D5", 6, 0, 0),
+ ( "E1", 23, 0, 1),
+ ( "E3", 13, 0, 1),
+ ( "E4", 9, 0, 1),
+ ( "E5", 5, 0, 0),
+ ( "F1", 23, 0, 0),
+ ( "F2", 19, 0, 1),
+ ( "F4", 12, 0, 1),
+ ( "F5", 6, 0, 1),
+ ]
}
# This database contains the locations of configuration bits of the DSP tiles
@@ -4692,8 +4722,19 @@ extra_cells_db = {
"CLKHFEN": (0, 29, "lutff_7/in_3"),
"CLKHF": (0, 29, "glb_netwk_4"),
"CLKHF_FABRIC": (0, 28, "slf_op_7"),
+ "TRIM0": (25, 28, "lutff_4/in_0"),
+ "TRIM1": (25, 28, "lutff_5/in_0"),
+ "TRIM2": (25, 28, "lutff_6/in_0"),
+ "TRIM3": (25, 28, "lutff_7/in_0"),
+ "TRIM4": (25, 29, "lutff_0/in_3"),
+ "TRIM5": (25, 29, "lutff_1/in_3"),
+ "TRIM6": (25, 29, "lutff_2/in_3"),
+ "TRIM7": (25, 29, "lutff_3/in_3"),
+ "TRIM8": (25, 29, "lutff_4/in_3"),
+ "TRIM9": (25, 29, "lutff_5/in_3"),
"CLKHF_DIV_1": (0, 16, "CBIT_4"),
- "CLKHF_DIV_0": (0, 16, "CBIT_3")
+ "CLKHF_DIV_0": (0, 16, "CBIT_3"),
+ "TRIM_EN": (0, 16, "CBIT_5")
},
("LFOSC", (25, 31, 1)) : {
"CLKLFPU": (25, 29, "lutff_0/in_1"),
@@ -4862,6 +4903,10 @@ extra_cells_db = {
"SOE": (0, 20, "slf_op_5"),
"SPIIRQ": (0, 20, "slf_op_2"),
"SPIWKUP": (0, 20, "slf_op_3"),
+ "SPI_ENABLE_0": (7, 0, "cbit2usealt_in_0"),
+ "SPI_ENABLE_1": (7, 0, "cbit2usealt_in_1"),
+ "SPI_ENABLE_2": (6, 0, "cbit2usealt_in_0"),
+ "SPI_ENABLE_3": (6, 0, "cbit2usealt_in_1"),
},
("SPI", (25, 0, 1)): {
"MCSNO0": (25, 21, "slf_op_2"),
@@ -4912,6 +4957,10 @@ extra_cells_db = {
"SOE": (25, 20, "slf_op_5"),
"SPIIRQ": (25, 20, "slf_op_2"),
"SPIWKUP": (25, 20, "slf_op_3"),
+ "SPI_ENABLE_0": (23, 0, "cbit2usealt_in_0"),
+ "SPI_ENABLE_1": (24, 0, "cbit2usealt_in_0"),
+ "SPI_ENABLE_2": (23, 0, "cbit2usealt_in_1"),
+ "SPI_ENABLE_3": (24, 0, "cbit2usealt_in_1"),
},
("LEDDA_IP", (0, 31, 2)): {
"LEDDADDR0": (0, 28, "lutff_4/in_0"),
@@ -4946,8 +4995,6 @@ logictile_8k_db = parse_db(iceboxdb.database_logic_txt, "8k")
logictile_384_db = parse_db(iceboxdb.database_logic_txt, "384")
rambtile_db = parse_db(iceboxdb.database_ramb_txt, "1k")
ramttile_db = parse_db(iceboxdb.database_ramt_txt, "1k")
-rambtile_5k_db = parse_db(iceboxdb.database_ramb_5k_txt, "5k")
-ramttile_5k_db = parse_db(iceboxdb.database_ramt_5k_txt, "5k")
rambtile_8k_db = parse_db(iceboxdb.database_ramb_8k_txt, "8k")
ramttile_8k_db = parse_db(iceboxdb.database_ramt_8k_txt, "8k")
@@ -5044,19 +5091,19 @@ iotile_b_5k_db.append([["B12[2]"], "IpConfig", "cbit2usealt_in_1"])
iotile_b_5k_db.append([["B12[3]"], "IpConfig", "SDA_input_delay"])
iotile_b_5k_db.append([["B15[3]"], "IpConfig", "SDA_output_delay"])
-for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, iotile_t_5k_db, iotile_b_5k_db, logictile_db, logictile_5k_db, logictile_8k_db, logictile_384_db, rambtile_db, ramttile_db, rambtile_5k_db, ramttile_5k_db, rambtile_8k_db, ramttile_8k_db, dsp0_5k_db, dsp1_5k_db, dsp2_5k_db, dsp3_5k_db, ipcon_5k_db]:
+for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, iotile_t_5k_db, iotile_b_5k_db, logictile_db, logictile_5k_db, logictile_8k_db, logictile_384_db, rambtile_db, ramttile_db, rambtile_8k_db, ramttile_8k_db, dsp0_5k_db, dsp1_5k_db, dsp2_5k_db, dsp3_5k_db, ipcon_5k_db]:
for entry in db:
if entry[1] in ("buffer", "routing"):
entry[2] = netname_normalize(entry[2],
ramb=(db == rambtile_db),
ramt=(db == ramttile_db),
- ramb_8k=(db in (rambtile_8k_db, rambtile_5k_db)),
- ramt_8k=(db in (ramttile_8k_db, ramttile_5k_db)))
+ ramb_8k=(db == rambtile_8k_db),
+ ramt_8k=(db == ramttile_8k_db))
entry[3] = netname_normalize(entry[3],
ramb=(db == rambtile_db),
ramt=(db == ramttile_db),
- ramb_8k=(db in (rambtile_8k_db, rambtile_5k_db)),
- ramt_8k=(db in (ramttile_8k_db, ramttile_5k_db)))
+ ramb_8k=(db == rambtile_8k_db),
+ ramt_8k=(db == ramttile_8k_db))
unique_entries = dict()
while db:
entry = db.pop()