mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-24 08:02:32 +00:00
WIP
This commit is contained in:
parent
1a8a95b472
commit
d13dfc21f4
32 changed files with 1348 additions and 769 deletions
|
|
@ -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 = ¤t_module->design->src_twines;
|
||||
TwinePool *pool = ¤t_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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue