mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-17 20:55:45 +00:00
gowin: infer DSP multipliers for the GW5A family
synth_gowin guarded the mul2dsp + dsp_map path to gw1n/gw2a, so GW5A multiplies expanded to LUTs. Add a gw5a branch mapping the GW5A's three multiplier widths: $__MUL27X18 (M0 27x18) for larger multiplies, $__MUL12X12 (M1 12x12) for <=12x12 (which pack two-per-block via M0+M1), and $__MUL27X36 (27x36) for wide (B>18) multiplies. The blocks are signed-only (no per-operand sign control), so DSP_SIGNEDONLY is mandatory without it a 32x16 -1*-1 mapping yields 0x08000001 instead of 1.
This commit is contained in:
parent
0e82bbefe5
commit
98656e284b
5 changed files with 195 additions and 0 deletions
|
|
@ -52,4 +52,5 @@ yosys_pass(synth_gowin
|
|||
lutrams_map.v
|
||||
lutrams.txt
|
||||
dsp_map.v
|
||||
dsp_map_gw5a.v
|
||||
)
|
||||
|
|
|
|||
95
techlibs/gowin/dsp_map_gw5a.v
Normal file
95
techlibs/gowin/dsp_map_gw5a.v
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
module \$__MUL27X18 (input [26:0] A, input [17:0] B, output [44:0] Y);
|
||||
|
||||
parameter A_WIDTH = 27;
|
||||
parameter B_WIDTH = 18;
|
||||
parameter Y_WIDTH = 45;
|
||||
parameter A_SIGNED = 0;
|
||||
parameter B_SIGNED = 0;
|
||||
|
||||
wire [47:0] dout_w;
|
||||
|
||||
MULTALU27X18 #(
|
||||
.MULT12X12_EN("FALSE"),
|
||||
.MULT_RESET_MODE("SYNC"),
|
||||
.AREG_CLK("BYPASS"),
|
||||
.BREG_CLK("BYPASS"),
|
||||
.PREG_CLK("BYPASS"),
|
||||
.OREG_CLK("BYPASS")
|
||||
) __TECHMAP_REPLACE__ (
|
||||
.DOUT(dout_w),
|
||||
.CASO(),
|
||||
.SOA(),
|
||||
.A(A),
|
||||
.SIA(27'd0),
|
||||
.B(B),
|
||||
.C(48'd0),
|
||||
.D(26'd0),
|
||||
.CASI(48'd0),
|
||||
.ACCSEL(1'b0),
|
||||
.PSEL(1'b0),
|
||||
.ASEL(1'b0),
|
||||
.PADDSUB(1'b0),
|
||||
.CSEL(1'b0),
|
||||
.CASISEL(1'b0),
|
||||
.ADDSUB(2'b00),
|
||||
.CLK(2'b00),
|
||||
.CE(2'b00),
|
||||
.RESET(2'b00)
|
||||
);
|
||||
|
||||
assign Y = dout_w[44:0];
|
||||
|
||||
endmodule
|
||||
|
||||
module \$__MUL12X12 (input [11:0] A, input [11:0] B, output [23:0] Y);
|
||||
|
||||
parameter A_WIDTH = 12;
|
||||
parameter B_WIDTH = 12;
|
||||
parameter Y_WIDTH = 24;
|
||||
parameter A_SIGNED = 0;
|
||||
parameter B_SIGNED = 0;
|
||||
|
||||
MULT12X12 #(
|
||||
.MULT_RESET_MODE("SYNC"),
|
||||
.AREG_CLK("BYPASS"),
|
||||
.BREG_CLK("BYPASS"),
|
||||
.PREG_CLK("BYPASS"),
|
||||
.OREG_CLK("BYPASS")
|
||||
) __TECHMAP_REPLACE__ (
|
||||
.DOUT(Y),
|
||||
.A(A),
|
||||
.B(B),
|
||||
.CLK(2'b00),
|
||||
.CE(2'b00),
|
||||
.RESET(2'b00)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module \$__MUL27X36 (input [26:0] A, input [35:0] B, output [62:0] Y);
|
||||
|
||||
parameter A_WIDTH = 27;
|
||||
parameter B_WIDTH = 36;
|
||||
parameter Y_WIDTH = 63;
|
||||
parameter A_SIGNED = 0;
|
||||
parameter B_SIGNED = 0;
|
||||
|
||||
MULT27X36 #(
|
||||
.MULT_RESET_MODE("SYNC"),
|
||||
.AREG_CLK("BYPASS"),
|
||||
.BREG_CLK("BYPASS"),
|
||||
.PREG_CLK("BYPASS"),
|
||||
.OREG_CLK("BYPASS")
|
||||
) __TECHMAP_REPLACE__ (
|
||||
.DOUT(Y),
|
||||
.A(A),
|
||||
.B(B),
|
||||
.D(26'd0),
|
||||
.PSEL(1'b0),
|
||||
.PADDSUB(1'b0),
|
||||
.CLK(2'b00),
|
||||
.CE(2'b00),
|
||||
.RESET(2'b00)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
@ -44,6 +44,12 @@ struct SynthGowinPass : public ScriptPass
|
|||
{9, 9, 4, 4, "$__MUL9X9"},
|
||||
};
|
||||
|
||||
const std::vector<DSPRule> gw5a_dsp_rules = {
|
||||
{27, 36, 2, 19, "$__MUL27X36"},
|
||||
{27, 18, 13, 13, "$__MUL27X18"},
|
||||
{12, 12, 2, 2, "$__MUL12X12"},
|
||||
};
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
|
|
@ -285,6 +291,8 @@ struct SynthGowinPass : public ScriptPass
|
|||
if (help_mode) {
|
||||
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp and if -family gw1n or gw2a)");
|
||||
run("techmap -map +/gowin/dsp_map.v", "(unless -nodsp and if -family gw1n or gw2a)");
|
||||
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp and if -family gw5a)");
|
||||
run("techmap -map +/gowin/dsp_map_gw5a.v", "(unless -nodsp and if -family gw5a)");
|
||||
} else if (!nodsp && (family == "gw1n" || family == "gw2a")) {
|
||||
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",
|
||||
|
|
@ -292,6 +300,14 @@ struct SynthGowinPass : public ScriptPass
|
|||
run("chtype -set $mul t:$__soft_mul");
|
||||
}
|
||||
run("techmap -map +/gowin/dsp_map.v");
|
||||
} else if (!nodsp && family == "gw5a") {
|
||||
for (const auto &rule : gw5a_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_SIGNEDONLY -D DSP_NAME=%s",
|
||||
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim));
|
||||
run("chtype -set $mul t:$__soft_mul");
|
||||
}
|
||||
run("techmap -map +/gowin/dsp_map_gw5a.v");
|
||||
}
|
||||
|
||||
run("alumacc");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue