Skip to content

Commit 52cdcc4

Browse files
authored
Merge pull request #369 from antmicro/fix-k6n10f-dsp-inference
Fix k6n10f DSP type inference
2 parents e71ace5 + 5c12d60 commit 52cdcc4

File tree

5 files changed

+356
-120
lines changed

5 files changed

+356
-120
lines changed

ql-qlf-plugin/ql-dsp-io-regs.cc

Lines changed: 177 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -10,133 +10,27 @@ PRIVATE_NAMESPACE_BEGIN
1010

1111
// ============================================================================
1212

13-
const std::vector<std::string> ports2del_mult = {"load_acc", "subtract", "acc_fir", "dly_b"};
14-
const std::vector<std::string> ports2del_mult_acc = {"acc_fir", "dly_b"};
15-
const std::vector<std::string> ports2del_mult_add = {"dly_b"};
16-
const std::vector<std::string> ports2del_extension = {"saturate_enable", "shift_right", "round"};
17-
18-
void ql_dsp_io_regs_pass(RTLIL::Module *module)
19-
{
20-
21-
for (auto cell : module->cells_) {
22-
std::string cell_type = cell.second->type.str();
23-
if (cell_type == RTLIL::escape_id("QL_DSP2") || cell_type == RTLIL::escape_id("QL_DSP3")) {
24-
auto dsp = cell.second;
25-
bool del_clk = false;
26-
bool use_dsp_cfg_params = cell_type == RTLIL::escape_id("QL_DSP3");
27-
28-
int reg_in_i;
29-
int out_sel_i;
30-
31-
// Get DSP configuration
32-
if (use_dsp_cfg_params) {
33-
// Read MODE_BITS at correct indexes
34-
auto mode_bits = &dsp->getParam(RTLIL::escape_id("MODE_BITS"));
35-
RTLIL::Const register_inputs;
36-
register_inputs = mode_bits->bits.at(MODE_BITS_REGISTER_INPUTS_ID);
37-
reg_in_i = register_inputs.as_int();
38-
39-
RTLIL::Const output_select;
40-
output_select = mode_bits->extract(MODE_BITS_OUTPUT_SELECT_START_ID, MODE_BITS_OUTPUT_SELECT_WIDTH);
41-
out_sel_i = output_select.as_int();
42-
} else {
43-
// Read dedicated configuration ports
44-
const RTLIL::SigSpec *register_inputs;
45-
register_inputs = &dsp->getPort(RTLIL::escape_id("register_inputs"));
46-
if (!register_inputs)
47-
log_error("register_inputs port not found!");
48-
auto reg_in_c = register_inputs->as_const();
49-
reg_in_i = reg_in_c.as_int();
50-
51-
const RTLIL::SigSpec *output_select;
52-
output_select = &dsp->getPort(RTLIL::escape_id("output_select"));
53-
if (!output_select)
54-
log_error("output_select port not found!");
55-
auto out_sel_c = output_select->as_const();
56-
out_sel_i = out_sel_c.as_int();
57-
}
58-
59-
// Build new type name
60-
std::string new_type = cell_type;
61-
new_type += "_MULT";
62-
63-
switch (out_sel_i) {
64-
case 1:
65-
new_type += "ACC";
66-
break;
67-
case 2:
68-
case 3:
69-
new_type += "ADD";
70-
break;
71-
case 5:
72-
new_type += "ACC";
73-
break;
74-
case 6:
75-
case 7:
76-
new_type += "ADD";
77-
break;
78-
default:
79-
break;
80-
}
81-
82-
if (reg_in_i)
83-
new_type += "_REGIN";
84-
85-
if (out_sel_i > 3)
86-
new_type += "_REGOUT";
87-
88-
// Set new type name
89-
dsp->type = RTLIL::IdString(new_type);
90-
91-
// Delete ports unused in given type of DSP cell
92-
del_clk = (!reg_in_i && out_sel_i <= 3 && out_sel_i != 1);
93-
94-
std::vector<std::string> ports2del;
95-
96-
if (del_clk)
97-
ports2del.push_back("clk");
98-
99-
switch (out_sel_i) {
100-
case 0:
101-
case 4:
102-
ports2del.insert(ports2del.end(), ports2del_mult.begin(), ports2del_mult.end());
103-
// Mark for deleton additional configuration ports
104-
if (!use_dsp_cfg_params) {
105-
ports2del.insert(ports2del.end(), ports2del_extension.begin(), ports2del_extension.end());
106-
}
13+
struct QlDspIORegs : public Pass {
10714

108-
break;
109-
case 1:
110-
case 5:
111-
ports2del.insert(ports2del.end(), ports2del_mult_acc.begin(), ports2del_mult_acc.end());
112-
break;
113-
case 2:
114-
case 3:
115-
case 6:
116-
case 7:
117-
ports2del.insert(ports2del.end(), ports2del_mult_add.begin(), ports2del_mult_add.end());
118-
break;
119-
}
15+
const std::vector<std::string> ports2del_mult = {"load_acc", "subtract", "acc_fir", "dly_b"};
16+
const std::vector<std::string> ports2del_mult_acc = {"acc_fir", "dly_b"};
17+
const std::vector<std::string> ports2del_mult_add = {"dly_b"};
18+
const std::vector<std::string> ports2del_extension = {"saturate_enable", "shift_right", "round"};
12019

121-
for (auto portname : ports2del) {
122-
const RTLIL::SigSpec *port = &dsp->getPort(RTLIL::escape_id(portname));
123-
if (!port)
124-
log_error("%s port not found!", portname.c_str());
125-
dsp->connections_.erase(RTLIL::escape_id(portname));
126-
}
127-
}
128-
}
129-
}
20+
/// Temporary SigBit to SigBit helper map.
21+
SigMap m_SigMap;
13022

131-
struct QlDspIORegs : public Pass {
23+
// ..........................................
13224

133-
QlDspIORegs() : Pass("ql_dsp_io_regs", "Does something") {}
25+
QlDspIORegs() : Pass("ql_dsp_io_regs", "Changes types of QL_DSP2/QL_DSP3 depending on their configuration.") {}
13426

13527
void help() override
13628
{
13729
log("\n");
13830
log(" ql_dsp_io_regs [options] [selection]\n");
13931
log("\n");
32+
log("Looks for QL_DSP2/QL_DSP3 cells and changes their types depending\n");
33+
log("on their configuration.\n");
14034
}
14135

14236
void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) override
@@ -153,6 +47,172 @@ struct QlDspIORegs : public Pass {
15347
ql_dsp_io_regs_pass(module);
15448
}
15549
}
50+
51+
// Returns a pair of mask and value describing constant bit connections of
52+
// a SigSpec
53+
std::pair<uint32_t, uint32_t> get_constant_mask_value(const RTLIL::SigSpec *sigspec)
54+
{
55+
uint32_t mask = 0L;
56+
uint32_t value = 0L;
57+
58+
auto sigbits = sigspec->bits();
59+
for (ssize_t i = (sigbits.size() - 1); i >= 0; --i) {
60+
auto other = m_SigMap(sigbits[i]);
61+
62+
mask <<= 1;
63+
value <<= 1;
64+
65+
// A known constant
66+
if (!other.is_wire() && other.data != RTLIL::Sx) {
67+
mask |= 0x1;
68+
value |= (other.data == RTLIL::S1);
69+
}
70+
}
71+
72+
return std::make_pair(mask, value);
73+
}
74+
75+
void ql_dsp_io_regs_pass(RTLIL::Module *module)
76+
{
77+
// Setup the SigMap
78+
m_SigMap.clear();
79+
m_SigMap.set(module);
80+
81+
for (auto cell : module->cells_) {
82+
std::string cell_type = cell.second->type.str();
83+
if (cell_type == RTLIL::escape_id("QL_DSP2") || cell_type == RTLIL::escape_id("QL_DSP3")) {
84+
auto dsp = cell.second;
85+
bool del_clk = true;
86+
bool use_dsp_cfg_params = (cell_type == RTLIL::escape_id("QL_DSP3"));
87+
88+
int reg_in_i;
89+
int out_sel_i;
90+
91+
// Get DSP configuration
92+
if (use_dsp_cfg_params) {
93+
// Read MODE_BITS at correct indexes
94+
auto mode_bits = &dsp->getParam(RTLIL::escape_id("MODE_BITS"));
95+
RTLIL::Const register_inputs;
96+
register_inputs = mode_bits->bits.at(MODE_BITS_REGISTER_INPUTS_ID);
97+
reg_in_i = register_inputs.as_int();
98+
99+
RTLIL::Const output_select;
100+
output_select = mode_bits->extract(MODE_BITS_OUTPUT_SELECT_START_ID, MODE_BITS_OUTPUT_SELECT_WIDTH);
101+
out_sel_i = output_select.as_int();
102+
} else {
103+
// Read dedicated configuration ports
104+
const RTLIL::SigSpec *register_inputs;
105+
register_inputs = &dsp->getPort(RTLIL::escape_id("register_inputs"));
106+
if (!register_inputs)
107+
log_error("register_inputs port not found!");
108+
auto reg_in_c = register_inputs->as_const();
109+
reg_in_i = reg_in_c.as_int();
110+
111+
const RTLIL::SigSpec *output_select;
112+
output_select = &dsp->getPort(RTLIL::escape_id("output_select"));
113+
if (!output_select)
114+
log_error("output_select port not found!");
115+
auto out_sel_c = output_select->as_const();
116+
out_sel_i = out_sel_c.as_int();
117+
}
118+
119+
// Get the feedback port
120+
const RTLIL::SigSpec *feedback;
121+
feedback = &dsp->getPort(RTLIL::escape_id("feedback"));
122+
if (!feedback)
123+
log_error("feedback port not found!");
124+
125+
// Check if feedback is or can be set to 0 which implies MACC
126+
auto feedback_con = get_constant_mask_value(feedback);
127+
bool have_macc = (feedback_con.second == 0x0);
128+
// log("mask=0x%08X value=0x%08X\n", consts.first, consts.second);
129+
// log_error("=== END HERE ===\n");
130+
131+
// Build new type name
132+
std::string new_type = cell_type;
133+
new_type += "_MULT";
134+
135+
if (have_macc) {
136+
switch (out_sel_i) {
137+
case 1:
138+
case 2:
139+
case 3:
140+
case 5:
141+
case 7:
142+
del_clk = false;
143+
new_type += "ACC";
144+
break;
145+
default:
146+
break;
147+
}
148+
} else {
149+
switch (out_sel_i) {
150+
case 1:
151+
case 2:
152+
case 3:
153+
case 5:
154+
case 7:
155+
new_type += "ADD";
156+
break;
157+
default:
158+
break;
159+
}
160+
}
161+
162+
if (reg_in_i) {
163+
del_clk = false;
164+
new_type += "_REGIN";
165+
}
166+
167+
if (out_sel_i > 3) {
168+
del_clk = false;
169+
new_type += "_REGOUT";
170+
}
171+
172+
// Set new type name
173+
dsp->type = RTLIL::IdString(new_type);
174+
175+
std::vector<std::string> ports2del;
176+
177+
if (del_clk)
178+
ports2del.push_back("clk");
179+
180+
switch (out_sel_i) {
181+
case 0:
182+
case 4:
183+
case 6:
184+
ports2del.insert(ports2del.end(), ports2del_mult.begin(), ports2del_mult.end());
185+
// Mark for deleton additional configuration ports
186+
if (!use_dsp_cfg_params) {
187+
ports2del.insert(ports2del.end(), ports2del_extension.begin(), ports2del_extension.end());
188+
}
189+
break;
190+
case 1:
191+
case 2:
192+
case 3:
193+
case 5:
194+
case 7:
195+
if (have_macc) {
196+
ports2del.insert(ports2del.end(), ports2del_mult_acc.begin(), ports2del_mult_acc.end());
197+
} else {
198+
ports2del.insert(ports2del.end(), ports2del_mult_add.begin(), ports2del_mult_add.end());
199+
}
200+
break;
201+
}
202+
203+
for (auto portname : ports2del) {
204+
const RTLIL::SigSpec *port = &dsp->getPort(RTLIL::escape_id(portname));
205+
if (!port)
206+
log_error("%s port not found!", portname.c_str());
207+
dsp->connections_.erase(RTLIL::escape_id(portname));
208+
}
209+
}
210+
}
211+
212+
// Clear the sigmap
213+
m_SigMap.clear();
214+
}
215+
156216
} QlDspIORegs;
157217

158218
PRIVATE_NAMESPACE_END

ql-qlf-plugin/tests/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ TESTS = \
3232
pp3_bram \
3333
qlf_k6n10f/dsp_mult \
3434
qlf_k6n10f/dsp_simd \
35-
qlf_k6n10f/dsp_macc
35+
qlf_k6n10f/dsp_macc \
36+
qlf_k6n10f/dsp_madd
3637
# qlf_k6n10_bram \
3738
3839
SIM_TESTS = \
@@ -73,4 +74,5 @@ pp3_bram_verify = true
7374
qlf_k6n10f-dsp_mult_verify = true
7475
qlf_k6n10f-dsp_simd_verify = true
7576
qlf_k6n10f-dsp_macc_verify = true
77+
qlf_k6n10f-dsp_madd_verify = true
7678
#qlf_k6n10_bram_verify = true

ql-qlf-plugin/tests/qlf_k6n10f/dsp_macc/dsp_macc.tcl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,6 @@ test_dsp_design "macc_simple_clr" "_MULTACC"
7575
test_dsp_design "macc_simple_arst" "_MULTACC"
7676
test_dsp_design "macc_simple_ena" "_MULTACC"
7777
test_dsp_design "macc_simple_arst_clr_ena" "_MULTACC"
78-
test_dsp_design "macc_simple_preacc" "_MULTADD"
79-
test_dsp_design "macc_simple_preacc_clr" "_MULTADD"
78+
test_dsp_design "macc_simple_preacc" "_MULTACC"
79+
test_dsp_design "macc_simple_preacc_clr" "_MULTACC"
8080

0 commit comments

Comments
 (0)