aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/ast.cc292
-rw-r--r--frontends/ast/ast.h13
-rw-r--r--frontends/ast/genrtlil.cc158
-rw-r--r--frontends/ast/simplify.cc109
-rw-r--r--frontends/ilang/ilang_parser.y16
-rw-r--r--frontends/liberty/liberty.cc13
-rw-r--r--frontends/verific/verific.cc312
-rw-r--r--frontends/verific/verific.h1
-rw-r--r--frontends/verilog/verilog_lexer.l11
-rw-r--r--frontends/verilog/verilog_parser.y169
10 files changed, 775 insertions, 319 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index e79be953a..2c1561552 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -2,6 +2,7 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -171,8 +172,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
AstNode *attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
- log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n",
- id.c_str());
+ log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str());
return attr->integer != 0;
}
@@ -903,9 +903,9 @@ RTLIL::Const AstNode::realAsConst(int width)
}
// create a new AstModule from an AST_MODULE AST node
-static AstModule* process_module(AstNode *ast, bool defer)
+static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL)
{
- log_assert(ast->type == AST_MODULE);
+ log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
if (defer)
log("Storing AST representation for module `%s'.\n", ast->str.c_str());
@@ -916,9 +916,14 @@ static AstModule* process_module(AstNode *ast, bool defer)
current_module->ast = NULL;
current_module->name = ast->str;
current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum);
+ current_module->set_bool_attribute("\\cells_not_processed");
current_ast_mod = ast;
- AstNode *ast_before_simplify = ast->clone();
+ AstNode *ast_before_simplify;
+ if (original_ast != NULL)
+ ast_before_simplify = original_ast;
+ else
+ ast_before_simplify = ast->clone();
if (flag_dump_ast1) {
log("Dumping Verilog AST before simplification:\n");
@@ -963,8 +968,7 @@ static AstModule* process_module(AstNode *ast, bool defer)
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
current_module->attributes[attr.first] = attr.second->asAttrConst();
}
for (size_t i = 0; i < ast->children.size(); i++) {
@@ -989,6 +993,8 @@ static AstModule* process_module(AstNode *ast, bool defer)
ignoreThisSignalsInInitial = RTLIL::SigSpec();
}
+ if (ast->type == AST_INTERFACE)
+ current_module->set_bool_attribute("\\is_interface");
current_module->ast = ast_before_simplify;
current_module->nolatches = flag_nolatches;
current_module->nomeminit = flag_nomeminit;
@@ -1031,7 +1037,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
log_assert(current_ast->type == AST_DESIGN);
for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)
{
- if ((*it)->type == AST_MODULE)
+ if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE)
{
for (auto n : design->verilog_globals)
(*it)->children.push_back(n->clone());
@@ -1053,8 +1059,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (design->has((*it)->str)) {
RTLIL::Module *existing_mod = design->module((*it)->str);
if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
- log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n",
- (*it)->str.c_str());
+ log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s:%d.\n",
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
@@ -1083,8 +1088,264 @@ AstModule::~AstModule()
delete ast;
}
+
+// An interface port with modport is specified like this:
+// <interface_name>.<modport_name>
+// This function splits the interface_name from the modport_name, and fails if it is not a valid combination
+std::pair<std::string,std::string> AST::split_modport_from_type(std::string name_type)
+{
+ std::string interface_type = "";
+ std::string interface_modport = "";
+ size_t ndots = std::count(name_type.begin(), name_type.end(), '.');
+ // Separate the interface instance name from any modports:
+ if (ndots == 0) { // Does not have modport
+ interface_type = name_type;
+ }
+ else {
+ std::stringstream name_type_stream(name_type);
+ std::string segment;
+ std::vector<std::string> seglist;
+ while(std::getline(name_type_stream, segment, '.')) {
+ seglist.push_back(segment);
+ }
+ if (ndots == 1) { // Has modport
+ interface_type = seglist[0];
+ interface_modport = seglist[1];
+ }
+ else { // Erroneous port type
+ log_error("More than two '.' in signal port type (%s)\n", name_type.c_str());
+ }
+ }
+ return std::pair<std::string,std::string>(interface_type, interface_modport);
+
+}
+
+AstNode * AST::find_modport(AstNode *intf, std::string name)
+{
+ for (auto &ch : intf->children)
+ if (ch->type == AST_MODPORT)
+ if (ch->str == name) // Modport found
+ return ch;
+ return NULL;
+}
+
+// Iterate over all wires in an interface and add them as wires in the AST module:
+void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport)
+{
+ for (auto &wire_it : intfmodule->wires_){
+ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
+ std::string origname = log_id(wire_it.first);
+ std::string newname = intfname + "." + origname;
+ wire->str = newname;
+ if (modport != NULL) {
+ bool found_in_modport = false;
+ // Search for the current wire in the wire list for the current modport
+ for (auto &ch : modport->children) {
+ if (ch->type == AST_MODPORTMEMBER) {
+ std::string compare_name = "\\" + origname;
+ if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output
+ found_in_modport = true;
+ wire->is_input = ch->is_input;
+ wire->is_output = ch->is_output;
+ break;
+ }
+ }
+ }
+ if (found_in_modport) {
+ module_ast->children.push_back(wire);
+ }
+ else { // If not found in modport, do not create port
+ delete wire;
+ }
+ }
+ else { // If no modport, set inout
+ wire->is_input = true;
+ wire->is_output = true;
+ module_ast->children.push_back(wire);
+ }
+ }
+}
+
+// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
+// from AST. The interface members are copied into the AST module with the prefix of the interface.
+void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module*> local_interfaces)
+{
+ bool is_top = false;
+ AstNode *new_ast = ast->clone();
+ for (auto &intf : local_interfaces) {
+ std::string intfname = intf.first.str();
+ RTLIL::Module *intfmodule = intf.second;
+ for (auto &wire_it : intfmodule->wires_){
+ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
+ std::string newname = log_id(wire_it.first);
+ newname = intfname + "." + newname;
+ wire->str = newname;
+ new_ast->children.push_back(wire);
+ }
+ }
+
+ AstNode *ast_before_replacing_interface_ports = new_ast->clone();
+
+ // Explode all interface ports. Note this will only have an effect on 'top
+ // level' modules. Other sub-modules will have their interface ports
+ // exploded via the derive(..) function
+ for (size_t i =0; i<new_ast->children.size(); i++)
+ {
+ AstNode *ch2 = new_ast->children[i];
+ if (ch2->type == AST_INTERFACEPORT) { // Is an interface port
+ std::string name_port = ch2->str; // Name of the interface port
+ if (ch2->children.size() > 0) {
+ for(size_t j=0; j<ch2->children.size();j++) {
+ AstNode *ch = ch2->children[j];
+ if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface
+ std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
+ std::string interface_type = res.first;
+ std::string interface_modport = res.second; // Is "", if no modport
+ if (design->modules_.count(interface_type) > 0) {
+ // Add a cell to the module corresponding to the interface port such that
+ // it can further propagated down if needed:
+ AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE);
+ celltype_for_intf->str = interface_type;
+ AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf);
+ cell_for_intf->str = name_port + "_inst_from_top_dummy";
+ new_ast->children.push_back(cell_for_intf);
+
+ // Get all members of this non-overridden dummy interface instance:
+ RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming
+ // reprocess_module is called from the hierarchy pass) be
+ // present in design->modules_
+ AstModule *ast_module_of_interface = (AstModule*)intfmodule;
+ std::string interface_modport_compare_str = "\\" + interface_modport;
+ AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport
+ // Iterate over all wires in the interface and add them to the module:
+ explode_interface_port(new_ast, intfmodule, name_port, modport);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // The old module will be deleted. Rename and mark for deletion:
+ std::string original_name = this->name.str();
+ std::string changed_name = original_name + "_before_replacing_local_interfaces";
+ design->rename(this, changed_name);
+ this->set_bool_attribute("\\to_delete");
+
+ // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
+ // new module.
+ if (this->get_bool_attribute("\\initial_top")) {
+ this->attributes.erase("\\initial_top");
+ is_top = true;
+ }
+
+ // Generate RTLIL from AST for the new module and add to the design:
+ AstModule *newmod = process_module(new_ast, false, ast_before_replacing_interface_ports);
+ delete(new_ast);
+ design->add(newmod);
+ RTLIL::Module* mod = design->module(original_name);
+ if (is_top)
+ mod->set_bool_attribute("\\top");
+
+ // Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
+ mod->set_bool_attribute("\\interfaces_replaced_in_module");
+}
+
+// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
+// This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail)
+{
+ AstNode *new_ast = NULL;
+ std::string modname = derive_common(design, parameters, &new_ast, mayfail);
+
+ // Since interfaces themselves may be instantiated with different parameters,
+ // "modname" must also take those into account, so that unique modules
+ // are derived for any variant of interface connections:
+ std::string interf_info = "";
+
+ bool has_interfaces = false;
+ for(auto &intf : interfaces) {
+ interf_info += log_id(intf.second->name);
+ has_interfaces = true;
+ }
+
+ if (has_interfaces)
+ modname += "$interfaces$" + interf_info;
+
+
+ if (!design->has(modname)) {
+ new_ast->str = modname;
+
+ // Iterate over all interfaces which are ports in this module:
+ for(auto &intf : interfaces) {
+ RTLIL::Module * intfmodule = intf.second;
+ std::string intfname = intf.first.str();
+ // Check if a modport applies for the interface port:
+ AstNode *modport = NULL;
+ if (modports.count(intfname) > 0) {
+ std::string interface_modport = modports.at(intfname).str();
+ AstModule *ast_module_of_interface = (AstModule*)intfmodule;
+ AstNode *ast_node_of_interface = ast_module_of_interface->ast;
+ modport = find_modport(ast_node_of_interface, interface_modport);
+ }
+ // Iterate over all wires in the interface and add them to the module:
+ explode_interface_port(new_ast, intfmodule, intfname, modport);
+ }
+
+ design->add(process_module(new_ast, false));
+ design->module(modname)->check();
+
+ RTLIL::Module* mod = design->module(modname);
+
+ // Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
+ for(auto &intf : interfaces) {
+ if(mod->wires_.count(intf.first)) {
+ mod->wires_.erase(intf.first);
+ mod->fixup_ports();
+ // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated
+ // down to sub-sub-modules etc.
+ RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name);
+ new_subcell->set_bool_attribute("\\is_interface");
+ }
+ else {
+ log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str());
+ }
+ }
+
+ // If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
+ if (interfaces.size() > 0) {
+ mod->set_bool_attribute("\\interfaces_replaced_in_module");
+ }
+
+ } else {
+ log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
+ }
+
+ delete new_ast;
+ return modname;
+}
+
+// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail)
+{
+ AstNode *new_ast = NULL;
+ std::string modname = derive_common(design, parameters, &new_ast, mayfail);
+
+ if (!design->has(modname)) {
+ new_ast->str = modname;
+ design->add(process_module(new_ast, false));
+ design->module(modname)->check();
+ } else {
+ log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
+ }
+
+ delete new_ast;
+ return modname;
+}
+
// create a new parametric module (when needed) and return the name of the generated module
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool)
+std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool)
{
std::string stripped_name = name.str();
@@ -1156,15 +1417,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
else
modname = "$paramod" + stripped_name + para_info;
- if (!design->has(modname)) {
- new_ast->str = modname;
- design->add(process_module(new_ast, false));
- design->module(modname)->check();
- } else {
- log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
- }
- delete new_ast;
+ (*new_ast_out) = new_ast;
return modname;
}
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 7e97bdb3b..08f91c9c3 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -142,6 +142,11 @@ namespace AST
AST_NEGEDGE,
AST_EDGE,
+ AST_INTERFACE,
+ AST_INTERFACEPORT,
+ AST_INTERFACEPORTTYPE,
+ AST_MODPORT,
+ AST_MODPORTMEMBER,
AST_PACKAGE
};
@@ -284,6 +289,9 @@ namespace AST
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
~AstModule() YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
+ RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
+ std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail);
+ void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;
RTLIL::Module *clone() const YS_OVERRIDE;
};
@@ -300,6 +308,11 @@ namespace AST
// call a DPI function
AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args);
+
+ // Helper functions related to handling SystemVerilog interfaces
+ std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
+ AstNode * find_modport(AstNode *intf, std::string name);
+ void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport);
}
namespace AST_INTERNAL
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index c9345ff08..9531dd356 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -55,8 +55,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
if (gen_attributes)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -89,8 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
if (that != NULL)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -117,8 +115,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -152,8 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -480,8 +476,7 @@ struct AST_INTERNAL::ProcessGenerator
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
sw->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -648,8 +643,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
delete left_at_zero_ast;
delete right_at_zero_ast;
@@ -778,7 +772,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
if (children[0]->type != AST_CONSTANT)
log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
- RTLIL::unescape_id(str).c_str());
+ RTLIL::unescape_id(str).c_str());
width_hint = max(width_hint, int(children[0]->asInt(true)));
}
break;
@@ -799,8 +793,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
default:
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
- log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n",
- type2str(type).c_str());
+ log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
}
if (*found_real)
@@ -853,6 +846,35 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_GENIF:
case AST_GENCASE:
case AST_PACKAGE:
+ case AST_MODPORT:
+ case AST_MODPORTMEMBER:
+ break;
+ case AST_INTERFACEPORT: {
+ // If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
+ // This is used by the hierarchy pass to know when it can replace interface connection with the individual
+ // signals.
+ RTLIL::Wire *wire = current_module->addWire(str, 1);
+ wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
+ wire->start_offset = 0;
+ wire->port_id = port_id;
+ wire->port_input = true;
+ wire->port_output = true;
+ wire->set_bool_attribute("\\is_interface");
+ if (children.size() > 0) {
+ for(size_t i=0; i<children.size();i++) {
+ if(children[i]->type == AST_INTERFACEPORTTYPE) {
+ std::pair<std::string,std::string> res = AST::split_modport_from_type(children[i]->str);
+ wire->attributes["\\interface_type"] = res.first;
+ if (res.second != "")
+ wire->attributes["\\interface_modport"] = res.second;
+ break;
+ }
+ }
+ }
+ wire->upto = 0;
+ }
+ break;
+ case AST_INTERFACEPORTTYPE:
break;
// remember the parameter, needed for example in techmap
@@ -863,11 +885,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Wire for an AST_WIRE node
case AST_WIRE: {
if (current_module->wires_.count(str) != 0)
- log_file_error(filename, linenum, "Re-definition of signal `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str());
if (!range_valid)
- log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str());
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
@@ -881,8 +901,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
wire->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -891,16 +910,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Memory for an AST_MEMORY node
case AST_MEMORY: {
if (current_module->memories.count(str) != 0)
- log_file_error(filename, linenum, "Re-definition of memory `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str());
log_assert(children.size() >= 2);
log_assert(children[0]->type == AST_RANGE);
log_assert(children[1]->type == AST_RANGE);
if (!children[0]->range_valid || !children[1]->range_valid)
- log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str());
RTLIL::Memory *memory = new RTLIL::Memory;
memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -917,8 +934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
memory->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -937,8 +953,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_REALVALUE:
{
RTLIL::SigSpec sig = realAsConst(width_hint);
- log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
- realvalue, log_signal(sig));
+ log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
return sig;
}
@@ -949,6 +964,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
{
RTLIL::Wire *wire = NULL;
RTLIL::SigChunk chunk;
+ bool is_interface = false;
int add_undef_bits_msb = 0;
int add_undef_bits_lsb = 0;
@@ -964,19 +980,42 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
if (id2ast->children[0]->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str());
chunk = RTLIL::Const(id2ast->children[0]->bits);
goto use_const_chunk;
}
- else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
- id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
- log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
- str.c_str());
+ else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
+ RTLIL::Wire *current_wire = current_module->wire(str);
+ if (current_wire->get_bool_attribute("\\is_interface"))
+ is_interface = true;
+ // Ignore
+ }
+ // If an identifier is found that is not already known, assume that it is an interface:
+ else if (1) { // FIXME: Check if sv_mode first?
+ is_interface = true;
+ }
+ else {
+ log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str());
+ }
if (id2ast->type == AST_MEMORY)
- log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str());
+
+ // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface'
+ // This makes it possible for the hierarchy pass to see what are interface connections and then replace them
+ // with the individual signals:
+ if (is_interface) {
+ RTLIL::Wire *dummy_wire;
+ std::string dummy_wire_name = "$dummywireforinterface" + str;
+ if (current_module->wires_.count(dummy_wire_name))
+ dummy_wire = current_module->wires_[dummy_wire_name];
+ else {
+ dummy_wire = current_module->addWire(dummy_wire_name);
+ dummy_wire->set_bool_attribute("\\is_interface");
+ }
+ RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire);
+ return tmp;
+ }
wire = current_module->wires_[str];
chunk.wire = wire;
@@ -995,8 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone());
@@ -1025,10 +1063,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
if (chunk.width == 1)
log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
- str.c_str());
+ str.c_str());
else
- log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n",
- str.c_str(), chunk.width);
+ log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
+ children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);
chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
} else {
if (chunk.width + chunk.offset > source_width) {
@@ -1041,11 +1079,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
chunk.offset += add_undef_bits_lsb;
}
if (add_undef_bits_lsb)
- log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
- str.c_str(), add_undef_bits_lsb);
+ log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
+ children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);
if (add_undef_bits_msb)
- log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
- str.c_str(), add_undef_bits_msb);
+ log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
+ children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);
}
}
}
@@ -1380,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -1403,9 +1440,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
new_right.append(right[i]);
}
log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
- " old assignment: %s = %s\n new assignment: %s = %s.\n",
- log_signal(left), log_signal(right),
- log_signal(new_left), log_signal(new_right));
+ " old assignment: %s = %s\n new assignment: %s = %s.\n",
+ log_signal(left), log_signal(right),
+ log_signal(new_left), log_signal(new_right));
left = new_left;
right = new_right;
}
@@ -1423,6 +1460,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::Cell *cell = current_module->addCell(str, "");
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
+ // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
+ cell->set_bool_attribute("\\module_not_derived");
for (auto it = children.begin(); it != children.end(); it++) {
AstNode *child = *it;
@@ -1436,14 +1475,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
if (child->children[0]->type == AST_REALVALUE) {
log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n",
- log_id(cell), log_id(paraname), child->children[0]->realvalue);
+ log_id(cell), log_id(paraname), child->children[0]->realvalue);
auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
strnode->cloneInto(child->children[0]);
delete strnode;
}
if (child->children[0]->type != AST_CONSTANT)
log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n",
- log_id(cell), log_id(paraname));
+ log_id(cell), log_id(paraname));
cell->parameters[paraname] = child->children[0]->asParaConst();
continue;
}
@@ -1464,8 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
- attr.first.c_str());
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -1493,18 +1531,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (GetSize(children) > 1)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n",
- RTLIL::unescape_id(str).c_str(), GetSize(children));
+ RTLIL::unescape_id(str).c_str(), GetSize(children));
if (GetSize(children) == 1) {
if (children[0]->type != AST_CONSTANT)
log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
- RTLIL::unescape_id(str).c_str());
+ RTLIL::unescape_id(str).c_str());
width = children[0]->asInt(true);
}
if (width <= 0)
- log_file_error(filename, linenum, "Failed to detect width of %s!\n",
- RTLIL::unescape_id(str).c_str());
+ log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());
Cell *cell = current_module->addCell(myid, str.substr(1));
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -1531,8 +1568,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
type_name = type2str(type);
- log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n",
- type_name.c_str());
+ log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str());
}
return RTLIL::SigSpec();
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 71eba547c..83714f897 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (stage == 0)
{
- log_assert(type == AST_MODULE);
+ log_assert(type == AST_MODULE || type == AST_INTERFACE);
last_blocking_assignment_warn = pair<string, int>();
deep_recursion_warning = true;
@@ -196,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
int nargs = GetSize(children);
if (nargs < 1)
log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
- str.c_str(), int(children.size()));
+ str.c_str(), int(children.size()));
// First argument is the format string
AstNode *node_string = children[0];
@@ -240,7 +240,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
case 'X':
if (next_arg >= GetSize(children))
log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
- cformat, str.c_str());
+ cformat, str.c_str());
node_arg = children[next_arg++];
while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
@@ -450,8 +450,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
- if (type == AST_ASSIGN && children[0]->id2ast->is_reg)
- log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
+ if (type == AST_ASSIGN && children[0]->id2ast->is_reg) {
+ bool is_rand_reg = false;
+ if (children[1]->type == AST_FCALL) {
+ if (children[1]->str == "\\$anyconst")
+ is_rand_reg = true;
+ if (children[1]->str == "\\$anyseq")
+ is_rand_reg = true;
+ if (children[1]->str == "\\$allconst")
+ is_rand_reg = true;
+ if (children[1]->str == "\\$allseq")
+ is_rand_reg = true;
+ }
+ if (!is_rand_reg)
+ log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
+ }
children[0]->was_checked = true;
}
break;
@@ -732,7 +745,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (current_scope.at(modname)->type != AST_CELL)
log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
- RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
+ RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
paraset->str = paramname;
@@ -880,7 +893,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (children[0]->type == AST_REALVALUE) {
RTLIL::Const constvalue = children[0]->realAsConst(width);
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
- children[0]->realvalue, log_signal(constvalue));
+ children[0]->realvalue, log_signal(constvalue));
delete children[0];
children[0] = mkconst_bits(constvalue.bits, sign_hint);
did_something = true;
@@ -1299,8 +1312,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PRIMITIVE)
{
if (children.size() < 2)
- log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());
std::vector<AstNode*> children_list;
for (auto child : children) {
@@ -1315,8 +1327,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
{
if (children_list.size() != 3)
- log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str());
std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
@@ -1336,6 +1347,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
str.clear();
type = AST_ASSIGN;
children.push_back(children_list.at(0));
+ children.back()->was_checked = true;
children.push_back(node);
did_something = true;
}
@@ -1372,6 +1384,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
str.clear();
type = AST_ASSIGN;
children.push_back(children_list[0]);
+ children.back()->was_checked = true;
children.push_back(node);
did_something = true;
}
@@ -1401,8 +1414,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
- str.c_str());
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
}
did_something = true;
@@ -1530,6 +1542,7 @@ skip_dynamic_range_lvalue_expansion:;
wire_tmp_id->str = wire_tmp->str;
newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone()));
+ newNode->children.back()->was_checked = true;
int cursor = 0;
for (auto child : children[0]->children)
@@ -1772,11 +1785,11 @@ skip_dynamic_range_lvalue_expansion:;
if (GetSize(children) != 1 && GetSize(children) != 2)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
if (!current_always_clocked)
log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
- RTLIL::unescape_id(str).c_str());
+ RTLIL::unescape_id(str).c_str());
if (GetSize(children) == 2)
{
@@ -1797,6 +1810,11 @@ skip_dynamic_range_lvalue_expansion:;
log_assert(block != nullptr);
+ if (num_steps == 0) {
+ newNode = children[0]->clone();
+ goto apply_newNode;
+ }
+
int myidx = autoidx++;
AstNode *outreg = nullptr;
@@ -1815,6 +1833,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *regid = new AstNode(AST_IDENTIFIER);
regid->str = reg->str;
regid->id2ast = reg;
+ regid->was_checked = true;
AstNode *rhs = nullptr;
@@ -1840,11 +1859,11 @@ skip_dynamic_range_lvalue_expansion:;
{
if (GetSize(children) != 1)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
if (!current_always_clocked)
log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
- RTLIL::unescape_id(str).c_str());
+ RTLIL::unescape_id(str).c_str());
AstNode *present = children.at(0)->clone();
AstNode *past = clone();
@@ -1857,10 +1876,14 @@ skip_dynamic_range_lvalue_expansion:;
newNode = new AstNode(AST_NE, past, present);
else if (str == "\\$rose")
- newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present);
+ newNode = new AstNode(AST_LOGIC_AND,
+ new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))),
+ new AstNode(AST_BIT_AND, present, mkconst_int(1,false)));
else if (str == "\\$fell")
- newNode = new AstNode(AST_LOGIC_AND, past, new AstNode(AST_LOGIC_NOT, present));
+ newNode = new AstNode(AST_LOGIC_AND,
+ new AstNode(AST_BIT_AND, past, mkconst_int(1,false)),
+ new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false))));
else
log_abort();
@@ -1878,7 +1901,7 @@ skip_dynamic_range_lvalue_expansion:;
{
if (children.size() != 1)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
AstNode *buf = children[0]->clone();
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
@@ -1895,7 +1918,7 @@ skip_dynamic_range_lvalue_expansion:;
if (arg_value.bits.at(i) == RTLIL::State::S1)
result = i + 1;
- newNode = mkconst_int(result, false);
+ newNode = mkconst_int(result, true);
goto apply_newNode;
}
@@ -1903,11 +1926,11 @@ skip_dynamic_range_lvalue_expansion:;
{
if (str == "\\$bits" && children.size() != 1)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
if (str == "\\$size" && children.size() != 1 && children.size() != 2)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
int dim = 1;
if (str == "\\$size" && children.size() == 2) {
@@ -1981,18 +2004,18 @@ skip_dynamic_range_lvalue_expansion:;
if (func_with_two_arguments) {
if (children.size() != 2)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
} else {
if (children.size() != 1)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
}
if (children.size() >= 1) {
while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (!children[0]->isConst())
log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
- RTLIL::unescape_id(str).c_str());
+ RTLIL::unescape_id(str).c_str());
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
children[0]->detectSignWidth(child_width_hint, child_sign_hint);
@@ -2003,7 +2026,7 @@ skip_dynamic_range_lvalue_expansion:;
while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (!children[1]->isConst())
log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
- RTLIL::unescape_id(str).c_str());
+ RTLIL::unescape_id(str).c_str());
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
children[1]->detectSignWidth(child_width_hint, child_sign_hint);
@@ -2091,7 +2114,7 @@ skip_dynamic_range_lvalue_expansion:;
{
if (GetSize(children) < 2 || GetSize(children) > 4)
log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
AstNode *node_filename = children[0]->clone();
while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
@@ -2204,6 +2227,8 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,
new AstNode(AST_ASSIGN_EQ, lvalue, clone())));
+ always->children[0]->children[0]->was_checked = true;
+
current_ast_mod->children.push_back(always);
goto replace_fcall_with_id;
@@ -2253,6 +2278,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *assign = child->is_input ?
new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :
new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone());
+ assign->children[0]->was_checked = true;
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
if (*it != current_block_child)
@@ -2323,6 +2349,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *assign = child->is_input ?
new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
new AstNode(AST_ASSIGN_EQ, arg, wire_id);
+ assign->children[0]->was_checked = true;
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
if (*it != current_block_child)
@@ -2762,6 +2789,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
block->children.back()->children[0]->str = memory->str;
block->children.back()->children[0]->id2ast = memory;
+ block->children.back()->children[0]->was_checked = true;
}
cursor += increment;
@@ -3022,6 +3050,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
AstNode *newNode = clone();
newNode->type = AST_ASSIGN_EQ;
+ newNode->children[0]->was_checked = true;
async_block->children[0]->children.push_back(newNode);
newNode = new AstNode(AST_NONE);
@@ -3067,6 +3096,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
assign_addr->children[0]->str = id_addr;
+ assign_addr->children[0]->was_checked = true;
block->children.insert(block->children.begin()+assign_idx+1, assign_addr);
AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
@@ -3090,6 +3120,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
children[0]->id2ast = NULL;
children[0]->str = id_data;
type = AST_ASSIGN_EQ;
+ children[0]->was_checked = true;
did_something = true;
}
@@ -3247,12 +3278,12 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
if (!children.empty()) {
if (children.size() != 1 || children.at(0)->type != AST_RANGE)
log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
children.at(0)->replace_variables(variables, fcall);
while (simplify(true, false, false, 1, -1, false, true)) { }
if (!children.at(0)->range_valid)
log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
offset = min(children.at(0)->range_left, children.at(0)->range_right);
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
}
@@ -3292,7 +3323,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (child->simplify(true, false, false, 1, -1, false, true)) { }
if (!child->range_valid)
log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
- child->str.c_str(), fcall->filename.c_str(), fcall->linenum);
+ child->str.c_str(), fcall->filename.c_str(), fcall->linenum);
variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
variables[child->str].offset = min(child->range_left, child->range_right);
variables[child->str].is_signed = child->is_signed;
@@ -3336,15 +3367,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (stmt->children.at(1)->type != AST_CONSTANT)
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
if (stmt->children.at(0)->type != AST_IDENTIFIER)
log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
if (!variables.count(stmt->children.at(0)->str))
log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
if (stmt->children.at(0)->children.empty()) {
variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
@@ -3352,7 +3383,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
AstNode *range = stmt->children.at(0)->children.at(0);
if (!range->range_valid)
log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
int offset = min(range->range_left, range->range_right);
int width = std::abs(range->range_left - range->range_right) + 1;
varinfo_t &v = variables[stmt->children.at(0)->str];
@@ -3384,7 +3415,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (cond->type != AST_CONSTANT)
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
if (cond->asBool()) {
block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
@@ -3405,7 +3436,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (num->type != AST_CONSTANT)
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
block->children.erase(block->children.begin());
for (int i = 0; i < num->bitsAsConst().as_int(); i++)
@@ -3443,7 +3474,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (cond->type != AST_CONSTANT)
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
found_match = cond->asBool();
delete cond;
@@ -3473,7 +3504,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
}
log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ fcall->filename.c_str(), fcall->linenum);
log_abort();
}
diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y
index bfc062fec..b957ecd96 100644
--- a/frontends/ilang/ilang_parser.y
+++ b/frontends/ilang/ilang_parser.y
@@ -387,17 +387,13 @@ sigspec:
$$ = new RTLIL::SigSpec(current_module->wires_[$1]);
free($1);
} |
- TOK_ID '[' TOK_INT ']' {
- if (current_module->wires_.count($1) == 0)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
- $$ = new RTLIL::SigSpec(current_module->wires_[$1], $3);
- free($1);
+ sigspec '[' TOK_INT ']' {
+ $$ = new RTLIL::SigSpec($1->extract($3));
+ delete $1;
} |
- TOK_ID '[' TOK_INT ':' TOK_INT ']' {
- if (current_module->wires_.count($1) == 0)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
- $$ = new RTLIL::SigSpec(current_module->wires_[$1], $5, $3 - $5 + 1);
- free($1);
+ sigspec '[' TOK_INT ':' TOK_INT ']' {
+ $$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
+ delete $1;
} |
'{' sigspec_list '}' {
$$ = $2;
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index 0a5bd84de..4acfbf1cb 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -36,7 +36,8 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
int id_len = 0;
while (('a' <= expr[id_len] && expr[id_len] <= 'z') || ('A' <= expr[id_len] && expr[id_len] <= 'Z') ||
- ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || expr[id_len] == '_') id_len++;
+ ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' ||
+ expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++;
if (id_len == 0)
log_error("Expected identifier at `%s'.\n", expr);
@@ -634,9 +635,12 @@ struct LibertyFrontend : public Frontend {
}
}
- for (auto node : cell->children)
+ if (!flag_lib)
{
- if (!flag_lib) {
+ // some liberty files do not put ff/latch at the beginning of a cell
+ // try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes
+ for (auto node : cell->children)
+ {
if (node->id == "ff" && node->args.size() == 2)
create_ff(module, node);
if (node->id == "latch" && node->args.size() == 2)
@@ -645,7 +649,10 @@ struct LibertyFrontend : public Frontend {
goto skip_cell;
}
}
+ }
+ for (auto node : cell->children)
+ {
if (node->id == "pin" && node->args.size() == 1)
{
LibertyAst *dir = node->find("direction");
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index dba3b0f0c..61d9d593c 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -130,6 +130,15 @@ bool is_blackbox(Netlist *nl)
return false;
}
+RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
+{
+ std::string s = stringf("$verific$%s", obj->Name());
+ if (obj->Linefile())
+ s += stringf("$%s:%d", Verific::LineFile::GetFileName(obj->Linefile()), Verific::LineFile::GetLineNo(obj->Linefile()));
+ s += stringf("$%d", autoidx++);
+ return s;
+}
+
void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)
{
MapIter mi;
@@ -215,7 +224,7 @@ RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*,
dummy_wire = NULL;
} else {
if (dummy_wire == NULL)
- dummy_wire = module->addWire(NEW_ID);
+ dummy_wire = module->addWire(new_verific_id(inst));
else
dummy_wire->width++;
sig.append(RTLIL::SigSpec(dummy_wire, dummy_wire->width - 1));
@@ -231,8 +240,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
}
if (inst->Type() == PRIM_NAND) {
- RTLIL::SigSpec tmp = module->addWire(NEW_ID);
- module->addAndGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
+ RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
+ module->addAndGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput()));
return true;
}
@@ -243,8 +252,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
}
if (inst->Type() == PRIM_NOR) {
- RTLIL::SigSpec tmp = module->addWire(NEW_ID);
- module->addOrGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
+ RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
+ module->addOrGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput()));
return true;
}
@@ -284,16 +293,16 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
if (inst->Type() == PRIM_FADD)
{
RTLIL::SigSpec a = net_map_at(inst->GetInput1()), b = net_map_at(inst->GetInput2()), c = net_map_at(inst->GetCin());
- RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(NEW_ID);
- RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID);
- RTLIL::SigSpec tmp1 = module->addWire(NEW_ID);
- RTLIL::SigSpec tmp2 = module->addWire(NEW_ID);
- RTLIL::SigSpec tmp3 = module->addWire(NEW_ID);
- module->addXorGate(NEW_ID, a, b, tmp1);
+ RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(new_verific_id(inst));
+ RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst));
+ RTLIL::SigSpec tmp1 = module->addWire(new_verific_id(inst));
+ RTLIL::SigSpec tmp2 = module->addWire(new_verific_id(inst));
+ RTLIL::SigSpec tmp3 = module->addWire(new_verific_id(inst));
+ module->addXorGate(new_verific_id(inst), a, b, tmp1);
module->addXorGate(inst_name, tmp1, c, y);
- module->addAndGate(NEW_ID, tmp1, c, tmp2);
- module->addAndGate(NEW_ID, a, b, tmp3);
- module->addOrGate(NEW_ID, tmp2, tmp3, x);
+ module->addAndGate(new_verific_id(inst), tmp1, c, tmp2);
+ module->addAndGate(new_verific_id(inst), a, b, tmp3);
+ module->addOrGate(new_verific_id(inst), tmp2, tmp3, x);
return true;
}
@@ -320,63 +329,78 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdString inst_name)
{
+ RTLIL::Cell *cell = nullptr;
+
if (inst->Type() == PRIM_AND) {
- module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ cell = module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_NAND) {
- RTLIL::SigSpec tmp = module->addWire(NEW_ID);
- module->addAnd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
- module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
+ RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
+ cell = module->addAnd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
+ import_attributes(cell->attributes, inst);
+ cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_OR) {
- module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ cell = module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_NOR) {
- RTLIL::SigSpec tmp = module->addWire(NEW_ID);
- module->addOr(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
- module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
+ RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
+ cell = module->addOr(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
+ import_attributes(cell->attributes, inst);
+ cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_XOR) {
- module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ cell = module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_XNOR) {
- module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ cell = module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_INV) {
- module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ cell = module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_MUX) {
- module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
+ cell = module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_TRI) {
- module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
+ cell = module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_FADD)
{
- RTLIL::SigSpec a_plus_b = module->addWire(NEW_ID, 2);
- RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID);
+ RTLIL::SigSpec a_plus_b = module->addWire(new_verific_id(inst), 2);
+ RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst));
if (inst->GetCout())
y.append(net_map_at(inst->GetCout()));
- module->addAdd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b);
- module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y);
+ cell = module->addAdd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b);
+ import_attributes(cell->attributes, inst);
+ cell = module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y);
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -387,24 +411,26 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
log_assert(clocking.body_net == nullptr);
if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd())
- clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ cell = clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
else if (inst->GetSet()->IsGnd())
- clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0);
+ cell = clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0);
else if (inst->GetReset()->IsGnd())
- clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1);
+ cell = clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1);
else
- clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
+ cell = clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == PRIM_DLATCHRS)
{
if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd())
- module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
else
- module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
+ cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -420,37 +446,45 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
if (inst->GetCout() != NULL)
out.append(net_map_at(inst->GetCout()));
if (inst->GetCin()->IsGnd()) {
- module->addAdd(inst_name, IN1, IN2, out, SIGNED);
+ cell = module->addAdd(inst_name, IN1, IN2, out, SIGNED);
+ import_attributes(cell->attributes, inst);
} else {
- RTLIL::SigSpec tmp = module->addWire(NEW_ID, GetSize(out));
- module->addAdd(NEW_ID, IN1, IN2, tmp, SIGNED);
- module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false);
+ RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst), GetSize(out));
+ cell = module->addAdd(new_verific_id(inst), IN1, IN2, tmp, SIGNED);
+ import_attributes(cell->attributes, inst);
+ cell = module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false);
+ import_attributes(cell->attributes, inst);
}
return true;
}
if (inst->Type() == OPER_MULTIPLIER) {
- module->addMul(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addMul(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_DIVIDER) {
- module->addDiv(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addDiv(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_MODULO) {
- module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_REMAINDER) {
- module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_SHIFT_LEFT) {
- module->addShl(inst_name, IN1, IN2, OUT, false);
+ cell = module->addShl(inst_name, IN1, IN2, OUT, false);
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -460,7 +494,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
for (unsigned i = 1; i < inst->OutputSize(); i++) {
vec.append(RTLIL::State::S0);
}
- module->addShl(inst_name, vec, IN, OUT, false);
+ cell = module->addShl(inst_name, vec, IN, OUT, false);
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -470,7 +505,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
for (unsigned i = 1; i < inst->OutputSize(); i++) {
vec.append(RTLIL::State::S0);
}
- module->addShl(inst_name, vec, IN, OUT, false);
+ cell = module->addShl(inst_name, vec, IN, OUT, false);
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -478,108 +514,127 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
Net *net_cin = inst->GetCin();
Net *net_a_msb = inst->GetInput1Bit(0);
if (net_cin->IsGnd())
- module->addShr(inst_name, IN1, IN2, OUT, false);
+ cell = module->addShr(inst_name, IN1, IN2, OUT, false);
else if (net_cin == net_a_msb)
- module->addSshr(inst_name, IN1, IN2, OUT, true);
+ cell = module->addSshr(inst_name, IN1, IN2, OUT, true);
else
log_error("Can't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", inst->Name());
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_REDUCE_AND) {
- module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_REDUCE_OR) {
- module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_REDUCE_XOR) {
- module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_REDUCE_XNOR) {
- module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_REDUCE_NOR) {
- SigSpec t = module->ReduceOr(NEW_ID, IN, SIGNED);
- module->addNot(inst_name, t, net_map_at(inst->GetOutput()));
+ SigSpec t = module->ReduceOr(new_verific_id(inst), IN, SIGNED);
+ cell = module->addNot(inst_name, t, net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_LESSTHAN) {
Net *net_cin = inst->GetCin();
if (net_cin->IsGnd())
- module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
else if (net_cin->IsPwr())
- module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
else
log_error("Can't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", inst->Name());
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_AND) {
- module->addAnd(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addAnd(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_OR) {
- module->addOr(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addOr(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_XOR) {
- module->addXor(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addXor(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_XNOR) {
- module->addXnor(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addXnor(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_BUF) {
- module->addPos(inst_name, IN, FILTERED_OUT, SIGNED);
+ cell = module->addPos(inst_name, IN, FILTERED_OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_INV) {
- module->addNot(inst_name, IN, OUT, SIGNED);
+ cell = module->addNot(inst_name, IN, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_MINUS) {
- module->addSub(inst_name, IN1, IN2, OUT, SIGNED);
+ cell = module->addSub(inst_name, IN1, IN2, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_UMINUS) {
- module->addNeg(inst_name, IN, OUT, SIGNED);
+ cell = module->addNeg(inst_name, IN, OUT, SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_EQUAL) {
- module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_NEQUAL) {
- module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
+ cell = module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_MUX) {
- module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT);
+ cell = module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_NTO1MUX) {
- module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
+ cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -599,25 +654,29 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
padded_data.append(d);
}
- module->addShr(inst_name, padded_data, sel, out);
+ cell = module->addShr(inst_name, padded_data, sel, out);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_SELECTOR)
{
- module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput()));
+ cell = module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_SELECTOR)
{
SigSpec out = OUT;
- module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out);
+ cell = module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out);
+ import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_TRI) {
- module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT);
+ cell = module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT);
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -631,9 +690,10 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
RTLIL::SigSpec sig_reset = operatorInport(inst, "reset");
if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool())
- clocking.addDff(inst_name, IN, OUT);
+ cell = clocking.addDff(inst_name, IN, OUT);
else
- clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT);
+ cell = clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT);
+ import_attributes(cell->attributes, inst);
return true;
}
@@ -862,7 +922,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
ascii_initdata++;
}
if (initval_valid) {
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit");
+ RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit");
cell->parameters["\\WORDS"] = 1;
if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound())
cell->setPort("\\ADDR", word_idx);
@@ -925,7 +985,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (net->Bus())
continue;
- RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : NEW_ID);
+ RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net));
if (verific_verbose)
log(" importing net %s as %s.\n", net->Name(), log_id(wire_name));
@@ -949,7 +1009,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (found_new_net)
{
- RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : NEW_ID);
+ RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus));
if (verific_verbose)
log(" importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name));
@@ -1025,16 +1085,16 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
}
if (GetSize(anyconst_sig))
- module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig)));
+ module->connect(anyconst_sig, module->Anyconst(new_verific_id(netbus), GetSize(anyconst_sig)));
if (GetSize(anyseq_sig))
- module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig)));
+ module->connect(anyseq_sig, module->Anyseq(new_verific_id(netbus), GetSize(anyseq_sig)));
if (GetSize(allconst_sig))
- module->connect(allconst_sig, module->Allconst(NEW_ID, GetSize(allconst_sig)));
+ module->connect(allconst_sig, module->Allconst(new_verific_id(netbus), GetSize(allconst_sig)));
if (GetSize(allseq_sig))
- module->connect(allseq_sig, module->Allseq(NEW_ID, GetSize(allseq_sig)));
+ module->connect(allseq_sig, module->Allseq(new_verific_id(netbus), GetSize(allseq_sig)));
}
for (auto it : init_nets)
@@ -1058,10 +1118,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
}
for (auto net : anyconst_nets)
- module->connect(net_map_at(net), module->Anyconst(NEW_ID));
+ module->connect(net_map_at(net), module->Anyconst(new_verific_id(net)));
for (auto net : anyseq_nets)
- module->connect(net_map_at(net), module->Anyseq(NEW_ID));
+ module->connect(net_map_at(net), module->Anyseq(new_verific_id(net)));
pool<Instance*, hash_ptr_ops> sva_asserts;
pool<Instance*, hash_ptr_ops> sva_assumes;
@@ -1072,7 +1132,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
{
- RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : NEW_ID);
+ RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst));
if (verific_verbose)
log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name));
@@ -1196,7 +1256,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
log_assert(inst->Input1Size() == inst->OutputSize());
SigSpec sig_d, sig_q, sig_o;
- sig_q = module->addWire(NEW_ID, inst->Input1Size());
+ sig_q = module->addWire(new_verific_id(inst), inst->Input1Size());
for (int i = int(inst->Input1Size())-1; i >= 0; i--){
sig_d.append(net_map_at(inst->GetInput1Bit(i)));
@@ -1210,8 +1270,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
log_signal(sig_d), log_signal(sig_q), log_signal(sig_o));
}
- clocking.addDff(NEW_ID, sig_d, sig_q);
- module->addXnor(NEW_ID, sig_d, sig_q, sig_o);
+ clocking.addDff(new_verific_id(inst), sig_d, sig_q);
+ module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o);
if (!mode_keep)
continue;
@@ -1225,7 +1285,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
SigSpec sig_d = net_map_at(inst->GetInput1());
SigSpec sig_o = net_map_at(inst->GetOutput());
- SigSpec sig_q = module->addWire(NEW_ID);
+ SigSpec sig_q = module->addWire(new_verific_id(inst));
if (verific_verbose) {
log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",
@@ -1234,8 +1294,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
log_signal(sig_d), log_signal(sig_q), log_signal(sig_o));
}
- clocking.addDff(NEW_ID, sig_d, sig_q);
- module->addXnor(NEW_ID, sig_d, sig_q, sig_o);
+ clocking.addDff(new_verific_id(inst), sig_d, sig_q);
+ module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o);
if (!mode_keep)
continue;
@@ -1254,7 +1314,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",
log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig));
- past_ffs.insert(clocking.addDff(NEW_ID, sig_d, sig_q));
+ past_ffs.insert(clocking.addDff(new_verific_id(inst), sig_d, sig_q));
if (!mode_keep)
continue;
@@ -1268,14 +1328,14 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
SigBit sig_d = net_map_at(inst->GetInput1());
SigBit sig_o = net_map_at(inst->GetOutput());
- SigBit sig_q = module->addWire(NEW_ID);
+ SigBit sig_q = module->addWire(new_verific_id(inst));
if (verific_verbose)
log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",
log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig));
- clocking.addDff(NEW_ID, sig_d, sig_q);
- module->addEq(NEW_ID, {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o);
+ clocking.addDff(new_verific_id(inst), sig_d, sig_q);
+ module->addEq(new_verific_id(inst), {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o);
if (!mode_keep)
continue;
@@ -1298,9 +1358,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
Cell *cell = nullptr;
if (assume_attr != nullptr && !strcmp(assume_attr, "1"))
- cell = module->addAssume(NEW_ID, cond, State::S1);
+ cell = module->addAssume(new_verific_id(inst), cond, State::S1);
else
- cell = module->addAssert(NEW_ID, cond, State::S1);
+ cell = module->addAssert(new_verific_id(inst), cond, State::S1);
import_attributes(cell->attributes, inst);
continue;
@@ -1342,7 +1402,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
IdString port_name_id = RTLIL::escape_id(port_name);
auto &sigvec = cell_port_conns[port_name_id];
if (GetSize(sigvec) <= port_offset) {
- SigSpec zwires = module->addWire(NEW_ID, port_offset+1-GetSize(sigvec));
+ SigSpec zwires = module->addWire(new_verific_id(inst), port_offset+1-GetSize(sigvec));
for (auto bit : zwires)
sigvec.push_back(bit);
}
@@ -1835,6 +1895,7 @@ struct VerificPass : public Pass {
Message::RegisterCallBackMsg(msg_func);
RuntimeFlags::SetVar("db_preserve_user_nets", 1);
RuntimeFlags::SetVar("db_allow_external_nets", 1);
+ RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);
RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
@@ -2093,42 +2154,6 @@ struct VerificPass : public Pass {
if (mode_all)
{
-#if 0
- log("Running veri_file::ElaborateAll().\n");
- if (!veri_file::ElaborateAll())
- log_cmd_error("Elaboration of Verilog modules failed.\n");
-
- log("Running vhdl_file::ElaborateAll().\n");
- if (!vhdl_file::ElaborateAll())
- log_cmd_error("Elaboration of VHDL modules failed.\n");
-
- Library *lib = Netlist::PresentDesign()->Owner()->Owner();
-
- if (argidx == GetSize(args))
- {
- MapIter iter;
- char *iter_name;
- Verific::Cell *iter_cell;
-
- FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) {
- if (*iter_name != '$')
- nl_todo.insert(iter_cell->GetFirstNetlist());
- }
- }
- else
- {
- for (; argidx < GetSize(args); argidx++)
- {
- Verific::Cell *cell = lib->GetCell(args[argidx].c_str());
-
- if (cell == nullptr)
- log_cmd_error("Module not found: %s\n", args[argidx].c_str());
-
- nl_todo.insert(cell->GetFirstNetlist());
- cell->GetFirstNetlist()->SetPresentDesign();
- }
- }
-#else
log("Running hier_tree::ElaborateAll().\n");
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
@@ -2145,28 +2170,12 @@ struct VerificPass : public Pass {
FOREACH_ARRAY_ITEM(netlists, i, nl)
nl_todo.insert(nl);
delete netlists;
-#endif
}
else
{
if (argidx == GetSize(args))
log_cmd_error("No top module specified.\n");
-#if 0
- for (; argidx < GetSize(args); argidx++) {
- if (veri_file::GetModule(args[argidx].c_str())) {
- log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str());
- if (!veri_file::Elaborate(args[argidx].c_str()))
- log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str());
- nl_todo.insert(Netlist::PresentDesign());
- } else {
- log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str());
- if (!vhdl_file::Elaborate(args[argidx].c_str()))
- log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str());
- nl_todo.insert(Netlist::PresentDesign());
- }
- }
-#else
Array veri_modules, vhdl_units;
for (; argidx < GetSize(args); argidx++)
{
@@ -2198,7 +2207,6 @@ struct VerificPass : public Pass {
FOREACH_ARRAY_ITEM(netlists, i, nl)
nl_todo.insert(nl);
delete netlists;
-#endif
}
if (!verific_error_msg.empty())
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index 334a436af..b331dd4b9 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -78,6 +78,7 @@ struct VerificImporter
RTLIL::SigBit net_map_at(Verific::Net *net);
+ RTLIL::IdString new_verific_id(Verific::DesignObj *obj);
void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj);
RTLIL::SigSpec operatorInput(Verific::Instance *inst);
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index 83921bf0b..f9118e142 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -135,6 +135,9 @@ YOSYS_NAMESPACE_END
frontend_verilog_yyerror("Unsupported default nettype: %s", p);
}
+"`protect"[^\n]* /* ignore `protect*/
+"`endprotect"[^\n]* /* ignore `endprotect*/
+
"`"[a-zA-Z_$][a-zA-Z0-9_$]* {
frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);
}
@@ -150,6 +153,9 @@ YOSYS_NAMESPACE_END
"specparam" { return TOK_SPECPARAM; }
"package" { SV_KEYWORD(TOK_PACKAGE); }
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
+"interface" { SV_KEYWORD(TOK_INTERFACE); }
+"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
+"modport" { SV_KEYWORD(TOK_MODPORT); }
"parameter" { return TOK_PARAMETER; }
"localparam" { return TOK_LOCALPARAM; }
"defparam" { return TOK_DEFPARAM; }
@@ -295,6 +301,11 @@ supply1 { return TOK_SUPPLY1; }
return TOK_ID;
}
+[a-zA-Z_$][a-zA-Z0-9_$\.]* {
+ frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
+ return TOK_ID;
+}
+
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
static bool printed_warning = false;
if (!printed_warning) {
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 16cac1460..51e112ed3 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -35,6 +35,7 @@
%{
#include <list>
+#include <stack>
#include <string.h>
#include "frontends/verilog/verilog_frontend.h"
#include "kernel/log.h"
@@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND {
int port_counter;
std::map<std::string, int> port_stubs;
- std::map<std::string, AstNode*> attr_list, default_attr_list;
+ std::map<std::string, AstNode*> *attr_list, default_attr_list;
+ std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf;
std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3;
@@ -61,6 +63,7 @@ namespace VERILOG_FRONTEND {
bool noassert_mode, noassume_mode, norestrict_mode;
bool assume_asserts_mode, assert_assumes_mode;
bool current_wire_rand, current_wire_const;
+ bool current_modport_input, current_modport_output;
std::istream *lexin;
}
YOSYS_NAMESPACE_END
@@ -106,6 +109,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
+%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
@@ -123,7 +127,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
%type <string> opt_label tok_prim_wrapper hierarchical_id
-%type <boolean> opt_signed unique_case_attr
+%type <boolean> opt_signed opt_property unique_case_attr
%type <al> attr case_attr
// operator precedence from low to high
@@ -168,19 +172,23 @@ design:
param_decl design |
localparam_decl design |
package design |
+ interface design |
/* empty */;
attr:
{
- for (auto &it : attr_list)
- delete it.second;
- attr_list.clear();
+ if (attr_list != nullptr)
+ attr_list_stack.push(attr_list);
+ attr_list = new std::map<std::string, AstNode*>;
for (auto &it : default_attr_list)
- attr_list[it.first] = it.second->clone();
+ (*attr_list)[it.first] = it.second->clone();
} attr_opt {
- std::map<std::string, AstNode*> *al = new std::map<std::string, AstNode*>;
- al->swap(attr_list);
- $$ = al;
+ $$ = attr_list;
+ if (!attr_list_stack.empty()) {
+ attr_list = attr_list_stack.top();
+ attr_list_stack.pop();
+ } else
+ attr_list = nullptr;
};
attr_opt:
@@ -189,15 +197,20 @@ attr_opt:
defattr:
DEFATTR_BEGIN {
+ if (attr_list != nullptr)
+ attr_list_stack.push(attr_list);
+ attr_list = new std::map<std::string, AstNode*>;
for (auto &it : default_attr_list)
delete it.second;
default_attr_list.clear();
- for (auto &it : attr_list)
- delete it.second;
- attr_list.clear();
} opt_attr_list {
- default_attr_list = attr_list;
- attr_list.clear();
+ attr_list->swap(default_attr_list);
+ delete attr_list;
+ if (!attr_list_stack.empty()) {
+ attr_list = attr_list_stack.top();
+ attr_list_stack.pop();
+ } else
+ attr_list = nullptr;
} DEFATTR_END;
opt_attr_list:
@@ -209,15 +222,15 @@ attr_list:
attr_assign:
hierarchical_id {
- if (attr_list.count(*$1) != 0)
- delete attr_list[*$1];
- attr_list[*$1] = AstNode::mkconst_int(1, false);
+ if (attr_list->count(*$1) != 0)
+ delete (*attr_list)[*$1];
+ (*attr_list)[*$1] = AstNode::mkconst_int(1, false);
delete $1;
} |
hierarchical_id '=' expr {
- if (attr_list.count(*$1) != 0)
- delete attr_list[*$1];
- attr_list[*$1] = $3;
+ if (attr_list->count(*$1) != 0)
+ delete (*attr_list)[*$1];
+ (*attr_list)[*$1] = $3;
delete $1;
};
@@ -302,7 +315,7 @@ module_arg_opt_assignment:
else
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
} else
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value.");
} |
/* empty */;
@@ -320,6 +333,21 @@ module_arg:
}
delete $1;
} module_arg_opt_assignment |
+ TOK_ID {
+ astbuf1 = new AstNode(AST_INTERFACEPORT);
+ astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE));
+ astbuf1->children[0]->str = *$1;
+ delete $1;
+ } TOK_ID { /* SV interfaces */
+ if (!sv_mode)
+ frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str());
+ astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type.
+ astbuf2->str = *$3;
+ delete $3;
+ astbuf2->port_id = ++port_counter;
+ ast_stack.back()->children.push_back(astbuf2);
+ delete astbuf1; // really only needed if multiple instances of same type.
+ } module_arg_opt_assignment |
attr wire_type range TOK_ID {
AstNode *node = $2;
node->str = *$4;
@@ -357,6 +385,33 @@ package_body:
package_body_stmt:
localparam_decl;
+interface:
+ TOK_INTERFACE TOK_ID {
+ do_not_require_port_stubs = false;
+ AstNode *intf = new AstNode(AST_INTERFACE);
+ ast_stack.back()->children.push_back(intf);
+ ast_stack.push_back(intf);
+ current_ast_mod = intf;
+ port_stubs.clear();
+ port_counter = 0;
+ intf->str = *$2;
+ delete $2;
+ } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE {
+ if (port_stubs.size() != 0)
+ frontend_verilog_yyerror("Missing details for module port `%s'.",
+ port_stubs.begin()->first.c_str());
+ ast_stack.pop_back();
+ log_assert(ast_stack.size() == 1);
+ current_ast_mod = NULL;
+ };
+
+interface_body:
+ interface_body interface_body_stmt |;
+
+interface_body_stmt:
+ param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
+ modport_stmt;
+
non_opt_delay:
'#' TOK_ID { delete $2; } |
'#' TOK_CONSTVAL { delete $2; } |
@@ -627,7 +682,7 @@ task_func_port:
astbuf2 = $3;
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
if (astbuf2) {
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)");
} else {
astbuf2 = new AstNode(AST_RANGE);
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
@@ -635,7 +690,7 @@ task_func_port:
}
}
if (astbuf2 && astbuf2->children.size() != 2)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("task/function argument range must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
} wire_name | wire_name;
task_func_body:
@@ -838,7 +893,7 @@ param_signed:
param_integer:
TOK_INTEGER {
if (astbuf1->children.size() != 1)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("Internal error in param_integer - should not happen?");
astbuf1->children.push_back(new AstNode(AST_RANGE));
astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));
astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true));
@@ -848,7 +903,7 @@ param_integer:
param_real:
TOK_REAL {
if (astbuf1->children.size() != 1)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real.");
astbuf1->children.push_back(new AstNode(AST_REALVALUE));
} | /* empty */;
@@ -856,7 +911,7 @@ param_range:
range {
if ($1 != NULL) {
if (astbuf1->children.size() != 1)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("integer/real parameters should not have a range.");
astbuf1->children.push_back($1);
}
};
@@ -885,7 +940,7 @@ single_param_decl:
AstNode *node;
if (astbuf1 == nullptr) {
if (!sv_mode)
- frontend_verilog_yyerror("syntax error");
+ frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword");
node = new AstNode(AST_PARAMETER);
node->children.push_back(AstNode::mkconst_int(0, true));
} else {
@@ -921,7 +976,7 @@ wire_decl:
astbuf2 = $3;
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
if (astbuf2) {
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions.");
} else {
astbuf2 = new AstNode(AST_RANGE);
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
@@ -929,7 +984,7 @@ wire_decl:
}
}
if (astbuf2 && astbuf2->children.size() != 2)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
} wire_name_list {
delete astbuf1;
if (astbuf2 != NULL)
@@ -1023,7 +1078,7 @@ wire_name_and_opt_assign:
wire_name:
TOK_ID range_or_multirange {
if (astbuf1 == nullptr)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node.");
AstNode *node = astbuf1->clone();
node->str = *$1;
append_attr_clone(node, albuf);
@@ -1031,7 +1086,7 @@ wire_name:
node->children.push_back(astbuf2->clone());
if ($2 != NULL) {
if (node->is_input || node->is_output)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions.");
if (!astbuf2) {
AstNode *rng = new AstNode(AST_RANGE);
rng->children.push_back(AstNode::mkconst_int(0, true));
@@ -1275,11 +1330,51 @@ opt_label:
};
opt_property:
- TOK_PROPERTY | /* empty */;
+ TOK_PROPERTY {
+ $$ = true;
+ } |
+ /* empty */ {
+ $$ = false;
+ };
opt_stmt_label:
TOK_ID ':' | /* empty */;
+modport_stmt:
+ TOK_MODPORT TOK_ID {
+ AstNode *modport = new AstNode(AST_MODPORT);
+ ast_stack.back()->children.push_back(modport);
+ ast_stack.push_back(modport);
+ modport->str = *$2;
+ delete $2;
+ } modport_args_opt {
+ ast_stack.pop_back();
+ log_assert(ast_stack.size() == 2);
+ } ';'
+
+modport_args_opt:
+ '(' ')' | '(' modport_args optional_comma ')';
+
+modport_args:
+ modport_arg | modport_args ',' modport_arg;
+
+modport_arg:
+ modport_type_token modport_member |
+ modport_member
+
+modport_member:
+ TOK_ID {
+ AstNode *modport_member = new AstNode(AST_MODPORTMEMBER);
+ ast_stack.back()->children.push_back(modport_member);
+ modport_member->str = *$1;
+ modport_member->is_input = current_modport_input;
+ modport_member->is_output = current_modport_output;
+ delete $1;
+ }
+
+modport_type_token:
+ TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
+
assert:
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
if (noassert_mode)
@@ -1319,12 +1414,16 @@ assert:
delete $5;
else
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
+ if (!$3)
+ log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
} |
opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (norestrict_mode)
delete $6;
else
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
+ if (!$3)
+ log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
};
assert_property:
@@ -1398,7 +1497,7 @@ behavioral_stmt:
node->str = *$3;
} behavioral_stmt_list TOK_END opt_label {
if ($3 != NULL && $7 != NULL && *$3 != *$7)
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);
if ($3 != NULL)
delete $3;
if ($7 != NULL)
@@ -1714,7 +1813,7 @@ basic_expr:
} |
'(' expr ')' TOK_CONSTVAL {
if ($4->substr(0, 1) != "'")
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
AstNode *bits = $2;
AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
if (val == NULL)
@@ -1724,7 +1823,7 @@ basic_expr:
} |
hierarchical_id TOK_CONSTVAL {
if ($2->substr(0, 1) != "'")
- frontend_verilog_yyerror("Syntax error.");
+ frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1;
AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);