diff --git a/Makefile b/Makefile index cf9fe9049..33ff74fa4 100644 --- a/Makefile +++ b/Makefile @@ -920,6 +920,7 @@ endif # Tests that generate .mk with tests/gen-tests-makefile.sh MK_TEST_DIRS = +MK_TEST_DIRS += tests/arch/analogdevices MK_TEST_DIRS += tests/arch/anlogic MK_TEST_DIRS += tests/arch/ecp5 MK_TEST_DIRS += tests/arch/efinix diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 61135e066..9494d6032 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -561,7 +561,7 @@ struct statdata_t { } } - if (tech == "xilinx") { + if (tech == "xilinx" || tech == "analogdevices") { log("\n"); log(" Estimated number of LCs: %10u\n", estimate_xilinx_lc()); } @@ -628,7 +628,7 @@ struct statdata_t { first_line = false; } log("\n }\n"); - if (tech == "xilinx") { + if (tech == "xilinx" || tech == "analogdevices") { log(" \"estimated_num_lc\": %u,\n", estimate_xilinx_lc()); } if (tech == "cmos") { @@ -710,7 +710,7 @@ struct statdata_t { log("\n"); log(" }"); } - if (tech == "xilinx") { + if (tech == "xilinx" || tech == "analogdevices") { log(",\n"); log(" \"estimated_num_lc\": %u", estimate_xilinx_lc()); } @@ -908,7 +908,7 @@ struct StatPass : public Pass { log("\n"); log(" -tech \n"); log(" print area estimate for the specified technology. Currently supported\n"); - log(" values for : xilinx, cmos\n"); + log(" values for : xilinx, analogdevices, cmos\n"); log("\n"); log(" -width\n"); log(" annotate internal cell types with their word width.\n"); @@ -968,7 +968,7 @@ struct StatPass : public Pass { if (!json_mode) log_header(design, "Printing statistics.\n"); - if (techname != "" && techname != "xilinx" && techname != "cmos" && !json_mode) + if (techname != "" && techname != "xilinx" && techname != "analogdevices" && techname != "cmos" && !json_mode) log_cmd_error("Unsupported technology: '%s'\n", techname); if (json_mode) { diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc index fa8eb563b..580853b51 100644 --- a/passes/opt/opt_lut_ins.cc +++ b/passes/opt/opt_lut_ins.cc @@ -39,7 +39,8 @@ struct OptLutInsPass : public Pass { log("\n"); log(" -tech \n"); log(" Instead of generic $lut cells, operate on LUT cells specific\n"); - log(" to the given technology. Valid values are: xilinx, lattice, gowin.\n"); + log(" to the given technology. Valid values are: xilinx, lattice,\n"); + log(" gowin, analogdevices.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override @@ -58,7 +59,7 @@ struct OptLutInsPass : public Pass { } extra_args(args, argidx, design); - if (techname != "" && techname != "xilinx" && techname != "lattice" && techname != "ecp5" && techname != "gowin") + if (techname != "" && techname != "xilinx" && techname != "lattice" && techname != "analogdevices" && techname != "gowin") log_cmd_error("Unsupported technology: '%s'\n", techname); for (auto module : design->selected_modules()) @@ -81,7 +82,7 @@ struct OptLutInsPass : public Pass { inputs = cell->getPort(ID::A); output = cell->getPort(ID::Y); lut = cell->getParam(ID::LUT); - } else if (techname == "xilinx" || techname == "gowin") { + } else if (techname == "xilinx" || techname == "gowin" || techname == "analogdevices") { if (cell->type == ID(LUT1)) { inputs = { cell->getPort(ID(I0)), @@ -126,11 +127,11 @@ struct OptLutInsPass : public Pass { continue; } lut = cell->getParam(ID::INIT); - if (techname == "xilinx") + if (techname == "xilinx" || techname == "analogdevices") output = cell->getPort(ID::O); else output = cell->getPort(ID::F); - } else if (techname == "lattice" || techname == "ecp5") { + } else if (techname == "lattice") { if (cell->type == ID(LUT4)) { inputs = { cell->getPort(ID::A), @@ -236,7 +237,7 @@ struct OptLutInsPass : public Pass { } else { // xilinx, gowin cell->setParam(ID::INIT, new_lut); - if (techname == "xilinx") + if (techname == "xilinx" || techname == "analogdevices") log_assert(GetSize(new_inputs) <= 6); else log_assert(GetSize(new_inputs) <= 4); diff --git a/techlibs/analogdevices/Makefile.inc b/techlibs/analogdevices/Makefile.inc new file mode 100644 index 000000000..5c2d6f05d --- /dev/null +++ b/techlibs/analogdevices/Makefile.inc @@ -0,0 +1,21 @@ + +OBJS += techlibs/analogdevices/synth_analogdevices.o + +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/cells_map.v)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/cells_sim.v)) + +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/lutrams.txt)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/lutrams_map.v)) + +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/brams_defs.vh)) + +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/brams.txt)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/brams_map.v)) + +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/arith_map.v)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/ff_map.v)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/lut_map.v)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/mux_map.v)) +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/dsp_map.v)) + +$(eval $(call add_share_file,share/analogdevices,techlibs/analogdevices/abc9_model.v)) diff --git a/techlibs/analogdevices/abc9_model.v b/techlibs/analogdevices/abc9_model.v new file mode 100644 index 000000000..a5a15026f --- /dev/null +++ b/techlibs/analogdevices/abc9_model.v @@ -0,0 +1,39 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// ============================================================================ + +// Box containing MUXF7.[AB] + MUXF8, +// Necessary to make these an atomic unit so that +// ABC cannot optimise just one of the MUXF7 away +// and expect to save on its delay +(* abc9_box, lib_whitebox *) +module \$__ANALOGDEVICES_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); + assign O = S1 ? (S0 ? I3 : I2) + : (S0 ? I1 : I0); + specify + (I0 => O) = 294; + (I1 => O) = 297; + (I2 => O) = 311; + (I3 => O) = 317; + (S0 => O) = 390; + (S1 => O) = 273; + endspecify +endmodule diff --git a/techlibs/analogdevices/arith_map.v b/techlibs/analogdevices/arith_map.v new file mode 100644 index 000000000..394a5a957 --- /dev/null +++ b/techlibs/analogdevices/arith_map.v @@ -0,0 +1,173 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// ============================================================================ +// LCU + +(* techmap_celltype = "$lcu" *) +module _80_analogdevices_lcu (P, G, CI, CO); + parameter WIDTH = 2; + + (* force_downto *) + input [WIDTH-1:0] P, G; + input CI; + + (* force_downto *) + output [WIDTH-1:0] CO; + + wire _TECHMAP_FAIL_ = WIDTH <= 2; + + genvar i; + +generate + localparam CARRY4_COUNT = (WIDTH + 3) / 4; + localparam MAX_WIDTH = CARRY4_COUNT * 4; + localparam PAD_WIDTH = MAX_WIDTH - WIDTH; + + (* force_downto *) + wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G}; + (* force_downto *) + wire [MAX_WIDTH-1:0] GG = {{PAD_WIDTH{1'b0}}, G}; + (* force_downto *) + wire [MAX_WIDTH-1:0] C; + assign CO = C; + + generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + if (i == 0) begin + wire INITCO; + + CRY4INIT init + ( + .CYINIT(CI), + .CO (INITCO) + ); + + CRY4 carry4 + ( + .CYINIT(1'd0), + .CI (INITCO), + .DI (GG[i*4 +: 4]), + .S (S [i*4 +: 4]), + .CO (C [i*4 +: 4]), + ); + end else begin + CRY4 carry4 + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (GG[i*4 +: 4]), + .S (S [i*4 +: 4]), + .CO (C [i*4 +: 4]), + ); + end + end endgenerate +endgenerate + +endmodule + + +// ============================================================================ +// ALU + +(* techmap_celltype = "$alu" *) +module _80_analogdevices_alu (A, B, CI, BI, X, Y, CO); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + parameter _TECHMAP_CONSTVAL_CI_ = 0; + parameter _TECHMAP_CONSTMSK_CI_ = 0; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] X, Y; + + input CI, BI; + (* force_downto *) + output [Y_WIDTH-1:0] CO; + + wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; + + (* force_downto *) + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + (* force_downto *) + wire [Y_WIDTH-1:0] AA = A_buf; + (* force_downto *) + wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; + + genvar i; + + localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; + localparam MAX_WIDTH = CARRY4_COUNT * 4; + localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH; + + (* force_downto *) + wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB}; + (* force_downto *) + wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA}; + + (* force_downto *) + wire [MAX_WIDTH-1:0] O; + (* force_downto *) + wire [MAX_WIDTH-1:0] C; + assign Y = O, CO = C; + + genvar i; + generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + if (i == 0) begin + wire INITCO; + + CRY4INIT init + ( + .CYINIT(CI), + .CO (INITCO) + ); + + CRY4 carry4 + ( + .CYINIT(1'd0), + .CI (INITCO), + .DI (DI[i*4 +: 4]), + .S (S [i*4 +: 4]), + .O (O [i*4 +: 4]), + .CO (C [i*4 +: 4]) + ); + end else begin + CRY4 carry4 + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (DI[i*4 +: 4]), + .S (S [i*4 +: 4]), + .O (O [i*4 +: 4]), + .CO (C [i*4 +: 4]) + ); + end + end endgenerate + + assign X = S; +endmodule + diff --git a/techlibs/analogdevices/brams.txt b/techlibs/analogdevices/brams.txt new file mode 100644 index 000000000..10cdadefb --- /dev/null +++ b/techlibs/analogdevices/brams.txt @@ -0,0 +1,285 @@ +ifdef IS_T16FFC { + ram block $__ANALOGDEVICES_BLOCKRAM_FULL_ { + option "ERR" "ECC" { + style "ECC"; + option "SIZE" "2048x32" { + abits 11; + width 32; + byte 32; + option "MODE" "TDP" cost 4502; + option "MODE" "SDP" forbid; + option "MODE" "SP" forbid; + } + option "SIZE" "1024x32" { + abits 10; + width 32; + byte 32; + option "MODE" "TDP" forbid; + option "MODE" "SDP" cost 2402; + option "MODE" "SP" forbid; + } + } + option "ERR" "BP" { + style "BP"; + option "SIZE" "2048x36" { + abits 11; + width 36; + byte 9; + option "MODE" "TDP" cost 4504; + option "MODE" "SDP" forbid; + option "MODE" "SP" forbid; + } + option "SIZE" "1024x36" { + abits 10; + width 36; + byte 9; + option "MODE" "TDP" forbid; + option "MODE" "SDP" cost 2404; + option "MODE" "SP" forbid; + } + } + option "ERR" "FP" { + style "FP"; + option "SIZE" "2048x18" { + abits 11; + width 18; + byte 18; + option "MODE" "TDP" cost 2501; + option "MODE" "SDP" cost 2401; + option "MODE" "SP" forbid; + } + } + option "ERR" "NONE" { + option "SIZE" "8192x05" { + abits 13; + width 5; + byte 1; + option "MODE" "TDP" cost 2505; + option "MODE" "SDP" forbid; + option "MODE" "SP" forbid; + } + option "SIZE" "4096x09" { + abits 12; + width 9; + byte 1; + option "MODE" "TDP" cost 2509; + option "MODE" "SDP" forbid; + option "MODE" "SP" forbid; + } + option "SIZE" "4096x10" { + abits 12; + width 10; + byte 1; + option "MODE" "TDP" forbid; + option "MODE" "SDP" cost 2410; + option "MODE" "SP" forbid; + } + option "SIZE" "2048x20" { + abits 11; + width 20; + byte 1; + option "MODE" "TDP" forbid; + option "MODE" "SDP" forbid; + option "MODE" "SP" cost 2320; + } + option "SIZE" "2048x40" { + abits 11; + width 40; + byte 8; + option "MODE" "TDP" cost 4505; + option "MODE" "SDP" forbid; + option "MODE" "SP" forbid; + } + } + + # supports any initialization value, but need to export memory files + init any; + + option "MODE" "TDP" { + port srsw "A" { + clock anyedge; + clken; + rdwr no_change; + } + port srsw "B" { + clock anyedge; + clken; + rdwr no_change; + } + } + option "MODE" "SDP" { + port sw "A" { + clock anyedge; + clken; + } + port sr "B" { + clock anyedge; + clken; + } + } + option "MODE" "SP" { + port srsw "A" { + clock anyedge; + clken; + rdwr no_change; + } + } + } +} + +ram block $__ANALOGDEVICES_BLOCKRAM_HALF_ { + option "ERR" "ECC" { + style "ECC"; + option "SIZE" "1024x32" { + abits 10; + width 32; + byte 32; + option "MODE" "SDP" cost 2402; + option "MODE" "SP" forbid; + option "MODE" "SP2" forbid; + } + option "SIZE" "512x32" { + abits 9; + width 32; + byte 32; + option "MODE" "SDP" forbid; + option "MODE" "SP" cost 2302; + option "MODE" "SP2" forbid; + } + } + option "ERR" "BP" { + style "BP"; + option "SIZE" "1024x36" { + abits 10; + width 36; + byte 9; + option "MODE" "SDP" cost 2404; + option "MODE" "SP" forbid; + option "MODE" "SP2" forbid; + } + option "SIZE" "512x36" { + abits 9; + width 36; + byte 9; + option "MODE" "SDP" forbid; + option "MODE" "SP" cost 2304; + option "MODE" "SP2" forbid; + } + } + option "ERR" "FP" { + style "FP"; + option "SIZE" "1024x18" { + abits 10; + width 18; + byte 18; + option "MODE" "SDP" forbid; + option "MODE" "SP" forbid; + option "MODE" "SP2" cost 2301; + } + } + option "ERR" "NONE" { + option "SIZE" "4096x05" { + abits 12; + width 5; + byte 1; + option "MODE" "SDP" cost 2405; + option "MODE" "SP" cost 2305; + option "MODE" "SP2" forbid; + } + option "SIZE" "2048x09" { + abits 11; + width 9; + byte 1; + option "MODE" "SDP" cost 2409; + option "MODE" "SP" forbid; + option "MODE" "SP2" cost 2309; + } + option "SIZE" "2048x10" { + abits 11; + width 10; + byte 1; + option "MODE" "SDP" cost 2410; + option "MODE" "SP" forbid; + option "MODE" "SP2" forbid; + } + option "SIZE" "1024x20" { + abits 10; + width 20; + byte 1; + option "MODE" "SDP" forbid; + option "MODE" "SP" cost 2320; + option "MODE" "SP2" forbid; + } + option "SIZE" "1024x40" { + abits 10; + width 40; + byte 8; + option "MODE" "SDP" cost 2405; + option "MODE" "SP" forbid; + option "MODE" "SP2" forbid; + } + } + + option "MODE" "SDP" { + ifdef IS_T16FFC forbid; + port sw "A" { + clock anyedge; + clken; + } + port sr "B" { + clock anyedge; + clken; + } + } + option "MODE" "SP" { + ifdef IS_T16FFC forbid; + port srsw "A" { + clock anyedge; + clken; + rdwr no_change; + } + } + option "MODE" "SP2" { + ifdef IS_T40LP forbid; + port srsw "A" { + clock anyedge; + clken; + rdwr no_change; + } + } +} + +ifdef IS_T40LP { + ram block $__ANALOGDEVICES_BLOCKRAM_QUARTER_ { + option "ERR" "BP" { + style "BP"; + option "SIZE" "512x18" { + abits 9; + width 18; + byte 9; + option "MODE" "SP2" cost 2202; + } + } + option "ERR" "NONE" { + option "SIZE" "2048x05" { + abits 11; + width 5; + byte 1; + option "MODE" "SP2" cost 2205; + } + option "SIZE" "1024x09" { + abits 10; + width 9; + byte 1; + option "MODE" "SP2" cost 2209; + } + } + option "MODE" "SP2" { + port srsw "A" { + clock anyedge; + clken; + rdwr no_change; + } + } + } +} diff --git a/techlibs/analogdevices/brams_defs.vh b/techlibs/analogdevices/brams_defs.vh new file mode 100644 index 000000000..69fe5d716 --- /dev/null +++ b/techlibs/analogdevices/brams_defs.vh @@ -0,0 +1,561 @@ +`define PARAMS_INIT_9 \ + .INIT_00(slice_init('h00)), \ + .INIT_01(slice_init('h01)), \ + .INIT_02(slice_init('h02)), \ + .INIT_03(slice_init('h03)), \ + .INIT_04(slice_init('h04)), \ + .INIT_05(slice_init('h05)), \ + .INIT_06(slice_init('h06)), \ + .INIT_07(slice_init('h07)), \ + .INIT_08(slice_init('h08)), \ + .INIT_09(slice_init('h09)), \ + .INIT_0A(slice_init('h0a)), \ + .INIT_0B(slice_init('h0b)), \ + .INIT_0C(slice_init('h0c)), \ + .INIT_0D(slice_init('h0d)), \ + .INIT_0E(slice_init('h0e)), \ + .INIT_0F(slice_init('h0f)), \ + .INIT_10(slice_init('h10)), \ + .INIT_11(slice_init('h11)), \ + .INIT_12(slice_init('h12)), \ + .INIT_13(slice_init('h13)), \ + .INIT_14(slice_init('h14)), \ + .INIT_15(slice_init('h15)), \ + .INIT_16(slice_init('h16)), \ + .INIT_17(slice_init('h17)), \ + .INIT_18(slice_init('h18)), \ + .INIT_19(slice_init('h19)), \ + .INIT_1A(slice_init('h1a)), \ + .INIT_1B(slice_init('h1b)), \ + .INIT_1C(slice_init('h1c)), \ + .INIT_1D(slice_init('h1d)), \ + .INIT_1E(slice_init('h1e)), \ + .INIT_1F(slice_init('h1f)), + +`define PARAMS_INITP_9 \ + .INITP_00(slice_initp('h00)), \ + .INITP_01(slice_initp('h01)), \ + .INITP_02(slice_initp('h02)), \ + .INITP_03(slice_initp('h03)), + +`define PARAMS_INIT_18 \ + .INIT_00(slice_init('h00)), \ + .INIT_01(slice_init('h01)), \ + .INIT_02(slice_init('h02)), \ + .INIT_03(slice_init('h03)), \ + .INIT_04(slice_init('h04)), \ + .INIT_05(slice_init('h05)), \ + .INIT_06(slice_init('h06)), \ + .INIT_07(slice_init('h07)), \ + .INIT_08(slice_init('h08)), \ + .INIT_09(slice_init('h09)), \ + .INIT_0A(slice_init('h0a)), \ + .INIT_0B(slice_init('h0b)), \ + .INIT_0C(slice_init('h0c)), \ + .INIT_0D(slice_init('h0d)), \ + .INIT_0E(slice_init('h0e)), \ + .INIT_0F(slice_init('h0f)), \ + .INIT_10(slice_init('h10)), \ + .INIT_11(slice_init('h11)), \ + .INIT_12(slice_init('h12)), \ + .INIT_13(slice_init('h13)), \ + .INIT_14(slice_init('h14)), \ + .INIT_15(slice_init('h15)), \ + .INIT_16(slice_init('h16)), \ + .INIT_17(slice_init('h17)), \ + .INIT_18(slice_init('h18)), \ + .INIT_19(slice_init('h19)), \ + .INIT_1A(slice_init('h1a)), \ + .INIT_1B(slice_init('h1b)), \ + .INIT_1C(slice_init('h1c)), \ + .INIT_1D(slice_init('h1d)), \ + .INIT_1E(slice_init('h1e)), \ + .INIT_1F(slice_init('h1f)), \ + .INIT_20(slice_init('h20)), \ + .INIT_21(slice_init('h21)), \ + .INIT_22(slice_init('h22)), \ + .INIT_23(slice_init('h23)), \ + .INIT_24(slice_init('h24)), \ + .INIT_25(slice_init('h25)), \ + .INIT_26(slice_init('h26)), \ + .INIT_27(slice_init('h27)), \ + .INIT_28(slice_init('h28)), \ + .INIT_29(slice_init('h29)), \ + .INIT_2A(slice_init('h2a)), \ + .INIT_2B(slice_init('h2b)), \ + .INIT_2C(slice_init('h2c)), \ + .INIT_2D(slice_init('h2d)), \ + .INIT_2E(slice_init('h2e)), \ + .INIT_2F(slice_init('h2f)), \ + .INIT_30(slice_init('h30)), \ + .INIT_31(slice_init('h31)), \ + .INIT_32(slice_init('h32)), \ + .INIT_33(slice_init('h33)), \ + .INIT_34(slice_init('h34)), \ + .INIT_35(slice_init('h35)), \ + .INIT_36(slice_init('h36)), \ + .INIT_37(slice_init('h37)), \ + .INIT_38(slice_init('h38)), \ + .INIT_39(slice_init('h39)), \ + .INIT_3A(slice_init('h3a)), \ + .INIT_3B(slice_init('h3b)), \ + .INIT_3C(slice_init('h3c)), \ + .INIT_3D(slice_init('h3d)), \ + .INIT_3E(slice_init('h3e)), \ + .INIT_3F(slice_init('h3f)), + +`define PARAMS_INIT_18_U \ + .INIT_00(slice_init('h40)), \ + .INIT_01(slice_init('h41)), \ + .INIT_02(slice_init('h42)), \ + .INIT_03(slice_init('h43)), \ + .INIT_04(slice_init('h44)), \ + .INIT_05(slice_init('h45)), \ + .INIT_06(slice_init('h46)), \ + .INIT_07(slice_init('h47)), \ + .INIT_08(slice_init('h48)), \ + .INIT_09(slice_init('h49)), \ + .INIT_0A(slice_init('h4a)), \ + .INIT_0B(slice_init('h4b)), \ + .INIT_0C(slice_init('h4c)), \ + .INIT_0D(slice_init('h4d)), \ + .INIT_0E(slice_init('h4e)), \ + .INIT_0F(slice_init('h4f)), \ + .INIT_10(slice_init('h50)), \ + .INIT_11(slice_init('h51)), \ + .INIT_12(slice_init('h52)), \ + .INIT_13(slice_init('h53)), \ + .INIT_14(slice_init('h54)), \ + .INIT_15(slice_init('h55)), \ + .INIT_16(slice_init('h56)), \ + .INIT_17(slice_init('h57)), \ + .INIT_18(slice_init('h58)), \ + .INIT_19(slice_init('h59)), \ + .INIT_1A(slice_init('h5a)), \ + .INIT_1B(slice_init('h5b)), \ + .INIT_1C(slice_init('h5c)), \ + .INIT_1D(slice_init('h5d)), \ + .INIT_1E(slice_init('h5e)), \ + .INIT_1F(slice_init('h5f)), \ + .INIT_20(slice_init('h60)), \ + .INIT_21(slice_init('h61)), \ + .INIT_22(slice_init('h62)), \ + .INIT_23(slice_init('h63)), \ + .INIT_24(slice_init('h64)), \ + .INIT_25(slice_init('h65)), \ + .INIT_26(slice_init('h66)), \ + .INIT_27(slice_init('h67)), \ + .INIT_28(slice_init('h68)), \ + .INIT_29(slice_init('h69)), \ + .INIT_2A(slice_init('h6a)), \ + .INIT_2B(slice_init('h6b)), \ + .INIT_2C(slice_init('h6c)), \ + .INIT_2D(slice_init('h6d)), \ + .INIT_2E(slice_init('h6e)), \ + .INIT_2F(slice_init('h6f)), \ + .INIT_30(slice_init('h70)), \ + .INIT_31(slice_init('h71)), \ + .INIT_32(slice_init('h72)), \ + .INIT_33(slice_init('h73)), \ + .INIT_34(slice_init('h74)), \ + .INIT_35(slice_init('h75)), \ + .INIT_36(slice_init('h76)), \ + .INIT_37(slice_init('h77)), \ + .INIT_38(slice_init('h78)), \ + .INIT_39(slice_init('h79)), \ + .INIT_3A(slice_init('h7a)), \ + .INIT_3B(slice_init('h7b)), \ + .INIT_3C(slice_init('h7c)), \ + .INIT_3D(slice_init('h7d)), \ + .INIT_3E(slice_init('h7e)), \ + .INIT_3F(slice_init('h7f)), + +`define PARAMS_INITP_18 \ + .INITP_00(slice_initp('h00)), \ + .INITP_01(slice_initp('h01)), \ + .INITP_02(slice_initp('h02)), \ + .INITP_03(slice_initp('h03)), \ + .INITP_04(slice_initp('h04)), \ + .INITP_05(slice_initp('h05)), \ + .INITP_06(slice_initp('h06)), \ + .INITP_07(slice_initp('h07)), + +`define PARAMS_INIT_36 \ + .INIT_00(slice_init('h00)), \ + .INIT_01(slice_init('h01)), \ + .INIT_02(slice_init('h02)), \ + .INIT_03(slice_init('h03)), \ + .INIT_04(slice_init('h04)), \ + .INIT_05(slice_init('h05)), \ + .INIT_06(slice_init('h06)), \ + .INIT_07(slice_init('h07)), \ + .INIT_08(slice_init('h08)), \ + .INIT_09(slice_init('h09)), \ + .INIT_0A(slice_init('h0a)), \ + .INIT_0B(slice_init('h0b)), \ + .INIT_0C(slice_init('h0c)), \ + .INIT_0D(slice_init('h0d)), \ + .INIT_0E(slice_init('h0e)), \ + .INIT_0F(slice_init('h0f)), \ + .INIT_10(slice_init('h10)), \ + .INIT_11(slice_init('h11)), \ + .INIT_12(slice_init('h12)), \ + .INIT_13(slice_init('h13)), \ + .INIT_14(slice_init('h14)), \ + .INIT_15(slice_init('h15)), \ + .INIT_16(slice_init('h16)), \ + .INIT_17(slice_init('h17)), \ + .INIT_18(slice_init('h18)), \ + .INIT_19(slice_init('h19)), \ + .INIT_1A(slice_init('h1a)), \ + .INIT_1B(slice_init('h1b)), \ + .INIT_1C(slice_init('h1c)), \ + .INIT_1D(slice_init('h1d)), \ + .INIT_1E(slice_init('h1e)), \ + .INIT_1F(slice_init('h1f)), \ + .INIT_20(slice_init('h20)), \ + .INIT_21(slice_init('h21)), \ + .INIT_22(slice_init('h22)), \ + .INIT_23(slice_init('h23)), \ + .INIT_24(slice_init('h24)), \ + .INIT_25(slice_init('h25)), \ + .INIT_26(slice_init('h26)), \ + .INIT_27(slice_init('h27)), \ + .INIT_28(slice_init('h28)), \ + .INIT_29(slice_init('h29)), \ + .INIT_2A(slice_init('h2a)), \ + .INIT_2B(slice_init('h2b)), \ + .INIT_2C(slice_init('h2c)), \ + .INIT_2D(slice_init('h2d)), \ + .INIT_2E(slice_init('h2e)), \ + .INIT_2F(slice_init('h2f)), \ + .INIT_30(slice_init('h30)), \ + .INIT_31(slice_init('h31)), \ + .INIT_32(slice_init('h32)), \ + .INIT_33(slice_init('h33)), \ + .INIT_34(slice_init('h34)), \ + .INIT_35(slice_init('h35)), \ + .INIT_36(slice_init('h36)), \ + .INIT_37(slice_init('h37)), \ + .INIT_38(slice_init('h38)), \ + .INIT_39(slice_init('h39)), \ + .INIT_3A(slice_init('h3a)), \ + .INIT_3B(slice_init('h3b)), \ + .INIT_3C(slice_init('h3c)), \ + .INIT_3D(slice_init('h3d)), \ + .INIT_3E(slice_init('h3e)), \ + .INIT_3F(slice_init('h3f)), \ + .INIT_40(slice_init('h40)), \ + .INIT_41(slice_init('h41)), \ + .INIT_42(slice_init('h42)), \ + .INIT_43(slice_init('h43)), \ + .INIT_44(slice_init('h44)), \ + .INIT_45(slice_init('h45)), \ + .INIT_46(slice_init('h46)), \ + .INIT_47(slice_init('h47)), \ + .INIT_48(slice_init('h48)), \ + .INIT_49(slice_init('h49)), \ + .INIT_4A(slice_init('h4a)), \ + .INIT_4B(slice_init('h4b)), \ + .INIT_4C(slice_init('h4c)), \ + .INIT_4D(slice_init('h4d)), \ + .INIT_4E(slice_init('h4e)), \ + .INIT_4F(slice_init('h4f)), \ + .INIT_50(slice_init('h50)), \ + .INIT_51(slice_init('h51)), \ + .INIT_52(slice_init('h52)), \ + .INIT_53(slice_init('h53)), \ + .INIT_54(slice_init('h54)), \ + .INIT_55(slice_init('h55)), \ + .INIT_56(slice_init('h56)), \ + .INIT_57(slice_init('h57)), \ + .INIT_58(slice_init('h58)), \ + .INIT_59(slice_init('h59)), \ + .INIT_5A(slice_init('h5a)), \ + .INIT_5B(slice_init('h5b)), \ + .INIT_5C(slice_init('h5c)), \ + .INIT_5D(slice_init('h5d)), \ + .INIT_5E(slice_init('h5e)), \ + .INIT_5F(slice_init('h5f)), \ + .INIT_60(slice_init('h60)), \ + .INIT_61(slice_init('h61)), \ + .INIT_62(slice_init('h62)), \ + .INIT_63(slice_init('h63)), \ + .INIT_64(slice_init('h64)), \ + .INIT_65(slice_init('h65)), \ + .INIT_66(slice_init('h66)), \ + .INIT_67(slice_init('h67)), \ + .INIT_68(slice_init('h68)), \ + .INIT_69(slice_init('h69)), \ + .INIT_6A(slice_init('h6a)), \ + .INIT_6B(slice_init('h6b)), \ + .INIT_6C(slice_init('h6c)), \ + .INIT_6D(slice_init('h6d)), \ + .INIT_6E(slice_init('h6e)), \ + .INIT_6F(slice_init('h6f)), \ + .INIT_70(slice_init('h70)), \ + .INIT_71(slice_init('h71)), \ + .INIT_72(slice_init('h72)), \ + .INIT_73(slice_init('h73)), \ + .INIT_74(slice_init('h74)), \ + .INIT_75(slice_init('h75)), \ + .INIT_76(slice_init('h76)), \ + .INIT_77(slice_init('h77)), \ + .INIT_78(slice_init('h78)), \ + .INIT_79(slice_init('h79)), \ + .INIT_7A(slice_init('h7a)), \ + .INIT_7B(slice_init('h7b)), \ + .INIT_7C(slice_init('h7c)), \ + .INIT_7D(slice_init('h7d)), \ + .INIT_7E(slice_init('h7e)), \ + .INIT_7F(slice_init('h7f)), + +`define PARAMS_INIT_36_U \ + .INIT_00(slice_init('h80)), \ + .INIT_01(slice_init('h81)), \ + .INIT_02(slice_init('h82)), \ + .INIT_03(slice_init('h83)), \ + .INIT_04(slice_init('h84)), \ + .INIT_05(slice_init('h85)), \ + .INIT_06(slice_init('h86)), \ + .INIT_07(slice_init('h87)), \ + .INIT_08(slice_init('h88)), \ + .INIT_09(slice_init('h89)), \ + .INIT_0A(slice_init('h8a)), \ + .INIT_0B(slice_init('h8b)), \ + .INIT_0C(slice_init('h8c)), \ + .INIT_0D(slice_init('h8d)), \ + .INIT_0E(slice_init('h8e)), \ + .INIT_0F(slice_init('h8f)), \ + .INIT_10(slice_init('h90)), \ + .INIT_11(slice_init('h91)), \ + .INIT_12(slice_init('h92)), \ + .INIT_13(slice_init('h93)), \ + .INIT_14(slice_init('h94)), \ + .INIT_15(slice_init('h95)), \ + .INIT_16(slice_init('h96)), \ + .INIT_17(slice_init('h97)), \ + .INIT_18(slice_init('h98)), \ + .INIT_19(slice_init('h99)), \ + .INIT_1A(slice_init('h9a)), \ + .INIT_1B(slice_init('h9b)), \ + .INIT_1C(slice_init('h9c)), \ + .INIT_1D(slice_init('h9d)), \ + .INIT_1E(slice_init('h9e)), \ + .INIT_1F(slice_init('h9f)), \ + .INIT_20(slice_init('ha0)), \ + .INIT_21(slice_init('ha1)), \ + .INIT_22(slice_init('ha2)), \ + .INIT_23(slice_init('ha3)), \ + .INIT_24(slice_init('ha4)), \ + .INIT_25(slice_init('ha5)), \ + .INIT_26(slice_init('ha6)), \ + .INIT_27(slice_init('ha7)), \ + .INIT_28(slice_init('ha8)), \ + .INIT_29(slice_init('ha9)), \ + .INIT_2A(slice_init('haa)), \ + .INIT_2B(slice_init('hab)), \ + .INIT_2C(slice_init('hac)), \ + .INIT_2D(slice_init('had)), \ + .INIT_2E(slice_init('hae)), \ + .INIT_2F(slice_init('haf)), \ + .INIT_30(slice_init('hb0)), \ + .INIT_31(slice_init('hb1)), \ + .INIT_32(slice_init('hb2)), \ + .INIT_33(slice_init('hb3)), \ + .INIT_34(slice_init('hb4)), \ + .INIT_35(slice_init('hb5)), \ + .INIT_36(slice_init('hb6)), \ + .INIT_37(slice_init('hb7)), \ + .INIT_38(slice_init('hb8)), \ + .INIT_39(slice_init('hb9)), \ + .INIT_3A(slice_init('hba)), \ + .INIT_3B(slice_init('hbb)), \ + .INIT_3C(slice_init('hbc)), \ + .INIT_3D(slice_init('hbd)), \ + .INIT_3E(slice_init('hbe)), \ + .INIT_3F(slice_init('hbf)), \ + .INIT_40(slice_init('hc0)), \ + .INIT_41(slice_init('hc1)), \ + .INIT_42(slice_init('hc2)), \ + .INIT_43(slice_init('hc3)), \ + .INIT_44(slice_init('hc4)), \ + .INIT_45(slice_init('hc5)), \ + .INIT_46(slice_init('hc6)), \ + .INIT_47(slice_init('hc7)), \ + .INIT_48(slice_init('hc8)), \ + .INIT_49(slice_init('hc9)), \ + .INIT_4A(slice_init('hca)), \ + .INIT_4B(slice_init('hcb)), \ + .INIT_4C(slice_init('hcc)), \ + .INIT_4D(slice_init('hcd)), \ + .INIT_4E(slice_init('hce)), \ + .INIT_4F(slice_init('hcf)), \ + .INIT_50(slice_init('hd0)), \ + .INIT_51(slice_init('hd1)), \ + .INIT_52(slice_init('hd2)), \ + .INIT_53(slice_init('hd3)), \ + .INIT_54(slice_init('hd4)), \ + .INIT_55(slice_init('hd5)), \ + .INIT_56(slice_init('hd6)), \ + .INIT_57(slice_init('hd7)), \ + .INIT_58(slice_init('hd8)), \ + .INIT_59(slice_init('hd9)), \ + .INIT_5A(slice_init('hda)), \ + .INIT_5B(slice_init('hdb)), \ + .INIT_5C(slice_init('hdc)), \ + .INIT_5D(slice_init('hdd)), \ + .INIT_5E(slice_init('hde)), \ + .INIT_5F(slice_init('hdf)), \ + .INIT_60(slice_init('he0)), \ + .INIT_61(slice_init('he1)), \ + .INIT_62(slice_init('he2)), \ + .INIT_63(slice_init('he3)), \ + .INIT_64(slice_init('he4)), \ + .INIT_65(slice_init('he5)), \ + .INIT_66(slice_init('he6)), \ + .INIT_67(slice_init('he7)), \ + .INIT_68(slice_init('he8)), \ + .INIT_69(slice_init('he9)), \ + .INIT_6A(slice_init('hea)), \ + .INIT_6B(slice_init('heb)), \ + .INIT_6C(slice_init('hec)), \ + .INIT_6D(slice_init('hed)), \ + .INIT_6E(slice_init('hee)), \ + .INIT_6F(slice_init('hef)), \ + .INIT_70(slice_init('hf0)), \ + .INIT_71(slice_init('hf1)), \ + .INIT_72(slice_init('hf2)), \ + .INIT_73(slice_init('hf3)), \ + .INIT_74(slice_init('hf4)), \ + .INIT_75(slice_init('hf5)), \ + .INIT_76(slice_init('hf6)), \ + .INIT_77(slice_init('hf7)), \ + .INIT_78(slice_init('hf8)), \ + .INIT_79(slice_init('hf9)), \ + .INIT_7A(slice_init('hfa)), \ + .INIT_7B(slice_init('hfb)), \ + .INIT_7C(slice_init('hfc)), \ + .INIT_7D(slice_init('hfd)), \ + .INIT_7E(slice_init('hfe)), \ + .INIT_7F(slice_init('hff)), + +`define PARAMS_INITP_36 \ + .INITP_00(slice_initp('h00)), \ + .INITP_01(slice_initp('h01)), \ + .INITP_02(slice_initp('h02)), \ + .INITP_03(slice_initp('h03)), \ + .INITP_04(slice_initp('h04)), \ + .INITP_05(slice_initp('h05)), \ + .INITP_06(slice_initp('h06)), \ + .INITP_07(slice_initp('h07)), \ + .INITP_08(slice_initp('h08)), \ + .INITP_09(slice_initp('h09)), \ + .INITP_0A(slice_initp('h0a)), \ + .INITP_0B(slice_initp('h0b)), \ + .INITP_0C(slice_initp('h0c)), \ + .INITP_0D(slice_initp('h0d)), \ + .INITP_0E(slice_initp('h0e)), \ + .INITP_0F(slice_initp('h0f)), + +`define MAKE_DO(do, dop, rdata) \ + wire [63:0] do; \ + wire [7:0] dop; \ + assign rdata = { \ + dop[7], \ + do[63:56], \ + dop[6], \ + do[55:48], \ + dop[5], \ + do[47:40], \ + dop[4], \ + do[39:32], \ + dop[3], \ + do[31:24], \ + dop[2], \ + do[23:16], \ + dop[1], \ + do[15:8], \ + dop[0], \ + do[7:0] \ + }; + +`define MAKE_DI(di, dip, wdata) \ + wire [63:0] di; \ + wire [7:0] dip; \ + assign { \ + dip[7], \ + di[63:56], \ + dip[6], \ + di[55:48], \ + dip[5], \ + di[47:40], \ + dip[4], \ + di[39:32], \ + dip[3], \ + di[31:24], \ + dip[2], \ + di[23:16], \ + dip[1], \ + di[15:8], \ + dip[0], \ + di[7:0] \ + } = wdata; + +function [71:0] ival; + input integer width; + input [71:0] val; + if (width == 72) + ival = { + val[71], + val[62], + val[53], + val[44], + val[35], + val[26], + val[17], + val[8], + val[70:63], + val[61:54], + val[52:45], + val[43:36], + val[34:27], + val[25:18], + val[16:9], + val[7:0] + }; + else if (width == 36) + ival = { + val[35], + val[26], + val[17], + val[8], + val[34:27], + val[25:18], + val[16:9], + val[7:0] + }; + else if (width == 18) + ival = { + val[17], + val[8], + val[16:9], + val[7:0] + }; + else + ival = val; +endfunction + +function [255:0] slice_init; + input integer idx; + integer i; + for (i = 0; i < 32; i = i + 1) + slice_init[i*8+:8] = INIT[(idx * 32 + i)*9+:8]; +endfunction + +function [255:0] slice_initp; + input integer idx; + integer i; + for (i = 0; i < 256; i = i + 1) + slice_initp[i] = INIT[(idx * 256 + i)*9+8]; +endfunction diff --git a/techlibs/analogdevices/brams_map.v b/techlibs/analogdevices/brams_map.v new file mode 100644 index 000000000..f1acaaf78 --- /dev/null +++ b/techlibs/analogdevices/brams_map.v @@ -0,0 +1,238 @@ +module $__ANALOGDEVICES_BLOCKRAM_FULL_ (...); + // libmap params + parameter INIT = 0; + parameter OPTION_MODE = "NONE"; + parameter OPTION_SIZE = "NONE"; + parameter OPTION_ERR = "NONE"; + parameter PORT_A_WR_EN_WIDTH = 1; + parameter PORT_A_CLK_POL = 1; + parameter PORT_B_WR_EN_WIDTH = PORT_A_WR_EN_WIDTH; + parameter PORT_B_CLK_POL = 1; + + // needs -force-params + parameter WIDTH = 40; + parameter ABITS = 13; + + // non libmap params +`ifdef IS_T40LP + localparam NODE = "T40LP_Gen2.4"; +`endif +`ifdef IS_T16FFC + localparam NODE = "T16FFC_Gen2.4"; +`endif + // localparam BRAM_MODE = "SDP_2048x36_BP"; + localparam BRAM_MODE = (OPTION_ERR!="NONE") ? {OPTION_MODE, "_", OPTION_SIZE, "_", OPTION_ERR} : + {OPTION_MODE, "_", OPTION_SIZE}; + localparam PBITS = (OPTION_ERR=="BP") ? PORT_A_WR_EN_WIDTH : 1; + + // libmap ports + input PORT_A_CLK; + input PORT_A_CLK_EN; + input [ABITS-1:0] PORT_A_ADDR; + input [WIDTH-1:0] PORT_A_WR_DATA; + output [WIDTH-1:0] PORT_A_RD_DATA; + input [PORT_A_WR_EN_WIDTH-1:0] PORT_A_WR_EN; + + input PORT_B_CLK; + input PORT_B_CLK_EN; + input [ABITS-1:0] PORT_B_ADDR; + input [WIDTH-1:0] PORT_B_WR_DATA; + output [WIDTH-1:0] PORT_B_RD_DATA; + input [PORT_B_WR_EN_WIDTH-1:0] PORT_B_WR_EN; + +`ifdef IS_T40LP + RBRAM +`endif +`ifdef IS_T16FFC + RBRAM2 +`endif + #( + .TARGET_NODE(NODE), + .BRAM_MODE(BRAM_MODE), + .QA_REG((OPTION_ERR=="ECC") ? 1 : 0), + .QB_REG((OPTION_ERR=="ECC") ? 1 : 0), + .CLKA_INV(!PORT_A_CLK_POL), + .CLKB_INV(!PORT_B_CLK_POL), + .DATA_WIDTH(WIDTH), + .ADDR_WIDTH(ABITS), + .WE_WIDTH(PORT_A_WR_EN_WIDTH), + .PERR_WIDTH(PBITS), + ) + _TECHMAP_REPLACE_ + ( + .QA(PORT_A_RD_DATA), + .DA(PORT_A_WR_DATA), + .CEA(PORT_A_CLK_EN), + .WEA(PORT_A_WR_EN), + .AA(PORT_A_ADDR), + .CLKA(PORT_A_CLK), + .QB(PORT_B_RD_DATA), + .DB(PORT_B_WR_DATA), + .CEB(PORT_B_CLK_EN), + .WEB(PORT_B_WR_EN), + .AB(PORT_B_ADDR), + .CLKB(PORT_B_CLK), + ); + + // check config + generate + if (PORT_A_WR_EN_WIDTH == PORT_B_WR_EN_WIDTH) + case (BRAM_MODE) + `ifdef IS_T40LP + "SDP_1024x18_FP", + "SDP_1024x16_BP", + "SDP_2048x09", + "SDP_4096x05", + "SDP_1024x32_ECC", + "SDP_1024x40", + "SDP_1024x36_BP", + "SDP_512x32_ECC", + "SDP_512x36_BP", + "SDP_2048x10", + "SP_512x32_ECC", + "SP_512x36_BP", + "SP_1024x20", + "SP2_512x18_BP", + "SP2_1024x09", + "SP2_2048x05": wire _TECHMAP_FAIL_ = 0; + `endif + `ifdef IS_T16FFC + "TDP_2048x18_FP", + "TDP_2048x16_BP", + "TDP_4096x09", + "TDP_8192x05", + "TDP_2048x32_ECC", + "TDP_2048x40", + "TDP_2048x36_BP", + "SDP_2048x18_FP", + "SDP_2048x16_BP", + // The following are rejected in eXpreso + // "SDP_4096x09", + // "SDP_8192x05", + // "SDP_2048x32_ECC", + // "SDP_2048x40", + // "SDP_2048x36_BP", + "SDP_1024x32_ECC", + "SDP_1024x36_BP", + "SDP_4096x10", + "SP_1024x32_ECC", + "SP_1024x36_BP", + "SP_2048x20", + "SP2_1024x18_BP", + "SP2_2048x09", + "SP2_4096x05": wire _TECHMAP_FAIL_ = 0; + `endif + default: wire _TECHMAP_FAIL_ = 1; + endcase + else + wire _TECHMAP_FAIL_ = 1; + endgenerate + +endmodule + +module $__ANALOGDEVICES_BLOCKRAM_HALF_ (...); + // libmap params + parameter INIT = 0; + parameter OPTION_MODE = "NONE"; + parameter OPTION_SIZE = "NONE"; + parameter OPTION_ERR = "NONE"; + parameter PORT_A_WR_EN_WIDTH = 1; + parameter PORT_A_CLK_POL = 1; + parameter PORT_B_WR_EN_WIDTH = PORT_A_WR_EN_WIDTH; + parameter PORT_B_CLK_POL = 1; + + // needs -force-params + parameter WIDTH = 40; + parameter ABITS = 13; + + // libmap ports + input PORT_A_CLK; + input PORT_A_CLK_EN; + input [ABITS-1:0] PORT_A_ADDR; + input [WIDTH-1:0] PORT_A_WR_DATA; + output [WIDTH-1:0] PORT_A_RD_DATA; + input [PORT_A_WR_EN_WIDTH-1:0] PORT_A_WR_EN; + + input PORT_B_CLK; + input PORT_B_CLK_EN; + input [ABITS-1:0] PORT_B_ADDR; + input [WIDTH-1:0] PORT_B_WR_DATA; + output [WIDTH-1:0] PORT_B_RD_DATA; + input [PORT_B_WR_EN_WIDTH-1:0] PORT_B_WR_EN; + + $__ANALOGDEVICES_BLOCKRAM_FULL_ + # ( + .INIT(INIT), + .OPTION_MODE(OPTION_MODE), + .OPTION_SIZE(OPTION_SIZE), + .OPTION_ERR(OPTION_ERR), + .PORT_A_WR_EN_WIDTH(PORT_A_WR_EN_WIDTH), + .PORT_A_CLK_POL(PORT_A_CLK_POL), + .PORT_B_WR_EN_WIDTH(PORT_B_WR_EN_WIDTH), + .PORT_B_CLK_POL(PORT_B_CLK_POL), + .WIDTH(WIDTH), + .ABITS(ABITS) + ) + _TECHMAP_REPLACE_ + ( + .PORT_A_CLK(PORT_A_CLK), + .PORT_A_CLK_EN(PORT_A_CLK_EN), + .PORT_A_ADDR(PORT_A_ADDR), + .PORT_A_WR_DATA(PORT_A_WR_DATA), + .PORT_A_RD_DATA(PORT_A_RD_DATA), + .PORT_A_WR_EN(PORT_A_WR_EN), + .PORT_B_CLK(PORT_B_CLK), + .PORT_B_CLK_EN(PORT_B_CLK_EN), + .PORT_B_ADDR(PORT_B_ADDR), + .PORT_B_WR_DATA(PORT_B_WR_DATA), + .PORT_B_RD_DATA(PORT_B_RD_DATA), + .PORT_B_WR_EN(PORT_B_WR_EN) + ); +endmodule + +module $__ANALOGDEVICES_BLOCKRAM_QUARTER_ (...); + // libmap params + parameter INIT = 0; + parameter OPTION_MODE = "NONE"; + parameter OPTION_SIZE = "NONE"; + parameter OPTION_ERR = "NONE"; + parameter PORT_A_WR_EN_WIDTH = 1; + parameter PORT_A_CLK_POL = 1; + parameter PORT_B_WR_EN_WIDTH = PORT_A_WR_EN_WIDTH; + parameter PORT_B_CLK_POL = 1; + + // needs -force-params + parameter WIDTH = 40; + parameter ABITS = 13; + + // libmap ports + input PORT_A_CLK; + input PORT_A_CLK_EN; + input [ABITS-1:0] PORT_A_ADDR; + input [WIDTH-1:0] PORT_A_WR_DATA; + output [WIDTH-1:0] PORT_A_RD_DATA; + input [PORT_A_WR_EN_WIDTH-1:0] PORT_A_WR_EN; + + $__ANALOGDEVICES_BLOCKRAM_FULL_ + # ( + .INIT(INIT), + .OPTION_MODE(OPTION_MODE), + .OPTION_SIZE(OPTION_SIZE), + .OPTION_ERR(OPTION_ERR), + .PORT_A_WR_EN_WIDTH(PORT_A_WR_EN_WIDTH), + .PORT_A_CLK_POL(PORT_A_CLK_POL), + .PORT_B_WR_EN_WIDTH(PORT_B_WR_EN_WIDTH), + .PORT_B_CLK_POL(PORT_B_CLK_POL), + .WIDTH(WIDTH), + .ABITS(ABITS) + ) + _TECHMAP_REPLACE_ + ( + .PORT_A_CLK(PORT_A_CLK), + .PORT_A_CLK_EN(PORT_A_CLK_EN), + .PORT_A_ADDR(PORT_A_ADDR), + .PORT_A_WR_DATA(PORT_A_WR_DATA), + .PORT_A_RD_DATA(PORT_A_RD_DATA), + .PORT_A_WR_EN(PORT_A_WR_EN), + ); +endmodule diff --git a/techlibs/analogdevices/cells_map.v b/techlibs/analogdevices/cells_map.v new file mode 100644 index 000000000..b8d362e4f --- /dev/null +++ b/techlibs/analogdevices/cells_map.v @@ -0,0 +1,364 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module \$__SHREG_ (input C, input D, input E, output Q); + parameter DEPTH = 0; + parameter [DEPTH-1:0] INIT = 0; + parameter CLKPOL = 1; + parameter ENPOL = 2; + + \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(DEPTH-1), .E(E), .Q(Q)); +endmodule + +module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO); + parameter DEPTH = 0; + parameter [DEPTH-1:0] INIT = 0; + parameter CLKPOL = 1; + parameter ENPOL = 2; + + // shregmap's INIT parameter shifts out LSB first; + // however Analog Devices expects MSB first + function [DEPTH-1:0] brev; + input [DEPTH-1:0] din; + integer i; + begin + for (i = 0; i < DEPTH; i=i+1) + brev[i] = din[DEPTH-1-i]; + end + endfunction + localparam [DEPTH-1:0] INIT_R = brev(INIT); + + parameter _TECHMAP_CONSTMSK_L_ = 0; + + wire CE; + generate + if (ENPOL == 0) + assign CE = ~E; + else if (ENPOL == 1) + assign CE = E; + else + assign CE = 1'b1; + if (DEPTH == 1) begin + if (CLKPOL) + FFRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + else + FFRE_N #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + end else + if (DEPTH <= 16) begin + SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH > 17 && DEPTH <= 32) begin + SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH > 33 && DEPTH <= 64) begin + wire T0, T1, T2; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T2; + else + LUTMUX7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5])); + end else + if (DEPTH > 65 && DEPTH <= 96) begin + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T4; + else + \$__ANALOGDEVICES_LUTMUX78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q)); + end else + if (DEPTH > 97 && DEPTH < 128) begin + wire T0, T1, T2, T3, T4, T5, T6, T7, T8; + SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; + else + \$__ANALOGDEVICES_LUTMUX78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); + end + else if (DEPTH == 128) begin + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT_R[ 32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[ 64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[ 96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; + else + \$__ANALOGDEVICES_LUTMUX78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); + end + // For fixed length, if just 1 over a convenient value, decompose + else if (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_) begin + wire T; + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(D), .L({32{1'b1}}), .E(E), .Q(T)); + \$__XILINX_SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(T), .L(L), .E(E), .Q(Q)); + end + // For variable length, if just 1 over a convenient value, then bump up one more + else if (DEPTH < 129 && ~&_TECHMAP_CONSTMSK_L_) + \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + else begin + localparam depth0 = 128; + localparam num_srl128 = DEPTH / depth0; + localparam depthN = DEPTH % depth0; + wire [num_srl128 + (depthN > 0 ? 1 : 0) - 1:0] T; + wire [num_srl128 + (depthN > 0 ? 1 : 0) :0] S; + assign S[0] = D; + genvar i; + for (i = 0; i < num_srl128; i++) + \$__XILINX_SHREG_ #(.DEPTH(depth0), .INIT(INIT[DEPTH-1-i*depth0-:depth0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(S[i]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[i]), .SO(S[i+1])); + + if (depthN > 0) + \$__XILINX_SHREG_ #(.DEPTH(depthN), .INIT(INIT[depthN-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(S[num_srl128]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[num_srl128])); + + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T[num_srl128 + (depthN > 0 ? 1 : 0) - 1]; + else + assign Q = T[L[DEPTH-1:$clog2(depth0)]]; + end + endgenerate +endmodule + +`ifdef MIN_MUX_INPUTS +module \$__ANALOGDEVICES_SHIFTX (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] Y; + + parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; + parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + + function integer A_WIDTH_trimmed; + input integer start; + begin + A_WIDTH_trimmed = start; + while (A_WIDTH_trimmed > 0 && _TECHMAP_CONSTMSK_A_[A_WIDTH_trimmed-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH_trimmed-1] === 1'bx) + A_WIDTH_trimmed = A_WIDTH_trimmed - 1; + end + endfunction + + generate + genvar i, j; + // Bit-blast + if (Y_WIDTH > 1) begin + for (i = 0; i < Y_WIDTH; i++) + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); + end + // If the LSB of B is constant zero (and Y_WIDTH is 1) then + // we can optimise by removing every other entry from A + // and popping the constant zero from B + else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin + wire [(A_WIDTH+1)/2-1:0] A_i; + for (i = 0; i < (A_WIDTH+1)/2; i++) + assign A_i[i] = A[i*2]; + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); + end + // Trim off any leading 1'bx -es in A + else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH-1] === 1'bx) begin + localparam A_WIDTH_new = A_WIDTH_trimmed(A_WIDTH-1); + if (A_WIDTH_new == 0) + assign Y = 1'bx; + else + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B), .Y(Y)); + end + else if (A_WIDTH < `MIN_MUX_INPUTS) begin + wire _TECHMAP_FAIL_ = 1; + end + else if (A_WIDTH == 2) begin + LUTMUX7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); + end + else if (A_WIDTH <= 4) begin + wire [4-1:0] Ax; + if (A_WIDTH == 4) + assign Ax = A; + else + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" status to get lost, extend with + // the same driver of F7B.I0 so that we can optimise F7B away + // later + assign Ax = {A[1], A}; + \$__ANALOGDEVICES_LUTMUX78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); + end + // Note that the following decompositions are 'backwards' in that + // the LSBs are placed on the hard resources, and the soft resources + // are used for MSBs. + // This has the effect of more effectively utilising the hard mux; + // take for example a 5:1 multiplexer, currently this would map as: + // + // A[0] \___ __ A[0] \__ __ + // A[4] / \| \ whereas the more A[1] / \| \ + // A[1] _____| | obvious mapping A[2] \___| | + // A[2] _____| |-- of MSBs to hard A[3] / | |__ + // A[3]______| | resources would A[4] ____| | + // |__/ lead to: 1'bx ____| | + // || |__/ + // || || + // B[1:0] B[1:2] + // + // Expectation would be that the 'forward' mapping (right) is more + // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers + // on its I0 and I1 inputs, and A[8] and 1'bx on its I2 and I3 inputs) + // but that the 'backwards' mapping (left) is more delay efficient + // since smaller LUTs are faster than wider ones. + else if (A_WIDTH <= 8) begin + wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A}; + wire T0 = B[2] ? Ax[4] : Ax[0]; + wire T1 = B[2] ? Ax[5] : Ax[1]; + wire T2 = B[2] ? Ax[6] : Ax[2]; + wire T3 = B[2] ? Ax[7] : Ax[3]; + \$__ANALOGDEVICES_LUTMUX78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); + end + else if (A_WIDTH <= 16) begin + wire [16-1:0] Ax = {{{16-A_WIDTH}{1'bx}}, A}; + wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] + : B[3] ? Ax[ 8] : Ax[0]; + wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] + : B[3] ? Ax[ 9] : Ax[1]; + wire T2 = B[2] ? B[3] ? Ax[14] : Ax[6] + : B[3] ? Ax[10] : Ax[2]; + wire T3 = B[2] ? B[3] ? Ax[15] : Ax[7] + : B[3] ? Ax[11] : Ax[3]; + \$__ANALOGDEVICES_LUTMUX78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); + end + else begin + localparam num_mux16 = (A_WIDTH+15) / 16; + localparam clog2_num_mux16 = $clog2(num_mux16); + wire [num_mux16-1:0] T; + wire [num_mux16*16-1:0] Ax = {{(num_mux16*16-A_WIDTH){1'bx}}, A}; + for (i = 0; i < num_mux16; i++) + \$__ANALOGDEVICES_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(16), + .B_WIDTH(4), + .Y_WIDTH(Y_WIDTH) + ) fpga_mux ( + .A(Ax[i*16+:16]), + .B(B[3:0]), + .Y(T[i]) + ); + \$__ANALOGDEVICES_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(num_mux16), + .B_WIDTH(clog2_num_mux16), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(T), + .B(B[B_WIDTH-1-:clog2_num_mux16]), + .Y(Y)); + end + endgenerate +endmodule + +(* techmap_celltype = "$__ANALOGDEVICES_SHIFTX" *) +module _90__ANALOGDEVICES_SHIFTX (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] Y; + + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); +endmodule + +module \$_MUX_ (A, B, S, Y); + input A, B, S; + output Y; + generate + if (`MIN_MUX_INPUTS == 2) + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(2), .B_WIDTH(1), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({B,A}), .B(S), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + endgenerate +endmodule + +module \$_MUX4_ (A, B, C, D, S, T, Y); + input A, B, C, D, S, T; + output Y; + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({D,C,B,A}), .B({T,S}), .Y(Y)); +endmodule + +module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); + input A, B, C, D, E, F, G, H, S, T, U; + output Y; + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); +endmodule + +module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); + input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; + output Y; + \$__ANALOGDEVICES_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); +endmodule +`endif + +module \$__ANALOGDEVICES_LUTMUX78 (O, I0, I1, I2, I3, S0, S1); + output O; + input I0, I1, I2, I3, S0, S1; + wire T0, T1; + parameter _TECHMAP_BITS_CONNMAP_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; + else + LUTMUX7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; + else + LUTMUX7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else + LUTMUX8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); +endmodule diff --git a/techlibs/analogdevices/cells_sim.v b/techlibs/analogdevices/cells_sim.v new file mode 100644 index 000000000..2bf958d8f --- /dev/null +++ b/techlibs/analogdevices/cells_sim.v @@ -0,0 +1,1216 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module VDD(output P); + assign P = 1; +endmodule + +module GND(output G); + assign G = 0; +endmodule + +module INBUF( + output O, + (* iopad_external_pin *) + input I); + parameter CCIO_EN = "TRUE"; + parameter CAPACITANCE = "DONT_CARE"; + parameter IBUF_DELAY_VALUE = "0"; + parameter IBUF_LOW_PWR = "TRUE"; + parameter IFD_DELAY_VALUE = "AUTO"; + parameter IOSTANDARD = "DEFAULT"; + assign O = I; +`ifdef IS_T16FFC + specify + (I => O) = 42; + endspecify +`endif +`ifdef IS_T40LP + specify + (I => O) = 187; + endspecify +`endif +endmodule + +module OUTBUF( + (* iopad_external_pin *) + output O, + input I); + parameter CAPACITANCE = "DONT_CARE"; + parameter IOSTANDARD = "DEFAULT"; + parameter DRIVE = 12; + parameter SLEW = "SLOW"; + assign O = I; +`ifdef IS_T16FFC + specify + (I => O) = 42; + endspecify +`endif +`ifdef IS_T40LP + specify + (I => O) = 187; + endspecify +`endif +endmodule + +(* abc9_lut=1 *) +module LUT1(output O, input I0); + parameter [1:0] INIT = 0; + assign O = I0 ? INIT[1] : INIT[0]; +`ifdef IS_T16FFC + specify + (I0 => O) = 42; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 187; + endspecify +`endif +endmodule + +(* abc9_lut=2 *) +module LUT2(output O, input I0, I1); + parameter [3:0] INIT = 0; + wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; +`ifdef IS_T16FFC + specify + (I0 => O) = 42; + (I1 => O) = 39; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 187; + (I1 => O) = 176; + endspecify +`endif +endmodule + +(* abc9_lut=3 *) +module LUT3(output O, input I0, I1, I2); + parameter [7:0] INIT = 0; + wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; +`ifdef IS_T16FFC + specify + (I0 => O) = 54; + (I1 => O) = 51; + (I2 => O) = 48; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 249; + (I1 => O) = 238; + (I2 => O) = 227; + endspecify +`endif +endmodule + +(* abc9_lut=4 *) +module LUT4(output O, input I0, I1, I2, I3); + parameter [15:0] INIT = 0; + wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; +`ifdef IS_T16FFC + specify + (I0 => O) = 96; + (I1 => O) = 87; + (I2 => O) = 79; + (I3 => O) = 71; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 192; + (I1 => O) = 181; + (I2 => O) = 170; + (I3 => O) = 160; + endspecify +`endif +endmodule + +(* abc9_lut=5 *) +module LUT5(output O, input I0, I1, I2, I3, I4); + parameter [31:0] INIT = 0; + wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; + wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; +`ifdef IS_T16FFC + specify + (I0 => O) = 99; + (I1 => O) = 90; + (I2 => O) = 82; + (I3 => O) = 74; + (I4 => O) = 66; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 204; + (I1 => O) = 195; + (I2 => O) = 186; + (I3 => O) = 178; + (I4 => O) = 169; + endspecify +`endif +endmodule + +(* abc9_lut=6 *) +module LUT6(output O, input I0, I1, I2, I3, I4, I5); + parameter [63:0] INIT = 0; + wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; + wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; + wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; +`ifdef IS_T16FFC + specify + (I0 => O) = 42; + (I1 => O) = 39; + (I2 => O) = 36; + (I3 => O) = 33; + (I4 => O) = 30; + (I5 => O) = 28; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 185; + (I1 => O) = 176; + (I2 => O) = 165; + (I3 => O) = 155; + (I4 => O) = 144; + (I5 => O) = 134; + endspecify +`endif +endmodule + +module LUT6_D(output O6, output O5, input I0, I1, I2, I3, I4, I5); + parameter [63:0] INIT = 0; + wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; + wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; + wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O6 = I0 ? s1[1] : s1[0]; + + wire [15: 0] s5_4 = I4 ? INIT[31:16] : INIT[15: 0]; + wire [ 7: 0] s5_3 = I3 ? s5_4[15: 8] : s5_4[ 7: 0]; + wire [ 3: 0] s5_2 = I2 ? s5_3[ 7: 4] : s5_3[ 3: 0]; + wire [ 1: 0] s5_1 = I1 ? s5_2[ 3: 2] : s5_2[ 1: 0]; + assign O5 = I0 ? s5_1[1] : s5_1[0]; +endmodule + +// This is a placeholder for ABC9 to extract the area/delay +// cost of 3-input LUTs and is not intended to be instantiated +(* abc9_lut=12 *) +module \$__ABC9_LUT7 (output O, input I0, I1, I2, I3, I4, I5, I6); +`ifndef __ICARUS__ +`ifdef IS_T16FFC + specify + (I0 => O) = 42 + 111 /* LUTMUX7.I1 */; + (I1 => O) = 39 + 111 /* LUTMUX7.I1 */; + (I2 => O) = 36 + 111 /* LUTMUX7.I1 */; + (I3 => O) = 33 + 111 /* LUTMUX7.I1 */; + (I4 => O) = 30 + 111 /* LUTMUX7.I1 */; + (I5 => O) = 28 + 111 /* LUTMUX7.I1 */; + (I6 => O) = 0 + 57 /* LUTMUX7.S */; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 185 + 210 /* LUTMUX7.I0 */; + (I1 => O) = 176 + 210 /* LUTMUX7.I0 */; + (I2 => O) = 165 + 210 /* LUTMUX7.I0 */; + (I3 => O) = 155 + 210 /* LUTMUX7.I0 */; + (I4 => O) = 144 + 210 /* LUTMUX7.I0 */; + (I5 => O) = 134 + 210 /* LUTMUX7.I0 */; + (I6 => O) = 0 + 188 /* LUTMUX7.S */; + endspecify +`endif +`endif +endmodule + +// This is a placeholder for ABC9 to extract the area/delay +// cost of 3-input LUTs and is not intended to be instantiated +(* abc9_lut=24 *) +module \$__ABC9_LUT8 (output O, input I0, I1, I2, I3, I4, I5, I6, I7); +`ifndef __ICARUS__ +`ifdef IS_T16FFC + specify + (I0 => O) = 42 + 111 /* LUTMUX7.I1 */ + 59 /* LUTMUX8.I0 */; + (I1 => O) = 39 + 111 /* LUTMUX7.I1 */ + 59 /* LUTMUX8.I0 */; + (I2 => O) = 36 + 111 /* LUTMUX7.I1 */ + 59 /* LUTMUX8.I0 */; + (I3 => O) = 33 + 111 /* LUTMUX7.I1 */ + 59 /* LUTMUX8.I0 */; + (I4 => O) = 30 + 111 /* LUTMUX7.I1 */ + 59 /* LUTMUX8.I0 */; + (I5 => O) = 28 + 111 /* LUTMUX7.I1 */ + 59 /* LUTMUX8.I0 */; + (I6 => O) = 0 + 57 /* LUTMUX7.S */ + 59 /* LUTMUX8.I0 */; + (I7 => O) = 0 + 0 + 60 /* LUTMUX8.S */; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 185 + 210 /* LUTMUX7.I0 */ + 155 /* LUTMUX8.I0 */; + (I1 => O) = 176 + 210 /* LUTMUX7.I0 */ + 155 /* LUTMUX8.I0 */; + (I2 => O) = 165 + 210 /* LUTMUX7.I0 */ + 155 /* LUTMUX8.I0 */; + (I3 => O) = 155 + 210 /* LUTMUX7.I0 */ + 155 /* LUTMUX8.I0 */; + (I4 => O) = 144 + 210 /* LUTMUX7.I0 */ + 155 /* LUTMUX8.I0 */; + (I5 => O) = 134 + 210 /* LUTMUX7.I0 */ + 155 /* LUTMUX8.I0 */; + (I6 => O) = 0 + 188 /* LUTMUX7.S */ + 155 /* LUTMUX8.I0 */; + (I7 => O) = 0 + 0 + 193 /* LUTMUX8.S */; + endspecify +`endif +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module LUTMUX7(output O, input I0, I1, S); + assign O = S ? I1 : I0; +`ifdef IS_T16FFC + specify + (I0 => O) = 95; + (I1 => O) = 111; + (S => O) = 57; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 210; + (I1 => O) = 182; + (S => O) = 188; + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module LUTMUX8(output O, input I0, I1, S); + assign O = S ? I1 : I0; +`ifdef IS_T16FFC + specify + (I0 => O) = 59; + (I1 => O) = 59; + (S => O) = 60; + endspecify +`endif +`ifdef IS_T40LP + specify + (I0 => O) = 155; + (I1 => O) = 147; + (S => O) = 193; + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module CRY4( + (* abc9_carry *) + output [3:0] CO, + output [3:0] O, + (* abc9_carry *) + input CI, + input CYINIT, + input [3:0] DI, S +); + assign O = S ^ {CO[2:0], CI | CYINIT}; + assign CO[0] = S[0] ? CI | CYINIT : DI[0]; + assign CO[1] = S[1] ? CO[0] : DI[1]; + assign CO[2] = S[2] ? CO[1] : DI[2]; + assign CO[3] = S[3] ? CO[2] : DI[3]; +`ifdef IS_T16FFC + specify + (CI => CO[0]) = 69; + (DI[0] => CO[0]) = 74; + (S[0] => CO[0]) = 76; + + (CI => CO[1]) = 76; + (DI[0] => CO[1]) = 109; + (DI[1] => CO[1]) = 69; + (S[0] => CO[1]) = 99; + (S[1] => CO[1]) = 59; + + (CI => CO[2]) = 144; + (DI[0] => CO[2]) = 155; + (DI[1] => CO[2]) = 126; + (DI[2] => CO[2]) = 63; + (S[0] => CO[2]) = 168; + (S[1] => CO[2]) = 117; + (S[2] => CO[2]) = 50; + + (CI => CO[3]) = 20; + (DI[0] => CO[3]) = 167; + (DI[1] => CO[3]) = 181; + (DI[2] => CO[3]) = 173; + (DI[3] => CO[3]) = 77; + (S[0] => CO[3]) = 185; + (S[1] => CO[3]) = 182; + (S[2] => CO[3]) = 159; + (S[3] => CO[3]) = 179; + + (CI => O[0]) = 50; + (S[0] => O[0]) = 82; + + (CI => O[1]) = 61; + (DI[0] => O[1]) = 117; + (S[0] => O[1]) = 132; + (S[1] => O[1]) = 49; + + (CI => O[2]) = 148; + (DI[0] => O[2]) = 196; + (DI[1] => O[2]) = 130; + (S[0] => O[2]) = 218; + (S[1] => O[2]) = 145; + (S[2] => O[2]) = 65; + + (CI => O[3]) = 132; + (DI[0] => O[3]) = 208; + (DI[1] => O[3]) = 148; + (DI[2] => O[3]) = 110; + (S[0] => O[3]) = 204; + (S[1] => O[3]) = 160; + (S[2] => O[3]) = 97; + (S[3] => O[3]) = 39; + endspecify +`endif +`ifdef IS_T40LP + specify + (CI => CO[0]) = 132; + (DI[0] => CO[0]) = 245; + (S[0] => CO[0]) = 218; + + (CI => CO[1]) = 183; + (DI[0] => CO[1]) = 261; + (DI[1] => CO[1]) = 325; + (S[0] => CO[1]) = 270; + (S[1] => CO[1]) = 199; + + (CI => CO[2]) = 218; + (DI[0] => CO[2]) = 284; + (DI[1] => CO[2]) = 345; + (DI[2] => CO[2]) = 242; + (S[0] => CO[2]) = 334; + (S[1] => CO[2]) = 271; + (S[2] => CO[2]) = 228; + + (CI => CO[3]) = 258; + (DI[0] => CO[3]) = 334; + (DI[1] => CO[3]) = 395; + (DI[2] => CO[3]) = 342; + (DI[3] => CO[3]) = 205; + (S[0] => CO[3]) = 382; + (S[1] => CO[3]) = 321; + (S[2] => CO[3]) = 324; + (S[3] => CO[3]) = 252; + + (CI => O[0]) = 123; + (S[0] => O[0]) = 150; + + (CI => O[1]) = 265; + (DI[0] => O[1]) = 331; + (S[0] => O[1]) = 292; + (S[1] => O[1]) = 151; + + (CI => O[2]) = 288; + (DI[0] => O[2]) = 371; + (DI[1] => O[2]) = 407; + (S[0] => O[2]) = 391; + (S[1] => O[2]) = 314; + (S[2] => O[2]) = 144; + + (CI => O[3]) = 313; + (DI[0] => O[3]) = 388; + (DI[1] => O[3]) = 432; + (DI[2] => O[3]) = 335; + (S[0] => O[3]) = 418; + (S[1] => O[3]) = 357; + (S[2] => O[3]) = 331; + (S[3] => O[3]) = 145; + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module CRY4INIT( + (* abc9_carry *) + output CO, + (* abc9_carry *) + input CYINIT +); + assign CO = CYINIT; +`ifdef IS_T16FFC + specify + (CYINIT => CO) = 77; + endspecify +`endif +`ifdef IS_T40LP + specify + (CYINIT => CO) = 205; + endspecify +`endif +endmodule + +// Flip-flops. + +(* abc9_flop, lib_whitebox *) +module FFRE ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input D, + input R +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @(posedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D , posedge C, 65); + $setup(CE, posedge C, 63); + $setup(R , posedge C, 63); + if (R) (posedge C => (Q : 1'b0)) = 291; + if (!R && CE) (posedge C => (Q : D)) = 291; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D , posedge C, 144); + $setup(CE, posedge C, 412); + $setup(R , posedge C, 667); + if (R) (posedge C => (Q : 1'b0)) = 712; + if (!R && CE) (posedge C => (Q : D)) = 712; + endspecify +`endif +endmodule + +(* abc9_flop, lib_whitebox *) +module FFRE_N ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input D, + input R +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D , negedge C, 65); + $setup(CE, negedge C, 63); + $setup(R , negedge C, 63); + if (R) (negedge C => (Q : 1'b0)) = 291; + if (!R && CE) (negedge C => (Q : D)) = 291; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D , negedge C, 144); + $setup(CE, negedge C, 412); + $setup(R , negedge C, 667); + if (R) (negedge C => (Q : 1'b0)) = 712; + if (!R && CE) (negedge C => (Q : D)) = 712; + endspecify +`endif +endmodule + +(* abc9_flop, lib_whitebox *) +module FFSE ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input D, + input S +); + parameter [0:0] INIT = 1'b1; + initial Q = INIT; + always @(posedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D , posedge C, 65); + $setup(CE, posedge C, 63); + $setup(S , posedge C, 63); + if (S) (posedge C => (Q : 1'b1)) = 265; + if (!S && CE) (posedge C => (Q : D)) = 265; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D , posedge C, 144); + $setup(CE, posedge C, 412); + $setup(S , posedge C, 689); + if (S) (posedge C => (Q : 1'b1)) = 693; + if (!S && CE) (posedge C => (Q : D)) = 693; + endspecify +`endif +endmodule + +(* abc9_flop, lib_whitebox *) +module FFSE_N ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input D, + input S +); + parameter [0:0] INIT = 1'b1; + initial Q = INIT; + always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D , negedge C, 65); + $setup(CE, negedge C, 63); + $setup(S , negedge C, 63); + if (S) (negedge C => (Q : 1'b1)) = 265; + if (!S && CE) (negedge C => (Q : D)) = 265; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D , negedge C, 144); + $setup(CE, negedge C, 412); + $setup(S , negedge C, 689); + if (S) (negedge C => (Q : 1'b1)) = 693; + if (!S && CE) (negedge C => (Q : D)) = 693; + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module FFCE ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input CLR, + input D +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D , posedge C, 65); + $setup(CE, posedge C, 64); + $setup(CLR, posedge C, 64); + if (!CLR && CE) (posedge C => (Q : D)) = 192; +`ifdef YOSYS + if (CLR) (CLR => Q) = 192; +`endif + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D , posedge C, 140); + $setup(CE, posedge C, 412); + $setup(CLR, posedge C, 6); + if (!CLR && CE) (posedge C => (Q : D)) = 55; +`ifdef YOSYS + if (CLR) (CLR => Q) = 55; +`endif + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module FFCE_N ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input CLR, + input D +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D, negedge C, 65); + $setup(CE, negedge C, 64); + $setup(CLR, negedge C, 64); + if (!CLR && CE) (negedge C => (Q : D)) = 192; +`ifdef YOSYS + if (CLR) (CLR => Q) = 192; +`endif + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D, negedge C, 140); + $setup(CE, negedge C, 412); + $setup(CLR, negedge C, 6); + if (!CLR && CE) (negedge C => (Q : D)) = 55; +`ifdef YOSYS + if (CLR) (CLR => Q) = 55; +`endif + endspecify +`endif +endmodule + +module FFPE ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input PRE, + input D +); + parameter [0:0] INIT = 1'b1; + initial Q = INIT; + always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D, posedge C, 65); + $setup(CE, posedge C, 65); + $setup(PRE, posedge C, 65); + if (!PRE && CE) (posedge C => (Q : D)) = 191; +`ifdef YOSYS + if (PRE) (PRE => Q) = 191; +`endif + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D, posedge C, 140); + $setup(CE, posedge C, 412); + $setup(PRE, posedge C, 6); + if (!PRE && CE) (posedge C => (Q : D)) = 55; +`ifdef YOSYS + if (PRE) (PRE => Q) = 55; +`endif + endspecify +`endif +endmodule + +module FFPE_N ( + output reg Q, + (* clkbuf_sink *) + input C, + input CE, + input PRE, + input D +); + parameter [0:0] INIT = 1'b1; + initial Q = INIT; + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; +`ifdef IS_T16FFC + specify + $setup(D, negedge C, 64); + $setup(CE, negedge C, 64); + $setup(PRE, negedge C, 64); + if (!PRE && CE) (negedge C => (Q : D)) = 291; +`ifdef YOSYS + if (PRE) (PRE => Q) = 333; +`endif + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(D, negedge C, 89); + $setup(CE, negedge C, 89); + $setup(PRE, negedge C, 89); + if (!PRE && CE) (negedge C => (Q : D)) = 712; +`ifdef YOSYS + if (PRE) (PRE => Q) = 57; +`endif + endspecify +`endif +endmodule + +// LUTRAM. + +// Single port. + +(* abc9_box, lib_whitebox *) +module RAMS32X1 ( + output O, + input A0, A1, A2, A3, A4, + input D, + (* clkbuf_sink *) + input WCLK, + input WE +); + parameter [31:0] INIT = 32'h00000000; + wire [4:0] a = {A4, A3, A2, A1, A0}; + reg [31:0] mem = INIT; + assign O = mem[a]; + always @(posedge WCLK) if (WE) mem[a] <= D; +`ifdef IS_T16FFC + specify + $setup(A0, posedge WCLK, 62); + $setup(A1, posedge WCLK, 62); + $setup(A2, posedge WCLK, 62); + $setup(A3, posedge WCLK, 62); + $setup(A4, posedge WCLK, 62); + $setup(D, posedge WCLK, 62); + $setup(WE, posedge WCLK, 62); + (A0 => O) = 100; + (A1 => O) = 91; + (A2 => O) = 83; + (A3 => O) = 75; + (A4 => O) = 67; + (posedge WCLK => (O : D)) = 807; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(A0, posedge WCLK, 198); + $setup(A1, posedge WCLK, 198); + $setup(A2, posedge WCLK, 198); + $setup(A3, posedge WCLK, 198); + $setup(A4, posedge WCLK, 198); + $setup(D, posedge WCLK, 198); + $setup(WE, posedge WCLK, 198); + (A0 => O) = 211; + (A1 => O) = 202; + (A2 => O) = 193; + (A3 => O) = 185; + (A4 => O) = 176; + (posedge WCLK => (O : D)) = 1586; + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module RAMS64X1 ( + output O, + input A0, A1, A2, A3, A4, A5, + input D, + (* clkbuf_sink *) + input WCLK, + input WE +); + parameter [63:0] INIT = 64'h0000000000000000; + wire [5:0] a = {A5, A4, A3, A2, A1, A0}; + reg [63:0] mem = INIT; + assign O = mem[a]; + always @(posedge WCLK) if (WE) mem[a] <= D; +`ifdef IS_T16FFC + specify + $setup(A0, posedge WCLK, 65); + $setup(A1, posedge WCLK, 65); + $setup(A2, posedge WCLK, 65); + $setup(A3, posedge WCLK, 65); + $setup(A4, posedge WCLK, 65); + $setup(A5, posedge WCLK, 65); + $setup(D, posedge WCLK, 65); + $setup(WE, posedge WCLK, 65); + (A0 => O) = 184; + (A1 => O) = 175; + (A2 => O) = 167; + (A3 => O) = 159; + (A4 => O) = 151; + (A5 => O) = 61; + (posedge WCLK => (O : D)) = 747; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(A0, posedge WCLK, 224); + $setup(A1, posedge WCLK, 224); + $setup(A2, posedge WCLK, 224); + $setup(A3, posedge WCLK, 224); + $setup(A4, posedge WCLK, 224); + $setup(A5, posedge WCLK, 224); + $setup(D, posedge WCLK, 224); + $setup(WE, posedge WCLK, 224); + (A0 => O) = 509; + (A1 => O) = 500; + (A2 => O) = 491; + (A3 => O) = 483; + (A4 => O) = 474; + (A5 => O) = 187; + (posedge WCLK => (O : D)) = 1730; + endspecify +`endif +endmodule + +// Dual port. + +(* abc9_box, lib_whitebox *) +module RAMD32X1 ( + output DPO, SPO, + input D, + (* clkbuf_sink *) + input WCLK, + input WE, + input A0, A1, A2, A3, A4, + input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 +); + parameter INIT = 32'h0; + wire [4:0] a = {A4, A3, A2, A1, A0}; + wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}; + reg [31:0] mem = INIT; + assign SPO = mem[a]; + assign DPO = mem[dpra]; + always @(posedge WCLK) if (WE) mem[a] <= D; +`ifdef IS_T16FFC + specify + $setup(A0, posedge WCLK, 62); + $setup(A1, posedge WCLK, 62); + $setup(A2, posedge WCLK, 62); + $setup(A3, posedge WCLK, 62); + $setup(A4, posedge WCLK, 62); + $setup(D, posedge WCLK, 62); + $setup(WE, posedge WCLK, 62); + (A0 => SPO) = 100; + (A1 => SPO) = 91; + (A2 => SPO) = 83; + (A3 => SPO) = 75; + (A4 => SPO) = 67; + (DPRA0 => DPO) = 101; + (DPRA1 => DPO) = 92; + (DPRA2 => DPO) = 84; + (DPRA3 => DPO) = 76; + (DPRA4 => DPO) = 68; + (posedge WCLK => (SPO : D)) = 807; + (posedge WCLK => (DPO : D)) = 807; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(A0, posedge WCLK, 198); + $setup(A1, posedge WCLK, 198); + $setup(A2, posedge WCLK, 198); + $setup(A3, posedge WCLK, 198); + $setup(A4, posedge WCLK, 198); + $setup(D, posedge WCLK, 198); + $setup(WE, posedge WCLK, 198); + (A0 => SPO) = 211; + (A1 => SPO) = 202; + (A2 => SPO) = 193; + (A3 => SPO) = 185; + (A4 => SPO) = 176; + (DPRA0 => DPO) = 185; + (DPRA1 => DPO) = 176; + (DPRA2 => DPO) = 167; + (DPRA3 => DPO) = 159; + (DPRA4 => DPO) = 150; + (posedge WCLK => (SPO : D)) = 1586; + (posedge WCLK => (DPO : D)) = 1586; + endspecify +`endif +endmodule + +(* abc9_box, lib_whitebox *) +module RAMD64X1 ( + output DPO, SPO, + input D, + (* clkbuf_sink *) + input WCLK, + input WE, + input A0, A1, A2, A3, A4, A5, + input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 +); + parameter INIT = 64'h0; + wire [5:0] a = {A5, A4, A3, A2, A1, A0}; + wire [5:0] dpra = {DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}; + reg [63:0] mem = INIT; + assign SPO = mem[a]; + assign DPO = mem[dpra]; + always @(posedge WCLK) if (WE) mem[a] <= D; +`ifdef IS_T16FFC + specify + $setup(A0, posedge WCLK, 65); + $setup(A1, posedge WCLK, 65); + $setup(A2, posedge WCLK, 65); + $setup(A3, posedge WCLK, 65); + $setup(A4, posedge WCLK, 65); + $setup(A5, posedge WCLK, 65); + $setup(D, posedge WCLK, 65); + $setup(WE, posedge WCLK, 65); + (A0 => SPO) = 184; + (A1 => SPO) = 175; + (A2 => SPO) = 167; + (A3 => SPO) = 159; + (A4 => SPO) = 151; + (A5 => SPO) = 61; + (DPRA0 => DPO) = 164; + (DPRA1 => DPO) = 155; + (DPRA2 => DPO) = 147; + (DPRA3 => DPO) = 139; + (DPRA4 => DPO) = 131; + (DPRA5 => DPO) = 64; + (posedge WCLK => (SPO : D)) = 761; + (posedge WCLK => (DPO : D)) = 733; + endspecify +`endif +`ifdef IS_T40LP + specify + $setup(A0, posedge WCLK, 224); + $setup(A1, posedge WCLK, 224); + $setup(A2, posedge WCLK, 224); + $setup(A3, posedge WCLK, 224); + $setup(A4, posedge WCLK, 224); + $setup(A5, posedge WCLK, 224); + $setup(D, posedge WCLK, 224); + $setup(WE, posedge WCLK, 224); + (A0 => SPO) = 509; + (A1 => SPO) = 500; + (A2 => SPO) = 491; + (A3 => SPO) = 483; + (A4 => SPO) = 474; + (A5 => SPO) = 187; + (DPRA0 => DPO) = 531; + (DPRA1 => DPO) = 522; + (DPRA2 => DPO) = 513; + (DPRA3 => DPO) = 505; + (DPRA4 => DPO) = 496; + (DPRA5 => DPO) = 199; + (posedge WCLK => (SPO : D)) = 1798; + (posedge WCLK => (DPO : D)) = 1807; + endspecify +`endif +endmodule + +// Shift registers. + +(* abc9_box, lib_whitebox *) +module SRG16E ( + output Q, + input A0, A1, A2, A3, CE, + (* clkbuf_sink *) + input CLK, + input D +); + parameter [15:0] INIT = 16'h0000; + + reg [15:0] r = INIT; + assign Q = r[{A3,A2,A1,A0}]; + always @(posedge CLK) if (CE) r <= { r[14:0], D }; + specify + $setup(D , posedge CLK, 173); + if (CE) (posedge CLK => (Q : D)) = 1472; + if (CE) (posedge CLK => (Q : 1'bx)) = 1472; + (A0 => Q) = 631; + (A1 => Q) = 472; + (A2 => Q) = 407; + (A3 => Q) = 238; + endspecify +endmodule + +// DSP + +(* abc9_box *) +module RBBDSP ( + output [21:0] AO_LOC, + output [21:0] BO_LOC, + output CE_O, + output [1:0] CO_LOC, + output [47:0] DO_LOC, + output [1:0] OPCODE_O, + output [47:0] P, + output [47:0] PO_LOC, + output RST_O, + + input [1:0] CI_LOC, + input [1:0] OPCODE, + input [1:0] OPCODE_I, + input [21:0] A, + input [21:0] AI_LOC, + input [21:0] B, + input [21:0] BI_LOC, + input [47:0] D, + input [47:0] DI_LOC, + input [47:0] PI_LOC, + input CE, + input CE_I, + (* clkbuf_sink *) + input CLK, + input CHIP_RST, + input RST_I, + input RST +); + +parameter AI_SEL_IN = 1'b0; +parameter [1:0] BC_CI = 2'b00; +parameter BI_SEL = 1'b0; +parameter BI_SEL_IN = 1'b0; +parameter CE_A = 1'b0; +parameter CE_ADD = 1'b0; +parameter CE_B = 1'b0; +parameter CE_C = 1'b0; +parameter CE_CRY = 1'b0; +parameter [1:0] CE_D = 2'b0; +parameter CE_M = 1'b0; +parameter CE_OPCODE = 1'b0; +parameter CE_PADD = 1'b0; +parameter CE_RST = 1'b1; +parameter CE_SEL = 1'b0; +parameter CE_SFT = 1'b0; +parameter [3:0] CI_SEL = 4'b0011; +parameter DI_SEL = 1'b0; +parameter DI_SEL_IN = 1'b0; +parameter OPCODE_SEL = 1'b0; +parameter [9:0] OP_ADD = 10'b0; +parameter OP_CPLX = 1'b0; +parameter [1:0] OP_MULT = 2'b11; +parameter [9:0] OP_PADD = 10'b0; +parameter [5:0] OP_SFT = 6'b0; +parameter [3:0] OP_X = 4'b1010; +parameter [3:0] OP_Y = 4'b0101; +parameter [3:0] OP_Z = 4'b0000; +parameter PO_LOC_SEL = 1'b1; +parameter PO_NWK_SEL = 1'b1; +parameter REG_A = 1'b0; +parameter REG_ADD = 1'b0; +parameter REG_B = 1'b0; +parameter REG_C = 1'b0; +parameter REG_CRY = 1'b0; +parameter [1:0] REG_D = 2'b0; +parameter REG_M = 1'b0; +parameter REG_OPCODE = 1'b0; +parameter REG_PADD = 1'b0; +parameter REG_SFT = 1'b0; +parameter RST_SEL = 1'b0; +parameter FF_SYNC_RST = 1'b0; + +specify + if (!REG_A) (A *> P) = 1000; + if (!REG_B) (B *> P) = 1000; + if (!REG_D) (D *> P) = 1000; +endspecify + +// Much of this functionality is TODO. + +assign P = $signed(A) * $signed(B); + +endmodule + +// Block RAM + +module RBRAM #( + parameter TARGET_NODE = "T40LP_Gen2.4", + parameter BRAM_MODE = "SDP_1024x40", + parameter QA_REG = 0, + parameter QB_REG = 0, + parameter CLKA_INV = 0, + parameter CLKB_INV = 0, + parameter DATA_WIDTH = 40, + parameter ADDR_WIDTH = 12, + parameter WE_WIDTH = 20, + parameter PERR_WIDTH = 4 +) ( + output [DATA_WIDTH-1:0] QA, + input [DATA_WIDTH-1:0] DA, + input CEA, + input [WE_WIDTH-1:0] WEA, + input [ADDR_WIDTH-1:0] AA, + (* clkbuf_sink *) + (* invertible_pin = "CLKA_INV" *) + input CLKA, + output [DATA_WIDTH-1:0] QB, + input [DATA_WIDTH-1:0] DB, + input CEB, + input [WE_WIDTH-1:0] WEB, + input [ADDR_WIDTH-1:0] AB, + (* clkbuf_sink *) + (* invertible_pin = "CLKB_INV" *) + input CLKB, + output reg [PERR_WIDTH-1:0] PERRA, + output reg [PERR_WIDTH-1:0] PERRB, + output SBEA, + output SBEB, + output MBEA, + output MBEB, + input SLP, + input PD +); + +// Timings simplified for now +specify + $setup(DA, posedge CLKA, 715); + $setup(CEA, posedge CLKA, 414); + $setup(AA, posedge CLKA, 624); + + $setup(DB, posedge CLKB, 744); + $setup(CEB, posedge CLKB, 350); + $setup(AB, posedge CLKB, 643); + + (posedge CLKA => (QA : DA)) = 2380; + (posedge CLKB => (QB : DB)) = 2289; +endspecify + +endmodule + +module RBRAM2 #( + parameter TARGET_NODE = "T16FFC_Gen2.4", + parameter BRAM_MODE = "SDP_2048x40", + parameter QA_REG = 0, + parameter QB_REG = 0, + parameter CLKA_INV = 0, + parameter CLKB_INV = 0, + parameter DATA_WIDTH = 40, + parameter ADDR_WIDTH = 13, + parameter WE_WIDTH = 20, + parameter PERR_WIDTH = 4 +) ( + output [DATA_WIDTH-1:0] QA, + input [DATA_WIDTH-1:0] DA, + input CEA, + input [WE_WIDTH-1:0] WEA, + input [ADDR_WIDTH-1:0] AA, + (* clkbuf_sink *) + (* invertible_pin = "CLKA_INV" *) + input CLKA, + output [DATA_WIDTH-1:0] QB, + input [DATA_WIDTH-1:0] DB, + input CEB, + input [WE_WIDTH-1:0] WEB, + input [ADDR_WIDTH-1:0] AB, + (* clkbuf_sink *) + (* invertible_pin = "CLKB_INV" *) + input CLKB, + output reg [PERR_WIDTH-1:0] PERRA, + output reg [PERR_WIDTH-1:0] PERRB, + output SBEA, + output SBEB, + output MBEA, + output MBEB, + input SLP, + input PD +); + +// Timings simplified for now +specify + $setup(DA, posedge CLKA, 2440); + $setup(CEA, posedge CLKA, 1668); + $setup(AA, posedge CLKA, 2289); + + $setup(DB, posedge CLKB, 2420); + $setup(CEB, posedge CLKB, 1805); + $setup(AB, posedge CLKB, 2170); + + (posedge CLKA => (QA : DA)) = 2227; + (posedge CLKB => (QB : DB)) = 2189; +endspecify + +endmodule diff --git a/techlibs/analogdevices/dsp_map.v b/techlibs/analogdevices/dsp_map.v new file mode 100644 index 000000000..6f4b0822b --- /dev/null +++ b/techlibs/analogdevices/dsp_map.v @@ -0,0 +1,60 @@ +module \$__MUL22X22 (input [21:0] A, input [21:0] B, output [43:0] Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + + wire [47:0] P_48; + RBBDSP #( + // Disable all registers + .AI_SEL_IN(1'b0), + .BC_CI(2'b00), + .BI_SEL(1'b0), + .BI_SEL_IN(1'b0), + .CE_A(1'b0), + .CE_ADD(1'b0), + .CE_B(1'b0), + .CE_C(1'b0), + .CE_CRY(1'b0), + .CE_D(2'b0), + .CE_M(1'b0), + .CE_OPCODE(1'b0), + .CE_PADD(1'b0), + .CE_RST(1'b1), + .CE_SEL(1'b0), + .CE_SFT(1'b0), + .CI_SEL(4'd3), + .DI_SEL(1'b0), + .DI_SEL_IN(1'b0), + .OPCODE_SEL(1'b0), + .OP_ADD(10'b0), + .OP_CPLX(1'b0), + .OP_MULT(2'b11), + .OP_PADD(10'b0000000000), + .OP_SFT(6'b000000), + .OP_X(4'b1010), + .OP_Y(4'b0101), + .OP_Z(4'b0000), + .PO_LOC_SEL(1'b1), + .PO_NWK_SEL(1'b1), + .REG_A(1'b0), + .REG_ADD(1'b0), + .REG_B(1'b0), + .REG_C(1'b0), + .REG_CRY(1'b0), + .REG_D(2'b0), + .REG_M(1'b0), + .REG_OPCODE(1'b0), + .REG_PADD(1'b0), + .REG_SFT(1'b0), + .RST_SEL(1'b0), + .FF_SYNC_RST(1'b0), + ) _TECHMAP_REPLACE_ ( + .P(P_48), + .A(A), + .B(B), + .D(48'b0) + ); + assign Y = P_48; +endmodule diff --git a/techlibs/analogdevices/ff_map.v b/techlibs/analogdevices/ff_map.v new file mode 100644 index 000000000..0be742b49 --- /dev/null +++ b/techlibs/analogdevices/ff_map.v @@ -0,0 +1,63 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`ifndef _NO_FFS + +// Async reset, enable. + +module \$_DFFE_NP0P_ (input D, C, E, R, output Q); + FFCE_N #(.INIT(1'b0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule +module \$_DFFE_PP0P_ (input D, C, E, R, output Q); + FFCE #(.INIT(1'b0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +module \$_DFFE_NP1P_ (input D, C, E, R, output Q); + FFPE_N #(.INIT(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule +module \$_DFFE_PP1P_ (input D, C, E, R, output Q); + FFPE #(.INIT(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +// Sync reset, enable. + +module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); + FFRE_N #(.INIT(1'b0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule +module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); + FFRE #(.INIT(1'b0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +module \$_SDFFE_NP1P_ (input D, C, E, R, output Q); + FFSE_N #(.INIT(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule +module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); + FFSE #(.INIT(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S(R)); + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +`endif + diff --git a/techlibs/analogdevices/lut_map.v b/techlibs/analogdevices/lut_map.v new file mode 100644 index 000000000..832b5cbfb --- /dev/null +++ b/techlibs/analogdevices/lut_map.v @@ -0,0 +1,79 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// ============================================================================ +// LUT mapping + +`ifndef _NO_LUTS + +module \$lut (A, Y); + parameter WIDTH = 0; + parameter LUT = 0; + + (* force_downto *) + input [WIDTH-1:0] A; + output Y; + + generate + if (WIDTH == 1) begin + LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0])); + end else + if (WIDTH == 2) begin + LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1])); + end else + if (WIDTH == 3) begin + LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2])); + end else + if (WIDTH == 4) begin + LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3])); + end else + if (WIDTH == 5) begin + LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4])); + end else + if (WIDTH == 6) begin + LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + end else + if (WIDTH == 7) begin + wire f0, f1; + \$lut #(.LUT(LUT[ 63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0)); + \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1)); + LUTMUX7 mux7(.I0(f0), .I1(f1), .S(A[6]), .O(Y)); + end else + if (WIDTH == 8) begin + wire f0, f1; + \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0)); + \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1)); + LUTMUX8 mux8 (.I0(f0), .I1(f1), .S(A[7]), .O(Y)); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate +endmodule + +`endif + diff --git a/techlibs/analogdevices/lutrams.txt b/techlibs/analogdevices/lutrams.txt new file mode 100644 index 000000000..c391cdb43 --- /dev/null +++ b/techlibs/analogdevices/lutrams.txt @@ -0,0 +1,20 @@ +ram distributed $__ANALOGDEVICES_LUTRAM_ { + option "SIZE" 32 abits 5; + option "SIZE" 64 abits 6; + width 1; + init no_undef; + prune_rom; + port arsw "RW" { + clock posedge; + } + option "MODE" "SP" { + option "SIZE" 32 cost 2; + option "SIZE" 64 cost 2; + } + option "MODE" "DP" { + option "SIZE" 32 cost 4; + option "SIZE" 64 cost 8; + port ar "R" { + } + } +} diff --git a/techlibs/analogdevices/lutrams_map.v b/techlibs/analogdevices/lutrams_map.v new file mode 100644 index 000000000..18fa93516 --- /dev/null +++ b/techlibs/analogdevices/lutrams_map.v @@ -0,0 +1,139 @@ +module $__ANALOGDEVICES_LUTRAM_ (...); + +parameter INIT = 0; +parameter OPTION_SIZE = 32; +parameter OPTION_MODE = "SP"; +parameter ABITS = 5; +parameter WIDTH = 1; + +output PORT_RW_RD_DATA; +input PORT_RW_WR_DATA; +input [ABITS-1:0] PORT_RW_ADDR; +input PORT_RW_WR_EN; +input PORT_RW_CLK; + +output PORT_R_RD_DATA; +input [ABITS-1:0] PORT_R_ADDR; + +generate + if (OPTION_MODE=="SP") + case(OPTION_SIZE) + 32: + RAMS32X1 + #( + .INIT(INIT) + ) + _TECHMAP_REPLACE_ + ( + .O(PORT_RW_RD_DATA), + .A0(PORT_RW_ADDR[0]), + .A1(PORT_RW_ADDR[1]), + .A2(PORT_RW_ADDR[2]), + .A3(PORT_RW_ADDR[3]), + .A4(PORT_RW_ADDR[4]), + .D(PORT_RW_WR_DATA), + .WCLK(PORT_RW_CLK), + .WE(PORT_RW_WR_EN) + ); + 64: + RAMS64X1 + #( + .INIT(INIT) + ) + _TECHMAP_REPLACE_ + ( + .O(PORT_RW_RD_DATA), + .A0(PORT_RW_ADDR[0]), + .A1(PORT_RW_ADDR[1]), + .A2(PORT_RW_ADDR[2]), + .A3(PORT_RW_ADDR[3]), + .A4(PORT_RW_ADDR[4]), + .A5(PORT_RW_ADDR[5]), + .D(PORT_RW_WR_DATA), + .WCLK(PORT_RW_CLK), + .WE(PORT_RW_WR_EN) + ); + default: + $error("invalid SIZE/MODE combination"); + endcase + else if (OPTION_MODE=="DP") + case (OPTION_SIZE) + 32: + RAMD32X1 + #( + .INIT(INIT) + ) + _TECHMAP_REPLACE_ + ( + .DPO(PORT_R_RD_DATA), + .SPO(PORT_RW_RD_DATA), + .A0(PORT_RW_ADDR[0]), + .A1(PORT_RW_ADDR[1]), + .A2(PORT_RW_ADDR[2]), + .A3(PORT_RW_ADDR[3]), + .A4(PORT_RW_ADDR[4]), + .D(PORT_RW_WR_DATA), + .DPRA0(PORT_R_ADDR[0]), + .DPRA1(PORT_R_ADDR[1]), + .DPRA2(PORT_R_ADDR[2]), + .DPRA3(PORT_R_ADDR[3]), + .DPRA4(PORT_R_ADDR[4]), + .WCLK(PORT_RW_CLK), + .WE(PORT_RW_WR_EN) + ); + 64: + RAMD64X1 + #( + .INIT(INIT) + ) + _TECHMAP_REPLACE_ + ( + .DPO(PORT_R_RD_DATA), + .SPO(PORT_RW_RD_DATA), + .A0(PORT_RW_ADDR[0]), + .A1(PORT_RW_ADDR[1]), + .A2(PORT_RW_ADDR[2]), + .A3(PORT_RW_ADDR[3]), + .A4(PORT_RW_ADDR[4]), + .A5(PORT_RW_ADDR[5]), + .D(PORT_RW_WR_DATA), + .DPRA0(PORT_R_ADDR[0]), + .DPRA1(PORT_R_ADDR[1]), + .DPRA2(PORT_R_ADDR[2]), + .DPRA3(PORT_R_ADDR[3]), + .DPRA4(PORT_R_ADDR[4]), + .DPRA5(PORT_R_ADDR[5]), + .WCLK(PORT_RW_CLK), + .WE(PORT_RW_WR_EN) + ); + default: + $error("invalid SIZE/MODE combination"); + endcase + else + wire _TECHMAP_FAIL_ = 1; +endgenerate + +endmodule + + +module $__ANALOGDEVICES_LUTRAM_DP_ (...); + +parameter INIT = 0; +parameter OPTION_SIZE = 32; +parameter ABITS = 5; +parameter WIDTH = 1; + +output PORT_RW_RD_DATA; +input PORT_RW_WR_DATA; +input [ABITS-1:0] PORT_RW_ADDR; +input PORT_RW_WR_EN; +input PORT_RW_CLK; + +output PORT_R_RD_DATA; +input [ABITS-1:0] PORT_R_ADDR; + +generate + +endgenerate + +endmodule diff --git a/techlibs/analogdevices/mux_map.v b/techlibs/analogdevices/mux_map.v new file mode 100644 index 000000000..7fa45cb54 --- /dev/null +++ b/techlibs/analogdevices/mux_map.v @@ -0,0 +1,74 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// The purpose of these mapping rules is to allow preserve all (sufficiently +// wide) $shiftx cells during 'techmap' so that they can be mapped to hard +// resources, rather than being bit-blasted to gates during 'techmap' +// execution + +module \$shiftx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] Y; + + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + + generate + if (B_SIGNED) begin + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + \$shiftx #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(0), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH-1'd1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), .B(B[B_WIDTH-2:0]), .Y(Y) + ); + else + wire _TECHMAP_FAIL_ = 1; + end + else begin + if (((A_WIDTH + Y_WIDTH - 1) / Y_WIDTH) < `MIN_MUX_INPUTS) + wire _TECHMAP_FAIL_ = 1; + else + \$__ANALOGDEVICES_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), .B(B), .Y(Y) + ); + end + endgenerate +endmodule diff --git a/techlibs/analogdevices/retarget_map.v b/techlibs/analogdevices/retarget_map.v new file mode 100644 index 000000000..a9712219f --- /dev/null +++ b/techlibs/analogdevices/retarget_map.v @@ -0,0 +1,49 @@ +module FF (input C, D, output Q); +parameter INIT = 1'b0; +if (INIT === 1'b1) begin +FFPE _TECHMAP_REPLACE_ (.C(C), .D(D), .PRE(1'b0), .CE(1'b1), .Q(Q)); +end else begin +FFCE _TECHMAP_REPLACE_ (.C(C), .D(D), .CLR(1'b0), .CE(1'b1), .Q(Q)); +end +endmodule + +module FF_N (input C, D, output Q); +parameter INIT = 1'b0; +if (INIT === 1'b1) begin +FFPE_N _TECHMAP_REPLACE_ (.C(C), .D(D), .PRE(1'b0), .CE(1'b1), .Q(Q)); +end else begin +FFCE_N _TECHMAP_REPLACE_ (.C(C), .D(D), .CLR(1'b0), .CE(1'b1), .Q(Q)); +end +endmodule + +module FFC (input C, D, CLR, output Q); +FFCE _TECHMAP_REPLACE_ (.C(C), .D(D), .CLR(CLR), .CE(1'b1), .Q(Q)); +endmodule + +module FFC_N (input C, D, CLR, output Q); +FFCE_N _TECHMAP_REPLACE_ (.C(C), .D(D), .CLR(CLR), .CE(1'b1), .Q(Q)); +endmodule + +module FFP (input C, D, PRE, output Q); +FFPE _TECHMAP_REPLACE_ (.C(C), .D(D), .PRE(PRE), .CE(1'b1), .Q(Q)); +endmodule + +module FFP_N (input C, D, CLR, output Q); +FFPE_N _TECHMAP_REPLACE_ (.C(C), .D(D), .PRE(PRE), .CE(1'b1), .Q(Q)); +endmodule + +module FFR (input C, D, R, output Q); +FFRE _TECHMAP_REPLACE_ (.C(C), .D(D), .R(R), .CE(1'b1), .Q(Q)); +endmodule + +module FFR_N (input C, D, R, output Q); +FFRE_N _TECHMAP_REPLACE_ (.C(C), .D(D), .R(R), .CE(1'b1), .Q(Q)); +endmodule + +module FFS (input C, D, S, output Q); +FFSE _TECHMAP_REPLACE_ (.C(C), .D(D), .S(S), .CE(1'b1), .Q(Q)); +endmodule + +module FFS_N (input C, D, S, output Q); +FFSE_N _TECHMAP_REPLACE_ (.C(C), .D(D), .S(S), .CE(1'b1), .Q(Q)); +endmodule diff --git a/techlibs/analogdevices/synth_analogdevices.cc b/techlibs/analogdevices/synth_analogdevices.cc new file mode 100644 index 000000000..00d2e18d6 --- /dev/null +++ b/techlibs/analogdevices/synth_analogdevices.cc @@ -0,0 +1,516 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * (C) 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthAnalogDevicesPass : public ScriptPass +{ + SynthAnalogDevicesPass() : ScriptPass("synth_analogdevices", "synthesis for Analog Devices FPGAs") { } + + void on_register() override + { + RTLIL::constpad["synth_analogdevices.abc9.W"] = "300"; // Number with which ABC will map a 6-input gate + // to one LUT6 (instead of a LUT5 + LUT2) + } + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth_analogdevices [options]\n"); + log("\n"); + log("This command runs synthesis for Analog Devices FPGAs. This command does not operate on\n"); + log("partly selected designs.\n"); + log("\n"); + log(" -top \n"); + log(" use the specified module as top module\n"); + log("\n"); + log(" -tech \n"); + log(" run synthesis for the specified ADI technology process\n"); + log(" currently only affects the type of BRAM used.\n"); + log(" supported values:\n"); + log(" - t40lp (RBRAM)\n"); + log(" - t16ffc (RBRAM2, default)\n"); + log("\n"); + log(" -edif \n"); + log(" write the design to the specified edif file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -nobram\n"); + log(" do not use block RAM cells in output netlist\n"); + log("\n"); + log(" -nolutram\n"); + log(" do not use distributed RAM cells in output netlist\n"); + log("\n"); + log(" -nosrl\n"); + log(" do not use distributed SRL cells in output netlist\n"); + log("\n"); + log(" -nocarry\n"); + log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n"); + log("\n"); + log(" -nowidelut\n"); + log(" do not use MUXF[7-8] resources to implement LUTs larger than native for\n"); + log(" the target\n"); + log("\n"); + log(" -nodsp\n"); + log(" do not use DSP48*s to implement multipliers and associated logic\n"); + log("\n"); + log(" -noiopad\n"); + log(" disable I/O buffer insertion (useful for hierarchical or \n"); + log(" out-of-context flows)\n"); + log("\n"); + log(" -noclkbuf\n"); + log(" disable automatic clock buffer insertion\n"); + log("\n"); + log(" -widemux \n"); + log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at\n"); + log(" or above this number of inputs (minimum value 2, recommended value >= 5)\n"); + log(" default: 0 (no inference)\n"); + log("\n"); + log(" -run :\n"); + log(" only run the commands between the labels (see below). an empty\n"); + log(" from label is synonymous to 'begin', and empty to label is\n"); + log(" synonymous to the end of the command list.\n"); + log("\n"); + log(" -noflatten\n"); + log(" do not flatten design before synthesis\n"); + log("\n"); + log(" -dff\n"); + log(" run 'abc'/'abc9' with -dff option\n"); + log("\n"); + log(" -retime\n"); + log(" run 'abc' with '-D 1' option to enable flip-flop retiming.\n"); + log(" implies -dff.\n"); + log("\n"); + log(" -noabc9\n"); + log(" disable use of new ABC9 flow\n"); + log("\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + help_script(); + log("\n"); + } + + std::string top_opt, edif_file, json_file, tech, tech_param; + bool flatten, retime, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp; + bool abc9, dff; + bool flatten_before_abc; + int widemux; + int widelut_size; + + void clear_flags() override + { + top_opt = "-auto-top"; + edif_file.clear(); + tech = "t16ffc"; + tech_param = " -D IS_T16FFC"; + flatten = true; + retime = false; + noiopad = false; + noclkbuf = false; + nocarry = false; + nobram = false; + nolutram = false; + nosrl = false; + nocarry = false; + nowidelut = false; + nodsp = false; + abc9 = true; + dff = false; + flatten_before_abc = false; + widemux = 0; + } + + void execute(std::vector args, RTLIL::Design *design) override + { + std::string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-top" && argidx+1 < args.size()) { + top_opt = "-top " + args[++argidx]; + continue; + } + if (args[argidx] == "-tech" && argidx+1 < args.size()) { + tech = args[++argidx]; + if (tech == "t16ffc") + tech_param = " -D IS_T16FFC"; + else if (tech == "t40lp") + tech_param = " -D IS_T40LP"; + continue; + } + if (args[argidx] == "-edif" && argidx+1 < args.size()) { + edif_file = args[++argidx]; + continue; + } + if (args[argidx] == "-run" && argidx+1 < args.size()) { + size_t pos = args[argidx+1].find(':'); + if (pos == std::string::npos) + break; + run_from = args[++argidx].substr(0, pos); + run_to = args[argidx].substr(pos+1); + continue; + } + if (args[argidx] == "-noflatten") { + flatten = false; + continue; + } + if (args[argidx] == "-flatten_before_abc") { + flatten_before_abc = true; + continue; + } + if (args[argidx] == "-retime") { + dff = true; + retime = true; + continue; + } + if (args[argidx] == "-nocarry") { + nocarry = true; + continue; + } + if (args[argidx] == "-nowidelut") { + nowidelut = true; + continue; + } + if (args[argidx] == "-iopad") { + continue; + } + if (args[argidx] == "-noiopad") { + noiopad = true; + continue; + } + if (args[argidx] == "-noclkbuf") { + noclkbuf = true; + continue; + } + if (args[argidx] == "-nocarry") { + nocarry = true; + continue; + } + if (args[argidx] == "-nobram") { + nobram = true; + continue; + } + if (args[argidx] == "-nolutram") { + nolutram = true; + continue; + } + if (args[argidx] == "-nosrl") { + nosrl = true; + continue; + } + if (args[argidx] == "-widemux" && argidx+1 < args.size()) { + widemux = atoi(args[++argidx].c_str()); + continue; + } + if (args[argidx] == "-noabc9") { + abc9 = false; + continue; + } + if (args[argidx] == "-nodsp") { + nodsp = true; + continue; + } + if (args[argidx] == "-dff") { + dff = true; + continue; + } + if (args[argidx] == "-json" && argidx+1 < args.size()) { + json_file = args[++argidx]; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!(tech == "t16ffc" || tech == "t40lp")) + log_cmd_error("Invalid ADI -tech setting: '%s'.\n", tech); + + if (widemux != 0 && widemux < 2) + log_cmd_error("-widemux value must be 0 or >= 2.\n"); + + if (!design->full_selection()) + log_cmd_error("This command only operates on fully selected designs!\n"); + + if (abc9 && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + + log_header(design, "Executing SYNTH_ANALOGDEVICES pass.\n"); + log_push(); + + run_script(design, run_from, run_to); + + log_pop(); + } + + void script() override + { + if (check_label("begin")) { + run(stringf("read_verilog -lib -specify %s +/analogdevices/cells_sim.v", tech_param)); + run(stringf("hierarchy -check %s", top_opt.c_str())); + } + + if (check_label("prepare")) { + run("proc"); + if (flatten || help_mode) + run("flatten", "(with '-flatten')"); + if (active_design) + active_design->scratchpad_unset("tribuf.added_something"); + run("tribuf -logic"); + if (noiopad && active_design && active_design->scratchpad_get_bool("tribuf.added_something")) + log_error("Tristate buffers are unsupported without the '-iopad' option.\n"); + run("deminout"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt -nodffe -nosdff"); + run("fsm"); + run("opt"); + if (help_mode) + run("wreduce [-keepdc]", "(option for '-widemux')"); + else + run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); + run("peepopt"); + run("opt_clean"); + + if (widemux > 0 || help_mode) + run("muxpack", " ('-widemux' only)"); + + // xilinx_srl looks for $shiftx cells for identifying variable-length + // shift registers, so attempt to convert $pmux-es to this + // Also: wide multiplexer inference benefits from this too + if (!(nosrl && widemux == 0) || help_mode) { + run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); + run("clean", " (skip if '-nosrl' and '-widemux=0')"); + } + } + + if (check_label("map_dsp", "(skip if '-nodsp')")) { + if (!nodsp || help_mode) { + run("memory_dff"); // xilinx_dsp will merge registers, reserve memory port registers first + // NB: Analog Devices multipliers are signed only + if (help_mode) + run("techmap -map +/mul2dsp.v -map +/analogdevices/{family}_dsp_map.v {options}"); + run("techmap -map +/mul2dsp.v -map +/analogdevices/dsp_map.v -D DSP_A_MAXWIDTH=22 -D DSP_B_MAXWIDTH=22 " + "-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally + // limited to 18x18 in order to take + // advantage of the (PCOUT << 17) -> PCIN + // dedicated cascade chain capability + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL22X22"); + + run("select a:mul2dsp"); + run("setattr -unset mul2dsp"); + run("opt_expr -fine"); + run("wreduce"); + run("select -clear"); + if (help_mode) + run("xilinx_dsp -family "); + else + run("xilinx_dsp -family xc7"); + run("chtype -set $mul t:$__soft_mul"); + } + } + + if (check_label("coarse")) { + run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=6"); + run("alumacc"); + run("share"); + run("opt"); + run("memory -nomap"); + run("opt_clean"); + } + + if (check_label("map_memory")) { + std::string params = ""; + std::string lutrams_map = "+/analogdevices/lutrams_map.v"; + std::string brams_map = "+/analogdevices/brams_map.v"; + if (help_mode) { + params = " [...]"; + } else { + params += " -logic-cost-rom 0.015625"; + params += " -force-params"; + params += " -lib +/analogdevices/lutrams.txt"; + params += " -lib +/analogdevices/brams.txt"; + params += tech_param; + brams_map += tech_param; + if (nolutram) + params += " -no-auto-distributed"; + if (nobram) + params += " -no-auto-block"; + } + run("memory_libmap" + params); + run("techmap -map " + lutrams_map); + run("techmap -map " + brams_map); + } + + if (check_label("map_ffram")) { + if (widemux > 0) { + run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover + // performs less efficiently + } else { + run("opt -fast -full"); + } + run("memory_map"); + } + + if (check_label("fine")) { + if (help_mode) { + run("simplemap t:$mux", "('-widemux' only)"); + run("muxcover ", "('-widemux' only)"); + } else if (widemux > 0) { + run("simplemap t:$mux"); + constexpr int cost_mux2 = 100; + std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); + switch (widemux) { + case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; + case 3: + case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; + case 5: + case 6: + case 7: + case 8: muxcover_args += stringf(" -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + default: muxcover_args += stringf(" -mux16=%d", cost_mux2*(widemux-1)-1); break; + } + run("muxcover " + muxcover_args); + } + run("opt -full"); + + if (!nosrl || help_mode) + run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')"); + + std::string techmap_args = " -map +/techmap.v -D LUT_SIZE=6"; + if (help_mode) + techmap_args += " [-map +/analogdevices/mux_map.v]"; + else if (widemux > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/analogdevices/mux_map.v", widemux); + if (!nocarry) { + techmap_args += " -map +/analogdevices/arith_map.v"; + } + run("techmap " + techmap_args); + run("opt -fast"); + } + + if (check_label("map_cells")) { + // Needs to be done before logic optimization, so that inverters (inserted + // here because of negative-polarity output enable) are handled. + if (help_mode || !noiopad) + run("iopadmap -bits -outpad OUTBUF I:O -inpad INBUF O:I A:top", "(skip if '-noiopad')"); + std::string techmap_args = "-map +/techmap.v -map +/analogdevices/cells_map.v"; + if (widemux > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); + run("techmap " + techmap_args); + run("clean"); + } + + if (check_label("map_ffs")) { + run("dfflegalize -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r"); + if (abc9 || help_mode) { + if (dff || help_mode) + run("zinit -all w:* t:$_SDFFE_*", "('-dff' only)"); + run("techmap -map +/analogdevices/ff_map.v", "('-abc9' only)"); + } + } + + if (check_label("map_luts")) { + run("opt_expr -mux_undef -noclkinv"); + if (flatten_before_abc) + run("flatten"); + if (help_mode) + run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); + else if (abc9) { + run("read_verilog -icells -lib -specify +/analogdevices/abc9_model.v"); + std::string abc9_opts; + std::string k = "synth_analogdevices.abc9.W"; + if (active_design && active_design->scratchpad.count(k)) + abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str()); + else { + abc9_opts += stringf(" -W %s", RTLIL::constpad.at("synth_analogdevices.abc9.W").c_str()); + } + if (nowidelut) + abc9_opts += stringf(" -maxlut 6"); + if (dff) + abc9_opts += " -dff"; + run("abc9" + abc9_opts); + } + else { + std::string abc_opts; + if (nowidelut) + abc_opts += " -luts 2:2,3,6:5"; + else + abc_opts += " -luts 2:2,3,6:5,10,20"; + if (dff) + abc_opts += " -dff"; + if (retime) + abc_opts += " -D 1"; + run("abc -dress" + abc_opts); + } + run("clean"); + + if (help_mode || !abc9) + run("techmap -map +/analogdevices/ff_map.v", "(only if not '-abc9')"); + // This shregmap call infers fixed length shift registers after abc + // has performed any necessary retiming + if (!nosrl || help_mode) + run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); + std::string techmap_args = "-map +/analogdevices/lut_map.v -map +/analogdevices/cells_map.v"; + techmap_args += " -D LUT_WIDTH=6"; + run("techmap " + techmap_args); + run("xilinx_dffopt"); + run("opt_lut_ins -tech analogdevices"); + } + + if (check_label("finalize")) { + run("clean"); + } + + if (check_label("check")) { + run("hierarchy -check"); + run("stat -tech analogdevices"); + run("check -noinit"); + run("blackbox =A:whitebox"); + } + + if (check_label("edif")) { + if (!edif_file.empty() || help_mode) { + run("delete t:$assert t:$scopeinfo"); + run(stringf("write_edif %s", edif_file.c_str())); + } + } + } +} SynthAnalogDevicesPass; + +PRIVATE_NAMESPACE_END diff --git a/tests/arch/analogdevices/.gitignore b/tests/arch/analogdevices/.gitignore new file mode 100644 index 000000000..fb232f235 --- /dev/null +++ b/tests/arch/analogdevices/.gitignore @@ -0,0 +1 @@ +t_*.ys diff --git a/tests/arch/analogdevices/add_sub.ys b/tests/arch/analogdevices/add_sub.ys new file mode 100644 index 000000000..2a297851c --- /dev/null +++ b/tests/arch/analogdevices/add_sub.ys @@ -0,0 +1,13 @@ +read_verilog ../common/add_sub.v +hierarchy -top top +proc +design -save orig + +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +stat +select -assert-count 8 t:LUT2 +select -assert-count 2 t:CRY4 +select -assert-count 2 t:CRY4INIT +select -assert-none t:LUT2 t:CRY4 t:CRY4INIT %% t:* %D diff --git a/tests/arch/analogdevices/adffs.ys b/tests/arch/analogdevices/adffs.ys new file mode 100644 index 000000000..9affcd52f --- /dev/null +++ b/tests/arch/analogdevices/adffs.ys @@ -0,0 +1,47 @@ +read_verilog ../common/adffs.v +design -save read + +hierarchy -top adff +proc +equiv_opt -async2sync -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adff # Constrain all select calls below inside the top module +select -assert-count 1 t:FFCE + +select -assert-none t:FFCE %% t:* %D + + +design -load read +hierarchy -top adffn +proc +equiv_opt -async2sync -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adffn # Constrain all select calls below inside the top module +select -assert-count 1 t:FFCE +select -assert-count 1 t:LUT1 + +select -assert-none t:FFCE t:LUT1 %% t:* %D + + +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:FFRE +select -assert-count 1 t:LUT2 +stat +select -assert-none t:FFRE t:LUT2 %% t:* %D + + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:FFRE_N +select -assert-count 1 t:LUT1 + +select -assert-none t:FFRE_N t:LUT1 %% t:* %D diff --git a/tests/arch/analogdevices/asym_ram_sdp.ys b/tests/arch/analogdevices/asym_ram_sdp.ys new file mode 100644 index 000000000..22ed5e010 --- /dev/null +++ b/tests/arch/analogdevices/asym_ram_sdp.ys @@ -0,0 +1,50 @@ +# Memory bits <= 18K; Data width <= 36; Address width <= 14: -> RBRAM2 + +# w4b | r16b +design -reset +read_verilog asym_ram_sdp_read_wider.v +synth_analogdevices -top asym_ram_sdp_read_wider -noiopad +select -assert-count 1 t:RBRAM2 + +# w8b | r16b +design -reset +read_verilog asym_ram_sdp_read_wider.v +chparam -set WIDTHA 8 -set SIZEA 512 -set ADDRWIDTHA 9 asym_ram_sdp_read_wider +synth_analogdevices -top asym_ram_sdp_read_wider -noiopad +select -assert-count 1 t:RBRAM2 + +# w4b | r32b +design -reset +read_verilog asym_ram_sdp_read_wider.v +chparam -set WIDTHB 32 -set SIZEB 128 -set ADDRWIDTHB 7 asym_ram_sdp_read_wider +synth_analogdevices -top asym_ram_sdp_read_wider -noiopad +select -assert-count 2 t:RBRAM2 + +# w16b | r4b +design -reset +read_verilog asym_ram_sdp_write_wider.v +synth_analogdevices -top asym_ram_sdp_write_wider -noiopad +select -assert-count 1 t:RBRAM2 + +# w16b | r8b +design -reset +read_verilog asym_ram_sdp_write_wider.v +chparam -set WIDTHB 8 -set SIZEB 512 -set ADDRWIDTHB 9 asym_ram_sdp_read_wider +synth_analogdevices -top asym_ram_sdp_write_wider -noiopad +select -assert-count 1 t:RBRAM2 + +# w32b | r4b +design -reset +read_verilog asym_ram_sdp_write_wider.v +chparam -set WIDTHA 32 -set SIZEA 128 -set ADDRWIDTHA 7 asym_ram_sdp_read_wider +synth_analogdevices -top asym_ram_sdp_write_wider -noiopad +select -assert-count 1 t:RBRAM2 + +# w4b | r24b +design -reset +read_verilog asym_ram_sdp_read_wider.v +chparam -set SIZEA 768 +chparam -set WIDTHB 24 -set SIZEB 128 -set ADDRWIDTHB 7 asym_ram_sdp_read_wider +synth_analogdevices -top asym_ram_sdp_read_wider -noiopad +select -assert-count 2 t:RBRAM2 + diff --git a/tests/arch/analogdevices/asym_ram_sdp_read_wider.v b/tests/arch/analogdevices/asym_ram_sdp_read_wider.v new file mode 100644 index 000000000..853ba6254 --- /dev/null +++ b/tests/arch/analogdevices/asym_ram_sdp_read_wider.v @@ -0,0 +1,73 @@ +// Asymmetric port RAM +// Read Wider than Write. Read Statement in loop +//asym_ram_sdp_read_wider.v +module asym_ram_sdp_read_wider (clkA, clkB, enaA, weA, enaB, addrA, addrB, diA, doB); + parameter WIDTHA = 4; + parameter SIZEA = 1024; + parameter ADDRWIDTHA = 10; + + parameter WIDTHB = 16; + parameter SIZEB = 256; + parameter ADDRWIDTHB = 8; + + input clkA; + input clkB; + input weA; + input enaA, enaB; + input [ADDRWIDTHA-1:0] addrA; + input [ADDRWIDTHB-1:0] addrB; + input [WIDTHA-1:0] diA; + output [WIDTHB-1:0] doB; + + `define max(a,b) {(a) > (b) ? (a) : (b)} + `define min(a,b) {(a) < (b) ? (a) : (b)} + + function integer log2; + input integer value; + reg [31:0] shifted; + integer res; + begin + if (value < 2) + log2 = value; + else + begin + shifted = value-1; + for (res=0; shifted>0; res=res+1) + shifted = shifted>>1; + log2 = res; + end + end + endfunction + + localparam maxSIZE = `max(SIZEA, SIZEB); + localparam maxWIDTH = `max(WIDTHA, WIDTHB); + localparam minWIDTH = `min(WIDTHA, WIDTHB); + + localparam RATIO = maxWIDTH / minWIDTH; + localparam log2RATIO = log2(RATIO); + + (* ram_style="block" *) + reg [minWIDTH-1:0] RAM [0:maxSIZE-1]; + reg [WIDTHB-1:0] readB; + + always @(posedge clkA) + begin + if (enaA) begin + if (weA) + RAM[addrA] <= diA; + end + end + + always @(posedge clkB) + begin : ramread + integer i; + reg [log2RATIO-1:0] lsbaddr; + if (enaB) begin + for (i = 0; i < RATIO; i = i+1) begin + lsbaddr = i; + readB[(i+1)*minWIDTH-1 -: minWIDTH] <= RAM[{addrB, lsbaddr}]; + end + end + end + assign doB = readB; +endmodule diff --git a/tests/arch/analogdevices/asym_ram_sdp_write_wider.v b/tests/arch/analogdevices/asym_ram_sdp_write_wider.v new file mode 100644 index 000000000..abffa9fc4 --- /dev/null +++ b/tests/arch/analogdevices/asym_ram_sdp_write_wider.v @@ -0,0 +1,72 @@ +// Asymmetric port RAM +// Write wider than Read. Write Statement in a loop. +// asym_ram_sdp_write_wider.v +module asym_ram_sdp_write_wider (clkA, clkB, weA, enaA, enaB, addrA, addrB, diA, doB); + parameter WIDTHB = 4; + parameter SIZEB = 1024; + parameter ADDRWIDTHB = 10; + + parameter WIDTHA = 16; + parameter SIZEA = 256; + parameter ADDRWIDTHA = 8; + + input clkA; + input clkB; + input weA; + input enaA, enaB; + input [ADDRWIDTHA-1:0] addrA; + input [ADDRWIDTHB-1:0] addrB; + input [WIDTHA-1:0] diA; + output [WIDTHB-1:0] doB; + + `define max(a,b) {(a) > (b) ? (a) : (b)} + `define min(a,b) {(a) < (b) ? (a) : (b)} + + function integer log2; + input integer value; + reg [31:0] shifted; + integer res; + begin + if (value < 2) + log2 = value; + else + begin + shifted = value-1; + for (res=0; shifted>0; res=res+1) + shifted = shifted>>1; + log2 = res; + end + end + endfunction + + localparam maxSIZE = `max(SIZEA, SIZEB); + localparam maxWIDTH = `max(WIDTHA, WIDTHB); + localparam minWIDTH = `min(WIDTHA, WIDTHB); + + localparam RATIO = maxWIDTH / minWIDTH; + localparam log2RATIO = log2(RATIO); + + (* ram_style="block" *) + reg [minWIDTH-1:0] RAM [0:maxSIZE-1]; + reg [WIDTHB-1:0] readB; + + always @(posedge clkB) begin + if (enaB) begin + readB <= RAM[addrB]; + end + end + assign doB = readB; + + always @(posedge clkA) + begin : ramwrite + integer i; + reg [log2RATIO-1:0] lsbaddr; + for (i=0; i< RATIO; i= i+ 1) begin : write1 + lsbaddr = i; + if (enaA) begin + if (weA) + RAM[{addrA, lsbaddr}] <= diA[(i+1)*minWIDTH-1 -: minWIDTH]; + end + end + end +endmodule diff --git a/tests/arch/analogdevices/attributes_test.ys b/tests/arch/analogdevices/attributes_test.ys new file mode 100644 index 000000000..03d6decff --- /dev/null +++ b/tests/arch/analogdevices/attributes_test.ys @@ -0,0 +1,39 @@ +# Check that blockram memory without parameters is not modified +read_verilog ../common/memory_attributes/attributes_test.v +hierarchy -top block_ram +synth_analogdevices -top block_ram -noiopad +cd block_ram # Constrain all select calls below inside the top module +# select -assert-count 1 t:RBRAM2 # This currently infers LUTRAM because BRAM is expensive. + +# Check that distributed memory without parameters is not modified +design -reset +read_verilog ../common/memory_attributes/attributes_test.v +hierarchy -top distributed_ram +synth_analogdevices -top distributed_ram -noiopad +cd distributed_ram # Constrain all select calls below inside the top module +select -assert-count 8 t:RAMS64X1 +select -assert-count 8 t:FFRE + +# Set ram_style distributed to blockram memory; will be implemented as distributed +design -reset +read_verilog ../common/memory_attributes/attributes_test.v +setattr -set ram_style "distributed" block_ram/m:* +synth_analogdevices -top block_ram -noiopad +cd block_ram # Constrain all select calls below inside the top module +select -assert-count 64 t:RAMS64X1 +select -assert-count 4 t:FFRE + +# Set synthesis, logic_block to blockram memory; will be implemented as distributed +design -reset +read_verilog ../common/memory_attributes/attributes_test.v +setattr -set logic_block 1 block_ram/m:* +synth_analogdevices -top block_ram -noiopad +cd block_ram # Constrain all select calls below inside the top module +select -assert-count 0 t:RBRAM2 + +# Set ram_style block to a distributed memory; will be implemented as blockram +design -reset +read_verilog ../common/memory_attributes/attributes_test.v +synth_analogdevices -top distributed_ram_manual -noiopad +cd distributed_ram_manual # Constrain all select calls below inside the top module +# select -assert-count 1 t:RBRAM2 # This gets implemented in logic instead diff --git a/tests/arch/analogdevices/blockram.ys b/tests/arch/analogdevices/blockram.ys new file mode 100644 index 000000000..f6efa5ba8 --- /dev/null +++ b/tests/arch/analogdevices/blockram.ys @@ -0,0 +1,77 @@ +### TODO: Not running equivalence checking because BRAM models does not exists +### currently. Checking instance counts instead. +# Memory bits <= 18K; Data width <= 36; Address width <= 14: -> RBRAM2 +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 12 -set DATA_WIDTH 1 sync_ram_sdp +setattr -set ram_style "block" sync_ram_sdp +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 + +design -reset +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 18 sync_ram_sdp +setattr -set ram_style "block" sync_ram_sdp +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 + +design -reset +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp +setattr -set ram_style "block" sync_ram_sdp +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 + +design -reset +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 + +# Anything memory bits < 1024 -> LUTRAM +design -reset +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 2 sync_ram_sdp +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 0 t:RBRAM2 +select -assert-count 8 t:RAMD64X1 +select -assert-count 2 t:FFRE + +# More than 18K bits, data width <= 36 (TDP), and address width from 10 to 15b (non-cascaded) -> RAMB36E1 +design -reset +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 36 sync_ram_sdp +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 + + +### With parameters + +design -reset +read_verilog ../common/blockram.v +hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 12 -chparam DATA_WIDTH 1 +setattr -set ram_style "block" m:memory +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 + +design -reset +read_verilog ../common/blockram.v +hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 12 -chparam DATA_WIDTH 1 +setattr -set logic_block 1 m:memory +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 0 t:RBRAM2 + +design -reset +read_verilog ../common/blockram.v +hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 8 -chparam DATA_WIDTH 1 +setattr -set ram_style "block" m:memory +synth_analogdevices -top sync_ram_sdp -noiopad +cd sync_ram_sdp +select -assert-count 1 t:RBRAM2 diff --git a/tests/arch/analogdevices/bug1460.ys b/tests/arch/analogdevices/bug1460.ys new file mode 100644 index 000000000..66fb96a5b --- /dev/null +++ b/tests/arch/analogdevices/bug1460.ys @@ -0,0 +1,34 @@ +read_verilog < 1: + top_list.pop(0) + + # iterate over string substitutions + for top in top_list: + # limit number of tests per file to allow parallel make + if not f: + fn = f"t_mem{i}.ys" + f = open(fn, mode="w") + j = 0 + + # output yosys script test file + print( + blockram_template.format(param_str=param_str, top=top, tech=sim_test.tech, opts=" ".join(sim_test.opts)), + file=f + ) + for assertion in sim_test.assertions: + print(f"log ** CHECKING CELL COUNTS FOR TEST {top} WITH PARAMS{param_str} ON TECH {sim_test.tech}", file=f) + print(f"select {assertion}", file=f) + print("", file=f) + + # increment test counter + j += 1 + if j >= max_j: + f = f.close() + i += 1 + +if f: + f.close() diff --git a/tests/arch/analogdevices/mul.ys b/tests/arch/analogdevices/mul.ys new file mode 100644 index 000000000..460bfeb68 --- /dev/null +++ b/tests/arch/analogdevices/mul.ys @@ -0,0 +1,9 @@ +read_verilog ../common/mul.v +hierarchy -top top +proc +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:RBBDSP +select -assert-none t:RBBDSP %% t:* %D diff --git a/tests/arch/analogdevices/mul_unsigned.v b/tests/arch/analogdevices/mul_unsigned.v new file mode 100644 index 000000000..e3713a642 --- /dev/null +++ b/tests/arch/analogdevices/mul_unsigned.v @@ -0,0 +1,30 @@ +/* +Example from: https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug901-vivado-synthesis.pdf [p. 89]. +*/ + +// Unsigned 16x24-bit Multiplier +// 1 latency stage on operands +// 3 latency stage after the multiplication +// File: multipliers2.v +// +module mul_unsigned (clk, A, B, RES); +parameter WIDTHA = /*16*/ 6; +parameter WIDTHB = /*24*/ 9; +input clk; +input [WIDTHA-1:0] A; +input [WIDTHB-1:0] B; +output [WIDTHA+WIDTHB-1:0] RES; +reg [WIDTHA-1:0] rA; +reg [WIDTHB-1:0] rB; +reg [WIDTHA+WIDTHB-1:0] M [3:0]; +integer i; +always @(posedge clk) + begin + rA <= A; + rB <= B; + M[0] <= rA * rB; + for (i = 0; i < 3; i = i+1) + M[i+1] <= M[i]; + end +assign RES = M[3]; +endmodule diff --git a/tests/arch/analogdevices/mul_unsigned.ys b/tests/arch/analogdevices/mul_unsigned.ys new file mode 100644 index 000000000..5bdbdaac4 --- /dev/null +++ b/tests/arch/analogdevices/mul_unsigned.ys @@ -0,0 +1,10 @@ +read_verilog mul_unsigned.v +hierarchy -top mul_unsigned +proc + +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mul_unsigned # Constrain all select calls below inside the top module +select -assert-count 1 t:RBBDSP +select -assert-count 75 t:FFRE +select -assert-none t:RBBDSP t:FFRE %% t:* %D diff --git a/tests/arch/analogdevices/mux.ys b/tests/arch/analogdevices/mux.ys new file mode 100644 index 000000000..375ce90f2 --- /dev/null +++ b/tests/arch/analogdevices/mux.ys @@ -0,0 +1,50 @@ +read_verilog ../common/mux.v +design -save read + +hierarchy -top mux2 +proc +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux2 # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT3 + +select -assert-none t:LUT3 %% t:* %D + + +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT6 + +select -assert-none t:LUT6 %% t:* %D + + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux8 # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT3 +select -assert-count 2 t:LUT6 + +select -assert-none t:LUT3 t:LUT6 %% t:* %D + + +design -load read +hierarchy -top mux16 +proc +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux16 # Constrain all select calls below inside the top module +select -assert-max 2 t:LUT3 +select -assert-max 2 t:LUT4 +select -assert-min 4 t:LUT6 +select -assert-max 7 t:LUT6 +select -assert-max 2 t:LUTMUX7 +dump + +select -assert-none t:LUT6 t:LUT4 t:LUT3 t:LUTMUX7 %% t:* %D diff --git a/tests/arch/analogdevices/opt_lut_ins.ys b/tests/arch/analogdevices/opt_lut_ins.ys new file mode 100644 index 000000000..9723ee651 --- /dev/null +++ b/tests/arch/analogdevices/opt_lut_ins.ys @@ -0,0 +1,26 @@ +read_rtlil << EOF + +module \top + + wire width 4 input 1 \A + + wire output 2 \O + + cell \LUT4 $0 + parameter \INIT 16'1111110011000000 + connect \I0 \A [0] + connect \I1 \A [1] + connect \I2 \A [2] + connect \I3 \A [3] + connect \O \O + end +end + +EOF + +read_verilog -lib +/analogdevices/cells_sim.v +equiv_opt -assert -map +/analogdevices/cells_sim.v opt_lut_ins -tech analogdevices + +design -load postopt + +select -assert-count 1 t:LUT3 diff --git a/tests/arch/analogdevices/run-test.sh b/tests/arch/analogdevices/run-test.sh new file mode 100755 index 000000000..9b5e2f7f4 --- /dev/null +++ b/tests/arch/analogdevices/run-test.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -eu +python3 mem_gen.py +source ../../gen-tests-makefile.sh +generate_mk --yosys-scripts --bash diff --git a/tests/arch/analogdevices/shifter.ys b/tests/arch/analogdevices/shifter.ys new file mode 100644 index 000000000..3cd67cb93 --- /dev/null +++ b/tests/arch/analogdevices/shifter.ys @@ -0,0 +1,10 @@ +read_verilog ../common/shifter.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 8 t:FFRE +select -assert-none t:FFRE %% t:* %D diff --git a/tests/arch/common/blockram.v b/tests/arch/common/blockram.v index 4a9d45a6b..4358a4655 100644 --- a/tests/arch/common/blockram.v +++ b/tests/arch/common/blockram.v @@ -22,6 +22,30 @@ module sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) endmodule // sync_ram_sp +module sync_ram_sp_nochange #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) + (input wire write_enable, clk, + input wire [DATA_WIDTH-1:0] data_in, + input wire [ADDRESS_WIDTH-1:0] address_in, + output wire [DATA_WIDTH-1:0] data_out); + + localparam WORD = (DATA_WIDTH-1); + localparam DEPTH = (2**ADDRESS_WIDTH-1); + + reg [WORD:0] data_out_r; + reg [WORD:0] memory [0:DEPTH]; + + always @(posedge clk) begin + if (write_enable) + memory[address_in] <= data_in; + else + data_out_r <= memory[address_in]; + end + + assign data_out = data_out_r; + +endmodule // sync_ram_sp_nochange + + module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) (input wire clk, write_enable, input wire [DATA_WIDTH-1:0] data_in, @@ -112,6 +136,62 @@ module sync_ram_sdp_wrr #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10, SHIFT_VAL=1) endmodule // sync_ram_sdp_wrr +module double_sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10, USE_TDP=0) +( + input wire write_enable_a, clk_a, + input wire [DATA_WIDTH-1:0] data_in_a, + input wire [ADDRESS_WIDTH-1:0] address_in_a, + output wire [DATA_WIDTH-1:0] data_out_a, + + input wire write_enable_b, clk_b, + input wire [DATA_WIDTH-1:0] data_in_b, + input wire [ADDRESS_WIDTH-1:0] address_in_b, + output wire [DATA_WIDTH-1:0] data_out_b +); + + generate + if (USE_TDP) begin + + sync_ram_tdp #( + .DATA_WIDTH(DATA_WIDTH), + .ADDRESS_WIDTH(ADDRESS_WIDTH+1) + ) ram ( + .clk_a(clk_a), .clk_b(clk_b), + .write_enable_a(write_enable_a), .write_enable_b(write_enable_b), + .write_data_a(data_in_a), .write_data_b(data_in_b), + .addr_a({1'b0, address_in_a}), .addr_b({1'b1, address_in_b}), + .read_data_a(data_out_a), .read_data_b(data_out_b) + ); + + end else begin + + sync_ram_sp #( + .DATA_WIDTH(DATA_WIDTH), + .ADDRESS_WIDTH(ADDRESS_WIDTH) + ) a_ram ( + .write_enable(write_enable_a), + .clk(clk_a), + .data_in(data_in_a), + .address_in(address_in_a), + .data_out(data_out_a) + ); + + sync_ram_sp #( + .DATA_WIDTH(DATA_WIDTH), + .ADDRESS_WIDTH(ADDRESS_WIDTH) + ) b_ram ( + .write_enable(write_enable_b), + .clk(clk_b), + .data_in(data_in_b), + .address_in(address_in_b), + .data_out(data_out_b) + ); + end + endgenerate + +endmodule // double_sync_ram_sp + + module double_sync_ram_sdp #(parameter DATA_WIDTH_A=8, ADDRESS_WIDTH_A=10, DATA_WIDTH_B=8, ADDRESS_WIDTH_B=10) ( input wire write_enable_a, clk_a, diff --git a/tests/arch/ecp5/opt_lut_ins.ys b/tests/arch/ecp5/opt_lut_ins.ys index 622b5406c..7f9970c69 100644 --- a/tests/arch/ecp5/opt_lut_ins.ys +++ b/tests/arch/ecp5/opt_lut_ins.ys @@ -23,7 +23,7 @@ EOF read_verilog -lib +/ecp5/cells_sim.v -equiv_opt -assert -map +/ecp5/cells_sim.v opt_lut_ins -tech ecp5 +equiv_opt -assert -map +/ecp5/cells_sim.v opt_lut_ins -tech lattice design -load postopt