Skip to content

Commit 9f241c9

Browse files
committed
nexus: DSP inference support
Signed-off-by: David Shah <[email protected]>
1 parent 5b35d95 commit 9f241c9

File tree

4 files changed

+151
-13
lines changed

4 files changed

+151
-13
lines changed

techlibs/nexus/Makefile.inc

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

techlibs/nexus/dsp_map.v

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
module \$__NX_MUL36X36 (input [35:0] A, input [35:0] B, output [71:0] Y);
2+
3+
parameter A_WIDTH = 36;
4+
parameter B_WIDTH = 36;
5+
parameter Y_WIDTH = 72;
6+
parameter A_SIGNED = 0;
7+
parameter B_SIGNED = 0;
8+
9+
MULT36X36 #(
10+
.REGINPUTA("BYPASS"),
11+
.REGINPUTB("BYPASS"),
12+
.REGOUTPUT("BYPASS")
13+
) _TECHMAP_REPLACE_ (
14+
.A(A), .B(B),
15+
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
16+
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
17+
.Z(Y)
18+
);
19+
endmodule
20+
21+
module \$__NX_MUL36X18 (input [35:0] A, input [17:0] B, output [53:0] Y);
22+
23+
parameter A_WIDTH = 36;
24+
parameter B_WIDTH = 18;
25+
parameter Y_WIDTH = 54;
26+
parameter A_SIGNED = 0;
27+
parameter B_SIGNED = 0;
28+
29+
MULT18X36 #(
30+
.REGINPUTA("BYPASS"),
31+
.REGINPUTB("BYPASS"),
32+
.REGOUTPUT("BYPASS")
33+
) _TECHMAP_REPLACE_ (
34+
.A(B), .B(A),
35+
.SIGNEDA(B_SIGNED ? 1'b1 : 1'b0),
36+
.SIGNEDB(A_SIGNED ? 1'b1 : 1'b0),
37+
.Z(Y)
38+
);
39+
endmodule
40+
41+
module \$__NX_MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
42+
43+
parameter A_WIDTH = 18;
44+
parameter B_WIDTH = 18;
45+
parameter Y_WIDTH = 36;
46+
parameter A_SIGNED = 0;
47+
parameter B_SIGNED = 0;
48+
49+
MULT18X18 #(
50+
.REGINPUTA("BYPASS"),
51+
.REGINPUTB("BYPASS"),
52+
.REGOUTPUT("BYPASS")
53+
) _TECHMAP_REPLACE_ (
54+
.A(A), .B(B),
55+
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
56+
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
57+
.Z(Y)
58+
);
59+
endmodule
60+
61+
module \$__NX_MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y);
62+
63+
parameter A_WIDTH = 9;
64+
parameter B_WIDTH = 9;
65+
parameter Y_WIDTH = 18;
66+
parameter A_SIGNED = 0;
67+
parameter B_SIGNED = 0;
68+
69+
MULT9X9 #(
70+
.REGINPUTA("BYPASS"),
71+
.REGINPUTB("BYPASS"),
72+
.REGOUTPUT("BYPASS")
73+
) _TECHMAP_REPLACE_ (
74+
.A(A), .B(B),
75+
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
76+
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
77+
.Z(Y)
78+
);
79+
endmodule

techlibs/nexus/synth_nexus.cc

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ struct SynthNexusPass : public ScriptPass
8989
log(" -noiopad\n");
9090
log(" do not insert IO buffers\n");
9191
log("\n");
92+
log(" -nodsp\n");
93+
log(" do not infer DSP multipliers\n");
94+
log("\n");
9295
log(" -abc9\n");
9396
log(" use new ABC9 flow (EXPERIMENTAL)\n");
9497
log("\n");
@@ -98,7 +101,7 @@ struct SynthNexusPass : public ScriptPass
98101
}
99102

100103
string top_opt, json_file, vm_file, family;
101-
bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, flatten, dff, retime, abc9;
104+
bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, nodsp, flatten, dff, retime, abc9;
102105

103106
void clear_flags() override
104107
{
@@ -112,6 +115,7 @@ struct SynthNexusPass : public ScriptPass
112115
nolutram = false;
113116
nowidelut = false;
114117
noiopad = false;
118+
nodsp = false;
115119
flatten = true;
116120
dff = false;
117121
retime = false;
@@ -161,6 +165,10 @@ struct SynthNexusPass : public ScriptPass
161165
dff = true;
162166
continue;
163167
}
168+
if (args[argidx] == "-nodsp") {
169+
nodsp = true;
170+
continue;
171+
}
164172
if (args[argidx] == "-retime") {
165173
retime = true;
166174
continue;
@@ -211,6 +219,22 @@ struct SynthNexusPass : public ScriptPass
211219
log_pop();
212220
}
213221

222+
struct DSPRule {
223+
int a_maxwidth;
224+
int b_maxwidth;
225+
int a_minwidth;
226+
int b_minwidth;
227+
std::string prim;
228+
};
229+
230+
const std::vector<DSPRule> dsp_rules = {
231+
{36, 36, 22, 22, "$__NX_MUL36X36"},
232+
{36, 18, 22, 10, "$__NX_MUL36X18"},
233+
{18, 18, 10, 4, "$__NX_MUL18X18"},
234+
{18, 18, 4, 10, "$__NX_MUL18X18"},
235+
{ 9, 9, 4, 4, "$__NX_MUL9X9"},
236+
};
237+
214238
void script() override
215239
{
216240

@@ -244,6 +268,18 @@ struct SynthNexusPass : public ScriptPass
244268
run("opt_expr");
245269
run("opt_clean");
246270

271+
if (help_mode) {
272+
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
273+
run("techmap -map +/nexus/dsp_map.v", "(unless -nodsp)");
274+
} else if (!nodsp) {
275+
for (const auto &rule : dsp_rules) {
276+
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",
277+
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str()));
278+
run("chtype -set $mul t:$__soft_mul");
279+
}
280+
run("techmap -map +/nexus/dsp_map.v");
281+
}
282+
247283
run("alumacc");
248284
run("opt");
249285
run("memory -nomap");

tests/arch/nexus/mul.ys

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
read_verilog ../common/mul.v
2+
chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
23
hierarchy -top top
34
proc
45

@@ -7,22 +8,43 @@ design -save read
78
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus
89
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
910
cd top # Constrain all select calls below inside the top module
10-
select -assert-count 7 t:CCU2
11-
select -assert-max 5 t:WIDEFN9
12-
select -assert-max 62 t:LUT4
11+
select -assert-count 1 t:MULT9X9
1312

14-
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
13+
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT9X9 %% t:* %D
1514

16-
design -load read
1715

18-
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9
19-
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
16+
design -reset
17+
read_verilog ../common/mul.v
18+
chparam -set X_WIDTH 16 -set Y_WIDTH 16 -set A_WIDTH 32
19+
hierarchy -top top
20+
proc
21+
# equivalence checking is too slow here
22+
synth_nexus
23+
cd top # Constrain all select calls below inside the top module
24+
select -assert-count 1 t:MULT18X18
25+
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X18 %% t:* %D
26+
27+
28+
design -reset
29+
read_verilog ../common/mul.v
30+
chparam -set X_WIDTH 32 -set Y_WIDTH 16 -set A_WIDTH 48
31+
hierarchy -top top
32+
proc
33+
# equivalence checking is too slow here
34+
synth_nexus
2035
cd top # Constrain all select calls below inside the top module
36+
select -assert-count 1 t:MULT18X36
37+
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X36 %% t:* %D
2138

22-
stat
2339

24-
select -assert-count 7 t:CCU2
25-
select -assert-max 12 t:WIDEFN9
26-
select -assert-max 58 t:LUT4
40+
design -reset
41+
read_verilog ../common/mul.v
42+
chparam -set X_WIDTH 32 -set Y_WIDTH 32 -set A_WIDTH 64
43+
hierarchy -top top
44+
proc
45+
# equivalence checking is too slow here
46+
synth_nexus
47+
cd top # Constrain all select calls below inside the top module
48+
select -assert-count 1 t:MULT36X36
2749

28-
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
50+
select -assert-none t:IB t:OB t:VLO t:VHI t:MULT36X36 %% t:* %D

0 commit comments

Comments
 (0)