3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-03 13:07:58 +00:00

proc_mux: emit fused action location src attributes on procmuxes

This commit is contained in:
Emil J. Tywoniak 2025-10-30 15:41:46 +01:00
parent 304757c881
commit d762c5f5e8
2 changed files with 59 additions and 6 deletions

View file

@ -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();
}

View file

@ -20,6 +20,7 @@
#include "kernel/register.h"
#include "kernel/bitpattern.h"
#include "kernel/log.h"
#include "kernel/rtlil.h"
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
@ -27,11 +28,31 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
using SnippetSourceMap = dict<std::pair<int, const RTLIL::CaseRule*>, 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<std::string>& 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<SigSpec> sigidx;
dict<SigBit, int> bit2snippet;
pool<int> 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<std::string>& 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<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRule *sw)
@ -328,6 +364,7 @@ const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRul
struct MuxTreeContext {
RTLIL::Module* mod;
SnippetSwCache& swcache;
const SnippetSourceMapper& source_mapper;
dict<RTLIL::SwitchRule*, bool> &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<int> pgroups(sw->cases.size());
pool<std::string> 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<SigBit> &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,