From a1759e7ae7c7a54017d95d05581f1218ea333399 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 13:42:08 +0200 Subject: [PATCH 01/18] fabulous: remove unused `-edif` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 0074a52af..f2b6090f1 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -48,10 +48,6 @@ struct SynthPass : public ScriptPass log(" write the design to the specified BLIF file. writing of an output file\n"); log(" is omitted if this parameter is not specified.\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(" -json \n"); log(" write the design to the specified JSON file. writing of an output file\n"); log(" is omitted if this parameter is not specified.\n"); From 32bd3e54183b0bb3a9658d2df272bc0f47ad00db Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 13:42:57 +0200 Subject: [PATCH 02/18] fabulous: remove unused `-encfile` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index f2b6090f1..0abfd843e 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -69,9 +69,6 @@ struct SynthPass : public ScriptPass log(" use the specified Verilog file for extra techmap rules (can be specified multiple\n"); log(" times).\n"); log("\n"); - log(" -encfile \n"); - log(" passed to 'fsm_recode' via 'fsm'\n"); - log("\n"); log(" -nofsm\n"); log(" do not run FSM optimization\n"); log("\n"); From d671de97e9f9464481b9e89a9952cf38f6283d0d Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 13:59:01 +0200 Subject: [PATCH 03/18] fabulous: remove legacy `-vpr` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 0abfd843e..b9efe5498 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -55,9 +55,6 @@ struct SynthPass : public ScriptPass log(" -lut \n"); log(" perform synthesis for a k-LUT architecture (default 4).\n"); log("\n"); - log(" -vpr\n"); - log(" perform synthesis for the FABulous VPR flow (using slightly different techmapping).\n"); - log("\n"); log(" -plib \n"); log(" use the specified Verilog file as a primitive library.\n"); log("\n"); @@ -118,7 +115,7 @@ struct SynthPass : public ScriptPass string top_module, json_file, blif_file, plib, fsm_opts, memory_opts, carry_mode; std::vector extra_plib, extra_map; - bool autotop, forvpr, noalumacc, nofsm, noshare, noregfile, iopad, complexdff, flatten; + bool autotop, noalumacc, nofsm, noshare, noregfile, iopad, complexdff, flatten; int lut; void clear_flags() override @@ -127,7 +124,6 @@ struct SynthPass : public ScriptPass plib.clear(); autotop = false; lut = 4; - forvpr = false; noalumacc = false; nofsm = false; noshare = false; @@ -170,10 +166,6 @@ struct SynthPass : public ScriptPass } continue; } - if (args[argidx] == "-vpr") { - forvpr = true; - continue; - } if (args[argidx] == "-auto-top") { autotop = true; continue; @@ -371,8 +363,7 @@ struct SynthPass : public ScriptPass } if (check_label("map_cells")) { - if (!forvpr) - run(stringf("techmap -D LUT_K=%d -map +/fabulous/cells_map.v", lut)); + run(stringf("techmap -D LUT_K=%d -map +/fabulous/cells_map.v", lut)); run("clean"); } if (check_label("check")) { From 54c37b395b37aaa7ba86bac60e928f7bc97eab3a Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:16:34 +0200 Subject: [PATCH 04/18] fabulous: fix argument check in `-lut` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index b9efe5498..17c3b86f5 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -170,7 +170,7 @@ struct SynthPass : public ScriptPass autotop = true; continue; } - if (args[argidx] == "-lut") { + if (args[argidx] == "-lut" && argidx+1 < args.size()) { lut = atoi(args[++argidx].c_str()); continue; } From 30640c71e2ca4f3a19af1ddd7773bd0b64828730 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:24:18 +0200 Subject: [PATCH 05/18] fabulous: fix argument check in `-carry` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 17c3b86f5..e22443d25 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -218,7 +218,7 @@ struct SynthPass : public ScriptPass complexdff = true; continue; } - if (args[argidx] == "-carry") { + if (args[argidx] == "-carry" && argidx+1 < args.size()) { carry_mode = args[++argidx]; if (carry_mode != "none" && carry_mode != "ha") log_cmd_error("Unsupported carry style: %s\n", carry_mode); From 6c82468031508540520f85e4bd8194162e4d253f Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:11:12 +0200 Subject: [PATCH 06/18] fabulous: add `-ff` option, remove legacy `-plib`/`-complex-dff` option The concept of 'COMPLEX_DFF' is deprecated. Instead, simply specify the supported flip-flops using `-ff ` and supply the mapping file. Signed-off-by: Leo Moser --- techlibs/fabulous/cells_map.v | 4 - techlibs/fabulous/ff_map.v | 9 - techlibs/fabulous/latches_map.v | 11 - techlibs/fabulous/prims.v | 487 ---------------------------- techlibs/fabulous/synth_fabulous.cc | 47 ++- 5 files changed, 20 insertions(+), 538 deletions(-) delete mode 100644 techlibs/fabulous/ff_map.v delete mode 100644 techlibs/fabulous/latches_map.v delete mode 100644 techlibs/fabulous/prims.v diff --git a/techlibs/fabulous/cells_map.v b/techlibs/fabulous/cells_map.v index e33e641a8..2329286f5 100644 --- a/techlibs/fabulous/cells_map.v +++ b/techlibs/fabulous/cells_map.v @@ -8,11 +8,9 @@ module \$lut (A, 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])); @@ -30,5 +28,3 @@ module \$lut (A, Y); end endgenerate endmodule - -module \$_DFF_P_ (input D, C, output Q); LUTFF _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C)); endmodule diff --git a/techlibs/fabulous/ff_map.v b/techlibs/fabulous/ff_map.v deleted file mode 100644 index 0a03bd692..000000000 --- a/techlibs/fabulous/ff_map.v +++ /dev/null @@ -1,9 +0,0 @@ -module \$_DFF_P_ (input D, C, output Q); LUTFF _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C)); endmodule - -module \$_DFFE_PP_ (input D, C, E, output Q); LUTFF_E _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .E(E)); endmodule - -module \$_SDFF_PP0_ (input D, C, R, output Q); LUTFF_SR _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .R(R)); endmodule -module \$_SDFF_PP1_ (input D, C, R, output Q); LUTFF_SS _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .S(R)); endmodule - -module \$_SDFFCE_PP0P_ (input D, C, E, R, output Q); LUTFF_ESR _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .E(E), .R(R)); endmodule -module \$_SDFFCE_PP1P_ (input D, C, E, R, output Q); LUTFF_ESS _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .E(E), .S(R)); endmodule diff --git a/techlibs/fabulous/latches_map.v b/techlibs/fabulous/latches_map.v deleted file mode 100644 index c28f88cf7..000000000 --- a/techlibs/fabulous/latches_map.v +++ /dev/null @@ -1,11 +0,0 @@ -module \$_DLATCH_N_ (E, D, Q); - wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; - input E, D; - output Q = !E ? D : Q; -endmodule - -module \$_DLATCH_P_ (E, D, Q); - wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; - input E, D; - output Q = E ? D : Q; -endmodule diff --git a/techlibs/fabulous/prims.v b/techlibs/fabulous/prims.v deleted file mode 100644 index d1c493080..000000000 --- a/techlibs/fabulous/prims.v +++ /dev/null @@ -1,487 +0,0 @@ -module LUT1(output O, input I0); - parameter [1:0] INIT = 0; - assign O = I0 ? INIT[1] : INIT[0]; -endmodule - -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]; -endmodule - -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]; -endmodule - -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]; -endmodule - -module LUT4_HA(output O, Co, input I0, I1, I2, I3, Ci); - parameter [15:0] INIT = 0; - parameter I0MUX = 1'b1; - - 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]; - - wire I0_sel = I0MUX ? Ci : I0; - assign O = I0_sel ? s1[1] : s1[0]; - - assign Co = (Ci & I1) | (Ci & I2) | (I1 & I2); -endmodule - -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]; -endmodule - -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]; -endmodule - -module LUT55_FCY (output O, Co, input I0, I1, I2, I3, I4, Ci); - parameter [63:0] INIT = 0; - - wire comb1, comb2; - - LUT5 #(.INIT(INIT[31: 0])) l5_1 (.I0(I0), .I1(I1), .I2(I2), .I3(I3), .I4(I4), .O(comb1)); - LUT5 #(.INIT(INIT[63:32])) l5_2 (.I0(I0), .I1(I1), .I2(I2), .I3(I3), .I4(I4), .O(comb2)); - - assign O = comb1 ^ Ci; - assign Co = comb1 ? Ci : comb2; -endmodule - - -module LUTFF(input CLK, D, output reg O); - initial O = 1'b0; - always @ (posedge CLK) begin - O <= D; - end -endmodule - -module FABULOUS_MUX2(input I0, I1, S0, output O); - assign O = S0 ? I1 : I0; -endmodule - -module FABULOUS_MUX4(input I0, I1, I2, I3, S0, S1, output O); - wire A0 = S0 ? I1 : I0; - wire A1 = S0 ? I3 : I2; - assign O = S1 ? A1 : A0; -endmodule - -module FABULOUS_MUX8(input I0, I1, I2, I3, I4, I5, I6, I7, S0, S1, S2, output O); - wire A0 = S0 ? I1 : I0; - wire A1 = S0 ? I3 : I2; - wire A2 = S0 ? I5 : I4; - wire A3 = S0 ? I7 : I6; - wire B0 = S1 ? A1 : A0; - wire B1 = S1 ? A3 : A2; - assign O = S2 ? B1 : B0; -endmodule - -module FABULOUS_LC #( - parameter K = 4, - parameter [2**K-1:0] INIT = 0, - parameter DFF_ENABLE = 1'b0 -) ( - input CLK, - input [K-1:0] I, - output O, - output Q -); - wire f_wire; - - //LUT #(.K(K), .INIT(INIT)) lut_i(.I(I), .Q(f_wire)); - generate - if (K == 1) begin - LUT1 #(.INIT(INIT)) lut1 (.O(f_wire), .I0(I[0])); - end else - if (K == 2) begin - LUT2 #(.INIT(INIT)) lut2 (.O(f_wire), .I0(I[0]), .I1(I[1])); - end else - if (K == 3) begin - LUT3 #(.INIT(INIT)) lut3 (.O(f_wire), .I0(I[0]), .I1(I[1]), .I2(I[2])); - end else - if (K == 4) begin - LUT4 #(.INIT(INIT)) lut4 (.O(f_wire), .I0(I[0]), .I1(I[1]), .I2(I[2]), .I3(I[3])); - end - endgenerate - - LUTFF dff_i(.CLK(CLK), .D(f_wire), .Q(Q)); - - assign O = f_wire; -endmodule - -(* blackbox *) -module Global_Clock (output CLK); -`ifndef SYNTHESIS - initial CLK = 0; - always #10 CLK = ~CLK; -`endif -endmodule - -(* blackbox, keep *) -module InPass4_frame_config (input CLK, output O0, O1, O2, O3); - -endmodule - - -(* blackbox, keep *) -module OutPass4_frame_config (input CLK, I0, I1, I2, I3); - -endmodule - -(* blackbox, keep *) -module InPass4_frame_config_mux #( - parameter [3:0] O_reg = 0 -) ( - input CLK, - output O0, - output O1, - output O2, - output O3 -); -endmodule - -(* blackbox, keep *) -module OutPass4_frame_config_mux #( - parameter [3:0] I_reg = 0 -) ( - input I0, - input I1, - input I2, - input I3, - input CLK -); -endmodule - -(* keep *) -module IO_1_bidirectional_frame_config_pass (input CLK, T, I, output Q, O, (* iopad_external_pin *) inout PAD); - assign PAD = T ? 1'bz : I; - assign O = PAD; - reg Q_q; - always @(posedge CLK) Q_q <= O; - assign Q = Q_q; -endmodule - - -module MULADD (A7, A6, A5, A4, A3, A2, A1, A0, B7, B6, B5, B4, B3, B2, B1, B0, C19, C18, C17, C16, C15, C14, C13, C12, C11, C10, C9, C8, C7, C6, C5, C4, C3, C2, C1, C0, Q19, Q18, Q17, Q16, Q15, Q14, Q13, Q12, Q11, Q10, Q9, Q8, Q7, Q6, Q5, Q4, Q3, Q2, Q1, Q0, clr, CLK); - parameter A_reg = 1'b0; - parameter B_reg = 1'b0; - parameter C_reg = 1'b0; - parameter ACC = 1'b0; - parameter signExtension = 1'b0; - parameter ACCout = 1'b0; - - //parameter NoConfigBits = 6;// has to be adjusted manually (we don't use an arithmetic parser for the value) - // IMPORTANT: this has to be in a dedicated line - input A7;// operand A - input A6; - input A5; - input A4; - input A3; - input A2; - input A1; - input A0; - input B7;// operand B - input B6; - input B5; - input B4; - input B3; - input B2; - input B1; - input B0; - input C19;// operand C - input C18; - input C17; - input C16; - input C15; - input C14; - input C13; - input C12; - input C11; - input C10; - input C9; - input C8; - input C7; - input C6; - input C5; - input C4; - input C3; - input C2; - input C1; - input C0; - output Q19;// result - output Q18; - output Q17; - output Q16; - output Q15; - output Q14; - output Q13; - output Q12; - output Q11; - output Q10; - output Q9; - output Q8; - output Q7; - output Q6; - output Q5; - output Q4; - output Q3; - output Q2; - output Q1; - output Q0; - - input clr; - input CLK; // EXTERNAL // SHARED_PORT // ## the EXTERNAL keyword will send this sisgnal all the way to top and the //SHARED Allows multiple BELs using the same port (e.g. for exporting a clock to the top) - // GLOBAL all primitive pins that are connected to the switch matrix have to go before the GLOBAL label - - - wire [7:0] A; // port A read data - wire [7:0] B; // port B read data - wire [19:0] C; // port B read data - reg [7:0] A_q; // port A read data register - reg [7:0] B_q; // port B read data register - reg [19:0] C_q; // port B read data register - wire [7:0] OPA; // port A - wire [7:0] OPB; // port B - wire [19:0] OPC; // port B - reg [19:0] ACC_data ; // accumulator register - wire [19:0] sum;// port B read data register - wire [19:0] sum_in;// port B read data register - wire [15:0] product; - wire [19:0] product_extended; - - assign A = {A7,A6,A5,A4,A3,A2,A1,A0}; - assign B = {B7,B6,B5,B4,B3,B2,B1,B0}; - assign C = {C19,C18,C17,C16,C15,C14,C13,C12,C11,C10,C9,C8,C7,C6,C5,C4,C3,C2,C1,C0}; - - assign OPA = A_reg ? A_q : A; - assign OPB = B_reg ? B_q : B; - assign OPC = C_reg ? C_q : C; - - assign sum_in = ACC ? ACC_data : OPC;// we can - - assign product = OPA * OPB; - -// The sign extension was not tested - assign product_extended = signExtension ? {product[15],product[15],product[15],product[15],product} : {4'b0000,product}; - - assign sum = product_extended + sum_in; - - assign Q19 = ACCout ? ACC_data[19] : sum[19]; - assign Q18 = ACCout ? ACC_data[18] : sum[18]; - assign Q17 = ACCout ? ACC_data[17] : sum[17]; - assign Q16 = ACCout ? ACC_data[16] : sum[16]; - assign Q15 = ACCout ? ACC_data[15] : sum[15]; - assign Q14 = ACCout ? ACC_data[14] : sum[14]; - assign Q13 = ACCout ? ACC_data[13] : sum[13]; - assign Q12 = ACCout ? ACC_data[12] : sum[12]; - assign Q11 = ACCout ? ACC_data[11] : sum[11]; - assign Q10 = ACCout ? ACC_data[10] : sum[10]; - assign Q9 = ACCout ? ACC_data[9] : sum[9]; - assign Q8 = ACCout ? ACC_data[8] : sum[8]; - assign Q7 = ACCout ? ACC_data[7] : sum[7]; - assign Q6 = ACCout ? ACC_data[6] : sum[6]; - assign Q5 = ACCout ? ACC_data[5] : sum[5]; - assign Q4 = ACCout ? ACC_data[4] : sum[4]; - assign Q3 = ACCout ? ACC_data[3] : sum[3]; - assign Q2 = ACCout ? ACC_data[2] : sum[2]; - assign Q1 = ACCout ? ACC_data[1] : sum[1]; - assign Q0 = ACCout ? ACC_data[0] : sum[0]; - - always @ (posedge CLK) - begin - A_q <= A; - B_q <= B; - C_q <= C; - if (clr == 1'b1) begin - ACC_data <= 20'b00000000000000000000; - end else begin - ACC_data <= sum; - end - end - -endmodule - -module RegFile_32x4 (D0, D1, D2, D3, W_ADR0, W_ADR1, W_ADR2, W_ADR3, W_ADR4, W_en, AD0, AD1, AD2, AD3, A_ADR0, A_ADR1, A_ADR2, A_ADR3, A_ADR4, BD0, BD1, BD2, BD3, B_ADR0, B_ADR1, B_ADR2, B_ADR3, B_ADR4, CLK); - //parameter NoConfigBits = 2;// has to be adjusted manually (we don't use an arithmetic parser for the value) - parameter AD_reg = 1'b0; - parameter BD_reg = 1'b0; - // IMPORTANT: this has to be in a dedicated line - input D0; // Register File write port - input D1; - input D2; - input D3; - input W_ADR0; - input W_ADR1; - input W_ADR2; - input W_ADR3; - input W_ADR4; - input W_en; - - output AD0;// Register File read port A - output AD1; - output AD2; - output AD3; - input A_ADR0; - input A_ADR1; - input A_ADR2; - input A_ADR3; - input A_ADR4; - - output BD0;//Register File read port B - output BD1; - output BD2; - output BD3; - input B_ADR0; - input B_ADR1; - input B_ADR2; - input B_ADR3; - input B_ADR4; - - input CLK;// EXTERNAL // SHARED_PORT // ## the EXTERNAL keyword will send this sisgnal all the way to top and the //SHARED Allows multiple BELs using the same port (e.g. for exporting a clock to the top) - - // GLOBAL all primitive pins that are connected to the switch matrix have to go before the GLOBAL label - - - //type memtype is array (31 downto 0) of std_logic_vector(3 downto 0); // 32 entries of 4 bit - //signal mem : memtype := (others => (others => '0')); - reg [3:0] mem [31:0]; - - wire [4:0] W_ADR;// write address - wire [4:0] A_ADR;// port A read address - wire [4:0] B_ADR;// port B read address - - wire [3:0] D; // write data - wire [3:0] AD; // port A read data - wire [3:0] BD; // port B read data - - reg [3:0] AD_q; // port A read data register - reg [3:0] BD_q; // port B read data register - - integer i; - - assign W_ADR = {W_ADR4,W_ADR3,W_ADR2,W_ADR1,W_ADR0}; - assign A_ADR = {A_ADR4,A_ADR3,A_ADR2,A_ADR1,A_ADR0}; - assign B_ADR = {B_ADR4,B_ADR3,B_ADR2,B_ADR1,B_ADR0}; - - assign D = {D3,D2,D1,D0}; - - initial begin - for (i=0; i<32; i=i+1) begin - mem[i] = 4'b0000; - end - end - - always @ (posedge CLK) begin : P_write - if (W_en == 1'b1) begin - mem[W_ADR] <= D ; - end - end - - assign AD = mem[A_ADR]; - assign BD = mem[B_ADR]; - - always @ (posedge CLK) begin - AD_q <= AD; - BD_q <= BD; - end - - assign AD0 = AD_reg ? AD_q[0] : AD[0]; - assign AD1 = AD_reg ? AD_q[1] : AD[1]; - assign AD2 = AD_reg ? AD_q[2] : AD[2]; - assign AD3 = AD_reg ? AD_q[3] : AD[3]; - - assign BD0 = BD_reg ? BD_q[0] : BD[0]; - assign BD1 = BD_reg ? BD_q[1] : BD[1]; - assign BD2 = BD_reg ? BD_q[2] : BD[2]; - assign BD3 = BD_reg ? BD_q[3] : BD[3]; - -endmodule - -`ifdef EQUIV -`define COMPLEX_DFF -`endif - -`ifdef COMPLEX_DFF -module LUTFF_E ( - output reg O, - input CLK, E, D -); - initial O = 1'b0; - always @(posedge CLK) - if (E) - O <= D; -endmodule - -module LUTFF_SR ( - output reg O, - input CLK, R, D -); - initial O = 1'b0; - always @(posedge CLK) - if (R) - O <= 0; - else - O <= D; -endmodule - -module LUTFF_SS ( - output reg O, - input CLK, S, D -); - initial O = 1'b0; - always @(posedge CLK) - if (S) - O <= 1; - else - O <= D; -endmodule - -module LUTFF_ESR ( - output reg O, - input CLK, E, R, D -); - initial O = 1'b0; - always @(posedge CLK) - if (E) begin - if (R) - O <= 0; - else - O <= D; - end -endmodule - -module LUTFF_ESS ( - output reg O, - input CLK, E, S, D -); - initial O = 1'b0; - always @(posedge CLK) - if (E) begin - if (S) - O <= 1; - else - O <= D; - end -endmodule -`endif // COMPLEX_DFF diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index e22443d25..76973098e 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -55,8 +55,8 @@ struct SynthPass : public ScriptPass log(" -lut \n"); log(" perform synthesis for a k-LUT architecture (default 4).\n"); log("\n"); - log(" -plib \n"); - log(" use the specified Verilog file as a primitive library.\n"); + log(" -ff \n"); + log(" convert FFs to cell types via dfflegalize (can be specified multiple times).\n"); log("\n"); log(" -extra-plib \n"); log(" use the specified Verilog file for extra primitives (can be specified multiple\n"); @@ -83,10 +83,6 @@ struct SynthPass : public ScriptPass log(" enable automatic insertion of IO buffers (otherwise a wrapper\n"); log(" with manually inserted and constrained IO should be used.)\n"); log("\n"); - log(" -complex-dff\n"); - log(" enable support for FFs with enable and synchronous SR (must also be\n"); - log(" supported by the target fabric.)\n"); - log("\n"); log(" -noflatten\n"); log(" do not flatten design after elaboration\n"); log("\n"); @@ -112,23 +108,22 @@ struct SynthPass : public ScriptPass log("\n"); } - string top_module, json_file, blif_file, plib, fsm_opts, memory_opts, carry_mode; + string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode; std::vector extra_plib, extra_map; + std::vector> extra_ffs; - bool autotop, noalumacc, nofsm, noshare, noregfile, iopad, complexdff, flatten; + bool autotop, noalumacc, nofsm, noshare, noregfile, iopad, flatten; int lut; void clear_flags() override { top_module.clear(); - plib.clear(); autotop = false; lut = 4; noalumacc = false; nofsm = false; noshare = false; iopad = false; - complexdff = false; carry_mode = "none"; flatten = true; json_file = ""; @@ -174,8 +169,10 @@ struct SynthPass : public ScriptPass lut = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-plib" && argidx+1 < args.size()) { - plib = args[++argidx]; + if (args[argidx] == "-ff" && argidx+2 < args.size()) { + string cell = args[++argidx]; + string init = args[++argidx]; + extra_ffs.push_back({cell, init}); continue; } if (args[argidx] == "-extra-plib" && argidx+1 < args.size()) { @@ -214,10 +211,6 @@ struct SynthPass : public ScriptPass iopad = true; continue; } - if (args[argidx] == "-complex-dff") { - complexdff = true; - continue; - } if (args[argidx] == "-carry" && argidx+1 < args.size()) { carry_mode = args[++argidx]; if (carry_mode != "none" && carry_mode != "ha") @@ -245,11 +238,6 @@ struct SynthPass : public ScriptPass void script() override { - if (plib.empty()) - run(stringf("read_verilog %s -lib +/fabulous/prims.v", complexdff ? "-DCOMPLEX_DFF" : "")); - else - run("read_verilog -lib " + plib); - if (help_mode) { run("read_verilog -lib ", "(for each -extra-plib)"); } else for (auto lib : extra_plib) { @@ -339,13 +327,18 @@ struct SynthPass : public ScriptPass if (check_label("map_ffs")) { - if (complexdff) { - run("dfflegalize -cell $_DFF_P_ 0 -cell $_SDFF_PP?_ 0 -cell $_SDFFCE_PP?P_ 0 -cell $_DLATCH_?_ x", "with -complex-dff"); - } else { - run("dfflegalize -cell $_DFF_P_ 0 -cell $_DLATCH_?_ x", "without -complex-dff"); + if (help_mode) { + run("dfflegalize -cell ...", "(for each -ff)"); + } else if (!extra_map.empty()) { + std::string dff_str = "dfflegalize"; + for (const auto &[cell, init] : extra_ffs) + dff_str += stringf(" -cell %s %s", cell, init); + run(dff_str); } - run("techmap -map +/fabulous/latches_map.v"); - run("techmap -map +/fabulous/ff_map.v"); + run("opt_merge"); + } + + if (check_label("map_extra")) { if (help_mode) { run("techmap -map ...", "(for each -extra-map)"); } else if (!extra_map.empty()) { From c73fd4f70ba0a879e157a093b3c8f8734cc0c49e Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:15:38 +0200 Subject: [PATCH 07/18] fabulous: add `-extra-mlibmap` option, remove legacy `-noregfile` option - this allows to map to any memories - to map legacy register files, use: `-extra-plib regfile.v -extra-mlibmap ram_regfile.txt -extra-map regfile_map.v` Signed-off-by: Leo Moser --- techlibs/fabulous/ram_regfile.txt | 46 ----------------------------- techlibs/fabulous/regfile_map.v | 42 -------------------------- techlibs/fabulous/synth_fabulous.cc | 32 ++++++++++---------- 3 files changed, 17 insertions(+), 103 deletions(-) delete mode 100644 techlibs/fabulous/ram_regfile.txt delete mode 100644 techlibs/fabulous/regfile_map.v diff --git a/techlibs/fabulous/ram_regfile.txt b/techlibs/fabulous/ram_regfile.txt deleted file mode 100644 index af834b005..000000000 --- a/techlibs/fabulous/ram_regfile.txt +++ /dev/null @@ -1,46 +0,0 @@ -# Yosys doesn't support configurable sync/async ports. -# So we define three RAMs for 2xasync, 1xsync 1xasync and 2xsync - -ram distributed $__REGFILE_AA_ { - abits 5; - width 4; - cost 6; - port sw "W" { - clock posedge "CLK"; - } - port ar "A" { - } - port ar "B" { - } -} - -ram distributed $__REGFILE_SA_ { - abits 5; - width 4; - cost 5; - port sw "W" { - clock posedge "CLK"; - wrtrans all old; - } - port sr "A" { - clock posedge "CLK"; - } - port ar "B" { - } -} - -ram distributed $__REGFILE_SS_ { - abits 5; - width 4; - cost 4; - port sw "W" { - clock posedge "CLK"; - wrtrans all old; - } - port sr "A" { - clock posedge "CLK"; - } - port sr "B" { - clock posedge "CLK"; - } -} diff --git a/techlibs/fabulous/regfile_map.v b/techlibs/fabulous/regfile_map.v deleted file mode 100644 index 14342495e..000000000 --- a/techlibs/fabulous/regfile_map.v +++ /dev/null @@ -1,42 +0,0 @@ -(* techmap_celltype = "$__REGFILE_[AS][AS]_" *) -module \$__REGFILE_XX_ (...); - -parameter _TECHMAP_CELLTYPE_ = ""; -localparam [0:0] B_SYNC = _TECHMAP_CELLTYPE_[15:8] == "S"; -localparam [0:0] A_SYNC = _TECHMAP_CELLTYPE_[23:16] == "S"; - -localparam WIDTH = 4; -localparam ABITS = 5; - -input [WIDTH-1:0] PORT_W_WR_DATA; -input [ABITS-1:0] PORT_W_ADDR; -input PORT_W_WR_EN; - -output [WIDTH-1:0] PORT_A_RD_DATA; -input [ABITS-1:0] PORT_A_ADDR; - -output [WIDTH-1:0] PORT_B_RD_DATA; -input [ABITS-1:0] PORT_B_ADDR; - -// Unused - we have a shared clock - but keep techmap happy -input PORT_W_CLK; -input PORT_A_CLK; -input PORT_B_CLK; - -input CLK_CLK; - -RegFile_32x4 #( - .AD_reg(A_SYNC), - .BD_reg(B_SYNC) -) _TECHMAP_REPLACE_ ( - .D0(PORT_W_WR_DATA[0]), .D1(PORT_W_WR_DATA[1]), .D2(PORT_W_WR_DATA[2]), .D3(PORT_W_WR_DATA[3]), - .W_ADR0(PORT_W_ADDR[0]), .W_ADR1(PORT_W_ADDR[1]), .W_ADR2(PORT_W_ADDR[2]), .W_ADR3(PORT_W_ADDR[3]), .W_ADR4(PORT_W_ADDR[4]), - .W_en(PORT_W_WR_EN), - .AD0(PORT_A_RD_DATA[0]), .AD1(PORT_A_RD_DATA[1]), .AD2(PORT_A_RD_DATA[2]), .AD3(PORT_A_RD_DATA[3]), - .A_ADR0(PORT_A_ADDR[0]), .A_ADR1(PORT_A_ADDR[1]), .A_ADR2(PORT_A_ADDR[2]), .A_ADR3(PORT_A_ADDR[3]), .A_ADR4(PORT_A_ADDR[4]), - .BD0(PORT_B_RD_DATA[0]), .BD1(PORT_B_RD_DATA[1]), .BD2(PORT_B_RD_DATA[2]), .BD3(PORT_B_RD_DATA[3]), - .B_ADR0(PORT_B_ADDR[0]), .B_ADR1(PORT_B_ADDR[1]), .B_ADR2(PORT_B_ADDR[2]), .B_ADR3(PORT_B_ADDR[3]), .B_ADR4(PORT_B_ADDR[4]), - .CLK(CLK_CLK) -); - -endmodule diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 76973098e..32837af61 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -66,6 +66,10 @@ struct SynthPass : public ScriptPass log(" use the specified Verilog file for extra techmap rules (can be specified multiple\n"); log(" times).\n"); log("\n"); + log(" -extra-mlibmap \n"); + log(" use the provided library convert memory into hardware supported memory (can be specified\n"); + log(" multiple times).\n"); + log("\n"); log(" -nofsm\n"); log(" do not run FSM optimization\n"); log("\n"); @@ -76,9 +80,6 @@ struct SynthPass : public ScriptPass log(" -carry \n"); log(" carry mapping style (none, half-adders, ...) default=none\n"); log("\n"); - log(" -noregfile\n"); - log(" do not map register files\n"); - log("\n"); log(" -iopad\n"); log(" enable automatic insertion of IO buffers (otherwise a wrapper\n"); log(" with manually inserted and constrained IO should be used.)\n"); @@ -109,10 +110,10 @@ struct SynthPass : public ScriptPass } string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode; - std::vector extra_plib, extra_map; + std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; - bool autotop, noalumacc, nofsm, noshare, noregfile, iopad, flatten; + bool autotop, noalumacc, nofsm, noshare, iopad, flatten; int lut; void clear_flags() override @@ -183,6 +184,10 @@ struct SynthPass : public ScriptPass extra_map.push_back(args[++argidx]); continue; } + if (args[argidx] == "-extra-mlibmap" && argidx+1 < args.size()) { + extra_mlibmap.push_back(args[++argidx]); + continue; + } if (args[argidx] == "-nofsm") { nofsm = true; continue; @@ -203,10 +208,6 @@ struct SynthPass : public ScriptPass memory_opts += " -no-rw-check"; continue; } - if (args[argidx] == "-noregfile") { - noregfile = true; - continue; - } if (args[argidx] == "-iopad") { iopad = true; continue; @@ -294,12 +295,13 @@ struct SynthPass : public ScriptPass run("opt_clean"); } - if (check_label("map_ram", "(unless -noregfile)")) { - // RegFile extraction - if (!noregfile) { - run("memory_libmap -lib +/fabulous/ram_regfile.txt"); - run("techmap -map +/fabulous/regfile_map.v"); - } + if (check_label("map_memory")) { + if (help_mode) { + run("memory_libmap -lib ", "(for each -extra-mlibmap)"); + } else + for (auto lib : extra_mlibmap) { + run("memory_libmap -lib " + lib); + } } if (check_label("map_ffram")) { From ec8155e04044ad47319023b61b18c0dff053cee1 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:23:36 +0200 Subject: [PATCH 08/18] fabulous: convert `-iopad` to `-noiopad`, map to `$__FABULOUS_[I|O|T|IO]BUF` - with PCF support in nextpnr fabulous, `-iopad` is now the default - supply further mapping using `-extra-plib` Signed-off-by: Leo Moser --- techlibs/fabulous/io_map.v | 7 ------- techlibs/fabulous/synth_fabulous.cc | 30 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 techlibs/fabulous/io_map.v diff --git a/techlibs/fabulous/io_map.v b/techlibs/fabulous/io_map.v deleted file mode 100644 index d3736258c..000000000 --- a/techlibs/fabulous/io_map.v +++ /dev/null @@ -1,7 +0,0 @@ -module \$__FABULOUS_IBUF (input PAD, output O); - IO_1_bidirectional_frame_config_pass _TECHMAP_REPLACE_ (.PAD(PAD), .O(O), .T(1'b1)); -endmodule - -module \$__FABULOUS_OBUF (output PAD, input I); - IO_1_bidirectional_frame_config_pass _TECHMAP_REPLACE_ (.PAD(PAD), .I(I), .T(1'b0)); -endmodule diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 32837af61..401607424 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -80,9 +80,9 @@ struct SynthPass : public ScriptPass log(" -carry \n"); log(" carry mapping style (none, half-adders, ...) default=none\n"); log("\n"); - log(" -iopad\n"); - log(" enable automatic insertion of IO buffers (otherwise a wrapper\n"); - log(" with manually inserted and constrained IO should be used.)\n"); + log(" -noiopad\n"); + log(" disable I/O buffer insertion (useful for hierarchical or \n"); + log(" out-of-context flows).\n"); log("\n"); log(" -noflatten\n"); log(" do not flatten design after elaboration\n"); @@ -113,7 +113,7 @@ struct SynthPass : public ScriptPass std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; - bool autotop, noalumacc, nofsm, noshare, iopad, flatten; + bool autotop, noalumacc, nofsm, noshare, noiopad, flatten; int lut; void clear_flags() override @@ -124,7 +124,7 @@ struct SynthPass : public ScriptPass noalumacc = false; nofsm = false; noshare = false; - iopad = false; + noiopad = false; carry_mode = "none"; flatten = true; json_file = ""; @@ -208,8 +208,8 @@ struct SynthPass : public ScriptPass memory_opts += " -no-rw-check"; continue; } - if (args[argidx] == "-iopad") { - iopad = true; + if (args[argidx] == "-noiopad") { + noiopad = true; continue; } if (args[argidx] == "-carry" && argidx+1 < args.size()) { @@ -317,14 +317,13 @@ struct SynthPass : public ScriptPass run("opt -fast"); } - if (check_label("map_iopad", "(if -iopad)")) { - if (iopad || help_mode) { - run("opt -full"); - run("iopadmap -bits -outpad $__FABULOUS_OBUF I:PAD -inpad $__FABULOUS_IBUF O:PAD " - "-toutpad IO_1_bidirectional_frame_config_pass ~T:I:PAD " - "-tinoutpad IO_1_bidirectional_frame_config_pass ~T:O:I:PAD A:top", "(skip if '-noiopad')"); - run("techmap -map +/fabulous/io_map.v"); - } + if (check_label("map_iopad", "(skip if -noiopad)") && !noiopad) { + run("opt -full"); + run("iopadmap -bits " + "-inpad $__FABULOUS_IBUF OUT:PAD " + "-outpad $__FABULOUS_OBUF IN:PAD " + "-toutpad $__FABULOUS_TBUF EN:IN:PAD " + "-tinoutpad $__FABULOUS_IOBUF EN:OUT:IN:PAD"); } @@ -349,6 +348,7 @@ struct SynthPass : public ScriptPass map_str += stringf(" -map %s", map); run(map_str); } + run("simplemap"); run("clean"); } From d72cca29457c0a52aeb060751735566a2b3b9840 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:29:14 +0200 Subject: [PATCH 09/18] fabulous: add `-clkbuf-map` option, map to `$__FABULOUS_GBUF` Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 401607424..11fcefbb2 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -58,6 +58,9 @@ struct SynthPass : public ScriptPass log(" -ff \n"); log(" convert FFs to cell types via dfflegalize (can be specified multiple times).\n"); log("\n"); + log(" -clkbuf-map \n"); + log(" insert clock buffers using clkbufmap and map to the specified Verilog file.\n"); + log("\n"); log(" -extra-plib \n"); log(" use the specified Verilog file for extra primitives (can be specified multiple\n"); log(" times).\n"); @@ -109,7 +112,7 @@ struct SynthPass : public ScriptPass log("\n"); } - string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode; + string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, clkbuf_map; std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; @@ -176,6 +179,10 @@ struct SynthPass : public ScriptPass extra_ffs.push_back({cell, init}); continue; } + if (args[argidx] == "-clkbuf-map" && argidx+1 < args.size()) { + clkbuf_map = args[++argidx]; + continue; + } if (args[argidx] == "-extra-plib" && argidx+1 < args.size()) { extra_plib.push_back(args[++argidx]); continue; @@ -361,6 +368,18 @@ struct SynthPass : public ScriptPass run(stringf("techmap -D LUT_K=%d -map +/fabulous/cells_map.v", lut)); run("clean"); } + + if (check_label("map_clkbufs")) { + if (help_mode) { + run("clkbufmap -buf $__FABULOUS_GBUF OUT:IN", "(if -clkbuf-map )"); + run("techmap -map ", "(if -clkbuf-map )"); + } else if (clkbuf_map != "") { + run("clkbufmap -buf $__FABULOUS_GBUF OUT:IN"); + run(stringf("techmap -map %s", clkbuf_map)); + run("clean"); + } + } + if (check_label("check")) { run("hierarchy -check"); run("stat"); From f79c0ad21464b24c8b0fb013d7e1c1ad7a9286e8 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 14:44:39 +0200 Subject: [PATCH 10/18] fabulous: add `-multiplier-map` option, map to `$__FABULOUS_MUL` - an example: `-multiplier-map multiplier_map.v 8:8:2:2:10` Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 42 +++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 11fcefbb2..979db0165 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -61,6 +61,9 @@ struct SynthPass : public ScriptPass log(" -clkbuf-map \n"); log(" insert clock buffers using clkbufmap and map to the specified Verilog file.\n"); log("\n"); + log(" -multiplier-map \n"); + log(" convert multiplications to multiplier primitives and map to the specified Verilog file.\n"); + log("\n"); log(" -extra-plib \n"); log(" use the specified Verilog file for extra primitives (can be specified multiple\n"); log(" times).\n"); @@ -112,12 +115,12 @@ struct SynthPass : public ScriptPass log("\n"); } - string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, clkbuf_map; + string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, clkbuf_map, multiplier_map; std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; bool autotop, noalumacc, nofsm, noshare, noiopad, flatten; - int lut; + int lut, multiplier_a_max, multiplier_b_max, multiplier_a_min, multiplier_b_min, multiplier_y_min; void clear_flags() override { @@ -183,6 +186,15 @@ struct SynthPass : public ScriptPass clkbuf_map = args[++argidx]; continue; } + if (args[argidx] == "-multiplier-map" && argidx+6 < args.size()) { + multiplier_map = args[++argidx]; + multiplier_a_max = atoi(args[++argidx].c_str()); + multiplier_b_max = atoi(args[++argidx].c_str()); + multiplier_a_min = atoi(args[++argidx].c_str()); + multiplier_b_min = atoi(args[++argidx].c_str()); + multiplier_y_min = atoi(args[++argidx].c_str()); + continue; + } if (args[argidx] == "-extra-plib" && argidx+1 < args.size()) { extra_plib.push_back(args[++argidx]); continue; @@ -293,6 +305,32 @@ struct SynthPass : public ScriptPass run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); else if (lut) run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut)); + if (help_mode || multiplier_map != "") { + run("wreduce t:$mul"); + if (help_mode) { + run("techmap -map +/mul2dsp.v -map -D DSP_A_MAXWIDTH= -D DSP_B_MAXWIDTH= " + "-D DSP_A_MINWIDTH= -D DSP_B_MINWIDTH= -D DSP_Y_MINWIDTH= " + "-D DSP_NAME=$__FABULOUS_MUL", "(if -multiplier-map)"); + } else { + run(stringf("techmap -map +/mul2dsp.v -map %s -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d " + "-D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_Y_MINWIDTH=%d " + "-D DSP_NAME=$__FABULOUS_MUL", + multiplier_map.c_str(), + multiplier_a_max, + multiplier_b_max, + multiplier_a_min, + multiplier_b_min, + multiplier_y_min + ) + ); + } + run("select a:mul2dsp", " (if -multiplier-map)"); + run("setattr -unset mul2dsp", " (if -multiplier-map)"); + run("opt_expr -fine", " (if -multiplier-map)"); + run("wreduce", " (if -multiplier-map)"); + run("select -clear", " (if -multiplier-map)"); + run("chtype -set $mul t:$__soft_mul", "(if -multiplier-map)"); + } if (!noalumacc) run("alumacc", " (unless -noalumacc)"); if (!noshare) From aa84f4a13b91587f09b0e535ecb7335dfa354286 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 15:03:48 +0200 Subject: [PATCH 11/18] fabulous: remove legacy `arith_map.v` mapping Signed-off-by: Leo Moser --- techlibs/fabulous/arith_map.v | 64 ----------------------------- techlibs/fabulous/synth_fabulous.cc | 6 +-- 2 files changed, 3 insertions(+), 67 deletions(-) delete mode 100644 techlibs/fabulous/arith_map.v diff --git a/techlibs/fabulous/arith_map.v b/techlibs/fabulous/arith_map.v deleted file mode 100644 index 8cf5a234b..000000000 --- a/techlibs/fabulous/arith_map.v +++ /dev/null @@ -1,64 +0,0 @@ -`default_nettype none - -`ifdef ARITH_ha -(* techmap_celltype = "$alu" *) -module _80_fabulous_ha_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_CONSTMSK_CI_ = 0; -parameter _TECHMAP_CONSTVAL_CI_ = 0; - -(* force_downto *) -input [A_WIDTH-1:0] A; -(* force_downto *) -input [B_WIDTH-1:0] B; -input CI, BI; -(* force_downto *) -output [Y_WIDTH-1:0] X, Y, CO; - -(* 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; -wire [Y_WIDTH:0] CARRY; - - -LUT4_HA #( - .INIT(16'b0), - .I0MUX(1'b1) -) carry_statrt ( - .I0(), .I1(CI), .I2(CI), .I3(), - .Ci(), - .Co(CARRY[0]) -); - -// Carry chain -genvar i; -generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - LUT4_HA #( - .INIT(16'b1001_0110_1001_0110), // full adder sum over (I2, I1, I0) - .I0MUX(1'b1) - ) lut_i ( - .I0(), .I1(AA[i]), .I2(BB[i]), .I3(), - .Ci(CARRY[i]), - .O(Y[i]), - .Co(CARRY[i+1]) - ); - - assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); -end endgenerate - -assign X = AA ^ BB; - -endmodule -`endif diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 979db0165..e174da3ab 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -357,8 +357,7 @@ struct SynthPass : public ScriptPass if (check_label("map_gates")) { run("opt -full"); - run(stringf("techmap -map +/techmap.v -map +/fabulous/arith_map.v -D ARITH_%s", - help_mode ? "" : carry_mode.c_str())); + run("techmap -map +/techmap.v"); run("opt -fast"); } @@ -386,11 +385,12 @@ struct SynthPass : public ScriptPass if (check_label("map_extra")) { if (help_mode) { - run("techmap -map ...", "(for each -extra-map)"); + run("techmap -map -D ARITH_...", "(for each -extra-map)"); } else if (!extra_map.empty()) { std::string map_str = "techmap"; for (auto map : extra_map) map_str += stringf(" -map %s", map); + map_str += stringf(" -D ARITH_%s", carry_mode.c_str()); run(map_str); } run("simplemap"); From 253550421710b88388b064849c0378e6270ab5ec Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 15:05:11 +0200 Subject: [PATCH 12/18] fabulous: update CMakeLists.txt Signed-off-by: Leo Moser --- techlibs/fabulous/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/techlibs/fabulous/CMakeLists.txt b/techlibs/fabulous/CMakeLists.txt index 53091e5d3..7794a01e4 100644 --- a/techlibs/fabulous/CMakeLists.txt +++ b/techlibs/fabulous/CMakeLists.txt @@ -31,11 +31,4 @@ yosys_pass(synth_fabulous fabulous DATA_FILES cells_map.v - prims.v - latches_map.v - ff_map.v - ram_regfile.txt - regfile_map.v - io_map.v - arith_map.v ) From d50999ea45dec45146fd34cb28cc23f38a7bd509 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 24 Jun 2026 15:15:05 +0200 Subject: [PATCH 13/18] fabulous: format using clang Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 83 ++++++++++++----------------- 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index e174da3ab..525a2e2e8 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -17,17 +17,16 @@ * */ -#include "kernel/register.h" #include "kernel/celltypes.h" -#include "kernel/rtlil.h" #include "kernel/log.h" +#include "kernel/register.h" +#include "kernel/rtlil.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -struct SynthPass : public ScriptPass -{ - SynthPass() : ScriptPass("synth_fabulous", "FABulous synthesis script") { } +struct SynthPass : public ScriptPass { + SynthPass() : ScriptPass("synth_fabulous", "FABulous synthesis script") {} void help() override { @@ -143,28 +142,27 @@ struct SynthPass : public ScriptPass clear_flags(); size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-top" && argidx+1 < args.size()) { + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-top" && argidx + 1 < args.size()) { top_module = args[++argidx]; continue; } - if (args[argidx] == "-json" && argidx+1 < args.size()) { + if (args[argidx] == "-json" && argidx + 1 < args.size()) { json_file = args[++argidx]; continue; } - if (args[argidx] == "-blif" && argidx+1 < args.size()) { + if (args[argidx] == "-blif" && argidx + 1 < args.size()) { blif_file = args[++argidx]; continue; } - if (args[argidx] == "-run" && argidx+1 < args.size()) { - size_t pos = args[argidx+1].find(':'); + if (args[argidx] == "-run" && argidx + 1 < args.size()) { + size_t pos = args[argidx + 1].find(':'); if (pos == std::string::npos) { run_from = args[++argidx]; run_to = args[argidx]; } else { run_from = args[++argidx].substr(0, pos); - run_to = args[argidx].substr(pos+1); + run_to = args[argidx].substr(pos + 1); } continue; } @@ -172,21 +170,21 @@ struct SynthPass : public ScriptPass autotop = true; continue; } - if (args[argidx] == "-lut" && argidx+1 < args.size()) { + if (args[argidx] == "-lut" && argidx + 1 < args.size()) { lut = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-ff" && argidx+2 < args.size()) { + if (args[argidx] == "-ff" && argidx + 2 < args.size()) { string cell = args[++argidx]; string init = args[++argidx]; extra_ffs.push_back({cell, init}); continue; } - if (args[argidx] == "-clkbuf-map" && argidx+1 < args.size()) { + if (args[argidx] == "-clkbuf-map" && argidx + 1 < args.size()) { clkbuf_map = args[++argidx]; continue; } - if (args[argidx] == "-multiplier-map" && argidx+6 < args.size()) { + if (args[argidx] == "-multiplier-map" && argidx + 6 < args.size()) { multiplier_map = args[++argidx]; multiplier_a_max = atoi(args[++argidx].c_str()); multiplier_b_max = atoi(args[++argidx].c_str()); @@ -195,15 +193,15 @@ struct SynthPass : public ScriptPass multiplier_y_min = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-extra-plib" && argidx+1 < args.size()) { + if (args[argidx] == "-extra-plib" && argidx + 1 < args.size()) { extra_plib.push_back(args[++argidx]); continue; } - if (args[argidx] == "-extra-map" && argidx+1 < args.size()) { + if (args[argidx] == "-extra-map" && argidx + 1 < args.size()) { extra_map.push_back(args[++argidx]); continue; } - if (args[argidx] == "-extra-mlibmap" && argidx+1 < args.size()) { + if (args[argidx] == "-extra-mlibmap" && argidx + 1 < args.size()) { extra_mlibmap.push_back(args[++argidx]); continue; } @@ -231,7 +229,7 @@ struct SynthPass : public ScriptPass noiopad = true; continue; } - if (args[argidx] == "-carry" && argidx+1 < args.size()) { + if (args[argidx] == "-carry" && argidx + 1 < args.size()) { carry_mode = args[++argidx]; if (carry_mode != "none" && carry_mode != "ha") log_cmd_error("Unsupported carry style: %s\n", carry_mode); @@ -260,9 +258,10 @@ struct SynthPass : public ScriptPass { if (help_mode) { run("read_verilog -lib ", "(for each -extra-plib)"); - } else for (auto lib : extra_plib) { - run("read_verilog -lib " + lib); - } + } else + for (auto lib : extra_plib) { + run("read_verilog -lib " + lib); + } if (check_label("begin")) { if (top_module.empty()) { @@ -275,9 +274,7 @@ struct SynthPass : public ScriptPass run("proc"); } - - if (check_label("flatten", "(unless -noflatten)")) - { + if (check_label("flatten", "(unless -noflatten)")) { if (flatten) { run("check"); run("flatten"); @@ -287,7 +284,7 @@ struct SynthPass : public ScriptPass } if (check_label("coarse")) { - run("tribuf -logic"); + run("tribuf -logic"); run("deminout"); // synth pass @@ -309,21 +306,16 @@ struct SynthPass : public ScriptPass run("wreduce t:$mul"); if (help_mode) { run("techmap -map +/mul2dsp.v -map -D DSP_A_MAXWIDTH= -D DSP_B_MAXWIDTH= " - "-D DSP_A_MINWIDTH= -D DSP_B_MINWIDTH= -D DSP_Y_MINWIDTH= " - "-D DSP_NAME=$__FABULOUS_MUL", "(if -multiplier-map)"); + "-D DSP_A_MINWIDTH= -D DSP_B_MINWIDTH= -D DSP_Y_MINWIDTH= " + "-D DSP_NAME=$__FABULOUS_MUL", + "(if -multiplier-map)"); } else { run(stringf("techmap -map +/mul2dsp.v -map %s -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d " "-D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_Y_MINWIDTH=%d " "-D DSP_NAME=$__FABULOUS_MUL", - multiplier_map.c_str(), - multiplier_a_max, - multiplier_b_max, - multiplier_a_min, - multiplier_b_min, - multiplier_y_min - ) - ); - } + multiplier_map.c_str(), multiplier_a_max, multiplier_b_max, multiplier_a_min, multiplier_b_min, + multiplier_y_min)); + } run("select a:mul2dsp", " (if -multiplier-map)"); run("setattr -unset mul2dsp", " (if -multiplier-map)"); run("opt_expr -fine", " (if -multiplier-map)"); @@ -370,7 +362,6 @@ struct SynthPass : public ScriptPass "-tinoutpad $__FABULOUS_IOBUF EN:OUT:IN:PAD"); } - if (check_label("map_ffs")) { if (help_mode) { run("dfflegalize -cell ...", "(for each -ff)"); @@ -423,18 +414,14 @@ struct SynthPass : public ScriptPass run("stat"); } - if (check_label("blif")) - { - if (!blif_file.empty() || help_mode) - { + if (check_label("blif")) { + if (!blif_file.empty() || help_mode) { run("opt_clean -purge"); - run(stringf("write_blif -attr -cname -conn -param %s", - help_mode ? "" : blif_file.c_str())); + run(stringf("write_blif -attr -cname -conn -param %s", help_mode ? "" : blif_file.c_str())); } } - if (check_label("json")) - { + if (check_label("json")) { if (!json_file.empty() || help_mode) run(stringf("write_json %s", help_mode ? "" : json_file)); } From 4fac567673eb6bb8b7166d18bc983732b0d7c3bd Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Tue, 30 Jun 2026 14:56:48 +0200 Subject: [PATCH 14/18] fabulous: add `-arith-map` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 525a2e2e8..f79bf4a73 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -57,6 +57,9 @@ struct SynthPass : public ScriptPass { log(" -ff \n"); log(" convert FFs to cell types via dfflegalize (can be specified multiple times).\n"); log("\n"); + log(" -arith-map \n"); + log(" mapping file for arithmetic operations.\n"); + log("\n"); log(" -clkbuf-map \n"); log(" insert clock buffers using clkbufmap and map to the specified Verilog file.\n"); log("\n"); @@ -114,7 +117,7 @@ struct SynthPass : public ScriptPass { log("\n"); } - string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, clkbuf_map, multiplier_map; + string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, arith_map, clkbuf_map, multiplier_map; std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; @@ -180,6 +183,10 @@ struct SynthPass : public ScriptPass { extra_ffs.push_back({cell, init}); continue; } + if (args[argidx] == "-arith-map" && argidx + 1 < args.size()) { + arith_map = args[++argidx]; + continue; + } if (args[argidx] == "-clkbuf-map" && argidx + 1 < args.size()) { clkbuf_map = args[++argidx]; continue; @@ -347,6 +354,15 @@ struct SynthPass : public ScriptPass { run("opt -undriven -fine"); } + if (check_label("map_arith")) { + if (help_mode) { + run("techmap -map -D ARITH_"); + } else if (!arith_map.empty()) { + run(stringf("techmap -map %s -D ARITH_%s", arith_map.c_str(), carry_mode.c_str())); + } + run("clean"); + } + if (check_label("map_gates")) { run("opt -full"); run("techmap -map +/techmap.v"); @@ -376,12 +392,11 @@ struct SynthPass : public ScriptPass { if (check_label("map_extra")) { if (help_mode) { - run("techmap -map -D ARITH_...", "(for each -extra-map)"); + run("techmap -map ...", "(for each -extra-map)"); } else if (!extra_map.empty()) { std::string map_str = "techmap"; for (auto map : extra_map) map_str += stringf(" -map %s", map); - map_str += stringf(" -D ARITH_%s", carry_mode.c_str()); run(map_str); } run("simplemap"); From 655cb40d0f1569202639124e1fb66af90db8850b Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Tue, 30 Jun 2026 15:29:26 +0200 Subject: [PATCH 15/18] fabulous: add `--cells-map` option Signed-off-by: Leo Moser --- techlibs/fabulous/CMakeLists.txt | 1 - techlibs/fabulous/synth_fabulous.cc | 15 +++++++++++++-- {techlibs => tests/arch}/fabulous/cells_map.v | 0 3 files changed, 13 insertions(+), 3 deletions(-) rename {techlibs => tests/arch}/fabulous/cells_map.v (100%) diff --git a/techlibs/fabulous/CMakeLists.txt b/techlibs/fabulous/CMakeLists.txt index 7794a01e4..ff6c08a0d 100644 --- a/techlibs/fabulous/CMakeLists.txt +++ b/techlibs/fabulous/CMakeLists.txt @@ -30,5 +30,4 @@ yosys_pass(synth_fabulous DATA_DIR fabulous DATA_FILES - cells_map.v ) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index f79bf4a73..d77dd54a9 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -57,6 +57,9 @@ struct SynthPass : public ScriptPass { log(" -ff \n"); log(" convert FFs to cell types via dfflegalize (can be specified multiple times).\n"); log("\n"); + log(" -cells-map \n"); + log(" map luts to corresponding cells.\n"); + log("\n"); log(" -arith-map \n"); log(" mapping file for arithmetic operations.\n"); log("\n"); @@ -117,7 +120,7 @@ struct SynthPass : public ScriptPass { log("\n"); } - string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, arith_map, clkbuf_map, multiplier_map; + string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, cells_map, arith_map, clkbuf_map, multiplier_map; std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; @@ -183,6 +186,10 @@ struct SynthPass : public ScriptPass { extra_ffs.push_back({cell, init}); continue; } + if (args[argidx] == "-cells-map" && argidx + 1 < args.size()) { + cells_map = args[++argidx]; + continue; + } if (args[argidx] == "-arith-map" && argidx + 1 < args.size()) { arith_map = args[++argidx]; continue; @@ -409,7 +416,11 @@ struct SynthPass : public ScriptPass { } if (check_label("map_cells")) { - run(stringf("techmap -D LUT_K=%d -map +/fabulous/cells_map.v", lut)); + if (help_mode) { + run("techmap -D LUT_K= -map "); + } else if (!cells_map.empty()) { + run(stringf("techmap -D LUT_K=%d -map %s", lut, cells_map.c_str())); + } run("clean"); } diff --git a/techlibs/fabulous/cells_map.v b/tests/arch/fabulous/cells_map.v similarity index 100% rename from techlibs/fabulous/cells_map.v rename to tests/arch/fabulous/cells_map.v From e87d8e162e2aaf6079bd88b897f52975df15ce32 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Tue, 30 Jun 2026 14:57:21 +0200 Subject: [PATCH 16/18] fabulous: update tests for new options Signed-off-by: Leo Moser --- tests/arch/fabulous/arith_map.v | 65 ++++ tests/arch/fabulous/carry.ys | 2 +- tests/arch/fabulous/complexflop.ys | 2 +- tests/arch/fabulous/counter.ys | 2 +- tests/arch/fabulous/ff_map.v | 9 + tests/arch/fabulous/fsm.ys | 2 +- tests/arch/fabulous/io_map.v | 15 + tests/arch/fabulous/latches_map.v | 11 + tests/arch/fabulous/logic.ys | 2 +- tests/arch/fabulous/prims.v | 488 ++++++++++++++++++++++++++++ tests/arch/fabulous/ram_regfile.txt | 46 +++ tests/arch/fabulous/regfile.ys | 2 +- tests/arch/fabulous/regfile_map.v | 42 +++ tests/arch/fabulous/tribuf.ys | 2 +- 14 files changed, 683 insertions(+), 7 deletions(-) create mode 100644 tests/arch/fabulous/arith_map.v create mode 100644 tests/arch/fabulous/ff_map.v create mode 100644 tests/arch/fabulous/io_map.v create mode 100644 tests/arch/fabulous/latches_map.v create mode 100644 tests/arch/fabulous/prims.v create mode 100644 tests/arch/fabulous/ram_regfile.txt create mode 100644 tests/arch/fabulous/regfile_map.v diff --git a/tests/arch/fabulous/arith_map.v b/tests/arch/fabulous/arith_map.v new file mode 100644 index 000000000..b27729f08 --- /dev/null +++ b/tests/arch/fabulous/arith_map.v @@ -0,0 +1,65 @@ +`default_nettype none + +`ifdef ARITH_ha +(* techmap_celltype = "$alu" *) +module _80_fabulous_ha_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_CONSTMSK_CI_ = 0; +parameter _TECHMAP_CONSTVAL_CI_ = 0; + +(* force_downto *) +input [A_WIDTH-1:0] A; +(* force_downto *) +input [B_WIDTH-1:0] B; +input CI, BI; +(* force_downto *) +output [Y_WIDTH-1:0] X, Y, CO; + +(* 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; +wire [Y_WIDTH:0] CARRY; + + +LUT4_HA #( + .INIT(16'b0), + .I0MUX(1'b1) +) carry_start ( + .I0(), .I1(CI), .I2(CI), .I3(), + .Ci(), + .Co(CARRY[0]) +); + +// Carry chain +genvar i; +generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + LUT4_HA #( + .INIT(16'b1001_0110_1001_0110), // full adder sum over (I2, I1, I0) + .I0MUX(1'b1) + ) lut_i ( + .I0(), .I1(AA[i]), .I2(BB[i]), .I3(), + .Ci(CARRY[i]), + .O(Y[i]), + .Co(CARRY[i+1]) + ); + + assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); +end endgenerate + +assign X = AA ^ BB; + +endmodule +`endif + diff --git a/tests/arch/fabulous/carry.ys b/tests/arch/fabulous/carry.ys index bba969d37..b0e723c75 100644 --- a/tests/arch/fabulous/carry.ys +++ b/tests/arch/fabulous/carry.ys @@ -1,7 +1,7 @@ read_verilog ../common/add_sub.v hierarchy -top top proc -equiv_opt -assert -map +/fabulous/prims.v synth_fabulous -carry ha # equivalency check +equiv_opt -assert -map prims.v synth_fabulous -carry ha -noiopad -ff $_DFF_P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -cells-map cells_map.v -arith-map arith_map.v -extra-map ff_map.v -extra-map latches_map.v # 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-max 10 t:LUT4_HA diff --git a/tests/arch/fabulous/complexflop.ys b/tests/arch/fabulous/complexflop.ys index 13f4522b9..c5f300284 100644 --- a/tests/arch/fabulous/complexflop.ys +++ b/tests/arch/fabulous/complexflop.ys @@ -25,7 +25,7 @@ EOT hierarchy -top top proc flatten -equiv_opt -assert -map +/fabulous/prims.v synth_fabulous -complex-dff # equivalency check +equiv_opt -assert -map prims.v synth_fabulous -noiopad -ff $_DFF_P_ x -ff $_DFFE_PP_ x -ff $_SDFF_PP?_ x -ff $_SDFFCE_PP?P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -cells-map cells_map.v -extra-map arith_map.v -extra-map ff_map.v -extra-map latches_map.v # 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 diff --git a/tests/arch/fabulous/counter.ys b/tests/arch/fabulous/counter.ys index d79b378a6..32647caae 100644 --- a/tests/arch/fabulous/counter.ys +++ b/tests/arch/fabulous/counter.ys @@ -15,7 +15,7 @@ EOT hierarchy -top top proc flatten -equiv_opt -assert -map +/fabulous/prims.v synth_fabulous # equivalency check +equiv_opt -assert -map prims.v synth_fabulous -noiopad -ff $_DFF_P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -cells-map cells_map.v -arith-map arith_map.v -extra-map ff_map.v -extra-map latches_map.v # 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 diff --git a/tests/arch/fabulous/ff_map.v b/tests/arch/fabulous/ff_map.v new file mode 100644 index 000000000..0a03bd692 --- /dev/null +++ b/tests/arch/fabulous/ff_map.v @@ -0,0 +1,9 @@ +module \$_DFF_P_ (input D, C, output Q); LUTFF _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C)); endmodule + +module \$_DFFE_PP_ (input D, C, E, output Q); LUTFF_E _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .E(E)); endmodule + +module \$_SDFF_PP0_ (input D, C, R, output Q); LUTFF_SR _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .R(R)); endmodule +module \$_SDFF_PP1_ (input D, C, R, output Q); LUTFF_SS _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .S(R)); endmodule + +module \$_SDFFCE_PP0P_ (input D, C, E, R, output Q); LUTFF_ESR _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .E(E), .R(R)); endmodule +module \$_SDFFCE_PP1P_ (input D, C, E, R, output Q); LUTFF_ESS _TECHMAP_REPLACE_ (.D(D), .O(Q), .CLK(C), .E(E), .S(R)); endmodule diff --git a/tests/arch/fabulous/fsm.ys b/tests/arch/fabulous/fsm.ys index 5f7ae28dd..b00c8a388 100644 --- a/tests/arch/fabulous/fsm.ys +++ b/tests/arch/fabulous/fsm.ys @@ -3,7 +3,7 @@ hierarchy -top fsm proc flatten -equiv_opt -run :prove -map +/fabulous/prims.v synth_fabulous +equiv_opt -run :prove -map prims.v synth_fabulous -noiopad -ff $_DFF_P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -cells-map cells_map.v -arith-map arith_map.v -extra-map ff_map.v -extra-map latches_map.v async2sync miter -equiv -make_assert -flatten gold gate miter stat diff --git a/tests/arch/fabulous/io_map.v b/tests/arch/fabulous/io_map.v new file mode 100644 index 000000000..031bd4a35 --- /dev/null +++ b/tests/arch/fabulous/io_map.v @@ -0,0 +1,15 @@ +module \$__FABULOUS_IBUF (input PAD, output OUT); + IO_1_bidirectional_frame_config_pass _TECHMAP_REPLACE_ (.T(1'b1), .O(OUT), .PAD(PAD)); +endmodule + +module \$__FABULOUS_OBUF (output PAD, input IN); + IO_1_bidirectional_frame_config_pass _TECHMAP_REPLACE_ (.T(1'b0), .I(IN), .PAD(PAD)); +endmodule + +module \$__FABULOUS_TBUF (output PAD, output IN, output EN); + IO_1_bidirectional_frame_config_pass _TECHMAP_REPLACE_ (.T(!EN), .I(IN), .PAD(PAD)); +endmodule + +module \$__FABULOUS_IOBUF (inout PAD, output OUT, input IN, output EN); + IO_1_bidirectional_frame_config_pass _TECHMAP_REPLACE_ (.T(!EN), .I(IN), .O(OUT), .PAD(PAD)); +endmodule diff --git a/tests/arch/fabulous/latches_map.v b/tests/arch/fabulous/latches_map.v new file mode 100644 index 000000000..c28f88cf7 --- /dev/null +++ b/tests/arch/fabulous/latches_map.v @@ -0,0 +1,11 @@ +module \$_DLATCH_N_ (E, D, Q); + wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; + input E, D; + output Q = !E ? D : Q; +endmodule + +module \$_DLATCH_P_ (E, D, Q); + wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; + input E, D; + output Q = E ? D : Q; +endmodule diff --git a/tests/arch/fabulous/logic.ys b/tests/arch/fabulous/logic.ys index 730d9ab54..e5b4773e7 100644 --- a/tests/arch/fabulous/logic.ys +++ b/tests/arch/fabulous/logic.ys @@ -1,7 +1,7 @@ read_verilog ../common/logic.v hierarchy -top top proc -equiv_opt -assert -map +/fabulous/prims.v synth_fabulous # equivalency check +equiv_opt -assert -map prims.v synth_fabulous -noiopad -ff $_DFF_P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -cells-map cells_map.v -arith-map arith_map.v -extra-map ff_map.v -extra-map latches_map.v # 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-max 1 t:LUT1 diff --git a/tests/arch/fabulous/prims.v b/tests/arch/fabulous/prims.v new file mode 100644 index 000000000..dfb70dc85 --- /dev/null +++ b/tests/arch/fabulous/prims.v @@ -0,0 +1,488 @@ +module LUT1(output O, input I0); + parameter [1:0] INIT = 0; + assign O = I0 ? INIT[1] : INIT[0]; +endmodule + +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]; +endmodule + +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]; +endmodule + +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]; +endmodule + +module LUT4_HA(output O, Co, input I0, I1, I2, I3, Ci); + parameter [15:0] INIT = 0; + parameter I0MUX = 1'b1; + + 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]; + + wire I0_sel = I0MUX ? Ci : I0; + assign O = I0_sel ? s1[1] : s1[0]; + + assign Co = (Ci & I1) | (Ci & I2) | (I1 & I2); +endmodule + +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]; +endmodule + +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]; +endmodule + +module LUT55_FCY (output O, Co, input I0, I1, I2, I3, I4, Ci); + parameter [63:0] INIT = 0; + + wire comb1, comb2; + + LUT5 #(.INIT(INIT[31: 0])) l5_1 (.I0(I0), .I1(I1), .I2(I2), .I3(I3), .I4(I4), .O(comb1)); + LUT5 #(.INIT(INIT[63:32])) l5_2 (.I0(I0), .I1(I1), .I2(I2), .I3(I3), .I4(I4), .O(comb2)); + + assign O = comb1 ^ Ci; + assign Co = comb1 ? Ci : comb2; +endmodule + + +module LUTFF(input CLK, D, output reg O); + initial O = 1'b0; + always @ (posedge CLK) begin + O <= D; + end +endmodule + +module FABULOUS_MUX2(input I0, I1, S0, output O); + assign O = S0 ? I1 : I0; +endmodule + +module FABULOUS_MUX4(input I0, I1, I2, I3, S0, S1, output O); + wire A0 = S0 ? I1 : I0; + wire A1 = S0 ? I3 : I2; + assign O = S1 ? A1 : A0; +endmodule + +module FABULOUS_MUX8(input I0, I1, I2, I3, I4, I5, I6, I7, S0, S1, S2, output O); + wire A0 = S0 ? I1 : I0; + wire A1 = S0 ? I3 : I2; + wire A2 = S0 ? I5 : I4; + wire A3 = S0 ? I7 : I6; + wire B0 = S1 ? A1 : A0; + wire B1 = S1 ? A3 : A2; + assign O = S2 ? B1 : B0; +endmodule + +module FABULOUS_LC #( + parameter K = 4, + parameter [2**K-1:0] INIT = 0, + parameter DFF_ENABLE = 1'b0 +) ( + input CLK, + input [K-1:0] I, + output O, + output Q +); + wire f_wire; + + //LUT #(.K(K), .INIT(INIT)) lut_i(.I(I), .Q(f_wire)); + generate + if (K == 1) begin + LUT1 #(.INIT(INIT)) lut1 (.O(f_wire), .I0(I[0])); + end else + if (K == 2) begin + LUT2 #(.INIT(INIT)) lut2 (.O(f_wire), .I0(I[0]), .I1(I[1])); + end else + if (K == 3) begin + LUT3 #(.INIT(INIT)) lut3 (.O(f_wire), .I0(I[0]), .I1(I[1]), .I2(I[2])); + end else + if (K == 4) begin + LUT4 #(.INIT(INIT)) lut4 (.O(f_wire), .I0(I[0]), .I1(I[1]), .I2(I[2]), .I3(I[3])); + end + endgenerate + + LUTFF dff_i(.CLK(CLK), .D(f_wire), .Q(Q)); + + assign O = f_wire; +endmodule + +(* blackbox *) +module Global_Clock (output CLK); +`ifndef SYNTHESIS + initial CLK = 0; + always #10 CLK = ~CLK; +`endif +endmodule + +(* blackbox, keep *) +module InPass4_frame_config (input CLK, output O0, O1, O2, O3); + +endmodule + + +(* blackbox, keep *) +module OutPass4_frame_config (input CLK, I0, I1, I2, I3); + +endmodule + +(* blackbox, keep *) +module InPass4_frame_config_mux #( + parameter [3:0] O_reg = 0 +) ( + input CLK, + output O0, + output O1, + output O2, + output O3 +); +endmodule + +(* blackbox, keep *) +module OutPass4_frame_config_mux #( + parameter [3:0] I_reg = 0 +) ( + input I0, + input I1, + input I2, + input I3, + input CLK +); +endmodule + +(* keep *) +module IO_1_bidirectional_frame_config_pass (input CLK, T, I, output Q, O, (* iopad_external_pin *) inout PAD); + assign PAD = T ? 1'bz : I; + assign O = PAD; + reg Q_q; + always @(posedge CLK) Q_q <= O; + assign Q = Q_q; +endmodule + + +module MULADD (A7, A6, A5, A4, A3, A2, A1, A0, B7, B6, B5, B4, B3, B2, B1, B0, C19, C18, C17, C16, C15, C14, C13, C12, C11, C10, C9, C8, C7, C6, C5, C4, C3, C2, C1, C0, Q19, Q18, Q17, Q16, Q15, Q14, Q13, Q12, Q11, Q10, Q9, Q8, Q7, Q6, Q5, Q4, Q3, Q2, Q1, Q0, clr, CLK); + parameter A_reg = 1'b0; + parameter B_reg = 1'b0; + parameter C_reg = 1'b0; + parameter ACC = 1'b0; + parameter signExtension = 1'b0; + parameter ACCout = 1'b0; + + //parameter NoConfigBits = 6;// has to be adjusted manually (we don't use an arithmetic parser for the value) + // IMPORTANT: this has to be in a dedicated line + input A7;// operand A + input A6; + input A5; + input A4; + input A3; + input A2; + input A1; + input A0; + input B7;// operand B + input B6; + input B5; + input B4; + input B3; + input B2; + input B1; + input B0; + input C19;// operand C + input C18; + input C17; + input C16; + input C15; + input C14; + input C13; + input C12; + input C11; + input C10; + input C9; + input C8; + input C7; + input C6; + input C5; + input C4; + input C3; + input C2; + input C1; + input C0; + output Q19;// result + output Q18; + output Q17; + output Q16; + output Q15; + output Q14; + output Q13; + output Q12; + output Q11; + output Q10; + output Q9; + output Q8; + output Q7; + output Q6; + output Q5; + output Q4; + output Q3; + output Q2; + output Q1; + output Q0; + + input clr; + input CLK; // EXTERNAL // SHARED_PORT // ## the EXTERNAL keyword will send this sisgnal all the way to top and the //SHARED Allows multiple BELs using the same port (e.g. for exporting a clock to the top) + // GLOBAL all primitive pins that are connected to the switch matrix have to go before the GLOBAL label + + + wire [7:0] A; // port A read data + wire [7:0] B; // port B read data + wire [19:0] C; // port B read data + reg [7:0] A_q; // port A read data register + reg [7:0] B_q; // port B read data register + reg [19:0] C_q; // port B read data register + wire [7:0] OPA; // port A + wire [7:0] OPB; // port B + wire [19:0] OPC; // port B + reg [19:0] ACC_data ; // accumulator register + wire [19:0] sum;// port B read data register + wire [19:0] sum_in;// port B read data register + wire [15:0] product; + wire [19:0] product_extended; + + assign A = {A7,A6,A5,A4,A3,A2,A1,A0}; + assign B = {B7,B6,B5,B4,B3,B2,B1,B0}; + assign C = {C19,C18,C17,C16,C15,C14,C13,C12,C11,C10,C9,C8,C7,C6,C5,C4,C3,C2,C1,C0}; + + assign OPA = A_reg ? A_q : A; + assign OPB = B_reg ? B_q : B; + assign OPC = C_reg ? C_q : C; + + assign sum_in = ACC ? ACC_data : OPC;// we can + + assign product = OPA * OPB; + +// The sign extension was not tested + assign product_extended = signExtension ? {product[15],product[15],product[15],product[15],product} : {4'b0000,product}; + + assign sum = product_extended + sum_in; + + assign Q19 = ACCout ? ACC_data[19] : sum[19]; + assign Q18 = ACCout ? ACC_data[18] : sum[18]; + assign Q17 = ACCout ? ACC_data[17] : sum[17]; + assign Q16 = ACCout ? ACC_data[16] : sum[16]; + assign Q15 = ACCout ? ACC_data[15] : sum[15]; + assign Q14 = ACCout ? ACC_data[14] : sum[14]; + assign Q13 = ACCout ? ACC_data[13] : sum[13]; + assign Q12 = ACCout ? ACC_data[12] : sum[12]; + assign Q11 = ACCout ? ACC_data[11] : sum[11]; + assign Q10 = ACCout ? ACC_data[10] : sum[10]; + assign Q9 = ACCout ? ACC_data[9] : sum[9]; + assign Q8 = ACCout ? ACC_data[8] : sum[8]; + assign Q7 = ACCout ? ACC_data[7] : sum[7]; + assign Q6 = ACCout ? ACC_data[6] : sum[6]; + assign Q5 = ACCout ? ACC_data[5] : sum[5]; + assign Q4 = ACCout ? ACC_data[4] : sum[4]; + assign Q3 = ACCout ? ACC_data[3] : sum[3]; + assign Q2 = ACCout ? ACC_data[2] : sum[2]; + assign Q1 = ACCout ? ACC_data[1] : sum[1]; + assign Q0 = ACCout ? ACC_data[0] : sum[0]; + + always @ (posedge CLK) + begin + A_q <= A; + B_q <= B; + C_q <= C; + if (clr == 1'b1) begin + ACC_data <= 20'b00000000000000000000; + end else begin + ACC_data <= sum; + end + end + +endmodule + +module RegFile_32x4 (D0, D1, D2, D3, W_ADR0, W_ADR1, W_ADR2, W_ADR3, W_ADR4, W_en, AD0, AD1, AD2, AD3, A_ADR0, A_ADR1, A_ADR2, A_ADR3, A_ADR4, BD0, BD1, BD2, BD3, B_ADR0, B_ADR1, B_ADR2, B_ADR3, B_ADR4, CLK); + //parameter NoConfigBits = 2;// has to be adjusted manually (we don't use an arithmetic parser for the value) + parameter AD_reg = 1'b0; + parameter BD_reg = 1'b0; + // IMPORTANT: this has to be in a dedicated line + input D0; // Register File write port + input D1; + input D2; + input D3; + input W_ADR0; + input W_ADR1; + input W_ADR2; + input W_ADR3; + input W_ADR4; + input W_en; + + output AD0;// Register File read port A + output AD1; + output AD2; + output AD3; + input A_ADR0; + input A_ADR1; + input A_ADR2; + input A_ADR3; + input A_ADR4; + + output BD0;//Register File read port B + output BD1; + output BD2; + output BD3; + input B_ADR0; + input B_ADR1; + input B_ADR2; + input B_ADR3; + input B_ADR4; + + input CLK;// EXTERNAL // SHARED_PORT // ## the EXTERNAL keyword will send this sisgnal all the way to top and the //SHARED Allows multiple BELs using the same port (e.g. for exporting a clock to the top) + + // GLOBAL all primitive pins that are connected to the switch matrix have to go before the GLOBAL label + + + //type memtype is array (31 downto 0) of std_logic_vector(3 downto 0); // 32 entries of 4 bit + //signal mem : memtype := (others => (others => '0')); + reg [3:0] mem [31:0]; + + wire [4:0] W_ADR;// write address + wire [4:0] A_ADR;// port A read address + wire [4:0] B_ADR;// port B read address + + wire [3:0] D; // write data + wire [3:0] AD; // port A read data + wire [3:0] BD; // port B read data + + reg [3:0] AD_q; // port A read data register + reg [3:0] BD_q; // port B read data register + + integer i; + + assign W_ADR = {W_ADR4,W_ADR3,W_ADR2,W_ADR1,W_ADR0}; + assign A_ADR = {A_ADR4,A_ADR3,A_ADR2,A_ADR1,A_ADR0}; + assign B_ADR = {B_ADR4,B_ADR3,B_ADR2,B_ADR1,B_ADR0}; + + assign D = {D3,D2,D1,D0}; + + initial begin + for (i=0; i<32; i=i+1) begin + mem[i] = 4'b0000; + end + end + + always @ (posedge CLK) begin : P_write + if (W_en == 1'b1) begin + mem[W_ADR] <= D ; + end + end + + assign AD = mem[A_ADR]; + assign BD = mem[B_ADR]; + + always @ (posedge CLK) begin + AD_q <= AD; + BD_q <= BD; + end + + assign AD0 = AD_reg ? AD_q[0] : AD[0]; + assign AD1 = AD_reg ? AD_q[1] : AD[1]; + assign AD2 = AD_reg ? AD_q[2] : AD[2]; + assign AD3 = AD_reg ? AD_q[3] : AD[3]; + + assign BD0 = BD_reg ? BD_q[0] : BD[0]; + assign BD1 = BD_reg ? BD_q[1] : BD[1]; + assign BD2 = BD_reg ? BD_q[2] : BD[2]; + assign BD3 = BD_reg ? BD_q[3] : BD[3]; + +endmodule + +module LUTFF(input CLK, D, output reg O); + initial O = 1'b0; + always @ (posedge CLK) begin + O <= D; + end +endmodule + +module LUTFF_E ( + output reg O, + input CLK, E, D +); + initial O = 1'b0; + always @(posedge CLK) + if (E) + O <= D; +endmodule + +module LUTFF_SR ( + output reg O, + input CLK, R, D +); + initial O = 1'b0; + always @(posedge CLK) + if (R) + O <= 0; + else + O <= D; +endmodule + +module LUTFF_SS ( + output reg O, + input CLK, S, D +); + initial O = 1'b0; + always @(posedge CLK) + if (S) + O <= 1; + else + O <= D; +endmodule + +module LUTFF_ESR ( + output reg O, + input CLK, E, R, D +); + initial O = 1'b0; + always @(posedge CLK) + if (E) begin + if (R) + O <= 0; + else + O <= D; + end +endmodule + +module LUTFF_ESS ( + output reg O, + input CLK, E, S, D +); + initial O = 1'b0; + always @(posedge CLK) + if (E) begin + if (S) + O <= 1; + else + O <= D; + end +endmodule diff --git a/tests/arch/fabulous/ram_regfile.txt b/tests/arch/fabulous/ram_regfile.txt new file mode 100644 index 000000000..af834b005 --- /dev/null +++ b/tests/arch/fabulous/ram_regfile.txt @@ -0,0 +1,46 @@ +# Yosys doesn't support configurable sync/async ports. +# So we define three RAMs for 2xasync, 1xsync 1xasync and 2xsync + +ram distributed $__REGFILE_AA_ { + abits 5; + width 4; + cost 6; + port sw "W" { + clock posedge "CLK"; + } + port ar "A" { + } + port ar "B" { + } +} + +ram distributed $__REGFILE_SA_ { + abits 5; + width 4; + cost 5; + port sw "W" { + clock posedge "CLK"; + wrtrans all old; + } + port sr "A" { + clock posedge "CLK"; + } + port ar "B" { + } +} + +ram distributed $__REGFILE_SS_ { + abits 5; + width 4; + cost 4; + port sw "W" { + clock posedge "CLK"; + wrtrans all old; + } + port sr "A" { + clock posedge "CLK"; + } + port sr "B" { + clock posedge "CLK"; + } +} diff --git a/tests/arch/fabulous/regfile.ys b/tests/arch/fabulous/regfile.ys index 8d1eedef0..191c596d7 100644 --- a/tests/arch/fabulous/regfile.ys +++ b/tests/arch/fabulous/regfile.ys @@ -10,7 +10,7 @@ module sync_sync(input clk, we, input [4:0] aw, aa, ab, input [3:0] wd, output r endmodule EOT -synth_fabulous -top sync_sync +synth_fabulous -top sync_sync -noiopad -ff $_DFF_P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -arith-map arith_map.v -cells-map cells_map.v -extra-map ff_map.v -extra-map latches_map.v -extra-mlibmap ram_regfile.txt -extra-map regfile_map.v cd sync_sync select -assert-count 1 t:RegFile_32x4 diff --git a/tests/arch/fabulous/regfile_map.v b/tests/arch/fabulous/regfile_map.v new file mode 100644 index 000000000..14342495e --- /dev/null +++ b/tests/arch/fabulous/regfile_map.v @@ -0,0 +1,42 @@ +(* techmap_celltype = "$__REGFILE_[AS][AS]_" *) +module \$__REGFILE_XX_ (...); + +parameter _TECHMAP_CELLTYPE_ = ""; +localparam [0:0] B_SYNC = _TECHMAP_CELLTYPE_[15:8] == "S"; +localparam [0:0] A_SYNC = _TECHMAP_CELLTYPE_[23:16] == "S"; + +localparam WIDTH = 4; +localparam ABITS = 5; + +input [WIDTH-1:0] PORT_W_WR_DATA; +input [ABITS-1:0] PORT_W_ADDR; +input PORT_W_WR_EN; + +output [WIDTH-1:0] PORT_A_RD_DATA; +input [ABITS-1:0] PORT_A_ADDR; + +output [WIDTH-1:0] PORT_B_RD_DATA; +input [ABITS-1:0] PORT_B_ADDR; + +// Unused - we have a shared clock - but keep techmap happy +input PORT_W_CLK; +input PORT_A_CLK; +input PORT_B_CLK; + +input CLK_CLK; + +RegFile_32x4 #( + .AD_reg(A_SYNC), + .BD_reg(B_SYNC) +) _TECHMAP_REPLACE_ ( + .D0(PORT_W_WR_DATA[0]), .D1(PORT_W_WR_DATA[1]), .D2(PORT_W_WR_DATA[2]), .D3(PORT_W_WR_DATA[3]), + .W_ADR0(PORT_W_ADDR[0]), .W_ADR1(PORT_W_ADDR[1]), .W_ADR2(PORT_W_ADDR[2]), .W_ADR3(PORT_W_ADDR[3]), .W_ADR4(PORT_W_ADDR[4]), + .W_en(PORT_W_WR_EN), + .AD0(PORT_A_RD_DATA[0]), .AD1(PORT_A_RD_DATA[1]), .AD2(PORT_A_RD_DATA[2]), .AD3(PORT_A_RD_DATA[3]), + .A_ADR0(PORT_A_ADDR[0]), .A_ADR1(PORT_A_ADDR[1]), .A_ADR2(PORT_A_ADDR[2]), .A_ADR3(PORT_A_ADDR[3]), .A_ADR4(PORT_A_ADDR[4]), + .BD0(PORT_B_RD_DATA[0]), .BD1(PORT_B_RD_DATA[1]), .BD2(PORT_B_RD_DATA[2]), .BD3(PORT_B_RD_DATA[3]), + .B_ADR0(PORT_B_ADDR[0]), .B_ADR1(PORT_B_ADDR[1]), .B_ADR2(PORT_B_ADDR[2]), .B_ADR3(PORT_B_ADDR[3]), .B_ADR4(PORT_B_ADDR[4]), + .CLK(CLK_CLK) +); + +endmodule diff --git a/tests/arch/fabulous/tribuf.ys b/tests/arch/fabulous/tribuf.ys index 0dcf1cbab..65305756b 100644 --- a/tests/arch/fabulous/tribuf.ys +++ b/tests/arch/fabulous/tribuf.ys @@ -4,7 +4,7 @@ proc tribuf flatten synth -equiv_opt -assert -map +/fabulous/prims.v -map +/simcells.v synth_fabulous -iopad # equivalency check +equiv_opt -assert -map prims.v -map +/simcells.v synth_fabulous -ff $_DFF_P_ x -ff $_DLATCH_?_ x -extra-plib prims.v -cells-map cells_map.v -arith-map arith_map.v -extra-map ff_map.v -extra-map latches_map.v -extra-map io_map.v # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd tristate # Constrain all select calls below inside the top module select -assert-count 3 t:IO_1_bidirectional_frame_config_pass From b06c57b2bfdec18427fc09cb158ca34020b47525 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Wed, 1 Jul 2026 10:30:06 +0200 Subject: [PATCH 17/18] fabulous: remove unused `-blif` option Signed-off-by: Leo Moser --- techlibs/fabulous/synth_fabulous.cc | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index d77dd54a9..59358c07e 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -43,10 +43,6 @@ struct SynthPass : public ScriptPass { log(" -auto-top\n"); log(" automatically determine the top of the design hierarchy\n"); log("\n"); - log(" -blif \n"); - log(" write the design to the specified BLIF file. writing of an output file\n"); - log(" is omitted if this parameter is not specified.\n"); - log("\n"); log(" -json \n"); log(" write the design to the specified JSON file. writing of an output file\n"); log(" is omitted if this parameter is not specified.\n"); @@ -120,7 +116,7 @@ struct SynthPass : public ScriptPass { log("\n"); } - string top_module, json_file, blif_file, fsm_opts, memory_opts, carry_mode, cells_map, arith_map, clkbuf_map, multiplier_map; + string top_module, json_file, fsm_opts, memory_opts, carry_mode, cells_map, arith_map, clkbuf_map, multiplier_map; std::vector extra_plib, extra_map, extra_mlibmap; std::vector> extra_ffs; @@ -139,7 +135,6 @@ struct SynthPass : public ScriptPass { carry_mode = "none"; flatten = true; json_file = ""; - blif_file = ""; } void execute(std::vector args, RTLIL::Design *design) override @@ -157,10 +152,6 @@ struct SynthPass : public ScriptPass { json_file = args[++argidx]; continue; } - if (args[argidx] == "-blif" && argidx + 1 < args.size()) { - blif_file = args[++argidx]; - continue; - } if (args[argidx] == "-run" && argidx + 1 < args.size()) { size_t pos = args[argidx + 1].find(':'); if (pos == std::string::npos) { @@ -440,13 +431,6 @@ struct SynthPass : public ScriptPass { run("stat"); } - if (check_label("blif")) { - if (!blif_file.empty() || help_mode) { - run("opt_clean -purge"); - run(stringf("write_blif -attr -cname -conn -param %s", help_mode ? "" : blif_file.c_str())); - } - } - if (check_label("json")) { if (!json_file.empty() || help_mode) run(stringf("write_json %s", help_mode ? "" : json_file)); From cd8a613460f8a12cb0b7ff9efafab6c83e5cbd56 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Tue, 7 Jul 2026 08:19:11 +0200 Subject: [PATCH 18/18] fabulous: add to CODEOWNERS Signed-off-by: Leo Moser --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 4617c39bb..681854226 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -36,6 +36,7 @@ frontends/ast/ @widlarizer techlibs/intel_alm/ @Ravenslofty techlibs/gowin/ @pepijndevos techlibs/gatemate/ @pu-cc +techlibs/fabulous/ fpga.research.group@gmail.com # pyosys pyosys/* @donn