diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 5c9f17710..cf5e6dcb7 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -441,6 +441,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::SigSpec lhs = init_lvalue_c; RTLIL::SigSpec rhs = init_rvalue.extract(offset, init_lvalue_c.width); remove_unwanted_lvalue_bits(lhs, rhs); + // TODO sync->actions.push_back({lhs, rhs, Const("")}); offset += lhs.size(); } diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index 5bef77cd2..9eae29bbd 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -20,6 +20,7 @@ #include "kernel/register.h" #include "kernel/bitpattern.h" #include "kernel/log.h" +#include "kernel/rtlil.h" #include #include #include @@ -27,11 +28,31 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +using SnippetSourceMap = dict, const Const*>; +struct SnippetSourceMapBuilder { + SnippetSourceMap map; + void insert(int snippet, const RTLIL::CaseRule* cs, const RTLIL::SyncAction& action) { + map[std::make_pair(snippet, cs)] = &action.src; + } + +}; +struct SnippetSourceMapper { + SnippetSourceMap map; + void try_map_into(pool& sources, int snippet, const RTLIL::CaseRule* cs) const { + auto src_it = map.find(std::make_pair(snippet, cs)); + if (src_it != map.end()) { + sources.insert(src_it->second->decode_string()); + } + } + +}; + struct SigSnippets { idict sigidx; dict bit2snippet; pool snippets; + SnippetSourceMapBuilder source_builder; void insert(SigSpec sig) { @@ -97,8 +118,11 @@ struct SigSnippets void insert(const RTLIL::CaseRule *cs) { - for (auto &action : cs->actions) + for (auto &action : cs->actions) { insert(action.lhs); + int idx = sigidx(action.lhs); + source_builder.insert(idx, cs, action); + } for (auto sw : cs->switches) for (auto cs2 : sw->cases) @@ -146,8 +170,14 @@ struct SnippetSwCache void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::CaseRule *cs) { - cell->attributes = sw->attributes; - cell->add_strpool_attribute(ID::src, cs->get_strpool_attribute(ID::src)); + Const old_src; + if (cell->attributes.count(ID::src)) { + std::swap(old_src, cell->attributes[ID::src]); + } + cell->attributes = cs->attributes; + if (old_src.size()) { + std::swap(old_src, cell->attributes[ID::src]); + } } struct MuxGenCtx { @@ -158,6 +188,9 @@ struct MuxGenCtx { RTLIL::SwitchRule *sw; RTLIL::CaseRule *cs; bool ifxmode; + const SnippetSourceMapper& source_mapper; + int current_snippet; + pool& snippet_sources; RTLIL::SigSpec gen_cmp() { std::stringstream sstr; @@ -255,6 +288,8 @@ struct MuxGenCtx { mux_cell->setPort(ID::S, ctrl_sig); mux_cell->setPort(ID::Y, RTLIL::SigSpec(result_wire)); + source_mapper.try_map_into(snippet_sources, current_snippet, cs); + last_mux_cell = mux_cell; return RTLIL::SigSpec(result_wire); } @@ -279,8 +314,9 @@ struct MuxGenCtx { last_mux_cell->setPort(ID::B, new_b); last_mux_cell->parameters[ID::S_WIDTH] = last_mux_cell->getPort(ID::S).size(); - } + source_mapper.try_map_into(snippet_sources, current_snippet, cs); + } }; const pool &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRule *sw) @@ -328,6 +364,7 @@ const pool &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRul struct MuxTreeContext { RTLIL::Module* mod; SnippetSwCache& swcache; + const SnippetSourceMapper& source_mapper; dict &swpara; RTLIL::CaseRule *cs; const RTLIL::SigSpec &sig; @@ -351,6 +388,7 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx) // detect groups of parallel cases std::vector pgroups(sw->cases.size()); + pool case_sources; bool is_simple_parallel_case = true; if (!sw->get_bool_attribute(ID::parallel_case)) { @@ -402,7 +440,13 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx) pool.take(pat); } } - + // Create sources for default cases + for (auto cs2 : sw -> cases) { + if (cs2->compare.empty()) { + int sn = ctx.swcache.current_snippet; + ctx.source_mapper.try_map_into(case_sources, sn, cs2); + } + } // mask default bits that are irrelevant because the output is driven by a full case const pool &full_case_bits = get_full_case_bits(ctx.swcache, sw); for (int i = 0; i < GetSize(ctx.sig); i++) @@ -416,7 +460,10 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx) nullptr, sw, nullptr, - ctx.ifxmode + ctx.ifxmode, + ctx.source_mapper, + ctx.swcache.current_snippet, + case_sources }; // evaluate in reverse order to give the first entry the top priority for (size_t i = 0; i < sw->cases.size(); i++) { @@ -433,6 +480,9 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx) result = mux_gen_ctx.gen_mux(value, result); } } + if (mux_gen_ctx.last_mux_cell) { + mux_gen_ctx.last_mux_cell->set_strpool_attribute(ID::src, case_sources); + } } return result; @@ -459,9 +509,11 @@ void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc, bool ifxmode) log_debug("%6d/%d: %s\n", ++cnt, GetSize(sigsnip.snippets), log_signal(sig)); + const SnippetSourceMapper mapper{sigsnip.source_builder.map}; RTLIL::SigSpec value = signal_to_mux_tree({ mod, swcache, + mapper, swpara, &proc->root_case, sig,