aboutsummaryrefslogtreecommitdiffstats
path: root/icefuzz/tests
diff options
context:
space:
mode:
Diffstat (limited to 'icefuzz/tests')
-rw-r--r--icefuzz/tests/dsp_cbit/.gitignore1
-rw-r--r--icefuzz/tests/dsp_cbit/dsp_cbits_up5k.txt9
-rwxr-xr-xicefuzz/tests/dsp_cbit/fuzz_dsp_cbit.py132
-rw-r--r--icefuzz/tests/rgba_drv_cbit/.gitignore1
-rwxr-xr-xicefuzz/tests/rgba_drv_cbit/fuzz_rgba_drv_cbit.py174
-rw-r--r--icefuzz/tests/rgba_drv_cbit/rgba_drv_data_up5k.txt20
-rw-r--r--icefuzz/tests/spram/.gitignore1
-rwxr-xr-xicefuzz/tests/spram/fuzz_spram.py174
-rw-r--r--icefuzz/tests/spram/up5k_spram_data.txt236
9 files changed, 748 insertions, 0 deletions
diff --git a/icefuzz/tests/dsp_cbit/.gitignore b/icefuzz/tests/dsp_cbit/.gitignore
new file mode 100644
index 0000000..95ff890
--- /dev/null
+++ b/icefuzz/tests/dsp_cbit/.gitignore
@@ -0,0 +1 @@
+work_dsp_cbit/
diff --git a/icefuzz/tests/dsp_cbit/dsp_cbits_up5k.txt b/icefuzz/tests/dsp_cbit/dsp_cbits_up5k.txt
new file mode 100644
index 0000000..e90c647
--- /dev/null
+++ b/icefuzz/tests/dsp_cbit/dsp_cbits_up5k.txt
@@ -0,0 +1,9 @@
+DSP (0, 15):
+ Missing (0, 16, CBIT_1)
+ Missing (0, 16, CBIT_2)
+ Missing (0, 16, CBIT_3)
+ Missing (0, 16, CBIT_4)
+ New: (0, 19, CBIT_3)
+ New: (0, 19, CBIT_5)
+ New: (0, 19, CBIT_4)
+ New: (0, 19, CBIT_6)
diff --git a/icefuzz/tests/dsp_cbit/fuzz_dsp_cbit.py b/icefuzz/tests/dsp_cbit/fuzz_dsp_cbit.py
new file mode 100755
index 0000000..79f376c
--- /dev/null
+++ b/icefuzz/tests/dsp_cbit/fuzz_dsp_cbit.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+
+import os, sys
+
+device = "up5k"
+
+# This script is designed to determine which DSPs have configuration bits
+# not in their usual position, as in some cases DSP and IPConnect tiles have
+# their config bits swapped
+
+# Unfortunately, arbitrary configurations are not allowed by icecube, so
+# we define a set that gives us maximum coverage (full coverage is not
+# possible as one CBIT is never set)
+
+allowed_configs = ["1110000010000001001110110", "0010000101000010111111111", "0001111000101100000000000"]
+
+coverage = set()
+for c in allowed_configs:
+ for i in range(25):
+ if c[i] == "1":
+ coverage.add(i)
+
+assert len(coverage) >= 24
+
+def parse_exp(f):
+ current_x = 0
+ current_y = 0
+ bits = set()
+ for line in f:
+ splitline = line.split(' ')
+ if splitline[0].endswith("_tile"):
+ current_x = int(splitline[1])
+ current_y = int(splitline[2])
+ elif splitline[0] == "IpConfig":
+ if splitline[1][:5] == "CBIT_":
+ bitidx = int(splitline[1][5:])
+ bits.add((current_x, current_y, bitidx))
+ return bits
+dsp_locs = [( 0, 5, 0), ( 0, 10, 0), ( 0, 15, 0), ( 0, 23, 0),
+ (25, 5, 0), (25, 10, 0), (25, 15, 0), (25, 23, 0)]
+
+dsp_data = {}
+
+if not os.path.exists("./work_dsp_cbit"):
+ os.mkdir("./work_dsp_cbit")
+
+for loc in dsp_locs:
+ x, y, z = loc
+ missing_bits = set()
+ new_bits = set()
+ for config in allowed_configs:
+ params = config[::-1]
+ with open("./work_dsp_cbit/dsp_cbit.v","w") as f:
+ print("""
+ module top(input clk, input a, input b, input c, input d, output y);
+ """, file=f)
+ print("""
+ SB_MAC16 #(
+ .C_REG(1'b%s),
+ .A_REG(1'b%s),
+ .B_REG(1'b%s),
+ .D_REG(1'b%s),
+ .TOP_8x8_MULT_REG(1'b%s),
+ .BOT_8x8_MULT_REG(1'b%s),
+ .PIPELINE_16x16_MULT_REG1(1'b%s),
+ .PIPELINE_16x16_MULT_REG2(1'b%s),
+ .TOPOUTPUT_SELECT(2'b%s),
+ .TOPADDSUB_LOWERINPUT(2'b%s),
+ .TOPADDSUB_UPPERINPUT(1'b%s),
+ .TOPADDSUB_CARRYSELECT(2'b%s),
+ .BOTOUTPUT_SELECT(2'b%s),
+ .BOTADDSUB_LOWERINPUT(2'b%s),
+ .BOTADDSUB_UPPERINPUT(1'b%s),
+ .BOTADDSUB_CARRYSELECT(2'b%s),
+ .MODE_8x8(1'b%s),
+ .A_SIGNED(1'b%s),
+ .B_SIGNED(1'b%s)
+ ) dsp (
+ .CLK(clk),
+ .C(c),
+ .A(a),
+ .B(b),
+ .D(d),
+ .O(y)
+ );"""
+ % (
+ params[0], params[1], params[2], params[3],
+ params[4], params[5], params[6], params[7],
+ params[8:10][::-1], params[10:12][::-1], params[12], params[13:15][::-1],
+ params[15:17][::-1], params[17:19][::-1], params[19], params[20:22][::-1],
+ params[22], params[23], params[24]), file=f)
+ print("endmodule",file=f)
+ with open("./work_dsp_cbit/dsp_cbit.pcf","w") as f:
+ print("set_location dsp %d %d %d" % loc, file=f)
+ retval = os.system("bash ../../icecube.sh -" + device + " ./work_dsp_cbit/dsp_cbit.v > ./work_dsp_cbit/icecube.log 2>&1")
+ if retval != 0:
+ sys.stderr.write('ERROR: icecube returned non-zero error code\n')
+ sys.exit(1)
+ retval = os.system("../../../icebox/icebox_explain.py ./work_dsp_cbit/dsp_cbit.asc > ./work_dsp_cbit/dsp_cbit.exp")
+ if retval != 0:
+ sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n')
+ sys.exit(1)
+ bits = set()
+ known = set()
+ with open('./work_dsp_cbit/dsp_cbit.exp', 'r') as f:
+ bits = parse_exp(f)
+ for i in range(25):
+ if params[i] == "1":
+ exp_pos = (x, y + (i // 8), i % 8)
+ if exp_pos not in bits:
+ missing_bits.add(exp_pos)
+ else:
+ known.add(exp_pos)
+ for bit in bits:
+ if bit not in known:
+ new_bits.add(bit)
+ if len(missing_bits) > 0 or len(new_bits) > 0:
+ print("DSP (%d, %d):" % (x, y))
+ for bit in missing_bits:
+ print("\tMissing (%d, %d, CBIT_%d)" % bit)
+ for bit in new_bits:
+ print("\tNew: (%d, %d, CBIT_%d)" % bit)
+ dsp_data[loc] = (missing_bits, new_bits)
+with open("dsp_cbits_%s.txt" % device, 'w') as f:
+ for loc in dsp_data:
+ x, y, z = loc
+ missing_bits, new_bits = dsp_data[loc]
+ print("DSP (%d, %d):" % (x, y), file=f)
+ for bit in missing_bits:
+ print("\tMissing (%d, %d, CBIT_%d)" % bit,file=f)
+ for bit in new_bits:
+ print("\tNew: (%d, %d, CBIT_%d)" % bit,file=f)
diff --git a/icefuzz/tests/rgba_drv_cbit/.gitignore b/icefuzz/tests/rgba_drv_cbit/.gitignore
new file mode 100644
index 0000000..a0beeed
--- /dev/null
+++ b/icefuzz/tests/rgba_drv_cbit/.gitignore
@@ -0,0 +1 @@
+work_rgba_drv/
diff --git a/icefuzz/tests/rgba_drv_cbit/fuzz_rgba_drv_cbit.py b/icefuzz/tests/rgba_drv_cbit/fuzz_rgba_drv_cbit.py
new file mode 100755
index 0000000..3d43ba4
--- /dev/null
+++ b/icefuzz/tests/rgba_drv_cbit/fuzz_rgba_drv_cbit.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python3
+
+import os, sys
+# SB_RGBA_DRV automatic fuzzing script
+
+device = "up5k"
+
+# SB_RGBA_DRV config bits to be fuzzed
+# These must be in an order such that a config with bit i set doesn't set any other undiscovered bits yet
+
+
+fuzz_bits = [
+ "RGB0_CURRENT_0",
+ "RGB0_CURRENT_1",
+ "RGB0_CURRENT_2",
+ "RGB0_CURRENT_3",
+ "RGB0_CURRENT_4",
+ "RGB0_CURRENT_5",
+
+ "RGB1_CURRENT_0",
+ "RGB1_CURRENT_1",
+ "RGB1_CURRENT_2",
+ "RGB1_CURRENT_3",
+ "RGB1_CURRENT_4",
+ "RGB1_CURRENT_5",
+
+ "RGB2_CURRENT_0",
+ "RGB2_CURRENT_1",
+ "RGB2_CURRENT_2",
+ "RGB2_CURRENT_3",
+ "RGB2_CURRENT_4",
+ "RGB2_CURRENT_5",
+
+ "CURRENT_MODE"
+]
+
+
+# Boilerplate code based on the icefuzz script
+code_prefix = """
+module top(
+ input curren,
+ input rgbleden,
+ input r_in,
+ input g_in,
+ input b_in,
+ output r_led,
+ output g_led,
+ output b_led);
+"""
+
+def get_param_value(param_name, param_size, fuzz_bit):
+ param = "\"0b";
+ #In the RGB driver, once bit i of a current parameter is set i-1..0 must also be set
+ is_high = False
+ for i in range(param_size - 1, -1, -1):
+ if fuzz_bit == param_name + "_" + str(i) or (i == 0 and fuzz_bit == "CURRENT_MODE") or is_high:
+ param += '1'
+ is_high = True
+ else:
+ param += '0'
+ param += "\""
+ return param
+def inst_rgba(fuzz_bit):
+ v = ""
+ v += """SB_RGBA_DRV rgba_inst (
+ .CURREN(curren),
+ .RGBLEDEN(rgbleden),
+ .RGB0PWM(r_in),
+ .RGB1PWM(g_in),
+ .RGB2PWM(b_in),
+ .RGB0(r_led),
+ .RGB1(g_led),
+ .RGB2(b_led)
+ );"""
+
+ v += "defparam rgba_inst.CURRENT_MODE = " + get_param_value("CURRENT_MODE", 1, fuzz_bit) + ";\n"
+ v += "defparam rgba_inst.RGB0_CURRENT = " + get_param_value("RGB0_CURRENT", 6, fuzz_bit) + ";\n"
+ v += "defparam rgba_inst.RGB1_CURRENT = " + get_param_value("RGB1_CURRENT", 6, fuzz_bit) + ";\n"
+ v += "defparam rgba_inst.RGB2_CURRENT = " + get_param_value("RGB2_CURRENT", 6, fuzz_bit) + ";\n"
+
+ return v;
+
+def make_vlog(fuzz_bit):
+ vlog = code_prefix
+ vlog += inst_rgba(fuzz_bit)
+ vlog += "endmodule"
+ return vlog
+
+known_bits = []
+
+# Set to true to continue even if multiple bits are changed (needed because
+# of the issue discusssed below)
+show_all_bits = False #TODO: make this an argument
+
+device = "up5k" #TODO: environment variable?
+
+#HACK: icecube doesn't let you set all of the config bits to 0,
+#which makes fuzzing early on annoying as there is never a case
+#with just 1 bit set. So a tiny bit of semi-manual work is needed
+#first to discover this (basically run this script with show_all_bits=True
+#and look for the stuck bit)
+#TODO: clever code could get rid of this
+rgba_drv_en_bit = {
+ "up5k" : (0, 28, 5)
+}
+
+#Return a list of RGBA_DRIVER config bits in the format (x, y, bit)
+def parse_exp(expfile):
+ current_x = 0
+ current_y = 0
+ bits = []
+ with open(expfile, 'r') as f:
+ for line in f:
+ splitline = line.split(' ')
+ if splitline[0].endswith("_tile"):
+ current_x = int(splitline[1])
+ current_y = int(splitline[2])
+ elif splitline[0] == "IpConfig":
+ if splitline[1][:5] == "CBIT_":
+ bitidx = int(splitline[1][5:])
+ bits.append((current_x, current_y, bitidx))
+ return bits
+
+#Convert a bit tuple as returned from the above to a nice string
+def bit_to_str(bit):
+ return "(%d, %d, \"CBIT_%d\")" % bit
+
+#The main fuzzing function
+def do_fuzz():
+ if not os.path.exists("./work_rgba_drv"):
+ os.mkdir("./work_rgba_drv")
+ known_bits.append(rgba_drv_en_bit[device])
+ with open("rgba_drv_data_" + device + ".txt", 'w') as dat:
+ for fuzz_bit in fuzz_bits:
+ vlog = make_vlog(fuzz_bit)
+ with open("./work_rgba_drv/rgba_drv.v", 'w') as f:
+ f.write(vlog)
+ with open("./work_rgba_drv/rgba_drv.pcf", 'w') as f:
+ f.write("""
+set_io r_led 39
+set_io g_led 40
+set_io b_led 41
+ """)
+ retval = os.system("bash ../../icecube.sh -" + device + " ./work_rgba_drv/rgba_drv.v > ./work_rgba_drv/icecube.log 2>&1")
+ if retval != 0:
+ sys.stderr.write('ERROR: icecube returned non-zero error code\n')
+ sys.exit(1)
+ retval = os.system("../../../icebox/icebox_explain.py ./work_rgba_drv/rgba_drv.asc > ./work_rgba_drv/rgba_drv.exp")
+ if retval != 0:
+ sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n')
+ sys.exit(1)
+ rgba_bits = parse_exp("./work_rgba_drv/rgba_drv.exp")
+ new_bits = []
+ for set_bit in rgba_bits:
+ if not (set_bit in known_bits):
+ new_bits.append(set_bit)
+ if len(new_bits) == 0:
+ sys.stderr.write('ERROR: no new bits set when setting config bit ' + fuzz_bit + '\n')
+ sys.exit(1)
+ if len(new_bits) > 1:
+ sys.stderr.write('ERROR: multiple new bits set when setting config bit ' + fuzz_bit + '\n')
+ for bit in new_bits:
+ sys.stderr.write('\t' + bit_to_str(bit) + '\n')
+ if not show_all_bits:
+ sys.exit(1)
+ if len(new_bits) == 1:
+ known_bits.append(new_bits[0])
+ #print DIVQ_0 at the right moment, as it's not fuzzed normally
+ if fuzz_bit == "RGB0_CURRENT_0":
+ print(("\"RGBA_DRV_EN\":").ljust(24) + bit_to_str(rgba_drv_en_bit[device]) + ",")
+ dat.write(("\"RGBA_DRV_EN\":").ljust(24) + bit_to_str(rgba_drv_en_bit[device]) + ",\n")
+ print(("\"" + fuzz_bit + "\":").ljust(24) + bit_to_str(new_bits[0]) + ",")
+ dat.write(("\"" + fuzz_bit + "\":").ljust(24) + bit_to_str(new_bits[0]) + ",\n")
+do_fuzz()
diff --git a/icefuzz/tests/rgba_drv_cbit/rgba_drv_data_up5k.txt b/icefuzz/tests/rgba_drv_cbit/rgba_drv_data_up5k.txt
new file mode 100644
index 0000000..73bfb90
--- /dev/null
+++ b/icefuzz/tests/rgba_drv_cbit/rgba_drv_data_up5k.txt
@@ -0,0 +1,20 @@
+"RGBA_DRV_EN": (0, 28, "CBIT_5"),
+"RGB0_CURRENT_0": (0, 28, "CBIT_6"),
+"RGB0_CURRENT_1": (0, 28, "CBIT_7"),
+"RGB0_CURRENT_2": (0, 29, "CBIT_0"),
+"RGB0_CURRENT_3": (0, 29, "CBIT_1"),
+"RGB0_CURRENT_4": (0, 29, "CBIT_2"),
+"RGB0_CURRENT_5": (0, 29, "CBIT_3"),
+"RGB1_CURRENT_0": (0, 29, "CBIT_4"),
+"RGB1_CURRENT_1": (0, 29, "CBIT_5"),
+"RGB1_CURRENT_2": (0, 29, "CBIT_6"),
+"RGB1_CURRENT_3": (0, 29, "CBIT_7"),
+"RGB1_CURRENT_4": (0, 30, "CBIT_0"),
+"RGB1_CURRENT_5": (0, 30, "CBIT_1"),
+"RGB2_CURRENT_0": (0, 30, "CBIT_2"),
+"RGB2_CURRENT_1": (0, 30, "CBIT_3"),
+"RGB2_CURRENT_2": (0, 30, "CBIT_4"),
+"RGB2_CURRENT_3": (0, 30, "CBIT_5"),
+"RGB2_CURRENT_4": (0, 30, "CBIT_6"),
+"RGB2_CURRENT_5": (0, 30, "CBIT_7"),
+"CURRENT_MODE": (0, 28, "CBIT_4"),
diff --git a/icefuzz/tests/spram/.gitignore b/icefuzz/tests/spram/.gitignore
new file mode 100644
index 0000000..7ce4577
--- /dev/null
+++ b/icefuzz/tests/spram/.gitignore
@@ -0,0 +1 @@
+work_spram/
diff --git a/icefuzz/tests/spram/fuzz_spram.py b/icefuzz/tests/spram/fuzz_spram.py
new file mode 100755
index 0000000..05fd828
--- /dev/null
+++ b/icefuzz/tests/spram/fuzz_spram.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python3
+
+import os, sys, re
+
+device = "up5k"
+
+pins = "2 3 4 6 9 10 11 12 13 18 19 20 21 25 26 27 28 31 32 34 35 36 37 38 42 43 44 45 46 47 48".split()
+
+# This script is designed to determine the routing of 5k SPRAM signals,
+# and the location of the enable config bits
+
+spram_locs = [(0, 0, 1), (0, 0, 2), (25, 0, 3), (25, 0, 4)]
+#spram_locs = [(0, 0, 1)]
+spram_data = { }
+
+spram_signals = ["WREN", "CHIPSELECT", "CLOCK", "STANDBY", "SLEEP", "POWEROFF"]
+
+for i in range(14):
+ spram_signals.append("ADDRESS[%d]" % i)
+
+for i in range(16):
+ spram_signals.append("DATAIN[%d]" % i)
+
+for i in range(16):
+ spram_signals.append("DATAOUT[%d]" % i)
+
+for i in range(4):
+ spram_signals.append("MASKWREN[%d]" % i)
+
+fuzz_options = ["ADDRESS", "DATAIN", "MASKWREN", "DATAOUT"]
+
+#Parse the output of an icebox vlog file to determine connectivity
+def parse_vlog(f, pin2net, net_map):
+ current_net = None
+
+ for line in f:
+ m = re.match(r"wire ([a-zA-Z0-9_]+);", line)
+ if m:
+ net = m.group(1)
+ mp = re.match(r"pin_([a-zA-Z0-9]+)", net)
+ if mp:
+ pin = mp.group(1)
+ if pin in pin2net:
+ current_net = pin2net[pin]
+ else:
+ current_net = None
+ else:
+ current_net = None
+ elif current_net is not None:
+ m = re.match(r"// \((\d+), (\d+), '([a-zA-Z0-9_/]+)'\)", line)
+ if m:
+ x = int(m.group(1))
+ y = int(m.group(2))
+ net = m.group(3)
+ if not (net.startswith("sp") or net.startswith("glb") or net.startswith("neigh") or net.startswith("io") or net.startswith("local") or net.startswith("fabout")):
+ net_map[current_net].add((x, y, net))
+def parse_exp(f):
+ current_x = 0
+ current_y = 0
+ bits = set()
+ for line in f:
+ splitline = line.split(' ')
+ if splitline[0].endswith("_tile"):
+ current_x = int(splitline[1])
+ current_y = int(splitline[2])
+ elif splitline[0] == "IpConfig":
+ if splitline[1][:5] == "CBIT_":
+ bitidx = int(splitline[1][5:])
+ bits.add((current_x, current_y, splitline[1].strip()))
+ return bits
+
+if not os.path.exists("./work_spram"):
+ os.mkdir("./work_spram")
+
+for loc in spram_locs:
+ x, y, z = loc
+ net_map = {}
+ for sig in spram_signals:
+ net_map[sig] = set()
+ net_map["SPRAM_EN"] = set() # actually a CBIT not a net
+
+ for n in fuzz_options:
+ with open("./work_spram/spram.v","w") as f:
+ print("""
+ module top(
+ input WREN,
+ input CHIPSELECT,
+ input CLOCK,
+ input STANDBY,
+ input SLEEP,
+ input POWEROFF,
+ """, file=f)
+ if n == "ADDRESS":
+ print("\t\t\tinput [13:0] ADDRESS,", file=f)
+ if n == "DATAIN":
+ print("\t\t\tinput [15:0] DATAIN,", file=f)
+ if n == "MASKWREN":
+ print("\t\t\tinput [3:0] MASKWREN,", file=f)
+ if n == "DATAOUT":
+ print("\t\t\toutput [15:0] DATAOUT);", file=f)
+ else:
+ print("\t\t\toutput [0:0] DATAOUT);", file=f) #some dataout is always required to prevent optimisation away
+
+ addr_net = "ADDRESS" if n == "ADDRESS" else ""
+ din_net = "DATAIN" if n == "DATAIN" else ""
+ mwren_net = "MASKWREN" if n == "MASKWREN" else ""
+
+ print("""
+ SB_SPRAM256KA spram_i
+ (
+ .ADDRESS(%s),
+ .DATAIN(%s),
+ .MASKWREN(%s),
+ .WREN(WREN),
+ .CHIPSELECT(CHIPSELECT),
+ .CLOCK(CLOCK),
+ .STANDBY(STANDBY),
+ .SLEEP(SLEEP),
+ .POWEROFF(POWEROFF),
+ .DATAOUT(DATAOUT)
+ );
+ """ % (addr_net, din_net, mwren_net), file=f)
+ print("endmodule",file=f)
+ pin2net = {}
+ with open("./work_spram/spram.pcf","w") as f:
+ temp_pins = list(pins)
+ for sig in spram_signals:
+ if sig.startswith("ADDRESS") and n != "ADDRESS":
+ continue
+ if sig.startswith("DATAIN") and n != "DATAIN":
+ continue
+ if sig.startswith("MASKWREN") and n != "MASKWREN":
+ continue
+ if sig.startswith("DATAOUT") and n != "DATAOUT" and sig != "DATAOUT[0]":
+ continue
+
+ if len(temp_pins) == 0:
+ sys.stderr.write("ERROR: no remaining pins to alloc")
+ sys.exit(1)
+
+ pin = temp_pins.pop()
+ pin2net[pin] = sig
+ print("set_io %s %s" % (sig, pin), file=f)
+ print("set_location spram_i %d %d %d" % loc, file=f)
+ retval = os.system("bash ../../icecube.sh -" + device + " ./work_spram/spram.v > ./work_spram/icecube.log 2>&1")
+ if retval != 0:
+ sys.stderr.write('ERROR: icecube returned non-zero error code\n')
+ sys.exit(1)
+ retval = os.system("../../../icebox/icebox_explain.py ./work_spram/spram.asc > ./work_spram/spram.exp")
+ if retval != 0:
+ sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n')
+ sys.exit(1)
+ retval = os.system("../../../icebox/icebox_vlog.py -l ./work_spram/spram.asc > ./work_spram/spram.vlog")
+ if retval != 0:
+ sys.stderr.write('ERROR: icebox_vlog returned non-zero error code\n')
+ sys.exit(1)
+ with open("./work_spram/spram.vlog", "r") as f:
+ parse_vlog(f, pin2net, net_map)
+ bits = []
+ with open("./work_spram/spram.exp", "r") as f:
+ bits = parse_exp(f)
+ net_map["SPRAM_EN"].update(bits)
+ spram_data[loc] = net_map
+
+with open(device + "_spram_data.txt", "w") as f:
+ for loc in spram_data:
+ print("\t(%d, %d, %d): {" % loc, file=f)
+ data = spram_data[loc]
+ for net in sorted(data):
+ cnets = []
+ for cnet in data[net]:
+ cnets.append("(%d, %d, \"%s\")" % cnet)
+ print("\t\t%s %s, " % (("\"" + net.replace("[","_").replace("]","") + "\":").ljust(24), " ".join(cnets)), file=f)
+ print("\t},", file=f)
diff --git a/icefuzz/tests/spram/up5k_spram_data.txt b/icefuzz/tests/spram/up5k_spram_data.txt
new file mode 100644
index 0000000..4526f93
--- /dev/null
+++ b/icefuzz/tests/spram/up5k_spram_data.txt
@@ -0,0 +1,236 @@
+ (0, 0, 1): {
+ "ADDRESS_0": (0, 2, "lutff_0/in_1"),
+ "ADDRESS_10": (0, 2, "lutff_2/in_0"),
+ "ADDRESS_11": (0, 2, "lutff_3/in_0"),
+ "ADDRESS_12": (0, 2, "lutff_4/in_0"),
+ "ADDRESS_13": (0, 2, "lutff_5/in_0"),
+ "ADDRESS_1": (0, 2, "lutff_1/in_1"),
+ "ADDRESS_2": (0, 2, "lutff_2/in_1"),
+ "ADDRESS_3": (0, 2, "lutff_3/in_1"),
+ "ADDRESS_4": (0, 2, "lutff_4/in_1"),
+ "ADDRESS_5": (0, 2, "lutff_5/in_1"),
+ "ADDRESS_6": (0, 2, "lutff_6/in_1"),
+ "ADDRESS_7": (0, 2, "lutff_7/in_1"),
+ "ADDRESS_8": (0, 2, "lutff_0/in_0"),
+ "ADDRESS_9": (0, 2, "lutff_1/in_0"),
+ "CHIPSELECT": (0, 3, "lutff_6/in_1"),
+ "CLOCK": (0, 1, "clk"),
+ "DATAIN_0": (0, 1, "lutff_0/in_3"),
+ "DATAIN_10": (0, 1, "lutff_2/in_1"),
+ "DATAIN_11": (0, 1, "lutff_3/in_1"),
+ "DATAIN_12": (0, 1, "lutff_4/in_1"),
+ "DATAIN_13": (0, 1, "lutff_5/in_1"),
+ "DATAIN_14": (0, 1, "lutff_6/in_1"),
+ "DATAIN_15": (0, 1, "lutff_7/in_1"),
+ "DATAIN_1": (0, 1, "lutff_1/in_3"),
+ "DATAIN_2": (0, 1, "lutff_2/in_3"),
+ "DATAIN_3": (0, 1, "lutff_3/in_3"),
+ "DATAIN_4": (0, 1, "lutff_4/in_3"),
+ "DATAIN_5": (0, 1, "lutff_5/in_3"),
+ "DATAIN_6": (0, 1, "lutff_6/in_3"),
+ "DATAIN_7": (0, 1, "lutff_7/in_3"),
+ "DATAIN_8": (0, 1, "lutff_0/in_1"),
+ "DATAIN_9": (0, 1, "lutff_1/in_1"),
+ "DATAOUT_0": (0, 1, "slf_op_0"),
+ "DATAOUT_10": (0, 2, "slf_op_2"),
+ "DATAOUT_11": (0, 2, "slf_op_3"),
+ "DATAOUT_12": (0, 2, "slf_op_4"),
+ "DATAOUT_13": (0, 2, "slf_op_5"),
+ "DATAOUT_14": (0, 2, "slf_op_6"),
+ "DATAOUT_15": (0, 2, "slf_op_7"),
+ "DATAOUT_1": (0, 1, "slf_op_1"),
+ "DATAOUT_2": (0, 1, "slf_op_2"),
+ "DATAOUT_3": (0, 1, "slf_op_3"),
+ "DATAOUT_4": (0, 1, "slf_op_4"),
+ "DATAOUT_5": (0, 1, "slf_op_5"),
+ "DATAOUT_6": (0, 1, "slf_op_6"),
+ "DATAOUT_7": (0, 1, "slf_op_7"),
+ "DATAOUT_8": (0, 2, "slf_op_0"),
+ "DATAOUT_9": (0, 2, "slf_op_1"),
+ "MASKWREN_0": (0, 3, "lutff_0/in_0"),
+ "MASKWREN_1": (0, 3, "lutff_1/in_0"),
+ "MASKWREN_2": (0, 3, "lutff_2/in_0"),
+ "MASKWREN_3": (0, 3, "lutff_3/in_0"),
+ "POWEROFF": (0, 4, "lutff_4/in_3"),
+ "SLEEP": (0, 4, "lutff_2/in_3"),
+ "SPRAM_EN": (0, 1, "CBIT_0"),
+ "STANDBY": (0, 4, "lutff_0/in_3"),
+ "WREN": (0, 3, "lutff_4/in_1"),
+ },
+ (0, 0, 2): {
+ "ADDRESS_0": (0, 2, "lutff_6/in_0"),
+ "ADDRESS_10": (0, 3, "lutff_0/in_1"),
+ "ADDRESS_11": (0, 3, "lutff_1/in_1"),
+ "ADDRESS_12": (0, 3, "lutff_2/in_1"),
+ "ADDRESS_13": (0, 3, "lutff_3/in_1"),
+ "ADDRESS_1": (0, 2, "lutff_7/in_0"),
+ "ADDRESS_2": (0, 3, "lutff_0/in_3"),
+ "ADDRESS_3": (0, 3, "lutff_1/in_3"),
+ "ADDRESS_4": (0, 3, "lutff_2/in_3"),
+ "ADDRESS_5": (0, 3, "lutff_3/in_3"),
+ "ADDRESS_6": (0, 3, "lutff_4/in_3"),
+ "ADDRESS_7": (0, 3, "lutff_5/in_3"),
+ "ADDRESS_8": (0, 3, "lutff_6/in_3"),
+ "ADDRESS_9": (0, 3, "lutff_7/in_3"),
+ "CHIPSELECT": (0, 3, "lutff_7/in_1"),
+ "CLOCK": (0, 2, "clk"),
+ "DATAIN_0": (0, 1, "lutff_0/in_0"),
+ "DATAIN_10": (0, 2, "lutff_2/in_3"),
+ "DATAIN_11": (0, 2, "lutff_3/in_3"),
+ "DATAIN_12": (0, 2, "lutff_4/in_3"),
+ "DATAIN_13": (0, 2, "lutff_5/in_3"),
+ "DATAIN_14": (0, 2, "lutff_6/in_3"),
+ "DATAIN_15": (0, 2, "lutff_7/in_3"),
+ "DATAIN_1": (0, 1, "lutff_1/in_0"),
+ "DATAIN_2": (0, 1, "lutff_2/in_0"),
+ "DATAIN_3": (0, 1, "lutff_3/in_0"),
+ "DATAIN_4": (0, 1, "lutff_4/in_0"),
+ "DATAIN_5": (0, 1, "lutff_5/in_0"),
+ "DATAIN_6": (0, 1, "lutff_6/in_0"),
+ "DATAIN_7": (0, 1, "lutff_7/in_0"),
+ "DATAIN_8": (0, 2, "lutff_0/in_3"),
+ "DATAIN_9": (0, 2, "lutff_1/in_3"),
+ "DATAOUT_0": (0, 3, "slf_op_0"),
+ "DATAOUT_10": (0, 4, "slf_op_2"),
+ "DATAOUT_11": (0, 4, "slf_op_3"),
+ "DATAOUT_12": (0, 4, "slf_op_4"),
+ "DATAOUT_13": (0, 4, "slf_op_5"),
+ "DATAOUT_14": (0, 4, "slf_op_6"),
+ "DATAOUT_15": (0, 4, "slf_op_7"),
+ "DATAOUT_1": (0, 3, "slf_op_1"),
+ "DATAOUT_2": (0, 3, "slf_op_2"),
+ "DATAOUT_3": (0, 3, "slf_op_3"),
+ "DATAOUT_4": (0, 3, "slf_op_4"),
+ "DATAOUT_5": (0, 3, "slf_op_5"),
+ "DATAOUT_6": (0, 3, "slf_op_6"),
+ "DATAOUT_7": (0, 3, "slf_op_7"),
+ "DATAOUT_8": (0, 4, "slf_op_0"),
+ "DATAOUT_9": (0, 4, "slf_op_1"),
+ "MASKWREN_0": (0, 3, "lutff_4/in_0"),
+ "MASKWREN_1": (0, 3, "lutff_5/in_0"),
+ "MASKWREN_2": (0, 3, "lutff_6/in_0"),
+ "MASKWREN_3": (0, 3, "lutff_7/in_0"),
+ "POWEROFF": (0, 4, "lutff_5/in_3"),
+ "SLEEP": (0, 4, "lutff_3/in_3"),
+ "SPRAM_EN": (0, 1, "CBIT_1"),
+ "STANDBY": (0, 4, "lutff_1/in_3"),
+ "WREN": (0, 3, "lutff_5/in_1"),
+ },
+ (25, 0, 3): {
+ "ADDRESS_0": (25, 2, "lutff_0/in_1"),
+ "ADDRESS_10": (25, 2, "lutff_2/in_0"),
+ "ADDRESS_11": (25, 2, "lutff_3/in_0"),
+ "ADDRESS_12": (25, 2, "lutff_4/in_0"),
+ "ADDRESS_13": (25, 2, "lutff_5/in_0"),
+ "ADDRESS_1": (25, 2, "lutff_1/in_1"),
+ "ADDRESS_2": (25, 2, "lutff_2/in_1"),
+ "ADDRESS_3": (25, 2, "lutff_3/in_1"),
+ "ADDRESS_4": (25, 2, "lutff_4/in_1"),
+ "ADDRESS_5": (25, 2, "lutff_5/in_1"),
+ "ADDRESS_6": (25, 2, "lutff_6/in_1"),
+ "ADDRESS_7": (25, 2, "lutff_7/in_1"),
+ "ADDRESS_8": (25, 2, "lutff_0/in_0"),
+ "ADDRESS_9": (25, 2, "lutff_1/in_0"),
+ "CHIPSELECT": (25, 3, "lutff_6/in_1"),
+ "CLOCK": (25, 1, "clk"),
+ "DATAIN_0": (25, 1, "lutff_0/in_3"),
+ "DATAIN_10": (25, 1, "lutff_2/in_1"),
+ "DATAIN_11": (25, 1, "lutff_3/in_1"),
+ "DATAIN_12": (25, 1, "lutff_4/in_1"),
+ "DATAIN_13": (25, 1, "lutff_5/in_1"),
+ "DATAIN_14": (25, 1, "lutff_6/in_1"),
+ "DATAIN_15": (25, 1, "lutff_7/in_1"),
+ "DATAIN_1": (25, 1, "lutff_1/in_3"),
+ "DATAIN_2": (25, 1, "lutff_2/in_3"),
+ "DATAIN_3": (25, 1, "lutff_3/in_3"),
+ "DATAIN_4": (25, 1, "lutff_4/in_3"),
+ "DATAIN_5": (25, 1, "lutff_5/in_3"),
+ "DATAIN_6": (25, 1, "lutff_6/in_3"),
+ "DATAIN_7": (25, 1, "lutff_7/in_3"),
+ "DATAIN_8": (25, 1, "lutff_0/in_1"),
+ "DATAIN_9": (25, 1, "lutff_1/in_1"),
+ "DATAOUT_0": (25, 1, "slf_op_0"),
+ "DATAOUT_10": (25, 2, "slf_op_2"),
+ "DATAOUT_11": (25, 2, "slf_op_3"),
+ "DATAOUT_12": (25, 2, "slf_op_4"),
+ "DATAOUT_13": (25, 2, "slf_op_5"),
+ "DATAOUT_14": (25, 2, "slf_op_6"),
+ "DATAOUT_15": (25, 2, "slf_op_7"),
+ "DATAOUT_1": (25, 1, "slf_op_1"),
+ "DATAOUT_2": (25, 1, "slf_op_2"),
+ "DATAOUT_3": (25, 1, "slf_op_3"),
+ "DATAOUT_4": (25, 1, "slf_op_4"),
+ "DATAOUT_5": (25, 1, "slf_op_5"),
+ "DATAOUT_6": (25, 1, "slf_op_6"),
+ "DATAOUT_7": (25, 1, "slf_op_7"),
+ "DATAOUT_8": (25, 2, "slf_op_0"),
+ "DATAOUT_9": (25, 2, "slf_op_1"),
+ "MASKWREN_0": (25, 3, "lutff_0/in_0"),
+ "MASKWREN_1": (25, 3, "lutff_1/in_0"),
+ "MASKWREN_2": (25, 3, "lutff_2/in_0"),
+ "MASKWREN_3": (25, 3, "lutff_3/in_0"),
+ "POWEROFF": (25, 4, "lutff_4/in_3"),
+ "SLEEP": (25, 4, "lutff_2/in_3"),
+ "SPRAM_EN": (25, 1, "CBIT_0"),
+ "STANDBY": (25, 4, "lutff_0/in_3"),
+ "WREN": (25, 3, "lutff_4/in_1"),
+ },
+ (25, 0, 4): {
+ "ADDRESS_0": (25, 2, "lutff_6/in_0"),
+ "ADDRESS_10": (25, 3, "lutff_0/in_1"),
+ "ADDRESS_11": (25, 3, "lutff_1/in_1"),
+ "ADDRESS_12": (25, 3, "lutff_2/in_1"),
+ "ADDRESS_13": (25, 3, "lutff_3/in_1"),
+ "ADDRESS_1": (25, 2, "lutff_7/in_0"),
+ "ADDRESS_2": (25, 3, "lutff_0/in_3"),
+ "ADDRESS_3": (25, 3, "lutff_1/in_3"),
+ "ADDRESS_4": (25, 3, "lutff_2/in_3"),
+ "ADDRESS_5": (25, 3, "lutff_3/in_3"),
+ "ADDRESS_6": (25, 3, "lutff_4/in_3"),
+ "ADDRESS_7": (25, 3, "lutff_5/in_3"),
+ "ADDRESS_8": (25, 3, "lutff_6/in_3"),
+ "ADDRESS_9": (25, 3, "lutff_7/in_3"),
+ "CHIPSELECT": (25, 3, "lutff_7/in_1"),
+ "CLOCK": (25, 2, "clk"),
+ "DATAIN_0": (25, 1, "lutff_0/in_0"),
+ "DATAIN_10": (25, 2, "lutff_2/in_3"),
+ "DATAIN_11": (25, 2, "lutff_3/in_3"),
+ "DATAIN_12": (25, 2, "lutff_4/in_3"),
+ "DATAIN_13": (25, 2, "lutff_5/in_3"),
+ "DATAIN_14": (25, 2, "lutff_6/in_3"),
+ "DATAIN_15": (25, 2, "lutff_7/in_3"),
+ "DATAIN_1": (25, 1, "lutff_1/in_0"),
+ "DATAIN_2": (25, 1, "lutff_2/in_0"),
+ "DATAIN_3": (25, 1, "lutff_3/in_0"),
+ "DATAIN_4": (25, 1, "lutff_4/in_0"),
+ "DATAIN_5": (25, 1, "lutff_5/in_0"),
+ "DATAIN_6": (25, 1, "lutff_6/in_0"),
+ "DATAIN_7": (25, 1, "lutff_7/in_0"),
+ "DATAIN_8": (25, 2, "lutff_0/in_3"),
+ "DATAIN_9": (25, 2, "lutff_1/in_3"),
+ "DATAOUT_0": (25, 3, "slf_op_0"),
+ "DATAOUT_10": (25, 4, "slf_op_2"),
+ "DATAOUT_11": (25, 4, "slf_op_3"),
+ "DATAOUT_12": (25, 4, "slf_op_4"),
+ "DATAOUT_13": (25, 4, "slf_op_5"),
+ "DATAOUT_14": (25, 4, "slf_op_6"),
+ "DATAOUT_15": (25, 4, "slf_op_7"),
+ "DATAOUT_1": (25, 3, "slf_op_1"),
+ "DATAOUT_2": (25, 3, "slf_op_2"),
+ "DATAOUT_3": (25, 3, "slf_op_3"),
+ "DATAOUT_4": (25, 3, "slf_op_4"),
+ "DATAOUT_5": (25, 3, "slf_op_5"),
+ "DATAOUT_6": (25, 3, "slf_op_6"),
+ "DATAOUT_7": (25, 3, "slf_op_7"),
+ "DATAOUT_8": (25, 4, "slf_op_0"),
+ "DATAOUT_9": (25, 4, "slf_op_1"),
+ "MASKWREN_0": (25, 3, "lutff_4/in_0"),
+ "MASKWREN_1": (25, 3, "lutff_5/in_0"),
+ "MASKWREN_2": (25, 3, "lutff_6/in_0"),
+ "MASKWREN_3": (25, 3, "lutff_7/in_0"),
+ "POWEROFF": (25, 4, "lutff_5/in_3"),
+ "SLEEP": (25, 4, "lutff_3/in_3"),
+ "SPRAM_EN": (25, 1, "CBIT_1"),
+ "STANDBY": (25, 4, "lutff_1/in_3"),
+ "WREN": (25, 3, "lutff_5/in_1"),
+ },