27
27
USING_YOSYS_NAMESPACE
28
28
PRIVATE_NAMESPACE_BEGIN
29
29
30
- RTLIL::SigSpec find_any_lvalue ( const RTLIL::CaseRule *cs)
30
+ struct SigSnippets
31
31
{
32
- for (auto &action : cs->actions ) {
33
- if (action.first .size ())
34
- return action.first ;
35
- }
32
+ idict<SigSpec> sigidx;
33
+ dict<SigBit, int > bit2snippet;
34
+ pool<int > snippets;
36
35
37
- for (auto sw : cs->switches )
38
- for (auto cs2 : sw->cases ) {
39
- RTLIL::SigSpec sig = find_any_lvalue (cs2);
40
- if (sig.size ())
41
- return sig;
36
+ void insert (SigSpec sig)
37
+ {
38
+ if (sig.empty ())
39
+ return ;
40
+
41
+ int key = sigidx (sig);
42
+ if (snippets.count (key))
43
+ return ;
44
+
45
+ SigSpec new_sig;
46
+
47
+ for (int i = 0 ; i < GetSize (sig); i++)
48
+ {
49
+ int other_key = bit2snippet.at (sig[i], -1 );
50
+
51
+ if (other_key < 0 ) {
52
+ new_sig.append (sig[i]);
53
+ continue ;
54
+ }
55
+
56
+ if (!new_sig.empty ()) {
57
+ int new_key = sigidx (new_sig);
58
+ snippets.insert (new_key);
59
+ for (auto bit : new_sig)
60
+ bit2snippet[bit] = new_key;
61
+ new_sig = SigSpec ();
62
+ }
63
+
64
+ SigSpec other_sig = sigidx[other_key];
65
+ int k = 0 , n = 1 ;
66
+
67
+ while (other_sig[k] != sig[i]) {
68
+ k++;
69
+ log_assert (k < GetSize (other_sig));
70
+ }
71
+
72
+ while (i+n < GetSize (sig) && k+n < GetSize (other_sig) && sig[i+n] == other_sig[k+n])
73
+ n++;
74
+
75
+ SigSpec sig1 = other_sig.extract (0 , k);
76
+ SigSpec sig2 = other_sig.extract (k, n);
77
+ SigSpec sig3 = other_sig.extract (k+n, GetSize (other_sig)-k-n);
78
+
79
+ for (auto bit : other_sig)
80
+ bit2snippet.erase (bit);
81
+ snippets.erase (other_key);
82
+
83
+ insert (sig1);
84
+ insert (sig2);
85
+ insert (sig3);
86
+
87
+ i += n-1 ;
88
+ }
89
+
90
+ if (!new_sig.empty ()) {
91
+ int new_key = sigidx (new_sig);
92
+ snippets.insert (new_key);
93
+ for (auto bit : new_sig)
94
+ bit2snippet[bit] = new_key;
95
+ }
42
96
}
43
97
44
- return RTLIL::SigSpec ();
45
- }
98
+ void insert (const RTLIL::CaseRule *cs)
99
+ {
100
+ for (auto &action : cs->actions )
101
+ insert (action.first );
46
102
47
- void extract_core_signal (const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig)
103
+ for (auto sw : cs->switches )
104
+ for (auto cs2 : sw->cases )
105
+ insert (cs2);
106
+ }
107
+ };
108
+
109
+ struct SnippetSwCache
48
110
{
49
- for (auto &action : cs->actions ) {
50
- RTLIL::SigSpec lvalue = action.first .extract (sig);
51
- if (lvalue.size ())
52
- sig = lvalue;
111
+ dict<RTLIL::SwitchRule*, pool<int >, hash_ptr_ops> cache;
112
+ const SigSnippets *snippets;
113
+ int current_snippet;
114
+
115
+ bool check (RTLIL::SwitchRule *sw)
116
+ {
117
+ return cache[sw].count (current_snippet) != 0 ;
53
118
}
54
119
55
- for (auto sw : cs->switches )
56
- for (auto cs2 : sw->cases )
57
- extract_core_signal (cs2, sig);
58
- }
120
+ void insert (const RTLIL::CaseRule *cs, vector<RTLIL::SwitchRule*> &sw_stack)
121
+ {
122
+ for (auto &action : cs->actions )
123
+ for (auto bit : action.first ) {
124
+ int sn = snippets->bit2snippet .at (bit, -1 );
125
+ if (sn < 0 )
126
+ continue ;
127
+ for (auto sw : sw_stack)
128
+ cache[sw].insert (sn);
129
+ }
130
+
131
+ for (auto sw : cs->switches ) {
132
+ sw_stack.push_back (sw);
133
+ for (auto cs2 : sw->cases )
134
+ insert (cs2, sw_stack);
135
+ sw_stack.pop_back ();
136
+ }
137
+ }
138
+
139
+ void insert (const RTLIL::CaseRule *cs)
140
+ {
141
+ vector<RTLIL::SwitchRule*> sw_stack;
142
+ insert (cs, sw_stack);
143
+ }
144
+ };
59
145
60
146
RTLIL::SigSpec gen_cmp (RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw)
61
147
{
@@ -179,7 +265,8 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve
179
265
last_mux_cell->parameters [" \\ S_WIDTH" ] = last_mux_cell->getPort (" \\ S" ).size ();
180
266
}
181
267
182
- RTLIL::SigSpec signal_to_mux_tree (RTLIL::Module *mod, RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval)
268
+ RTLIL::SigSpec signal_to_mux_tree (RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool , hash_ptr_ops> &swpara,
269
+ RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval)
183
270
{
184
271
RTLIL::SigSpec result = defval;
185
272
@@ -190,9 +277,37 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const
190
277
191
278
for (auto sw : cs->switches )
192
279
{
280
+ if (!swcache.check (sw))
281
+ continue ;
282
+
193
283
// detect groups of parallel cases
194
284
std::vector<int > pgroups (sw->cases .size ());
285
+ bool is_simple_parallel_case = true ;
286
+
195
287
if (!sw->get_bool_attribute (" \\ parallel_case" )) {
288
+ if (!swpara.count (sw)) {
289
+ pool<Const> case_values;
290
+ for (size_t i = 0 ; i < sw->cases .size (); i++) {
291
+ RTLIL::CaseRule *cs2 = sw->cases [i];
292
+ for (auto pat : cs2->compare ) {
293
+ if (!pat.is_fully_def ())
294
+ goto not_simple_parallel_case;
295
+ Const cpat = pat.as_const ();
296
+ if (case_values.count (cpat))
297
+ goto not_simple_parallel_case;
298
+ case_values.insert (cpat);
299
+ }
300
+ }
301
+ if (0 )
302
+ not_simple_parallel_case:
303
+ is_simple_parallel_case = false ;
304
+ swpara[sw] = is_simple_parallel_case;
305
+ } else {
306
+ is_simple_parallel_case = swpara.at (sw);
307
+ }
308
+ }
309
+
310
+ if (!is_simple_parallel_case) {
196
311
BitPatternPool pool (sw->signal .size ());
197
312
bool extra_group_for_next_case = false ;
198
313
for (size_t i = 0 ; i < sw->cases .size (); i++) {
@@ -225,7 +340,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const
225
340
for (size_t i = 0 ; i < sw->cases .size (); i++) {
226
341
int case_idx = sw->cases .size () - i - 1 ;
227
342
RTLIL::CaseRule *cs2 = sw->cases [case_idx];
228
- RTLIL::SigSpec value = signal_to_mux_tree (mod, cs2, sig, initial_val);
343
+ RTLIL::SigSpec value = signal_to_mux_tree (mod, swcache, swpara, cs2, sig, initial_val);
229
344
if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1 ])
230
345
append_pmux (mod, sw->signal , cs2->compare , value, last_mux_cell, sw);
231
346
else
@@ -238,24 +353,26 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const
238
353
239
354
void proc_mux (RTLIL::Module *mod, RTLIL::Process *proc)
240
355
{
241
- bool first = true ;
242
- while (1 )
243
- {
244
- RTLIL::SigSpec sig = find_any_lvalue (&proc->root_case );
356
+ log (" Creating decoders for process `%s.%s'.\n " , mod->name .c_str (), proc->name .c_str ());
245
357
246
- if (sig. size () == 0 )
247
- break ;
358
+ SigSnippets sigsnip;
359
+ sigsnip. insert (&proc-> root_case ) ;
248
360
249
- if (first) {
250
- log (" Creating decoders for process `%s.%s'.\n " , mod->name .c_str (), proc->name .c_str ());
251
- first = false ;
252
- }
361
+ SnippetSwCache swcache;
362
+ swcache.snippets = &sigsnip;
363
+ swcache.insert (&proc->root_case );
364
+
365
+ dict<RTLIL::SwitchRule*, bool , hash_ptr_ops> swpara;
253
366
254
- extract_core_signal (&proc->root_case , sig);
367
+ int cnt = 0 ;
368
+ for (int idx : sigsnip.snippets )
369
+ {
370
+ swcache.current_snippet = idx;
371
+ RTLIL::SigSpec sig = sigsnip.sigidx [idx];
255
372
256
- log (" creating decoder for signal `%s'. \n " , log_signal (sig));
373
+ log (" %6d/%d: %s \n " , ++cnt, GetSize (sigsnip. snippets ) , log_signal (sig));
257
374
258
- RTLIL::SigSpec value = signal_to_mux_tree (mod, &proc->root_case , sig, RTLIL::SigSpec (RTLIL::State::Sx, sig.size ()));
375
+ RTLIL::SigSpec value = signal_to_mux_tree (mod, swcache, swpara, &proc->root_case , sig, RTLIL::SigSpec (RTLIL::State::Sx, sig.size ()));
259
376
mod->connect (RTLIL::SigSig (sig, value));
260
377
}
261
378
}
0 commit comments