aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--passes/opt/opt_expr.cc8
-rw-r--r--passes/techmap/dfflegalize.cc2
-rw-r--r--techlibs/gowin/Makefile.inc1
-rw-r--r--techlibs/gowin/determine_init.cc72
-rw-r--r--techlibs/gowin/synth_gowin.cc2
-rw-r--r--techlibs/intel_alm/Makefile.inc2
-rw-r--r--techlibs/intel_alm/common/dff_map.v123
-rw-r--r--techlibs/intel_alm/common/dsp_map.v49
-rw-r--r--techlibs/intel_alm/common/dsp_sim.v35
-rw-r--r--techlibs/intel_alm/common/megafunction_bb.v28
-rw-r--r--techlibs/intel_alm/common/quartus_rename.v23
-rw-r--r--techlibs/intel_alm/synth_intel_alm.cc65
-rw-r--r--tests/arch/intel_alm/fsm.ys2
-rw-r--r--tests/arch/intel_alm/mul.ys23
-rw-r--r--tests/opt/bug2221.ys16
15 files changed, 245 insertions, 206 deletions
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 1051a59f2..649ad83a6 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -1596,6 +1596,14 @@ skip_identity:
log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n",
a_zeros, b_zeros, cell->name.c_str(), module->name.c_str());
+ if (y_zeros >= GetSize(sig_y)) {
+ module->connect(sig_y, RTLIL::SigSpec(0, GetSize(sig_y)));
+ module->remove(cell);
+
+ did_something = true;
+ goto next_cell;
+ }
+
if (a_zeros) {
cell->setPort(ID::A, sig_a.extract_end(a_zeros));
cell->parameters[ID::A_WIDTH] = GetSize(sig_a) - a_zeros;
diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc
index 7f2cdc6ac..b2fe90702 100644
--- a/passes/techmap/dfflegalize.cc
+++ b/passes/techmap/dfflegalize.cc
@@ -364,7 +364,7 @@ flip_dqi:
// Some DFF is supported with this init val. Just pick a type.
if (ff_type == FF_DFF) {
// Try adding a set or reset pin.
- for (auto new_type: {FF_ADFF0, FF_ADFF1, FF_SDFF0, FF_SDFF1})
+ for (auto new_type: {FF_SDFF0, FF_SDFF1, FF_ADFF0, FF_ADFF1})
if (supported_cells[new_type] & initmask) {
ff_type = new_type;
sig_r = State::S0;
diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc
index 0756e3bcf..e6a6be970 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -1,6 +1,5 @@
OBJS += techlibs/gowin/synth_gowin.o
-OBJS += techlibs/gowin/determine_init.o
GENFILES += techlibs/gowin/bram_init_16.vh
diff --git a/techlibs/gowin/determine_init.cc b/techlibs/gowin/determine_init.cc
deleted file mode 100644
index 15ff115de..000000000
--- a/techlibs/gowin/determine_init.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
- *
- * 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/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct DetermineInitPass : public Pass {
- DetermineInitPass() : Pass("determine_init", "Determine the init value of cells") { }
- void help() override
- {
- log("\n");
- log(" determine_init [selection]\n");
- log("\n");
- log("Determine the init value of cells that doesn't allow unknown init value.\n");
- log("\n");
- }
-
- Const determine_init(Const init)
- {
- for (int i = 0; i < GetSize(init); i++) {
- if (init[i] != State::S0 && init[i] != State::S1)
- init[i] = State::S0;
- }
-
- return init;
- }
-
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing DETERMINE_INIT pass (determine init value for cells).\n");
-
- extra_args(args, args.size(), design);
-
- int cnt = 0;
- for (auto module : design->selected_modules())
- {
- for (auto cell : module->selected_cells())
- {
- if (cell->type == ID(RAM16S4))
- {
- cell->setParam(ID(INIT_0), determine_init(cell->getParam(ID(INIT_0))));
- cell->setParam(ID(INIT_1), determine_init(cell->getParam(ID(INIT_1))));
- cell->setParam(ID(INIT_2), determine_init(cell->getParam(ID(INIT_2))));
- cell->setParam(ID(INIT_3), determine_init(cell->getParam(ID(INIT_3))));
- cnt++;
- }
- }
- }
- log_header(design, "Updated %d cells with determined init value.\n", cnt);
- }
-} DetermineInitPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 32d9cc0a5..1e82e1ed6 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -198,7 +198,7 @@ struct SynthGowinPass : public ScriptPass
{
run("memory_bram -rules +/gowin/lutrams.txt");
run("techmap -map +/gowin/lutrams_map.v");
- run("determine_init");
+ run("setundef -params -zero t:RAM16S4");
}
if (check_label("map_ffram"))
diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc
index 477be6353..552f00c65 100644
--- a/techlibs/intel_alm/Makefile.inc
+++ b/techlibs/intel_alm/Makefile.inc
@@ -10,6 +10,8 @@ $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/al
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dsp_sim.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dsp_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v))
# RAM
diff --git a/techlibs/intel_alm/common/dff_map.v b/techlibs/intel_alm/common/dff_map.v
index 962be670c..1a4b5d65a 100644
--- a/techlibs/intel_alm/common/dff_map.v
+++ b/techlibs/intel_alm/common/dff_map.v
@@ -1,124 +1,13 @@
`default_nettype none
-// D flip-flops
-module \$_DFF_P_ (input D, C, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+// D flip-flop with async reset and enable
+module \$_DFFE_PN0P_ (input D, C, R, E, output Q);
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop that initialises to one");
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
endmodule
-module \$_DFF_N_ (input D, C, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+// D flip-flop with sync reset and enable (enable has priority)
+module \$_SDFFCE_PP0P_ (input D, C, R, E, output Q);
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop that initialises to one");
-endmodule
-
-// D flip-flops with reset
-module \$_DFF_PP0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-module \$_DFF_PN0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-module \$_DFF_NP0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-module \$_DFF_NN0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-// D flip-flops with set
-module \$_DFF_PP1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
- assign Q = ~Q_tmp;
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-module \$_DFF_PN1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-module \$_DFF_NP1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
- assign Q = ~Q_tmp;
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-module \$_DFF_NN1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
- assign Q = ~Q_tmp;
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-// D flip-flops with clock enable
-module \$_DFFE_PP_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
-endmodule
-
-module \$_DFFE_PN_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
-endmodule
-
-module \$_DFFE_NP_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
-endmodule
-
-module \$_DFFE_NN_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(R), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
endmodule
diff --git a/techlibs/intel_alm/common/dsp_map.v b/techlibs/intel_alm/common/dsp_map.v
new file mode 100644
index 000000000..d1bc25e65
--- /dev/null
+++ b/techlibs/intel_alm/common/dsp_map.v
@@ -0,0 +1,49 @@
+module __MUL27X27(A, B, Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+parameter A_WIDTH = 27;
+parameter B_WIDTH = 27;
+parameter Y_WIDTH = 54;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+MISTRAL_MUL27X27 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+
+endmodule
+
+
+module __MUL18X18(A, B, Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+parameter A_WIDTH = 18;
+parameter B_WIDTH = 18;
+parameter Y_WIDTH = 36;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+MISTRAL_MUL18X18 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+
+endmodule
+
+
+module __MUL9X9(A, B, Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+parameter A_WIDTH = 9;
+parameter B_WIDTH = 9;
+parameter Y_WIDTH = 18;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+MISTRAL_MUL9X9 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+
+endmodule
diff --git a/techlibs/intel_alm/common/dsp_sim.v b/techlibs/intel_alm/common/dsp_sim.v
new file mode 100644
index 000000000..5dc4c02de
--- /dev/null
+++ b/techlibs/intel_alm/common/dsp_sim.v
@@ -0,0 +1,35 @@
+(* abc9_box *)
+module MISTRAL_MUL27x27(input [26:0] A, input [26:0] B, output [53:0] Y);
+
+specify
+ (A *> Y) = 4057;
+ (B *> Y) = 4057;
+endspecify
+
+assign Y = $signed(A) * $signed(B);
+
+endmodule
+
+(* abc9_box *)
+module MISTRAL_MUL18X18(input [17:0] A, input [17:0] B, output [35:0] Y);
+
+specify
+ (A *> Y) = 4057;
+ (B *> Y) = 4057;
+endspecify
+
+assign Y = $signed(A) * $signed(B);
+
+endmodule
+
+(* abc9_box *)
+module MISTRAL_MUL9X9(input [8:0] A, input [8:0] B, output [17:0] Y);
+
+specify
+ (A *> Y) = 4057;
+ (B *> Y) = 4057;
+endspecify
+
+assign Y = $signed(A) * $signed(B);
+
+endmodule
diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v
index c749fa70b..b5a3d8892 100644
--- a/techlibs/intel_alm/common/megafunction_bb.v
+++ b/techlibs/intel_alm/common/megafunction_bb.v
@@ -129,3 +129,31 @@ output [data_width-1:0] portbdataout;
input ena0, clk0, clk1;
endmodule
+
+(* blackbox *)
+module cyclonev_mac(ax, ay, resulta);
+
+parameter ax_width = 9;
+parameter ay_scan_in_width = 9;
+parameter result_a_width = 18;
+parameter operation_mode = "M9x9";
+
+input [ax_width-1:0] ax;
+input [ay_scan_in_width-1:0] ay;
+output [result_a_width-1:0] resulta;
+
+endmodule
+
+(* blackbox *)
+module cyclone10gx_mac(ax, ay, resulta);
+
+parameter ax_width = 18;
+parameter ay_scan_in_width = 18;
+parameter result_a_width = 36;
+parameter operation_mode = "M18X18_FULL";
+
+input [ax_width-1:0] ax;
+input [ay_scan_in_width-1:0] ay;
+output [result_a_width-1:0] resulta;
+
+endmodule \ No newline at end of file
diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v
index c40a4e02d..46ef2aa0d 100644
--- a/techlibs/intel_alm/common/quartus_rename.v
+++ b/techlibs/intel_alm/common/quartus_rename.v
@@ -1,9 +1,11 @@
`ifdef cyclonev
`define LCELL cyclonev_lcell_comb
+`define MAC cyclonev_mac
`define MLAB cyclonev_mlab_cell
`endif
`ifdef cyclone10gx
`define LCELL cyclone10gx_lcell_comb
+`define MAC cyclone10gx_mac
`define MLAB cyclone10gx_mlab_cell
`endif
@@ -119,3 +121,24 @@ module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1
);
endmodule
+
+
+module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y);
+
+`MAC #(.ax_width(27), .ay_scan_in_width(27), .result_a_width(54), .operation_mode("M27x27")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y));
+
+endmodule
+
+
+module MISTRAL_MUL18X18(input [17:0] A, B, output [35:0] Y);
+
+`MAC #(.ax_width(18), .ay_scan_in_width(18), .result_a_width(36), .operation_mode("M18x18_FULL")) _TECHMAP_REPLACE_ (.ax(B), .ay(A), .resulta(Y));
+
+endmodule
+
+
+module MISTRAL_MUL9X9(input [8:0] A, B, output [17:0] Y);
+
+`MAC #(.ax_width(9), .ay_scan_in_width(9), .result_a_width(18), .operation_mode("M9x9")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y));
+
+endmodule
diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc
index 4bc943cb2..b751e8413 100644
--- a/techlibs/intel_alm/synth_intel_alm.cc
+++ b/techlibs/intel_alm/synth_intel_alm.cc
@@ -69,13 +69,16 @@ struct SynthIntelALMPass : public ScriptPass {
log(" -nobram\n");
log(" do not use block RAM cells in output netlist\n");
log("\n");
+ log(" -nodsp\n");
+ log(" do not map multipliers to MISTRAL_MUL cells\n");
+ log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_opt, family_opt, bram_type, vout_file;
- bool flatten, quartus, nolutram, nobram, dff;
+ bool flatten, quartus, nolutram, nobram, dff, nodsp;
void clear_flags() override
{
@@ -88,6 +91,7 @@ struct SynthIntelALMPass : public ScriptPass {
nolutram = false;
nobram = false;
dff = false;
+ nodsp = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -130,6 +134,10 @@ struct SynthIntelALMPass : public ScriptPass {
nobram = true;
continue;
}
+ if (args[argidx] == "-nodsp") {
+ nodsp = true;
+ continue;
+ }
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
@@ -169,9 +177,11 @@ struct SynthIntelALMPass : public ScriptPass {
}
if (check_label("begin")) {
- run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
+ if (family_opt == "cyclonev")
+ run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
+ run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dsp_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s -icells +/intel_alm/common/abc9_model.v", family_opt.c_str()));
@@ -181,16 +191,46 @@ struct SynthIntelALMPass : public ScriptPass {
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
- if (flatten && check_label("flatten", "(unless -noflatten)")) {
+ if (check_label("coarse")) {
run("proc");
- run("flatten");
+ if (flatten || help_mode)
+ run("flatten", "(skip if -noflatten)");
run("tribuf -logic");
run("deminout");
- }
-
- if (check_label("coarse")) {
- run("synth -run coarse -lut 6");
- run("techmap -map +/intel_alm/common/arith_alm_map.v");
+ run("opt_expr");
+ run("opt_clean");
+ run("check");
+ run("opt");
+ run("wreduce");
+ run("peepopt");
+ run("opt_clean");
+ run("share");
+ run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
+ run("opt_expr");
+ run("opt_clean");
+ if (help_mode) {
+ run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
+ } else if (!nodsp) {
+ // Cyclone V supports 9x9 multiplication, Cyclone 10 GX does not.
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27 -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=19 -D DSP_SIGNEDONLY -D DSP_NAME=__MUL27X27");
+ run("chtype -set $mul t:$__soft_mul");
+ if (family_opt == "cyclonev") {
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10 -D DSP_SIGNEDONLY -D DSP_NAME=__MUL18X18");
+ run("chtype -set $mul t:$__soft_mul");
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_SIGNEDONLY -D DSP_NAME=__MUL9X9");
+ run("chtype -set $mul t:$__soft_mul");
+ } else if (family_opt == "cyclone10gx") {
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_SIGNEDONLY -D DSP_NAME=__MUL18X18");
+ run("chtype -set $mul t:$__soft_mul");
+ }
+ }
+ run("alumacc");
+ run("techmap -map +/intel_alm/common/arith_alm_map.v -map +/intel_alm/common/dsp_map.v");
+ run("opt");
+ run("fsm");
+ run("opt -fast");
+ run("memory -nomap");
+ run("opt_clean");
}
if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
@@ -208,11 +248,10 @@ struct SynthIntelALMPass : public ScriptPass {
}
if (check_label("map_ffs")) {
+ run("techmap");
run("dff2dffe");
- // As mentioned in common/dff_sim.v, Intel flops power up to zero,
- // so use `zinit` to add inverters where needed.
- run("zinit");
- run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
+ run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0");
+ run("techmap -map +/intel_alm/common/dff_map.v");
run("opt -full -undriven -mux_undef");
run("clean -purge");
}
diff --git a/tests/arch/intel_alm/fsm.ys b/tests/arch/intel_alm/fsm.ys
index 02e4a9789..60cd23373 100644
--- a/tests/arch/intel_alm/fsm.ys
+++ b/tests/arch/intel_alm/fsm.ys
@@ -15,6 +15,6 @@ select -assert-count 6 t:MISTRAL_FF
select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1
select -assert-count 1 t:MISTRAL_ALUT3
select -assert-max 1 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1
-select -assert-max 5 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4
+select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4
select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2
select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
diff --git a/tests/arch/intel_alm/mul.ys b/tests/arch/intel_alm/mul.ys
new file mode 100644
index 000000000..92f00156a
--- /dev/null
+++ b/tests/arch/intel_alm/mul.ys
@@ -0,0 +1,23 @@
+read_verilog ../common/mul.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # 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 1 t:MISTRAL_MUL9X9
+select -assert-none t:MISTRAL_MUL9X9 %% t:* %D
+
+design -reset
+read_verilog ../common/mul.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx # 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
+
+# Cyclone 10 GX does not have 9x9 multipliers, so we use 18x18.
+select -assert-count 1 t:MISTRAL_MUL18X18
+select -assert-none t:MISTRAL_MUL18X18 %% t:* %D
diff --git a/tests/opt/bug2221.ys b/tests/opt/bug2221.ys
new file mode 100644
index 000000000..8ac380243
--- /dev/null
+++ b/tests/opt/bug2221.ys
@@ -0,0 +1,16 @@
+read_verilog <<EOT
+module test (
+ input [1:0] a,
+ input [1:0] b,
+ output [5:0] y
+);
+
+wire [5:0] aa = {a, 4'h0};
+wire [5:0] bb = {b, 4'h0};
+
+assign y = aa * bb;
+
+endmodule
+EOT
+
+equiv_opt -assert opt_expr