3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-24 08:02:32 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-08 23:40:51 +02:00
parent 1a8a95b472
commit d13dfc21f4
32 changed files with 1348 additions and 769 deletions

View file

@ -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
// thousands of objects in one file this collapses N copies of a long
// path into 1 Leaf + N short Suffix tails.
TwinePool *pool = &current_module->design->src_twines;
TwinePool *pool = &current_module->design->twines;
Twine::Id file_id = pool->intern(*loc.begin.filename);
std::string tail = stringf(":%d.%d-%d.%d",
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;
current_module = module;
// 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
// the module into the design's modules_ dict; we just need design
// reachable as a backpointer for src interning meanwhile.

View file

@ -503,7 +503,7 @@ struct AST_INTERNAL::ProcessGenerator
chunk.wire->name.c_str(), chunk.width+chunk.offset-1, chunk.offset);;
if (chunk.wire->name.str().find('$') != std::string::npos)
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);
set_src_attr(wire, always.get());
@ -1629,10 +1629,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
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);
set_src_attr(wire, this);
wire->name = str;
// If we are currently processing a bind directive which wires up
// 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);
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);
if (current_wire->get_bool_attribute(ID::is_interface))
is_interface = true;
@ -1682,7 +1681,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
return dummy_wire;
}
wire = current_module->wires_[str];
wire = current_module->wire(RTLIL::IdString(str));
chunk.wire = wire;
chunk.width = wire->width;
chunk.offset = 0;

View file

@ -47,11 +47,12 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1;
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);
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)
@ -728,7 +729,7 @@ struct LibertyFrontend : public Frontend {
if (flag_lib && dir->value == "internal")
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);
const LibertyAst *capacitance = node->find("capacitance");

View file

@ -54,11 +54,11 @@ struct RTLILFrontendWorker {
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->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
// during parse_twines are tracked here so they can be released at
// 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;
template <typename... Args>
@ -171,7 +171,7 @@ struct RTLILFrontendWorker {
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];
if (ch != '\\' && ch != '$')
@ -183,15 +183,15 @@ struct RTLILFrontendWorker {
break;
++idx;
}
IdString result(line.substr(0, idx));
std::string result(line.substr(0, idx));
line = line.substr(idx);
consume_whitespace_and_comments();
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())
error("Expected ID, got `%s'.", error_token());
return std::move(*id);
@ -423,7 +423,7 @@ struct RTLILFrontendWorker {
void parse_module()
{
RTLIL::IdString module_name = parse_id();
Twine::Id module_name = design->twines.lookup(parse_id());
expect_eol();
bool delete_current_module = false;
@ -445,7 +445,7 @@ struct RTLILFrontendWorker {
current_module = new RTLIL::Module;
current_module->design = design;
current_module->name = std::move(module_name);
current_module->meta_->name_id = 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.
@ -515,15 +515,16 @@ struct RTLILFrontendWorker {
// 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();
Twine::Id file_id = TwinePool::parse_ref(raw);
if (file_id != Twine::Null) {
// TODO error handling
auto file_id = design->twines.parse_ref(raw);
if (file_id) {
// Translate the file-local twine id to the destination
// design's pool id via twine_remap. If the file had no
// `twines` block (legacy) the remap is empty — accept the
// 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())
c = RTLIL::Const(TwinePool::format_ref(it->second));
c = RTLIL::Const(design->twines.format_ref(it->second));
} else if (raw.find('|') != std::string::npos) {
log_warning("line %d: src attribute %s contains '|' separators. "
"That convention is Yosys-internal; the producing tool "
@ -538,61 +539,47 @@ struct RTLILFrontendWorker {
// Parses a `twines` ... `end` block. Builds twine_remap so subsequent
// 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
// against the existing pool by the pool itself. Each parser-side
// retain is tracked in twine_parser_holds and released at end-of-parse
// so only cell/wire references survive.
void parse_twines()
{
TwinePoolExtender extender(design->twines, design->twines.size());
expect_eol();
while (true) {
if (try_parse_keyword("end"))
break;
if (try_parse_keyword("leaf")) {
int file_id = static_cast<int>(parse_integer());
size_t file_id = parse_integer();
std::string text = parse_string();
expect_eol();
Twine::Id local_id = design->src_twines.intern(text);
twine_parser_holds.push_back(local_id);
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
extender.extend_leaf(text, file_id);
continue;
}
if (try_parse_keyword("suffix")) {
int file_id = static_cast<int>(parse_integer());
Twine::Id file_parent = static_cast<Twine::Id>(parse_integer());
size_t file_id = parse_integer();
size_t file_parent = parse_integer();
std::string tail = parse_string();
expect_eol();
auto it = twine_remap.find(file_parent);
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;
extender.extend_suffix(file_parent, tail, file_id);
continue;
}
if (try_parse_keyword("concat")) {
int file_id = static_cast<int>(parse_integer());
std::vector<Twine::Id> children;
size_t file_id = parse_integer();
std::vector<size_t> children;
while (!try_parse_eol()) {
Twine::Id file_child = static_cast<Twine::Id>(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);
children.push_back(parse_integer());
}
Twine::Id local_id = design->src_twines.concat(
std::span<const Twine::Id>{children});
twine_parser_holds.push_back(local_id);
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
extender.extend_concat(children, file_id);
continue;
}
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
error_token());
}
expect_eol();
extender.finish();
}
// Release the per-file parser refs gathered during parse_twines. Call
@ -601,7 +588,7 @@ struct RTLILFrontendWorker {
void release_twine_parser_holds()
{
for (Twine::Id id : twine_parser_holds)
design->src_twines.release(id);
design->twines.release(id);
twine_parser_holds.clear();
twine_remap.clear();
}