mirror of
https://github.com/YosysHQ/yosys.git
synced 2026-08-22 06:07:26 +02:00
WIP
This commit is contained in:
@@ -52,7 +52,7 @@ std::string getFileinfo(const RTLIL::AttrObject *design_entity, const RTLIL::Des
|
|||||||
// Get a port direction with respect to a specific module.
|
// Get a port direction with respect to a specific module.
|
||||||
FDirection getPortFDirection(IdString id, Module *module)
|
FDirection getPortFDirection(IdString id, Module *module)
|
||||||
{
|
{
|
||||||
Wire *wire = module->wires_.at(id);
|
Wire *wire = module->wire(id);
|
||||||
FDirection direction = FD_NODIRECTION;
|
FDirection direction = FD_NODIRECTION;
|
||||||
if (wire && wire->port_id)
|
if (wire && wire->port_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const R
|
|||||||
Twine::Id id = design->obj_src_id(obj);
|
Twine::Id id = design->obj_src_id(obj);
|
||||||
f << stringf("%s" "attribute \\src ", indent);
|
f << stringf("%s" "attribute \\src ", indent);
|
||||||
if (resolve_src) {
|
if (resolve_src) {
|
||||||
dump_const(f, RTLIL::Const(design->src_twines.flatten(id)));
|
dump_const(f, RTLIL::Const(design->twines.flatten(id)));
|
||||||
} else {
|
} else {
|
||||||
dump_const(f, RTLIL::Const(TwinePool::format_ref(id)));
|
dump_const(f, RTLIL::Const(design->twines.format_ref(id)));
|
||||||
}
|
}
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
@@ -56,10 +56,10 @@ void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const R
|
|||||||
|
|
||||||
void RTLIL_BACKEND::dump_twines(std::ostream &f, const RTLIL::Design *design)
|
void RTLIL_BACKEND::dump_twines(std::ostream &f, const RTLIL::Design *design)
|
||||||
{
|
{
|
||||||
if (!design || design->src_twines.size() == 0)
|
if (!design || design->twines.size() == 0)
|
||||||
return;
|
return;
|
||||||
f << stringf("twines\n");
|
f << stringf("twines\n");
|
||||||
design->src_twines.for_each_live([&](Twine::Id id, const Twine &n) {
|
design->twines.for_each_live([&](Twine::Id id, const Twine &n) {
|
||||||
if (n.is_leaf()) {
|
if (n.is_leaf()) {
|
||||||
f << stringf(" leaf %u ", id);
|
f << stringf(" leaf %u ", id);
|
||||||
dump_const(f, RTLIL::Const(n.leaf()));
|
dump_const(f, RTLIL::Const(n.leaf()));
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ YOSYS_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
namespace RTLIL_BACKEND {
|
namespace RTLIL_BACKEND {
|
||||||
// If `design` is non-null AND `resolve_src` is true, the ID::src
|
// If `design` is non-null AND `resolve_src` is true, the ID::src
|
||||||
// attribute is expanded through design->src_twines so the emitted
|
// attribute is expanded through design->twines so the emitted
|
||||||
// value is the flat path:line.col string. Otherwise the stored value
|
// value is the flat path:line.col string. Otherwise the stored value
|
||||||
// is written verbatim — including any "@N" twine references, which
|
// is written verbatim — including any "@N" twine references, which
|
||||||
// the matching `twines` header block emitted by dump_design lets the
|
// the matching `twines` header block emitted by dump_design lets the
|
||||||
|
|||||||
@@ -1122,7 +1122,7 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
|
|||||||
// carrying only ":line.col-line.col". For a typical large design with
|
// carrying only ":line.col-line.col". For a typical large design with
|
||||||
// thousands of objects in one file this collapses N copies of a long
|
// thousands of objects in one file this collapses N copies of a long
|
||||||
// path into 1 Leaf + N short Suffix tails.
|
// path into 1 Leaf + N short Suffix tails.
|
||||||
TwinePool *pool = ¤t_module->design->src_twines;
|
TwinePool *pool = ¤t_module->design->twines;
|
||||||
Twine::Id file_id = pool->intern(*loc.begin.filename);
|
Twine::Id file_id = pool->intern(*loc.begin.filename);
|
||||||
std::string tail = stringf(":%d.%d-%d.%d",
|
std::string tail = stringf(":%d.%d-%d.%d",
|
||||||
loc.begin.line, loc.begin.column,
|
loc.begin.line, loc.begin.column,
|
||||||
@@ -1155,7 +1155,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||||||
AstModule *module = new AstModule;
|
AstModule *module = new AstModule;
|
||||||
current_module = module;
|
current_module = module;
|
||||||
// Set design backpointer early — every set_src_attr in genrtlil.cc
|
// Set design backpointer early — every set_src_attr in genrtlil.cc
|
||||||
// resolves the pool via current_module->design->src_twines. The
|
// resolves the pool via current_module->design->twines. The
|
||||||
// final design->add(current_module) at end-of-process_module hooks
|
// final design->add(current_module) at end-of-process_module hooks
|
||||||
// the module into the design's modules_ dict; we just need design
|
// the module into the design's modules_ dict; we just need design
|
||||||
// reachable as a backpointer for src interning meanwhile.
|
// reachable as a backpointer for src interning meanwhile.
|
||||||
|
|||||||
@@ -503,7 +503,7 @@ struct AST_INTERNAL::ProcessGenerator
|
|||||||
chunk.wire->name.c_str(), chunk.width+chunk.offset-1, chunk.offset);;
|
chunk.wire->name.c_str(), chunk.width+chunk.offset-1, chunk.offset);;
|
||||||
if (chunk.wire->name.str().find('$') != std::string::npos)
|
if (chunk.wire->name.str().find('$') != std::string::npos)
|
||||||
wire_name += stringf("$%d", autoidx++);
|
wire_name += stringf("$%d", autoidx++);
|
||||||
} while (current_module->wires_.count(wire_name) > 0);
|
} while (current_module->wire(RTLIL::IdString(wire_name)) != nullptr);
|
||||||
|
|
||||||
RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
|
RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
|
||||||
set_src_attr(wire, always.get());
|
set_src_attr(wire, always.get());
|
||||||
@@ -1629,10 +1629,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||||||
|
|
||||||
log_assert(id2ast != nullptr);
|
log_assert(id2ast != nullptr);
|
||||||
|
|
||||||
if (id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
|
if (id2ast->type == AST_AUTOWIRE && current_module->wire(RTLIL::IdString(str)) == nullptr) {
|
||||||
RTLIL::Wire *wire = current_module->addWire(str);
|
RTLIL::Wire *wire = current_module->addWire(str);
|
||||||
set_src_attr(wire, this);
|
set_src_attr(wire, this);
|
||||||
wire->name = str;
|
|
||||||
|
|
||||||
// If we are currently processing a bind directive which wires up
|
// If we are currently processing a bind directive which wires up
|
||||||
// signals or parameters explicitly, rather than with .*, then
|
// signals or parameters explicitly, rather than with .*, then
|
||||||
@@ -1652,7 +1651,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||||||
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
||||||
goto use_const_chunk;
|
goto use_const_chunk;
|
||||||
}
|
}
|
||||||
else if ((id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
|
else if ((id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wire(RTLIL::IdString(str)) != nullptr) {
|
||||||
RTLIL::Wire *current_wire = current_module->wire(str);
|
RTLIL::Wire *current_wire = current_module->wire(str);
|
||||||
if (current_wire->get_bool_attribute(ID::is_interface))
|
if (current_wire->get_bool_attribute(ID::is_interface))
|
||||||
is_interface = true;
|
is_interface = true;
|
||||||
@@ -1682,7 +1681,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||||||
return dummy_wire;
|
return dummy_wire;
|
||||||
}
|
}
|
||||||
|
|
||||||
wire = current_module->wires_[str];
|
wire = current_module->wire(RTLIL::IdString(str));
|
||||||
chunk.wire = wire;
|
chunk.wire = wire;
|
||||||
chunk.width = wire->width;
|
chunk.width = wire->width;
|
||||||
chunk.offset = 0;
|
chunk.offset = 0;
|
||||||
|
|||||||
@@ -47,11 +47,12 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
|
|||||||
return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1;
|
return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||||
|
|
||||||
std::string id = RTLIL::escape_id(std::string(expr, id_len));
|
std::string id = RTLIL::escape_id(std::string(expr, id_len));
|
||||||
if (!module->wires_.count(id))
|
RTLIL::Wire *w = module->wire(RTLIL::IdString(id));
|
||||||
|
if (!w)
|
||||||
log_error("Can't resolve wire name %s in %s.\n", RTLIL::unescape_id(id), module);
|
log_error("Can't resolve wire name %s in %s.\n", RTLIL::unescape_id(id), module);
|
||||||
|
|
||||||
expr += id_len;
|
expr += id_len;
|
||||||
return module->wires_.at(id);
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack, token_t next_token)
|
static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack, token_t next_token)
|
||||||
@@ -728,7 +729,7 @@ struct LibertyFrontend : public Frontend {
|
|||||||
if (flag_lib && dir->value == "internal")
|
if (flag_lib && dir->value == "internal")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
RTLIL::Wire *wire = module->wires_.at(RTLIL::escape_id(node->args.at(0)));
|
RTLIL::Wire *wire = module->wire(RTLIL::IdString(RTLIL::escape_id(node->args.at(0))));
|
||||||
log_assert(wire);
|
log_assert(wire);
|
||||||
|
|
||||||
const LibertyAst *capacitance = node->find("capacitance");
|
const LibertyAst *capacitance = node->find("capacitance");
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ struct RTLILFrontendWorker {
|
|||||||
std::vector<RTLIL::CaseRule*> case_stack;
|
std::vector<RTLIL::CaseRule*> case_stack;
|
||||||
|
|
||||||
// Remap from file-local twine ids (as they appear in the `twines` block
|
// Remap from file-local twine ids (as they appear in the `twines` block
|
||||||
// and on cell/wire src attrs) to ids in design->src_twines. Filled by
|
// and on cell/wire src attrs) to ids in design->twines. Filled by
|
||||||
// parse_twines; consumed by parse_attribute. Parser-side ids retained
|
// parse_twines; consumed by parse_attribute. Parser-side ids retained
|
||||||
// during parse_twines are tracked here so they can be released at
|
// during parse_twines are tracked here so they can be released at
|
||||||
// end-of-parse — only the cell/wire references should survive.
|
// end-of-parse — only the cell/wire references should survive.
|
||||||
dict<Twine::Id, Twine::Id> twine_remap;
|
dict<size_t, Twine::Id> twine_remap;
|
||||||
std::vector<Twine::Id> twine_parser_holds;
|
std::vector<Twine::Id> twine_parser_holds;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@@ -171,7 +171,7 @@ struct RTLILFrontendWorker {
|
|||||||
error("Expected EOL, got `%s'.", error_token());
|
error("Expected EOL, got `%s'.", error_token());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RTLIL::IdString> try_parse_id()
|
std::optional<std::string> try_parse_id()
|
||||||
{
|
{
|
||||||
char ch = line[0];
|
char ch = line[0];
|
||||||
if (ch != '\\' && ch != '$')
|
if (ch != '\\' && ch != '$')
|
||||||
@@ -183,15 +183,15 @@ struct RTLILFrontendWorker {
|
|||||||
break;
|
break;
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
IdString result(line.substr(0, idx));
|
std::string result(line.substr(0, idx));
|
||||||
line = line.substr(idx);
|
line = line.substr(idx);
|
||||||
consume_whitespace_and_comments();
|
consume_whitespace_and_comments();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::IdString parse_id()
|
std::string parse_id()
|
||||||
{
|
{
|
||||||
std::optional<RTLIL::IdString> id = try_parse_id();
|
std::optional<std::string> id = try_parse_id();
|
||||||
if (!id.has_value())
|
if (!id.has_value())
|
||||||
error("Expected ID, got `%s'.", error_token());
|
error("Expected ID, got `%s'.", error_token());
|
||||||
return std::move(*id);
|
return std::move(*id);
|
||||||
@@ -423,7 +423,7 @@ struct RTLILFrontendWorker {
|
|||||||
|
|
||||||
void parse_module()
|
void parse_module()
|
||||||
{
|
{
|
||||||
RTLIL::IdString module_name = parse_id();
|
Twine::Id module_name = design->twines.lookup(parse_id());
|
||||||
expect_eol();
|
expect_eol();
|
||||||
|
|
||||||
bool delete_current_module = false;
|
bool delete_current_module = false;
|
||||||
@@ -445,7 +445,7 @@ struct RTLILFrontendWorker {
|
|||||||
|
|
||||||
current_module = new RTLIL::Module;
|
current_module = new RTLIL::Module;
|
||||||
current_module->design = design;
|
current_module->design = design;
|
||||||
current_module->name = std::move(module_name);
|
current_module->meta_->name_id = module_name;
|
||||||
if (delete_current_module) {
|
if (delete_current_module) {
|
||||||
// Module is about to be discarded — drop its src attribute
|
// Module is about to be discarded — drop its src attribute
|
||||||
// rather than push it into a pool we'll never reach.
|
// rather than push it into a pool we'll never reach.
|
||||||
@@ -515,15 +515,16 @@ struct RTLILFrontendWorker {
|
|||||||
// is wrong and silently interning it would hide that.
|
// is wrong and silently interning it would hide that.
|
||||||
if (id == RTLIL::ID::src && (c.flags & RTLIL::CONST_FLAG_STRING)) {
|
if (id == RTLIL::ID::src && (c.flags & RTLIL::CONST_FLAG_STRING)) {
|
||||||
std::string raw = c.decode_string();
|
std::string raw = c.decode_string();
|
||||||
Twine::Id file_id = TwinePool::parse_ref(raw);
|
// TODO error handling
|
||||||
if (file_id != Twine::Null) {
|
auto file_id = design->twines.parse_ref(raw);
|
||||||
|
if (file_id) {
|
||||||
// Translate the file-local twine id to the destination
|
// Translate the file-local twine id to the destination
|
||||||
// design's pool id via twine_remap. If the file had no
|
// design's pool id via twine_remap. If the file had no
|
||||||
// `twines` block (legacy) the remap is empty — accept the
|
// `twines` block (legacy) the remap is empty — accept the
|
||||||
// ref verbatim and let downstream code intern it.
|
// ref verbatim and let downstream code intern it.
|
||||||
auto it = twine_remap.find(file_id);
|
auto it = twine_remap.find(*file_id);
|
||||||
if (it != twine_remap.end())
|
if (it != twine_remap.end())
|
||||||
c = RTLIL::Const(TwinePool::format_ref(it->second));
|
c = RTLIL::Const(design->twines.format_ref(it->second));
|
||||||
} else if (raw.find('|') != std::string::npos) {
|
} else if (raw.find('|') != std::string::npos) {
|
||||||
log_warning("line %d: src attribute %s contains '|' separators. "
|
log_warning("line %d: src attribute %s contains '|' separators. "
|
||||||
"That convention is Yosys-internal; the producing tool "
|
"That convention is Yosys-internal; the producing tool "
|
||||||
@@ -538,61 +539,47 @@ struct RTLILFrontendWorker {
|
|||||||
|
|
||||||
// Parses a `twines` ... `end` block. Builds twine_remap so subsequent
|
// Parses a `twines` ... `end` block. Builds twine_remap so subsequent
|
||||||
// cell/wire src "@N" references (which use file-local ids) translate
|
// cell/wire src "@N" references (which use file-local ids) translate
|
||||||
// to ids in design->src_twines. The destination pool may already be
|
// to ids in design->twines. The destination pool may already be
|
||||||
// non-empty (multi-file load) — interned/concated nodes are dedup'd
|
// non-empty (multi-file load) — interned/concated nodes are dedup'd
|
||||||
// against the existing pool by the pool itself. Each parser-side
|
// against the existing pool by the pool itself. Each parser-side
|
||||||
// retain is tracked in twine_parser_holds and released at end-of-parse
|
// retain is tracked in twine_parser_holds and released at end-of-parse
|
||||||
// so only cell/wire references survive.
|
// so only cell/wire references survive.
|
||||||
void parse_twines()
|
void parse_twines()
|
||||||
{
|
{
|
||||||
|
TwinePoolExtender extender(design->twines, design->twines.size());
|
||||||
expect_eol();
|
expect_eol();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (try_parse_keyword("end"))
|
if (try_parse_keyword("end"))
|
||||||
break;
|
break;
|
||||||
if (try_parse_keyword("leaf")) {
|
if (try_parse_keyword("leaf")) {
|
||||||
int file_id = static_cast<int>(parse_integer());
|
size_t file_id = parse_integer();
|
||||||
std::string text = parse_string();
|
std::string text = parse_string();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
Twine::Id local_id = design->src_twines.intern(text);
|
extender.extend_leaf(text, file_id);
|
||||||
twine_parser_holds.push_back(local_id);
|
|
||||||
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (try_parse_keyword("suffix")) {
|
if (try_parse_keyword("suffix")) {
|
||||||
int file_id = static_cast<int>(parse_integer());
|
size_t file_id = parse_integer();
|
||||||
Twine::Id file_parent = static_cast<Twine::Id>(parse_integer());
|
size_t file_parent = parse_integer();
|
||||||
std::string tail = parse_string();
|
std::string tail = parse_string();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
auto it = twine_remap.find(file_parent);
|
extender.extend_suffix(file_parent, tail, file_id);
|
||||||
if (it == twine_remap.end())
|
|
||||||
error("twines: suffix %d references undefined parent %u.",
|
|
||||||
file_id, file_parent);
|
|
||||||
Twine::Id local_id = design->src_twines.intern_suffix(it->second, tail);
|
|
||||||
twine_parser_holds.push_back(local_id);
|
|
||||||
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (try_parse_keyword("concat")) {
|
if (try_parse_keyword("concat")) {
|
||||||
int file_id = static_cast<int>(parse_integer());
|
size_t file_id = parse_integer();
|
||||||
std::vector<Twine::Id> children;
|
std::vector<size_t> children;
|
||||||
while (!try_parse_eol()) {
|
while (!try_parse_eol()) {
|
||||||
Twine::Id file_child = static_cast<Twine::Id>(parse_integer());
|
children.push_back(parse_integer());
|
||||||
auto it = twine_remap.find(file_child);
|
|
||||||
if (it == twine_remap.end())
|
|
||||||
error("twines: concat %d references undefined leaf/concat %u.",
|
|
||||||
file_id, file_child);
|
|
||||||
children.push_back(it->second);
|
|
||||||
}
|
}
|
||||||
Twine::Id local_id = design->src_twines.concat(
|
extender.extend_concat(children, file_id);
|
||||||
std::span<const Twine::Id>{children});
|
|
||||||
twine_parser_holds.push_back(local_id);
|
|
||||||
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
|
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
|
||||||
error_token());
|
error_token());
|
||||||
}
|
}
|
||||||
expect_eol();
|
expect_eol();
|
||||||
|
extender.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the per-file parser refs gathered during parse_twines. Call
|
// Release the per-file parser refs gathered during parse_twines. Call
|
||||||
@@ -601,7 +588,7 @@ struct RTLILFrontendWorker {
|
|||||||
void release_twine_parser_holds()
|
void release_twine_parser_holds()
|
||||||
{
|
{
|
||||||
for (Twine::Id id : twine_parser_holds)
|
for (Twine::Id id : twine_parser_holds)
|
||||||
design->src_twines.release(id);
|
design->twines.release(id);
|
||||||
twine_parser_holds.clear();
|
twine_parser_holds.clear();
|
||||||
twine_remap.clear();
|
twine_remap.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -46,8 +46,7 @@ void manufacture_info(InputType flop, OutputType& info, FfInitVals *initvals) {
|
|||||||
// id verbatim into the new cell — no flatten/re-intern, no
|
// id verbatim into the new cell — no flatten/re-intern, no
|
||||||
// pipe-leaf risk for cells whose src is a Concat.
|
// pipe-leaf risk for cells whose src is a Concat.
|
||||||
if (cell->src_id() != Twine::Null && cell->module && cell->module->design)
|
if (cell->src_id() != Twine::Null && cell->module && cell->module->design)
|
||||||
info.src_twine = OwnedTwine(&cell->module->design->src_twines,
|
info.src_twine = cell->src_id();
|
||||||
cell->src_id());
|
|
||||||
if (initvals)
|
if (initvals)
|
||||||
info.val_init = (*initvals)(info.sig_q);
|
info.val_init = (*initvals)(info.sig_q);
|
||||||
}
|
}
|
||||||
@@ -768,7 +767,7 @@ Cell *FfData::emit() {
|
|||||||
// FfData is destroyed; set_src_id retains on the cell's behalf.
|
// FfData is destroyed; set_src_id retains on the cell's behalf.
|
||||||
cell->attributes = attributes;
|
cell->attributes = attributes;
|
||||||
if (!src_twine.empty() && cell->module && cell->module->design) {
|
if (!src_twine.empty() && cell->module && cell->module->design) {
|
||||||
TwinePool *dst_pool = &cell->module->design->src_twines;
|
TwinePool *dst_pool = &cell->module->design->twines;
|
||||||
if (src_twine.pool() == dst_pool) {
|
if (src_twine.pool() == dst_pool) {
|
||||||
cell->set_src_id(src_twine.id());
|
cell->set_src_id(src_twine.id());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -173,7 +173,7 @@ struct FfData : FfTypeData {
|
|||||||
// Stashed src across construction → emit. Refcount-managed so the
|
// Stashed src across construction → emit. Refcount-managed so the
|
||||||
// source cell's pool slot survives if the cell itself is removed
|
// source cell's pool slot survives if the cell itself is removed
|
||||||
// before emit() runs. Empty when the source cell had no src.
|
// before emit() runs. Empty when the source cell had no src.
|
||||||
OwnedTwine src_twine;
|
Twine::Id src_twine;
|
||||||
|
|
||||||
FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
|
FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
|
||||||
width = 0;
|
width = 0;
|
||||||
|
|||||||
+5
-6
@@ -894,10 +894,10 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
|||||||
// below adopts the same slot as Mem itself (via set_src_attribute's
|
// below adopts the same slot as Mem itself (via set_src_attribute's
|
||||||
// "@N" parse_ref path), and there's no flatten → re-intern → pipe-
|
// "@N" parse_ref path), and there's no flatten → re-intern → pipe-
|
||||||
// leaf round-trip on cells whose src is a Concat node.
|
// leaf round-trip on cells whose src is a Concat node.
|
||||||
TwinePool *src_pool = (module && module->design) ? &module->design->src_twines : nullptr;
|
log_assert(module && module->design);
|
||||||
Twine::Id mem_src_id = (module && module->design) ? module->design->obj_src_id(this) : Twine::Null;
|
Twine::Id mem_src_id = module->design->obj_src_id(this);
|
||||||
std::string mem_src = (src_pool && mem_src_id != Twine::Null) ?
|
std::string mem_src = (mem_src_id != Twine::Null) ?
|
||||||
TwinePool::format_ref(mem_src_id) : std::string();
|
module->design->twines.format_ref(mem_src_id) : std::string();
|
||||||
|
|
||||||
Cell *c;
|
Cell *c;
|
||||||
|
|
||||||
@@ -1005,8 +1005,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
|||||||
FfData ff(module, initvals, name);
|
FfData ff(module, initvals, name);
|
||||||
// Carry mem's src into the ff via the OwnedTwine handle — same
|
// Carry mem's src into the ff via the OwnedTwine handle — same
|
||||||
// pool, direct id retain. emit() transfers verbatim.
|
// pool, direct id retain. emit() transfers verbatim.
|
||||||
if (src_pool && mem_src_id != Twine::Null)
|
ff.src_twine = mem_src_id;
|
||||||
ff.src_twine = OwnedTwine(src_pool, mem_src_id);
|
|
||||||
ff.width = GetSize(port.data);
|
ff.width = GetSize(port.data);
|
||||||
ff.has_clk = true;
|
ff.has_clk = true;
|
||||||
ff.sig_clk = port.clk;
|
ff.sig_clk = port.clk;
|
||||||
|
|||||||
+480
-331
File diff suppressed because it is too large
Load Diff
+241
-79
@@ -130,6 +130,8 @@ namespace RTLIL
|
|||||||
struct SrcAttr;
|
struct SrcAttr;
|
||||||
struct ObjMeta;
|
struct ObjMeta;
|
||||||
struct ModuleNameMasq;
|
struct ModuleNameMasq;
|
||||||
|
struct WireNameMasq;
|
||||||
|
struct CellNameMasq;
|
||||||
|
|
||||||
typedef std::pair<SigSpec, SigSpec> SigSig;
|
typedef std::pair<SigSpec, SigSpec> SigSig;
|
||||||
struct PortBit;
|
struct PortBit;
|
||||||
@@ -603,6 +605,14 @@ public:
|
|||||||
if (global_id_index_.empty())
|
if (global_id_index_.empty())
|
||||||
prepopulate();
|
prepopulate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Thread-safe read-only pool lookup for use while Multithreading::active().
|
||||||
|
// global_id_index_ is stable (no writes) during parallel passes, so
|
||||||
|
// concurrent find() calls are safe. Returns empty IdString if not found.
|
||||||
|
static IdString lookup_threadsafe(std::string_view p) {
|
||||||
|
auto it = global_id_index_.find(p);
|
||||||
|
return from_index(it != global_id_index_.end() ? it->second : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RTLIL::OwningIdString : public RTLIL::IdString {
|
struct RTLIL::OwningIdString : public RTLIL::IdString {
|
||||||
@@ -910,15 +920,15 @@ namespace RTLIL {
|
|||||||
// This iterator-range-pair is used for Design::modules(), Module::wires() and Module::cells().
|
// This iterator-range-pair is used for Design::modules(), Module::wires() and Module::cells().
|
||||||
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
|
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename Key = RTLIL::IdString>
|
||||||
struct ObjIterator {
|
struct ObjIterator {
|
||||||
using iterator_category = std::forward_iterator_tag;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
using pointer = T*;
|
using pointer = T*;
|
||||||
using reference = T&;
|
using reference = T&;
|
||||||
typename dict<RTLIL::IdString, T>::iterator it;
|
typename dict<Key, T>::iterator it;
|
||||||
dict<RTLIL::IdString, T> *list_p;
|
dict<Key, T> *list_p;
|
||||||
int *refcount_p;
|
int *refcount_p;
|
||||||
|
|
||||||
ObjIterator() : list_p(nullptr), refcount_p(nullptr) {
|
ObjIterator() : list_p(nullptr), refcount_p(nullptr) {
|
||||||
@@ -934,7 +944,7 @@ namespace RTLIL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjIterator(const RTLIL::ObjIterator<T> &other) {
|
ObjIterator(const RTLIL::ObjIterator<T, Key> &other) {
|
||||||
it = other.it;
|
it = other.it;
|
||||||
list_p = other.list_p;
|
list_p = other.list_p;
|
||||||
refcount_p = other.refcount_p;
|
refcount_p = other.refcount_p;
|
||||||
@@ -942,7 +952,7 @@ namespace RTLIL {
|
|||||||
(*refcount_p)++;
|
(*refcount_p)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjIterator &operator=(const RTLIL::ObjIterator<T> &other) {
|
ObjIterator &operator=(const RTLIL::ObjIterator<T, Key> &other) {
|
||||||
if (refcount_p)
|
if (refcount_p)
|
||||||
(*refcount_p)--;
|
(*refcount_p)--;
|
||||||
it = other.it;
|
it = other.it;
|
||||||
@@ -963,18 +973,18 @@ namespace RTLIL {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const RTLIL::ObjIterator<T> &other) const {
|
inline bool operator!=(const RTLIL::ObjIterator<T, Key> &other) const {
|
||||||
if (list_p == nullptr || other.list_p == nullptr)
|
if (list_p == nullptr || other.list_p == nullptr)
|
||||||
return list_p != other.list_p;
|
return list_p != other.list_p;
|
||||||
return it != other.it;
|
return it != other.it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool operator==(const RTLIL::ObjIterator<T> &other) const {
|
inline bool operator==(const RTLIL::ObjIterator<T, Key> &other) const {
|
||||||
return !(*this != other);
|
return !(*this != other);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ObjIterator<T>& operator++() {
|
inline ObjIterator<T, Key>& operator++() {
|
||||||
log_assert(list_p != nullptr);
|
log_assert(list_p != nullptr);
|
||||||
if (++it == list_p->end()) {
|
if (++it == list_p->end()) {
|
||||||
(*refcount_p)--;
|
(*refcount_p)--;
|
||||||
@@ -984,7 +994,7 @@ namespace RTLIL {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ObjIterator<T>& operator+=(int amt) {
|
inline ObjIterator<T, Key>& operator+=(int amt) {
|
||||||
log_assert(list_p != nullptr);
|
log_assert(list_p != nullptr);
|
||||||
it += amt;
|
it += amt;
|
||||||
if (it == list_p->end()) {
|
if (it == list_p->end()) {
|
||||||
@@ -995,9 +1005,9 @@ namespace RTLIL {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ObjIterator<T> operator+(int amt) {
|
inline ObjIterator<T, Key> operator+(int amt) {
|
||||||
log_assert(list_p != nullptr);
|
log_assert(list_p != nullptr);
|
||||||
ObjIterator<T> new_obj(*this);
|
ObjIterator<T, Key> new_obj(*this);
|
||||||
new_obj.it += amt;
|
new_obj.it += amt;
|
||||||
if (new_obj.it == list_p->end()) {
|
if (new_obj.it == list_p->end()) {
|
||||||
(*(new_obj.refcount_p))--;
|
(*(new_obj.refcount_p))--;
|
||||||
@@ -1007,22 +1017,22 @@ namespace RTLIL {
|
|||||||
return new_obj;
|
return new_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ObjIterator<T> operator++(int) {
|
inline const ObjIterator<T, Key> operator++(int) {
|
||||||
ObjIterator<T> result(*this);
|
ObjIterator<T, Key> result(*this);
|
||||||
++(*this);
|
++(*this);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename Key = RTLIL::IdString>
|
||||||
struct ObjRange
|
struct ObjRange
|
||||||
{
|
{
|
||||||
dict<RTLIL::IdString, T> *list_p;
|
dict<Key, T> *list_p;
|
||||||
int *refcount_p;
|
int *refcount_p;
|
||||||
|
|
||||||
ObjRange(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) { }
|
ObjRange(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) { }
|
||||||
RTLIL::ObjIterator<T> begin() { return RTLIL::ObjIterator<T>(list_p, refcount_p); }
|
RTLIL::ObjIterator<T, Key> begin() { return RTLIL::ObjIterator<T, Key>(list_p, refcount_p); }
|
||||||
RTLIL::ObjIterator<T> end() { return RTLIL::ObjIterator<T>(); }
|
RTLIL::ObjIterator<T, Key> end() { return RTLIL::ObjIterator<T, Key>(); }
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return list_p->size();
|
return list_p->size();
|
||||||
@@ -1297,7 +1307,8 @@ public:
|
|||||||
struct RTLIL::ObjMeta
|
struct RTLIL::ObjMeta
|
||||||
{
|
{
|
||||||
Twine::Id src = Twine::Null;
|
Twine::Id src = Twine::Null;
|
||||||
RTLIL::IdString name;
|
// RTLIL::IdString name; // used by Module names
|
||||||
|
Twine::Id name_id = Twine::Null; // used by Wire/Cell names (per-Design twines)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RTLIL::AttrObject
|
struct RTLIL::AttrObject
|
||||||
@@ -1322,10 +1333,10 @@ struct RTLIL::AttrObject
|
|||||||
void set_string_attribute(RTLIL::IdString id, string value);
|
void set_string_attribute(RTLIL::IdString id, string value);
|
||||||
string get_string_attribute(RTLIL::IdString id) const;
|
string get_string_attribute(RTLIL::IdString id) const;
|
||||||
|
|
||||||
static std::string strpool_attribute_to_str(const pool<string> &data);
|
// static std::string strpool_attribute_to_str(const pool<string> &data);
|
||||||
void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
|
// void set_strpool_attribute(IdString id, const pool<string> &data);
|
||||||
void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
|
// void add_strpool_attribute(IdString id, const pool<string> &data);
|
||||||
pool<string> get_strpool_attribute(RTLIL::IdString id) const;
|
// pool<string> get_strpool_attribute(RTLIL::IdString id) const;
|
||||||
|
|
||||||
void set_hdlname_attribute(const vector<string> &hierarchy);
|
void set_hdlname_attribute(const vector<string> &hierarchy);
|
||||||
vector<string> get_hdlname_attribute() const;
|
vector<string> get_hdlname_attribute() const;
|
||||||
@@ -1339,6 +1350,88 @@ struct RTLIL::NamedObject : public RTLIL::AttrObject
|
|||||||
RTLIL::IdString name;
|
RTLIL::IdString name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Read-only masquerade for Wire::name. Reads materialise the Twine::Id in
|
||||||
|
// the owning Design's twines pool into a temporary IdString. Writes are
|
||||||
|
// intentionally unsupported — use Module::rename(wire, new_name) instead.
|
||||||
|
// Defined before Wire so it can be used as a [[no_unique_address]] member.
|
||||||
|
struct RTLIL::WireNameMasq {
|
||||||
|
WireNameMasq() = default;
|
||||||
|
WireNameMasq(const WireNameMasq &) = delete;
|
||||||
|
WireNameMasq(WireNameMasq &&) = delete;
|
||||||
|
WireNameMasq &operator=(const WireNameMasq &) = delete;
|
||||||
|
WireNameMasq &operator=(WireNameMasq &&) = delete;
|
||||||
|
// Materialise → IdString. Slow path; intended for plugin code.
|
||||||
|
operator RTLIL::IdString() const;
|
||||||
|
bool empty() const { return RTLIL::IdString(*this).empty(); }
|
||||||
|
std::string str() const { return RTLIL::IdString(*this).str(); }
|
||||||
|
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
|
||||||
|
bool isPublic() const { return RTLIL::IdString(*this).isPublic(); }
|
||||||
|
std::string unescape() const { return RTLIL::IdString(*this).unescape(); }
|
||||||
|
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
|
||||||
|
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
|
||||||
|
template <typename... Ts> bool in(Ts &&...args) const {
|
||||||
|
return RTLIL::IdString(*this).in(std::forward<Ts>(args)...);
|
||||||
|
}
|
||||||
|
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
|
||||||
|
return RTLIL::IdString(*this).substr(pos, len);
|
||||||
|
}
|
||||||
|
size_t size() const { return RTLIL::IdString(*this).size(); }
|
||||||
|
bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); }
|
||||||
|
char operator[](int n) const { return RTLIL::IdString(*this).str()[n]; }
|
||||||
|
bool lt_by_name(RTLIL::IdString rhs) const { return RTLIL::IdString(*this).lt_by_name(rhs); }
|
||||||
|
bool lt_by_name(const WireNameMasq &rhs) const { return RTLIL::IdString(*this).lt_by_name(RTLIL::IdString(rhs)); }
|
||||||
|
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; }
|
||||||
|
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; }
|
||||||
|
bool operator<(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; }
|
||||||
|
bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; }
|
||||||
|
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; }
|
||||||
|
bool operator==(const WireNameMasq &rhs) const { return RTLIL::IdString(*this) == RTLIL::IdString(rhs); }
|
||||||
|
bool operator!=(const WireNameMasq &rhs) const { return RTLIL::IdString(*this) != RTLIL::IdString(rhs); }
|
||||||
|
bool operator<(const WireNameMasq &rhs) const { return RTLIL::IdString(*this) < RTLIL::IdString(rhs); }
|
||||||
|
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(*this).hash_into(h); }
|
||||||
|
};
|
||||||
|
inline bool operator==(RTLIL::IdString lhs, const RTLIL::WireNameMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
|
||||||
|
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::WireNameMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
|
||||||
|
|
||||||
|
// Read-only masquerade for Cell::name. Same contract as WireNameMasq.
|
||||||
|
struct RTLIL::CellNameMasq {
|
||||||
|
CellNameMasq() = default;
|
||||||
|
CellNameMasq(const CellNameMasq &) = delete;
|
||||||
|
CellNameMasq(CellNameMasq &&) = delete;
|
||||||
|
CellNameMasq &operator=(const CellNameMasq &) = delete;
|
||||||
|
CellNameMasq &operator=(CellNameMasq &&) = delete;
|
||||||
|
operator RTLIL::IdString() const;
|
||||||
|
bool empty() const { return RTLIL::IdString(*this).empty(); }
|
||||||
|
std::string str() const { return RTLIL::IdString(*this).str(); }
|
||||||
|
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
|
||||||
|
bool isPublic() const { return RTLIL::IdString(*this).isPublic(); }
|
||||||
|
std::string unescape() const { return RTLIL::IdString(*this).unescape(); }
|
||||||
|
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
|
||||||
|
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
|
||||||
|
template <typename... Ts> bool in(Ts &&...args) const {
|
||||||
|
return RTLIL::IdString(*this).in(std::forward<Ts>(args)...);
|
||||||
|
}
|
||||||
|
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
|
||||||
|
return RTLIL::IdString(*this).substr(pos, len);
|
||||||
|
}
|
||||||
|
size_t size() const { return RTLIL::IdString(*this).size(); }
|
||||||
|
bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); }
|
||||||
|
char operator[](int n) const { return RTLIL::IdString(*this).str()[n]; }
|
||||||
|
bool lt_by_name(RTLIL::IdString rhs) const { return RTLIL::IdString(*this).lt_by_name(rhs); }
|
||||||
|
bool lt_by_name(const CellNameMasq &rhs) const { return RTLIL::IdString(*this).lt_by_name(RTLIL::IdString(rhs)); }
|
||||||
|
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; }
|
||||||
|
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; }
|
||||||
|
bool operator<(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; }
|
||||||
|
bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; }
|
||||||
|
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; }
|
||||||
|
bool operator==(const CellNameMasq &rhs) const { return RTLIL::IdString(*this) == RTLIL::IdString(rhs); }
|
||||||
|
bool operator!=(const CellNameMasq &rhs) const { return RTLIL::IdString(*this) != RTLIL::IdString(rhs); }
|
||||||
|
bool operator<(const CellNameMasq &rhs) const { return RTLIL::IdString(*this) < RTLIL::IdString(rhs); }
|
||||||
|
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(*this).hash_into(h); }
|
||||||
|
};
|
||||||
|
inline bool operator==(RTLIL::IdString lhs, const RTLIL::CellNameMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
|
||||||
|
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::CellNameMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
|
||||||
|
|
||||||
struct RTLIL::SigChunk
|
struct RTLIL::SigChunk
|
||||||
{
|
{
|
||||||
RTLIL::Wire *wire;
|
RTLIL::Wire *wire;
|
||||||
@@ -1823,8 +1916,8 @@ struct RTLIL::Selection
|
|||||||
bool complete_selection;
|
bool complete_selection;
|
||||||
// selection covers full design, not including boxed modules
|
// selection covers full design, not including boxed modules
|
||||||
bool full_selection;
|
bool full_selection;
|
||||||
pool<RTLIL::IdString> selected_modules;
|
pool<Twine::Id> selected_modules;
|
||||||
dict<RTLIL::IdString, pool<RTLIL::IdString>> selected_members;
|
dict<Twine::Id, pool<Twine::Id>> selected_members;
|
||||||
RTLIL::Design *current_design;
|
RTLIL::Design *current_design;
|
||||||
|
|
||||||
// create a new selection
|
// create a new selection
|
||||||
@@ -1840,18 +1933,18 @@ struct RTLIL::Selection
|
|||||||
|
|
||||||
// checks if the given module exists in the current design and is a
|
// checks if the given module exists in the current design and is a
|
||||||
// boxed module, warning the user if the current design is not set
|
// boxed module, warning the user if the current design is not set
|
||||||
bool boxed_module(RTLIL::IdString mod_name) const;
|
bool boxed_module(Twine::Id mod_name) const;
|
||||||
|
|
||||||
// checks if the given module is included in this selection
|
// checks if the given module is included in this selection
|
||||||
bool selected_module(RTLIL::IdString mod_name) const;
|
bool selected_module(Twine::Id mod_name) const;
|
||||||
|
|
||||||
// checks if the given module is wholly included in this selection,
|
// checks if the given module is wholly included in this selection,
|
||||||
// i.e. not partially selected
|
// i.e. not partially selected
|
||||||
bool selected_whole_module(RTLIL::IdString mod_name) const;
|
bool selected_whole_module(Twine::Id mod_name) const;
|
||||||
|
|
||||||
// checks if the given member from the given module is included in this
|
// checks if the given member from the given module is included in this
|
||||||
// selection
|
// selection
|
||||||
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const;
|
bool selected_member(Twine::Id mod_name, Twine::Id memb_name) const;
|
||||||
|
|
||||||
// optimizes this selection for the given design by:
|
// optimizes this selection for the given design by:
|
||||||
// - removing non-existent modules and members, any boxed modules and
|
// - removing non-existent modules and members, any boxed modules and
|
||||||
@@ -1872,9 +1965,10 @@ struct RTLIL::Selection
|
|||||||
|
|
||||||
// add whole module to this selection
|
// add whole module to this selection
|
||||||
template<typename T1> void select(T1 *module) {
|
template<typename T1> void select(T1 *module) {
|
||||||
if (!selects_all() && selected_modules.count(module->name) == 0) {
|
if (!selects_all() && selected_modules.count(module->meta_->name_id) == 0) {
|
||||||
selected_modules.insert(module->name);
|
Twine::Id name = module->meta_->name_id;
|
||||||
selected_members.erase(module->name);
|
selected_modules.insert(name);
|
||||||
|
selected_members.erase(name);
|
||||||
if (module->get_blackbox_attribute())
|
if (module->get_blackbox_attribute())
|
||||||
selects_boxes = true;
|
selects_boxes = true;
|
||||||
}
|
}
|
||||||
@@ -1944,12 +2038,10 @@ struct RTLIL::Design
|
|||||||
void sigNormalize(bool enable=true);
|
void sigNormalize(bool enable=true);
|
||||||
|
|
||||||
int refcount_modules_;
|
int refcount_modules_;
|
||||||
dict<RTLIL::IdString, RTLIL::Module*> modules_;
|
dict<Twine::Id, RTLIL::Module*> modules_;
|
||||||
std::vector<RTLIL::Binding*> bindings_;
|
std::vector<RTLIL::Binding*> bindings_;
|
||||||
|
|
||||||
// Interns src-attribute strings and concats thereof. Cells reach this
|
TwinePool twines;
|
||||||
// via cell->module->design->src_twines.
|
|
||||||
TwinePool src_twines;
|
|
||||||
|
|
||||||
// Per-Design ObjMeta pool: stable storage (deque) + LIFO freelist of
|
// Per-Design ObjMeta pool: stable storage (deque) + LIFO freelist of
|
||||||
// returned slots. AttrObject::meta_ points into obj_meta_storage_.
|
// returned slots. AttrObject::meta_ points into obj_meta_storage_.
|
||||||
@@ -1965,15 +2057,22 @@ struct RTLIL::Design
|
|||||||
void obj_set_src_id(RTLIL::AttrObject *obj, Twine::Id id);
|
void obj_set_src_id(RTLIL::AttrObject *obj, Twine::Id id);
|
||||||
void obj_release_src(RTLIL::AttrObject *obj);
|
void obj_release_src(RTLIL::AttrObject *obj);
|
||||||
|
|
||||||
RTLIL::IdString obj_name(const RTLIL::AttrObject *obj) const {
|
std::string obj_name(const RTLIL::AttrObject *obj) const {
|
||||||
return (obj->meta_ ? obj->meta_->name : RTLIL::IdString());
|
return (obj->meta_ ? twines.flat_string(obj->meta_->name_id) : std::string());
|
||||||
}
|
}
|
||||||
void obj_set_name(RTLIL::AttrObject *obj, RTLIL::IdString name);
|
void obj_set_name(RTLIL::AttrObject *obj, RTLIL::IdString name);
|
||||||
void obj_release_name(RTLIL::AttrObject *obj);
|
void obj_release_name(RTLIL::AttrObject *obj);
|
||||||
|
|
||||||
|
// Wire/Cell names: stored as Twine::Id in twines.
|
||||||
|
Twine::Id obj_name_id(const RTLIL::AttrObject *obj) const {
|
||||||
|
return (obj->meta_ ? obj->meta_->name_id : Twine::Null);
|
||||||
|
}
|
||||||
|
void obj_set_name_id(RTLIL::AttrObject *obj, Twine::Id id);
|
||||||
|
void obj_release_name_id(RTLIL::AttrObject *obj);
|
||||||
|
|
||||||
// Replacements for the methods that used to live on AttrObject and
|
// Replacements for the methods that used to live on AttrObject and
|
||||||
// took an explicit TwinePool*. Same semantics; the pool resolves
|
// took an explicit TwinePool*. Same semantics; the pool resolves
|
||||||
// to this->src_twines internally.
|
// to this->twines internally.
|
||||||
void set_src_attribute(RTLIL::AttrObject *obj, const RTLIL::SrcAttr &src);
|
void set_src_attribute(RTLIL::AttrObject *obj, const RTLIL::SrcAttr &src);
|
||||||
std::string get_src_attribute(const RTLIL::AttrObject *obj) const;
|
std::string get_src_attribute(const RTLIL::AttrObject *obj) const;
|
||||||
void adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source);
|
void adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source);
|
||||||
@@ -1983,13 +2082,13 @@ struct RTLIL::Design
|
|||||||
|
|
||||||
// Resolve a stored src-attribute string to its flat path:line.col
|
// Resolve a stored src-attribute string to its flat path:line.col
|
||||||
// representation. If `raw` is a twine reference ("@N") returns
|
// representation. If `raw` is a twine reference ("@N") returns
|
||||||
// src_twines.flatten(N); otherwise returns `raw` unchanged. Backends
|
// twines.flatten(N); otherwise returns `raw` unchanged. Backends
|
||||||
// must call this whenever they emit src to a user-facing format.
|
// must call this whenever they emit src to a user-facing format.
|
||||||
std::string resolve_src(std::string_view raw) const {
|
std::string resolve_src(std::string_view raw) {
|
||||||
Twine::Id id = TwinePool::parse_ref(raw);
|
Twine* id = twines.get_ref(raw);
|
||||||
if (id == Twine::Null)
|
if (id == nullptr)
|
||||||
return std::string(raw);
|
return std::string(raw);
|
||||||
return src_twines.flatten(id);
|
return twines.flatten(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge `source`'s src attribute into `target`'s src attribute via the
|
// Merge `source`'s src attribute into `target`'s src attribute via the
|
||||||
@@ -2012,7 +2111,7 @@ struct RTLIL::Design
|
|||||||
pool<std::string> src_leaves(const RTLIL::AttrObject *obj) const;
|
pool<std::string> src_leaves(const RTLIL::AttrObject *obj) const;
|
||||||
|
|
||||||
// Walk the design, collect the set of "@N" ids actually referenced by
|
// Walk the design, collect the set of "@N" ids actually referenced by
|
||||||
// any AttrObject's src, then compact src_twines to contain only those
|
// any AttrObject's src, then compact twines to contain only those
|
||||||
// nodes plus their transitive leaf children, and rewrite every cell
|
// nodes plus their transitive leaf children, and rewrite every cell
|
||||||
// src attribute through the resulting old-id -> new-id remap.
|
// src attribute through the resulting old-id -> new-id remap.
|
||||||
// Intermediate concats produced by successive merges become unreferenced
|
// Intermediate concats produced by successive merges become unreferenced
|
||||||
@@ -2025,26 +2124,27 @@ struct RTLIL::Design
|
|||||||
|
|
||||||
std::vector<RTLIL::Selection> selection_stack;
|
std::vector<RTLIL::Selection> selection_stack;
|
||||||
dict<RTLIL::IdString, RTLIL::Selection> selection_vars;
|
dict<RTLIL::IdString, RTLIL::Selection> selection_vars;
|
||||||
std::string selected_active_module;
|
Twine::Id selected_active_module;
|
||||||
|
|
||||||
Design();
|
Design();
|
||||||
~Design();
|
~Design();
|
||||||
|
|
||||||
RTLIL::ObjRange<RTLIL::Module*> modules();
|
RTLIL::ObjRange<RTLIL::Module*, Twine::Id> modules();
|
||||||
RTLIL::Module *module(RTLIL::IdString name);
|
RTLIL::Module *module(IdString name);
|
||||||
const RTLIL::Module *module(RTLIL::IdString name) const;
|
RTLIL::Module *module(Twine::Id name);
|
||||||
|
const RTLIL::Module *module(Twine::Id name) const;
|
||||||
RTLIL::Module *top_module() const;
|
RTLIL::Module *top_module() const;
|
||||||
|
|
||||||
bool has(RTLIL::IdString id) const {
|
bool has(Twine::Id id) const {
|
||||||
return modules_.count(id) != 0;
|
return modules_.count(id) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(RTLIL::Module *module);
|
void add(RTLIL::Module *module);
|
||||||
void add(RTLIL::Binding *binding);
|
void add(RTLIL::Binding *binding);
|
||||||
|
|
||||||
RTLIL::Module *addModule(RTLIL::IdString name);
|
RTLIL::Module *addModule(Twine::Id name);
|
||||||
void remove(RTLIL::Module *module);
|
void remove(RTLIL::Module *module);
|
||||||
void rename(RTLIL::Module *module, RTLIL::IdString new_name);
|
void rename(RTLIL::Module *module, Twine::Id new_name);
|
||||||
|
|
||||||
void scratchpad_unset(const std::string &varname);
|
void scratchpad_unset(const std::string &varname);
|
||||||
|
|
||||||
@@ -2062,22 +2162,22 @@ struct RTLIL::Design
|
|||||||
void optimize();
|
void optimize();
|
||||||
|
|
||||||
// Wholesale-copy this design into `dst`. `dst` must be empty (no
|
// Wholesale-copy this design into `dst`. `dst` must be empty (no
|
||||||
// modules). Copies src_twines verbatim and clones each module
|
// modules). Copies twines verbatim and clones each module
|
||||||
// preserving src_id_ values directly — avoids the per-module
|
// preserving src_id_ values directly — avoids the per-module
|
||||||
// copy_from pool rebuild and yields byte-identical RTLIL output
|
// copy_from pool rebuild and yields byte-identical RTLIL output
|
||||||
// across design -push/-pop, -save/-load, etc.
|
// across design -push/-pop, -save/-load, etc.
|
||||||
void clone_into(RTLIL::Design *dst) const;
|
void clone_into(RTLIL::Design *dst) const;
|
||||||
|
|
||||||
// checks if the given module is included in the current selection
|
// checks if the given module is included in the current selection
|
||||||
bool selected_module(RTLIL::IdString mod_name) const;
|
bool selected_module(Twine::Id mod_name) const;
|
||||||
|
|
||||||
// checks if the given module is wholly included in the current
|
// checks if the given module is wholly included in the current
|
||||||
// selection, i.e. not partially selected
|
// selection, i.e. not partially selected
|
||||||
bool selected_whole_module(RTLIL::IdString mod_name) const;
|
bool selected_whole_module(Twine::Id mod_name) const;
|
||||||
|
|
||||||
// checks if the given member from the given module is included in the
|
// checks if the given member from the given module is included in the
|
||||||
// current selection
|
// current selection
|
||||||
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const;
|
bool selected_member(Twine::Id mod_name, Twine::Id memb_name) const;
|
||||||
|
|
||||||
// checks if the given module is included in the current selection
|
// checks if the given module is included in the current selection
|
||||||
bool selected_module(RTLIL::Module *mod) const;
|
bool selected_module(RTLIL::Module *mod) const;
|
||||||
@@ -2193,6 +2293,10 @@ private:
|
|||||||
friend struct RTLIL::Module;
|
friend struct RTLIL::Module;
|
||||||
friend struct RTLIL::Patch;
|
friend struct RTLIL::Patch;
|
||||||
public:
|
public:
|
||||||
|
// Shadows NamedObject::name. Reads materialise via twines; writes
|
||||||
|
// are a compile error — use Module::rename(wire, new_name) instead.
|
||||||
|
[[no_unique_address]] RTLIL::WireNameMasq name;
|
||||||
|
|
||||||
Hasher::hash_t hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
||||||
// use module->addWire() and module->remove() to create or destroy wires
|
// use module->addWire() and module->remove() to create or destroy wires
|
||||||
@@ -2300,6 +2404,10 @@ private:
|
|||||||
void signorm_index_add(RTLIL::IdString portname, const RTLIL::SigSpec &new_signal, bool is_input);
|
void signorm_index_add(RTLIL::IdString portname, const RTLIL::SigSpec &new_signal, bool is_input);
|
||||||
bool bufnorm_handle_setPort(RTLIL::IdString portname, RTLIL::SigSpec &signal, dict<RTLIL::IdString, RTLIL::SigSpec>::iterator conn_it);
|
bool bufnorm_handle_setPort(RTLIL::IdString portname, RTLIL::SigSpec &signal, dict<RTLIL::IdString, RTLIL::SigSpec>::iterator conn_it);
|
||||||
public:
|
public:
|
||||||
|
// Shadows NamedObject::name. Reads materialise via twines; writes
|
||||||
|
// are a compile error — use Module::rename(cell, new_name) instead.
|
||||||
|
[[no_unique_address]] RTLIL::CellNameMasq name;
|
||||||
|
|
||||||
Hasher::hash_t hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
||||||
|
|
||||||
@@ -2566,7 +2674,10 @@ inline Hasher RTLIL::SigBit::hash_into(Hasher h) const {
|
|||||||
inline Hasher RTLIL::SigBit::hash_top() const {
|
inline Hasher RTLIL::SigBit::hash_top() const {
|
||||||
Hasher h;
|
Hasher h;
|
||||||
if (wire) {
|
if (wire) {
|
||||||
h.force(hashlib::legacy::djb2_add(wire->name.index_, offset));
|
// Use the wire's name_id (Twine::Id) directly — avoids IdString materialisation.
|
||||||
|
Twine::Id name_id = wire->meta_ ? wire->meta_->name_id : Twine::Null;
|
||||||
|
h.eat(name_id);
|
||||||
|
h.eat(offset);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
h.force(data);
|
h.force(data);
|
||||||
@@ -2815,6 +2926,7 @@ struct RTLIL::ModuleNameMasq {
|
|||||||
ModuleNameMasq(const ModuleNameMasq&) = delete;
|
ModuleNameMasq(const ModuleNameMasq&) = delete;
|
||||||
ModuleNameMasq(ModuleNameMasq&&) = delete;
|
ModuleNameMasq(ModuleNameMasq&&) = delete;
|
||||||
operator RTLIL::IdString() const;
|
operator RTLIL::IdString() const;
|
||||||
|
operator Twine::Id() const;
|
||||||
ModuleNameMasq& operator=(RTLIL::IdString id);
|
ModuleNameMasq& operator=(RTLIL::IdString id);
|
||||||
// Without this, `new_mod->name = src_mod->name` invokes the implicit
|
// Without this, `new_mod->name = src_mod->name` invokes the implicit
|
||||||
// copy-assign (no-op) instead of operator=(IdString), so the meta
|
// copy-assign (no-op) instead of operator=(IdString), so the meta
|
||||||
@@ -2867,8 +2979,8 @@ public:
|
|||||||
int refcount_wires_;
|
int refcount_wires_;
|
||||||
int refcount_cells_;
|
int refcount_cells_;
|
||||||
|
|
||||||
dict<RTLIL::IdString, RTLIL::Wire*> wires_;
|
dict<Twine::Id, RTLIL::Wire*> wires_;
|
||||||
dict<RTLIL::IdString, RTLIL::Cell*> cells_;
|
dict<Twine::Id, RTLIL::Cell*> cells_;
|
||||||
|
|
||||||
std::vector<RTLIL::SigSig> connections_;
|
std::vector<RTLIL::SigSig> connections_;
|
||||||
std::vector<RTLIL::Binding*> bindings_;
|
std::vector<RTLIL::Binding*> bindings_;
|
||||||
@@ -2892,7 +3004,7 @@ public:
|
|||||||
virtual ~Module();
|
virtual ~Module();
|
||||||
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, bool mayfail = false);
|
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, bool mayfail = false);
|
||||||
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
|
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
|
||||||
virtual size_t count_id(RTLIL::IdString id);
|
virtual size_t count_id(Twine* id);
|
||||||
virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
|
virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
|
||||||
virtual bool reprocess_if_necessary(RTLIL::Design *design);
|
virtual bool reprocess_if_necessary(RTLIL::Design *design);
|
||||||
|
|
||||||
@@ -2944,8 +3056,8 @@ public:
|
|||||||
template<typename T> void rewrite_sigspecs(T &functor);
|
template<typename T> void rewrite_sigspecs(T &functor);
|
||||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||||
// `src_id_verbatim`: when true, the caller guarantees that
|
// `src_id_verbatim`: when true, the caller guarantees that
|
||||||
// `new_mod->design->src_twines` is a verbatim copy of
|
// `new_mod->design->twines` is a verbatim copy of
|
||||||
// `this->design->src_twines`, so src_id_ values can be transferred
|
// `this->design->twines`, so src_id_ values can be transferred
|
||||||
// without retain/release on the destination pool (the copied refcounts
|
// without retain/release on the destination pool (the copied refcounts
|
||||||
// already account for the new AttrObject references). Used by
|
// already account for the new AttrObject references). Used by
|
||||||
// Design::clone_into for wholesale design copies.
|
// Design::clone_into for wholesale design copies.
|
||||||
@@ -2982,28 +3094,42 @@ public:
|
|||||||
return design->selected_member(name, member->name);
|
return design->selected_member(name, member->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::Wire* wire(const RTLIL::IdString &id) {
|
// Primary (fast) overloads — key directly into the dict.
|
||||||
|
RTLIL::Wire* wire(Twine::Id id) {
|
||||||
auto it = wires_.find(id);
|
auto it = wires_.find(id);
|
||||||
return it == wires_.end() ? nullptr : it->second;
|
return it == wires_.end() ? nullptr : it->second;
|
||||||
}
|
}
|
||||||
|
RTLIL::Cell* cell(Twine::Id id) {
|
||||||
|
auto it = cells_.find(id);
|
||||||
|
return it == cells_.end() ? nullptr : it->second;
|
||||||
|
}
|
||||||
|
const RTLIL::Wire* wire(Twine::Id id) const {
|
||||||
|
auto it = wires_.find(id);
|
||||||
|
return it == wires_.end() ? nullptr : it->second;
|
||||||
|
}
|
||||||
|
const RTLIL::Cell* cell(Twine::Id id) const {
|
||||||
|
auto it = cells_.find(id);
|
||||||
|
return it == cells_.end() ? nullptr : it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdString compatibility shims: look up via twines, then dispatch.
|
||||||
|
RTLIL::Wire* wire(const RTLIL::IdString &id) {
|
||||||
|
return wire(design->twines.lookup(id.str()));
|
||||||
|
}
|
||||||
RTLIL::Cell* cell(const RTLIL::IdString &id) {
|
RTLIL::Cell* cell(const RTLIL::IdString &id) {
|
||||||
auto it = cells_.find(id);
|
return cell(design->twines.lookup(id.str()));
|
||||||
return it == cells_.end() ? nullptr : it->second;
|
|
||||||
}
|
}
|
||||||
|
const RTLIL::Wire* wire(const RTLIL::IdString &id) const {
|
||||||
const RTLIL::Wire* wire(const RTLIL::IdString &id) const{
|
return wire(design->twines.lookup(id.str()));
|
||||||
auto it = wires_.find(id);
|
|
||||||
return it == wires_.end() ? nullptr : it->second;
|
|
||||||
}
|
}
|
||||||
const RTLIL::Cell* cell(const RTLIL::IdString &id) const {
|
const RTLIL::Cell* cell(const RTLIL::IdString &id) const {
|
||||||
auto it = cells_.find(id);
|
return cell(design->twines.lookup(id.str()));
|
||||||
return it == cells_.end() ? nullptr : it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::ObjRange<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
|
RTLIL::ObjRange<RTLIL::Wire*, Twine::Id> wires() { return RTLIL::ObjRange<RTLIL::Wire*, Twine::Id>(&wires_, &refcount_wires_); }
|
||||||
int wires_size() const { return wires_.size(); }
|
int wires_size() const { return wires_.size(); }
|
||||||
RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; }
|
RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; }
|
||||||
RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }
|
RTLIL::ObjRange<RTLIL::Cell*, Twine::Id> cells() { return RTLIL::ObjRange<RTLIL::Cell*, Twine::Id>(&cells_, &refcount_cells_); }
|
||||||
int cells_size() const { return cells_.size(); }
|
int cells_size() const { return cells_.size(); }
|
||||||
RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; }
|
RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; }
|
||||||
|
|
||||||
@@ -3025,9 +3151,17 @@ public:
|
|||||||
RTLIL::IdString uniquify(RTLIL::IdString name);
|
RTLIL::IdString uniquify(RTLIL::IdString name);
|
||||||
RTLIL::IdString uniquify(RTLIL::IdString name, int &index);
|
RTLIL::IdString uniquify(RTLIL::IdString name, int &index);
|
||||||
|
|
||||||
|
// Primary overloads: name already interned in design->twines.
|
||||||
|
RTLIL::Wire *addWire(Twine::Id name, int width = 1);
|
||||||
|
RTLIL::Wire *addWire(Twine::Id name, const RTLIL::Wire *other);
|
||||||
|
// IdString compatibility: interns name into twines, then dispatches.
|
||||||
RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1);
|
RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1);
|
||||||
RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other);
|
RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other);
|
||||||
|
|
||||||
|
// Primary overloads.
|
||||||
|
RTLIL::Cell *addCell(Twine::Id name, RTLIL::IdString type);
|
||||||
|
RTLIL::Cell *addCell(Twine::Id name, const RTLIL::Cell *other);
|
||||||
|
// IdString compatibility.
|
||||||
RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type);
|
RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type);
|
||||||
RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other);
|
RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other);
|
||||||
|
|
||||||
@@ -3185,20 +3319,48 @@ void RTLIL::Process::rewrite_sigspecs2(T &functor)
|
|||||||
it->rewrite_sigspecs2(functor);
|
it->rewrite_sigspecs2(functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline RTLIL::WireNameMasq::operator RTLIL::IdString() const {
|
||||||
|
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
|
||||||
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
|
||||||
|
if (!w->module || !w->module->design || !w->meta_)
|
||||||
|
return RTLIL::IdString{};
|
||||||
|
Twine::Id id = w->meta_->name_id;
|
||||||
|
if (id == Twine::Null)
|
||||||
|
return RTLIL::IdString{};
|
||||||
|
return RTLIL::IdString(w->module->design->twines.flat_string(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RTLIL::CellNameMasq::operator RTLIL::IdString() const {
|
||||||
|
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
|
||||||
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
|
||||||
|
if (!c->module || !c->module->design || !c->meta_)
|
||||||
|
return RTLIL::IdString{};
|
||||||
|
Twine::Id id = c->meta_->name_id;
|
||||||
|
if (id == Twine::Null)
|
||||||
|
return RTLIL::IdString{};
|
||||||
|
return RTLIL::IdString(c->module->design->twines.flat_string(id));
|
||||||
|
}
|
||||||
|
|
||||||
inline RTLIL::ModuleNameMasq::operator RTLIL::IdString() const {
|
inline RTLIL::ModuleNameMasq::operator RTLIL::IdString() const {
|
||||||
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module*>(
|
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module*>(
|
||||||
reinterpret_cast<const char*>(this) - offsetof(RTLIL::Module, name));
|
reinterpret_cast<const char*>(this) - offsetof(RTLIL::Module, name));
|
||||||
return m->design ? m->design->obj_name(m) : RTLIL::IdString{};
|
return m->design ? m->design->obj_name(m) : std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) {
|
inline RTLIL::ModuleNameMasq::operator Twine::Id() const {
|
||||||
RTLIL::Module *m = reinterpret_cast<RTLIL::Module*>(
|
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module*>(
|
||||||
reinterpret_cast<char*>(this) - offsetof(RTLIL::Module, name));
|
reinterpret_cast<const char*>(this) - offsetof(RTLIL::Module, name));
|
||||||
log_assert(m->design && "assignment to Module::name requires the module to be attached to a design");
|
return m->design ? m->design->obj_src_id(m) : nullptr;
|
||||||
m->design->obj_set_name(m, id);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) {
|
||||||
|
// RTLIL::Module *m = reinterpret_cast<RTLIL::Module*>(
|
||||||
|
// reinterpret_cast<char*>(this) - offsetof(RTLIL::Module, name));
|
||||||
|
// log_assert(m->design && "assignment to Module::name requires the module to be attached to a design");
|
||||||
|
// m->design->obj_set_name(m, id);
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -520,12 +520,14 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
|
|||||||
while (!cell->connections_.empty())
|
while (!cell->connections_.empty())
|
||||||
cell->unsetPort(cell->connections_.begin()->first);
|
cell->unsetPort(cell->connections_.begin()->first);
|
||||||
|
|
||||||
log_assert(cells_.count(cell->name) != 0);
|
log_assert(cell->meta_ && cell->meta_->name_id != Twine::Null);
|
||||||
|
Twine::Id cell_id = cell->meta_->name_id;
|
||||||
|
log_assert(cells_.count(cell_id) != 0);
|
||||||
log_assert(refcount_cells_ == 0);
|
log_assert(refcount_cells_ == 0);
|
||||||
cells_.erase(cell->name);
|
cells_.erase(cell_id);
|
||||||
if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) {
|
if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) {
|
||||||
cell->type.clear();
|
cell->type.clear();
|
||||||
cell->name.clear();
|
design->obj_release_name_id(cell);
|
||||||
pending_deleted_cells.insert(cell);
|
pending_deleted_cells.insert(cell);
|
||||||
} else {
|
} else {
|
||||||
if (sig_norm_index != nullptr) {
|
if (sig_norm_index != nullptr) {
|
||||||
|
|||||||
+10
-10
@@ -252,13 +252,13 @@ static int tcl_get_attr(ClientData, Tcl_Interp *interp, int argc, const char *ar
|
|||||||
ERROR("bad usage: expected \"get_attr -mod [-string|-int|-sint|-uint|-bool] <module> <attrname>\""
|
ERROR("bad usage: expected \"get_attr -mod [-string|-int|-sint|-uint|-bool] <module> <attrname>\""
|
||||||
" or \"get_attr [-string|-int|-sint|-uint|-bool] <module> <identifier> <attrname>\"")
|
" or \"get_attr [-string|-int|-sint|-uint|-bool] <module> <identifier> <attrname>\"")
|
||||||
|
|
||||||
IdString mod_id, obj_id, attr_id;
|
std::string mod_id, obj_id, attr_id;
|
||||||
mod_id = RTLIL::escape_id(argv[i++]);
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
if (!mod_flag)
|
if (!mod_flag)
|
||||||
obj_id = RTLIL::escape_id(argv[i++]);
|
obj_id = RTLIL::escape_id(argv[i++]);
|
||||||
attr_id = RTLIL::escape_id(argv[i++]);
|
attr_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
RTLIL::Module *mod = yosys_design->module(mod_id);
|
RTLIL::Module *mod = yosys_design->module(yosys_design->twines.lookup(mod_id));
|
||||||
if (!mod)
|
if (!mod)
|
||||||
ERROR("module not found")
|
ERROR("module not found")
|
||||||
|
|
||||||
@@ -315,13 +315,13 @@ static int tcl_has_attr(ClientData, Tcl_Interp *interp, int argc, const char *ar
|
|||||||
ERROR("bad usage: expected \"has_attr -mod <module> <attrname>\""
|
ERROR("bad usage: expected \"has_attr -mod <module> <attrname>\""
|
||||||
" or \"has_attr <module> <identifier> <attrname>\"")
|
" or \"has_attr <module> <identifier> <attrname>\"")
|
||||||
|
|
||||||
IdString mod_id, obj_id, attr_id;
|
std::string mod_id, obj_id, attr_id;
|
||||||
mod_id = RTLIL::escape_id(argv[i++]);
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
if (!mod_flag)
|
if (!mod_flag)
|
||||||
obj_id = RTLIL::escape_id(argv[i++]);
|
obj_id = RTLIL::escape_id(argv[i++]);
|
||||||
attr_id = RTLIL::escape_id(argv[i++]);
|
attr_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
RTLIL::Module *mod = yosys_design->module(mod_id);
|
RTLIL::Module *mod = yosys_design->module(yosys_design->twines.lookup(mod_id));
|
||||||
if (!mod)
|
if (!mod)
|
||||||
ERROR("module not found")
|
ERROR("module not found")
|
||||||
|
|
||||||
@@ -368,13 +368,13 @@ static int tcl_set_attr(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const
|
|||||||
" or \"set_attr [-true|-false] <module> <identifier> <attrname>\""
|
" or \"set_attr [-true|-false] <module> <identifier> <attrname>\""
|
||||||
" or \"set_attr -mod [-true|-false| <module> <attrname>\"")
|
" or \"set_attr -mod [-true|-false| <module> <attrname>\"")
|
||||||
|
|
||||||
IdString mod_id, obj_id, attr_id;
|
std::string mod_id, obj_id, attr_id;
|
||||||
mod_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
mod_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
||||||
if (!mod_flag)
|
if (!mod_flag)
|
||||||
obj_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
obj_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
||||||
attr_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
attr_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
||||||
|
|
||||||
RTLIL::Module *mod = yosys_design->module(mod_id);
|
RTLIL::Module *mod = yosys_design->module(yosys_design->twines.lookup(mod_id));
|
||||||
if (!mod)
|
if (!mod)
|
||||||
ERROR("module not found")
|
ERROR("module not found")
|
||||||
|
|
||||||
@@ -446,12 +446,12 @@ static int tcl_get_param(ClientData, Tcl_Interp *interp, int argc, const char *a
|
|||||||
(string_flag + int_flag > 1))
|
(string_flag + int_flag > 1))
|
||||||
ERROR("bad usage: expected \"get_param [-string|-int|-sint|-uint] <module> <cellid> <paramname>")
|
ERROR("bad usage: expected \"get_param [-string|-int|-sint|-uint] <module> <cellid> <paramname>")
|
||||||
|
|
||||||
IdString mod_id, cell_id, param_id;
|
std::string mod_id, cell_id, param_id;
|
||||||
mod_id = RTLIL::escape_id(argv[i++]);
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
cell_id = RTLIL::escape_id(argv[i++]);
|
cell_id = RTLIL::escape_id(argv[i++]);
|
||||||
param_id = RTLIL::escape_id(argv[i++]);
|
param_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
RTLIL::Module *mod = yosys_design->module(mod_id);
|
RTLIL::Module *mod = yosys_design->module(yosys_design->twines.lookup(mod_id));
|
||||||
if (!mod)
|
if (!mod)
|
||||||
ERROR("module not found")
|
ERROR("module not found")
|
||||||
|
|
||||||
@@ -492,12 +492,12 @@ static int tcl_set_param(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *cons
|
|||||||
(string_flag + sint_flag + uint_flag > 1))
|
(string_flag + sint_flag + uint_flag > 1))
|
||||||
ERROR("bad usage: expected \"set_param [-string|-sint|-uint] <module> <cellid> <paramname> <value>")
|
ERROR("bad usage: expected \"set_param [-string|-sint|-uint] <module> <cellid> <paramname> <value>")
|
||||||
|
|
||||||
IdString mod_id, cell_id, param_id;
|
std::string mod_id, cell_id, param_id;
|
||||||
mod_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
mod_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
||||||
cell_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
cell_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
||||||
param_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
param_id = RTLIL::escape_id(Tcl_GetString(objv[i++]));
|
||||||
|
|
||||||
RTLIL::Module *mod = yosys_design->module(mod_id);
|
RTLIL::Module *mod = yosys_design->module(yosys_design->twines.lookup(mod_id));
|
||||||
if (!mod)
|
if (!mod)
|
||||||
ERROR("module not found")
|
ERROR("module not found")
|
||||||
|
|
||||||
|
|||||||
+220
-116
@@ -3,6 +3,52 @@
|
|||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
TwinePool::TwinePool()
|
||||||
|
: leaf_index_(0, LeafHash{this}, LeafEq{this})
|
||||||
|
, suffix_index_(0, SuffixHash{this}, SuffixEq{this})
|
||||||
|
, concat_index_(0, ConcatHash{this}, ConcatEq{this})
|
||||||
|
{}
|
||||||
|
|
||||||
|
TwinePool::TwinePool(const TwinePool &other)
|
||||||
|
: nodes_(other.nodes_)
|
||||||
|
, refcount_(other.refcount_)
|
||||||
|
, free_list_(other.free_list_)
|
||||||
|
, leaf_index_(0, LeafHash{this}, LeafEq{this})
|
||||||
|
, suffix_index_(0, SuffixHash{this}, SuffixEq{this})
|
||||||
|
, concat_index_(0, ConcatHash{this}, ConcatEq{this})
|
||||||
|
{
|
||||||
|
rebuild_indexes_();
|
||||||
|
}
|
||||||
|
|
||||||
|
TwinePool &TwinePool::operator=(const TwinePool &other)
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
nodes_ = other.nodes_;
|
||||||
|
refcount_ = other.refcount_;
|
||||||
|
free_list_ = other.free_list_;
|
||||||
|
// Re-create the index sets with functors pointing to *this,
|
||||||
|
// then rebuild their contents from the (now-copied) nodes_.
|
||||||
|
leaf_index_ = std::unordered_set<Twine::Id, LeafHash, LeafEq>(
|
||||||
|
0, LeafHash{this}, LeafEq{this});
|
||||||
|
suffix_index_ = std::unordered_set<Twine::Id, SuffixHash, SuffixEq>(
|
||||||
|
0, SuffixHash{this}, SuffixEq{this});
|
||||||
|
concat_index_ = std::unordered_set<Twine::Id, ConcatHash, ConcatEq>(
|
||||||
|
0, ConcatHash{this}, ConcatEq{this});
|
||||||
|
rebuild_indexes_();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwinePool::rebuild_indexes_()
|
||||||
|
{
|
||||||
|
for (auto& n : nodes_) {
|
||||||
|
if (n.is_dead()) continue;
|
||||||
|
if (n.is_leaf()) leaf_index_.insert(&n);
|
||||||
|
else if (n.is_suffix()) suffix_index_.insert(&n);
|
||||||
|
else if (n.is_concat()) concat_index_.insert(&n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Twine::Id TwinePool::alloc_slot_(Twine &&node)
|
Twine::Id TwinePool::alloc_slot_(Twine &&node)
|
||||||
{
|
{
|
||||||
if (!free_list_.empty()) {
|
if (!free_list_.empty()) {
|
||||||
@@ -12,40 +58,59 @@ Twine::Id TwinePool::alloc_slot_(Twine &&node)
|
|||||||
// "@N" refs across design -push;-pop and similar wholesale-clone
|
// "@N" refs across design -push;-pop and similar wholesale-clone
|
||||||
// cycles, even though the in-memory pool got renumbered through
|
// cycles, even though the in-memory pool got renumbered through
|
||||||
// the free list.
|
// the free list.
|
||||||
auto it = std::min_element(free_list_.begin(), free_list_.end());
|
// TODO nevermind, inefficient, solve in RTLIL frontend and backend
|
||||||
Twine::Id id = *it;
|
// auto it = std::min_element(free_list_.begin(), free_list_.end());
|
||||||
free_list_.erase(it);
|
// Twine::Id id = *it;
|
||||||
nodes_[id] = std::move(node);
|
// free_list_.erase(it);
|
||||||
refcount_[id] = 0;
|
Twine* id = free_list_.back();
|
||||||
|
*id = std::move(node);
|
||||||
|
// size_t idx = id - &nodes_.front();
|
||||||
|
// log_assert(idx > 0 && idx < refcount_.size());
|
||||||
|
// refcount_[idx] = 0;
|
||||||
|
refcount(id) = 0;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
Twine::Id id = static_cast<Twine::Id>(nodes_.size());
|
// Twine::Id id = static_cast<Twine::Id>(nodes_.size());
|
||||||
nodes_.push_back(std::move(node));
|
nodes_.push_back(std::move(node));
|
||||||
|
Twine* id = &nodes_.back();
|
||||||
refcount_.push_back(0);
|
refcount_.push_back(0);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Twine::Id TwinePool::intern(std::string_view leaf)
|
Twine::Id TwinePool::intern(std::string_view str)
|
||||||
{
|
{
|
||||||
if (leaf.empty())
|
if (str.empty())
|
||||||
return Twine::Null;
|
return Twine::Null;
|
||||||
std::string key{leaf};
|
// Transparent find: probes with string_view, no string allocation.
|
||||||
if (auto it = leaf_index_.find(key); it != leaf_index_.end()) {
|
// TODO why are they split like this? Is this called on a hot path somewhere?
|
||||||
retain(it->second);
|
if (auto it = leaf_index_.find(str); it != leaf_index_.end()) {
|
||||||
return it->second;
|
retain(*it);
|
||||||
|
return *it;
|
||||||
}
|
}
|
||||||
Twine::Id id = alloc_slot_(Twine{std::move(key)});
|
if (auto it = suffix_index_.find(str); it != suffix_index_.end()) {
|
||||||
leaf_index_[std::get<std::string>(nodes_[id].data)] = id;
|
retain(*it);
|
||||||
refcount_[id] = 1;
|
return *it;
|
||||||
|
}
|
||||||
|
if (auto it = concat_index_.find(str); it != concat_index_.end()) {
|
||||||
|
retain(*it);
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
Twine::Id id = alloc_slot_(Twine{std::string{str}});
|
||||||
|
leaf_index_.insert(id);
|
||||||
|
|
||||||
|
// size_t idx = id - &nodes_.front();
|
||||||
|
// log_assert(idx > 0 && idx < refcount_.size());
|
||||||
|
// refcount_[idx] = 1;
|
||||||
|
refcount(id) = 1;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Twine::Id TwinePool::intern_suffix(Twine::Id parent, std::string_view tail)
|
Twine* TwinePool::intern_suffix(Twine* parent, std::string_view tail)
|
||||||
{
|
{
|
||||||
if (parent == Twine::Null)
|
if (parent == Twine::Null)
|
||||||
return intern(tail);
|
return intern(tail);
|
||||||
log_assert(parent < nodes_.size() && !nodes_[parent].is_dead());
|
log_assert(parent > &nodes_.front() && parent <= &nodes_.back() && !parent->is_dead());
|
||||||
log_assert(nodes_[parent].is_flat() && "Suffix parent must be a flat node (Leaf or Suffix)");
|
log_assert(parent->is_flat() && "Suffix parent must be a flat node (Leaf or Suffix)");
|
||||||
if (tail.empty()) {
|
if (tail.empty()) {
|
||||||
// No tail means "the same string as parent". Hand back a fresh
|
// No tail means "the same string as parent". Hand back a fresh
|
||||||
// owning ref on parent — semantically equivalent to a degenerate
|
// owning ref on parent — semantically equivalent to a degenerate
|
||||||
@@ -54,18 +119,18 @@ Twine::Id TwinePool::intern_suffix(Twine::Id parent, std::string_view tail)
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Twine::Id, std::string> key{parent, std::string{tail}};
|
// Transparent find: probes with (parent, string_view), no allocation.
|
||||||
|
SuffixKey key{parent, tail};
|
||||||
if (auto it = suffix_index_.find(key); it != suffix_index_.end()) {
|
if (auto it = suffix_index_.find(key); it != suffix_index_.end()) {
|
||||||
retain(it->second);
|
retain(*it);
|
||||||
return it->second;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal child ref: the suffix node owns one ref on its parent.
|
// Internal child ref: the suffix node owns one ref on its parent.
|
||||||
retain(parent);
|
retain(parent);
|
||||||
Twine::Id id = alloc_slot_(Twine{Twine::Suffix{parent, std::string{tail}}});
|
Twine::Id id = alloc_slot_(Twine{Twine::Suffix{parent, std::string{tail}}});
|
||||||
const auto &stored = std::get<Twine::Suffix>(nodes_[id].data);
|
suffix_index_.insert(id);
|
||||||
suffix_index_[std::make_pair(stored.parent, stored.tail)] = id;
|
refcount(id) = 1;
|
||||||
refcount_[id] = 1;
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +150,8 @@ Twine::Id TwinePool::concat(std::span<const Twine::Id> parts)
|
|||||||
for (Twine::Id p : parts) {
|
for (Twine::Id p : parts) {
|
||||||
if (p == Twine::Null)
|
if (p == Twine::Null)
|
||||||
continue;
|
continue;
|
||||||
log_assert(p < nodes_.size() && !nodes_[p].is_dead());
|
// log_assert(p < nodes_.size() && !nodes_[p].is_dead());
|
||||||
const Twine &n = nodes_[p];
|
const Twine &n = *p;
|
||||||
if (n.is_flat()) {
|
if (n.is_flat()) {
|
||||||
push_flat(p);
|
push_flat(p);
|
||||||
} else {
|
} else {
|
||||||
@@ -102,17 +167,19 @@ Twine::Id TwinePool::concat(std::span<const Twine::Id> parts)
|
|||||||
return children.front();
|
return children.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto it = concat_index_.find(children); it != concat_index_.end()) {
|
// Transparent find: probes with span, no vector allocation.
|
||||||
retain(it->second);
|
std::span<const Twine::Id> child_span{children};
|
||||||
return it->second;
|
if (auto it = concat_index_.find(child_span); it != concat_index_.end()) {
|
||||||
|
retain(*it);
|
||||||
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal child refs: the concat node owns one ref on each child.
|
// Internal child refs: the concat node owns one ref on each child.
|
||||||
for (Twine::Id c : children)
|
for (Twine::Id c : children)
|
||||||
retain(c);
|
retain(c);
|
||||||
Twine::Id id = alloc_slot_(Twine{std::move(children)});
|
Twine::Id id = alloc_slot_(Twine{std::move(children)});
|
||||||
concat_index_[std::get<std::vector<Twine::Id>>(nodes_[id].data)] = id;
|
concat_index_.insert(id);
|
||||||
refcount_[id] = 1;
|
refcount(id) = 1;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,55 +193,68 @@ void TwinePool::retain(Twine::Id id)
|
|||||||
{
|
{
|
||||||
if (id == Twine::Null)
|
if (id == Twine::Null)
|
||||||
return;
|
return;
|
||||||
log_assert(id < nodes_.size() && !nodes_[id].is_dead());
|
refcount(id)++;
|
||||||
refcount_[id]++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwinePool::release(Twine::Id id)
|
void TwinePool::release(Twine::Id id)
|
||||||
{
|
{
|
||||||
if (id == Twine::Null)
|
if (id == Twine::Null)
|
||||||
return;
|
return;
|
||||||
log_assert(id < nodes_.size() && !nodes_[id].is_dead());
|
// log_assert(id < nodes_.size() && !nodes_[id].is_dead());
|
||||||
log_assert(refcount_[id] > 0);
|
log_assert(refcount(id) > 0);
|
||||||
if (--refcount_[id] == 0)
|
if (--refcount(id) == 0)
|
||||||
destroy_slot_(id);
|
destroy_slot_(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t TwinePool::index(Twine::Id p) const
|
||||||
|
{
|
||||||
|
return p - &nodes_.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t& TwinePool::refcount(Twine::Id id)
|
||||||
|
{
|
||||||
|
log_assert(id != Twine::Null);
|
||||||
|
size_t idx = index(id);
|
||||||
|
log_assert(idx > 0 && idx < refcount_.size());
|
||||||
|
return refcount_[idx];
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t TwinePool::refcount(Twine::Id id) const
|
uint32_t TwinePool::refcount(Twine::Id id) const
|
||||||
{
|
{
|
||||||
if (id == Twine::Null)
|
log_assert(id != Twine::Null);
|
||||||
return 0;
|
size_t idx = id - &nodes_.front();
|
||||||
return refcount_.at(id);
|
log_assert(idx > 0 && idx < refcount_.size());
|
||||||
|
return refcount_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwinePool::is_alive(Twine::Id id) const
|
bool TwinePool::is_alive(Twine::Id id) const
|
||||||
{
|
{
|
||||||
if (id == Twine::Null)
|
if (id == Twine::Null)
|
||||||
return false;
|
return false;
|
||||||
return id < nodes_.size() && !nodes_[id].is_dead();
|
return id >= &nodes_.front() && id <= &nodes_.back() && !id->is_dead();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwinePool::destroy_slot_(Twine::Id id)
|
void TwinePool::destroy_slot_(Twine::Id id)
|
||||||
{
|
{
|
||||||
Twine &n = nodes_[id];
|
Twine &n = *id;
|
||||||
if (n.is_leaf()) {
|
if (n.is_leaf()) {
|
||||||
leaf_index_.erase(n.leaf());
|
// Erase by id: functor reads nodes_[id].leaf() before we tombstone.
|
||||||
|
leaf_index_.erase(id);
|
||||||
} else if (n.is_concat()) {
|
} else if (n.is_concat()) {
|
||||||
// Release internal child refs. Capture by move so iteration is
|
// Erase by id first (while data is still readable), then capture
|
||||||
// stable across child destroy_slot_ side effects.
|
// children by move so iteration is stable across recursive release.
|
||||||
std::vector<Twine::Id> children = std::move(std::get<std::vector<Twine::Id>>(n.data));
|
concat_index_.erase(id);
|
||||||
concat_index_.erase(children);
|
std::vector<Twine::Id> children =
|
||||||
|
std::move(std::get<std::vector<Twine::Id>>(n.data));
|
||||||
n.data = std::monostate{};
|
n.data = std::monostate{};
|
||||||
free_list_.push_back(id);
|
free_list_.push_back(id);
|
||||||
for (Twine::Id c : children)
|
for (Twine::Id c : children)
|
||||||
release(c);
|
release(c);
|
||||||
return;
|
return;
|
||||||
} else if (n.is_suffix()) {
|
} else if (n.is_suffix()) {
|
||||||
// Capture parent by move and release after dropping the slot,
|
// Same pattern: erase first, then move data for deferred release.
|
||||||
// since releasing may recursively destroy the parent and we
|
suffix_index_.erase(id);
|
||||||
// want this slot's tombstone to be visible by then.
|
|
||||||
Twine::Suffix s = std::move(std::get<Twine::Suffix>(n.data));
|
Twine::Suffix s = std::move(std::get<Twine::Suffix>(n.data));
|
||||||
suffix_index_.erase(std::make_pair(s.parent, s.tail));
|
|
||||||
n.data = std::monostate{};
|
n.data = std::monostate{};
|
||||||
free_list_.push_back(id);
|
free_list_.push_back(id);
|
||||||
release(s.parent);
|
release(s.parent);
|
||||||
@@ -184,11 +264,30 @@ void TwinePool::destroy_slot_(Twine::Id id)
|
|||||||
free_list_.push_back(id);
|
free_list_.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Twine::Id TwinePool::lookup(std::string_view sv) const
|
||||||
|
{
|
||||||
|
if (sv.empty())
|
||||||
|
return Twine::Null;
|
||||||
|
auto it = leaf_index_.find(sv);
|
||||||
|
return (it != leaf_index_.end()) ? *it : Twine::Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
char TwinePool::first_char(Twine::Id id) const
|
||||||
|
{
|
||||||
|
log_assert(id != Twine::Null && id > &nodes_.front() && id <= &nodes_.back() && !id->is_dead());
|
||||||
|
// Walk suffix parents to reach the root leaf, then return its first char.
|
||||||
|
while (id->is_suffix())
|
||||||
|
id = id->suffix().parent;
|
||||||
|
const std::string &s = id->leaf();
|
||||||
|
// TODO seems wrong for concate
|
||||||
|
return s.empty() ? '\0' : s.front();
|
||||||
|
}
|
||||||
|
|
||||||
void TwinePool::collect_leaves(Twine::Id id, pool<std::string> &out) const
|
void TwinePool::collect_leaves(Twine::Id id, pool<std::string> &out) const
|
||||||
{
|
{
|
||||||
if (id == Twine::Null)
|
if (id == Twine::Null)
|
||||||
return;
|
return;
|
||||||
const Twine &n = nodes_.at(id);
|
const Twine &n = *id;
|
||||||
if (n.is_dead())
|
if (n.is_dead())
|
||||||
return;
|
return;
|
||||||
if (n.is_leaf()) {
|
if (n.is_leaf()) {
|
||||||
@@ -213,7 +312,7 @@ std::string TwinePool::flat_string_(Twine::Id id) const
|
|||||||
log_assert(id != Twine::Null);
|
log_assert(id != Twine::Null);
|
||||||
std::vector<std::string_view> parts;
|
std::vector<std::string_view> parts;
|
||||||
while (true) {
|
while (true) {
|
||||||
const Twine &n = nodes_.at(id);
|
const Twine &n = *id;
|
||||||
if (n.is_leaf()) {
|
if (n.is_leaf()) {
|
||||||
parts.push_back(n.leaf());
|
parts.push_back(n.leaf());
|
||||||
break;
|
break;
|
||||||
@@ -249,27 +348,32 @@ std::string TwinePool::flatten(Twine::Id id, char sep) const
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TwinePool::format_ref(Twine::Id id)
|
std::string TwinePool::format_ref(Twine::Id id) const
|
||||||
{
|
{
|
||||||
if (id == Twine::Null)
|
if (id == Twine::Null)
|
||||||
return {};
|
return {};
|
||||||
return "@" + std::to_string(id);
|
size_t i = index(id);
|
||||||
|
return "@" + std::to_string(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
Twine::Id TwinePool::parse_ref(std::string_view s)
|
std::optional<size_t> TwinePool::parse_ref(std::string_view s)
|
||||||
{
|
{
|
||||||
if (s.size() < 2 || s[0] != '@')
|
if (s.size() < 2 || s[0] != '@')
|
||||||
return Twine::Null;
|
return std::nullopt;
|
||||||
uint64_t v = 0;
|
uint64_t v = 0;
|
||||||
for (size_t i = 1; i < s.size(); i++) {
|
for (size_t i = 1; i < s.size(); i++) {
|
||||||
char c = s[i];
|
char c = s[i];
|
||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return Twine::Null;
|
return std::nullopt;
|
||||||
v = v * 10 + static_cast<uint64_t>(c - '0');
|
v = v * 10 + static_cast<uint64_t>(c - '0');
|
||||||
if (v >= std::numeric_limits<Twine::Id>::max())
|
|
||||||
return Twine::Null;
|
|
||||||
}
|
}
|
||||||
return static_cast<Twine::Id>(v);
|
return v;
|
||||||
|
}
|
||||||
|
Twine::Id TwinePool::get_ref(std::string_view s)
|
||||||
|
{
|
||||||
|
if (auto idx = parse_ref(s))
|
||||||
|
return &nodes_.front() + *idx;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwinePool::dump(const char *banner) const
|
void TwinePool::dump(const char *banner) const
|
||||||
@@ -281,18 +385,18 @@ void TwinePool::dump(const char *banner) const
|
|||||||
concat_index_.size(), free_list_.size());
|
concat_index_.size(), free_list_.size());
|
||||||
for_each_live([&](Twine::Id id, const Twine &n) {
|
for_each_live([&](Twine::Id id, const Twine &n) {
|
||||||
if (n.is_leaf()) {
|
if (n.is_leaf()) {
|
||||||
log(" @%u leaf rc=%u %s\n", id, refcount_[id], n.leaf().c_str());
|
log(" @%u leaf rc=%u %s\n", id, refcount(id), n.leaf().c_str());
|
||||||
} else if (n.is_suffix()) {
|
} else if (n.is_suffix()) {
|
||||||
log(" @%u suffix rc=%u @%u + %s\n", id, refcount_[id],
|
log(" @%u suffix rc=%u @%u + %s\n", id, refcount(id),
|
||||||
n.suffix().parent, n.suffix().tail.c_str());
|
n.suffix().parent, n.suffix().tail.c_str());
|
||||||
} else {
|
} else {
|
||||||
std::string children;
|
std::string children;
|
||||||
for (Twine::Id c : n.children()) {
|
for (Twine::Id c : n.children()) {
|
||||||
if (!children.empty())
|
if (!children.empty())
|
||||||
children += ", ";
|
children += ", ";
|
||||||
children += "@" + std::to_string(c);
|
children += format_ref(c);
|
||||||
}
|
}
|
||||||
log(" @%u concat rc=%u [%s]\n", id, refcount_[id], children.c_str());
|
log(" @%u concat rc=%u [%s]\n", id, refcount(id), children.c_str());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -306,7 +410,7 @@ dict<Twine::Id, Twine::Id> TwinePool::gc(const pool<Twine::Id> &live)
|
|||||||
pool<Twine::Id> reachable;
|
pool<Twine::Id> reachable;
|
||||||
std::vector<Twine::Id> work;
|
std::vector<Twine::Id> work;
|
||||||
for (Twine::Id id : live) {
|
for (Twine::Id id : live) {
|
||||||
if (id == Twine::Null || id >= nodes_.size() || nodes_[id].is_dead())
|
if (!id || id->is_dead())
|
||||||
continue;
|
continue;
|
||||||
if (reachable.insert(id).second)
|
if (reachable.insert(id).second)
|
||||||
work.push_back(id);
|
work.push_back(id);
|
||||||
@@ -314,7 +418,7 @@ dict<Twine::Id, Twine::Id> TwinePool::gc(const pool<Twine::Id> &live)
|
|||||||
while (!work.empty()) {
|
while (!work.empty()) {
|
||||||
Twine::Id id = work.back();
|
Twine::Id id = work.back();
|
||||||
work.pop_back();
|
work.pop_back();
|
||||||
const Twine &n = nodes_[id];
|
const Twine &n = *id;
|
||||||
if (n.is_concat()) {
|
if (n.is_concat()) {
|
||||||
for (Twine::Id c : n.children())
|
for (Twine::Id c : n.children())
|
||||||
if (reachable.insert(c).second)
|
if (reachable.insert(c).second)
|
||||||
@@ -326,101 +430,101 @@ dict<Twine::Id, Twine::Id> TwinePool::gc(const pool<Twine::Id> &live)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild the pool from scratch. Process flats (Leaf, then Suffix)
|
// Rebuild the pool from scratch using temporary storage; process flats
|
||||||
// before Concats so concat-child lookups can resolve, and process
|
// before concats so child lookups can resolve.
|
||||||
// suffixes parent-before-child via a recursive helper that memoizes
|
|
||||||
// into `remap`.
|
|
||||||
std::vector<Twine> new_nodes;
|
std::vector<Twine> new_nodes;
|
||||||
std::vector<uint32_t> new_refcount;
|
std::vector<uint32_t> new_refcount;
|
||||||
dict<std::string, Twine::Id> new_leaf_index;
|
|
||||||
dict<std::vector<Twine::Id>, Twine::Id> new_concat_index;
|
|
||||||
dict<std::pair<Twine::Id, std::string>, Twine::Id> new_suffix_index;
|
|
||||||
dict<Twine::Id, Twine::Id> remap;
|
dict<Twine::Id, Twine::Id> remap;
|
||||||
|
|
||||||
auto intern_leaf = [&](const std::string &text) -> Twine::Id {
|
// Helper: insert a leaf into new_nodes, dedup by string.
|
||||||
if (auto it = new_leaf_index.find(text); it != new_leaf_index.end())
|
// dict<std::string, Twine::Id> new_leaf_map;
|
||||||
return it->second;
|
|
||||||
Twine::Id id = static_cast<Twine::Id>(new_nodes.size());
|
|
||||||
new_nodes.push_back(Twine{text});
|
|
||||||
new_refcount.push_back(0);
|
|
||||||
new_leaf_index[std::get<std::string>(new_nodes.back().data)] = id;
|
|
||||||
return id;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (Twine::Id old_id : reachable) {
|
for (Twine::Id old_id : reachable) {
|
||||||
const Twine &n = nodes_[old_id];
|
const Twine &n = *old_id;
|
||||||
if (n.is_leaf())
|
if (n.is_leaf())
|
||||||
remap[old_id] = intern_leaf(n.leaf());
|
remap[old_id] = intern(n.leaf());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<Twine::Id(Twine::Id)> remap_flat = [&](Twine::Id old_id) -> Twine::Id {
|
std::function<Twine::Id(Twine::Id)> remap_flat = [&](Twine::Id old_id) -> Twine::Id {
|
||||||
if (auto it = remap.find(old_id); it != remap.end())
|
if (auto it = remap.find(old_id); it != remap.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
const Twine &n = nodes_[old_id];
|
const Twine &n = *old_id;
|
||||||
log_assert(n.is_suffix());
|
log_assert(n.is_suffix());
|
||||||
Twine::Id new_parent = remap_flat(n.suffix().parent);
|
Twine::Id new_parent = remap_flat(n.suffix().parent);
|
||||||
std::pair<Twine::Id, std::string> key{new_parent, n.suffix().tail};
|
// Dedup suffix nodes in the new pool.
|
||||||
if (auto sit = new_suffix_index.find(key); sit != new_suffix_index.end()) {
|
for (auto& i : new_nodes) {
|
||||||
remap[old_id] = sit->second;
|
if (i.is_suffix()) {
|
||||||
return sit->second;
|
const auto &s = i.suffix();
|
||||||
|
if (s.parent == new_parent && s.tail == n.suffix().tail) {
|
||||||
|
remap[old_id] = &i;
|
||||||
|
return &i;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Twine::Id new_id = static_cast<Twine::Id>(new_nodes.size());
|
// Twine::Id new_id = static_cast<Twine::Id>(new_nodes.size());
|
||||||
new_nodes.push_back(Twine{Twine::Suffix{new_parent, n.suffix().tail}});
|
new_nodes.push_back(Twine{Twine::Suffix{new_parent, n.suffix().tail}});
|
||||||
|
Twine::Id new_id = &new_nodes.back();
|
||||||
new_refcount.push_back(0);
|
new_refcount.push_back(0);
|
||||||
const auto &stored = std::get<Twine::Suffix>(new_nodes.back().data);
|
|
||||||
new_suffix_index[std::make_pair(stored.parent, stored.tail)] = new_id;
|
|
||||||
remap[old_id] = new_id;
|
remap[old_id] = new_id;
|
||||||
return new_id;
|
return new_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (Twine::Id old_id : reachable) {
|
for (Twine::Id old_id : reachable) {
|
||||||
const Twine &n = nodes_[old_id];
|
const Twine &n = *old_id;
|
||||||
if (n.is_suffix() && remap.find(old_id) == remap.end())
|
if (n.is_suffix() && remap.find(old_id) == remap.end())
|
||||||
remap_flat(old_id);
|
remap_flat(old_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dedup concat nodes by child vector.
|
||||||
|
dict<std::vector<Twine::Id>, Twine::Id> new_concat_map;
|
||||||
for (Twine::Id old_id : reachable) {
|
for (Twine::Id old_id : reachable) {
|
||||||
const Twine &n = nodes_[old_id];
|
const Twine &n = *old_id;
|
||||||
if (!n.is_concat())
|
if (!n.is_concat())
|
||||||
continue;
|
continue;
|
||||||
std::vector<Twine::Id> children;
|
std::vector<Twine::Id> children;
|
||||||
children.reserve(n.children().size());
|
children.reserve(n.children().size());
|
||||||
for (Twine::Id c : n.children())
|
for (Twine::Id c : n.children())
|
||||||
children.push_back(remap.at(c));
|
children.push_back(remap.at(c));
|
||||||
if (auto it = new_concat_index.find(children); it != new_concat_index.end()) {
|
if (auto it = new_concat_map.find(children); it != new_concat_map.end()) {
|
||||||
remap[old_id] = it->second;
|
remap[old_id] = it->second;
|
||||||
} else {
|
} else {
|
||||||
Twine::Id new_id = static_cast<Twine::Id>(new_nodes.size());
|
// Twine::Id new_id = static_cast<Twine::Id>(new_nodes.size());
|
||||||
new_nodes.push_back(Twine{std::move(children)});
|
new_nodes.push_back(Twine{children});
|
||||||
|
Twine::Id new_id = &new_nodes.back();
|
||||||
new_refcount.push_back(0);
|
new_refcount.push_back(0);
|
||||||
new_concat_index[std::get<std::vector<Twine::Id>>(new_nodes.back().data)] = new_id;
|
new_concat_map[std::get<std::vector<Twine::Id>>(new_nodes.back().data)] = new_id;
|
||||||
remap[old_id] = new_id;
|
remap[old_id] = new_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refcounts in the rebuilt pool: every external "live" id passed in by
|
|
||||||
// the caller corresponds to one external owner reference; concats
|
|
||||||
// hold one ref per stored child; suffixes hold one ref on their parent.
|
// Swap in the new storage and rebuild the intrusive indexes.
|
||||||
|
nodes_ = std::move(new_nodes);
|
||||||
|
refcount_ = std::move(new_refcount);
|
||||||
|
|
||||||
|
// Refcounts in the rebuilt pool.
|
||||||
for (Twine::Id old_id : live) {
|
for (Twine::Id old_id : live) {
|
||||||
auto it = remap.find(old_id);
|
auto it = remap.find(old_id);
|
||||||
if (it != remap.end())
|
if (it != remap.end())
|
||||||
new_refcount[it->second]++;
|
refcount(it->second)++;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < new_nodes.size(); i++) {
|
for (size_t i = 0; i < nodes_.size(); i++) {
|
||||||
if (new_nodes[i].is_concat()) {
|
if (nodes_[i].is_concat()) {
|
||||||
for (Twine::Id c : new_nodes[i].children())
|
for (Twine::Id c : nodes_[i].children())
|
||||||
new_refcount[c]++;
|
refcount(c)++;
|
||||||
} else if (new_nodes[i].is_suffix()) {
|
} else if (nodes_[i].is_suffix()) {
|
||||||
new_refcount[new_nodes[i].suffix().parent]++;
|
refcount(nodes_[i].suffix().parent)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes_ = std::move(new_nodes);
|
|
||||||
refcount_ = std::move(new_refcount);
|
|
||||||
free_list_.clear();
|
free_list_.clear();
|
||||||
leaf_index_ = std::move(new_leaf_index);
|
leaf_index_ = std::unordered_set<Twine::Id, LeafHash, LeafEq>(
|
||||||
concat_index_ = std::move(new_concat_index);
|
0, LeafHash{this}, LeafEq{this});
|
||||||
suffix_index_ = std::move(new_suffix_index);
|
suffix_index_ = std::unordered_set<Twine::Id, SuffixHash, SuffixEq>(
|
||||||
|
0, SuffixHash{this}, SuffixEq{this});
|
||||||
|
concat_index_ = std::unordered_set<Twine::Id, ConcatHash, ConcatEq>(
|
||||||
|
0, ConcatHash{this}, ConcatEq{this});
|
||||||
|
rebuild_indexes_();
|
||||||
return remap;
|
return remap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +532,8 @@ Twine::Id TwinePool::copy_from(const TwinePool &src, Twine::Id src_id)
|
|||||||
{
|
{
|
||||||
if (src_id == Twine::Null)
|
if (src_id == Twine::Null)
|
||||||
return Twine::Null;
|
return Twine::Null;
|
||||||
log_assert(src_id < src.nodes_.size() && !src.nodes_[src_id].is_dead());
|
// log_assert(src_id < src.nodes_.size() && !src.nodes_[src_id].is_dead());
|
||||||
const Twine &n = src.nodes_[src_id];
|
const Twine &n = *src_id;
|
||||||
if (n.is_leaf())
|
if (n.is_leaf())
|
||||||
return intern(n.leaf());
|
return intern(n.leaf());
|
||||||
if (n.is_suffix()) {
|
if (n.is_suffix()) {
|
||||||
|
|||||||
+254
-91
@@ -8,6 +8,8 @@
|
|||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <list>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -20,24 +22,24 @@ YOSYS_NAMESPACE_BEGIN
|
|||||||
// the total path-string length the materialized result would have.
|
// the total path-string length the materialized result would have.
|
||||||
//
|
//
|
||||||
// Twines are valid only relative to the TwinePool that minted them. The pool
|
// Twines are valid only relative to the TwinePool that minted them. The pool
|
||||||
// lives on RTLIL::Design (design->src_twines).
|
// lives on RTLIL::Design (design->twines).
|
||||||
struct Twine
|
struct Twine
|
||||||
{
|
{
|
||||||
using Id = uint32_t;
|
using Id = Twine*;
|
||||||
static constexpr Id Null = std::numeric_limits<Id>::max();
|
static constexpr Id Null = nullptr;
|
||||||
|
|
||||||
// Suffix shares a `parent` prefix with other suffixes and contributes
|
// Suffix shares a `prefix` prefix with other suffixes and contributes
|
||||||
// its own `tail` string. The materialized leaf string is
|
// its own `tail` string. The materialized leaf string is
|
||||||
// flat_string(parent) + tail, i.e. suffixes form trees whose leaves
|
// flat_string(prefix) + tail, i.e. suffixes form trees whose leaves
|
||||||
// (string variant) are the roots — like a reverse-trie of common
|
// (string variant) are the roots — like a reverse-trie of common
|
||||||
// prefixes. The parent is itself flat (Leaf or Suffix), never a
|
// prefixes. The prefix is itself flat (Leaf or Suffix), never a
|
||||||
// Concat.
|
// Concat.
|
||||||
struct Suffix {
|
struct Suffix {
|
||||||
Id parent;
|
Id prefix;
|
||||||
std::string tail;
|
std::string tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Leaf holds the literal path:line.col string. Suffix holds a parent
|
// Leaf holds the literal path:line.col string. Suffix holds a prefix
|
||||||
// id + own tail (see above). Concat holds the ordered children.
|
// id + own tail (see above). Concat holds the ordered children.
|
||||||
// Concats are kept flat by TwinePool::concat — children are always
|
// Concats are kept flat by TwinePool::concat — children are always
|
||||||
// flat (Leaf or Suffix), never other Concats. monostate is the
|
// flat (Leaf or Suffix), never other Concats. monostate is the
|
||||||
@@ -54,10 +56,21 @@ struct Twine
|
|||||||
const Suffix &suffix() const { return std::get<Suffix>(data); }
|
const Suffix &suffix() const { return std::get<Suffix>(data); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TwinePoolExtender;
|
||||||
class TwinePool
|
class TwinePool
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
friend struct TwinePoolExtender;
|
||||||
|
uint32_t& refcount(Twine::Id id);
|
||||||
public:
|
public:
|
||||||
TwinePool() = default;
|
TwinePool();
|
||||||
|
// Custom copy: functor pointers must target the NEW pool's nodes_.
|
||||||
|
TwinePool(const TwinePool &other);
|
||||||
|
TwinePool &operator=(const TwinePool &other);
|
||||||
|
// Move is deleted; the intrusive functors hold `this`, so a move would
|
||||||
|
// silently leave them pointing at the old (now-empty) pool.
|
||||||
|
TwinePool(TwinePool &&) = delete;
|
||||||
|
TwinePool &operator=(TwinePool &&) = delete;
|
||||||
|
|
||||||
// Intern a leaf string. Returns the same Id for byte-equal inputs. The
|
// Intern a leaf string. Returns the same Id for byte-equal inputs. The
|
||||||
// returned Id carries one reference for the caller — release it when
|
// returned Id carries one reference for the caller — release it when
|
||||||
@@ -65,14 +78,14 @@ public:
|
|||||||
Twine::Id intern(std::string_view leaf);
|
Twine::Id intern(std::string_view leaf);
|
||||||
|
|
||||||
// Intern a Suffix node. The resulting flat string is
|
// Intern a Suffix node. The resulting flat string is
|
||||||
// flat_string(parent) + tail. `parent` must be a flat node (Leaf or
|
// flat_string(prefix) + tail. `prefix` must be a flat node (Leaf or
|
||||||
// Suffix) — pass Twine::Null with a non-empty `tail` to fall back to
|
// Suffix) — pass Twine::Null with a non-empty `tail` to fall back to
|
||||||
// intern(tail). Suffixes with the same (parent, tail) dedup. The
|
// intern(tail). Suffixes with the same (prefix, tail) dedup. The
|
||||||
// returned Id carries one reference for the caller. Internally the
|
// returned Id carries one reference for the caller. Internally the
|
||||||
// new suffix retains a reference on `parent`; releasing the suffix
|
// new suffix retains a reference on `prefix`; releasing the suffix
|
||||||
// releases that internal parent ref. Empty `tail` returns `parent`
|
// releases that internal prefix ref. Empty `tail` returns `prefix`
|
||||||
// (with +1 ref for the caller).
|
// (with +1 ref for the caller).
|
||||||
Twine::Id intern_suffix(Twine::Id parent, std::string_view tail);
|
Twine::Id intern_suffix(Twine::Id prefix, std::string_view tail);
|
||||||
|
|
||||||
// Build a Concat node referencing `parts` in order. Concat children are
|
// Build a Concat node referencing `parts` in order. Concat children are
|
||||||
// always leaves (flat-leaf invariant): any Concat passed in `parts` has
|
// always leaves (flat-leaf invariant): any Concat passed in `parts` has
|
||||||
@@ -85,15 +98,26 @@ public:
|
|||||||
Twine::Id concat(std::span<const Twine::Id> parts);
|
Twine::Id concat(std::span<const Twine::Id> parts);
|
||||||
Twine::Id concat(Twine::Id a, Twine::Id b);
|
Twine::Id concat(Twine::Id a, Twine::Id b);
|
||||||
|
|
||||||
|
// Non-interning lookup: return the Id of the leaf whose string equals
|
||||||
|
// `sv`, or Twine::Null if no such leaf exists. Does not allocate.
|
||||||
|
Twine::Id lookup(std::string_view sv) const;
|
||||||
|
|
||||||
// Refcount control. retain bumps; release decrements and, on reaching
|
// Refcount control. retain bumps; release decrements and, on reaching
|
||||||
// zero, marks the slot dead, drops it from the dedup indexes, releases
|
// zero, marks the slot dead, drops it from the dedup indexes, releases
|
||||||
// any child refs the slot owned, and pushes the slot id onto the free
|
// any child refs the slot owned, and pushes the slot id onto the free
|
||||||
// list for reuse by the next intern/concat. Both no-op on Twine::Null.
|
// list for reuse by the next intern/concat. Both no-op on Twine::Null.
|
||||||
|
|
||||||
|
size_t index(Twine* p) const;
|
||||||
void retain(Twine::Id id);
|
void retain(Twine::Id id);
|
||||||
void release(Twine::Id id);
|
void release(Twine::Id id);
|
||||||
uint32_t refcount(Twine::Id id) const;
|
uint32_t refcount(Twine::Id id) const;
|
||||||
bool is_alive(Twine::Id id) const;
|
bool is_alive(Twine::Id id) const;
|
||||||
|
|
||||||
|
// Quick character queries on any flat node — avoids materializing the
|
||||||
|
// full string for the common `name[0] == '$'` / `.isPublic()` tests.
|
||||||
|
char first_char(Twine::Id id) const;
|
||||||
|
bool is_public(Twine::Id id) const { return first_char(id) == '\\'; }
|
||||||
|
|
||||||
// Materialize a Twine to the pipe-separated flat string used by the
|
// Materialize a Twine to the pipe-separated flat string used by the
|
||||||
// existing src attribute convention. Leaves visit in left-to-right DFS
|
// existing src attribute convention. Leaves visit in left-to-right DFS
|
||||||
// order; duplicate leaves are skipped to match `pool`-style semantics.
|
// order; duplicate leaves are skipped to match `pool`-style semantics.
|
||||||
@@ -105,16 +129,13 @@ public:
|
|||||||
|
|
||||||
// Format an interned Id as the canonical src-attribute reference "@N".
|
// Format an interned Id as the canonical src-attribute reference "@N".
|
||||||
// Twine::Null formats as the empty string.
|
// Twine::Null formats as the empty string.
|
||||||
static std::string format_ref(Twine::Id id);
|
std::string format_ref(Twine::Id id) const;
|
||||||
|
|
||||||
// Parse an "@N" reference back to an Id. Returns Twine::Null if `s` is
|
// Parse an "@N" reference back to an Id
|
||||||
// not exactly "@" followed by one or more decimal digits — so legacy
|
static std::optional<size_t> parse_ref(std::string_view s);
|
||||||
// literal src strings (which always contain ':' separators and have no
|
Twine::Id get_ref(std::string_view s);
|
||||||
// reason to start with '@') are passed through unrecognized.
|
|
||||||
static Twine::Id parse_ref(std::string_view s);
|
|
||||||
|
|
||||||
// Lookup. Bounds-checked: out-of-range Id triggers log_assert via op.
|
const Twine &operator[](Twine::Id id) const { return *id; }
|
||||||
const Twine &operator[](Twine::Id id) const { return nodes_.at(id); }
|
|
||||||
|
|
||||||
size_t size() const { return nodes_.size(); }
|
size_t size() const { return nodes_.size(); }
|
||||||
size_t leaf_count() const { return leaf_index_.size(); }
|
size_t leaf_count() const { return leaf_index_.size(); }
|
||||||
@@ -143,101 +164,243 @@ public:
|
|||||||
// Iterate every live (non-tombstoned) node. fn is `void(Twine::Id, const Twine&)`.
|
// Iterate every live (non-tombstoned) node. fn is `void(Twine::Id, const Twine&)`.
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
void for_each_live(Fn fn) const {
|
void for_each_live(Fn fn) const {
|
||||||
for (size_t i = 0; i < nodes_.size(); i++) {
|
for (auto& n : nodes_) {
|
||||||
const Twine &n = nodes_[i];
|
|
||||||
if (n.is_dead())
|
if (n.is_dead())
|
||||||
continue;
|
continue;
|
||||||
fn(static_cast<Twine::Id>(i), n);
|
fn(&n, n); // TODO de-stupid this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Twine> nodes_;
|
std::vector<Twine> nodes_;
|
||||||
std::vector<uint32_t> refcount_;
|
std::vector<uint32_t> refcount_;
|
||||||
std::vector<Twine::Id> free_list_;
|
std::list<Twine::Id> free_list_;
|
||||||
dict<std::string, Twine::Id> leaf_index_;
|
|
||||||
dict<std::vector<Twine::Id>, Twine::Id> concat_index_;
|
// --- Intrusive dedup indexes (Step 0) -----------------------------------
|
||||||
dict<std::pair<Twine::Id, std::string>, Twine::Id> suffix_index_;
|
// Each set stores only the Twine::Id; hash/eq functors reach into
|
||||||
|
// nodes_[id] for the keying data. This avoids the duplicate-string cost
|
||||||
|
// of the old dict<std::string, Twine::Id> approach.
|
||||||
|
// All functors hold a raw pointer to *this; TwinePool is non-movable
|
||||||
|
// and copy-assignment rebuilds the sets from scratch so the pointer
|
||||||
|
// always stays valid.
|
||||||
|
|
||||||
|
using SuffixKey = std::pair<Twine::Id, std::string_view>;
|
||||||
|
|
||||||
|
struct LeafHash {
|
||||||
|
using is_transparent = void;
|
||||||
|
const TwinePool *pool;
|
||||||
|
size_t operator()(Twine::Id id) const noexcept {
|
||||||
|
return std::hash<std::string_view>{}(id->leaf());
|
||||||
|
}
|
||||||
|
size_t operator()(std::string_view sv) const noexcept {
|
||||||
|
return std::hash<std::string_view>{}(sv);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct LeafEq {
|
||||||
|
using is_transparent = void;
|
||||||
|
const TwinePool *pool;
|
||||||
|
bool operator()(Twine::Id a, Twine::Id b) const noexcept {
|
||||||
|
return a->leaf() == b->leaf();
|
||||||
|
}
|
||||||
|
bool operator()(Twine::Id id, std::string_view sv) const noexcept {
|
||||||
|
return id->leaf() == sv;
|
||||||
|
}
|
||||||
|
bool operator()(std::string_view sv, Twine::Id id) const noexcept {
|
||||||
|
return sv == id->leaf();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct SuffixHash {
|
||||||
|
using is_transparent = void;
|
||||||
|
const TwinePool *pool;
|
||||||
|
static size_t combine(size_t a, size_t b) noexcept {
|
||||||
|
return a ^ (b + 0x9e3779b9u + (a << 6) + (a >> 2));
|
||||||
|
}
|
||||||
|
size_t operator()(Twine::Id id) const noexcept {
|
||||||
|
const auto &s = id->suffix();
|
||||||
|
return combine(std::hash<Twine::Id>{}(s.prefix),
|
||||||
|
std::hash<std::string_view>{}(s.tail));
|
||||||
|
}
|
||||||
|
size_t operator()(SuffixKey k) const noexcept {
|
||||||
|
return combine(std::hash<Twine::Id>{}(k.first),
|
||||||
|
std::hash<std::string_view>{}(k.second));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct SuffixEq {
|
||||||
|
using is_transparent = void;
|
||||||
|
const TwinePool *pool;
|
||||||
|
bool operator()(Twine::Id a, Twine::Id b) const noexcept {
|
||||||
|
const auto &sa = a->suffix();
|
||||||
|
const auto &sb = b->suffix();
|
||||||
|
return sa.prefix == sb.prefix && sa.tail == sb.tail;
|
||||||
|
}
|
||||||
|
bool operator()(Twine::Id id, SuffixKey k) const noexcept {
|
||||||
|
const auto &s = id->suffix();
|
||||||
|
return s.prefix == k.first && s.tail == k.second;
|
||||||
|
}
|
||||||
|
bool operator()(SuffixKey k, Twine::Id id) const noexcept {
|
||||||
|
return (*this)(id, k);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct ConcatHash {
|
||||||
|
using is_transparent = void;
|
||||||
|
const TwinePool *pool;
|
||||||
|
static size_t hash_ids(std::span<const Twine::Id> v) noexcept {
|
||||||
|
size_t h = 0;
|
||||||
|
for (Twine::Id c : v)
|
||||||
|
h ^= std::hash<Twine::Id>{}(c) + 0x9e3779b9u + (h << 6) + (h >> 2);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
size_t operator()(Twine::Id id) const noexcept {
|
||||||
|
return hash_ids(id->children());
|
||||||
|
}
|
||||||
|
size_t operator()(std::span<const Twine::Id> v) const noexcept {
|
||||||
|
return hash_ids(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct ConcatEq {
|
||||||
|
using is_transparent = void;
|
||||||
|
const TwinePool *pool;
|
||||||
|
bool operator()(Twine::Id a, Twine::Id b) const noexcept {
|
||||||
|
return a->children() == b->children();
|
||||||
|
}
|
||||||
|
bool operator()(Twine::Id id, std::span<const Twine::Id> v) const noexcept {
|
||||||
|
const auto &ch = id->children();
|
||||||
|
return ch.size() == v.size() &&
|
||||||
|
std::equal(ch.begin(), ch.end(), v.begin());
|
||||||
|
}
|
||||||
|
bool operator()(std::span<const Twine::Id> v, Twine::Id id) const noexcept {
|
||||||
|
return (*this)(id, v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_set<Twine::Id, LeafHash, LeafEq> leaf_index_;
|
||||||
|
std::unordered_set<Twine::Id, SuffixHash, SuffixEq> suffix_index_;
|
||||||
|
std::unordered_set<Twine::Id, ConcatHash, ConcatEq> concat_index_;
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
Twine::Id alloc_slot_(Twine &&node);
|
Twine::Id alloc_slot_(Twine &&node);
|
||||||
void destroy_slot_(Twine::Id id);
|
void destroy_slot_(Twine::Id id);
|
||||||
void collect_leaves(Twine::Id id, pool<std::string> &out) const;
|
void collect_leaves(Twine::Id id, pool<std::string> &out) const;
|
||||||
// Materialize a flat node (Leaf or Suffix) into its full string.
|
// Materialize a flat node (Leaf or Suffix) into its full string.
|
||||||
std::string flat_string_(Twine::Id id) const;
|
std::string flat_string_(Twine::Id id) const;
|
||||||
|
// Populate the three indexes from the current nodes_ vector (used by
|
||||||
|
// the copy constructor/assignment and by gc()).
|
||||||
|
void rebuild_indexes_();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Owning reference to a Twine slot. Retains on construction (and on copy
|
// // Owning reference to a Twine slot. Retains on construction (and on copy
|
||||||
// of a non-empty ref), releases on destruction. Use this in transient
|
// // of a non-empty ref), releases on destruction. Use this in transient
|
||||||
// container types — FfData, Mem helpers — that need to keep a src_id_
|
// // container types — FfData, Mem helpers — that need to keep a src_id_
|
||||||
// alive across destruction of the original AttrObject that minted it,
|
// // alive across destruction of the original AttrObject that minted it,
|
||||||
// without having to fall back to a flattened path-string stash.
|
// // without having to fall back to a flattened path-string stash.
|
||||||
//
|
// //
|
||||||
// Empty (no pool/no id) by default. A non-empty ref always carries a
|
// // Empty (no pool/no id) by default. A non-empty ref always carries a
|
||||||
// non-null pool and a live id.
|
// // non-null pool and a live id.
|
||||||
class OwnedTwine
|
// class OwnedTwine
|
||||||
{
|
// {
|
||||||
public:
|
// public:
|
||||||
OwnedTwine() = default;
|
// OwnedTwine() = default;
|
||||||
|
|
||||||
// Adopt the +1 reference returned by `intern` / `concat` / `intern_suffix`
|
// // Adopt the +1 reference returned by `intern` / `concat` / `intern_suffix`
|
||||||
// / `copy_from`. Use OwnedTwine(pool, id, retain=true) when copying an
|
// // / `copy_from`. Use OwnedTwine(pool, id, retain=true) when copying an
|
||||||
// id already held elsewhere (e.g. another AttrObject's src_id_).
|
// // id already held elsewhere (e.g. another AttrObject's src_id_).
|
||||||
OwnedTwine(TwinePool *pool, Twine::Id id, bool retain = true) : pool_(pool), id_(id) {
|
// OwnedTwine(TwinePool *pool, Twine::Id id, bool retain = true) : pool_(pool), id_(id) {
|
||||||
if (retain && pool_ && id_ != Twine::Null)
|
// if (retain && pool_ && id_ != Twine::Null)
|
||||||
pool_->retain(id_);
|
// pool_->retain(id_);
|
||||||
}
|
// }
|
||||||
|
|
||||||
OwnedTwine(const OwnedTwine &other) : pool_(other.pool_), id_(other.id_) {
|
// OwnedTwine(const OwnedTwine &other) : pool_(other.pool_), id_(other.id_) {
|
||||||
if (pool_ && id_ != Twine::Null)
|
// if (pool_ && id_ != Twine::Null)
|
||||||
pool_->retain(id_);
|
// pool_->retain(id_);
|
||||||
}
|
// }
|
||||||
|
|
||||||
OwnedTwine(OwnedTwine &&other) noexcept : pool_(other.pool_), id_(other.id_) {
|
// OwnedTwine(OwnedTwine &&other) noexcept : pool_(other.pool_), id_(other.id_) {
|
||||||
other.pool_ = nullptr;
|
// other.pool_ = nullptr;
|
||||||
other.id_ = Twine::Null;
|
// other.id_ = Twine::Null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
OwnedTwine &operator=(const OwnedTwine &other) {
|
// OwnedTwine &operator=(const OwnedTwine &other) {
|
||||||
if (this == &other)
|
// if (this == &other)
|
||||||
return *this;
|
// return *this;
|
||||||
release_();
|
// release_();
|
||||||
pool_ = other.pool_;
|
// pool_ = other.pool_;
|
||||||
id_ = other.id_;
|
// id_ = other.id_;
|
||||||
if (pool_ && id_ != Twine::Null)
|
// if (pool_ && id_ != Twine::Null)
|
||||||
pool_->retain(id_);
|
// pool_->retain(id_);
|
||||||
return *this;
|
// return *this;
|
||||||
}
|
// }
|
||||||
|
|
||||||
OwnedTwine &operator=(OwnedTwine &&other) noexcept {
|
// OwnedTwine &operator=(OwnedTwine &&other) noexcept {
|
||||||
if (this == &other)
|
// if (this == &other)
|
||||||
return *this;
|
// return *this;
|
||||||
release_();
|
// release_();
|
||||||
pool_ = other.pool_;
|
// pool_ = other.pool_;
|
||||||
id_ = other.id_;
|
// id_ = other.id_;
|
||||||
other.pool_ = nullptr;
|
// other.pool_ = nullptr;
|
||||||
other.id_ = Twine::Null;
|
// other.id_ = Twine::Null;
|
||||||
return *this;
|
// return *this;
|
||||||
}
|
// }
|
||||||
|
|
||||||
~OwnedTwine() { release_(); }
|
// ~OwnedTwine() { release_(); }
|
||||||
|
|
||||||
void reset() {
|
// void reset() {
|
||||||
release_();
|
// release_();
|
||||||
pool_ = nullptr;
|
// pool_ = nullptr;
|
||||||
id_ = Twine::Null;
|
// id_ = Twine::Null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
TwinePool *pool() const { return pool_; }
|
// TwinePool *pool() const { return pool_; }
|
||||||
Twine::Id id() const { return id_; }
|
// Twine::Id id() const { return id_; }
|
||||||
bool empty() const { return id_ == Twine::Null; }
|
// bool empty() const { return id_ == Twine::Null; }
|
||||||
|
|
||||||
|
// private:
|
||||||
|
// TwinePool *pool_ = nullptr;
|
||||||
|
// Twine::Id id_ = Twine::Null;
|
||||||
|
|
||||||
|
// void release_() {
|
||||||
|
// if (pool_ && id_ != Twine::Null)
|
||||||
|
// pool_->release(id_);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
struct TwinePoolExtender {
|
||||||
|
TwinePool& pool;
|
||||||
|
size_t offset;
|
||||||
private:
|
private:
|
||||||
TwinePool *pool_ = nullptr;
|
size_t resize_for_idx(size_t idx) {
|
||||||
Twine::Id id_ = Twine::Null;
|
auto real_idx = offset + idx;
|
||||||
|
pool.nodes_.resize(std::max(pool.nodes_.size(), real_idx + 1));
|
||||||
void release_() {
|
return real_idx;
|
||||||
if (pool_ && id_ != Twine::Null)
|
}
|
||||||
pool_->release(id_);
|
void commit(Twine&& twine, size_t idx) {
|
||||||
|
pool.nodes_[idx] = std::move(twine);
|
||||||
|
pool.leaf_index_.insert(&pool.nodes_[idx]);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// TwinePoolExtender(Design* design) : pool(design->twines), offset(design->twines.size()) {}
|
||||||
|
void extend_leaf(std::string leaf, size_t idx) {
|
||||||
|
auto real_idx = resize_for_idx(idx);
|
||||||
|
commit(Twine(leaf), real_idx);
|
||||||
|
}
|
||||||
|
void extend_concat(std::vector<size_t> children, size_t idx) {
|
||||||
|
auto real_idx = resize_for_idx(idx);
|
||||||
|
Twine* first = &pool.nodes_.front() + offset;
|
||||||
|
std::vector<Twine*> real_children;
|
||||||
|
real_children.reserve(children.size());
|
||||||
|
for (auto child : children)
|
||||||
|
real_children.push_back(first + child);
|
||||||
|
commit(Twine(std::move(real_children)), real_idx);
|
||||||
|
}
|
||||||
|
void extend_suffix(size_t prefix, std::string tail, size_t idx) {
|
||||||
|
auto real_idx = resize_for_idx(idx);
|
||||||
|
Twine* first = &pool.nodes_.front() + offset;
|
||||||
|
Twine* real_prefix = first + prefix;
|
||||||
|
commit(Twine(Twine::Suffix(real_prefix, std::move(tail))), real_idx);
|
||||||
|
}
|
||||||
|
void finish() {
|
||||||
|
for (size_t i = offset; i < pool.nodes_.size(); i++)
|
||||||
|
if (pool.nodes_[i].is_dead())
|
||||||
|
pool.free_list_.push_back(&pool.nodes_[i]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Wire* Patch::addWire(IdString name, int width) {
|
|||||||
wires_.push_back(std::make_unique<Wire>(Wire::ConstructToken{}));
|
wires_.push_back(std::make_unique<Wire>(Wire::ConstructToken{}));
|
||||||
|
|
||||||
Wire* wire = wires_.back().get();
|
Wire* wire = wires_.back().get();
|
||||||
wire->name = name;
|
staged_wire_names_[wire] = name;
|
||||||
wire->width = width;
|
wire->width = width;
|
||||||
wire->module = nullptr;
|
wire->module = nullptr;
|
||||||
return wire;
|
return wire;
|
||||||
@@ -48,7 +48,12 @@ RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *othe
|
|||||||
|
|
||||||
Wire* Patch::commit_wire(std::unique_ptr<Wire> wire) {
|
Wire* Patch::commit_wire(std::unique_ptr<Wire> wire) {
|
||||||
Wire* raw = wire.release();
|
Wire* raw = wire.release();
|
||||||
mod->wires_[raw->name] = raw;
|
IdString name = staged_wire_names_.at(raw);
|
||||||
|
staged_wire_names_.erase(raw);
|
||||||
|
Twine::Id id = mod->design->twines.intern(name.str());
|
||||||
|
mod->design->obj_set_name_id(raw, id);
|
||||||
|
mod->design->twines.release(id);
|
||||||
|
mod->wires_[raw->meta_->name_id] = raw;
|
||||||
raw->module = mod;
|
raw->module = mod;
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
@@ -57,9 +62,11 @@ Cell* Patch::commit_cell(std::unique_ptr<Cell> cell) {
|
|||||||
Cell* raw = cell.release();
|
Cell* raw = cell.release();
|
||||||
IdString name = staged_cell_names_.at(raw);
|
IdString name = staged_cell_names_.at(raw);
|
||||||
staged_cell_names_.erase(raw);
|
staged_cell_names_.erase(raw);
|
||||||
raw->name = name;
|
Twine::Id id = mod->design->twines.intern(name.str());
|
||||||
|
mod->design->obj_set_name_id(raw, id);
|
||||||
|
mod->design->twines.release(id);
|
||||||
raw->module = mod;
|
raw->module = mod;
|
||||||
mod->cells_[name] = raw;
|
mod->cells_[raw->meta_->name_id] = raw;
|
||||||
raw->initIndex();
|
raw->initIndex();
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
@@ -87,7 +94,7 @@ namespace {
|
|||||||
if (!mod || !mod->design)
|
if (!mod || !mod->design)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TwinePool& pool = mod->design->src_twines;
|
TwinePool& pool = mod->design->twines;
|
||||||
std::vector<Twine::Id> ids;
|
std::vector<Twine::Id> ids;
|
||||||
ids.reserve(2 + extras.size());
|
ids.reserve(2 + extras.size());
|
||||||
auto push = [&](Cell *c) {
|
auto push = [&](Cell *c) {
|
||||||
@@ -103,7 +110,7 @@ namespace {
|
|||||||
Twine::Id merged = pool.concat(std::span<const Twine::Id>{ids});
|
Twine::Id merged = pool.concat(std::span<const Twine::Id>{ids});
|
||||||
if (ys_debug()) {
|
if (ys_debug()) {
|
||||||
log_debug("twine: merge yields %s (pool size %zu)\n",
|
log_debug("twine: merge yields %s (pool size %zu)\n",
|
||||||
TwinePool::format_ref(merged).c_str(), pool.size());
|
pool.format_ref(merged).c_str(), pool.size());
|
||||||
if (ys_debug(2))
|
if (ys_debug(2))
|
||||||
pool.dump("twine pool state");
|
pool.dump("twine pool state");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
vector<std::unique_ptr<Wire>> wires_ = {};
|
vector<std::unique_ptr<Wire>> wires_ = {};
|
||||||
vector<std::unique_ptr<Cell>> cells_ = {};
|
vector<std::unique_ptr<Cell>> cells_ = {};
|
||||||
dict<RTLIL::Cell*, RTLIL::IdString> staged_cell_names_;
|
dict<RTLIL::Cell*, RTLIL::IdString> staged_cell_names_;
|
||||||
|
dict<RTLIL::Wire*, RTLIL::IdString> staged_wire_names_;
|
||||||
|
|
||||||
void connect(const RTLIL::SigSig &conn);
|
void connect(const RTLIL::SigSig &conn);
|
||||||
void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs);
|
void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs);
|
||||||
|
|||||||
+1
-1
@@ -369,7 +369,7 @@ const char *create_prompt(RTLIL::Design *design, int recursion_counter)
|
|||||||
if (design->selected_active_module.empty())
|
if (design->selected_active_module.empty())
|
||||||
str += "*";
|
str += "*";
|
||||||
else if (design->selection().selected_modules.size() != 1 || design->selection().selected_members.size() != 0 ||
|
else if (design->selection().selected_modules.size() != 1 || design->selection().selected_members.size() != 0 ||
|
||||||
design->selection().selected_modules.count(design->selected_active_module) == 0)
|
design->selection().selected_modules.count(design->twines.intern(design->selected_active_module)) == 0)
|
||||||
str += "*";
|
str += "*";
|
||||||
}
|
}
|
||||||
snprintf(buffer, 100, "%s> ", str.c_str());
|
snprintf(buffer, 100, "%s> ", str.c_str());
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ struct CheckPass : public Pass {
|
|||||||
SigBit to = sigmap(to_portsig[to_bit]);
|
SigBit to = sigmap(to_portsig[to_bit]);
|
||||||
|
|
||||||
if (from.wire && to.wire)
|
if (from.wire && to.wire)
|
||||||
topo.edge(std::make_pair(from.wire->name, from.offset), std::make_pair(to.wire->name, to.offset));
|
topo.edge(std::make_pair(RTLIL::IdString(from.wire->name), from.offset), std::make_pair(RTLIL::IdString(to.wire->name), to.offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool detail_costly(Cell *cell) {
|
bool detail_costly(Cell *cell) {
|
||||||
@@ -338,14 +338,14 @@ struct CheckPass : public Pass {
|
|||||||
if (cell->input(conn.first))
|
if (cell->input(conn.first))
|
||||||
for (auto bit : sigmap(conn.second))
|
for (auto bit : sigmap(conn.second))
|
||||||
if (bit.wire)
|
if (bit.wire)
|
||||||
topo.edge(std::make_pair(bit.wire->name, bit.offset),
|
topo.edge(std::make_pair(RTLIL::IdString(bit.wire->name), bit.offset),
|
||||||
std::make_pair(cell->name, -1));
|
std::make_pair(RTLIL::IdString(cell->name), -1));
|
||||||
|
|
||||||
if (cell->output(conn.first))
|
if (cell->output(conn.first))
|
||||||
for (auto bit : sigmap(conn.second))
|
for (auto bit : sigmap(conn.second))
|
||||||
if (bit.wire)
|
if (bit.wire)
|
||||||
topo.edge(std::make_pair(cell->name, -1),
|
topo.edge(std::make_pair(RTLIL::IdString(cell->name), -1),
|
||||||
std::make_pair(bit.wire->name, bit.offset));
|
std::make_pair(RTLIL::IdString(bit.wire->name), bit.offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return false to signify the fallback
|
// Return false to signify the fallback
|
||||||
|
|||||||
+22
-14
@@ -104,14 +104,18 @@ public:
|
|||||||
void check_wires()
|
void check_wires()
|
||||||
{
|
{
|
||||||
for (const auto &it : mod_a->wires_) {
|
for (const auto &it : mod_a->wires_) {
|
||||||
if (mod_b->wires_.count(it.first) == 0)
|
RTLIL::IdString wname(it.second->name);
|
||||||
error("Module %s missing wire %s in second design.\n", mod_a->name.unescape(), it.first.unescape());
|
RTLIL::Wire *wb = mod_b->wire(wname);
|
||||||
if (std::string mismatch = compare_wires(it.second, mod_b->wires_.at(it.first)); !mismatch.empty())
|
if (!wb)
|
||||||
error("Module %s wire %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch);
|
error("Module %s missing wire %s in second design.\n", mod_a->name.unescape(), wname.unescape());
|
||||||
|
else if (std::string mismatch = compare_wires(it.second, wb); !mismatch.empty())
|
||||||
|
error("Module %s wire %s %s.\n", mod_a->name.unescape(), wname.unescape(), mismatch);
|
||||||
|
}
|
||||||
|
for (const auto &it : mod_b->wires_) {
|
||||||
|
RTLIL::IdString wname(it.second->name);
|
||||||
|
if (!mod_a->wire(wname))
|
||||||
|
error("Module %s missing wire %s in first design.\n", mod_b->name.unescape(), wname.unescape());
|
||||||
}
|
}
|
||||||
for (const auto &it : mod_b->wires_)
|
|
||||||
if (mod_a->wires_.count(it.first) == 0)
|
|
||||||
error("Module %s missing wire %s in first design.\n", mod_b->name.unescape(), it.first.unescape());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string compare_memories(const RTLIL::Memory *a, const RTLIL::Memory *b)
|
std::string compare_memories(const RTLIL::Memory *a, const RTLIL::Memory *b)
|
||||||
@@ -164,14 +168,18 @@ public:
|
|||||||
void check_cells()
|
void check_cells()
|
||||||
{
|
{
|
||||||
for (const auto &it : mod_a->cells_) {
|
for (const auto &it : mod_a->cells_) {
|
||||||
if (mod_b->cells_.count(it.first) == 0)
|
RTLIL::IdString cname(it.second->name);
|
||||||
error("Module %s missing cell %s in second design.\n", mod_a->name.unescape(), it.first.unescape());
|
RTLIL::Cell *cb = mod_b->cell(cname);
|
||||||
if (std::string mismatch = compare_cells(it.second, mod_b->cells_.at(it.first)); !mismatch.empty())
|
if (!cb)
|
||||||
error("Module %s cell %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch);
|
error("Module %s missing cell %s in second design.\n", mod_a->name.unescape(), cname.unescape());
|
||||||
|
else if (std::string mismatch = compare_cells(it.second, cb); !mismatch.empty())
|
||||||
|
error("Module %s cell %s %s.\n", mod_a->name.unescape(), cname.unescape(), mismatch);
|
||||||
|
}
|
||||||
|
for (const auto &it : mod_b->cells_) {
|
||||||
|
RTLIL::IdString cname(it.second->name);
|
||||||
|
if (!mod_a->cell(cname))
|
||||||
|
error("Module %s missing cell %s in first design.\n", mod_b->name.unescape(), cname.unescape());
|
||||||
}
|
}
|
||||||
for (const auto &it : mod_b->cells_)
|
|
||||||
if (mod_a->cells_.count(it.first) == 0)
|
|
||||||
error("Module %s missing cell %s in first design.\n", mod_b->name.unescape(), it.first.unescape());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_memories()
|
void check_memories()
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct DumpTwinesPass : public Pass {
|
|||||||
log("\n");
|
log("\n");
|
||||||
log(" dump_twines [-flat]\n");
|
log(" dump_twines [-flat]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Print every node in design->src_twines. Leaves show the literal\n");
|
log("Print every node in design->twines. Leaves show the literal\n");
|
||||||
log("path:line.col string, concats show their child id list. With\n");
|
log("path:line.col string, concats show their child id list. With\n");
|
||||||
log("-flat each concat is additionally rendered as the pipe-joined\n");
|
log("-flat each concat is additionally rendered as the pipe-joined\n");
|
||||||
log("flat string a backend would emit.\n");
|
log("flat string a backend would emit.\n");
|
||||||
@@ -39,7 +39,7 @@ struct DumpTwinesPass : public Pass {
|
|||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
const TwinePool &pool = design->src_twines;
|
const TwinePool &pool = design->twines;
|
||||||
log("twine pool: %zu nodes (%zu leaves, %zu suffixes, %zu concats)\n",
|
log("twine pool: %zu nodes (%zu leaves, %zu suffixes, %zu concats)\n",
|
||||||
pool.size(), pool.leaf_count(), pool.suffix_count(), pool.concat_count());
|
pool.size(), pool.leaf_count(), pool.suffix_count(), pool.concat_count());
|
||||||
pool.for_each_live([&](Twine::Id id, const Twine &n) {
|
pool.for_each_live([&](Twine::Id id, const Twine &n) {
|
||||||
@@ -82,7 +82,7 @@ struct GcTwinesPass : public Pass {
|
|||||||
log(" gc_twines\n");
|
log(" gc_twines\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Walk the design, collect every \"@N\" referenced by any cell, wire,\n");
|
log("Walk the design, collect every \"@N\" referenced by any cell, wire,\n");
|
||||||
log("module, memory, or process attribute, and rebuild design->src_twines\n");
|
log("module, memory, or process attribute, and rebuild design->twines\n");
|
||||||
log("to contain only those entries plus their transitive leaf children.\n");
|
log("to contain only those entries plus their transitive leaf children.\n");
|
||||||
log("Cell src attributes are rewritten in place via the resulting id\n");
|
log("Cell src attributes are rewritten in place via the resulting id\n");
|
||||||
log("remap, so the design is unchanged at the path:line.col layer.\n");
|
log("remap, so the design is unchanged at the path:line.col layer.\n");
|
||||||
@@ -98,10 +98,10 @@ struct GcTwinesPass : public Pass {
|
|||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
extra_args(args, 1, design);
|
extra_args(args, 1, design);
|
||||||
size_t before = design->src_twines.size();
|
size_t before = design->twines.size();
|
||||||
size_t freed = design->gc_twines();
|
size_t freed = design->gc_twines();
|
||||||
log("twine gc: %zu nodes -> %zu (%zu freed)\n",
|
log("twine gc: %zu nodes -> %zu (%zu freed)\n",
|
||||||
before, design->src_twines.size(), freed);
|
before, design->twines.size(), freed);
|
||||||
}
|
}
|
||||||
} GcTwinesPass;
|
} GcTwinesPass;
|
||||||
|
|
||||||
|
|||||||
@@ -239,12 +239,12 @@ static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int c
|
|||||||
|
|
||||||
for (auto cell : mod->cells()) {
|
for (auto cell : mod->cells()) {
|
||||||
if (lhs.selected_member(mod->name, cell->name))
|
if (lhs.selected_member(mod->name, cell->name))
|
||||||
objects.push_back(make_pair(RTLIL::IdString(mod->name), cell->name));
|
objects.push_back(make_pair(RTLIL::IdString(mod->name), RTLIL::IdString(cell->name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto wire : mod->wires()) {
|
for (auto wire : mod->wires()) {
|
||||||
if (lhs.selected_member(mod->name, wire->name))
|
if (lhs.selected_member(mod->name, wire->name))
|
||||||
objects.push_back(make_pair(RTLIL::IdString(mod->name), wire->name));
|
objects.push_back(make_pair(RTLIL::IdString(mod->name), RTLIL::IdString(wire->name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1792,7 +1792,7 @@ static void log_matches(const char *title, Module *module, const T &list)
|
|||||||
|
|
||||||
for (auto &it : list)
|
for (auto &it : list)
|
||||||
if (module->selected(it.second))
|
if (module->selected(it.second))
|
||||||
matches.push_back(it.first);
|
matches.push_back(RTLIL::IdString(it.second->name));
|
||||||
|
|
||||||
if (!matches.empty()) {
|
if (!matches.empty()) {
|
||||||
log("\n%d %s:\n", int(matches.size()), title);
|
log("\n%d %s:\n", int(matches.size()), title);
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ struct XpropWorker
|
|||||||
auto sig_a = cell->getPort(ID::A);
|
auto sig_a = cell->getPort(ID::A);
|
||||||
auto sig_b = cell->getPort(ID::B);
|
auto sig_b = cell->getPort(ID::B);
|
||||||
|
|
||||||
auto name = cell->name;
|
RTLIL::IdString name(cell->name);
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
module->addXnor(name, sig_a, sig_b, sig_y);
|
module->addXnor(name, sig_a, sig_b, sig_y);
|
||||||
return;
|
return;
|
||||||
@@ -497,7 +497,7 @@ struct XpropWorker
|
|||||||
auto sig_a = cell->getPort(ID::A);
|
auto sig_a = cell->getPort(ID::A);
|
||||||
auto sig_b = cell->getPort(ID::B);
|
auto sig_b = cell->getPort(ID::B);
|
||||||
|
|
||||||
auto name = cell->name;
|
RTLIL::IdString name(cell->name);
|
||||||
auto type = cell->type;
|
auto type = cell->type;
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
if (type == ID($eqx))
|
if (type == ID($eqx))
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ struct EquivMiterWorker
|
|||||||
vector<SigChunk> chunks = sig.chunks();
|
vector<SigChunk> chunks = sig.chunks();
|
||||||
for (auto &c : chunks)
|
for (auto &c : chunks)
|
||||||
if (c.wire != NULL)
|
if (c.wire != NULL)
|
||||||
c.wire = mod->wires_.at(c.wire->name);
|
c.wire = mod->wire(RTLIL::IdString(c.wire->name));
|
||||||
sig = chunks;
|
sig = chunks;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL
|
|||||||
|
|
||||||
for (auto &cellport : cellport_list)
|
for (auto &cellport : cellport_list)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = module->cells_.at(cellport.first);
|
RTLIL::Cell *cell = module->cell(cellport.first);
|
||||||
if ((cell->type != ID($mux) && cell->type != ID($pmux)) || cellport.second != ID::Y) {
|
if ((cell->type != ID($mux) && cell->type != ID($pmux)) || cellport.second != ID::Y) {
|
||||||
log(" unexpected cell type %s (%s) found in state selection tree.\n", cell->type, cell->name);
|
log(" unexpected cell type %s (%s) found in state selection tree.\n", cell->type, cell->name);
|
||||||
return false;
|
return false;
|
||||||
@@ -271,7 +271,7 @@ static void extract_fsm(RTLIL::Wire *wire)
|
|||||||
std::set<sig2driver_entry_t> cellport_list;
|
std::set<sig2driver_entry_t> cellport_list;
|
||||||
sig2driver.find(dff_out, cellport_list);
|
sig2driver.find(dff_out, cellport_list);
|
||||||
for (auto &cellport : cellport_list) {
|
for (auto &cellport : cellport_list) {
|
||||||
RTLIL::Cell *cell = module->cells_.at(cellport.first);
|
RTLIL::Cell *cell = module->cell(cellport.first);
|
||||||
if ((cell->type != ID($dff) && cell->type != ID($adff)) || cellport.second != ID::Q)
|
if ((cell->type != ID($dff) && cell->type != ID($adff)) || cellport.second != ID::Q)
|
||||||
continue;
|
continue;
|
||||||
log(" found %s cell for state register: %s\n", cell->type, cell->name);
|
log(" found %s cell for state register: %s\n", cell->type, cell->name);
|
||||||
@@ -319,7 +319,7 @@ static void extract_fsm(RTLIL::Wire *wire)
|
|||||||
cellport_list.clear();
|
cellport_list.clear();
|
||||||
sig2trigger.find(dff_out, cellport_list);
|
sig2trigger.find(dff_out, cellport_list);
|
||||||
for (auto &cellport : cellport_list) {
|
for (auto &cellport : cellport_list) {
|
||||||
RTLIL::Cell *cell = module->cells_.at(cellport.first);
|
RTLIL::Cell *cell = module->cell(cellport.first);
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b;
|
RTLIL::SigSpec sig_b;
|
||||||
if (cell->hasPort(ID::B))
|
if (cell->hasPort(ID::B))
|
||||||
@@ -388,10 +388,8 @@ static void extract_fsm(RTLIL::Wire *wire)
|
|||||||
|
|
||||||
// rename original state wire
|
// rename original state wire
|
||||||
|
|
||||||
module->wires_.erase(wire->name);
|
|
||||||
wire->attributes.erase(ID::fsm_encoding);
|
wire->attributes.erase(ID::fsm_encoding);
|
||||||
wire->name = stringf("$fsm$oldstate%s", wire->name);
|
module->rename(wire, stringf("$fsm$oldstate%s", wire->name.c_str()));
|
||||||
module->wires_[wire->name] = wire;
|
|
||||||
if(wire->attributes.count(ID::hdlname)) {
|
if(wire->attributes.count(ID::hdlname)) {
|
||||||
auto hdlname = wire->get_hdlname_attribute();
|
auto hdlname = wire->get_hdlname_attribute();
|
||||||
hdlname.pop_back();
|
hdlname.pop_back();
|
||||||
@@ -405,7 +403,7 @@ static void extract_fsm(RTLIL::Wire *wire)
|
|||||||
cellport_list.clear();
|
cellport_list.clear();
|
||||||
sig2driver.find(ctrl_out, cellport_list);
|
sig2driver.find(ctrl_out, cellport_list);
|
||||||
for (auto &cellport : cellport_list) {
|
for (auto &cellport : cellport_list) {
|
||||||
RTLIL::Cell *cell = module->cells_.at(cellport.first);
|
RTLIL::Cell *cell = module->cell(cellport.first);
|
||||||
RTLIL::SigSpec port_sig = assign_map(cell->getPort(cellport.second));
|
RTLIL::SigSpec port_sig = assign_map(cell->getPort(cellport.second));
|
||||||
RTLIL::SigSpec unconn_sig = port_sig.extract(ctrl_out);
|
RTLIL::SigSpec unconn_sig = port_sig.extract(ctrl_out);
|
||||||
RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%d", autoidx++), unconn_sig.size());
|
RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%d", autoidx++), unconn_sig.size());
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ struct MemoryMapWorker
|
|||||||
c->setPort(ID::D, w_in);
|
c->setPort(ID::D, w_in);
|
||||||
|
|
||||||
std::string w_out_name = stringf("%s[%d]", mem.memid, addr);
|
std::string w_out_name = stringf("%s[%d]", mem.memid, addr);
|
||||||
if (module->wires_.count(w_out_name) > 0)
|
if (module->wire(RTLIL::IdString(w_out_name)) != nullptr)
|
||||||
w_out_name = genid(mem.memid, "", addr, "$q");
|
w_out_name = genid(mem.memid, "", addr, "$q");
|
||||||
|
|
||||||
RTLIL::Wire *w_out = module->addWire(w_out_name, mem.width);
|
RTLIL::Wire *w_out = module->addWire(w_out_name, mem.width);
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ struct CutpointPass : public Pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::Cell *scopeinfo = nullptr;
|
RTLIL::Cell *scopeinfo = nullptr;
|
||||||
auto cell_name = cell->name;
|
RTLIL::IdString cell_name(cell->name);
|
||||||
if (flag_scopeinfo && cell_name.isPublic()) {
|
if (flag_scopeinfo && cell_name.isPublic()) {
|
||||||
auto scopeinfo = module->addCell(NEW_ID, ID($scopeinfo));
|
auto scopeinfo = module->addCell(NEW_ID, ID($scopeinfo));
|
||||||
scopeinfo->setParam(ID::TYPE, RTLIL::Const("blackbox"));
|
scopeinfo->setParam(ID::TYPE, RTLIL::Const("blackbox"));
|
||||||
|
|||||||
+14
-14
@@ -1298,8 +1298,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
SigBit D = mapped_cell->getPort(ID::D);
|
SigBit D = mapped_cell->getPort(ID::D);
|
||||||
SigBit Q = mapped_cell->getPort(ID::Q);
|
SigBit Q = mapped_cell->getPort(ID::Q);
|
||||||
if (D.wire)
|
if (D.wire)
|
||||||
D.wire = module->wires_.at(remap_name(D.wire->name));
|
D.wire = module->wire(remap_name(D.wire->name));
|
||||||
Q.wire = module->wires_.at(remap_name(Q.wire->name));
|
Q.wire = module->wire(remap_name(Q.wire->name));
|
||||||
module->connect(Q, D);
|
module->connect(Q, D);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1341,8 +1341,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
// If a driver couldn't be found (could be from PI or box CI)
|
// If a driver couldn't be found (could be from PI or box CI)
|
||||||
// then implement using a LUT
|
// then implement using a LUT
|
||||||
RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name)),
|
RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name)),
|
||||||
RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
|
RTLIL::SigBit(module->wire(remap_name(a_bit.wire->name)), a_bit.offset),
|
||||||
RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
|
RTLIL::SigBit(module->wire(remap_name(y_bit.wire->name)), y_bit.offset),
|
||||||
RTLIL::Const::from_string("01"));
|
RTLIL::Const::from_string("01"));
|
||||||
bit2sinks[cell->getPort(ID::A)].push_back(cell);
|
bit2sinks[cell->getPort(ID::A)].push_back(cell);
|
||||||
cell_stats[ID($lut)]++;
|
cell_stats[ID($lut)]++;
|
||||||
@@ -1365,7 +1365,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
continue;
|
continue;
|
||||||
//log_assert(c.width == 1);
|
//log_assert(c.width == 1);
|
||||||
if (c.wire)
|
if (c.wire)
|
||||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
c.wire = module->wire(remap_name(c.wire->name));
|
||||||
newsig.append(c);
|
newsig.append(c);
|
||||||
}
|
}
|
||||||
cell->setPort(mapped_conn.first, newsig);
|
cell->setPort(mapped_conn.first, newsig);
|
||||||
@@ -1392,9 +1392,9 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
SigBit I = mapped_cell->getPort(ID(i));
|
SigBit I = mapped_cell->getPort(ID(i));
|
||||||
SigBit O = mapped_cell->getPort(ID(o));
|
SigBit O = mapped_cell->getPort(ID(o));
|
||||||
if (I.wire)
|
if (I.wire)
|
||||||
I.wire = module->wires_.at(remap_name(I.wire->name));
|
I.wire = module->wire(remap_name(I.wire->name));
|
||||||
log_assert(O.wire);
|
log_assert(O.wire);
|
||||||
O.wire = module->wires_.at(remap_name(O.wire->name));
|
O.wire = module->wire(remap_name(O.wire->name));
|
||||||
module->connect(O, I);
|
module->connect(O, I);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1434,7 +1434,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
old_q = existing_cell->getPort(port_name);
|
old_q = existing_cell->getPort(port_name);
|
||||||
}
|
}
|
||||||
auto new_q = outputs[0];
|
auto new_q = outputs[0];
|
||||||
new_q.wire = module->wires_.at(remap_name(new_q.wire->name));
|
new_q.wire = module->wire(remap_name(new_q.wire->name));
|
||||||
module->connect(old_q, new_q);
|
module->connect(old_q, new_q);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1467,7 +1467,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
continue;
|
continue;
|
||||||
//log_assert(c.width == 1);
|
//log_assert(c.width == 1);
|
||||||
if (c.wire)
|
if (c.wire)
|
||||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
c.wire = module->wire(remap_name(c.wire->name));
|
||||||
newsig.append(c);
|
newsig.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1490,14 +1490,14 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
if (!conn.first.is_fully_const()) {
|
if (!conn.first.is_fully_const()) {
|
||||||
std::vector<RTLIL::SigChunk> chunks = conn.first.chunks();
|
std::vector<RTLIL::SigChunk> chunks = conn.first.chunks();
|
||||||
for (auto &c : chunks)
|
for (auto &c : chunks)
|
||||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
c.wire = module->wire(remap_name(c.wire->name));
|
||||||
conn.first = std::move(chunks);
|
conn.first = std::move(chunks);
|
||||||
}
|
}
|
||||||
if (!conn.second.is_fully_const()) {
|
if (!conn.second.is_fully_const()) {
|
||||||
std::vector<RTLIL::SigChunk> chunks = conn.second.chunks();
|
std::vector<RTLIL::SigChunk> chunks = conn.second.chunks();
|
||||||
for (auto &c : chunks)
|
for (auto &c : chunks)
|
||||||
if (c.wire)
|
if (c.wire)
|
||||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
c.wire = module->wire(remap_name(c.wire->name));
|
||||||
conn.second = std::move(chunks);
|
conn.second = std::move(chunks);
|
||||||
}
|
}
|
||||||
module->connect(conn);
|
module->connect(conn);
|
||||||
@@ -1564,8 +1564,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||||||
RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
|
RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
|
||||||
RTLIL::Const driver_mask;
|
RTLIL::Const driver_mask;
|
||||||
|
|
||||||
a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
|
a_bit.wire = module->wire(remap_name(a_bit.wire->name));
|
||||||
y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name));
|
y_bit.wire = module->wire(remap_name(y_bit.wire->name));
|
||||||
|
|
||||||
auto jt = bit2sinks.find(a_bit);
|
auto jt = bit2sinks.find(a_bit);
|
||||||
if (jt == bit2sinks.end())
|
if (jt == bit2sinks.end())
|
||||||
@@ -1614,7 +1614,7 @@ clone_lut:
|
|||||||
y_bit,
|
y_bit,
|
||||||
driver_mask);
|
driver_mask);
|
||||||
for (auto &bit : cell->connections_.at(ID::A)) {
|
for (auto &bit : cell->connections_.at(ID::A)) {
|
||||||
bit.wire = module->wires_.at(remap_name(bit.wire->name));
|
bit.wire = module->wire(remap_name(bit.wire->name));
|
||||||
bit2sinks[bit].push_back(cell);
|
bit2sinks[bit].push_back(cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,16 +145,16 @@ struct ClkbufmapPass : public Pass {
|
|||||||
auto wire = module->wire(port);
|
auto wire = module->wire(port);
|
||||||
if (wire->get_bool_attribute(ID::clkbuf_driver))
|
if (wire->get_bool_attribute(ID::clkbuf_driver))
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
if (wire->get_bool_attribute(ID::clkbuf_sink))
|
if (wire->get_bool_attribute(ID::clkbuf_sink))
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
sink_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
sink_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
auto it = wire->attributes.find(ID::clkbuf_inv);
|
auto it = wire->attributes.find(ID::clkbuf_inv);
|
||||||
if (it != wire->attributes.end()) {
|
if (it != wire->attributes.end()) {
|
||||||
IdString in_name = RTLIL::escape_id(it->second.decode_string());
|
IdString in_name = RTLIL::escape_id(it->second.decode_string());
|
||||||
for (int i = 0; i < GetSize(wire); i++) {
|
for (int i = 0; i < GetSize(wire); i++) {
|
||||||
inv_ports_out[make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i))] = make_pair(in_name, i);
|
inv_ports_out[make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i))] = make_pair(in_name, i);
|
||||||
inv_ports_in[make_pair(RTLIL::IdString(module->name), make_pair(in_name, i))] = make_pair(wire->name, i);
|
inv_ports_in[make_pair(RTLIL::IdString(module->name), make_pair(in_name, i))] = make_pair(RTLIL::IdString(wire->name), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ struct ClkbufmapPass : public Pass {
|
|||||||
// some buffer higher up in the hierarchy.
|
// some buffer higher up in the hierarchy.
|
||||||
if (wire->port_output)
|
if (wire->port_output)
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ struct ClkbufmapPass : public Pass {
|
|||||||
if (buf_wire_bits.count(mapped_wire_bit)) {
|
if (buf_wire_bits.count(mapped_wire_bit)) {
|
||||||
// Already buffered downstream. If this is an output, mark it.
|
// Already buffered downstream. If this is an output, mark it.
|
||||||
if (wire->port_output)
|
if (wire->port_output)
|
||||||
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
} else if (!sink_wire_bits.count(mapped_wire_bit)) {
|
} else if (!sink_wire_bits.count(mapped_wire_bit)) {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
} else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute(ID::top))) {
|
} else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute(ID::top))) {
|
||||||
@@ -288,7 +288,7 @@ struct ClkbufmapPass : public Pass {
|
|||||||
// A clock input in a submodule -- mark it, let higher level
|
// A clock input in a submodule -- mark it, let higher level
|
||||||
// worry about it.
|
// worry about it.
|
||||||
if (wire->port_input)
|
if (wire->port_input)
|
||||||
sink_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
sink_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!input_bits.empty()) {
|
if (!input_bits.empty()) {
|
||||||
@@ -320,7 +320,7 @@ struct ClkbufmapPass : public Pass {
|
|||||||
SigBit wire_bit(wire, i);
|
SigBit wire_bit(wire, i);
|
||||||
SigBit mapped_wire_bit = sigmap(wire_bit);
|
SigBit mapped_wire_bit = sigmap(wire_bit);
|
||||||
if (buffered_bits.count(mapped_wire_bit))
|
if (buffered_bits.count(mapped_wire_bit))
|
||||||
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module)
|
|||||||
for (auto cell : cell_list)
|
for (auto cell : cell_list)
|
||||||
{
|
{
|
||||||
auto cell_type = cell->type;
|
auto cell_type = cell->type;
|
||||||
auto cell_name = cell->name;
|
RTLIL::IdString cell_name(cell->name);
|
||||||
auto cell_connections = cell->connections();
|
auto cell_connections = cell->connections();
|
||||||
std::string src = cell->get_src_attribute();
|
std::string src = cell->get_src_attribute();
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ struct IopadmapPass : public Pass {
|
|||||||
|
|
||||||
// Collect explicitly-marked already-buffered SigBits.
|
// Collect explicitly-marked already-buffered SigBits.
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
if (wire->get_bool_attribute(ID::iopad_external_pin) || ignore.count(make_pair(RTLIL::IdString(module->name), wire->name)))
|
if (wire->get_bool_attribute(ID::iopad_external_pin) || ignore.count(make_pair(RTLIL::IdString(module->name), RTLIL::IdString(wire->name))))
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
buf_bits.insert(sigmap(SigBit(wire, i)));
|
buf_bits.insert(sigmap(SigBit(wire, i)));
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ struct IopadmapPass : public Pass {
|
|||||||
if (wire->port_input || wire->port_output)
|
if (wire->port_input || wire->port_output)
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
if (buf_bits.count(sigmap(SigBit(wire, i)))) {
|
if (buf_bits.count(sigmap(SigBit(wire, i)))) {
|
||||||
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
log("Marking already mapped port: %s.%s[%d].\n", module, wire, i);
|
log("Marking already mapped port: %s.%s[%d].\n", module, wire, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,7 @@ struct IopadmapPass : public Pass {
|
|||||||
SigBit wire_bit(wire, i);
|
SigBit wire_bit(wire, i);
|
||||||
Cell *tbuf_cell = nullptr;
|
Cell *tbuf_cell = nullptr;
|
||||||
|
|
||||||
if (buf_ports.count(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i))))
|
if (buf_ports.count(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tbuf_bits.count(wire_bit))
|
if (tbuf_bits.count(wire_bit))
|
||||||
@@ -370,7 +370,7 @@ struct IopadmapPass : public Pass {
|
|||||||
if (!toutpad_portname_pad.empty())
|
if (!toutpad_portname_pad.empty())
|
||||||
rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(toutpad_portname_pad));
|
rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(toutpad_portname_pad));
|
||||||
}
|
}
|
||||||
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i)));
|
buf_ports.insert(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ struct IopadmapPass : public Pass {
|
|||||||
pool<int> skip_bit_indices;
|
pool<int> skip_bit_indices;
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
if (buf_ports.count(make_pair(RTLIL::IdString(module->name), make_pair(wire->name, i))))
|
if (buf_ports.count(make_pair(RTLIL::IdString(module->name), make_pair(RTLIL::IdString(wire->name), i))))
|
||||||
skip_bit_indices.insert(i);
|
skip_bit_indices.insert(i);
|
||||||
|
|
||||||
if (GetSize(wire) == GetSize(skip_bit_indices))
|
if (GetSize(wire) == GetSize(skip_bit_indices))
|
||||||
|
|||||||
Reference in New Issue
Block a user