mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-15 03:35:40 +00:00
techmap: efficient twines
This commit is contained in:
parent
7c73fd62e4
commit
ba4ea22831
1 changed files with 70 additions and 31 deletions
|
|
@ -47,32 +47,69 @@ void apply_prefix(IdString prefix, IdString &id)
|
|||
id = stringf("$techmap%s.%s", prefix, id);
|
||||
}
|
||||
|
||||
TwineRef apply_prefix_ref(IdString prefix, IdString id, RTLIL::Design *design)
|
||||
// Prefixes a template object's name with an instance's "<cell>." (public) or
|
||||
// "$techmap<cell>." (private) prefix, for one cell's worth of instantiation.
|
||||
// A name like "\a.b.c" is stored as nested Suffix nodes
|
||||
// Suffix{Suffix{"\a.", "b."}, "c"}; recursing the Suffix chain re-prefixes only
|
||||
// the innermost leaf ("\a." -> "\u.a.") and reuses the rest, so "b.", "c" stay
|
||||
// shared instead of materialising "a.b.c" as one fresh tail per object.
|
||||
// Reads the template name from TwinePool src and writes TwinePool dst.
|
||||
struct PrefixApplier
|
||||
{
|
||||
std::string ids = id.str();
|
||||
std::string shared, tail;
|
||||
if (!ids.empty() && ids[0] == '\\') {
|
||||
shared = prefix.str() + ".";
|
||||
tail = ids.substr(1);
|
||||
} else {
|
||||
shared = "$techmap" + prefix.str() + ".";
|
||||
tail = std::move(ids);
|
||||
}
|
||||
TwineRef pref = design->twines.add(std::move(shared));
|
||||
return design->twines.add(Twine{Twine::Suffix{pref, std::move(tail)}});
|
||||
}
|
||||
RTLIL::Design *dst;
|
||||
RTLIL::Design *src;
|
||||
TwineRef cell_name;
|
||||
TwineRef pub_prefix;
|
||||
TwineRef priv_prefix = Twine::Null;
|
||||
dict<TwineRef, TwineRef> memo;
|
||||
|
||||
void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
|
||||
{
|
||||
vector<SigChunk> chunks = sig;
|
||||
for (auto &chunk : chunks)
|
||||
if (chunk.wire != nullptr) {
|
||||
TwineRef wire_ref = apply_prefix_ref(prefix, chunk.wire->name, module->design);
|
||||
log_assert(module->wire(wire_ref) != nullptr);
|
||||
chunk.wire = module->wire(wire_ref);
|
||||
PrefixApplier(RTLIL::Design *dst, TwineRef prefix, RTLIL::Design *src)
|
||||
: dst(dst), src(src), cell_name(prefix)
|
||||
{
|
||||
pub_prefix = dst->twines.add(Twine{Twine::Suffix{prefix, "."}});
|
||||
}
|
||||
|
||||
// "$techmap<cell>." can't reuse the cell name's nodes (a tail is appended,
|
||||
// not prepended), so it is the one prefix we materialise -- lazily, since
|
||||
// many templates have no private wires.
|
||||
TwineRef techmap_prefix()
|
||||
{
|
||||
if (priv_prefix == Twine::Null)
|
||||
priv_prefix = dst->twines.add("$techmap" + dst->twines.str(cell_name) + ".");
|
||||
return priv_prefix;
|
||||
}
|
||||
|
||||
TwineRef name(TwineRef obj_ref)
|
||||
{
|
||||
if (auto it = memo.find(obj_ref); it != memo.end())
|
||||
return it->second;
|
||||
|
||||
const Twine &node = src->twines[obj_ref];
|
||||
TwineRef result;
|
||||
if (node.is_suffix()) {
|
||||
const Twine::Suffix &sfx = node.suffix();
|
||||
TwineRef prefix = name(twine_tag(sfx.prefix, obj_ref.is_public()));
|
||||
result = dst->twines.add(Twine{Twine::Suffix{prefix, sfx.tail}});
|
||||
} else {
|
||||
TwineRef prefix = obj_ref.is_public() ? pub_prefix : techmap_prefix();
|
||||
result = dst->twines.add(Twine{Twine::Suffix{prefix, node.leaf()}});
|
||||
}
|
||||
sig = chunks;
|
||||
}
|
||||
memo[obj_ref] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void apply(RTLIL::SigSpec &sig, RTLIL::Module *module)
|
||||
{
|
||||
vector<SigChunk> chunks = sig;
|
||||
for (auto &chunk : chunks)
|
||||
if (chunk.wire != nullptr) {
|
||||
TwineRef wire_ref = name(chunk.wire->name.ref());
|
||||
log_assert(module->wire(wire_ref) != nullptr);
|
||||
chunk.wire = module->wire(wire_ref);
|
||||
}
|
||||
sig = chunks;
|
||||
}
|
||||
};
|
||||
|
||||
struct TechmapWorker
|
||||
{
|
||||
|
|
@ -185,6 +222,8 @@ struct TechmapWorker
|
|||
break;
|
||||
}
|
||||
|
||||
PrefixApplier ap(module->design, cell->name.ref(), tpl->design);
|
||||
|
||||
dict<IdString, IdString> memory_renames;
|
||||
|
||||
for (auto &it : tpl->memories) {
|
||||
|
|
@ -222,7 +261,7 @@ struct TechmapWorker
|
|||
autopurge_tpl_bits.insert(bit);
|
||||
}
|
||||
}
|
||||
TwineRef w_ref = apply_prefix_ref(cell->name, tpl_w->name, module->design);
|
||||
TwineRef w_ref = ap.name(tpl_w->name.ref());
|
||||
RTLIL::Wire *w = module->wire(w_ref);
|
||||
if (w != nullptr) {
|
||||
temp_renamed_wires[w] = w->name.ref();
|
||||
|
|
@ -280,18 +319,18 @@ struct TechmapWorker
|
|||
if (w->port_output && !w->port_input) {
|
||||
c.first = it.second;
|
||||
c.second = RTLIL::SigSpec(w);
|
||||
apply_prefix(cell->name, c.second, module);
|
||||
ap.apply(c.second, module);
|
||||
extra_connect.first = c.second;
|
||||
extra_connect.second = c.first;
|
||||
} else if (!w->port_output && w->port_input) {
|
||||
c.first = RTLIL::SigSpec(w);
|
||||
c.second = it.second;
|
||||
apply_prefix(cell->name, c.first, module);
|
||||
ap.apply(c.first, module);
|
||||
extra_connect.first = c.first;
|
||||
extra_connect.second = c.second;
|
||||
} else {
|
||||
SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
|
||||
apply_prefix(cell->name, sig_tpl_pf, module);
|
||||
ap.apply(sig_tpl_pf, module);
|
||||
for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
|
||||
if (tpl_written_bits.count(sig_tpl[i])) {
|
||||
c.first.append(sig_mod[i]);
|
||||
|
|
@ -350,7 +389,7 @@ struct TechmapWorker
|
|||
else if (const char *p = strstr(tpl_cell->name.str().c_str(), "_TECHMAP_REPLACE_."))
|
||||
c_ref = module->design->twines.add(stringf("%s%s", orig_cell_name, p + strlen("_TECHMAP_REPLACE_")));
|
||||
else
|
||||
c_ref = apply_prefix_ref(cell->name, tpl_cell->name, module->design);
|
||||
c_ref = ap.name(tpl_cell->name.ref());
|
||||
|
||||
RTLIL::Cell *c = module->addCell(c_ref, tpl_cell);
|
||||
design->select(module, c);
|
||||
|
|
@ -378,7 +417,7 @@ struct TechmapWorker
|
|||
autopurge_ports.push_back(conn.first);
|
||||
} else {
|
||||
RTLIL::SigSpec new_conn = conn.second;
|
||||
apply_prefix(cell->name, new_conn, module);
|
||||
ap.apply(new_conn, module);
|
||||
port_signal_map.apply(new_conn);
|
||||
c->setPort(conn.first, std::move(new_conn));
|
||||
}
|
||||
|
|
@ -410,8 +449,8 @@ struct TechmapWorker
|
|||
|
||||
for (auto &it : tpl->connections()) {
|
||||
RTLIL::SigSig c = it;
|
||||
apply_prefix(cell->name.str(), c.first, module);
|
||||
apply_prefix(cell->name.str(), c.second, module);
|
||||
ap.apply(c.first, module);
|
||||
ap.apply(c.second, module);
|
||||
port_signal_map.apply(c.first);
|
||||
port_signal_map.apply(c.second);
|
||||
module->connect(c);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue