From 4a930377f0a635bcaa28922e8fa6bd0aa8eee6d9 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Oct 2017 14:46:24 +0100 Subject: Quick fix of pin 23 issue (pending further discussion) --- icefuzz/fuzzconfig.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'icefuzz') diff --git a/icefuzz/fuzzconfig.py b/icefuzz/fuzzconfig.py index 2e925ef..a5c1e2c 100644 --- a/icefuzz/fuzzconfig.py +++ b/icefuzz/fuzzconfig.py @@ -63,8 +63,10 @@ elif device_class == "5k": #TODO(tannewt): Add 39, 40, 41 to this list. It causes placement failures for some reason. # Also add 14 15 16 17 which are constrained to SPI. + #TODO(daveshah1): Add back I3C IO 23 which cause placement failures when assigned to + #an SB_IO clk_in pins = """2 3 4 6 9 10 11 12 - 13 18 19 20 21 23 + 13 18 19 20 21 25 26 27 28 31 32 34 35 36 37 38 42 43 44 45 46 47 48 """.split() -- cgit v1.2.3 From 42047c61145b5d9e06aca30d706f132f4268dc74 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Oct 2017 15:18:39 +0100 Subject: Fix case where make_prim allocates all global buffer pins This is a low probability bug more likely to show up in low pin count devices with few GBINs. In rare cases make_prim would constrain all of the global buffer capable pins but not the clock input. icecube would then fail to place the clock input. This is fixed by always constraining the clock if all GBIN pins are used. --- icefuzz/make_prim.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'icefuzz') diff --git a/icefuzz/make_prim.py b/icefuzz/make_prim.py index b96a100..90186da 100644 --- a/icefuzz/make_prim.py +++ b/icefuzz/make_prim.py @@ -31,20 +31,40 @@ for idx in range(num): print("endmodule", file=f) with open(working_dir + "/prim_%02d.pcf" % idx, "w") as f: p = np.random.permutation(pins) + used_pins = [] if np.random.choice([True, False]): for i in range(w): print("set_io a[%d] %s" % (i, p[i]), file=f) + used_pins.append(p[i]) if np.random.choice([True, False]): for i in range(w): print("set_io b[%d] %s" % (i, p[w+i]), file=f) + used_pins.append(p[w+i]) if np.random.choice([True, False]): for i in range(w): print("set_io y[%d] %s" % (i, p[2*w+i]), file=f) + used_pins.append(p[2*w+i]) if np.random.choice([True, False]): print("set_io x %s" % p[3*w], file=f) + used_pins.append(p[3*w]) + if np.random.choice([True, False]): print("set_io y %s" % p[3*w+1], file=f) - if np.random.choice([True, False]): + used_pins.append(p[3*w+1]) + + # There is a low but non-zero probability, particularly on devices with + # fewer pins and GBINs such as the UltraPlus, that a permutation will be + # picked where all of the GBINs are already constrained at this point, + # hence icecube fails to assign clk successfully. This is fixed by + # forcing clock assignment if no GBINs are free. + + global_free = False + for glbi in gpins: + if not glbi in used_pins: + global_free = True + break + + if np.random.choice([True, False]) or not global_free: print("set_io clk %s" % p[3*w+2], file=f) -- cgit v1.2.3 From 172d561b012a8d09cbd0d37570f75ff920867c48 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Oct 2017 16:27:06 +0100 Subject: Fix make_ram40 for UltraPlus Sometimes make_ram40 was assigning too many IO pins, causing a placment failure, and also sometimes connecting a global clock net to WCLKE or RCLKE which was also causing a placment failure. --- icefuzz/make_ram40.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'icefuzz') diff --git a/icefuzz/make_ram40.py b/icefuzz/make_ram40.py index f4acb4e..75ac604 100644 --- a/icefuzz/make_ram40.py +++ b/icefuzz/make_ram40.py @@ -14,7 +14,11 @@ os.mkdir(working_dir) for idx in range(num): with open(working_dir + "/ram40_%02d.v" % idx, "w") as f: glbs = ["glb[%d]" % i for i in range(np.random.randint(8)+1)] - glbs_choice = ["wa", "ra", "msk", "wd", "we", "wce", "wc", "re", "rce", "rc"] + # Connecting GLB to CE pins seemingly disallowed + if device_class == "5k": + glbs_choice = ["wa", "ra", "msk", "wd", "we", "wc", "re", "rc"] + else: + glbs_choice = ["wa", "ra", "msk", "wd", "we", "wce", "wc", "re", "rce", "rc"] print(""" module top ( input [%d:0] glb_pins, @@ -26,7 +30,7 @@ for idx in range(num): .USER_SIGNAL_TO_GLOBAL_BUFFER(glb_pins), .GLOBAL_BUFFER_OUTPUT(glb) ); - """ % (len(glbs)-1, len(pins) - 16 - 1, len(glbs)-1, len(glbs)-1), file=f) + """ % (len(glbs)-1, len(pins) - len(glbs) - 16 - 1, len(glbs)-1, len(glbs)-1), file=f) bits = ["in_pins[%d]" % i for i in range(60)] bits = list(np.random.permutation(bits)) for i in range(num_ramb40): @@ -102,7 +106,7 @@ for idx in range(num): print("endmodule", file=f) with open(working_dir + "/ram40_%02d.pcf" % idx, "w") as f: p = list(np.random.permutation(pins)) - for i in range(len(pins) - 16): + for i in range(len(pins) - len(glbs) - 16): print("set_io in_pins[%d] %s" % (i, p.pop()), file=f) for i in range(16): print("set_io out_pins[%d] %s" % (i, p.pop()), file=f) -- cgit v1.2.3 From aa653a2a510a5d31ed099e0974b465efcbfcc010 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 21 Oct 2017 14:59:13 +0100 Subject: Add DSP and IPConnect tile support to icepack and glbcheck --- icefuzz/glbcheck.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'icefuzz') diff --git a/icefuzz/glbcheck.py b/icefuzz/glbcheck.py index 742c335..49008ca 100644 --- a/icefuzz/glbcheck.py +++ b/icefuzz/glbcheck.py @@ -30,13 +30,13 @@ with open(argv[1]) as f: with open(argv[2]) as f: current_tile = None for line in f: - if line.startswith(("Tile", "IO_Tile", "RAM_Tile", "LogicTile")): - f = line.replace("IO_", "").replace("RAM_", "").split("_") + if line.startswith(("Tile", "IO_Tile", "RAM_Tile", "LogicTile", "DSP_Tile", "IpCon_Tile")): + f = line.replace("IO_", "").replace("RAM_", "").replace("DSP_","").replace("IpCon_","").split("_") assert len(f) == 3 current_tile = "%02d.%02d" % (int(f[1]), int(f[2])) continue - if line.find("GlobalNetwork") >= 0 or line.startswith(("IpCon", "DSP")): + if line.find("GlobalNetwork") >= 0: current_tile = None continue @@ -65,4 +65,3 @@ for bit in sorted(only_in_glb): print(bit) exit(1) - -- cgit v1.2.3 From bf21b644984656fdea6ec2609b22a74f3296115b Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 23 Oct 2017 11:30:23 +0100 Subject: Fix IeRen database for up5k --- icefuzz/tests/.gitignore | 2 ++ icefuzz/tests/ioctrl_5k.py | 21 +++++++++++++++++++++ icefuzz/tests/ioctrl_5k.sh | 28 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 icefuzz/tests/.gitignore create mode 100644 icefuzz/tests/ioctrl_5k.py create mode 100755 icefuzz/tests/ioctrl_5k.sh (limited to 'icefuzz') diff --git a/icefuzz/tests/.gitignore b/icefuzz/tests/.gitignore new file mode 100644 index 0000000..cc0ba46 --- /dev/null +++ b/icefuzz/tests/.gitignore @@ -0,0 +1,2 @@ +ioctrl.work +intosc.work diff --git a/icefuzz/tests/ioctrl_5k.py b/icefuzz/tests/ioctrl_5k.py new file mode 100644 index 0000000..67c0c6d --- /dev/null +++ b/icefuzz/tests/ioctrl_5k.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_5k.sh b/icefuzz/tests/ioctrl_5k.sh new file mode 100755 index 0000000..339cac7 --- /dev/null +++ b/icefuzz/tests/ioctrl_5k.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -ex + +mkdir -p ioctrl.work +cd ioctrl.work + +pins="2 3 4 6 9 10 11 12 + 13 14 15 16 17 18 19 20 21 23 + 25 26 27 28 31 32 34 35 36 + 37 38 42 43 44 45 46 47 48 + " +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 -up5k ${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--" -- cgit v1.2.3 From 81e0d3c361e1b639064e07ff7efd1b8232090e0c Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 23 Oct 2017 17:48:22 +0100 Subject: Add some verilog tests for analysing up5k features --- icefuzz/tests/intosc.pcf | 3 ++ icefuzz/tests/intosc.v | 14 ++++++++++ icefuzz/tests/sb_io_od.pcf | 12 ++++++++ icefuzz/tests/sb_io_od.v | 62 +++++++++++++++++++++++++++++++++++++++++ icefuzz/tests/sb_mac16.v | 65 +++++++++++++++++++++++++++++++++++++++++++ icefuzz/tests/sb_rgba_drv.pcf | 3 ++ icefuzz/tests/sb_rgba_drv.v | 32 +++++++++++++++++++++ icefuzz/tests/sb_spram256ka.v | 25 +++++++++++++++++ 8 files changed, 216 insertions(+) create mode 100644 icefuzz/tests/intosc.pcf create mode 100644 icefuzz/tests/intosc.v create mode 100644 icefuzz/tests/sb_io_od.pcf create mode 100644 icefuzz/tests/sb_io_od.v create mode 100644 icefuzz/tests/sb_mac16.v create mode 100644 icefuzz/tests/sb_rgba_drv.pcf create mode 100644 icefuzz/tests/sb_rgba_drv.v create mode 100644 icefuzz/tests/sb_spram256ka.v (limited to 'icefuzz') diff --git a/icefuzz/tests/intosc.pcf b/icefuzz/tests/intosc.pcf new file mode 100644 index 0000000..9e580de --- /dev/null +++ b/icefuzz/tests/intosc.pcf @@ -0,0 +1,3 @@ +set_io clkhfpu 2 +set_io clkhfen 3 +set_io clkhf 4 diff --git a/icefuzz/tests/intosc.v b/icefuzz/tests/intosc.v new file mode 100644 index 0000000..227cb55 --- /dev/null +++ b/icefuzz/tests/intosc.v @@ -0,0 +1,14 @@ +module top ( + input clkhfpu, + input clkhfen, + output clkhf +); +SB_HFOSC #( + + .CLKHF_DIV("0b10") +) hfosc ( + .CLKHFPU(clkhfpu), + .CLKHFEN(clkhfen), + .CLKHF(clkhf) +); +endmodule diff --git a/icefuzz/tests/sb_io_od.pcf b/icefuzz/tests/sb_io_od.pcf new file mode 100644 index 0000000..b613227 --- /dev/null +++ b/icefuzz/tests/sb_io_od.pcf @@ -0,0 +1,12 @@ +# set_io pin 1 +set_io pin 39 + +# set_io pin +# set_io latch_in +# set_io clk_in +# set_io clk_out +# set_io oen +# set_io dout_0 +# set_io dout_1 +# set_io din_0 +# set_io din_1 diff --git a/icefuzz/tests/sb_io_od.v b/icefuzz/tests/sb_io_od.v new file mode 100644 index 0000000..7894741 --- /dev/null +++ b/icefuzz/tests/sb_io_od.v @@ -0,0 +1,62 @@ +//`define CONN_INTERNAL_BITS + +`define PINTYPE 6'b010001 +// `define IOSTANDARD "SB_LVCMOS" +`define IOSTANDARD "SB_LVCMOS" + +// The following IO standards are just aliases for SB_LVCMOS +// `define IOSTANDARD "SB_LVCMOS25_16" +// `define IOSTANDARD "SB_LVCMOS25_12" +// `define IOSTANDARD "SB_LVCMOS25_8" +// `define IOSTANDARD "SB_LVCMOS25_4" +// `define IOSTANDARD "SB_LVCMOS18_10" +// `define IOSTANDARD "SB_LVCMOS18_8" +// `define IOSTANDARD "SB_LVCMOS18_4" +// `define IOSTANDARD "SB_LVCMOS18_2" +// `define IOSTANDARD "SB_LVCMOS15_4" +// `define IOSTANDARD "SB_LVCMOS15_2" +// `define IOSTANDARD "SB_MDDR10" +// `define IOSTANDARD "SB_MDDR8" +// `define IOSTANDARD "SB_MDDR4" +// `define IOSTANDARD "SB_MDDR2" + +`ifdef CONN_INTERNAL_BITS +module top ( + inout pin, + input latch_in, + input clk_in, + input clk_out, + input oen, + input dout_0, + input dout_1, + output din_0, + output din_1 +); +`else +module top(pin); + inout pin; + wire latch_in = 0; + wire clk_in = 0; + wire clk_out = 0; + wire oen = 0; + wire dout_0 = 0; + wire dout_1 = 0; + wire din_0; + wire din_1; +`endif + SB_IO_OD #( + .PIN_TYPE(`PINTYPE), + .NEG_TRIGGER(1'b0) + ) IO_PIN_I ( + .PACKAGEPIN(pin), + .LATCHINPUTVALUE(latch_in), + .CLOCKENABLE(clk_en), + .INPUTCLK(clk_in), + .OUTPUTCLK(clk_out), + .OUTPUTENABLE(oen), + .DOUT0(dout_0), + .DOUT1(dout_1), + .DIN0(din_0), + .DIN1(din_1) + ); +endmodule diff --git a/icefuzz/tests/sb_mac16.v b/icefuzz/tests/sb_mac16.v new file mode 100644 index 0000000..c2fd850 --- /dev/null +++ b/icefuzz/tests/sb_mac16.v @@ -0,0 +1,65 @@ +module top( + input clk, + input rst, + input [7:0] a, + input [7:0] b, + output [15:0] y); + wire co; + wire [31:0] out; + SB_MAC16 i_sbmac16 + ( + .A(a), + .B(b), + .C(8'd0), + .D(8'd0), + .O(out), + .CLK(clk), + .IRSTTOP(rst), + .IRSTBOT(rst), + .ORSTTOP(rst), + .ORSTBOT(rst), + .AHOLD(1'b0), + .BHOLD(1'b0), + .CHOLD(1'b0), + .DHOLD(1'b0), + .OHOLDTOP(1'b0), + .OHOLDBOT(1'b0), + .OLOADTOP(1'b0), + .OLOADBOT(1'b0), + .ADDSUBTOP(1'b0), + .ADDSUBBOT(1'b0), + .CO(co), + .CI(1'b0), + .ACCUMCI(), + .ACCUMCO(), + .SIGNEXTIN(), + .SIGNEXTOUT() + ); + +//Config: mult_8x8_pipeline_unsigned + +defparam i_sbmac16. B_SIGNED = 1'b0; +defparam i_sbmac16. A_SIGNED = 1'b0; +defparam i_sbmac16. MODE_8x8 = 1'b1; + +defparam i_sbmac16. BOTADDSUB_CARRYSELECT = 2'b00; +defparam i_sbmac16. BOTADDSUB_UPPERINPUT = 1'b0; +defparam i_sbmac16. BOTADDSUB_LOWERINPUT = 2'b00; +defparam i_sbmac16. BOTOUTPUT_SELECT = 2'b10; + +defparam i_sbmac16. TOPADDSUB_CARRYSELECT = 2'b00; +defparam i_sbmac16. TOPADDSUB_UPPERINPUT = 1'b0; +defparam i_sbmac16. TOPADDSUB_LOWERINPUT = 2'b00; +defparam i_sbmac16. TOPOUTPUT_SELECT = 2'b10; + +defparam i_sbmac16. PIPELINE_16x16_MULT_REG2 = 1'b0; +defparam i_sbmac16. PIPELINE_16x16_MULT_REG1 = 1'b1; +defparam i_sbmac16. BOT_8x8_MULT_REG = 1'b1; +defparam i_sbmac16. TOP_8x8_MULT_REG = 1'b1; +defparam i_sbmac16. D_REG = 1'b0; +defparam i_sbmac16. B_REG = 1'b1; +defparam i_sbmac16. A_REG = 1'b1; +defparam i_sbmac16. C_REG = 1'b0; + +assign y = out[15:0]; +endmodule \ No newline at end of file diff --git a/icefuzz/tests/sb_rgba_drv.pcf b/icefuzz/tests/sb_rgba_drv.pcf new file mode 100644 index 0000000..94515d2 --- /dev/null +++ b/icefuzz/tests/sb_rgba_drv.pcf @@ -0,0 +1,3 @@ +set_io r_led 39 +set_io g_led 40 +set_io b_led 41 diff --git a/icefuzz/tests/sb_rgba_drv.v b/icefuzz/tests/sb_rgba_drv.v new file mode 100644 index 0000000..e5a0c36 --- /dev/null +++ b/icefuzz/tests/sb_rgba_drv.v @@ -0,0 +1,32 @@ +module top( + input r_in, + input g_in, + input b_in, + output r_led, + output g_led, + output b_led); + + wire curren; + wire rgbleden; + + SB_RGBA_DRV RGBA_DRIVER ( + .CURREN(curren), + .RGBLEDEN(rgbleden), + .RGB0PWM(r_in), + .RGB1PWM(r_in), + .RGB2PWM(r_in), + .RGB0(r_led), + .RGB1(g_led), + .RGB2(b_led) + ); + +defparam RGBA_DRIVER.CURRENT_MODE = "0b0"; +defparam RGBA_DRIVER.RGB0_CURRENT = "0b000011"; +defparam RGBA_DRIVER.RGB1_CURRENT = "0b001111"; +defparam RGBA_DRIVER.RGB2_CURRENT = "0b111111"; + +assign curren = 1'b1; +assign rgbleden = 1'b1; + + +endmodule \ No newline at end of file diff --git a/icefuzz/tests/sb_spram256ka.v b/icefuzz/tests/sb_spram256ka.v new file mode 100644 index 0000000..e1e1403 --- /dev/null +++ b/icefuzz/tests/sb_spram256ka.v @@ -0,0 +1,25 @@ +module top( + input clk, + input [13:0] addr, + input [7:0] din, + input wren, + input cs, + output [7:0] dout +); + +SB_SPRAM256KA spram_i + ( + .ADDRESS(addr), + .DATAIN(din), + .MASKWREN(4'b1111), + .WREN(wren), + .CHIPSELECT(cs), + .CLOCK(clk), + .STANDBY(1'b0), + .SLEEP(1'b0), + .POWEROFF(1'b0), + .DATAOUT(dout) + ); + + +endmodule \ No newline at end of file -- cgit v1.2.3 From 2a7c32e49aaaa0e763546c604b0082aa12714d4a Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 25 Oct 2017 10:50:36 +0100 Subject: Add ColBufCtrl bits to database for 5k parts --- icefuzz/database.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'icefuzz') diff --git a/icefuzz/database.py b/icefuzz/database.py index 8cb81d8..8a068ee 100644 --- a/icefuzz/database.py +++ b/icefuzz/database.py @@ -60,6 +60,10 @@ def read_database(filename, tile_type): elif m.group(1) in ["1", "2"]: line[1] = re.sub(r"glb_netwk_", "1k_glb_netwk_", line[1]) raw_db.append((bit, (line[0], line[1]))) + #Slightly hacky approach for the 5k devices, which are the same as the 8k + if m.group(1) == "7": + line[1] = re.sub(r"8k_glb_netwk_", "5k_glb_netwk_", line[1]) + raw_db.append((bit, (line[0], line[1]))) elif line[0] == "Cascade": match = re.match("LH_LC0(\d)_inmux02_5", line[1]) if match: -- cgit v1.2.3 From e9e9d0e9cb858e5643aff9684de7e8cded68405f Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 29 Oct 2017 16:14:15 +0000 Subject: Share glb_netwk data between 5k and 8k parts --- icefuzz/database.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'icefuzz') diff --git a/icefuzz/database.py b/icefuzz/database.py index 8a068ee..8cb81d8 100644 --- a/icefuzz/database.py +++ b/icefuzz/database.py @@ -60,10 +60,6 @@ def read_database(filename, tile_type): elif m.group(1) in ["1", "2"]: line[1] = re.sub(r"glb_netwk_", "1k_glb_netwk_", line[1]) raw_db.append((bit, (line[0], line[1]))) - #Slightly hacky approach for the 5k devices, which are the same as the 8k - if m.group(1) == "7": - line[1] = re.sub(r"8k_glb_netwk_", "5k_glb_netwk_", line[1]) - raw_db.append((bit, (line[0], line[1]))) elif line[0] == "Cascade": match = re.match("LH_LC0(\d)_inmux02_5", line[1]) if match: -- cgit v1.2.3 From 3059607dd799e18d5ce22c536021fc690d3ac13a Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 30 Oct 2017 11:32:17 +0000 Subject: PLL configuration fuzzing script --- icefuzz/tests/pllauto/.gitignore | 1 + icefuzz/tests/pllauto/pll_data_up5k.txt | 39 +++++ icefuzz/tests/pllauto/pllauto.py | 276 ++++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 icefuzz/tests/pllauto/.gitignore create mode 100644 icefuzz/tests/pllauto/pll_data_up5k.txt create mode 100755 icefuzz/tests/pllauto/pllauto.py (limited to 'icefuzz') diff --git a/icefuzz/tests/pllauto/.gitignore b/icefuzz/tests/pllauto/.gitignore new file mode 100644 index 0000000..7fafebe --- /dev/null +++ b/icefuzz/tests/pllauto/.gitignore @@ -0,0 +1 @@ +work_pllauto/ \ No newline at end of file diff --git a/icefuzz/tests/pllauto/pll_data_up5k.txt b/icefuzz/tests/pllauto/pll_data_up5k.txt new file mode 100644 index 0000000..2010989 --- /dev/null +++ b/icefuzz/tests/pllauto/pll_data_up5k.txt @@ -0,0 +1,39 @@ +"PLLTYPE_1": (14, 31, "PLLCONFIG_1"), +"PLLTYPE_2": (14, 31, "PLLCONFIG_3"), +"PLLTYPE_0": (12, 31, "PLLCONFIG_5"), +"FEEDBACK_PATH_0": (14, 31, "PLLCONFIG_5"), +"FEEDBACK_PATH_1": (11, 31, "PLLCONFIG_9"), +"FEEDBACK_PATH_2": (12, 31, "PLLCONFIG_1"), +"PLLOUT_SELECT_A_0": (12, 31, "PLLCONFIG_6"), +"PLLOUT_SELECT_A_1": (12, 31, "PLLCONFIG_7"), +"PLLOUT_SELECT_B_0": (12, 31, "PLLCONFIG_2"), +"PLLOUT_SELECT_B_1": (12, 31, "PLLCONFIG_3"), +"SHIFTREG_DIV_MODE": (12, 31, "PLLCONFIG_4"), +"FDA_FEEDBACK_0": (12, 31, "PLLCONFIG_9"), +"FDA_FEEDBACK_1": (13, 31, "PLLCONFIG_1"), +"FDA_FEEDBACK_2": (13, 31, "PLLCONFIG_2"), +"FDA_FEEDBACK_3": (13, 31, "PLLCONFIG_3"), +"FDA_RELATIVE_0": (13, 31, "PLLCONFIG_5"), +"FDA_RELATIVE_1": (13, 31, "PLLCONFIG_6"), +"FDA_RELATIVE_2": (13, 31, "PLLCONFIG_7"), +"FDA_RELATIVE_3": (13, 31, "PLLCONFIG_8"), +"DIVR_0": (10, 31, "PLLCONFIG_1"), +"DIVR_1": (10, 31, "PLLCONFIG_2"), +"DIVR_2": (10, 31, "PLLCONFIG_3"), +"DIVR_3": (10, 31, "PLLCONFIG_4"), +"DIVF_0": (10, 31, "PLLCONFIG_5"), +"DIVF_1": (10, 31, "PLLCONFIG_6"), +"DIVF_2": (10, 31, "PLLCONFIG_7"), +"DIVF_3": (10, 31, "PLLCONFIG_8"), +"DIVF_4": (10, 31, "PLLCONFIG_9"), +"DIVF_5": (11, 31, "PLLCONFIG_1"), +"DIVF_6": (11, 31, "PLLCONFIG_2"), +"DIVQ_0": (11, 31, "PLLCONFIG_3"), +"DIVQ_1": (11, 31, "PLLCONFIG_4"), +"DIVQ_2": (11, 31, "PLLCONFIG_5"), +"FILTER_RANGE_0": (11, 31, "PLLCONFIG_6"), +"FILTER_RANGE_1": (11, 31, "PLLCONFIG_7"), +"FILTER_RANGE_2": (11, 31, "PLLCONFIG_8"), +"TEST_MODE": (12, 31, "PLLCONFIG_8"), +"DELAY_ADJMODE_FB": (13, 31, "PLLCONFIG_4"), +"DELAY_ADJMODE_REL": (13, 31, "PLLCONFIG_9"), diff --git a/icefuzz/tests/pllauto/pllauto.py b/icefuzz/tests/pllauto/pllauto.py new file mode 100755 index 0000000..647be29 --- /dev/null +++ b/icefuzz/tests/pllauto/pllauto.py @@ -0,0 +1,276 @@ +#!/usr/bin/env python3 + +import os, sys +# PLL automatic fuzzing script (WIP) + +device = "up5k" + +# PLL 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 +# e.g. PLL_TYPE must be fuzzed first as these will need to be set later on by virtue of enabling the PLL + +fuzz_bits = [ + "PLLTYPE_1", + "PLLTYPE_2", + "PLLTYPE_0", #NB: as per the rule above this comes later is it can only be set by also setting 1 or 2 + + "FEEDBACK_PATH_0", + "FEEDBACK_PATH_1", + "FEEDBACK_PATH_2", + + "PLLOUT_SELECT_A_0", + "PLLOUT_SELECT_A_1", + + "PLLOUT_SELECT_B_0", + "PLLOUT_SELECT_B_1", + + "SHIFTREG_DIV_MODE", + + "FDA_FEEDBACK_0", + "FDA_FEEDBACK_1", + "FDA_FEEDBACK_2", + "FDA_FEEDBACK_3", + + "FDA_RELATIVE_0", + "FDA_RELATIVE_1", + "FDA_RELATIVE_2", + "FDA_RELATIVE_3", + + "DIVR_0", + "DIVR_1", + "DIVR_2", + "DIVR_3", + + "DIVF_0", + "DIVF_1", + "DIVF_2", + "DIVF_3", + "DIVF_4", + "DIVF_5", + "DIVF_6", + + #DIVQ_0 is missing, see comments later on + "DIVQ_1", + "DIVQ_2", + + "FILTER_RANGE_0", + "FILTER_RANGE_1", + "FILTER_RANGE_2", + + "TEST_MODE", + + "DELAY_ADJMODE_FB", #these come at the end in case they set FDA_RELATIVE?? + "DELAY_ADJMODE_REL" +] + +# Boilerplate code based on the icefuzz script +code_prefix = """ +module top(packagepin, a, b, w, x, y, z, extfeedback, bypass, resetb, lock, latchinputvalue, sdi, sdo, sclk, dynamicdelay_0, dynamicdelay_1, dynamicdelay_2, dynamicdelay_3, dynamicdelay_4, dynamicdelay_5, dynamicdelay_6, dynamicdelay_7); +input packagepin; +input a; +input b; +output w; +output x; +output reg y; +output reg z; +input extfeedback; +input bypass; +input resetb; +output lock; +input latchinputvalue; +input sdi; +output sdo; +input sclk; +wire plloutcorea; +wire plloutcoreb; +wire plloutglobala; +wire plloutglobalb; +assign w = plloutcorea ^ a; +assign x = plloutcoreb ^ b; +always @(posedge plloutglobala) y <= a; +always @(posedge plloutglobalb) z <= b; +input dynamicdelay_0; +input dynamicdelay_1; +input dynamicdelay_2; +input dynamicdelay_3; +input dynamicdelay_4; +input dynamicdelay_5; +input dynamicdelay_6; +input dynamicdelay_7; +""" + +def get_param_value(param_name, param_size, fuzz_bit): + param = str(param_size) + "'b"; + for i in range(param_size - 1, -1, -1): + if fuzz_bit == param_name + "_" + str(i): + param += '1' + else: + param += '0' + return param +def inst_pll(fuzz_bit): + pll_type = "SB_PLL40_2F_PAD" #default to this as it's most flexible + + if fuzz_bit == "PLLTYPE_0": + pll_type = "SB_PLL40_CORE" + elif fuzz_bit == "PLLTYPE_1": + pll_type = "SB_PLL40_PAD" + elif fuzz_bit == "PLLTYPE_2": + pll_type = "SB_PLL40_2_PAD" + + v = pll_type + " pll_inst (\n" + if pll_type == "SB_PLL40_CORE": + v += "\t.REFERENCECLK(referenceclk), \n" + else: + v += "\t.PACKAGEPIN(packagepin), \n" + v += "\t.RESETB(resetb),\n" + v += "\t.BYPASS(bypass),\n" + v += "\t.EXTFEEDBACK(extfeedback),\n" + v += "\t.LOCK(lock),\n" + v += "\t.LATCHINPUTVALUE(latchinputvalue),\n" + v += "\t.SDI(sdi),\n" + v += "\t.SDO(sdo),\n" + v += "\t.SCLK(sclk),\n" + if pll_type == "SB_PLL40_2F_PAD" or pll_type == "SB_PLL40_2_PAD": + v += "\t.PLLOUTCOREA(plloutcorea),\n" + v += "\t.PLLOUTGLOBALA(plloutglobala),\n" + v += "\t.PLLOUTCOREB(plloutcoreb),\n" + v += "\t.PLLOUTGLOBALB(plloutglobalb),\n" + else: + v += "\t.PLLOUTCORE(plloutcorea),\n" + v += "\t.PLLOUTGLOBAL(plloutglobala),\n" + v += "\t.DYNAMICDELAY({dynamicdelay_7, dynamicdelay_6, dynamicdelay_5, dynamicdelay_4, dynamicdelay_3, dynamicdelay_2, dynamicdelay_1, dynamicdelay_0})\n" + v += ");\n" + + v += "defparam pll_inst.DIVR = " + get_param_value("DIVR", 4, fuzz_bit) + ";\n" + v += "defparam pll_inst.DIVF = " + get_param_value("DIVF", 7, fuzz_bit) + ";\n" + v += "defparam pll_inst.DIVQ = " + get_param_value("DIVQ", 3, fuzz_bit) + ";\n" + v += "defparam pll_inst.FILTER_RANGE = " + get_param_value("FILTER_RANGE", 3, fuzz_bit) + ";\n" + + if fuzz_bit == "FEEDBACK_PATH_0": + v += "defparam pll_inst.FEEDBACK_PATH = \"SIMPLE\";\n" + elif fuzz_bit == "FEEDBACK_PATH_1": + v += "defparam pll_inst.FEEDBACK_PATH = \"PHASE_AND_DELAY\";\n" + elif fuzz_bit == "FEEDBACK_PATH_2": + v += "defparam pll_inst.FEEDBACK_PATH = \"EXTERNAL\";\n" + else: + v += "defparam pll_inst.FEEDBACK_PATH = \"DELAY\";\n" + + v += "defparam pll_inst.DELAY_ADJUSTMENT_MODE_FEEDBACK = \"" + ("DYNAMIC" if (fuzz_bit == "DELAY_ADJMODE_FB") else "FIXED") + "\";\n" + v += "defparam pll_inst.FDA_FEEDBACK = " + get_param_value("FDA_FEEDBACK", 4, fuzz_bit) + ";\n" + v += "defparam pll_inst.DELAY_ADJUSTMENT_MODE_RELATIVE = \"" + ("DYNAMIC" if (fuzz_bit == "DELAY_ADJMODE_REL") else "FIXED") + "\";\n" + v += "defparam pll_inst.FDA_RELATIVE = " + get_param_value("FDA_RELATIVE", 4, fuzz_bit) + ";\n" + v += "defparam pll_inst.SHIFTREG_DIV_MODE = " + ("1'b1" if (fuzz_bit == "SHIFTREG_DIV_MODE") else "1'b0") + ";\n" + + + + if pll_type == "SB_PLL40_2F_PAD" or pll_type == "SB_PLL40_2_PAD": + if pll_type == "SB_PLL40_2F_PAD": + if fuzz_bit == "PLLOUT_SELECT_A_0": + v += "defparam pll_inst.PLLOUT_SELECT_PORTA = \"GENCLK_HALF\";\n" + elif fuzz_bit == "PLLOUT_SELECT_A_1": + v += "defparam pll_inst.PLLOUT_SELECT_PORTA = \"SHIFTREG_90deg\";\n" + else: + v += "defparam pll_inst.PLLOUT_SELECT_PORTA = \"GENCLK\";\n" + if fuzz_bit == "PLLOUT_SELECT_B_0": + v += "defparam pll_inst.PLLOUT_SELECT_PORTB = \"GENCLK_HALF\";\n" + elif fuzz_bit == "PLLOUT_SELECT_B_1": + v += "defparam pll_inst.PLLOUT_SELECT_PORTB = \"SHIFTREG_90deg\";\n" + else: + v += "defparam pll_inst.PLLOUT_SELECT_PORTB = \"GENCLK\";\n" + else: + if fuzz_bit == "PLLOUT_SELECT_A_0": + v += "defparam pll_inst.PLLOUT_SELECT = \"GENCLK_HALF\";\n" + elif fuzz_bit == "PLLOUT_SELECT_A_1": + v += "defparam pll_inst.PLLOUT_SELECT = \"SHIFTREG_90deg\";\n" + else: + v += "defparam pll_inst.PLLOUT_SELECT = \"GENCLK\";\n" + v += "defparam pll_inst.TEST_MODE = " + ("1'b1" if (fuzz_bit == "TEST_MODE") else "1'b0") + ";\n" + + return v; + +def make_vlog(fuzz_bit): + vlog = code_prefix + vlog += inst_pll(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 DIVQ 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 +divq_bit0 = { + "up5k" : (11, 31, 3) +} + +#Return a list of PLL 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] == ".io_tile": + current_x = int(splitline[1]) + current_y = int(splitline[2]) + elif splitline[0] == "PLL": + if splitline[1][:10] == "PLLCONFIG_": + bitidx = int(splitline[1][10:]) + 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, \"PLLCONFIG_%d\")" % bit + +#The main fuzzing function +def do_fuzz(): + if not os.path.exists("./work_pllauto"): + os.mkdir("./work_pllauto") + known_bits.append(divq_bit0[device]) + with open("pll_data_" + device + ".txt", 'w') as dat: + for fuzz_bit in fuzz_bits: + vlog = make_vlog(fuzz_bit) + with open("./work_pllauto/pllauto.v", 'w') as f: + f.write(vlog) + retval = os.system("bash ../../icecube.sh -" + device + " ./work_pllauto/pllauto.v > ./work_pllauto/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_pllauto/pllauto.asc > ./work_pllauto/pllauto.exp") + if retval != 0: + sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n') + sys.exit(1) + pll_bits = parse_exp("./work_pllauto/pllauto.exp") + new_bits = [] + for set_bit in pll_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 == "DIVQ_1": + print(("\"DIVQ_0\":").ljust(24) + bit_to_str(divq_bit0[device]) + ",") + dat.write(("\"DIVQ_0\":").ljust(24) + bit_to_str(divq_bit0[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() \ No newline at end of file -- cgit v1.2.3