diff options
Diffstat (limited to 'techlibs/intel_alm')
-rw-r--r-- | techlibs/intel_alm/Makefile.inc | 5 | ||||
-rw-r--r-- | techlibs/intel_alm/common/abc9_map.v | 18 | ||||
-rw-r--r-- | techlibs/intel_alm/common/abc9_model.v | 10 | ||||
-rw-r--r-- | techlibs/intel_alm/common/abc9_unmap.v | 11 | ||||
-rw-r--r-- | techlibs/intel_alm/common/dff_map.v | 123 | ||||
-rw-r--r-- | techlibs/intel_alm/common/dff_sim.v | 41 | ||||
-rw-r--r-- | techlibs/intel_alm/common/dsp_map.v | 49 | ||||
-rw-r--r-- | techlibs/intel_alm/common/dsp_sim.v | 35 | ||||
-rw-r--r-- | techlibs/intel_alm/common/megafunction_bb.v | 28 | ||||
-rw-r--r-- | techlibs/intel_alm/common/mem_sim.v | 10 | ||||
-rw-r--r-- | techlibs/intel_alm/common/quartus_rename.v | 23 | ||||
-rw-r--r-- | techlibs/intel_alm/synth_intel_alm.cc | 90 |
12 files changed, 296 insertions, 147 deletions
diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc index ed6c4510b..552f00c65 100644 --- a/techlibs/intel_alm/Makefile.inc +++ b/techlibs/intel_alm/Makefile.inc @@ -2,11 +2,16 @@ OBJS += techlibs/intel_alm/synth_intel_alm.o # Techmap +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_map.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_unmap.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_model.v)) $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v)) $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v)) $(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/abc9_map.v b/techlibs/intel_alm/common/abc9_map.v new file mode 100644 index 000000000..9d11bb240 --- /dev/null +++ b/techlibs/intel_alm/common/abc9_map.v @@ -0,0 +1,18 @@ +// This file exists to map purely-synchronous flops to ABC9 flops, while +// mapping flops with asynchronous-clear as boxes, this is because ABC9 +// doesn't support asynchronous-clear flops in sequential synthesis. + +module MISTRAL_FF( + input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +parameter _TECHMAP_CONSTMSK_ACLR_ = 1'b0; + +// If the async-clear is constant, we assume it's disabled. +if (_TECHMAP_CONSTMSK_ACLR_ != 1'b0) + $__MISTRAL_FF_SYNCONLY _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q)); +else + wire _TECHMAP_FAIL_ = 1; + +endmodule diff --git a/techlibs/intel_alm/common/abc9_model.v b/techlibs/intel_alm/common/abc9_model.v new file mode 100644 index 000000000..8f06d3835 --- /dev/null +++ b/techlibs/intel_alm/common/abc9_model.v @@ -0,0 +1,10 @@ +// This is a purely-synchronous flop, that ABC9 can use for sequential synthesis. +(* abc9_flop, lib_whitebox *) +module $__MISTRAL_FF_SYNCONLY ( + input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +MISTRAL_FF ff (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .ACLR(1'b1), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q)); + +endmodule diff --git a/techlibs/intel_alm/common/abc9_unmap.v b/techlibs/intel_alm/common/abc9_unmap.v new file mode 100644 index 000000000..4b28866a3 --- /dev/null +++ b/techlibs/intel_alm/common/abc9_unmap.v @@ -0,0 +1,11 @@ +// After performing sequential synthesis, map the synchronous flops back to +// standard MISTRAL_FF flops. + +module $__MISTRAL_FF_SYNCONLY ( + input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +MISTRAL_FF _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ACLR(1'b1), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q)); + +endmodule 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/dff_sim.v b/techlibs/intel_alm/common/dff_sim.v index 32444dd46..9ff8f9f67 100644 --- a/techlibs/intel_alm/common/dff_sim.v +++ b/techlibs/intel_alm/common/dff_sim.v @@ -53,23 +53,44 @@ // Q: data output // // Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements. + +`ifdef cyclonev +`define SYNCPATH 262 +`define SYNCSETUP 522 +`define COMBPATH 0 +`endif +`ifdef cyclone10gx +`define SYNCPATH 219 +`define SYNCSETUP 268 +`define COMBPATH 0 +`endif + +// fallback for when a family isn't detected (e.g. when techmapping for equivalence) +`ifndef SYNCPATH +`define SYNCPATH 0 +`define SYNCSETUP 0 +`define COMBPATH 0 +`endif + +(* abc9_box, lib_whitebox *) module MISTRAL_FF( input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, output reg Q ); -`ifdef cyclonev -specify - (posedge CLK => (Q : DATAIN)) = 262; - $setup(DATAIN, posedge CLK, 522); -endspecify -`endif -`ifdef cyclone10gx specify - (posedge CLK => (Q : DATAIN)) = 219; - $setup(DATAIN, posedge CLK, 268); + if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = `SYNCPATH; + if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = `SYNCPATH; + if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = `SYNCPATH; + + $setup(DATAIN, posedge CLK, `SYNCSETUP); + $setup(ENA, posedge CLK, `SYNCSETUP); + $setup(SCLR, posedge CLK, `SYNCSETUP); + $setup(SLOAD, posedge CLK, `SYNCSETUP); + $setup(SDATA, posedge CLK, `SYNCSETUP); + + if (ACLR === 1'b0) (ACLR => Q) = `COMBPATH; endspecify -`endif initial begin // Altera flops initialise to zero. 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/mem_sim.v b/techlibs/intel_alm/common/mem_sim.v index ae79b19a4..f6f9ecb02 100644 --- a/techlibs/intel_alm/common/mem_sim.v +++ b/techlibs/intel_alm/common/mem_sim.v @@ -48,10 +48,20 @@ // the following model because it's very difficult to trigger this in practice // as clock cycles will be much longer than any potential blip of 'x, so the // model can be treated as always returning a defined result. + +(* abc9_box, lib_whitebox *) module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); reg [31:0] mem = 32'b0; +// TODO +specify + $setup(A1ADDR, posedge CLK1, 0); + $setup(A1DATA, posedge CLK1, 0); + + (B1ADDR *> B1DATA) = 0; +endspecify + always @(posedge CLK1) if (A1EN) mem[A1ADDR] <= A1DATA; 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 fabfc9003..b751e8413 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -38,20 +38,26 @@ struct SynthIntelALMPass : public ScriptPass { log("This command runs synthesis for ALM-based Intel FPGAs.\n"); log("\n"); log(" -top <module>\n"); - log(" use the specified module as top module (default='top')\n"); + log(" use the specified module as top module\n"); log("\n"); log(" -family <family>\n"); log(" target one of:\n"); log(" \"cyclonev\" - Cyclone V (default)\n"); log(" \"cyclone10gx\" - Cyclone 10GX\n"); log("\n"); - log(" -quartus\n"); - log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n"); - log("\n"); log(" -vqm <file>\n"); log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); log(" output file is omitted if this parameter is not specified. Implies -quartus.\n"); log("\n"); + log(" -noflatten\n"); + log(" do not flatten design before synthesis; useful for per-module area statistics\n"); + log("\n"); + log(" -quartus\n"); + log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n"); + log("\n"); + log(" -dff\n"); + log(" pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)\n"); + log("\n"); log(" -run <from_label>:<to_label>\n"); log(" only run the commands between the labels (see below). an empty\n"); log(" from label is synonymous to 'begin', and empty to label is\n"); @@ -63,8 +69,8 @@ struct SynthIntelALMPass : public ScriptPass { log(" -nobram\n"); log(" do not use block RAM cells in output netlist\n"); log("\n"); - log(" -noflatten\n"); - log(" do not flatten design before synthesis\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(); @@ -72,7 +78,7 @@ struct SynthIntelALMPass : public ScriptPass { } string top_opt, family_opt, bram_type, vout_file; - bool flatten, quartus, nolutram, nobram; + bool flatten, quartus, nolutram, nobram, dff, nodsp; void clear_flags() override { @@ -84,6 +90,8 @@ struct SynthIntelALMPass : public ScriptPass { quartus = false; nolutram = false; nobram = false; + dff = false; + nodsp = false; } void execute(std::vector<std::string> args, RTLIL::Design *design) override @@ -126,10 +134,18 @@ struct SynthIntelALMPass : public ScriptPass { nobram = true; continue; } + if (args[argidx] == "-nodsp") { + nodsp = true; + continue; + } if (args[argidx] == "-noflatten") { flatten = false; continue; } + if (args[argidx] == "-dff") { + dff = true; + continue; + } break; } extra_args(args, argidx, design); @@ -161,10 +177,13 @@ 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())); // Misc and common cells run("read_verilog -lib +/intel/common/altpll_bb.v"); @@ -172,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)")) { @@ -199,17 +248,18 @@ 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"); } if (check_label("map_luts")) { - run("abc9 -maxlut 6 -W 200"); + run("techmap -map +/intel_alm/common/abc9_map.v"); + run(stringf("abc9 %s -maxlut 6 -W 200", help_mode ? "[-dff]" : dff ? "-dff" : "")); + run("techmap -map +/intel_alm/common/abc9_unmap.v"); run("techmap -map +/intel_alm/common/alm_map.v"); run("opt -fast"); run("autoname"); |