mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-23 15:42:32 +00:00
twine: fix replayability, reduce TwineSearch usage
This commit is contained in:
parent
e9eb3889b7
commit
7c73fd62e4
41 changed files with 273 additions and 272 deletions
|
|
@ -269,13 +269,14 @@ end_of_header:
|
|||
else
|
||||
log_abort();
|
||||
|
||||
RTLIL::Wire* n0 = module->wire(TwineSearch(&design->twines).find(stringf("$aiger%d$0", aiger_autoidx)));
|
||||
RTLIL::Wire* n0 = aiger_wires.count(0) ? aiger_wires.at(0) : nullptr;
|
||||
if (n0)
|
||||
module->connect(n0, State::S0);
|
||||
|
||||
// Parse footer (symbol table, comments, etc.)
|
||||
unsigned l1;
|
||||
std::string s;
|
||||
TwineSearch search(&design->twines);
|
||||
for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
|
||||
if (c == 'i' || c == 'l' || c == 'o' || c == 'b') {
|
||||
f.ignore(1);
|
||||
|
|
@ -294,7 +295,7 @@ end_of_header:
|
|||
log_assert(l1 < latches.size());
|
||||
wire = latches[l1];
|
||||
} else if (c == 'o') {
|
||||
wire = module->wire(TwineSearch(&design->twines).find(escaped_s.str()));
|
||||
wire = module->wire(search.find(escaped_s.str()));
|
||||
log_assert(l1 < outputs.size());
|
||||
if (wire) {
|
||||
// Could have been renamed by a latch
|
||||
|
|
@ -307,7 +308,7 @@ end_of_header:
|
|||
wire = bad_properties[l1];
|
||||
} else log_abort();
|
||||
|
||||
module->rename(wire, design->twines.add(std::string{escaped_s.str()}));
|
||||
module->rename(wire, intern_name(escaped_s.str(), search));
|
||||
}
|
||||
else if (c == 'j' || c == 'f') {
|
||||
// TODO
|
||||
|
|
@ -346,25 +347,28 @@ RTLIL::Wire* AigerReader::createWireIfNotExists(RTLIL::Module *module, unsigned
|
|||
{
|
||||
const unsigned variable = literal >> 1;
|
||||
const bool invert = literal & 1;
|
||||
if (auto it = aiger_wires.find(literal); it != aiger_wires.end())
|
||||
return it->second;
|
||||
RTLIL::IdString wire_name(stringf("$aiger%d$%d%s", aiger_autoidx, variable, invert ? "b" : ""));
|
||||
RTLIL::Wire *wire = module->wire(TwineSearch(&design->twines).find(wire_name.str()));
|
||||
if (wire) return wire;
|
||||
log_debug2("Creating %s\n", wire_name.c_str());
|
||||
wire = module->addWire(design->twines.add(std::string{wire_name.str()}));
|
||||
RTLIL::Wire *wire = module->addWire(design->twines.add(std::string{wire_name.str()}));
|
||||
wire->port_input = wire->port_output = false;
|
||||
aiger_wires[literal] = wire;
|
||||
if (!invert) return wire;
|
||||
RTLIL::IdString wire_inv_name(stringf("$aiger%d$%d", aiger_autoidx, variable));
|
||||
RTLIL::Wire *wire_inv = module->wire(TwineSearch(&design->twines).find(wire_inv_name.str()));
|
||||
if (wire_inv) {
|
||||
if (module->cell(TwineSearch(&design->twines).find(wire_inv_name.str()))) return wire;
|
||||
const unsigned base_literal = variable << 1;
|
||||
RTLIL::Wire *wire_inv;
|
||||
if (auto it = aiger_wires.find(base_literal); it != aiger_wires.end()) {
|
||||
wire_inv = it->second;
|
||||
}
|
||||
else {
|
||||
RTLIL::IdString wire_inv_name(stringf("$aiger%d$%d", aiger_autoidx, variable));
|
||||
log_debug2("Creating %s\n", wire_inv_name.c_str());
|
||||
wire_inv = module->addWire(design->twines.add(std::string{wire_inv_name.str()}));
|
||||
wire_inv->port_input = wire_inv->port_output = false;
|
||||
aiger_wires[base_literal] = wire_inv;
|
||||
}
|
||||
|
||||
log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str());
|
||||
log_debug2("Creating %s = ~$aiger%d$%d\n", wire_name.c_str(), aiger_autoidx, variable);
|
||||
module->addNotGate(Twine{stringf("$not$aiger%d$%d", aiger_autoidx, variable)}, wire_inv, wire);
|
||||
|
||||
return wire;
|
||||
|
|
@ -402,7 +406,7 @@ void AigerReader::parse_xaiger()
|
|||
else
|
||||
log_abort();
|
||||
|
||||
RTLIL::Wire* n0 = module->wire(TwineSearch(&design->twines).find(stringf("$aiger%d$0", aiger_autoidx)));
|
||||
RTLIL::Wire* n0 = aiger_wires.count(0) ? aiger_wires.at(0) : nullptr;
|
||||
if (n0)
|
||||
module->connect(n0, State::S0);
|
||||
|
||||
|
|
@ -422,11 +426,12 @@ void AigerReader::parse_xaiger()
|
|||
uint32_t lutSize = parse_xaiger_literal(f);
|
||||
log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
|
||||
ConstEvalAig ce(module);
|
||||
TwineSearch search(&design->twines);
|
||||
for (unsigned i = 0; i < lutNum; ++i) {
|
||||
uint32_t rootNodeID = parse_xaiger_literal(f);
|
||||
uint32_t cutLeavesM = parse_xaiger_literal(f);
|
||||
log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM);
|
||||
RTLIL::Wire *output_sig = module->wire(TwineSearch(&design->twines).find(stringf("$aiger%d$%d", aiger_autoidx, rootNodeID)));
|
||||
RTLIL::Wire *output_sig = module->wire(search.find(stringf("$aiger%d$%d", aiger_autoidx, rootNodeID)));
|
||||
log_assert(output_sig);
|
||||
uint32_t nodeID;
|
||||
RTLIL::SigSpec input_sig;
|
||||
|
|
@ -437,7 +442,7 @@ void AigerReader::parse_xaiger()
|
|||
log_debug("\tLUT '$lut$aiger%d$%d' input %d is constant!\n", aiger_autoidx, rootNodeID, cutLeavesM);
|
||||
continue;
|
||||
}
|
||||
RTLIL::Wire *wire = module->wire(TwineSearch(&design->twines).find(stringf("$aiger%d$%d", aiger_autoidx, nodeID)));
|
||||
RTLIL::Wire *wire = module->wire(search.find(stringf("$aiger%d$%d", aiger_autoidx, nodeID)));
|
||||
log_assert(wire);
|
||||
input_sig.append(wire);
|
||||
}
|
||||
|
|
@ -456,7 +461,7 @@ void AigerReader::parse_xaiger()
|
|||
log_assert(o.wire == nullptr);
|
||||
lut_mask.set(gray, o.data);
|
||||
}
|
||||
RTLIL::Cell *output_cell = module->cell(TwineSearch(&design->twines).find(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)));
|
||||
RTLIL::Cell *output_cell = module->cell(search.find(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)));
|
||||
log_assert(output_cell);
|
||||
module->remove(output_cell);
|
||||
module->addLut(Twine{stringf("$lut$aiger%d$%d", aiger_autoidx, rootNodeID)}, input_sig, output_sig, std::move(lut_mask));
|
||||
|
|
@ -772,6 +777,21 @@ void AigerReader::parse_aiger_binary()
|
|||
}
|
||||
}
|
||||
|
||||
// add(std::string) always interns a fresh leaf, but an equal-content name may
|
||||
// already exist in the pool as a NEW_TWINE suffix (auto-generated names share a
|
||||
// prefix leaf). Reuse that ref so every wire/cell with the same name string is
|
||||
// keyed by a single canonical ref; otherwise leaf-vs-suffix refs diverge and
|
||||
// module->wire()/cell() lookups miss.
|
||||
TwineRef AigerReader::intern_name(const std::string &escaped, TwineSearch &search)
|
||||
{
|
||||
TwineRef existing = search.find(escaped);
|
||||
if (existing != Twine::Null)
|
||||
return existing;
|
||||
TwineRef ref = design->twines.add(std::string{escaped});
|
||||
search.insert(ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
void AigerReader::post_process()
|
||||
{
|
||||
unsigned ci_count = 0, co_count = 0;
|
||||
|
|
@ -816,6 +836,7 @@ void AigerReader::post_process()
|
|||
std::ifstream mf(map_filename);
|
||||
std::string type, symbol;
|
||||
int variable, index;
|
||||
TwineSearch search(&design->twines);
|
||||
while (mf >> type >> variable >> index >> symbol) {
|
||||
RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
|
||||
if (type == "input") {
|
||||
|
|
@ -830,9 +851,9 @@ void AigerReader::post_process()
|
|||
// Cope with the fact that a CI might be identical
|
||||
// to a PI (necessary due to ABC); in those cases
|
||||
// simply connect the latter to the former
|
||||
existing = module->wire(TwineSearch(&design->twines).find(escaped_s.str()));
|
||||
existing = module->wire(search.find(escaped_s.str()));
|
||||
if (!existing)
|
||||
module->rename(wire, design->twines.add(std::string{escaped_s.str()}));
|
||||
module->rename(wire, intern_name(escaped_s.str(), search));
|
||||
else {
|
||||
wire->port_input = false;
|
||||
module->connect(wire, existing);
|
||||
|
|
@ -841,9 +862,9 @@ void AigerReader::post_process()
|
|||
}
|
||||
else {
|
||||
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index);
|
||||
existing = module->wire(TwineSearch(&design->twines).find(indexed_name.str()));
|
||||
existing = module->wire(search.find(indexed_name.str()));
|
||||
if (!existing)
|
||||
module->rename(wire, design->twines.add(std::string{indexed_name.str()}));
|
||||
module->rename(wire, intern_name(indexed_name.str(), search));
|
||||
else {
|
||||
module->connect(wire, existing);
|
||||
wire->port_input = false;
|
||||
|
|
@ -875,9 +896,9 @@ void AigerReader::post_process()
|
|||
// Cope with the fact that a CO might be identical
|
||||
// to a PO (necessary due to ABC); in those cases
|
||||
// simply connect the latter to the former
|
||||
existing = module->wire(TwineSearch(&design->twines).find(escaped_s.str()));
|
||||
existing = module->wire(search.find(escaped_s.str()));
|
||||
if (!existing)
|
||||
module->rename(wire, design->twines.add(std::string{escaped_s.str()}));
|
||||
module->rename(wire, intern_name(escaped_s.str(), search));
|
||||
else {
|
||||
wire->port_output = false;
|
||||
existing->port_output = true;
|
||||
|
|
@ -888,9 +909,9 @@ void AigerReader::post_process()
|
|||
}
|
||||
else {
|
||||
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index);
|
||||
existing = module->wire(TwineSearch(&design->twines).find(indexed_name.str()));
|
||||
existing = module->wire(search.find(indexed_name.str()));
|
||||
if (!existing)
|
||||
module->rename(wire, design->twines.add(std::string{indexed_name.str()}));
|
||||
module->rename(wire, intern_name(indexed_name.str(), search));
|
||||
else {
|
||||
wire->port_output = false;
|
||||
existing->port_output = true;
|
||||
|
|
@ -912,17 +933,18 @@ void AigerReader::post_process()
|
|||
}
|
||||
}
|
||||
else if (type == "box") {
|
||||
RTLIL::Cell* cell = module->cell(TwineSearch(&design->twines).find(stringf("$box%d", variable)));
|
||||
RTLIL::Cell* cell = module->cell(search.find(stringf("$box%d", variable)));
|
||||
if (!cell)
|
||||
log_debug("Box %d (%s) no longer exists.\n", variable, log_id(escaped_s));
|
||||
else
|
||||
module->rename(cell, design->twines.add(std::string{escaped_s.str()}));
|
||||
module->rename(cell, intern_name(escaped_s.str(), search));
|
||||
}
|
||||
else
|
||||
log_error("Symbol type '%s' not recognised.\n", type);
|
||||
}
|
||||
}
|
||||
|
||||
TwineSearch wp_search(&design->twines);
|
||||
for (auto &wp : wideports_cache) {
|
||||
auto name = wp.first;
|
||||
int min = wp.second.first;
|
||||
|
|
@ -930,30 +952,33 @@ void AigerReader::post_process()
|
|||
if (min == 0 && max == 0)
|
||||
continue;
|
||||
|
||||
RTLIL::Wire *wire = module->wire(TwineSearch(&design->twines).find(name.str()));
|
||||
if (wire)
|
||||
module->rename(wire, design->twines.add(std::string{RTLIL::escape_id(stringf("%s[%d]", name.str(), 0))}));
|
||||
RTLIL::Wire *wire = module->wire(wp_search.find(name.str()));
|
||||
if (wire) {
|
||||
TwineRef renamed = design->twines.add(std::string{RTLIL::escape_id(stringf("%s[%d]", name.str(), 0))});
|
||||
wp_search.insert(renamed);
|
||||
module->rename(wire, renamed);
|
||||
}
|
||||
|
||||
// Do not make ports with a mix of input/output into
|
||||
// wide ports
|
||||
bool port_input = false, port_output = false;
|
||||
for (int i = min; i <= max; i++) {
|
||||
RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
|
||||
RTLIL::Wire *other_wire = module->wire(TwineSearch(&design->twines).find(other_name.str()));
|
||||
RTLIL::Wire *other_wire = module->wire(wp_search.find(other_name.str()));
|
||||
if (other_wire) {
|
||||
port_input = port_input || other_wire->port_input;
|
||||
port_output = port_output || other_wire->port_output;
|
||||
}
|
||||
}
|
||||
|
||||
wire = module->addWire(design->twines.add(std::string{name.str()}), max-min+1);
|
||||
wire = module->addWire(intern_name(name.str(), wp_search), max-min+1);
|
||||
wire->start_offset = min;
|
||||
wire->port_input = port_input;
|
||||
wire->port_output = port_output;
|
||||
|
||||
for (int i = min; i <= max; i++) {
|
||||
RTLIL::IdString other_name = stringf("%s[%d]", name, i);
|
||||
RTLIL::Wire *other_wire = module->wire(TwineSearch(&design->twines).find(other_name.str()));
|
||||
RTLIL::Wire *other_wire = module->wire(wp_search.find(other_name.str()));
|
||||
if (other_wire) {
|
||||
other_wire->port_input = false;
|
||||
other_wire->port_output = false;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ struct AigerReader
|
|||
std::vector<RTLIL::Wire*> bad_properties;
|
||||
std::vector<RTLIL::Cell*> boxes;
|
||||
std::vector<int> mergeability, initial_state;
|
||||
dict<unsigned, RTLIL::Wire*> aiger_wires;
|
||||
|
||||
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
|
||||
void parse_aiger();
|
||||
|
|
@ -54,6 +55,7 @@ struct AigerReader
|
|||
void parse_aiger_binary();
|
||||
void post_process();
|
||||
|
||||
TwineRef intern_name(const std::string &escaped, TwineSearch &search);
|
||||
RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ struct Xaiger2Frontend : public Frontend {
|
|||
log_error("Bad map file: primary output literal out of range\n");
|
||||
if (bits[lit] == RTLIL::Sm)
|
||||
log_error("Bad map file: primary output literal is a marker\n");
|
||||
Wire *w = module->wire(TwineSearch(&design->twines).find(name));
|
||||
Wire *w = module->wire(search.find(name));
|
||||
if (!w || woffset < 0 || woffset >= w->width)
|
||||
log_error("Map file references non-existent signal bit %s[%d]\n",
|
||||
name.c_str(), woffset);
|
||||
|
|
@ -434,8 +434,8 @@ struct Xaiger2Frontend : public Frontend {
|
|||
log_error("Bad map file: pseudo primary output literal out of range\n");
|
||||
if (bits[lit] == RTLIL::Sm)
|
||||
log_error("Bad map file: pseudo primary output literal is a marker\n");
|
||||
Cell *cell = module->cell(TwineSearch(&design->twines).find(box_name));
|
||||
auto box_port_ref = TwineSearch(&design->twines).find(box_port);
|
||||
Cell *cell = module->cell(search.find(box_name));
|
||||
auto box_port_ref = search.find(box_port);
|
||||
if (!cell || !cell->hasPort(box_port_ref))
|
||||
log_error("Map file references non-existent box port %s/%s\n",
|
||||
box_name.c_str(), box_port.c_str());
|
||||
|
|
|
|||
|
|
@ -1106,10 +1106,6 @@ std::string AstNode::loc_string() const
|
|||
|
||||
void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
|
||||
{
|
||||
// All AttrObjects in genrtlil — Cell/Wire/Module/Process AND the inner
|
||||
// types (CaseRule, SwitchRule, MemWriteAction) — share current_module's
|
||||
// design's twine pool. process_module attaches current_module->design
|
||||
// early so this is reachable.
|
||||
if (!current_module || !current_module->design)
|
||||
return;
|
||||
const auto &loc = ast->location;
|
||||
|
|
@ -1152,11 +1148,6 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
|
||||
AstModule *module = new AstModule;
|
||||
current_module = module;
|
||||
// Set design backpointer early — every set_src_attr in genrtlil.cc
|
||||
// resolves the pool via current_module->design->twines. The
|
||||
// final design->add(current_module) at end-of-process_module hooks
|
||||
// the module into the design's modules_ dict; we just need design
|
||||
// reachable as a backpointer for src interning meanwhile.
|
||||
module->design = design;
|
||||
|
||||
module->ast = nullptr;
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
|
||||
Module *module = new RTLIL::Module;
|
||||
module->design = design;
|
||||
module->meta_->name = design->twines.add(Twine{RTLIL::escape_id(modname)});
|
||||
module->meta_->name = design->twines.add(RTLIL::escape_id(modname));
|
||||
|
||||
if (design->module(module->meta_->name))
|
||||
log_error("Re-definition of module %s.\n", design->twines.str(module->meta_->name));
|
||||
|
|
@ -327,6 +327,8 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
|
||||
dict<int, SigBit> signal_bits;
|
||||
|
||||
dict<IdString, Wire*> wire_cache;
|
||||
|
||||
if (node->data_dict.count("ports"))
|
||||
{
|
||||
JsonNode *ports_node = node->data_dict.at("ports");
|
||||
|
|
@ -357,10 +359,12 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
if (port_bits_node->type != 'A')
|
||||
log_error("JSON port node '%s' has non-array bits attribute.\n", port_name.unescape());
|
||||
|
||||
Wire *port_wire = module->wire(TwineSearch(&design->twines).find(port_name.str()));
|
||||
Wire *port_wire = wire_cache.count(port_name) ? wire_cache.at(port_name) : nullptr;
|
||||
|
||||
if (port_wire == nullptr)
|
||||
port_wire = module->addWire(Twine{port_name.str()}, GetSize(port_bits_node->data_array));
|
||||
if (port_wire == nullptr) {
|
||||
port_wire = module->addWire(design->twines.add(port_name.str()), GetSize(port_bits_node->data_array));
|
||||
wire_cache[port_name] = port_wire;
|
||||
}
|
||||
|
||||
if (port_node->data_dict.count("upto") != 0) {
|
||||
JsonNode *val = port_node->data_dict.at("upto");
|
||||
|
|
@ -455,10 +459,12 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
if (bits_node->type != 'A')
|
||||
log_error("JSON netname node '%s' has non-array bits attribute.\n", net_name.unescape());
|
||||
|
||||
Wire *wire = module->wire(TwineSearch(&design->twines).find(net_name.str()));
|
||||
Wire *wire = wire_cache.count(net_name) ? wire_cache.at(net_name) : nullptr;
|
||||
|
||||
if (wire == nullptr)
|
||||
wire = module->addWire(Twine{net_name.str()}, GetSize(bits_node->data_array));
|
||||
if (wire == nullptr) {
|
||||
wire = module->addWire(design->twines.add(net_name.str()), GetSize(bits_node->data_array));
|
||||
wire_cache[net_name] = wire;
|
||||
}
|
||||
|
||||
if (net_node->data_dict.count("upto") != 0) {
|
||||
JsonNode *val = net_node->data_dict.at("upto");
|
||||
|
|
@ -532,7 +538,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
|
||||
IdString cell_type = RTLIL::escape_id(type_node->data_string.c_str());
|
||||
|
||||
Cell *cell = module->addCell(Twine{cell_name.str()}, Twine{cell_type.str()});
|
||||
Cell *cell = module->addCell(design->twines.add(cell_name.str()), design->twines.add(cell_type.str()));
|
||||
|
||||
if (cell_node->data_dict.count("connections") == 0)
|
||||
log_error("JSON cells node '%s' has no connections attribute.\n", cell_name.unescape());
|
||||
|
|
@ -580,7 +586,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
|
||||
}
|
||||
|
||||
cell->setPort(design->twines.add(Twine{conn_name.str()}), sig);
|
||||
cell->setPort(design->twines.add(conn_name.str()), sig);
|
||||
}
|
||||
|
||||
if (cell_node->data_dict.count("attributes"))
|
||||
|
|
@ -604,7 +610,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
JsonNode *memory_node = memory_node_it.second;
|
||||
|
||||
RTLIL::Memory *mem = new RTLIL::Memory;
|
||||
mem->meta_->name = design->twines.add(Twine{memory_name.str()});
|
||||
mem->meta_->name = design->twines.add(memory_name.str());
|
||||
mem->module = module;
|
||||
|
||||
if (memory_node->type != 'D')
|
||||
|
|
|
|||
|
|
@ -50,26 +50,14 @@ struct RTLILFrontendWorker {
|
|||
|
||||
RTLIL::Module *current_module;
|
||||
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
|
||||
// A resolved "@N" src reference, carried from parse_attribute to the
|
||||
// object's absorb_attrs site so it lands on the object without being
|
||||
// flattened into a fresh leaf.
|
||||
|
||||
TwineRef pending_src = Twine::Null;
|
||||
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
|
||||
std::vector<RTLIL::CaseRule*> case_stack;
|
||||
|
||||
// Remap from file-local twine ids (as they appear in the `twines` block
|
||||
// and on cell/wire src attrs) to ids in design->twines. Filled by
|
||||
// parse_twines; consumed by parse_attribute. Parser-side ids retained
|
||||
// during parse_twines are tracked here so they can be released at
|
||||
// end-of-parse — only the cell/wire references should survive.
|
||||
dict<size_t, TwineRef> twine_remap;
|
||||
std::vector<TwineRef> twine_parser_holds;
|
||||
|
||||
// Raw twines-block node descriptors keyed by file-local id. The block may
|
||||
// list a node before its children (the writer emits in pool-index order,
|
||||
// and free-list slot reuse can place a parent at a lower index than a
|
||||
// child), so descriptors are collected first and materialized on demand in
|
||||
// dependency order via materialize_file_twine.
|
||||
struct TwineDesc {
|
||||
enum Kind { Leaf, Suffix, Concat } kind;
|
||||
std::string text;
|
||||
|
|
@ -481,8 +469,6 @@ struct RTLILFrontendWorker {
|
|||
current_module->design = design;
|
||||
current_module->meta_->name = module_name;
|
||||
if (delete_current_module) {
|
||||
// Module is about to be discarded — drop its src attribute
|
||||
// rather than push it into a pool we'll never reach.
|
||||
attrbuf.erase(ID::src);
|
||||
pending_src = Twine::Null;
|
||||
current_module->attributes = std::move(attrbuf);
|
||||
|
|
@ -543,18 +529,9 @@ struct RTLILFrontendWorker {
|
|||
{
|
||||
RTLIL::IdString id = parse_id();
|
||||
RTLIL::Const c = parse_const();
|
||||
// The '|' separator inside a src attribute is a Yosys-internal
|
||||
// merge convention emitted only by the legacy strpool path or by
|
||||
// a `dump -resolve-src`; no external tool should be producing it.
|
||||
// Warn so the producer learns to emit one path:line.col per
|
||||
// attribute. We don't try to repair the value — the user's input
|
||||
// is wrong and silently interning it would hide that.
|
||||
if (id == RTLIL::ID::src && (c.flags & RTLIL::CONST_FLAG_STRING)) {
|
||||
std::string raw = c.decode_string();
|
||||
if (!raw.empty() && raw[0] == '@') {
|
||||
// Compact "@N" reference into the `twines` block: carry the
|
||||
// resolved twine straight to the object (set after its
|
||||
// absorb_attrs) so its structure is preserved, not flattened.
|
||||
size_t file_id = 0;
|
||||
auto [ptr, ec] = std::from_chars(raw.data() + 1, raw.data() + raw.size(), file_id);
|
||||
if (ec != std::errc() || ptr != raw.data() + raw.size())
|
||||
|
|
@ -591,10 +568,7 @@ struct RTLILFrontendWorker {
|
|||
base = TwineRef(id);
|
||||
} else {
|
||||
auto it = twine_remap.find(id);
|
||||
if (it == twine_remap.end())
|
||||
base = materialize_file_twine(id);
|
||||
else
|
||||
base = it->second;
|
||||
base = (it == twine_remap.end()) ? materialize_file_twine(id) : it->second;
|
||||
}
|
||||
return twine_tag(base, is_public);
|
||||
}
|
||||
|
|
@ -708,21 +682,17 @@ struct RTLILFrontendWorker {
|
|||
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
|
||||
error_token());
|
||||
}
|
||||
std::vector<size_t> ordered_ids;
|
||||
ordered_ids.reserve(twine_descs.size());
|
||||
for (auto &it : twine_descs)
|
||||
materialize_file_twine(it.first);
|
||||
ordered_ids.push_back(it.first);
|
||||
std::sort(ordered_ids.begin(), ordered_ids.end());
|
||||
for (size_t id : ordered_ids)
|
||||
materialize_file_twine(id);
|
||||
twine_descs.clear();
|
||||
expect_eol();
|
||||
}
|
||||
|
||||
// Release the per-file parser refs gathered during parse_twines. Call
|
||||
// once the entire file has been parsed and every cell/wire that ever
|
||||
// referred to a file_id has already adopted the corresponding local_id.
|
||||
void release_twine_parser_holds()
|
||||
{
|
||||
twine_parser_holds.clear();
|
||||
twine_remap.clear();
|
||||
}
|
||||
|
||||
void parse_parameter()
|
||||
{
|
||||
RTLIL::IdString id = parse_id();
|
||||
|
|
@ -1080,9 +1050,6 @@ struct RTLILFrontendWorker {
|
|||
act.enable = parse_sigspec();
|
||||
act.priority_mask = parse_const();
|
||||
rule->mem_write_actions.push_back(act);
|
||||
// meta_idx_ is a weak ref — drop ours so the pushed copy
|
||||
// in the vector is the sole holder. Process::~Process
|
||||
// walks the tree to actually release.
|
||||
act.meta_ = nullptr;
|
||||
expect_eol();
|
||||
}
|
||||
|
|
@ -1126,7 +1093,9 @@ struct RTLILFrontendWorker {
|
|||
}
|
||||
if (attrbuf.size() != 0)
|
||||
error("dangling attribute");
|
||||
release_twine_parser_holds();
|
||||
|
||||
twine_parser_holds.clear();
|
||||
twine_remap.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue