diff options
author | Clifford Wolf <clifford@clifford.at> | 2018-05-13 20:55:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-13 20:55:43 +0200 |
commit | 51ae9e64f0db16ce71e32113d96a40b8915b26e7 (patch) | |
tree | bbe706304d24b5d3e2f8adb4f3146f9868632620 | |
parent | 1b22af089e2aa943daf569ad71f2261f7254ac7d (diff) | |
parent | f967b53fe9be32fc7a169847287f227e705dbe52 (diff) | |
download | icestorm-51ae9e64f0db16ce71e32113d96a40b8915b26e7.tar.gz icestorm-51ae9e64f0db16ce71e32113d96a40b8915b26e7.tar.bz2 icestorm-51ae9e64f0db16ce71e32113d96a40b8915b26e7.zip |
Merge pull request #139 from awygle/lm_icebox
Icebox support for ice40 LM
-rw-r--r-- | icebox/.gitignore | 1 | ||||
-rw-r--r-- | icebox/Makefile | 10 | ||||
-rw-r--r-- | icebox/icebox.py | 277 | ||||
-rwxr-xr-x | icebox/icebox_chipdb.py | 10 | ||||
-rw-r--r-- | icefuzz/Makefile | 5 | ||||
-rw-r--r-- | icefuzz/fuzzconfig.py | 19 | ||||
-rw-r--r-- | icefuzz/tests/colbuf_io_lm4k.sh | 41 | ||||
-rw-r--r-- | icefuzz/tests/colbuf_logic_lm4k.sh | 29 | ||||
-rwxr-xr-x | icefuzz/tests/colbuf_ram_lm4k.sh | 56 | ||||
-rw-r--r-- | icefuzz/tests/io_latched_lm4k.sh | 31 | ||||
-rw-r--r-- | icefuzz/tests/ioctrl_lm4k.py | 21 | ||||
-rwxr-xr-x | icefuzz/tests/ioctrl_lm4k.sh | 33 | ||||
-rwxr-xr-x | icefuzz/tests/pllauto/pllauto.py | 3 |
13 files changed, 521 insertions, 15 deletions
diff --git a/icebox/.gitignore b/icebox/.gitignore index 035ca9c..0cd67f6 100644 --- a/icebox/.gitignore +++ b/icebox/.gitignore @@ -1,5 +1,6 @@ chipdb-1k.txt chipdb-5k.txt +chipdb-lm4k.txt chipdb-8k.txt chipdb-384.txt __pycache__ diff --git a/icebox/Makefile b/icebox/Makefile index a26d80c..5f4d47a 100644 --- a/icebox/Makefile +++ b/icebox/Makefile @@ -1,6 +1,6 @@ include ../config.mk -all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt chipdb-5k.txt +all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt chipdb-5k.txt chipdb-lm4k.txt chipdb-384.txt: icebox.py iceboxdb.py icebox_chipdb.py python3 icebox_chipdb.py -3 > chipdb-384.new @@ -14,6 +14,10 @@ chipdb-5k.txt: icebox.py iceboxdb.py icebox_chipdb.py python3 icebox_chipdb.py -5 > chipdb-5k.new mv chipdb-5k.new chipdb-5k.txt +chipdb-lm4k.txt: icebox.py iceboxdb.py icebox_chipdb.py + python3 icebox_chipdb.py -4 > chipdb-lm4k.new + mv chipdb-lm4k.new chipdb-lm4k.txt + chipdb-8k.txt: icebox.py iceboxdb.py icebox_chipdb.py python3 icebox_chipdb.py -8 > chipdb-8k.new mv chipdb-8k.new chipdb-8k.txt @@ -24,7 +28,7 @@ check: all python3 tc_logic_xpr.py clean: - rm -f chipdb-1k.txt chipdb-8k.txt chipdb-384.txt chipdb-5k.txt + rm -f chipdb-1k.txt chipdb-8k.txt chipdb-384.txt chipdb-5k.txt chipdb-lm4k.txt rm -f icebox.pyc iceboxdb.pyc install: all @@ -34,6 +38,7 @@ install: all cp chipdb-1k.txt $(DESTDIR)$(PREFIX)/share/icebox/ cp chipdb-8k.txt $(DESTDIR)$(PREFIX)/share/icebox/ cp chipdb-5k.txt $(DESTDIR)$(PREFIX)/share/icebox/ + cp chipdb-lm4k.txt $(DESTDIR)$(PREFIX)/share/icebox/ cp icebox.py $(DESTDIR)$(PREFIX)/bin/icebox.py cp iceboxdb.py $(DESTDIR)$(PREFIX)/bin/iceboxdb.py cp icebox_chipdb.py $(DESTDIR)$(PREFIX)/bin/icebox_chipdb$(PY_EXE) @@ -63,6 +68,7 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-384.txt rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-1k.txt rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-8k.txt + rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-lm4k.txt -rmdir $(DESTDIR)$(PREFIX)/share/icebox .PHONY: all check clean install uninstall diff --git a/icebox/icebox.py b/icebox/icebox.py index af55719..36572c0 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -79,6 +79,30 @@ class iceconfig: self.io_tiles[(0, y)] = ["0" * 18 for i in range(16)] self.io_tiles[(self.max_x, y)] = ["0" * 18 for i in range(16)] + def setup_empty_lm4k(self): + self.clear() + self.device = "lm4k" + self.max_x = 25 + self.max_y = 21 + + for x in range(1, self.max_x): + for y in range(1, self.max_y): + if x in (6, 19): + 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)] + + for x in range(1, self.max_x): + self.io_tiles[(x, 0)] = ["0" * 18 for i in range(16)] + self.io_tiles[(x, self.max_y)] = ["0" * 18 for i in range(16)] + + for y in range(1, self.max_y): + self.io_tiles[(0, y)] = ["0" * 18 for i in range(16)] + self.io_tiles[(self.max_x, y)] = ["0" * 18 for i in range(16)] + def setup_empty_5k(self): self.clear() self.device = "5k" @@ -153,6 +177,7 @@ class iceconfig: def pinloc_db(self): if self.device == "384": return pinloc_db["384-qn32"] if self.device == "1k": return pinloc_db["1k-tq144"] + if self.device == "lm4k": return pinloc_db["lm4k-cm49"] if self.device == "5k": return pinloc_db["5k-sg48"] if self.device == "8k": return pinloc_db["8k-ct256"] assert False @@ -175,6 +200,8 @@ class iceconfig: def pll_list(self): if self.device == "1k": return ["1k"] + if self.device == "lm4k": + return ["lm4k"] if self.device == "5k": return ["5k"] if self.device == "8k": @@ -203,6 +230,19 @@ class iceconfig: entries.append((x, src_y, x, y)) return entries + # TODO(awygle) - actually capture 0 and 21 here + if self.device == "lm4k": + entries = list() + for x in range(self.max_x+1): + for y in range(self.max_y+1): + src_y = None + if 0 <= y <= 4: src_y = 4 + if 5 <= y <= 10: src_y = 5 + if 11 <= y <= 16: src_y = 16 + if 17 <= y <= 21: src_y = 17 + entries.append((x, src_y, x, y)) + return entries + if self.device == "8k": entries = list() for x in range(self.max_x+1): @@ -302,7 +342,7 @@ class iceconfig: def tile_db(self, x, y): # Only these devices have IO on the left and right sides. - if self.device in ["384", "1k", "8k"]: + if self.device in ["384", "1k", "lm4k", "8k"]: if x == 0: return iotile_l_db if x == self.max_x: return iotile_r_db # The 5k needs an IO db including the extra bits @@ -326,7 +366,7 @@ class iceconfig: if (x, y) in self.dsp_tiles[2]: return dsp2_5k_db if (x, y) in self.dsp_tiles[3]: return dsp3_5k_db - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": if (x, y) in self.logic_tiles: return logictile_8k_db if (x, y) in self.ramb_tiles: return rambtile_8k_db if (x, y) in self.ramt_tiles: return ramttile_8k_db @@ -449,7 +489,7 @@ class iceconfig: return (nx, ny, "ram/RDATA_%d" % func) elif self.device == "5k": return (nx, ny, "ram/RDATA_%d" % (15-func)) - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": return (nx, ny, "ram/RDATA_%d" % (15-func)) else: assert False @@ -458,7 +498,7 @@ class iceconfig: return (nx, ny, "ram/RDATA_%d" % (8+func)) elif self.device == "5k": return (nx, ny, "ram/RDATA_%d" % (7-func)) - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": return (nx, ny, "ram/RDATA_%d" % (7-func)) else: assert False @@ -500,7 +540,7 @@ class iceconfig: funcnets |= self.follow_funcnet(x, y, int(match.group(1)) % 8) elif self.device == "5k": funcnets |= self.follow_funcnet(x, y, 7 - int(match.group(1)) % 8) - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": funcnets |= self.follow_funcnet(x, y, 7 - int(match.group(1)) % 8) else: assert False @@ -714,7 +754,7 @@ class iceconfig: add_seed_segments(idx, tile, logictile_db) elif self.device == "5k": add_seed_segments(idx, tile, logictile_5k_db) - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": add_seed_segments(idx, tile, logictile_8k_db) elif self.device == "384": add_seed_segments(idx, tile, logictile_384_db) @@ -726,7 +766,7 @@ class iceconfig: add_seed_segments(idx, tile, rambtile_db) elif self.device == "5k": add_seed_segments(idx, tile, rambtile_8k_db) - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": add_seed_segments(idx, tile, rambtile_8k_db) else: assert False @@ -736,7 +776,7 @@ class iceconfig: add_seed_segments(idx, tile, ramttile_db) elif self.device == "5k": add_seed_segments(idx, tile, ramttile_8k_db) - elif self.device == "8k": + elif self.device == "8k" or self.device == "lm4k": add_seed_segments(idx, tile, ramttile_8k_db) else: assert False @@ -881,7 +921,7 @@ class iceconfig: self.extra_bits.add((int(line[1]), int(line[2]), int(line[3]))) continue if line[0] == ".device": - assert line[1] in ["1k", "5k", "8k", "384"] + assert line[1] in ["1k", "lm4k", "5k", "8k", "384"] self.device = line[1] continue if line[0] == ".warmboot": @@ -1303,7 +1343,8 @@ def run_checks_neigh(): print("Running consistency checks on neighbour finder..") ic = iceconfig() # ic.setup_empty_1k() - ic.setup_empty_5k() + ic.setup_empty_lm4k() + # ic.setup_empty_5k() # ic.setup_empty_8k() # ic.setup_empty_384() @@ -1353,7 +1394,8 @@ def parse_db(text, device="1k"): continue line = line_1k elif line_8k != line: - if device != "8k" and device != "5k": # global network is the same for 8k and 5k + # global network is the same for 8k, 5k, and lm4k + if device != "8k" and device != "5k" and device != "lm4k": continue line = line_8k elif line_384 != line: @@ -1378,6 +1420,16 @@ extra_bits_db = { (0, 330, 143): ("padin_glb_netwk", "6"), # (0 0) (330 143) (330 143) routing T_0_0.padin_6 <X> T_0_0.glb_netwk_6 (0, 331, 143): ("padin_glb_netwk", "7"), }, + "lm4k": { + (0, 654, 174): ("padin_glb_netwk", "0"), + (0, 655, 174): ("padin_glb_netwk", "1"), + (1, 654, 175): ("padin_glb_netwk", "2"), + (1, 655, 175): ("padin_glb_netwk", "3"), + (1, 654, 174): ("padin_glb_netwk", "4"), # HSOSC + (1, 655, 174): ("padin_glb_netwk", "5"), # LSOSC + (0, 654, 175): ("padin_glb_netwk", "6"), + (0, 655, 175): ("padin_glb_netwk", "7"), + }, "5k": { (0, 690, 334): ("padin_glb_netwk", "0"), # check (0, 691, 334): ("padin_glb_netwk", "1"), # good @@ -1431,6 +1483,16 @@ gbufin_db = { (13, 31, 1), #checked (19, 31, 2), #checked ], + "lm4k": [ + ( 6, 0, 6), + (12, 0, 5), + (13, 0, 0), + (19, 0, 7), + ( 6, 21, 3), + (12, 21, 4), + (13, 21, 1), + (19, 21, 2), + ], "8k": [ (33, 16, 7), ( 0, 16, 6), @@ -1468,6 +1530,10 @@ iolatch_db = { ( 5, 0), ( 8, 17), ], + "lm4k": [ + (14, 0), + (14, 21) + ], "5k": [ (14, 0), (14, 31), @@ -1500,6 +1566,12 @@ warmbootinfo_db = { "S0": ( 23, 0, "fabout" ), "S1": ( 24, 0, "fabout" ), }, + "lm4k": { + # These are the right locations but may be the wrong order. + "BOOT": ( 23, 0, "fabout" ), + "S0": ( 24, 0, "fabout" ), + "S1": ( 25, 1, "fabout" ), + }, "8k": { "BOOT": ( 31, 0, "fabout" ), "S0": ( 33, 1, "fabout" ), @@ -1619,6 +1691,99 @@ pllinfo_db = { "SDI": ( 4, 0, "fabout"), "SCLK": ( 3, 0, "fabout"), }, + "lm4k": { + "LOC" : (12, 0), + + # 3'b000 = "DISABLED" + # 3'b010 = "SB_PLL40_PAD" + # 3'b100 = "SB_PLL40_2_PAD" + # 3'b110 = "SB_PLL40_2F_PAD" + # 3'b011 = "SB_PLL40_CORE" + # 3'b111 = "SB_PLL40_2F_CORE" + "PLLTYPE_0": (12, 0, "PLLCONFIG_5"), + "PLLTYPE_1": (14, 0, "PLLCONFIG_1"), + "PLLTYPE_2": (14, 0, "PLLCONFIG_3"), + + # 3'b000 = "DELAY" + # 3'b001 = "SIMPLE" + # 3'b010 = "PHASE_AND_DELAY" + # 3'b110 = "EXTERNAL" + "FEEDBACK_PATH_0": (14, 0, "PLLCONFIG_5"), + "FEEDBACK_PATH_1": (11, 0, "PLLCONFIG_9"), + "FEEDBACK_PATH_2": (12, 0, "PLLCONFIG_1"), + + # 1'b0 = "FIXED" + # 1'b1 = "DYNAMIC" (also set FDA_FEEDBACK=4'b1111) + "DELAY_ADJMODE_FB": (13, 0, "PLLCONFIG_4"), + + # 1'b0 = "FIXED" + # 1'b1 = "DYNAMIC" (also set FDA_RELATIVE=4'b1111) + "DELAY_ADJMODE_REL": (13, 0, "PLLCONFIG_9"), + + # 2'b00 = "GENCLK" + # 2'b01 = "GENCLK_HALF" + # 2'b10 = "SHIFTREG_90deg" + # 2'b11 = "SHIFTREG_0deg" + "PLLOUT_SELECT_A_0": (12, 0, "PLLCONFIG_6"), + "PLLOUT_SELECT_A_1": (12, 0, "PLLCONFIG_7"), + # 2'b00 = "GENCLK" + # 2'b01 = "GENCLK_HALF" + # 2'b10 = "SHIFTREG_90deg" + # 2'b11 = "SHIFTREG_0deg" + "PLLOUT_SELECT_B_0": (12, 0, "PLLCONFIG_2"), + "PLLOUT_SELECT_B_1": (12, 0, "PLLCONFIG_3"), + + # Numeric Parameters + "SHIFTREG_DIV_MODE": (12, 0, "PLLCONFIG_4"), + "FDA_FEEDBACK_0": (12, 0, "PLLCONFIG_9"), + "FDA_FEEDBACK_1": (13, 0, "PLLCONFIG_1"), + "FDA_FEEDBACK_2": (13, 0, "PLLCONFIG_2"), + "FDA_FEEDBACK_3": (13, 0, "PLLCONFIG_3"), + "FDA_RELATIVE_0": (13, 0, "PLLCONFIG_5"), + "FDA_RELATIVE_1": (13, 0, "PLLCONFIG_6"), + "FDA_RELATIVE_2": (13, 0, "PLLCONFIG_7"), + "FDA_RELATIVE_3": (13, 0, "PLLCONFIG_8"), + "DIVR_0": (10, 0, "PLLCONFIG_1"), + "DIVR_1": (10, 0, "PLLCONFIG_2"), + "DIVR_2": (10, 0, "PLLCONFIG_3"), + "DIVR_3": (10, 0, "PLLCONFIG_4"), + "DIVF_0": (10, 0, "PLLCONFIG_5"), + "DIVF_1": (10, 0, "PLLCONFIG_6"), + "DIVF_2": (10, 0, "PLLCONFIG_7"), + "DIVF_3": (10, 0, "PLLCONFIG_8"), + "DIVF_4": (10, 0, "PLLCONFIG_9"), + "DIVF_5": (11, 0, "PLLCONFIG_1"), + "DIVF_6": (11, 0, "PLLCONFIG_2"), + "DIVQ_0": (11, 0, "PLLCONFIG_3"), + "DIVQ_1": (11, 0, "PLLCONFIG_4"), + "DIVQ_2": (11, 0, "PLLCONFIG_5"), + "FILTER_RANGE_0": (11, 0, "PLLCONFIG_6"), + "FILTER_RANGE_1": (11, 0, "PLLCONFIG_7"), + "FILTER_RANGE_2": (11, 0, "PLLCONFIG_8"), + "TEST_MODE": (12, 0, "PLLCONFIG_8"), + + # PLL Ports + # TODO(awygle) confirm these + "PLLOUT_A": ( 12, 0, 1), + "PLLOUT_B": ( 13, 0, 0), + "REFERENCECLK": ( 10, 0, "fabout"), + "EXTFEEDBACK": ( 11, 0, "fabout"), + "DYNAMICDELAY_0": ( 1, 0, "fabout"), + "DYNAMICDELAY_1": ( 2, 0, "fabout"), + "DYNAMICDELAY_2": ( 3, 0, "fabout"), + "DYNAMICDELAY_3": ( 4, 0, "fabout"), + "DYNAMICDELAY_4": ( 5, 0, "fabout"), + "DYNAMICDELAY_5": ( 7, 0, "fabout"), + "DYNAMICDELAY_6": ( 8, 0, "fabout"), + "DYNAMICDELAY_7": ( 9, 0, "fabout"), + "LOCK": ( 1, 1, "neigh_op_bnl_1"), #check? + "BYPASS": ( 15, 0, "fabout"), + "RESETB": ( 16, 0, "fabout"), + "LATCHINPUTVALUE": ( 14, 0, "fabout"), + "SDO": ( 24, 1, "neigh_op_bnr_3"), #check? + "SDI": ( 18, 0, "fabout"), + "SCLK": ( 17, 0, "fabout"), + }, "5k": { "LOC" : (12, 31), @@ -1910,6 +2075,18 @@ padin_pio_db = { ( 6, 0, 1), # glb_netwk_6 ( 6, 17, 1), # glb_netwk_7 ], + "lm4k": [ + (19, 0, 0), #0 fixed + ( 6, 0, 1), #1 fixed + (13, 21, 0), #2 fixed + (13, 0, 0), #3 fixed + + (19, 21, 0), #These two are questionable, but keep the order correct + ( 6, 21, 0), #They may need to be fixed if other package options are added. + + (12, 0, 1), #6 fixed + (12, 21, 1), #7 fixed + ], "5k": [ (19, 0, 1), #0 fixed ( 6, 0, 1), #1 fixed @@ -2308,6 +2485,45 @@ ieren_db = { ( 7, 6, 0, 7, 6, 1), ( 7, 6, 1, 7, 6, 0), ], + "lm4k": [ + ( 6, 0, 0, 6, 0, 1), + ( 6, 0, 1, 6, 0, 0), + ( 7, 0, 0, 7, 0, 1), + ( 7, 0, 1, 7, 0, 0), + ( 8, 0, 0, 8, 0, 1), + ( 8, 0, 1, 8, 0, 0), + (10, 0, 0, 10, 0, 1), + (12, 0, 0, 12, 0, 1), + (12, 0, 1, 12, 0, 0), + (13, 0, 0, 13, 0, 1), + (13, 0, 1, 13, 0, 0), + (19, 0, 0, 19, 0, 1), + (19, 0, 1, 19, 0, 0), + (21, 0, 0, 21, 0, 1), + (21, 0, 1, 21, 0, 0), + (22, 0, 0, 22, 0, 1), + (23, 0, 0, 23, 0, 1), + (23, 0, 1, 23, 0, 0), + (24, 0, 0, 24, 0, 1), + (24, 0, 1, 24, 0, 0), + ( 4, 21, 0, 4, 21, 1), + ( 4, 21, 1, 4, 21, 0), + ( 5, 21, 1, 5, 21, 0), + ( 6, 21, 0, 6, 21, 1), + ( 7, 21, 1, 7, 21, 0), + ( 9, 21, 0, 9, 21, 1), + (12, 21, 1, 12, 21, 0), + (13, 21, 0, 13, 21, 1), + (15, 21, 0, 15, 21, 1), + (17, 21, 1, 17, 21, 0), + (18, 21, 0, 18, 21, 1), + (19, 21, 0, 19, 21, 1), + (19, 21, 1, 19, 21, 0), + (21, 21, 1, 21, 21, 0), + (22, 21, 1, 22, 21, 0), + (23, 21, 0, 23, 21, 1), + (23, 21, 1, 23, 21, 0), + ], "5k": [ ( 8, 0, 0, 8, 0, 1), ( 9, 0, 1, 9, 0, 0), @@ -4615,6 +4831,45 @@ pinloc_db = { ( "F2", 19, 0, 1), ( "F4", 12, 0, 1), ( "F5", 6, 0, 1), + ], + "lm4k-cm49": [ + ( "A1", 5, 21, 1), + ( "A2", 6, 21, 0), + ( "A3", 12, 21, 1), + ( "A4", 13, 21, 0), + ( "A5", 17, 21, 1), + ( "A6", 19, 21, 1), + ( "A7", 22, 21, 1), + ( "B1", 4, 21, 1), + ( "B2", 7, 21, 1), + ( "B4", 15, 21, 0), + ( "B6", 18, 21, 0), + ( "B7", 23, 21, 1), + ( "C1", 4, 21, 0), + ( "C3", 9, 21, 0), + ( "C4", 19, 21, 0), + ( "C6", 21, 21, 1), + ( "C7", 23, 21, 0), + ( "D1", 7, 0, 1), + ( "D2", 6, 0, 1), + ( "D3", 10, 0, 0), + ( "D6", 19, 0, 1), + ( "D7", 21, 0, 0), + ( "E1", 6, 0, 0), + ( "E2", 12, 0, 1), + ( "E3", 7, 0, 0), + ( "E4", 12, 0, 0), + ( "E5", 19, 0, 0), + ( "E6", 24, 0, 1), + ( "E7", 22, 0, 0), + ( "F2", 8, 0, 1), + ( "F3", 8, 0, 0), + ( "F4", 13, 0, 1), + ( "F5", 23, 0, 0), + ( "F6", 24, 0, 0), + ( "F7", 21, 0, 1), + ( "G3", 13, 0, 0), + ( "G6", 23, 0, 1), ] } diff --git a/icebox/icebox_chipdb.py b/icebox/icebox_chipdb.py index 6ff7c46..6497ae2 100755 --- a/icebox/icebox_chipdb.py +++ b/icebox/icebox_chipdb.py @@ -19,6 +19,7 @@ import icebox import getopt, sys, re mode_384 = False +mode_lm4k = False mode_5k = False mode_8k = False @@ -34,11 +35,14 @@ Usage: icebox_chipdb [options] [bitmap.asc] -8 create chipdb for 8k device + + -4 + create chipdb for lm4k device """) sys.exit(0) try: - opts, args = getopt.getopt(sys.argv[1:], "358") + opts, args = getopt.getopt(sys.argv[1:], "3584") except: usage() @@ -49,6 +53,8 @@ for o, a in opts: mode_5k = True elif o == "-3": mode_384 = True + elif o == "-4": + mode_lm4k = True else: usage() @@ -59,6 +65,8 @@ elif mode_5k: ic.setup_empty_5k() elif mode_384: ic.setup_empty_384() +elif mode_lm4k: + ic.setup_empty_lm4k() else: ic.setup_empty_1k() diff --git a/icefuzz/Makefile b/icefuzz/Makefile index a2a40b4..ea9f3e0 100644 --- a/icefuzz/Makefile +++ b/icefuzz/Makefile @@ -18,6 +18,11 @@ ifeq ($(DEVICECLASS), 5k) RAM_SUFFIX := _8k endif +ifeq ($(DEVICECLASS), 4k) + DEVICE := lm4k-cm49 + RAM_SUFFIX := _8k +endif + ifeq ($(DEVICECLASS), 8k) DEVICE := hx8k-ct256 RAM_SUFFIX = _8k diff --git a/icefuzz/fuzzconfig.py b/icefuzz/fuzzconfig.py index a50cce5..f03c815 100644 --- a/icefuzz/fuzzconfig.py +++ b/icefuzz/fuzzconfig.py @@ -60,6 +60,25 @@ elif device_class == "1k": """.split() gpins = "20 21 49 50 93 94 128 129".split() + +elif device_class == "4k": + num_ramb40 = 20 + num_iobanks = 2 + num_dsp = 0 + + # TODO(awygle) add F5 G6 F6 E6 which are constrained to (config) SPI. + pins = """ + A1 A2 A3 A4 A5 A6 A7 + B1 B2 B4 B6 B7 + C1 C3 C4 C6 C7 + D1 D2 D3 D6 D7 + E1 E2 E3 E4 E5 E7 + F2 F3 F4 F7 + G3 + """.split() + + gpins = "A3 A4 D2 E2 E5 G3".split() + elif device_class == "5k": num_ramb40 = 30 num_iobanks = 2 diff --git a/icefuzz/tests/colbuf_io_lm4k.sh b/icefuzz/tests/colbuf_io_lm4k.sh new file mode 100644 index 0000000..80d2f64 --- /dev/null +++ b/icefuzz/tests/colbuf_io_lm4k.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -ex + +mkdir -p colbuf_io_lm4k.work +cd colbuf_io_lm4k.work + +glb_pins="A3 A4 D2 E2 E5 G3" + +pins=" + A1 A2 A3 A4 A5 A6 A7 + B1 B2 B4 B6 B7 + C1 C3 C4 C6 C7 + D1 D2 D3 D6 D7 + E1 E2 E3 E4 E5 E7 + F2 F3 F4 F7 + G3 +" +pins="$( echo $pins )" + +for pin in $pins; do + pf="colbuf_io_lm4k_$pin" + gpin=$( echo $glb_pins | tr ' ' '\n' | grep -v $pin | sort -R | head -n1; ) + cat > ${pf}.v <<- EOT + module top (input clk, data, output pin); + SB_IO #( + .PIN_TYPE(6'b 0101_00) + ) pin_obuf ( + .PACKAGE_PIN(pin), + .OUTPUT_CLK(clk), + .D_OUT_0(data) + ); + endmodule + EOT + echo "set_io pin $pin" > ${pf}.pcf + echo "set_io clk $gpin" >> ${pf}.pcf + ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v > ${pf}.log 2>&1 + ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp + rm -rf ${pf}.tmp +done + diff --git a/icefuzz/tests/colbuf_logic_lm4k.sh b/icefuzz/tests/colbuf_logic_lm4k.sh new file mode 100644 index 0000000..d1dc681 --- /dev/null +++ b/icefuzz/tests/colbuf_logic_lm4k.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -ex + +mkdir -p colbuf_logic_lm4k.work +cd colbuf_logic_lm4k.work + +glb_pins="A3 A4 D2 E2 E5 G3" + +for y in {1..32}; do +for y in {1..20}; do + pf="colbuf_logic_lm4k_${x}_${y}" + gpin=$( echo $glb_pins | tr ' ' '\n' | sort -R | head -n1; ) + cat > ${pf}.v <<- EOT + module top (input c, d, output q); + SB_DFF dff ( + .C(c), + .D(d), + .Q(q) + ); + endmodule + EOT + echo "set_location dff $x $y 0" > ${pf}.pcf + echo "set_io c $gpin" >> ${pf}.pcf + ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v > ${pf}.log 2>&1 + ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp + rm -rf ${pf}.tmp +done; done + diff --git a/icefuzz/tests/colbuf_ram_lm4k.sh b/icefuzz/tests/colbuf_ram_lm4k.sh new file mode 100755 index 0000000..86fb08a --- /dev/null +++ b/icefuzz/tests/colbuf_ram_lm4k.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +set -ex + +mkdir -p colbuf_ram_lm4k.work +cd colbuf_ram_lm4k.work + +glb_pins="A3 A4 D2 E2 E5 G3" + +for x in 6 19; do +for y in {1..20}; do + pf="colbuf_ram_lm4k_${x}_${y}" + gpin=$( echo $glb_pins | tr ' ' '\n' | sort -R | head -n1; ) + if [ $((y % 2)) == 1 ]; then + clkport="WCLK" + other_clkport="RCLK" + else + clkport="RCLK" + other_clkport="WCLK" + fi + cat > ${pf}.v <<- EOT + module top (input c, oc, input [1:0] d, output [1:0] q); + wire gc; + SB_GB_IO #( + .PIN_TYPE(6'b 0000_00), + .PULLUP(1'b0), + .NEG_TRIGGER(1'b0), + .IO_STANDARD("SB_LVCMOS") + ) gbuf ( + .PACKAGE_PIN(c), + .GLOBAL_BUFFER_OUTPUT(gc) + ); + SB_RAM40_4K #( + .READ_MODE(3), + .WRITE_MODE(3) + ) ram40 ( + .WADDR(11'b0), + .RADDR(11'b0), + .$clkport(gc), + .$other_clkport(oc), + .RDATA(q), + .WDATA(d), + .WE(1'b1), + .WCLKE(1'b1), + .RE(1'b1), + .RCLKE(1'b1) + ); + endmodule + EOT + echo "set_location ram40 $x $((y - (1 - y%2))) 0" > ${pf}.pcf + echo "set_io oc 1" >> ${pf}.pcf + echo "set_io c $gpin" >> ${pf}.pcf + ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v > ${pf}.log 2>&1 + ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp + rm -rf ${pf}.tmp +done; done diff --git a/icefuzz/tests/io_latched_lm4k.sh b/icefuzz/tests/io_latched_lm4k.sh new file mode 100644 index 0000000..5e6b63c --- /dev/null +++ b/icefuzz/tests/io_latched_lm4k.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -ex + +mkdir -p io_latched_lm4k.work +cd io_latched_lm4k.work + +pins=" + A1 A2 A3 A4 A5 A6 A7 + B1 B2 B4 B6 B7 + C1 C3 C4 C6 C7 + D1 D2 D3 D6 D7 + E1 E2 E3 E4 E5 E7 + F2 F3 F4 F7 + G3 +" +pins="$( echo $pins )" + +for pin in $pins; do + pf="io_latched_$pin" + cp ../io_latched.v ${pf}.v + read pin_latch pin_data < <( echo $pins | tr ' ' '\n' | grep -v $pin | sort -R; ) + { + echo "set_io pin $pin" + echo "set_io latch_in $pin_latch" + echo "set_io data_out $pin_data" + } > ${pf}.pcf + ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v + ../../../icebox/icebox_vlog.py -SP ${pf}.psb ${pf}.asc > ${pf}.ve +done + diff --git a/icefuzz/tests/ioctrl_lm4k.py b/icefuzz/tests/ioctrl_lm4k.py new file mode 100644 index 0000000..67c0c6d --- /dev/null +++ b/icefuzz/tests/ioctrl_lm4k.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +import fileinput + +for line in fileinput.input(): + line = line.split() + if len(line) == 0: + continue + if line[0] == ".io_tile": + current_tile = (int(line[1]), int(line[2])) + if line[0] == "IoCtrl" and line[1] == "REN_0": + ren = (current_tile[0], current_tile[1], 0) + if line[0] == "IoCtrl" and line[1] == "REN_1": + ren = (current_tile[0], current_tile[1], 1) + if line[0] == "IOB_0": + iob = (current_tile[0], current_tile[1], 0) + if line[0] == "IOB_1": + iob = (current_tile[0], current_tile[1], 1) + +print("(%2d, %2d, %2d, %2d, %2d, %2d)," % (iob[0], iob[1], iob[2], ren[0], ren[1], ren[2])) + diff --git a/icefuzz/tests/ioctrl_lm4k.sh b/icefuzz/tests/ioctrl_lm4k.sh new file mode 100755 index 0000000..9722038 --- /dev/null +++ b/icefuzz/tests/ioctrl_lm4k.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -ex + +mkdir -p ioctrl.work +cd ioctrl.work + +pins=" + A1 A2 A3 A4 A5 A6 A7 + B1 B2 B4 B6 B7 + C1 C3 C4 C6 C7 + D1 D2 D3 D6 D7 + E1 E2 E3 E4 E5 E6 E7 + F2 F3 F4 F5 F6 F7 + G3 G6 +" + +pins="$( echo $pins )" + +for pin in $pins; do + pf="ioctrl_$pin" + echo "module top (output pin); assign pin = 1; endmodule" > ${pf}.v + echo "set_io pin $pin" > ${pf}.pcf + bash ../../icecube.sh -lm4k ${pf}.v > ${pf}.log 2>&1 + ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp +done + +set +x +echo "--snip--" +for pin in $pins; do + python3 ../ioctrl_5k.py ioctrl_${pin}.exp +done | tee ioctrl_db.txt +echo "--snap--" diff --git a/icefuzz/tests/pllauto/pllauto.py b/icefuzz/tests/pllauto/pllauto.py index 647be29..517417d 100755 --- a/icefuzz/tests/pllauto/pllauto.py +++ b/icefuzz/tests/pllauto/pllauto.py @@ -209,7 +209,8 @@ device = "up5k" #TODO: environment variable? #and look for the stuck bit) #TODO: clever code could get rid of this divq_bit0 = { - "up5k" : (11, 31, 3) + "up5k" : (11, 31, 3), + "lm4k" : (11, 0, 3) } #Return a list of PLL config bits in the format (x, y, bit) |