@@ -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
158218PRIVATE_NAMESPACE_END
0 commit comments