aboutsummaryrefslogtreecommitdiffstats
path: root/icebox/icebox_vlog.py
diff options
context:
space:
mode:
Diffstat (limited to 'icebox/icebox_vlog.py')
-rwxr-xr-xicebox/icebox_vlog.py275
1 files changed, 268 insertions, 7 deletions
diff --git a/icebox/icebox_vlog.py b/icebox/icebox_vlog.py
index acf7913..8db925f 100755
--- a/icebox/icebox_vlog.py
+++ b/icebox/icebox_vlog.py
@@ -96,7 +96,10 @@ for o, a in opts:
if not re.match(r"[a-zA-Z_][a-zA-Z0-9_]*$", p):
p = "\\%s " % p
unmatched_ports.add(p)
- pinloc = tuple([int(s) for s in line[2:]])
+ if len(line) > 3:
+ pinloc = tuple([int(s) for s in line[2:]])
+ else:
+ pinloc = (line[2],)
pcf_data[pinloc] = p
elif o == "-R":
check_ieren = True
@@ -135,6 +138,8 @@ iocells_special = set()
iocells_type = dict()
iocells_negclk = set()
iocells_inbufs = set()
+iocells_skip = set()
+iocells_pll = set()
def is_interconn(netname):
if netname.startswith("sp4_"): return True
@@ -146,6 +151,36 @@ def is_interconn(netname):
if netname.startswith("local_"): return True
return False
+pll_config_bitidx = dict()
+pll_gbuf = dict()
+
+for entry in icebox.iotile_l_db:
+ if entry[1] == "PLL":
+ match = re.match(r"B(\d+)\[(\d+)\]", entry[0][0]);
+ assert match
+ pll_config_bitidx[entry[2]] = (int(match.group(1)), int(match.group(2)))
+
+def get_pll_bit(pllinfo, name):
+ bit = pllinfo[name]
+ assert bit[2] in pll_config_bitidx
+ return ic.tile(bit[0], bit[1])[pll_config_bitidx[bit[2]][0]][pll_config_bitidx[bit[2]][1]]
+
+def get_pll_bits(pllinfo, name, n):
+ return "".join([get_pll_bit(pllinfo, "%s_%d" % (name, i)) for i in range(n-1, -1, -1)])
+
+for pllid in ic.pll_list():
+ pllinfo = icebox.pllinfo_db[pllid]
+ plltype = get_pll_bits(pllinfo, "PLLTYPE", 3)
+ if plltype != "000":
+ if plltype in ["010", "100", "110"]:
+ iocells_special.add(pllinfo["PLLOUT_A"])
+ else:
+ iocells_skip.add(pllinfo["PLLOUT_A"])
+ iocells_pll.add(pllinfo["PLLOUT_A"])
+ if plltype not in ["010", "011"]:
+ iocells_skip.add(pllinfo["PLLOUT_B"])
+ iocells_pll.add(pllinfo["PLLOUT_B"])
+
extra_connections = list()
extra_segments = list()
@@ -154,11 +189,15 @@ for bit in ic.extra_bits:
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))
+ if pin_entry in iocells_pll:
+ pll_gbuf[pin_entry] = (pin_entry[0], pin_entry[1], "padin_%d" % pin_entry[2])
+ extra_segments.append(pll_gbuf[pin_entry])
+ else:
+ 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], "padin_%d" % pin_entry[2])
+ extra_connections.append((s1, s2))
for idx, tile in ic.io_tiles.items():
tc = icebox.tileconfig(tile)
@@ -187,6 +226,8 @@ for segs in sorted(ic.group_segments()):
match = re.match("io_(\d+)/D_(IN|OUT)_(\d+)", seg[2])
if match:
cell = (seg[0], seg[1], int(match.group(1)))
+ if cell in iocells_skip:
+ continue
iocells.add(cell)
if match.group(2) == "IN":
if check_ieren:
@@ -231,7 +272,7 @@ for segs in sorted(ic.group_segments(extra_connections=extra_connections, extra_
p = "io_%d_%d_%d" % idx
net_segs.add(p)
if lookup_pins or pcf_data:
- for entry in icebox.pinloc_db:
+ for entry in ic.pinloc_db():
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],)]
@@ -310,6 +351,167 @@ def seg_to_net(seg, default=None):
text_wires.append("")
return seg2net[seg]
+wb_boot = seg_to_net(icebox.warmbootinfo_db[ic.device]["BOOT"], "")
+wb_s0 = seg_to_net(icebox.warmbootinfo_db[ic.device]["S0"], "")
+wb_s1 = seg_to_net(icebox.warmbootinfo_db[ic.device]["S1"], "")
+
+if wb_boot != "" or wb_s0 != "" or wb_s1 != "":
+ text_func.append("SB_WARMBOOT (")
+ text_func.append(" .BOOT(%s)," % wb_boot)
+ text_func.append(" .S0(%s)," % wb_s0)
+ text_func.append(" .S1(%s)," % wb_s1)
+ text_func.append(");")
+ text_func.append("")
+
+def get_pll_feedback_path(pllinfo):
+ v = get_pll_bits(pllinfo, "FEEDBACK_PATH", 3)
+ if v == "000": return "DELAY"
+ if v == "001": return "SIMPLE"
+ if v == "010": return "PHASE_AND_DELAY"
+ if v == "110": return "EXTERNAL"
+ assert False
+
+def get_pll_adjmode(pllinfo, name):
+ v = get_pll_bit(pllinfo, name)
+ if v == "0": return "FIXED"
+ if v == "1": return "DYNAMIC"
+ assert False
+
+def get_pll_outsel(pllinfo, name):
+ v = get_pll_bits(pllinfo, name, 2)
+ if v == "00": return "GENCLK"
+ if v == "01": return "GENCLK_HALF"
+ if v == "10": return "SHIFTREG_90deg"
+ if v == "11": return "SHIFTREG_0deg"
+ assert False
+
+for pllid in ic.pll_list():
+ pllinfo = icebox.pllinfo_db[pllid]
+ plltype = get_pll_bits(pllinfo, "PLLTYPE", 3)
+
+ if plltype == "000":
+ continue
+
+ if not strip_comments:
+ text_func.append("// plltype = %s" % plltype)
+ for ti in sorted(ic.io_tiles):
+ for bit in sorted(pll_config_bitidx):
+ if ic.io_tiles[ti][pll_config_bitidx[bit][0]][pll_config_bitidx[bit][1]] == "1":
+ resolved_bitname = ""
+ for bitname in pllinfo:
+ if pllinfo[bitname] == (ti[0], ti[1], bit):
+ resolved_bitname = " " + bitname
+ text_func.append("// (%2d, %2d, \"%s\")%s" % (ti[0], ti[1], bit, resolved_bitname))
+
+ if plltype in ["010", "100", "110"]:
+ if plltype == "010": text_func.append("SB_PLL40_PAD #(")
+ if plltype == "100": text_func.append("SB_PLL40_2_PAD #(")
+ if plltype == "110": text_func.append("SB_PLL40_2F_PAD #(")
+ text_func.append(" .FEEDBACK_PATH(\"%s\")," % get_pll_feedback_path(pllinfo))
+ text_func.append(" .DELAY_ADJUSTMENT_MODE_FEEDBACK(\"%s\")," % get_pll_adjmode(pllinfo, "DELAY_ADJMODE_FB"))
+ text_func.append(" .DELAY_ADJUSTMENT_MODE_RELATIVE(\"%s\")," % get_pll_adjmode(pllinfo, "DELAY_ADJMODE_REL"))
+ if plltype == "010":
+ text_func.append(" .PLLOUT_SELECT(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_A"))
+ else:
+ if plltype != "100":
+ text_func.append(" .PLLOUT_SELECT_PORTA(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_A"))
+ text_func.append(" .PLLOUT_SELECT_PORTB(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_B"))
+ text_func.append(" .SHIFTREG_DIV_MODE(1'b%s)," % get_pll_bit(pllinfo, "SHIFTREG_DIV_MODE"))
+ text_func.append(" .FDA_FEEDBACK(4'b%s)," % get_pll_bits(pllinfo, "FDA_FEEDBACK", 4))
+ text_func.append(" .FDA_RELATIVE(4'b%s)," % get_pll_bits(pllinfo, "FDA_RELATIVE", 4))
+ text_func.append(" .DIVR(4'b%s)," % get_pll_bits(pllinfo, "DIVR", 4))
+ text_func.append(" .DIVF(7'b%s)," % get_pll_bits(pllinfo, "DIVF", 7))
+ text_func.append(" .DIVQ(3'b%s)," % get_pll_bits(pllinfo, "DIVQ", 3))
+ text_func.append(" .FILTER_RANGE(3'b%s)," % get_pll_bits(pllinfo, "FILTER_RANGE", 3))
+ if plltype == "010":
+ text_func.append(" .ENABLE_ICEGATE(1'b0),")
+ else:
+ text_func.append(" .ENABLE_ICEGATE_PORTA(1'b0),")
+ text_func.append(" .ENABLE_ICEGATE_PORTB(1'b0),")
+ text_func.append(" .TEST_MODE(1'b%s)" % get_pll_bit(pllinfo, "TEST_MODE"))
+ text_func.append(") PLL_%d_%d (" % pllinfo["LOC"])
+ if plltype == "010":
+ pad_segment = (pllinfo["PLLOUT_A"][0], pllinfo["PLLOUT_A"][1], "io_%d/PAD" % pllinfo["PLLOUT_A"][2])
+ text_func.append(" .PACKAGEPIN(%s)," % seg_to_net(pad_segment))
+ del seg2net[pad_segment]
+ text_func.append(" .PLLOUTCORE(%s)," % seg_to_net(pad_segment))
+ if pllinfo["PLLOUT_A"] in pll_gbuf:
+ text_func.append(" .PLLOUTGLOBAL(%s)," % seg_to_net(pll_gbuf[pllinfo["PLLOUT_A"]]))
+ else:
+ pad_segment = (pllinfo["PLLOUT_A"][0], pllinfo["PLLOUT_A"][1], "io_%d/PAD" % pllinfo["PLLOUT_A"][2])
+ text_func.append(" .PACKAGEPIN(%s)," % seg_to_net(pad_segment))
+ del seg2net[pad_segment]
+ text_func.append(" .PLLOUTCOREA(%s)," % seg_to_net(pad_segment))
+ if pllinfo["PLLOUT_A"] in pll_gbuf:
+ text_func.append(" .PLLOUTGLOBALA(%s)," % seg_to_net(pll_gbuf[pllinfo["PLLOUT_A"]]))
+ pad_segment = (pllinfo["PLLOUT_B"][0], pllinfo["PLLOUT_B"][1], "io_%d/D_IN_0" % pllinfo["PLLOUT_B"][2])
+ text_func.append(" .PLLOUTCOREB(%s)," % seg_to_net(pad_segment))
+ if pllinfo["PLLOUT_B"] in pll_gbuf:
+ text_func.append(" .PLLOUTGLOBALB(%s)," % seg_to_net(pll_gbuf[pllinfo["PLLOUT_B"]]))
+ text_func.append(" .EXTFEEDBACK(%s)," % seg_to_net(pllinfo["EXTFEEDBACK"], "1'b0"))
+ text_func.append(" .DYNAMICDELAY({%s})," % ", ".join([seg_to_net(pllinfo["DYNAMICDELAY_%d" % i], "1'b0") for i in range(7, -1, -1)]))
+ text_func.append(" .LOCK(%s)," % seg_to_net(pllinfo["LOCK"]))
+ text_func.append(" .BYPASS(%s)," % seg_to_net(pllinfo["BYPASS"], "1'b0"))
+ text_func.append(" .RESETB(%s)," % seg_to_net(pllinfo["RESETB"], "1'b0"))
+ text_func.append(" .LATCHINPUTVALUE(%s)," % seg_to_net(pllinfo["LATCHINPUTVALUE"], "1'b0"))
+ text_func.append(" .SDO(%s)," % seg_to_net(pllinfo["SDO"]))
+ text_func.append(" .SDI(%s)," % seg_to_net(pllinfo["SDI"], "1'b0"))
+ text_func.append(" .SCLK(%s)" % seg_to_net(pllinfo["SCLK"], "1'b0"))
+ text_func.append(");")
+
+ if plltype in ["011", "111"]:
+ if plltype == "011": text_func.append("SB_PLL40_CORE #(")
+ if plltype == "111": text_func.append("SB_PLL40_2F_CORE #(")
+ text_func.append(" .FEEDBACK_PATH(\"%s\")," % get_pll_feedback_path(pllinfo))
+ text_func.append(" .DELAY_ADJUSTMENT_MODE_FEEDBACK(\"%s\")," % get_pll_adjmode(pllinfo, "DELAY_ADJMODE_FB"))
+ text_func.append(" .DELAY_ADJUSTMENT_MODE_RELATIVE(\"%s\")," % get_pll_adjmode(pllinfo, "DELAY_ADJMODE_REL"))
+ if plltype == "011":
+ text_func.append(" .PLLOUT_SELECT(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_A"))
+ else:
+ text_func.append(" .PLLOUT_SELECT_PORTA(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_A"))
+ text_func.append(" .PLLOUT_SELECT_PORTB(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_B"))
+ text_func.append(" .SHIFTREG_DIV_MODE(1'b%s)," % get_pll_bit(pllinfo, "SHIFTREG_DIV_MODE"))
+ text_func.append(" .FDA_FEEDBACK(4'b%s)," % get_pll_bits(pllinfo, "FDA_FEEDBACK", 4))
+ text_func.append(" .FDA_RELATIVE(4'b%s)," % get_pll_bits(pllinfo, "FDA_RELATIVE", 4))
+ text_func.append(" .DIVR(4'b%s)," % get_pll_bits(pllinfo, "DIVR", 4))
+ text_func.append(" .DIVF(7'b%s)," % get_pll_bits(pllinfo, "DIVF", 7))
+ text_func.append(" .DIVQ(3'b%s)," % get_pll_bits(pllinfo, "DIVQ", 3))
+ text_func.append(" .FILTER_RANGE(3'b%s)," % get_pll_bits(pllinfo, "FILTER_RANGE", 3))
+ if plltype == "011":
+ text_func.append(" .ENABLE_ICEGATE(1'b0),")
+ else:
+ text_func.append(" .ENABLE_ICEGATE_PORTA(1'b0),")
+ text_func.append(" .ENABLE_ICEGATE_PORTB(1'b0),")
+ text_func.append(" .TEST_MODE(1'b%s)" % get_pll_bit(pllinfo, "TEST_MODE"))
+ text_func.append(") PLL_%d_%d (" % pllinfo["LOC"])
+ text_func.append(" .REFERENCECLK(%s)," % seg_to_net(pllinfo["REFERENCECLK"], "1'b0"))
+ if plltype == "011":
+ pad_segment = (pllinfo["PLLOUT_A"][0], pllinfo["PLLOUT_A"][1], "io_%d/D_IN_0" % pllinfo["PLLOUT_A"][2])
+ text_func.append(" .PLLOUTCORE(%s)," % seg_to_net(pad_segment))
+ if pllinfo["PLLOUT_A"] in pll_gbuf:
+ text_func.append(" .PLLOUTGLOBAL(%s)," % seg_to_net(pll_gbuf[pllinfo["PLLOUT_A"]]))
+ else:
+ pad_segment = (pllinfo["PLLOUT_A"][0], pllinfo["PLLOUT_A"][1], "io_%d/D_IN_0" % pllinfo["PLLOUT_A"][2])
+ text_func.append(" .PLLOUTCOREA(%s)," % seg_to_net(pad_segment))
+ if pllinfo["PLLOUT_A"] in pll_gbuf:
+ text_func.append(" .PLLOUTGLOBALA(%s)," % seg_to_net(pll_gbuf[pllinfo["PLLOUT_A"]]))
+ pad_segment = (pllinfo["PLLOUT_B"][0], pllinfo["PLLOUT_B"][1], "io_%d/D_IN_0" % pllinfo["PLLOUT_B"][2])
+ text_func.append(" .PLLOUTCOREB(%s)," % seg_to_net(pad_segment))
+ if pllinfo["PLLOUT_B"] in pll_gbuf:
+ text_func.append(" .PLLOUTGLOBALB(%s)," % seg_to_net(pll_gbuf[pllinfo["PLLOUT_B"]]))
+ text_func.append(" .EXTFEEDBACK(%s)," % seg_to_net(pllinfo["EXTFEEDBACK"], "1'b0"))
+ text_func.append(" .DYNAMICDELAY({%s})," % ", ".join([seg_to_net(pllinfo["DYNAMICDELAY_%d" % i], "1'b0") for i in range(7, -1, -1)]))
+ text_func.append(" .LOCK(%s)," % seg_to_net(pllinfo["LOCK"]))
+ text_func.append(" .BYPASS(%s)," % seg_to_net(pllinfo["BYPASS"], "1'b0"))
+ text_func.append(" .RESETB(%s)," % seg_to_net(pllinfo["RESETB"], "1'b0"))
+ text_func.append(" .LATCHINPUTVALUE(%s)," % seg_to_net(pllinfo["LATCHINPUTVALUE"], "1'b0"))
+ text_func.append(" .SDO(%s)," % seg_to_net(pllinfo["SDO"]))
+ text_func.append(" .SDI(%s)," % seg_to_net(pllinfo["SDI"], "1'b0"))
+ text_func.append(" .SCLK(%s)" % seg_to_net(pllinfo["SCLK"], "1'b0"))
+ text_func.append(");")
+
+ text_func.append("")
+
for cell in iocells:
if cell in iocells_type:
net_pad = seg_to_net((cell[0], cell[1], "io_%d/PAD" % cell[2]))
@@ -438,6 +640,65 @@ for cell in iocells:
for p in unmatched_ports:
text_ports.append("input %s" % p)
+ram_config_bitidx = dict()
+
+for tile in ic.ramb_tiles:
+ for entry in ic.tile_db(tile[0], tile[1]):
+ if entry[1] == "RamConfig":
+ assert entry[2] not in ram_config_bitidx
+ ram_config_bitidx[entry[2]] = ('B', entry[0])
+ for entry in ic.tile_db(tile[0], tile[1]+1):
+ if entry[1] == "RamConfig":
+ assert entry[2] not in ram_config_bitidx
+ ram_config_bitidx[entry[2]] = ('T', entry[0])
+ break
+
+for tile in ic.ramb_tiles:
+ ramb_config = icebox.tileconfig(ic.tile(tile[0], tile[1]))
+ ramt_config = icebox.tileconfig(ic.tile(tile[0], tile[1]+1))
+ def get_ram_config(name):
+ assert name in ram_config_bitidx
+ if ram_config_bitidx[name][0] == 'B':
+ return ramb_config.match(ram_config_bitidx[name][1])
+ elif ram_config_bitidx[name][0] == 'T':
+ return ramt_config.match(ram_config_bitidx[name][1])
+ else:
+ assert False
+ def get_ram_wire(name, msb, lsb):
+ wire_bits = []
+ for i in range(msb, lsb-1, -1):
+ if msb != lsb:
+ n = "ram/%s_%d" % (name, i)
+ else:
+ n = "ram/" + name
+ b = seg_to_net((tile[0], tile[1], n), "1'b0")
+ b = seg_to_net((tile[0], tile[1]+1, n), b)
+ if len(wire_bits) != 0 or b != "1'b0" or i == lsb:
+ wire_bits.append(b)
+ if len(wire_bits) > 1:
+ return "{%s}" % ", ".join(wire_bits)
+ return wire_bits[0]
+ if get_ram_config('PowerUp') == (ic.device == "8k"):
+ if not strip_comments:
+ text_func.append("// RAM TILE %d %d" % tile)
+ text_func.append("SB_RAM40_4K #(");
+ text_func.append(" .READ_MODE(%d)," % ((1 if get_ram_config('CBIT_2') else 0) + (2 if get_ram_config('CBIT_3') else 0)));
+ text_func.append(" .WRITE_MODE(%d)" % ((1 if get_ram_config('CBIT_0') else 0) + (2 if get_ram_config('CBIT_1') else 0)));
+ text_func.append(") ram40_%d_%d (" % tile);
+ text_func.append(" .WADDR(%s)," % get_ram_wire('WADDR', 10, 0))
+ text_func.append(" .RADDR(%s)," % get_ram_wire('RADDR', 10, 0))
+ text_func.append(" .MASK(%s)," % get_ram_wire('MASK', 15, 0))
+ text_func.append(" .WDATA(%s)," % get_ram_wire('WDATA', 15, 0))
+ text_func.append(" .RDATA(%s)," % get_ram_wire('RDATA', 15, 0))
+ text_func.append(" .WE(%s)," % get_ram_wire('WE', 0, 0))
+ text_func.append(" .WCLKE(%s)," % get_ram_wire('WCLKE', 0, 0))
+ text_func.append(" .WCLK(%s)," % get_ram_wire('WCLK', 0, 0))
+ text_func.append(" .RE(%s)," % get_ram_wire('RE', 0, 0))
+ text_func.append(" .RCLKE(%s)," % get_ram_wire('RCLKE', 0, 0))
+ text_func.append(" .RCLK(%s)" % get_ram_wire('RCLK', 0, 0))
+ text_func.append(");")
+ text_func.append("")
+
wire_to_reg = set()
lut_assigns = list()
const_assigns = list()