-
Notifications
You must be signed in to change notification settings - Fork 48
/
ql-dsp-io-regs.cc
119 lines (95 loc) · 3.69 KB
/
ql-dsp-io-regs.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "kernel/sigtools.h"
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
// ============================================================================
const std::vector<std::string> ports2del_mult = {"feedback", "load_acc", "saturate_enable", "shift_right", "round", "subtract", "acc_fir", "dly_b"};
const std::vector<std::string> ports2del_mult_add_acc = {"saturate_enable", "shift_right", "round", "acc_fir", "dly_b"};
void ql_dsp_io_regs_pass(RTLIL::Module *module)
{
for (auto cell : module->cells_) {
std::string cell_type = cell.second->type.str();
if (cell_type == RTLIL::escape_id("QL_DSP2")) {
auto dsp = cell.second;
bool del_clk = false;
// Get DSP configuration
const RTLIL::SigSpec *register_inputs;
register_inputs = &dsp->getPort(RTLIL::escape_id("register_inputs"));
if (!register_inputs)
log_error("register_inputs port not found!");
auto reg_in_c = register_inputs->as_const();
int reg_in_i = reg_in_c.as_int();
const RTLIL::SigSpec *output_select;
output_select = &dsp->getPort(RTLIL::escape_id("output_select"));
if (!output_select)
log_error("output_select port not found!");
auto out_sel_c = output_select->as_const();
int out_sel_i = out_sel_c.as_int();
// Build new type name
std::string new_type = cell_type;
new_type += "_MULT";
switch (out_sel_i) {
case 1:
new_type += "ACC";
break;
case 2:
case 3:
new_type += "ADD";
break;
case 5:
new_type += "ACC";
break;
case 6:
case 7:
new_type += "ADD";
break;
default:
break;
}
if (reg_in_i)
new_type += "_REGIN";
if (out_sel_i > 3)
new_type += "_REGOUT";
// Set new type name
dsp->type = RTLIL::IdString(new_type);
// Delete ports unused in given type of DSP cell
del_clk = (!reg_in_i && out_sel_i <= 3);
std::vector<std::string> ports2del;
if (del_clk)
ports2del.push_back("clk");
if (out_sel_i == 0 || out_sel_i == 4) {
ports2del.insert(ports2del.end(), ports2del_mult.begin(), ports2del_mult.end());
} else {
ports2del.insert(ports2del.end(), ports2del_mult_add_acc.begin(), ports2del_mult_add_acc.end());
}
for (auto portname : ports2del) {
const RTLIL::SigSpec *port = &dsp->getPort(RTLIL::escape_id(portname));
if (!port)
log_error("%s port not found!", portname.c_str());
dsp->connections_.erase(RTLIL::escape_id(portname));
}
}
}
}
struct QlDspIORegs : public Pass {
QlDspIORegs() : Pass("ql_dsp_io_regs", "Does something") {}
void help() override
{
log("\n");
log(" ql_dsp_io_regs [options] [selection]\n");
log("\n");
}
void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) override
{
log_header(a_Design, "Executing QL_DSP_IO_REGS pass.\n");
size_t argidx;
for (argidx = 1; argidx < a_Args.size(); argidx++) {
break;
}
extra_args(a_Args, argidx, a_Design);
for (auto module : a_Design->selected_modules()) {
ql_dsp_io_regs_pass(module);
}
}
} QlDspIORegs;
PRIVATE_NAMESPACE_END