| #!/usr/bin/env python3 |
| # -*- coding: utf-8 -*- |
| # |
| # Copyright (C) 2017-2020 The Project X-Ray Authors. |
| # |
| # Use of this source code is governed by a ISC-style |
| # license that can be found in the LICENSE file or at |
| # https://opensource.org/licenses/ISC |
| # |
| # SPDX-License-Identifier: ISC |
| ''' |
| Need coverage for the following: |
| RAM32X1S_N |
| RAM32X1D |
| RAM32M |
| RAM64X1S_N |
| RAM64X1D_N |
| RAM64M |
| RAM128X1S_N |
| RAM128X1D |
| RAM256X1S |
| SRL16E_N |
| SRLC32E_N |
| |
| Note: LUT6 was added to try to simplify reduction, although it might not be needed |
| ''' |
| |
| import os, random |
| random.seed(0) |
| from prjxray import util |
| 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 = 50 + int(INCREMENT) |
| print('//Requested CLBs: %s' % str(CLBN)) |
| |
| |
| def gen_slicems(): |
| for _tile_name, site_name, _site_type in util.get_roi().gen_sites( |
| ['SLICEM']): |
| yield site_name |
| |
| |
| DIN_N = CLBN * 8 |
| DOUT_N = CLBN * 8 |
| |
| verilog.top_harness(DIN_N, DOUT_N) |
| |
| f = open('params.csv', 'w') |
| f.write('module,loc,bela,belb,belc,beld\n') |
| slices = sorted(gen_slicems()) |
| random.shuffle(slices) |
| |
| print( |
| 'module roi(input clk, input [%d:0] din, output [%d:0] dout);' % |
| (DIN_N - 1, DOUT_N - 1)) |
| randluts = 0 |
| for clbi, loc in zip(range(CLBN), slices): |
| params = '' |
| cparams = '' |
| # Multi module |
| # Fill with random assortment of SRL16E and SRLC32E |
| if random.randint(0, 1): |
| params = '' |
| module = 'my_ram_N' |
| |
| # Can fit 4 per CLB |
| # BELable |
| bel_opts = [ |
| 'SRL16E', |
| 'SRLC32E', |
| # Weight LUT6 more heavily to make WEMUX.CE solve quicker |
| 'LUT6', |
| 'LUT6', |
| ] |
| |
| bels = [] |
| for beli in range(4): |
| belc = chr(ord('A') + beli) |
| if randluts: |
| bel = random.choice(bel_opts) |
| else: |
| # Force one without memory elements to bring CE bit low |
| bel = 'LUT6' |
| |
| params += ', .%c_%s(1)' % (belc, bel) |
| bels.append(bel) |
| # Record the BELs we chose in the module (A, B, C, D) |
| cparams = ',' + (','.join(bels)) |
| randluts += 1 |
| # Greedy module |
| # Don't place anything else in it |
| # For solving muxes vs previous results |
| else: |
| modules = [ |
| # (module, N max, FF opt) |
| ('my_RAM32X1S_N', 4, 0), |
| ('my_RAM32X1D', None, 0), |
| ('my_RAM32M', None, 0), |
| ('my_RAM64X1S_N', 4, 0), |
| ('my_RAM64X1D_N', 2, 0), |
| ('my_RAM64M', None, 0), |
| ('my_RAM128X1S_N', 2, 1), |
| ('my_RAM128X1D', None, 1), |
| ('my_RAM256X1S', None, 1), |
| ] |
| |
| module, nmax, ff_param = random.choice(modules) |
| |
| n = '' |
| if nmax: |
| n = random.randint(1, nmax) |
| params += ',.N(%d)' % n |
| cparams += ',%s' % n |
| |
| ff = '' |
| if ff_param: |
| ff = random.randint(0, 1) |
| params += ',.FF(%d)' % ff |
| cparams += ',%s' % ff |
| |
| # Pad to match above CSV size |
| cparams += ",," |
| |
| print(' %s' % module) |
| print(' #(.LOC("%s")%s)' % (loc, params)) |
| sel = random.random() |
| if sel > .15: |
| print( |
| ' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' |
| % (clbi, 8 * clbi, 8 * clbi)) |
| else: |
| print( |
| " clb_%d (.clk(clk), .din({8{1'b1}}), .dout());" % |
| (clbi, )) |
| |
| f.write('%s,%s%s\n' % (module, loc, cparams)) |
| f.close() |
| print( |
| '''endmodule |
| |
| // --------------------------------------------------------------------- |
| |
| ''') |
| |
| print( |
| ''' |
| |
| //*************************************************************** |
| //Basic |
| |
| module maybe_ff (input clk, din, dout); |
| parameter FF = 0; |
| |
| generate |
| if (FF) begin |
| reg r; |
| assign dout = r; |
| always @(posedge clk) begin |
| r = din; |
| end |
| end else begin |
| assign dout = din; |
| end |
| endgenerate |
| endmodule |
| |
| module my_RAM32X1S_N (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| //1-4 |
| parameter N=1; |
| |
| genvar i; |
| generate |
| for (i = 0; i < N; i = i + 1) begin : loop |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM32X1S #( |
| ) RAM32X1S ( |
| .O(dout[i]), |
| .A0(din[0]), |
| .A1(din[1]), |
| .A2(din[2]), |
| .A3(din[3]), |
| .A4(din[4]), |
| .D(din[5]), |
| .WCLK(clk), |
| .WE(ce)); |
| end |
| endgenerate |
| endmodule |
| |
| module my_RAM32X1D (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM32X1D #( |
| ) RAM32X1D ( |
| .DPO(dout[0]), |
| .SPO(dout[1]), |
| .A0(din[0]), |
| .A1(din[1]), |
| .A2(din[2]), |
| .A3(din[3]), |
| .A4(din[4]), |
| .D(din[5]), |
| .DPRA0(din[6]), |
| .DPRA1(din[7]), |
| .DPRA2(din[0]), |
| .DPRA3(din[1]), |
| .DPRA4(din[2]), |
| .WCLK(din[3]), |
| .WE(din[4])); |
| endmodule |
| |
| module my_RAM32M (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM32M #( |
| ) RAM32M ( |
| .DOA(dout[1:0]), |
| .DOB(dout[3:2]), |
| .DOC(dout[5:4]), |
| .DOD(dout[7:6]), |
| .ADDRA(din[4:0]), |
| .ADDRB(din[4:0]), |
| .ADDRC(din[4:0]), |
| .ADDRD(din[4:0]), |
| .DIA(din[5:4]), |
| .DIB(din[6:5]), |
| .DIC(din[7:6]), |
| .DID(din[1:0]), |
| .WCLK(din[1]), |
| .WE(din[2])); |
| endmodule |
| |
| module my_RAM64X1S_N (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| //1-4 |
| parameter N=1; |
| |
| genvar i; |
| generate |
| for (i = 0; i < N; i = i + 1) begin : loop |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM64X1S #( |
| ) RAM64X1S ( |
| .O(dout[i]), |
| .A0(din[0]), |
| .A1(din[1]), |
| .A2(din[2]), |
| .A3(din[3]), |
| .A4(din[4]), |
| .A5(din[5]), |
| .D(din[6]), |
| .WCLK(clk), |
| .WE(ce)); |
| end |
| endgenerate |
| endmodule |
| |
| module my_RAM64X1D_N (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| //1-2 |
| parameter N=1; |
| |
| genvar i; |
| generate |
| for (i = 0; i < N; i = i + 1) begin : loop |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM64X1D #( |
| .INIT(64'h0), |
| .IS_WCLK_INVERTED(1'b0) |
| ) ramb ( |
| .DPO(dout[i]), |
| .D(din[0]), |
| .WCLK(clk), |
| .WE(din[2]), |
| .A0(din[3]), |
| .A1(din[4]), |
| .A2(din[5]), |
| .A3(din[6]), |
| .A4(din[7]), |
| .A5(din[0]), |
| .DPRA0(din[1]), |
| .DPRA1(din[2]), |
| .DPRA2(din[3]), |
| .DPRA3(din[4]), |
| .DPRA4(din[5]), |
| .DPRA5(din[6])); |
| end |
| endgenerate |
| endmodule |
| |
| module my_RAM64M (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| parameter BEL="A6LUT"; |
| |
| (* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *) |
| RAM64M #( |
| ) RAM64M ( |
| .DOA(dout[0]), |
| .DOB(dout[1]), |
| .DOC(dout[2]), |
| .DOD(dout[3]), |
| .ADDRA(din[0]), |
| .ADDRB(din[1]), |
| .ADDRC(din[2]), |
| .ADDRD(din[3]), |
| .DIA(din[4]), |
| .DIB(din[5]), |
| .DIC(din[6]), |
| .DID(din[7]), |
| .WCLK(clk), |
| .WE(din[1])); |
| endmodule |
| |
| module my_RAM128X1S_N (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| //1-2 |
| parameter N=1; |
| parameter FF = 0; |
| |
| genvar i; |
| generate |
| for (i = 0; i < N; i = i + 1) begin : loop |
| wire o; |
| |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM128X1S #( |
| ) RAM128X1S ( |
| .O(o), |
| .A0(din[0]), |
| .A1(din[1]), |
| .A2(din[2]), |
| .A3(din[3]), |
| .A4(din[4]), |
| .A5(din[5]), |
| .A6(din[6]), |
| .D(din[7]), |
| .WCLK(din[0]), |
| .WE(din[1])); |
| |
| maybe_ff #(.FF(FF)) ff (.clk(clk), .din(o), .dout(dout[i])); |
| end |
| endgenerate |
| endmodule |
| |
| module my_RAM128X1D (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| parameter FF = 0; |
| |
| wire dpo, spo; |
| |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM128X1D #( |
| .INIT(128'h0), |
| .IS_WCLK_INVERTED(1'b0) |
| ) RAM128X1D ( |
| .DPO(dpo), |
| .SPO(spo), |
| .D(din[0]), |
| .WCLK(clk), |
| .WE(din[2])); |
| |
| maybe_ff #(.FF(FF)) ff0 (.clk(clk), .din(dpo), .dout(dout[0])); |
| maybe_ff #(.FF(FF)) ff1 (.clk(clk), .din(spo), .dout(dout[1])); |
| endmodule |
| |
| //Dedicated LOC |
| module my_RAM256X1S (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| parameter FF = 0; |
| |
| wire o; |
| |
| (* LOC=LOC, KEEP, DONT_TOUCH *) |
| RAM256X1S #( |
| ) RAM256X1S ( |
| .O(o), |
| .A({din[0], din[7:0]}), |
| .D(din[0]), |
| .WCLK(din[1]), |
| .WE(din[2])); |
| |
| maybe_ff #(.FF(FF)) ff (.clk(clk), .din(o), .dout(dout[0])); |
| endmodule |
| |
| //*************************************************************** |
| |
| module my_ram_N_inst (input clk, input [7:0] din, output dout); |
| parameter LOC=""; |
| parameter BEL=""; |
| parameter N_SRL16E=0; |
| parameter N_SRLC32E=0; |
| parameter N_LUT6=0; |
| |
| parameter SRLINIT = 32'h00000000; |
| parameter LUTINIT6 = 64'h0000_0000_0000_0000; |
| |
| wire ce = din[4]; |
| |
| generate |
| //******************** |
| if (N_SRL16E) begin |
| (* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *) |
| SRL16E #( |
| ) lut ( |
| .Q(dout), |
| .A0(din[0]), |
| .A1(din[1]), |
| .A2(din[2]), |
| .A3(din[3]), |
| .CE(ce), |
| .CLK(clk), |
| .D(din[6])); |
| end |
| if (N_SRLC32E) begin |
| (* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *) |
| SRLC32E #( |
| .INIT(SRLINIT), |
| .IS_CLK_INVERTED(1'b0) |
| ) lut ( |
| .Q(dout), |
| .Q31(), |
| .A(din[4:0]), |
| .CE(ce), |
| .CLK(clk), |
| .D(din[7])); |
| end |
| if (N_LUT6) begin |
| (* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *) |
| LUT6_2 #( |
| .INIT(LUTINIT6) |
| ) lut ( |
| .I0(din[0]), |
| .I1(din[1]), |
| .I2(din[2]), |
| .I3(din[3]), |
| .I4(din[4]), |
| .I5(din[5]), |
| .O5(), |
| .O6(dout)); |
| end |
| endgenerate |
| endmodule |
| |
| /* |
| Supermodule for LOC'able prims |
| Mix and match as needed |
| Specify at most one function generator per LUT |
| */ |
| module my_ram_N (input clk, input [7:0] din, output [7:0] dout); |
| parameter LOC = ""; |
| parameter D_SRL16E=0; |
| parameter D_SRLC32E=0; |
| parameter D_LUT6=0; |
| |
| parameter C_SRL16E=0; |
| parameter C_SRLC32E=0; |
| parameter C_LUT6=0; |
| |
| parameter B_SRL16E=0; |
| parameter B_SRLC32E=0; |
| parameter B_LUT6=0; |
| |
| parameter A_SRL16E=0; |
| parameter A_SRLC32E=0; |
| parameter A_LUT6=0; |
| |
| my_ram_N_inst #(.LOC(LOC), .BEL("D6LUT"), .N_SRL16E(D_SRL16E), .N_SRLC32E(D_SRLC32E), .N_LUT6(D_LUT6)) |
| lutd(.clk(clk), .din(din), .dout(dout[3])); |
| my_ram_N_inst #(.LOC(LOC), .BEL("C6LUT"), .N_SRL16E(C_SRL16E), .N_SRLC32E(C_SRLC32E), .N_LUT6(C_LUT6)) |
| lutc(.clk(clk), .din(din), .dout(dout[2])); |
| my_ram_N_inst #(.LOC(LOC), .BEL("B6LUT"), .N_SRL16E(B_SRL16E), .N_SRLC32E(B_SRLC32E), .N_LUT6(B_LUT6)) |
| lutb(.clk(clk), .din(din), .dout(dout[1])); |
| my_ram_N_inst #(.LOC(LOC), .BEL("A6LUT"), .N_SRL16E(A_SRL16E), .N_SRLC32E(A_SRLC32E), .N_LUT6(A_LUT6)) |
| luta(.clk(clk), .din(din), .dout(dout[0])); |
| endmodule |
| |
| ''') |