mirror of
https://github.com/YosysHQ/yosys
synced 2026-08-10 08:01:14 +00:00
ast, flatten, hierarchy: canonically split hierarchical references into twines
This commit is contained in:
parent
39df31571e
commit
628501c786
5 changed files with 75 additions and 25 deletions
|
|
@ -1100,10 +1100,34 @@ std::string AstNode::loc_string() const
|
|||
return stringf("%s:%d.%d-%d.%d", location.begin.filename->c_str(), location.begin.line, location.begin.column, location.end.line, location.end.column);
|
||||
}
|
||||
|
||||
static TwineRef build_hier_content(TwinePool &pool, std::string_view content)
|
||||
{
|
||||
size_t dot = content.rfind('.');
|
||||
if (dot == std::string_view::npos)
|
||||
return pool.add(Twine{std::string{content}}).tag(true);
|
||||
TwineRef prefix = build_hier_content(pool, content.substr(0, dot));
|
||||
return pool.add(Twine{Twine::Suffix{prefix, std::string{content.substr(dot)}}});
|
||||
}
|
||||
|
||||
TwineRef AST::intern_hier_name(RTLIL::Design *design, std::string_view escaped)
|
||||
{
|
||||
if (escaped.size() > 1 && escaped[0] == '\\')
|
||||
return build_hier_content(design->twines, escaped.substr(1));
|
||||
return design->twines.add(std::string{escaped});
|
||||
}
|
||||
|
||||
void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
|
||||
{
|
||||
if (!current_module || !current_module->design)
|
||||
return;
|
||||
auto it = ast->attributes.find(ID::src);
|
||||
if (it != ast->attributes.end() && it->second->type == AST_CONSTANT) {
|
||||
// An explicit (* src *) attribute (e.g. when re-reading written output)
|
||||
// takes precedence over the parse position
|
||||
current_module->design->set_src_attribute(obj,
|
||||
current_module->design->twines.add(Twine{it->second->asAttrConst().decode_string()}));
|
||||
return;
|
||||
}
|
||||
const auto &loc = ast->location;
|
||||
if (!loc.begin.filename || loc.begin.filename->empty()) {
|
||||
current_module->design->set_src_attribute(obj, current_module->design->twines.add(Twine{ast->loc_string()}));
|
||||
|
|
@ -1285,6 +1309,8 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
|
||||
for (auto &attr : ast->attributes) {
|
||||
log_assert((bool)attr.second.get());
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
module->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -1313,6 +1339,8 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
}
|
||||
else {
|
||||
for (auto &attr : ast->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
continue;
|
||||
module->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -1758,7 +1786,7 @@ TwineRef AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RT
|
|||
new_subcell->set_bool_attribute(ID::is_interface);
|
||||
}
|
||||
else {
|
||||
log_error("No port with matching name found (%s) in %s. Stopping\n", intf.first, modname);
|
||||
log_error("No port with matching name found (%s) in %s. Stopping\n", mod->design->twines.str(intf.first).c_str(), modname);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -429,6 +429,9 @@ namespace AST
|
|||
AstNode * find_modport(AstNode *intf, std::string name);
|
||||
void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport);
|
||||
|
||||
// Intern Verilog hierarchical reference "a.b.c" as a Suffix chain "a" ".b" ".c"
|
||||
TwineRef intern_hier_name(RTLIL::Design *design, std::string_view escaped);
|
||||
|
||||
// Helper for setting the src attribute.
|
||||
void set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, TwineRef type, int result_width
|
|||
|
||||
if (gen_attributes)
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -88,6 +90,8 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
|
|||
|
||||
if (that != nullptr)
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -114,6 +118,8 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, TwineRef type, int result_width
|
|||
wire->is_signed = that->is_signed;
|
||||
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -149,6 +155,8 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
|
|||
wire->is_signed = that->is_signed;
|
||||
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -178,7 +186,7 @@ static void check_unique_id(RTLIL::Module *module, RTLIL::IdString id,
|
|||
to_add_kind, id.c_str(), existing_kind, location_str.c_str());
|
||||
};
|
||||
|
||||
TwineRef id_tw = module->design->twines.find(id.str());
|
||||
TwineRef id_tw = intern_hier_name(module->design, id.str());
|
||||
if (const RTLIL::Wire *wire = module->wire(id_tw))
|
||||
already_exists(wire, "signal");
|
||||
if (const RTLIL::Cell *cell = module->cell(id_tw))
|
||||
|
|
@ -358,6 +366,8 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
proc = current_module->addProcess(current_module->design->twines.add(std::string{stringf("$proc$%s:%d$%d", RTLIL::encode_filename(*always->location.begin.filename), always->location.begin.line, autoidx++)}));
|
||||
set_src_attr(proc, always.get());
|
||||
for (auto &attr : always->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
always->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
proc->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -685,6 +695,8 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
current_case->switches.push_back(sw);
|
||||
|
||||
for (auto &attr : ast->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
sw->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -928,6 +940,8 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
set_src_attr(cell, ast);
|
||||
cell->set_bool_attribute(ID(keep));
|
||||
for (auto &attr : ast->attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -1466,7 +1480,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
// signals.
|
||||
RTLIL::IdString id = str;
|
||||
check_unique_id(current_module, id, this, "interface port");
|
||||
RTLIL::Wire *wire = current_module->addWire(current_module->design->twines.add(std::string{id.str()}), 1);
|
||||
RTLIL::Wire *wire = current_module->addWire(intern_hier_name(current_module->design, id.str()), 1);
|
||||
set_src_attr(wire, this);
|
||||
wire->start_offset = 0;
|
||||
wire->port_id = port_id;
|
||||
|
|
@ -1506,7 +1520,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
RTLIL::Const val = children[0]->bitsAsConst();
|
||||
RTLIL::IdString id = str;
|
||||
check_unique_id(current_module, id, this, "pwire");
|
||||
RTLIL::Wire *wire = current_module->addWire(current_module->design->twines.add(std::string{id.str()}), GetSize(val));
|
||||
RTLIL::Wire *wire = current_module->addWire(intern_hier_name(current_module->design, id.str()), GetSize(val));
|
||||
current_module->connect(wire, val);
|
||||
wire->is_signed = children[0]->is_signed;
|
||||
|
||||
|
|
@ -1514,6 +1528,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
wire->attributes[type == AST_PARAMETER ? ID::parameter : ID::localparam] = 1;
|
||||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
wire->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -1531,7 +1547,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
RTLIL::IdString id = str;
|
||||
check_unique_id(current_module, id, this, "signal");
|
||||
RTLIL::Wire *wire = current_module->addWire(current_module->design->twines.add(std::string{id.str()}), range_left - range_right + 1);
|
||||
RTLIL::Wire *wire = current_module->addWire(intern_hier_name(current_module->design, id.str()), range_left - range_right + 1);
|
||||
set_src_attr(wire, this);
|
||||
wire->start_offset = range_right;
|
||||
wire->port_id = port_id;
|
||||
|
|
@ -1542,6 +1558,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
wire->is_signed = is_signed;
|
||||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
wire->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -1562,7 +1580,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
input_error("Memory `%s' with non-constant width or size!\n", str);
|
||||
|
||||
check_unique_id(current_module, RTLIL::IdString(str), this, "memory");
|
||||
RTLIL::Memory *memory = current_module->addMemory(current_module->design->twines.add(std::string{str}));
|
||||
RTLIL::Memory *memory = current_module->addMemory(intern_hier_name(current_module->design, str));
|
||||
set_src_attr(memory, this);
|
||||
memory->width = children[0]->range_left - children[0]->range_right + 1;
|
||||
if (children[1]->range_right < children[1]->range_left) {
|
||||
|
|
@ -1574,6 +1592,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
}
|
||||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
memory->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -1617,10 +1637,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
log_assert(id2ast != nullptr);
|
||||
|
||||
TwineRef str_ref = current_module->design->twines.find(str);
|
||||
TwineRef str_ref = intern_hier_name(current_module->design, str);
|
||||
|
||||
if (id2ast->type == AST_AUTOWIRE && current_module->wire(str_ref) == nullptr) {
|
||||
RTLIL::Wire *wire = current_module->addWire(current_module->design->twines.add(std::string{str}));
|
||||
RTLIL::Wire *wire = current_module->addWire(str_ref);
|
||||
str_ref = wire->name.ref();
|
||||
set_src_attr(wire, this);
|
||||
|
||||
|
|
@ -2131,6 +2151,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
RTLIL::Cell *cell = current_module->addCell(current_module->design->twines.add(std::string{cellname.str()}), TW::$check);
|
||||
set_src_attr(cell, this);
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
input_error("Attribute `%s' with non-constant value!\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
@ -2180,7 +2202,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
RTLIL::IdString id = str;
|
||||
check_unique_id(current_module, id, this, "cell");
|
||||
RTLIL::Cell *cell = current_module->addCell(current_module->design->twines.add(std::string{id.str()}), Twine::Null);
|
||||
RTLIL::Cell *cell = current_module->addCell(intern_hier_name(current_module->design, id.str()), Twine::Null);
|
||||
set_src_attr(cell, this);
|
||||
|
||||
for (auto it = children.begin(); it != children.end(); it++) {
|
||||
|
|
@ -2251,6 +2273,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
cell->set_bool_attribute(ID::module_not_derived);
|
||||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.first == ID::src)
|
||||
continue;
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
input_error("Attribute `%s' with non-constant value.\n", attr.first);
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
|
|
|
|||
|
|
@ -69,15 +69,8 @@ std::string concat_name(RTLIL::Cell *cell, std::string_view object_name_view, co
|
|||
return prefix + tail;
|
||||
}
|
||||
|
||||
// Build the flattened name of a template object, given the instance's already
|
||||
// interned public/private prefix leaves. A name like "\a.b.c.w" is stored as
|
||||
// nested Suffix nodes Suffix{Suffix{Suffix{"\a.", "b."}, "c."}, "w"}. When the
|
||||
// template was itself flattened earlier its names are already such Suffixes, so
|
||||
// flattening instance "u" re-prefixes only the innermost leaf ("\a." -> "\u.a.")
|
||||
// and reuses the rest, yielding "\u.a.b.c.w" while keeping "b.", "c.", "w"
|
||||
// shared -- rather than materialising "a.b.c.w" as one fresh tail per object.
|
||||
TwineRef remap_flattened_name(RTLIL::Design *design, TwineRef obj_ref,
|
||||
TwineRef pub_prefix_ref, TwineRef priv_prefix_ref, dict<TwineRef, TwineRef> &memo)
|
||||
TwineRef pub_prefix_ref, TwineRef priv_prefix_ref, const std::string &separator, dict<TwineRef, TwineRef> &memo)
|
||||
{
|
||||
if (auto it = memo.find(obj_ref); it != memo.end())
|
||||
return it->second;
|
||||
|
|
@ -87,13 +80,13 @@ TwineRef remap_flattened_name(RTLIL::Design *design, TwineRef obj_ref,
|
|||
if (node.is_suffix()) {
|
||||
const Twine::Suffix &sfx = node.suffix();
|
||||
TwineRef prefix = remap_flattened_name(design, twine_tag(sfx.prefix, obj_ref.is_public()),
|
||||
pub_prefix_ref, priv_prefix_ref, memo);
|
||||
pub_prefix_ref, priv_prefix_ref, separator, memo);
|
||||
result = design->twines.add(Twine{Twine::Suffix{prefix, sfx.tail}});
|
||||
} else {
|
||||
std::string escaped = design->twines.str(obj_ref);
|
||||
std::string_view obj = escaped;
|
||||
if (!obj.empty() && obj[0] == '\\') {
|
||||
result = design->twines.add(Twine{Twine::Suffix{pub_prefix_ref, std::string(obj.substr(1))}});
|
||||
result = design->twines.add(Twine{Twine::Suffix{pub_prefix_ref, separator + std::string(obj.substr(1))}});
|
||||
} else {
|
||||
constexpr std::string_view flatten_prefix = "$flatten";
|
||||
if (obj.substr(0, flatten_prefix.size()) == flatten_prefix)
|
||||
|
|
@ -171,11 +164,11 @@ struct FlattenWorker
|
|||
{
|
||||
// Copy the contents of the flattened cell
|
||||
|
||||
TwineRef pub_prefix_ref = design->twines.add(cell->name.str() + separator);
|
||||
TwineRef pub_prefix_ref = cell->name.ref();
|
||||
TwineRef priv_prefix_ref = design->twines.add("$flatten" + cell->name.str() + separator);
|
||||
dict<TwineRef, TwineRef> remap_memo;
|
||||
auto make_name = [&](TwineRef obj_ref) -> TwineRef {
|
||||
return module->uniquify(remap_flattened_name(design, obj_ref, pub_prefix_ref, priv_prefix_ref, remap_memo));
|
||||
return module->uniquify(remap_flattened_name(design, obj_ref, pub_prefix_ref, priv_prefix_ref, separator, remap_memo));
|
||||
};
|
||||
|
||||
dict<std::string, TwineRef> memory_map;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "frontends/verific/verific.h"
|
||||
#include "frontends/ast/ast.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
|
|
@ -282,10 +283,11 @@ struct IFExpander
|
|||
// Go over all wires in interface, and add replacements to lists.
|
||||
std::string conn_name_str(design.twines.str(conn_name));
|
||||
for (auto mod_wire : mod_replace_ports->wires()) {
|
||||
std::string signal_name1 = conn_name_str + "." + design.twines.unescaped_str(mod_wire->name.ref());
|
||||
std::string signal_name2 = interface_name.str() + "." + design.twines.unescaped_str(mod_wire->name.ref());
|
||||
connections_to_add.push_back(design.twines.add(std::string{signal_name1}));
|
||||
TwineRef signal_name2_ref = TwineSearch(&design.twines).find(signal_name2);
|
||||
std::string member = design.twines.unescaped_str(mod_wire->name.ref());
|
||||
std::string signal_name1 = conn_name_str + "." + member;
|
||||
std::string signal_name2 = interface_name.str() + "." + member;
|
||||
connections_to_add.push_back(AST::intern_hier_name(&design, signal_name1));
|
||||
TwineRef signal_name2_ref = AST::intern_hier_name(&design, signal_name2);
|
||||
if(module.wire(signal_name2_ref) == nullptr) {
|
||||
log_error("Could not find signal '%s' in '%s'\n",
|
||||
signal_name2.c_str(), design.twines.str(module.meta_->name).data());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue