2828USING_YOSYS_NAMESPACE
2929PRIVATE_NAMESPACE_BEGIN
3030
31+ /* *
32+ * Actions are assignments in cases of switches.
33+ * Snippets are non-overlapping slices of signals on the left-hand side
34+ * of actions. For example, if you have these two actions for r[7:0]:
35+ * r = a; r[1:2] = 2'b0;
36+ * you will arrive at three snippets:
37+ * r[0], r[2:1], r[7:3]
38+ * For each snippet, multiplexers ($mux or $pmux) are emitted
39+ * based on the full switch.
40+ * $pmux are only emitted when legal based on whether the cases can be
41+ * evaluated in parallel.
42+ * In that case, instead of a $pmux, you get a chain of $mux.
43+ * Nested switches build branching trees of muxes.
44+ */
45+
3146using SnippetSourceMap = std::vector<dict<const RTLIL::CaseRule*, const Const*>>;
3247struct SnippetSourceMapBuilder {
3348 SnippetSourceMap map;
@@ -202,6 +217,7 @@ struct MuxGenCtx {
202217 int current_snippet;
203218 pool<std::string>& snippet_sources;
204219
220+ // Returns signal for the select input of a mux
205221 RTLIL::SigSpec gen_cmp () {
206222 std::stringstream sstr;
207223 sstr << " $procmux$" << (autoidx++);
@@ -408,6 +424,38 @@ bool is_simple_parallel_case(RTLIL::SwitchRule* sw, dict<RTLIL::SwitchRule*, boo
408424 return ret;
409425}
410426
427+ std::vector<int > parallel_groups (MuxTreeContext ctx, RTLIL::SwitchRule* sw)
428+ {
429+ std::vector<int > pgroups (sw->cases .size ());
430+ if (!is_simple_parallel_case (sw, ctx.swpara )) {
431+ BitPatternPool pool (sw->signal .size ());
432+ bool extra_group_for_next_case = false ;
433+ for (size_t i = 0 ; i < sw->cases .size (); i++) {
434+ RTLIL::CaseRule *cs2 = sw->cases [i];
435+ if (i != 0 ) {
436+ pgroups[i] = pgroups[i-1 ];
437+ if (extra_group_for_next_case) {
438+ pgroups[i] = pgroups[i-1 ]+1 ;
439+ extra_group_for_next_case = false ;
440+ }
441+ for (auto pat : cs2->compare )
442+ if (!pat.is_fully_const () || !pool.has_all (pat))
443+ pgroups[i] = pgroups[i-1 ]+1 ;
444+ if (cs2->compare .empty ())
445+ pgroups[i] = pgroups[i-1 ]+1 ;
446+ if (pgroups[i] != pgroups[i-1 ])
447+ pool = BitPatternPool (sw->signal .size ());
448+ }
449+ for (auto pat : cs2->compare )
450+ if (!pat.is_fully_const ())
451+ extra_group_for_next_case = true ;
452+ else if (!ctx.ifxmode )
453+ pool.take (pat);
454+ }
455+ }
456+ return pgroups;
457+ }
458+
411459RTLIL::SigSpec signal_to_mux_tree (MuxTreeContext ctx)
412460{
413461 RTLIL::SigSpec result = ctx.defval ;
@@ -422,36 +470,9 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
422470 if (!ctx.swcache .check (sw))
423471 continue ;
424472
425- // detect groups of parallel cases
426- std::vector<int > pgroups (sw-> cases . size () );
473+ // Detect groups of parallel cases
474+ std::vector<int > pgroups = parallel_groups (ctx, sw );
427475 pool<std::string> case_sources;
428-
429- if (!is_simple_parallel_case (sw, ctx.swpara )) {
430- BitPatternPool pool (sw->signal .size ());
431- bool extra_group_for_next_case = false ;
432- for (size_t i = 0 ; i < sw->cases .size (); i++) {
433- RTLIL::CaseRule *cs2 = sw->cases [i];
434- if (i != 0 ) {
435- pgroups[i] = pgroups[i-1 ];
436- if (extra_group_for_next_case) {
437- pgroups[i] = pgroups[i-1 ]+1 ;
438- extra_group_for_next_case = false ;
439- }
440- for (auto pat : cs2->compare )
441- if (!pat.is_fully_const () || !pool.has_all (pat))
442- pgroups[i] = pgroups[i-1 ]+1 ;
443- if (cs2->compare .empty ())
444- pgroups[i] = pgroups[i-1 ]+1 ;
445- if (pgroups[i] != pgroups[i-1 ])
446- pool = BitPatternPool (sw->signal .size ());
447- }
448- for (auto pat : cs2->compare )
449- if (!pat.is_fully_const ())
450- extra_group_for_next_case = true ;
451- else if (!ctx.ifxmode )
452- pool.take (pat);
453- }
454- }
455476 // Create sources for default cases
456477 for (auto cs2 : sw -> cases) {
457478 if (cs2->compare .empty ()) {
@@ -466,7 +487,8 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
466487 result[i] = State::Sx;
467488
468489 RTLIL::SigSpec initial_val = result;
469- MuxGenCtx mux_gen_ctx {ctx.mod ,
490+ MuxGenCtx mux_gen_ctx {
491+ ctx.mod ,
470492 sw->signal ,
471493 nullptr ,
472494 nullptr ,
@@ -477,7 +499,7 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
477499 ctx.swcache .current_snippet ,
478500 case_sources
479501 };
480- // evaluate in reverse order to give the first entry the top priority
502+ // Evaluate in reverse order to give the first entry the top priority
481503 for (size_t i = 0 ; i < sw->cases .size (); i++) {
482504 int case_idx = sw->cases .size () - i - 1 ;
483505 MuxTreeContext new_ctx = ctx;
0 commit comments