Skip to content

Commit e05c0e7

Browse files
committed
gowin: dsp: Add basic DSP block inferencing for various MULT cells
1 parent 35bade5 commit e05c0e7

File tree

5 files changed

+204
-1
lines changed

5 files changed

+204
-1
lines changed

techlibs/gowin/Makefile.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map.v))
1111
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams.txt))
1212
$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams_map.v))
1313
$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams.txt))
14+
$(eval $(call add_share_file,share/gowin,techlibs/gowin/dsp_map.v))

techlibs/gowin/dsp_map.v

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
module \$__MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y);
2+
parameter A_WIDTH = 9;
3+
parameter B_WIDTH = 9;
4+
parameter Y_WIDTH = 18;
5+
parameter A_SIGNED = 0;
6+
parameter B_SIGNED = 0;
7+
8+
wire [8:0] soa;
9+
wire [8:0] sob;
10+
11+
MULT9X9 _TECHMAP_REPLACE_ (
12+
.A(A),
13+
.B(B),
14+
.SIA(8'b0),
15+
.SIB(8'b0),
16+
.ASIGN(A_SIGNED),
17+
.BSIGN(B_SIGNED),
18+
.ASEL(1'b0),
19+
.BSEL(1'b0),
20+
.SOA(soa),
21+
.SOB(sob),
22+
.DOUT(Y)
23+
);
24+
endmodule
25+
26+
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
27+
parameter A_WIDTH = 18;
28+
parameter B_WIDTH = 18;
29+
parameter Y_WIDTH = 36;
30+
parameter A_SIGNED = 0;
31+
parameter B_SIGNED = 0;
32+
33+
wire [17:0] soa;
34+
wire [17:0] sob;
35+
36+
MULT18X18 _TECHMAP_REPLACE_ (
37+
.A(A),
38+
.B(B),
39+
.SIA(18'b0),
40+
.SIB(18'b0),
41+
.ASIGN(A_SIGNED),
42+
.BSIGN(B_SIGNED),
43+
.ASEL(1'b0),
44+
.BSEL(1'b0),
45+
.SOA(soa),
46+
.SOB(sob),
47+
.DOUT(Y)
48+
);
49+
endmodule
50+
51+
module \$__MUL36X36 (input [35:0] A, input [35:0] B, output [72:0] Y);
52+
parameter A_WIDTH = 36;
53+
parameter B_WIDTH = 36;
54+
parameter Y_WIDTH = 72;
55+
parameter A_SIGNED = 0;
56+
parameter B_SIGNED = 0;
57+
58+
MULT36X36 _TECHMAP_REPLACE_ (
59+
.A(A),
60+
.B(B),
61+
.ASIGN(A_SIGNED),
62+
.BSIGN(B_SIGNED),
63+
.DOUT(Y)
64+
);
65+
endmodule

techlibs/gowin/synth_gowin.cc

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,16 @@ struct SynthGowinPass : public ScriptPass
9191
log(" The following families are supported:\n");
9292
log(" 'gw1n', 'gw2a', 'gw5a'.\n");
9393
log("\n");
94+
log(" -nodsp\n");
95+
log(" do not infer DSP multipliers.\n");
96+
log("\n");
9497
log("The following commands are executed by this synthesis command:\n");
9598
help_script();
9699
log("\n");
97100
}
98101

99102
string top_opt, vout_file, json_file, family;
100-
bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads, noalu, no_rw_check;
103+
bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads, noalu, no_rw_check, nodsp;
101104

102105
void clear_flags() override
103106
{
@@ -115,6 +118,7 @@ struct SynthGowinPass : public ScriptPass
115118
noiopads = false;
116119
noalu = false;
117120
no_rw_check = false;
121+
nodsp = false;
118122
}
119123

120124
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -193,6 +197,10 @@ struct SynthGowinPass : public ScriptPass
193197
no_rw_check = true;
194198
continue;
195199
}
200+
if (args[argidx] == "-nodsp") {
201+
nodsp = true;
202+
continue;
203+
}
196204
break;
197205
}
198206
extra_args(args, argidx, design);
@@ -208,6 +216,24 @@ struct SynthGowinPass : public ScriptPass
208216
log_pop();
209217
}
210218

219+
// DSP mapping rules for mul2dsp
220+
struct DSPRule {
221+
int a_maxwidth;
222+
int b_maxwidth;
223+
int a_minwidth;
224+
int b_minwidth;
225+
std::string prim;
226+
};
227+
228+
// gw1n and gw2a
229+
const std::vector<DSPRule> dsp_rules = {
230+
{36, 36, 18, 18, "$__MUL36X36"},
231+
{18, 18, 10, 4, "$__MUL18X18"},
232+
{18, 18, 4, 10, "$__MUL18X18"},
233+
{ 9, 9, 4, 4, "$__MUL9X9"},
234+
};
235+
// TODO: gw5a (MULT12X12, MULT27x36)
236+
211237
void script() override
212238
{
213239
std::string no_rw_check_opt = "";
@@ -233,6 +259,23 @@ struct SynthGowinPass : public ScriptPass
233259

234260
if (check_label("coarse"))
235261
{
262+
if (help_mode)
263+
{
264+
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
265+
run("techmap -map +/gowin/dsp_map.v [...]", "(unless -nodsp)");
266+
} else if (!nodsp) {
267+
if (family == "gw1n" || family == "gw2a")
268+
{
269+
for (const auto &rule : dsp_rules)
270+
{
271+
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",
272+
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str()));
273+
run("chtype -set $mul t:$__soft_mul");
274+
}
275+
run("techmap -map +/gowin/dsp_map.v");
276+
}
277+
}
278+
236279
run("synth -run coarse" + no_rw_check_opt);
237280
}
238281

tests/arch/gowin/mul_gw1n.ys

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
read_verilog ../common/mul.v
2+
chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
3+
hierarchy -top top
4+
proc
5+
# equivalence checking is somewhat slow (and missing simulation models)
6+
synth_gowin -family gw1n
7+
8+
cd top # Constrain all select calls below inside the top module
9+
select -assert-count 1 t:MULT9X9
10+
# XXX: Whats's `top/x_IBUF_I_O_MULT9X9_A_A_GND_G` ??
11+
# select -assert-none t:IBUF t:OBUF t:MULT9X9 %% t:* %D
12+
13+
design -reset
14+
read_verilog ../common/mul.v
15+
chparam -set X_WIDTH 16 -set Y_WIDTH 16 -set A_WIDTH 32
16+
hierarchy -top top
17+
proc
18+
synth_gowin -family gw1n
19+
cd top # Constrain all select calls below inside the top module
20+
select -assert-count 1 t:MULT18X18
21+
# XXX: top/x_IBUF_I_O_MULT18X18_A_A_GND_G ???
22+
# select -assert-none t:IBUF t:OBUF t:MULT18X18 %% t:* %D
23+
24+
25+
design -reset
26+
read_verilog ../common/mul.v
27+
chparam -set X_WIDTH 32 -set Y_WIDTH 32 -set A_WIDTH 64
28+
hierarchy -top top
29+
proc
30+
# equivalence checking is too slow here
31+
synth_gowin
32+
cd top # Constrain all select calls below inside the top module
33+
select -assert-count 1 t:MULT36X36
34+
# XXX: top/x_IBUF_I_O_MULT36X36_A_A_GND_G
35+
# select -assert-none t:IBUF t:OBUF t:MULT36X36 %% t:* %D
36+
37+
# TODO: We end up with two 18x18 multipliers
38+
# design -reset
39+
# read_verilog ../common/mul.v
40+
# chparam -set X_WIDTH 32 -set Y_WIDTH 16 -set A_WIDTH 48
41+
# hierarchy -top top
42+
# proc
43+
# # equivalence checking is too slow here
44+
# synth_gowin
45+
# cd top # Constrain all select calls below inside the top module
46+
# select -assert-count 2 t:MULT18X18
47+
# select -assert-none t:IBUF t:OBUF t:MULT36X36 %% t:* %D

tests/arch/gowin/mul_gw2a.ys

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
read_verilog ../common/mul.v
2+
chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
3+
hierarchy -top top
4+
proc
5+
# equivalence checking is somewhat slow (and missing simulation models)
6+
synth_gowin -family gw2a
7+
8+
cd top # Constrain all select calls below inside the top module
9+
select -assert-count 1 t:MULT9X9
10+
# XXX: Whats's `top/x_IBUF_I_O_MULT9X9_A_A_GND_G` ??
11+
# select -assert-none t:IBUF t:OBUF t:MULT9X9 %% t:* %D
12+
13+
design -reset
14+
read_verilog ../common/mul.v
15+
chparam -set X_WIDTH 16 -set Y_WIDTH 16 -set A_WIDTH 32
16+
hierarchy -top top
17+
proc
18+
synth_gowin -family gw2a
19+
cd top # Constrain all select calls below inside the top module
20+
select -assert-count 1 t:MULT18X18
21+
# XXX: top/x_IBUF_I_O_MULT18X18_A_A_GND_G ???
22+
# select -assert-none t:IBUF t:OBUF t:MULT18X18 %% t:* %D
23+
24+
25+
design -reset
26+
read_verilog ../common/mul.v
27+
chparam -set X_WIDTH 32 -set Y_WIDTH 32 -set A_WIDTH 64
28+
hierarchy -top top
29+
proc
30+
# equivalence checking is too slow here
31+
synth_gowin -family gw2a
32+
cd top # Constrain all select calls below inside the top module
33+
select -assert-count 1 t:MULT36X36
34+
# XXX: top/x_IBUF_I_O_MULT36X36_A_A_GND_G
35+
# select -assert-none t:IBUF t:OBUF t:MULT36X36 %% t:* %D
36+
37+
# TODO: We end up with two 18x18 multipliers
38+
# design -reset
39+
# read_verilog ../common/mul.v
40+
# chparam -set X_WIDTH 32 -set Y_WIDTH 16 -set A_WIDTH 48
41+
# hierarchy -top top
42+
# proc
43+
# # equivalence checking is too slow here
44+
# synth_gowin -family gw2a
45+
# cd top # Constrain all select calls below inside the top module
46+
# select -assert-count 2 t:MULT18X18
47+
# select -assert-none t:IBUF t:OBUF t:MULT36X36 %% t:* %D

0 commit comments

Comments
 (0)