mirror of https://github.com/YosysHQ/yosys.git
intel_alm: DSP inference
This commit is contained in:
parent
01772dec8c
commit
b004f09018
|
@ -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/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_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/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))
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v))
|
||||||
|
|
||||||
# RAM
|
# RAM
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -129,3 +129,31 @@ output [data_width-1:0] portbdataout;
|
||||||
input ena0, clk0, clk1;
|
input ena0, clk0, clk1;
|
||||||
|
|
||||||
endmodule
|
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
|
|
@ -1,9 +1,11 @@
|
||||||
`ifdef cyclonev
|
`ifdef cyclonev
|
||||||
`define LCELL cyclonev_lcell_comb
|
`define LCELL cyclonev_lcell_comb
|
||||||
|
`define MAC cyclonev_mac
|
||||||
`define MLAB cyclonev_mlab_cell
|
`define MLAB cyclonev_mlab_cell
|
||||||
`endif
|
`endif
|
||||||
`ifdef cyclone10gx
|
`ifdef cyclone10gx
|
||||||
`define LCELL cyclone10gx_lcell_comb
|
`define LCELL cyclone10gx_lcell_comb
|
||||||
|
`define MAC cyclone10gx_mac
|
||||||
`define MLAB cyclone10gx_mlab_cell
|
`define MLAB cyclone10gx_mlab_cell
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
@ -119,3 +121,24 @@ module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
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
|
||||||
|
|
|
@ -69,13 +69,16 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
log(" -nobram\n");
|
log(" -nobram\n");
|
||||||
log(" do not use block RAM cells in output netlist\n");
|
log(" do not use block RAM cells in output netlist\n");
|
||||||
log("\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");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
help_script();
|
help_script();
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, family_opt, bram_type, vout_file;
|
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
|
void clear_flags() override
|
||||||
{
|
{
|
||||||
|
@ -88,6 +91,7 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
nolutram = false;
|
nolutram = false;
|
||||||
nobram = false;
|
nobram = false;
|
||||||
dff = false;
|
dff = false;
|
||||||
|
nodsp = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
@ -130,6 +134,10 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
nobram = true;
|
nobram = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-nodsp") {
|
||||||
|
nodsp = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-noflatten") {
|
if (args[argidx] == "-noflatten") {
|
||||||
flatten = false;
|
flatten = false;
|
||||||
continue;
|
continue;
|
||||||
|
@ -169,9 +177,11 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("begin")) {
|
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/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/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 +/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()));
|
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()));
|
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("proc");
|
||||||
run("flatten");
|
if (flatten || help_mode)
|
||||||
|
run("flatten", "(skip if -noflatten)");
|
||||||
run("tribuf -logic");
|
run("tribuf -logic");
|
||||||
run("deminout");
|
run("deminout");
|
||||||
}
|
run("opt_expr");
|
||||||
|
run("opt_clean");
|
||||||
if (check_label("coarse")) {
|
run("check");
|
||||||
run("synth -run coarse -lut 6");
|
run("opt");
|
||||||
run("techmap -map +/intel_alm/common/arith_alm_map.v");
|
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)")) {
|
if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue