mirror of https://github.com/YosysHQ/yosys.git
nexus: DSP inference support
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
5b35d953f7
commit
9f241c9a42
|
@ -11,4 +11,5 @@ $(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v))
|
||||||
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt))
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt))
|
||||||
$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v))
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v))
|
||||||
$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v))
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/dsp_map.v))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
module \$__NX_MUL36X36 (input [35:0] A, input [35:0] B, output [71:0] Y);
|
||||||
|
|
||||||
|
parameter A_WIDTH = 36;
|
||||||
|
parameter B_WIDTH = 36;
|
||||||
|
parameter Y_WIDTH = 72;
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
|
||||||
|
MULT36X36 #(
|
||||||
|
.REGINPUTA("BYPASS"),
|
||||||
|
.REGINPUTB("BYPASS"),
|
||||||
|
.REGOUTPUT("BYPASS")
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.A(A), .B(B),
|
||||||
|
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.Z(Y)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__NX_MUL36X18 (input [35:0] A, input [17:0] B, output [53:0] Y);
|
||||||
|
|
||||||
|
parameter A_WIDTH = 36;
|
||||||
|
parameter B_WIDTH = 18;
|
||||||
|
parameter Y_WIDTH = 54;
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
|
||||||
|
MULT18X36 #(
|
||||||
|
.REGINPUTA("BYPASS"),
|
||||||
|
.REGINPUTB("BYPASS"),
|
||||||
|
.REGOUTPUT("BYPASS")
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.A(B), .B(A),
|
||||||
|
.SIGNEDA(B_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.SIGNEDB(A_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.Z(Y)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__NX_MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
|
||||||
|
|
||||||
|
parameter A_WIDTH = 18;
|
||||||
|
parameter B_WIDTH = 18;
|
||||||
|
parameter Y_WIDTH = 36;
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
|
||||||
|
MULT18X18 #(
|
||||||
|
.REGINPUTA("BYPASS"),
|
||||||
|
.REGINPUTB("BYPASS"),
|
||||||
|
.REGOUTPUT("BYPASS")
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.A(A), .B(B),
|
||||||
|
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.Z(Y)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__NX_MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y);
|
||||||
|
|
||||||
|
parameter A_WIDTH = 9;
|
||||||
|
parameter B_WIDTH = 9;
|
||||||
|
parameter Y_WIDTH = 18;
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
|
||||||
|
MULT9X9 #(
|
||||||
|
.REGINPUTA("BYPASS"),
|
||||||
|
.REGINPUTB("BYPASS"),
|
||||||
|
.REGOUTPUT("BYPASS")
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.A(A), .B(B),
|
||||||
|
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
|
||||||
|
.Z(Y)
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -89,6 +89,9 @@ struct SynthNexusPass : public ScriptPass
|
||||||
log(" -noiopad\n");
|
log(" -noiopad\n");
|
||||||
log(" do not insert IO buffers\n");
|
log(" do not insert IO buffers\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -nodsp\n");
|
||||||
|
log(" do not infer DSP multipliers\n");
|
||||||
|
log("\n");
|
||||||
log(" -abc9\n");
|
log(" -abc9\n");
|
||||||
log(" use new ABC9 flow (EXPERIMENTAL)\n");
|
log(" use new ABC9 flow (EXPERIMENTAL)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -98,7 +101,7 @@ struct SynthNexusPass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, json_file, vm_file, family;
|
string top_opt, json_file, vm_file, family;
|
||||||
bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, flatten, dff, retime, abc9;
|
bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, nodsp, flatten, dff, retime, abc9;
|
||||||
|
|
||||||
void clear_flags() override
|
void clear_flags() override
|
||||||
{
|
{
|
||||||
|
@ -112,6 +115,7 @@ struct SynthNexusPass : public ScriptPass
|
||||||
nolutram = false;
|
nolutram = false;
|
||||||
nowidelut = false;
|
nowidelut = false;
|
||||||
noiopad = false;
|
noiopad = false;
|
||||||
|
nodsp = false;
|
||||||
flatten = true;
|
flatten = true;
|
||||||
dff = false;
|
dff = false;
|
||||||
retime = false;
|
retime = false;
|
||||||
|
@ -161,6 +165,10 @@ struct SynthNexusPass : public ScriptPass
|
||||||
dff = true;
|
dff = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-nodsp") {
|
||||||
|
nodsp = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-retime") {
|
if (args[argidx] == "-retime") {
|
||||||
retime = true;
|
retime = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -211,6 +219,22 @@ struct SynthNexusPass : public ScriptPass
|
||||||
log_pop();
|
log_pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DSPRule {
|
||||||
|
int a_maxwidth;
|
||||||
|
int b_maxwidth;
|
||||||
|
int a_minwidth;
|
||||||
|
int b_minwidth;
|
||||||
|
std::string prim;
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<DSPRule> dsp_rules = {
|
||||||
|
{36, 36, 22, 22, "$__NX_MUL36X36"},
|
||||||
|
{36, 18, 22, 10, "$__NX_MUL36X18"},
|
||||||
|
{18, 18, 10, 4, "$__NX_MUL18X18"},
|
||||||
|
{18, 18, 4, 10, "$__NX_MUL18X18"},
|
||||||
|
{ 9, 9, 4, 4, "$__NX_MUL9X9"},
|
||||||
|
};
|
||||||
|
|
||||||
void script() override
|
void script() override
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -244,6 +268,18 @@ struct SynthNexusPass : public ScriptPass
|
||||||
run("opt_expr");
|
run("opt_expr");
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
|
|
||||||
|
if (help_mode) {
|
||||||
|
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
|
||||||
|
run("techmap -map +/nexus/dsp_map.v", "(unless -nodsp)");
|
||||||
|
} else if (!nodsp) {
|
||||||
|
for (const auto &rule : dsp_rules) {
|
||||||
|
run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s",
|
||||||
|
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str()));
|
||||||
|
run("chtype -set $mul t:$__soft_mul");
|
||||||
|
}
|
||||||
|
run("techmap -map +/nexus/dsp_map.v");
|
||||||
|
}
|
||||||
|
|
||||||
run("alumacc");
|
run("alumacc");
|
||||||
run("opt");
|
run("opt");
|
||||||
run("memory -nomap");
|
run("memory -nomap");
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
read_verilog ../common/mul.v
|
read_verilog ../common/mul.v
|
||||||
|
chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
|
||||||
hierarchy -top top
|
hierarchy -top top
|
||||||
proc
|
proc
|
||||||
|
|
||||||
|
@ -7,22 +8,43 @@ design -save read
|
||||||
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus
|
||||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
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
|
cd top # Constrain all select calls below inside the top module
|
||||||
select -assert-count 7 t:CCU2
|
select -assert-count 1 t:MULT9X9
|
||||||
select -assert-max 5 t:WIDEFN9
|
|
||||||
select -assert-max 62 t:LUT4
|
|
||||||
|
|
||||||
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
|
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT9X9 %% t:* %D
|
||||||
|
|
||||||
design -load read
|
|
||||||
|
|
||||||
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9
|
design -reset
|
||||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
read_verilog ../common/mul.v
|
||||||
|
chparam -set X_WIDTH 16 -set Y_WIDTH 16 -set A_WIDTH 32
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
# equivalence checking is too slow here
|
||||||
|
synth_nexus
|
||||||
cd top # Constrain all select calls below inside the top module
|
cd top # Constrain all select calls below inside the top module
|
||||||
|
select -assert-count 1 t:MULT18X18
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X18 %% t:* %D
|
||||||
|
|
||||||
stat
|
|
||||||
|
|
||||||
select -assert-count 7 t:CCU2
|
design -reset
|
||||||
select -assert-max 12 t:WIDEFN9
|
read_verilog ../common/mul.v
|
||||||
select -assert-max 58 t:LUT4
|
chparam -set X_WIDTH 32 -set Y_WIDTH 16 -set A_WIDTH 48
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
# equivalence checking is too slow here
|
||||||
|
synth_nexus
|
||||||
|
cd top # Constrain all select calls below inside the top module
|
||||||
|
select -assert-count 1 t:MULT18X36
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X36 %% t:* %D
|
||||||
|
|
||||||
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
|
|
||||||
|
design -reset
|
||||||
|
read_verilog ../common/mul.v
|
||||||
|
chparam -set X_WIDTH 32 -set Y_WIDTH 32 -set A_WIDTH 64
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
# equivalence checking is too slow here
|
||||||
|
synth_nexus
|
||||||
|
cd top # Constrain all select calls below inside the top module
|
||||||
|
select -assert-count 1 t:MULT36X36
|
||||||
|
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT36X36 %% t:* %D
|
||||||
|
|
Loading…
Reference in New Issue