From 775b8f2f4c8c740abc016202b63106daf745e662 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 11 Dec 2025 00:45:30 +0100 Subject: [PATCH] proc_mux, genrtlil: make use of case_src for better case condition vs block tracking --- frontends/ast/genrtlil.cc | 18 ++++++++++++------ passes/proc/proc_mux.cc | 4 ++++ tests/proc/proc_mux_src.v | 22 ++++++++++++++++++++++ tests/proc/proc_mux_src.ys | 7 +++++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index cf5e6dcb7..bdd4acaa0 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -660,17 +660,23 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::CaseRule *backup_case = current_case; // here current_case = new RTLIL::CaseRule; - set_src_attr(current_case, child.get()); + current_case->compare_src = child->loc_string(); last_generated_case = current_case; - addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue, child.get()); + std::optional block; for (auto& node : child->children) { - if (node->type == AST_DEFAULT) + if (node->type == AST_DEFAULT) { default_case = current_case; - else if (node->type == AST_BLOCK) - processAst(node.get()); - else + } else if (node->type == AST_BLOCK) { + log_assert(!block.has_value()); + block = node.get(); + } else { current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap())); + } } + log_assert(block.has_value()); + set_src_attr(current_case, *block); + addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue, *block); + processAst(*block); if (default_case != current_case) sw->cases.push_back(current_case); else diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index aff295f98..a98495727 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -248,6 +248,8 @@ struct MuxGenCtx { // create compare cell RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str(), cmp_wire->width), ifxmode ? ID($eqx) : ID($eq)); apply_attrs(eq_cell, cs); + if (cs->compare_src.size()) + eq_cell->attributes[ID::src] = cs->compare_src; eq_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); eq_cell->parameters[ID::B_SIGNED] = RTLIL::Const(0); @@ -274,6 +276,8 @@ struct MuxGenCtx { // reduce cmp vector to one logic signal RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", ID($reduce_or)); apply_attrs(any_cell, cs); + if (cs->compare_src.size()) + any_cell->attributes[ID::src] = cs->compare_src; any_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); any_cell->parameters[ID::A_WIDTH] = RTLIL::Const(cmp_wire->width); diff --git a/tests/proc/proc_mux_src.v b/tests/proc/proc_mux_src.v index 17d6da104..2856a4280 100644 --- a/tests/proc/proc_mux_src.v +++ b/tests/proc/proc_mux_src.v @@ -90,3 +90,25 @@ module tiny2( endcase end endmodule + +module ifelse(input clk, + input cond1, + input cond2, + output reg [1:0] out +); + + always @(posedge clk) begin + if (cond1) begin + out <= 0; + end else begin + if(cond2) + begin + out <= 1; + end + else + begin + out <= 2; + end + end + end +endmodule diff --git a/tests/proc/proc_mux_src.ys b/tests/proc/proc_mux_src.ys index 8c146db70..d72977a1c 100644 --- a/tests/proc/proc_mux_src.ys +++ b/tests/proc/proc_mux_src.ys @@ -28,3 +28,10 @@ select -assert-count 5 nested/t:$pmux select -assert-count 1 nested/t:$pmux a:src=proc_mux_src.v:21.5-21.20|proc_mux_src.v:26.5-26.20|proc_mux_src.v:32.5-45.12|proc_mux_src.v:48.5-48.19 %i # No nesting for output reg arith select -assert-count 1 nested/t:$pmux a:src=proc_mux_src.v:23.5-23.18|proc_mux_src.v:28.5-28.18|proc_mux_src.v:31.5-31.18|proc_mux_src.v:50.5-50.18 %i + +# if/elseif can't be turned into a $pmux +# Otherwise, behaves as expected +select -assert-count 0 ifelse/t:$pmux +select -assert-count 2 ifelse/t:$mux +select -assert-count 1 ifelse/t:$mux a:src=proc_mux_src.v:102.4-102.12|proc_mux_src.v:103.11-112.6 %i +select -assert-count 1 ifelse/t:$mux a:src=proc_mux_src.v:106.6-106.14|proc_mux_src.v:110.6-110.14 %i \ No newline at end of file