diff --git a/fuzzers/015-clb-nffmux/Makefile b/fuzzers/015-clb-nffmux/Makefile index 8ebcd2c2..6980f1f4 100644 --- a/fuzzers/015-clb-nffmux/Makefile +++ b/fuzzers/015-clb-nffmux/Makefile @@ -1,4 +1,8 @@ -N := 3 -CLB_DBFIXUP=Y -include ../clb.mk +# Specimen count +N := 5 + +# A grep regex for SLICEM features to be skipped for SLICELs +SLICEM_FEATURES ?= "DFFMUX.MC31" + +include ../clb_ext.mk diff --git a/fuzzers/015-clb-nffmux/generate.py b/fuzzers/015-clb-nffmux/generate.py index 3fa520ad..98b442e9 100644 --- a/fuzzers/015-clb-nffmux/generate.py +++ b/fuzzers/015-clb-nffmux/generate.py @@ -59,12 +59,27 @@ for l in f: # create 0-tags for all sources on the remaining (unused) MUXes for loc, muxes in cache.items(): for which in muxes: - for src in "F7 F8 CY O5 AX XOR O6".split(): + for src in "F7 F8 CY O5 AX XOR O6 MC31".split(): + if src == "MC31" and which is not "D": continue if src == "F7" and which not in "AC": continue if src == "F8" and which not in "B": continue if src == "AX": src = which + "X" tag = "%sFFMUX.%s" % (which, src) segmk.add_site_tag(loc, tag, 0) -segmk.compile(bitfilter=util.bitfilter_clb_mux) + +def bitfilter(frame_idx, bit_idx): + + # Since the SRL32 is enabled along with DFFMUX.MC31, bits related to + # SRL32 features are masked out. + if (frame_idx, bit_idx) in [ + (30, 16), # ALUT.SRL + (1, 23), # WEMUX.CE + ]: + return False + + return util.bitfilter_clb_mux(frame_idx, bit_idx) + + +segmk.compile(bitfilter=bitfilter) segmk.write() diff --git a/fuzzers/015-clb-nffmux/top.py b/fuzzers/015-clb-nffmux/top.py index 90769867..8cc79b72 100644 --- a/fuzzers/015-clb-nffmux/top.py +++ b/fuzzers/015-clb-nffmux/top.py @@ -6,15 +6,19 @@ from prjxray import verilog # INCREMENT is the amount of additional CLBN to be instantiated in the design. # This makes the fuzzer compilation more robust against failures. INCREMENT = os.getenv('CLBN', 0) -CLBN = 400 + int(INCREMENT) +CLBN = 600 + int(INCREMENT) print('//Requested CLBs: %s' % str(CLBN)) -def gen_slices(): - for _tile_name, site_name, _site_type in util.get_roi().gen_sites([ - 'SLICEL', - 'SLICEM', - ]): +def gen_slicels(): + for _tile_name, site_name, _site_type in util.get_roi().gen_sites( + ['SLICEL']): + yield site_name + + +def gen_slicems(): + for _tile_name, site_name, _site_type in util.get_roi().gen_sites( + ['SLICEM']): yield site_name @@ -25,22 +29,31 @@ verilog.top_harness(DIN_N, DOUT_N) f = open('params.csv', 'w') f.write('module,loc,n\n') -slices = gen_slices() +slicels = gen_slicels() +slicems = gen_slicems() print( 'module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1)) for i in range(CLBN): - modules = [ - 'clb_NFFMUX_' + x for x in ['AX', 'CY', 'F78', 'O5', 'O6', 'XOR'] - ] + + use_slicem = (i % 2) == 0 + + if use_slicem: + loc = next(slicems) + variants = ['AX', 'CY', 'F78', 'O5', 'O6', 'XOR', 'MC31'] + else: + loc = next(slicels) + variants = ['AX', 'CY', 'F78', 'O5', 'O6', 'XOR'] + + modules = ['clb_NFFMUX_' + x for x in variants] module = random.choice(modules) - if module == 'clb_NFFMUX_F78': + if module == 'clb_NFFMUX_MC31': + n = 3 # Only DOUTMUX has MC31 input + elif module == 'clb_NFFMUX_F78': n = random.randint(0, 2) else: n = random.randint(0, 3) - #n = 0 - loc = next(slices) print(' %s' % module) print(' #(.LOC("%s"), .N(%d))' % (loc, n)) @@ -65,10 +78,12 @@ module myLUT8 (input clk, input [7:0] din, //carco: CLA result (carry module additional output) output caro, output carco, output bo5, output bo6, + output wire mc31, output wire ff_q, //always connect to output input wire ff_d); //mux output net parameter LOC="SLICE_FIXME"; parameter N=-1; + parameter ALUT_SRL=0; wire [3:0] caro_all; assign caro = caro_all[N]; @@ -127,18 +142,37 @@ module myLUT8 (input clk, input [7:0] din, .O5(lutno5[1]), .O6(lutno6[1])); + generate if (ALUT_SRL != 0) begin + (* LOC=LOC, BEL="A6LUT", KEEP, DONT_TOUCH *) - LUT6_2 #( - .INIT(64'h8000_1CE0_0000_0001) - ) luta ( - .I0(din[0]), - .I1(din[1]), - .I2(din[2]), - .I3(din[3]), - .I4(din[4]), - .I5(din[5]), - .O5(lutno5[0]), - .O6(lutno6[0])); + SRLC32E #( + .INIT(64'h8000_1CE0_0000_0001) + ) srla ( + .CLK(clk), + .CE(din[6]), + .D(din[5]), + .A(din[4:0]), + .Q(lutno6[0]), + .Q31(mc31)); + + assign lutno5[0] = din[6]; + + end else begin + + (* LOC=LOC, BEL="A6LUT", KEEP, DONT_TOUCH *) + LUT6_2 #( + .INIT(64'h8000_1CE0_0000_0001) + ) luta ( + .I0(din[0]), + .I1(din[1]), + .I2(din[2]), + .I3(din[3]), + .I4(din[4]), + .I5(din[5]), + .O5(lutno5[0]), + .O6(lutno6[0])); + + end endgenerate //Outputs do not have to be used, will stay without them (* LOC=LOC, KEEP, DONT_TOUCH *) @@ -302,4 +336,19 @@ module clb_NFFMUX_XOR (input clk, input [7:0] din, output [7:0] dout); .ff_q(dout[0]), .ff_d(caro)); endmodule + +module clb_NFFMUX_MC31 (input clk, input [7:0] din, output [7:0] dout); + parameter LOC="SLICE_FIXME"; + parameter N=-1; // Dummy + wire mc31; + + myLUT8 #(.LOC(LOC), .N(3), .ALUT_SRL(1)) + myLUT8(.clk(clk), .din(din), + .lut8o(), + .caro(caro), .carco(), + .bo5(), .bo6(bo6), + .mc31(mc31), + .ff_q(dout[0]), + .ff_d(mc31)); +endmodule ''') diff --git a/fuzzers/016-clb-noutmux/Makefile b/fuzzers/016-clb-noutmux/Makefile index 8ebcd2c2..c5cce725 100644 --- a/fuzzers/016-clb-noutmux/Makefile +++ b/fuzzers/016-clb-noutmux/Makefile @@ -1,4 +1,8 @@ -N := 3 -CLB_DBFIXUP=Y -include ../clb.mk +# Specimen count +N := 5 + +# A grep regex for SLICEM features to be skipped for SLICELs +SLICEM_FEATURES ?= "DOUTMUX.MC31" + +include ../clb_ext.mk diff --git a/fuzzers/016-clb-noutmux/generate.py b/fuzzers/016-clb-noutmux/generate.py index 78a6ab86..07ad3716 100644 --- a/fuzzers/016-clb-noutmux/generate.py +++ b/fuzzers/016-clb-noutmux/generate.py @@ -62,7 +62,8 @@ for l in f: # create 0-tags for all sources on the remaining (unused) MUXes for loc, muxes in cache.items(): for which in muxes: - for src in "F7 F8 CY O5 XOR 5Q".split(): + for src in "F7 F8 CY O5 XOR 5Q MC31".split(): + if src == "MC31" and which is not "D": continue if src == "F7" and which not in "AC": continue if src == "F8" and which not in "B": continue if src == "5Q": src = which + "5Q" @@ -74,6 +75,10 @@ def bitfilter(frame_idx, bit_idx): # locations of A5MA, B5MA, C5MA, D5MA bits. because of the way we generate specimens # in this fuzzer we get some aliasing with those bits, so we have to manually exclude # them. (Maybe FIXME: read the bit locations from the database files) + + # Since the SRL32 is enabled along with DOUTMUX.MC31, bits related to + # SRL32 features are masked out. + if (frame_idx, bit_idx) in [ (30, 55), (31, 55), # D5MA @@ -83,6 +88,8 @@ def bitfilter(frame_idx, bit_idx): (31, 19), # B5MA (30, 9), (31, 8), # A5MA + (30, 16), # ALUT.SRL + (1, 23), # WEMUX.CE ]: return False diff --git a/fuzzers/016-clb-noutmux/top.py b/fuzzers/016-clb-noutmux/top.py index 808ef73c..2d513066 100644 --- a/fuzzers/016-clb-noutmux/top.py +++ b/fuzzers/016-clb-noutmux/top.py @@ -6,13 +6,19 @@ from prjxray import verilog # INCREMENT is the amount of additional CLBN to be instantiated in the design. # This makes the fuzzer compilation more robust against failures. INCREMENT = os.getenv('CLBN', 0) -CLBN = 400 + int(INCREMENT) +CLBN = 600 + int(INCREMENT) print('//Requested CLBs: %s' % str(CLBN)) -def gen_slices(): +def gen_slicels(): for _tile_name, site_name, _site_type in util.get_roi().gen_sites( - ['SLICEL', 'SLICEM']): + ['SLICEL']): + yield site_name + + +def gen_slicems(): + for _tile_name, site_name, _site_type in util.get_roi().gen_sites( + ['SLICEM']): yield site_name @@ -23,21 +29,32 @@ verilog.top_harness(DIN_N, DOUT_N) f = open('params.csv', 'w') f.write('module,loc,n\n') -slices = gen_slices() +slicels = gen_slicels() +slicems = gen_slicems() print( 'module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1)) for i in range(CLBN): + + use_slicem = (i % 2) == 0 + + if use_slicem: + loc = next(slicems) + variants = ['CY', 'F78', 'O5', 'XOR', 'B5Q', 'MC31'] + else: + loc = next(slicels) + variants = ['CY', 'F78', 'O5', 'XOR', 'B5Q'] + # Don't have an O6 example - modules = ['clb_NOUTMUX_' + x for x in ['CY', 'F78', 'O5', 'XOR', 'B5Q']] + modules = ['clb_NOUTMUX_' + x for x in variants] module = random.choice(modules) - if module == 'clb_NOUTMUX_F78': + if module == 'clb_NOUTMUX_MC31': + n = 3 # Only DOUTMUX has MC31 input + elif module == 'clb_NOUTMUX_F78': n = random.randint(0, 2) else: n = random.randint(0, 3) - #n = 0 - loc = next(slices) print(' %s' % module) print(' #(.LOC("%s"), .N(%d))' % (loc, n)) @@ -64,10 +81,13 @@ module myLUT8 (input clk, input [7:0] din, output bo5, output bo6, //Note: b5ff_q requires the mux and will conflict with other wires //Otherwise this FF drops out - output wire ff_q); //output wire [3:0] n5ff_q); + output wire ff_q, + output wire mc31); + parameter N=-1; parameter LOC="SLICE_FIXME"; + parameter ALUT_SRL=0; wire [3:0] caro_all; assign caro = caro_all[N]; @@ -126,7 +146,24 @@ module myLUT8 (input clk, input [7:0] din, .O5(lutno5[1]), .O6(lutno6[1])); - (* LOC=LOC, BEL="A6LUT", KEEP, DONT_TOUCH *) + generate if (ALUT_SRL != 0) begin + + (* LOC=LOC, BEL="A6LUT", KEEP, DONT_TOUCH *) + SRLC32E #( + .INIT(64'h8000_1CE0_0000_0001) + ) srla ( + .CLK(clk), + .CE(din[6]), + .D(din[5]), + .A(din[4:0]), + .Q(lutno6[0]), + .Q31(mc31)); + + assign lutno5[0] = din[6]; + + end else begin + + (* LOC=LOC, BEL="A6LUT", KEEP, DONT_TOUCH *) LUT6_2 #( .INIT(64'h8000_1CE0_0000_0001) ) luta ( @@ -139,6 +176,8 @@ module myLUT8 (input clk, input [7:0] din, .O5(lutno5[0]), .O6(lutno6[0])); + end endgenerate + //Outputs do not have to be used, will stay without them (* LOC=LOC, KEEP, DONT_TOUCH *) CARRY4 carry4(.O(caro_all), .CO(carco_all), .DI(lutno5), .S(lutno6), .CYINIT(1'b0), .CI()); @@ -273,4 +312,16 @@ module clb_NOUTMUX_B5Q (input clk, input [7:0] din, output [7:0] dout); .bo5(), .bo6(), .ff_q(dout[0])); endmodule + +module clb_NOUTMUX_MC31 (input clk, input [7:0] din, output [7:0] dout); + parameter LOC="SLICE_FIXME"; + parameter N=0; // Dummy + + myLUT8 #(.LOC(LOC), .N(0), .ALUT_SRL(1)) + myLUT8(.clk(clk), .din(din), + .lut8o(), + .caro(), .carco(), + .bo5(), .bo6(), + .ff_q(), .mc31(dout[0])); +endmodule ''') diff --git a/fuzzers/clb_ext.mk b/fuzzers/clb_ext.mk new file mode 100644 index 00000000..902777b9 --- /dev/null +++ b/fuzzers/clb_ext.mk @@ -0,0 +1,60 @@ +# Speciment count +N ?= 1 + +# A grep regex for SLICEM features to be skipped for SLICELs +SLICEM_FEATURES ?= "*" + +# This set of variables are used to store the increment +# in the number of CLBs in case they are not enough and +# the generated database is inconsistent +CLBN ?= 0 +INC ?= 50 +VAR ?= "CLBN=$$(($(CLBN) + $(INC)))" +ENV_VAR ?= "CLBN=$(CLBN)" +ITER ?= 0 +MAX_ITER ?= 10 +FUZDIR = ${PWD} + +SEGMATCH_ARGS ?=-m 2 -M 2 + +SEGDATAS=$(addsuffix /segdata_clbl[lm]_[lr].txt,$(SPECIMENS)) + +include ../fuzzer.mk + +build/segbits_clbx.rdb: $(SPECIMENS_OK) + ${XRAY_SEGMATCH} $(SEGMATCH_ARGS) -o build/segbits_clbx.rdb $(SEGDATAS) + +checkdb: + # If the database presents errors or is incomplete, the fuzzer is rerun. + # When it reaches the maximum number of iterations it fails. + @if [ $(ITER) -gt $(MAX_ITER) ]; then \ + echo "Max Iterations reached. Fuzzer unsolvable."; \ + exit 1; \ + fi + $(MAKE) parsedb || $(MAKE) $(VAR) ITER=$$(($(ITER) + 1)) run + +parsedb: + $(foreach file, $(wildcard build/*.db), ${XRAY_PARSEDB} --strict $(file);) + +database: build/segbits_clbl.db build/segbits_clbm.db + +build/segbits_clbm.rdb: build/segbits_clbx.rdb + cp $^ $@ +build/segbits_clbl.rdb: build/segbits_clbx.rdb + cat $^ | grep -E -v $(SLICEM_FEATURES) >$@ + +build/%.db: build/%.rdb + ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@ + ${XRAY_MASKMERGE} $(subst .rdb,.db,$(subst segbits,mask,$^)) $(SEGDATAS) + +pushdb: checkdb + ${XRAY_MERGEDB} clbll_l build/segbits_clbl.db + ${XRAY_MERGEDB} clbll_r build/segbits_clbl.db + ${XRAY_MERGEDB} mask_clbll_l build/mask_clbl.db + ${XRAY_MERGEDB} mask_clbll_r build/mask_clbl.db + ${XRAY_MERGEDB} clblm_l build/segbits_clbm.db + ${XRAY_MERGEDB} clblm_r build/segbits_clbm.db + ${XRAY_MERGEDB} mask_clblm_l build/mask_clbm.db + ${XRAY_MERGEDB} mask_clblm_r build/mask_clbm.db + +.PHONY: checkdb parsedb pushdb