mirror of https://github.com/YosysHQ/yosys.git
techmap: efficient twines
This commit is contained in:
parent
7c73fd62e4
commit
ba4ea22831
|
|
@ -47,32 +47,69 @@ void apply_prefix(IdString prefix, IdString &id)
|
||||||
id = stringf("$techmap%s.%s", prefix, 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();
|
RTLIL::Design *dst;
|
||||||
std::string shared, tail;
|
RTLIL::Design *src;
|
||||||
if (!ids.empty() && ids[0] == '\\') {
|
TwineRef cell_name;
|
||||||
shared = prefix.str() + ".";
|
TwineRef pub_prefix;
|
||||||
tail = ids.substr(1);
|
TwineRef priv_prefix = Twine::Null;
|
||||||
} else {
|
dict<TwineRef, TwineRef> memo;
|
||||||
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)}});
|
|
||||||
}
|
|
||||||
|
|
||||||
void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
|
PrefixApplier(RTLIL::Design *dst, TwineRef prefix, RTLIL::Design *src)
|
||||||
{
|
: dst(dst), src(src), cell_name(prefix)
|
||||||
vector<SigChunk> chunks = sig;
|
{
|
||||||
for (auto &chunk : chunks)
|
pub_prefix = dst->twines.add(Twine{Twine::Suffix{prefix, "."}});
|
||||||
if (chunk.wire != nullptr) {
|
}
|
||||||
TwineRef wire_ref = apply_prefix_ref(prefix, chunk.wire->name, module->design);
|
|
||||||
log_assert(module->wire(wire_ref) != nullptr);
|
// "$techmap<cell>." can't reuse the cell name's nodes (a tail is appended,
|
||||||
chunk.wire = module->wire(wire_ref);
|
// 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
|
struct TechmapWorker
|
||||||
{
|
{
|
||||||
|
|
@ -185,6 +222,8 @@ struct TechmapWorker
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrefixApplier ap(module->design, cell->name.ref(), tpl->design);
|
||||||
|
|
||||||
dict<IdString, IdString> memory_renames;
|
dict<IdString, IdString> memory_renames;
|
||||||
|
|
||||||
for (auto &it : tpl->memories) {
|
for (auto &it : tpl->memories) {
|
||||||
|
|
@ -222,7 +261,7 @@ struct TechmapWorker
|
||||||
autopurge_tpl_bits.insert(bit);
|
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);
|
RTLIL::Wire *w = module->wire(w_ref);
|
||||||
if (w != nullptr) {
|
if (w != nullptr) {
|
||||||
temp_renamed_wires[w] = w->name.ref();
|
temp_renamed_wires[w] = w->name.ref();
|
||||||
|
|
@ -280,18 +319,18 @@ struct TechmapWorker
|
||||||
if (w->port_output && !w->port_input) {
|
if (w->port_output && !w->port_input) {
|
||||||
c.first = it.second;
|
c.first = it.second;
|
||||||
c.second = RTLIL::SigSpec(w);
|
c.second = RTLIL::SigSpec(w);
|
||||||
apply_prefix(cell->name, c.second, module);
|
ap.apply(c.second, module);
|
||||||
extra_connect.first = c.second;
|
extra_connect.first = c.second;
|
||||||
extra_connect.second = c.first;
|
extra_connect.second = c.first;
|
||||||
} else if (!w->port_output && w->port_input) {
|
} else if (!w->port_output && w->port_input) {
|
||||||
c.first = RTLIL::SigSpec(w);
|
c.first = RTLIL::SigSpec(w);
|
||||||
c.second = it.second;
|
c.second = it.second;
|
||||||
apply_prefix(cell->name, c.first, module);
|
ap.apply(c.first, module);
|
||||||
extra_connect.first = c.first;
|
extra_connect.first = c.first;
|
||||||
extra_connect.second = c.second;
|
extra_connect.second = c.second;
|
||||||
} else {
|
} else {
|
||||||
SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
|
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++) {
|
for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
|
||||||
if (tpl_written_bits.count(sig_tpl[i])) {
|
if (tpl_written_bits.count(sig_tpl[i])) {
|
||||||
c.first.append(sig_mod[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_."))
|
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_")));
|
c_ref = module->design->twines.add(stringf("%s%s", orig_cell_name, p + strlen("_TECHMAP_REPLACE_")));
|
||||||
else
|
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);
|
RTLIL::Cell *c = module->addCell(c_ref, tpl_cell);
|
||||||
design->select(module, c);
|
design->select(module, c);
|
||||||
|
|
@ -378,7 +417,7 @@ struct TechmapWorker
|
||||||
autopurge_ports.push_back(conn.first);
|
autopurge_ports.push_back(conn.first);
|
||||||
} else {
|
} else {
|
||||||
RTLIL::SigSpec new_conn = conn.second;
|
RTLIL::SigSpec new_conn = conn.second;
|
||||||
apply_prefix(cell->name, new_conn, module);
|
ap.apply(new_conn, module);
|
||||||
port_signal_map.apply(new_conn);
|
port_signal_map.apply(new_conn);
|
||||||
c->setPort(conn.first, std::move(new_conn));
|
c->setPort(conn.first, std::move(new_conn));
|
||||||
}
|
}
|
||||||
|
|
@ -410,8 +449,8 @@ struct TechmapWorker
|
||||||
|
|
||||||
for (auto &it : tpl->connections()) {
|
for (auto &it : tpl->connections()) {
|
||||||
RTLIL::SigSig c = it;
|
RTLIL::SigSig c = it;
|
||||||
apply_prefix(cell->name.str(), c.first, module);
|
ap.apply(c.first, module);
|
||||||
apply_prefix(cell->name.str(), c.second, module);
|
ap.apply(c.second, module);
|
||||||
port_signal_map.apply(c.first);
|
port_signal_map.apply(c.first);
|
||||||
port_signal_map.apply(c.second);
|
port_signal_map.apply(c.second);
|
||||||
module->connect(c);
|
module->connect(c);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue