frontends: trivial twine damage

This commit is contained in:
Emil J. Tywoniak
2026-08-13 18:15:58 +02:00
parent 2686d1ce47
commit d8e0180ffb
9 changed files with 279 additions and 123 deletions
+8
View File
@@ -37,6 +37,14 @@ IdString read_idstring(std::istream &f)
return RTLIL::escape_id(str);
}
IdString resolve_sym(Design *design, const std::string &tok)
{
IdString ref = design->twines.ref_from_token(tok);
if (ref == IdString::Null)
log_error("Bad map file: '%s' is not a live name reference of this yosys run\n", tok.c_str());
return ref;
}
struct Xaiger2Frontend : public Frontend {
Xaiger2Frontend() : Frontend("xaiger2", "(experimental) read XAIGER file")
{
+3 -3
View File
@@ -34,14 +34,14 @@ AST::Binding::Binding(RTLIL::IdString target_type,
}
std::string
AST::Binding::describe() const
AST::Binding::describe(const RTLIL::Design *design) const
{
std::ostringstream oss;
oss << "directive to bind " << ast_node->str
<< " to " << target_name.str();
<< " to " << design->twines.str(target_name);
if (!target_type.empty())
oss << " (target type: "
<< target_type.str()
<< design->twines.str(target_type)
<< ")";
return oss.str();
}
+1 -1
View File
@@ -45,7 +45,7 @@ namespace AST
RTLIL::IdString target_name,
const AstNode &cell);
std::string describe() const override;
std::string describe(const RTLIL::Design *design) const override;
private:
// The syntax-level representation of the cell to be bound.
+37 -29
View File
@@ -57,7 +57,7 @@ static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count,
}
}
static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
static std::pair<std::string, int> wideports_split(std::string name)
{
int pos = -1;
@@ -78,10 +78,10 @@ static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
}
if (pos >= 0)
return std::pair<RTLIL::IdString, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1));
return std::pair<std::string, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1));
failed:
return std::pair<RTLIL::IdString, int>(RTLIL::IdString(), 0);
return std::pair<std::string, int>(std::string(), 0);
}
void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports)
@@ -115,11 +115,11 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
}
}
IdString wire_id = RTLIL::escape_id(wire_name);
Wire *wire = module->wire(wire_id);
IdString wire_ref = design->twines.add(RTLIL::escape_id(wire_name));
Wire *wire = module->wire(wire_ref);
if (wire == nullptr)
wire = module->addWire(wire_id);
wire = module->addWire(wire_ref);
return wire;
};
@@ -167,11 +167,12 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (module != nullptr)
goto error;
module = new RTLIL::Module;
module->design = design;
lastcell = nullptr;
char *name = strtok(NULL, " \t\r\n");
if (name == nullptr)
goto error;
module->name = RTLIL::escape_id(name);
module->name = design->twines.add(RTLIL::escape_id(name));
obj_attributes = &module->attributes;
obj_parameters = nullptr;
if (design->module(module->name))
@@ -202,8 +203,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
wire->port_output = !isinput;
for (int i = 0; i < width; i++) {
RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
RTLIL::Wire *other_wire = module->wire(other_name);
std::string other_name = design->twines.str(name) + stringf("[%d]", i);
IdString other_ref = design->twines.find(other_name);
RTLIL::Wire *other_wire = module->wire(other_ref);
if (other_wire) {
other_wire->port_input = false;
other_wire->port_output = false;
@@ -232,9 +234,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
for (auto cell : remove_cells)
module->remove(cell);
Wire *true_wire = module->wire(ID($true));
Wire *false_wire = module->wire(ID($false));
Wire *undef_wire = module->wire(ID($undef));
Wire *true_wire = module->wire(ID::lookup("$true"));
Wire *false_wire = module->wire(ID::lookup("$false"));
Wire *undef_wire = module->wire(ID::lookup("$undef"));
if (true_wire != nullptr)
module->rename(true_wire, stringf("$true$%d", ++blif_maxnum));
@@ -271,20 +273,22 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
char *p;
while ((p = strtok(NULL, " \t\r\n")) != NULL)
{
RTLIL::IdString wire_name(stringf("\\%s", p));
RTLIL::Wire *wire = module->wire(wire_name);
std::string wire_name_str = stringf("\\%s", p);
IdString wire_ref = design->twines.add(std::string{wire_name_str});
RTLIL::Wire *wire = module->wire(wire_ref);
if (wire == nullptr)
wire = module->addWire(wire_name);
wire = module->addWire(wire_ref);
if (!strcmp(cmd, ".inputs"))
wire->port_input = true;
else
wire->port_output = true;
if (wideports) {
std::pair<RTLIL::IdString, int> wp = wideports_split(p);
std::pair<std::string, int> wp = wideports_split(p);
if (!wp.first.empty() && wp.second >= 0) {
wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second + 1);
wideports_cache[wp.first].second = !strcmp(cmd, ".inputs");
IdString wp_ref = design->twines.add(std::string(wp.first));
wideports_cache[wp_ref].first = std::max(wideports_cache[wp_ref].first, wp.second + 1);
wideports_cache[wp_ref].second = !strcmp(cmd, ".inputs");
}
}
}
@@ -312,7 +316,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) {
char *n = strtok(NULL, " \t\r\n");
char *v = strtok(NULL, "\r\n");
IdString id_n = RTLIL::escape_id(n);
IdString id_n = design->twines.add(RTLIL::escape_id(n));
Const const_v;
if (v[0] == '"') {
std::string str(v+1);
@@ -372,7 +376,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
cell = module->addDlatchGate(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false);
else {
no_latch_clock:
if (dff_name.empty()) {
if (dff_name == IdString::Null) {
cell = module->addFfGate(NEW_ID, blif_wire(d), blif_wire(q));
} else {
cell = module->addCell(NEW_ID, dff_name);
@@ -393,9 +397,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (p == NULL)
goto error;
IdString celltype = RTLIL::escape_id(p);
IdString celltype = design->twines.add(RTLIL::escape_id(p));
RTLIL::Cell *cell = module->addCell(NEW_ID, celltype);
RTLIL::Module *cell_mod = design->module(celltype);
RTLIL::Module *cell_mod = design->module(cell->type);
dict<RTLIL::IdString, dict<int, SigBit>> cell_wideports_cache;
@@ -407,13 +411,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
*(q++) = 0;
if (wideports) {
std::pair<RTLIL::IdString, int> wp = wideports_split(p);
if (wp.first.empty())
cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
else
cell_wideports_cache[wp.first][wp.second] = blif_wire(q);
std::pair<std::string, int> wp = wideports_split(p);
if (wp.first.empty()) {
IdString port_ref = design->twines.add(RTLIL::escape_id(p));
cell->setPort(port_ref, *q ? blif_wire(q) : SigSpec());
} else {
IdString wp_ref = design->twines.add(std::string(wp.first));
cell_wideports_cache[wp_ref][wp.second] = blif_wire(q);
}
} else {
cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
IdString port_ref = design->twines.add(RTLIL::escape_id(p));
cell->setPort(port_ref, *q ? blif_wire(q) : SigSpec());
}
}
@@ -686,7 +694,7 @@ struct BlifFrontend : public Frontend {
}
extra_args(f, filename, args, argidx);
parse_blif(design, *f, "", true, sop_mode, wideports);
parse_blif(design, *f, IdString::Null, true, sop_mode, wideports);
}
} BlifFrontend;
+49 -48
View File
@@ -274,14 +274,14 @@ Const json_parse_attr_param_value(JsonNode *node)
return value;
}
void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
void json_parse_attr_param(RTLIL::Design *design, dict<IdString, Const> &results, JsonNode *node)
{
if (node->type != 'D')
log_error("JSON attributes or parameters node is not a dictionary.\n");
for (auto it : node->data_dict)
{
IdString key = RTLIL::escape_id(it.first.c_str());
IdString key = design->twines.add(RTLIL::escape_id(it.first.c_str()));
Const value = json_parse_attr_param_value(it.second);
results[key] = value;
}
@@ -292,7 +292,8 @@ void json_import(Design *design, string &modname, JsonNode *node)
log("Importing module %s from JSON tree.\n", modname);
Module *module = new RTLIL::Module;
module->name = RTLIL::escape_id(modname.c_str());
module->design = design;
module->name = design->twines.add(RTLIL::escape_id(modname));
if (design->module(module->name))
log_error("Re-definition of module %s.\n", module->name.unescape());
@@ -300,10 +301,10 @@ void json_import(Design *design, string &modname, JsonNode *node)
design->add(module);
if (node->data_dict.count("attributes"))
json_parse_attr_param(module->attributes, node->data_dict.at("attributes"));
json_parse_attr_param(design, module->attributes, node->data_dict.at("attributes"));
if (node->data_dict.count("parameter_default_values"))
json_parse_attr_param(module->parameter_default_values, node->data_dict.at("parameter_default_values"));
json_parse_attr_param(design, module->parameter_default_values, node->data_dict.at("parameter_default_values"));
dict<int, SigBit> signal_bits;
@@ -316,31 +317,31 @@ void json_import(Design *design, string &modname, JsonNode *node)
for (int port_id = 1; port_id <= GetSize(ports_node->data_dict_keys); port_id++)
{
IdString port_name = RTLIL::escape_id(ports_node->data_dict_keys[port_id-1].c_str());
IdString port_ref = design->twines.add(RTLIL::escape_id(ports_node->data_dict_keys[port_id-1]));
JsonNode *port_node = ports_node->data_dict.at(ports_node->data_dict_keys[port_id-1]);
if (port_node->type != 'D')
log_error("JSON port node '%s' is not a dictionary.\n", port_name.unescape());
log_error("JSON port node '%s' is not a dictionary.\n", PooledName(design, port_ref).unescape());
if (port_node->data_dict.count("direction") == 0)
log_error("JSON port node '%s' has no direction attribute.\n", port_name.unescape());
log_error("JSON port node '%s' has no direction attribute.\n", PooledName(design, port_ref).unescape());
if (port_node->data_dict.count("bits") == 0)
log_error("JSON port node '%s' has no bits attribute.\n", port_name.unescape());
log_error("JSON port node '%s' has no bits attribute.\n", PooledName(design, port_ref).unescape());
JsonNode *port_direction_node = port_node->data_dict.at("direction");
JsonNode *port_bits_node = port_node->data_dict.at("bits");
if (port_direction_node->type != 'S')
log_error("JSON port node '%s' has non-string direction attribute.\n", port_name.unescape());
log_error("JSON port node '%s' has non-string direction attribute.\n", PooledName(design, port_ref).unescape());
if (port_bits_node->type != 'A')
log_error("JSON port node '%s' has non-array bits attribute.\n", port_name.unescape());
log_error("JSON port node '%s' has non-array bits attribute.\n", PooledName(design, port_ref).unescape());
Wire *port_wire = module->wire(port_name);
Wire *port_wire = module->wire(port_ref);
if (port_wire == nullptr)
port_wire = module->addWire(port_name, GetSize(port_bits_node->data_array));
port_wire = module->addWire(port_ref, GetSize(port_bits_node->data_array));
if (port_node->data_dict.count("upto") != 0) {
JsonNode *val = port_node->data_dict.at("upto");
@@ -370,7 +371,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
port_wire->port_input = true;
port_wire->port_output = true;
} else
log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", port_name.unescape(), port_direction_node->data_string);
log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", PooledName(design, port_ref).unescape(), port_direction_node->data_string);
port_wire->port_id = port_id;
@@ -390,7 +391,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
module->connect(sigbit, State::Sz);
else
log_error("JSON port node '%s' has invalid '%s' bit string value on bit %d.\n",
port_name.unescape(), bitval_node->data_string.c_str(), i);
PooledName(design, port_ref).unescape(), bitval_node->data_string.c_str(), i);
} else
if (bitval_node->type == 'N') {
int bitidx = bitval_node->data_number;
@@ -405,7 +406,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
signal_bits[bitidx] = sigbit;
}
} else
log_error("JSON port node '%s' has invalid bit value on bit %d.\n", port_name.unescape(), i);
log_error("JSON port node '%s' has invalid bit value on bit %d.\n", PooledName(design, port_ref).unescape(), i);
}
}
@@ -421,24 +422,24 @@ void json_import(Design *design, string &modname, JsonNode *node)
for (auto &net : netnames_node->data_dict)
{
IdString net_name = RTLIL::escape_id(net.first.c_str());
IdString net_ref = design->twines.add(RTLIL::escape_id(net.first));
JsonNode *net_node = net.second;
if (net_node->type != 'D')
log_error("JSON netname node '%s' is not a dictionary.\n", net_name.unescape());
log_error("JSON netname node '%s' is not a dictionary.\n", PooledName(design, net_ref).unescape());
if (net_node->data_dict.count("bits") == 0)
log_error("JSON netname node '%s' has no bits attribute.\n", net_name.unescape());
log_error("JSON netname node '%s' has no bits attribute.\n", PooledName(design, net_ref).unescape());
JsonNode *bits_node = net_node->data_dict.at("bits");
if (bits_node->type != 'A')
log_error("JSON netname node '%s' has non-array bits attribute.\n", net_name.unescape());
log_error("JSON netname node '%s' has non-array bits attribute.\n", PooledName(design, net_ref).unescape());
Wire *wire = module->wire(net_name);
Wire *wire = module->wire(net_ref);
if (wire == nullptr)
wire = module->addWire(net_name, GetSize(bits_node->data_array));
wire = module->addWire(net_ref, GetSize(bits_node->data_array));
if (net_node->data_dict.count("upto") != 0) {
JsonNode *val = net_node->data_dict.at("upto");
@@ -468,7 +469,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
module->connect(sigbit, State::Sz);
else
log_error("JSON netname node '%s' has invalid '%s' bit string value on bit %d.\n",
net_name.unescape(), bitval_node->data_string.c_str(), i);
PooledName(design, net_ref).unescape(), bitval_node->data_string.c_str(), i);
} else
if (bitval_node->type == 'N') {
int bitidx = bitval_node->data_number;
@@ -479,11 +480,11 @@ void json_import(Design *design, string &modname, JsonNode *node)
signal_bits[bitidx] = sigbit;
}
} else
log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", net_name.unescape(), i);
log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", PooledName(design, net_ref).unescape(), i);
}
if (net_node->data_dict.count("attributes"))
json_parse_attr_param(wire->attributes, net_node->data_dict.at("attributes"));
json_parse_attr_param(design, wire->attributes, net_node->data_dict.at("attributes"));
}
}
@@ -496,39 +497,39 @@ void json_import(Design *design, string &modname, JsonNode *node)
for (auto &cell_node_it : cells_node->data_dict)
{
IdString cell_name = RTLIL::escape_id(cell_node_it.first.c_str());
IdString cell_ref = design->twines.add(RTLIL::escape_id(cell_node_it.first));
JsonNode *cell_node = cell_node_it.second;
if (cell_node->type != 'D')
log_error("JSON cells node '%s' is not a dictionary.\n", cell_name.unescape());
log_error("JSON cells node '%s' is not a dictionary.\n", PooledName(design, cell_ref).unescape());
if (cell_node->data_dict.count("type") == 0)
log_error("JSON cells node '%s' has no type attribute.\n", cell_name.unescape());
log_error("JSON cells node '%s' has no type attribute.\n", PooledName(design, cell_ref).unescape());
JsonNode *type_node = cell_node->data_dict.at("type");
if (type_node->type != 'S')
log_error("JSON cells node '%s' has a non-string type.\n", cell_name.unescape());
log_error("JSON cells node '%s' has a non-string type.\n", PooledName(design, cell_ref).unescape());
IdString cell_type = RTLIL::escape_id(type_node->data_string.c_str());
IdString cell_type = design->twines.add(RTLIL::escape_id(type_node->data_string));
Cell *cell = module->addCell(cell_name, cell_type);
Cell *cell = module->addCell(cell_ref, cell_type);
if (cell_node->data_dict.count("connections") == 0)
log_error("JSON cells node '%s' has no connections attribute.\n", cell_name.unescape());
log_error("JSON cells node '%s' has no connections attribute.\n", PooledName(design, cell_ref).unescape());
JsonNode *connections_node = cell_node->data_dict.at("connections");
if (connections_node->type != 'D')
log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", cell_name.unescape());
log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", PooledName(design, cell_ref).unescape());
for (auto &conn_it : connections_node->data_dict)
{
IdString conn_name = RTLIL::escape_id(conn_it.first.c_str());
IdString conn_ref = design->twines.add(RTLIL::escape_id(conn_it.first));
JsonNode *conn_node = conn_it.second;
if (conn_node->type != 'A')
log_error("JSON cells node '%s' connection '%s' is not an array.\n", cell_name.unescape(), conn_name.unescape());
log_error("JSON cells node '%s' connection '%s' is not an array.\n", PooledName(design, cell_ref).unescape(), PooledName(design, conn_ref).unescape());
SigSpec sig;
@@ -547,7 +548,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
sig.append(State::Sz);
else
log_error("JSON cells node '%s' connection '%s' has invalid '%s' bit string value on bit %d.\n",
cell_name.unescape(), conn_name.unescape(), bitval_node->data_string.c_str(), i);
PooledName(design, cell_ref).unescape(), PooledName(design, conn_ref).unescape(), bitval_node->data_string.c_str(), i);
} else
if (bitval_node->type == 'N') {
int bitidx = bitval_node->data_number;
@@ -556,18 +557,18 @@ void json_import(Design *design, string &modname, JsonNode *node)
sig.append(signal_bits.at(bitidx));
} else
log_error("JSON cells node '%s' connection '%s' has invalid bit value on bit %d.\n",
cell_name.unescape(), conn_name.unescape(), i);
PooledName(design, cell_ref).unescape(), PooledName(design, conn_ref).unescape(), i);
}
cell->setPort(conn_name, sig);
cell->setPort(conn_ref, sig);
}
if (cell_node->data_dict.count("attributes"))
json_parse_attr_param(cell->attributes, cell_node->data_dict.at("attributes"));
json_parse_attr_param(design, cell->attributes, cell_node->data_dict.at("attributes"));
if (cell_node->data_dict.count("parameters"))
json_parse_attr_param(cell->parameters, cell_node->data_dict.at("parameters"));
json_parse_attr_param(design, cell->parameters, cell_node->data_dict.at("parameters"));
}
}
@@ -580,27 +581,27 @@ void json_import(Design *design, string &modname, JsonNode *node)
for (auto &memory_node_it : memories_node->data_dict)
{
IdString memory_name = RTLIL::escape_id(memory_node_it.first.c_str());
JsonNode *memory_node = memory_node_it.second;
RTLIL::Memory *mem = new RTLIL::Memory;
mem->name = memory_name;
mem->name = design->twines.add(RTLIL::escape_id(memory_node_it.first));
mem->module = module;
if (memory_node->type != 'D')
log_error("JSON memory node '%s' is not a dictionary.\n", memory_name.unescape());
log_error("JSON memory node '%s' is not a dictionary.\n", mem->name.unescape());
if (memory_node->data_dict.count("width") == 0)
log_error("JSON memory node '%s' has no width attribute.\n", memory_name.unescape());
log_error("JSON memory node '%s' has no width attribute.\n", mem->name.unescape());
JsonNode *width_node = memory_node->data_dict.at("width");
if (width_node->type != 'N')
log_error("JSON memory node '%s' has a non-number width.\n", memory_name.unescape());
log_error("JSON memory node '%s' has a non-number width.\n", mem->name.unescape());
mem->width = width_node->data_number;
if (memory_node->data_dict.count("size") == 0)
log_error("JSON memory node '%s' has no size attribute.\n", memory_name.unescape());
log_error("JSON memory node '%s' has no size attribute.\n", mem->name.unescape());
JsonNode *size_node = memory_node->data_dict.at("size");
if (size_node->type != 'N')
log_error("JSON memory node '%s' has a non-number size.\n", memory_name.unescape());
log_error("JSON memory node '%s' has a non-number size.\n", mem->name.unescape());
mem->size = size_node->data_number;
mem->start_offset = 0;
@@ -611,7 +612,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
}
if (memory_node->data_dict.count("attributes"))
json_parse_attr_param(mem->attributes, memory_node->data_dict.at("attributes"));
json_parse_attr_param(design, mem->attributes, memory_node->data_dict.at("attributes"));
module->memories[mem->name] = mem;
}
+17 -10
View File
@@ -47,11 +47,13 @@ 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))
IdString wire_ref = module->design->twines.find(id);
RTLIL::Wire *w = module->wire(wire_ref);
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)
@@ -196,8 +198,10 @@ static void create_latch_ff_wires(RTLIL::Module *module, const LibertyAst *node)
static std::pair<RTLIL::SigSpec, RTLIL::SigSpec> find_latch_ff_wires(RTLIL::Module *module, const LibertyAst *node)
{
auto* iq_wire = module->wire(RTLIL::escape_id(node->args.at(0)));
auto* iqn_wire = module->wire(RTLIL::escape_id(node->args.at(1)));
IdString iq_ref = module->design->twines.find(RTLIL::escape_id(node->args.at(0)));
IdString iqn_ref = module->design->twines.find(RTLIL::escape_id(node->args.at(1)));
auto* iq_wire = module->wire(iq_ref);
auto* iqn_wire = module->wire(iqn_ref);
log_assert(iq_wire && iqn_wire);
return std::make_pair(iq_wire, iqn_wire);
}
@@ -239,7 +243,7 @@ static void create_ff(RTLIL::Module *module, const LibertyAst *node)
module->addNotGate(NEW_ID, q_sig, out_sig);
}
RTLIL::Cell* cell = module->addCell(NEW_ID, "");
RTLIL::Cell* cell = module->addCell(NEW_ID, IdString::Null);
cell->setPort(ID::D, data_sig);
cell->setPort(ID::Q, q_sig);
cell->setPort(ID::C, clk_sig);
@@ -505,8 +509,10 @@ struct LibertyFrontend : public Frontend {
parse_type_map(type_map, cell);
RTLIL::Module *module = new RTLIL::Module;
module->design = design;
std::string cell_name = RTLIL::escape_id(cell->args.at(0));
module->name = cell_name;
IdString cell_name_ref = design->twines.add(std::string{cell_name});
module->name = cell_name_ref;
if (flag_lib)
module->set_bool_attribute(ID::blackbox);
@@ -519,7 +525,7 @@ struct LibertyFrontend : public Frontend {
module->attributes[ID::area] = area->value;
for (auto &attr : attributes)
module->attributes[attr] = 1;
module->attributes[design->twines.add(std::string(attr))] = 1;
bool simple_comb_cell = true, has_outputs = false;
@@ -626,7 +632,8 @@ struct LibertyFrontend : public Frontend {
if (flag_lib && dir->value == "internal")
continue;
RTLIL::Wire *wire = module->wires_.at(RTLIL::escape_id(node->args.at(0)));
IdString wire_ref = module->design->twines.find(RTLIL::escape_id(node->args.at(0)));
RTLIL::Wire *wire = module->wire(wire_ref);
log_assert(wire);
const LibertyAst *capacitance = node->find("capacitance");
@@ -710,8 +717,8 @@ struct LibertyFrontend : public Frontend {
}
}
if (design->has(cell_name)) {
Module *existing_mod = design->module(cell_name);
if (design->has(cell_name_ref)) {
Module *existing_mod = design->module(cell_name_ref);
if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
log_error("Re-definition of cell/module %s!\n", RTLIL::unescape_id(cell_name));
} else if (flag_nooverwrite) {
+130
View File
@@ -491,6 +491,136 @@ struct RTLILFrontendWorker {
expect_eol();
}
bool static_ids_match(const std::vector<size_t> &ordered_ids)
{
for (size_t id : ordered_ids) {
if (id >= STATIC_TWINE_END)
continue;
const TwineDesc &desc = twine_descs.at(id);
IdString found;
if (desc.kind == TwineDesc::Leaf)
found = design->twines.find(Twine{Twine::Leaf{desc.text}});
else
found = design->twines.find(Twine{Twine::Suffix{
IdString(desc.parent), desc.text}});
if (found == IdString::Null || found.untag().raw() != id)
return false;
}
return true;
}
IdString resolve_file_twine(size_t id, bool is_public = false)
{
return materialize_file_twine(id).tag(is_public);
}
IdString materialize_file_twine(size_t id)
{
auto rit = twine_remap.find(id);
if (rit != twine_remap.end())
return rit->second;
auto dit = twine_descs.find(id);
if (dit == twine_descs.end()) {
if (id < STATIC_TWINE_END)
return IdString(id);
error("Unknown twine reference @%zu at line %d", id, line_num);
}
TwineDesc &desc = dit->second;
if (desc.materializing)
error("Cyclic twine reference @%zu at line %d", id, line_num);
desc.materializing = true;
IdString ref;
switch (desc.kind) {
case TwineDesc::Leaf:
ref = design->twines.add(Twine::Leaf{desc.text});
break;
case TwineDesc::Suffix:
ref = design->twines.add(Twine::Suffix{
materialize_file_twine(desc.parent),
desc.text});
break;
}
desc.materializing = false;
twine_remap[id] = ref;
return ref;
}
std::optional<IdString> try_parse_twine_handle()
{
bool is_public;
size_t prefix = IdString::handle_token_prefix(line, is_public);
if (prefix == 0)
return std::nullopt;
line = line.substr(prefix);
return resolve_file_twine(parse_integer(), is_public);
}
std::optional<IdString> try_parse_twine()
{
if (std::optional<IdString> handle = try_parse_twine_handle())
return handle;
std::optional<std::string> id = try_parse_id();
if (!id)
return std::nullopt;
return design->twines.add(std::move(*id));
}
IdString parse_twine()
{
std::optional<IdString> t = try_parse_twine();
if (!t)
error("Expected twine reference or ID, got `%s'.", error_token());
return *t;
}
void parse_twines()
{
expect_eol();
while (true) {
if (try_parse_keyword("end"))
break;
if (try_parse_keyword("leaf")) {
size_t file_id = parse_integer();
TwineDesc &desc = twine_descs[file_id];
desc.kind = TwineDesc::Leaf;
desc.text = parse_string();
expect_eol();
continue;
}
if (try_parse_keyword("suffix")) {
size_t file_id = parse_integer();
TwineDesc &desc = twine_descs[file_id];
desc.kind = TwineDesc::Suffix;
desc.parent = parse_integer();
desc.text = parse_string();
expect_eol();
continue;
}
error("Expected `leaf` or `suffix` inside twines block, got `%s'.",
error_token());
}
std::vector<size_t> ordered_ids;
ordered_ids.reserve(twine_descs.size());
for (auto &it : twine_descs)
ordered_ids.push_back(it.first);
std::sort(ordered_ids.begin(), ordered_ids.end());
if (static_ids_match(ordered_ids)) {
std::vector<size_t> dynamic_ids;
dynamic_ids.reserve(ordered_ids.size());
for (size_t id : ordered_ids) {
if (id < STATIC_TWINE_END)
twine_descs.erase(id);
else
dynamic_ids.push_back(id);
}
ordered_ids.swap(dynamic_ids);
}
for (size_t id : ordered_ids)
materialize_file_twine(id);
twine_descs.clear();
expect_eol();
}
void parse_parameter()
{
RTLIL::IdString id = parse_id();
+5 -3
View File
@@ -549,9 +549,11 @@ struct VerilogFrontend : public Frontend {
for (auto &child : parse_state.current_ast->children) {
if (child->type == AST::AST_MODULE)
for (auto &attr : attributes)
if (child->attributes.count(attr) == 0)
child->attributes[attr] = AST::AstNode::mkconst_int(top_loc, 1, false);
for (auto &attr : attributes) {
IdString attr_id = AST::intern_attr_name(attr);
if (child->attributes.count(attr_id) == 0)
child->attributes[attr_id] = AST::AstNode::mkconst_int(top_loc, 1, false);
}
}
if (flag_nodpi)
+29 -29
View File
@@ -69,10 +69,10 @@
struct ParseState {
int port_counter;
dict<std::string, int> port_stubs;
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr_list;
dict<IdString, std::unique_ptr<AstNode>> default_attr_list;
std::stack<std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>>> attr_list_stack;
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> albuf;
std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> attr_list;
dict<std::string, std::unique_ptr<AstNode>> default_attr_list;
std::stack<std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>>> attr_list_stack;
std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> albuf;
std::vector<UserTypeMap> user_type_stack;
dict<std::string, AstNode*> pkg_user_types;
std::vector<AstNode*> ast_stack;
@@ -98,15 +98,15 @@
bool isInLocalScope(const std::string *name);
void rewriteGenForDeclInit(AstNode *loop);
void ensureAsgnExprAllowed(const parser::location_type loc, bool sv_mode);
const AstNode *addIncOrDecStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> stmt_attr,
const AstNode *addIncOrDecStmt(std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> stmt_attr,
std::unique_ptr<AstNode> lhs,
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> op_attr, AST::AstNodeType op,
std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> op_attr, AST::AstNodeType op,
parser::location_type loc);
std::unique_ptr<AstNode> addIncOrDecExpr(std::unique_ptr<AstNode> lhs,
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> attr,
AST::AstNodeType op, parser::location_type loc, bool undo, bool sv_mode);
// add a binary operator assignment statement, e.g., a += b
std::unique_ptr<AstNode> addAsgnBinopStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<AstNode> addAsgnBinopStmt(std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<AstNode> eq_lhs, AST::AstNodeType op, std::unique_ptr<AstNode> rhs);
};
struct ParseMode {
@@ -154,17 +154,17 @@
return Location(begin.begin, end.end);
}
static void append_attr(AstNode *ast, std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> al)
static void append_attr(AstNode *ast, std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> al)
{
for (auto &it : *al) {
ast->attributes[it.first] = std::move(it.second);
ast->attributes[AST::intern_attr_name(it.first)] = std::move(it.second);
}
}
static void append_attr_clone(AstNode *ast, std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> &al)
static void append_attr_clone(AstNode *ast, std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> &al)
{
for (auto &it : *al) {
ast->attributes[it.first] = it.second->clone();
ast->attributes[AST::intern_attr_name(it.first)] = it.second->clone();
}
}
@@ -361,9 +361,9 @@
}
// add a pre/post-increment/decrement statement
const AstNode *ParseState::addIncOrDecStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> stmt_attr,
const AstNode *ParseState::addIncOrDecStmt(std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> stmt_attr,
std::unique_ptr<AstNode> lhs,
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> op_attr, AST::AstNodeType op,
std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> op_attr, AST::AstNodeType op,
Location loc)
{
auto one = AstNode::mkconst_int(loc, 1, true);
@@ -380,7 +380,7 @@
// create a pre/post-increment/decrement expression, and add the corresponding statement
std::unique_ptr<AstNode> ParseState::addIncOrDecExpr(std::unique_ptr<AstNode> lhs,
std::unique_ptr<dict<IdString,
std::unique_ptr<dict<std::string,
std::unique_ptr<AstNode>>> attr,
AST::AstNodeType op, Location loc, bool undo, bool sv_mode)
{
@@ -397,7 +397,7 @@
}
// add a binary operator assignment statement, e.g., a += b
std::unique_ptr<AstNode> ParseState::addAsgnBinopStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<AstNode> ParseState::addAsgnBinopStmt(std::unique_ptr<dict<std::string, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<AstNode> eq_lhs, AST::AstNodeType op, std::unique_ptr<AstNode> rhs)
{
Location loc = location_range(eq_lhs->location, rhs->location);
@@ -462,7 +462,7 @@
using string_t = std::unique_ptr<std::string>;
using ast_t = std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>;
using al_t = std::unique_ptr<YOSYS_NAMESPACE_PREFIX dict<YOSYS_NAMESPACE_PREFIX RTLIL::IdString, std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>>>;
using al_t = std::unique_ptr<YOSYS_NAMESPACE_PREFIX dict<std::string, std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>>>;
using specify_target_ptr_t = std::unique_ptr<struct specify_target>;
using specify_triple_ptr_t = std::unique_ptr<struct specify_triple>;
using specify_rise_fall_ptr_t = std::unique_ptr<struct specify_rise_fall>;
@@ -617,7 +617,7 @@ attr:
{
if (extra->attr_list)
extra->attr_list_stack.push(std::move(extra->attr_list));
extra->attr_list = std::make_unique<dict<IdString, std::unique_ptr<AstNode>>>();
extra->attr_list = std::make_unique<dict<std::string, std::unique_ptr<AstNode>>>();
for (auto &it : extra->default_attr_list)
(*extra->attr_list)[it.first] = it.second->clone();
} attr_opt {
@@ -639,7 +639,7 @@ defattr:
DEFATTR_BEGIN {
if (extra->attr_list != nullptr)
extra->attr_list_stack.push(std::move(extra->attr_list));
extra->attr_list = std::make_unique<dict<IdString, std::unique_ptr<AstNode>>>();
extra->attr_list = std::make_unique<dict<std::string, std::unique_ptr<AstNode>>>();
extra->default_attr_list.clear();
} opt_attr_list {
extra->attr_list->swap(extra->default_attr_list);
@@ -1302,7 +1302,7 @@ task_func_port:
if (!extra->astbuf1) {
if (!mode->sv)
err_at_loc(@$, "task/function argument direction missing");
extra->albuf = std::make_unique<dict<IdString, std::unique_ptr<AstNode>>>();
extra->albuf = std::make_unique<dict<std::string, std::unique_ptr<AstNode>>>();
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_WIRE);
extra->current_wire_rand = false;
extra->current_wire_const = false;
@@ -2911,7 +2911,7 @@ behavioral_stmt:
// we have to undangle it from the stack
patch_block_on_stack = true;
} else if (outer->get_bool_attribute(ID::full_case))
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false);
}
auto expr = std::make_unique<AstNode>(@$, AST_REDUCE_BOOL, std::move($4));
if (!node) {
@@ -2957,22 +2957,22 @@ if_attr:
AstNode *context = extra->ast_stack.back();
if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
err_at_loc(@2, "unique0 keyword cannot be used for 'else if' branch.");
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false);
$$ = std::move($1);
} |
attr TOK_PRIORITY {
AstNode *context = extra->ast_stack.back();
if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
err_at_loc(@2, "priority keyword cannot be used for 'else if' branch.");
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false);
$$ = std::move($1);
} |
attr TOK_UNIQUE {
AstNode *context = extra->ast_stack.back();
if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
err_at_loc(@2, "unique keyword cannot be used for 'else if' branch.");
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false);
$$ = std::move($1);
};
@@ -2981,16 +2981,16 @@ case_attr:
$$ = std::move($1);
} |
attr TOK_UNIQUE0 {
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false);
$$ = std::move($1);
} |
attr TOK_PRIORITY {
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false);
$$ = std::move($1);
} |
attr TOK_UNIQUE {
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false);
$$ = std::move($1);
};