mirror of https://github.com/YosysHQ/yosys.git
Synthesis support for SystemVerilog interfaces
This time doing the changes mostly in AST before RTLIL generation
This commit is contained in:
parent
9850de405a
commit
75009ada3c
|
@ -905,7 +905,7 @@ RTLIL::Const AstNode::realAsConst(int width)
|
||||||
// create a new AstModule from an AST_MODULE AST node
|
// 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)
|
||||||
{
|
{
|
||||||
log_assert(ast->type == AST_MODULE);
|
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
|
||||||
|
|
||||||
if (defer)
|
if (defer)
|
||||||
log("Storing AST representation for module `%s'.\n", ast->str.c_str());
|
log("Storing AST representation for module `%s'.\n", ast->str.c_str());
|
||||||
|
@ -916,6 +916,7 @@ static AstModule* process_module(AstNode *ast, bool defer)
|
||||||
current_module->ast = NULL;
|
current_module->ast = NULL;
|
||||||
current_module->name = ast->str;
|
current_module->name = ast->str;
|
||||||
current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum);
|
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;
|
current_ast_mod = ast;
|
||||||
AstNode *ast_before_simplify = ast->clone();
|
AstNode *ast_before_simplify = ast->clone();
|
||||||
|
@ -989,6 +990,8 @@ static AstModule* process_module(AstNode *ast, bool defer)
|
||||||
ignoreThisSignalsInInitial = RTLIL::SigSpec();
|
ignoreThisSignalsInInitial = RTLIL::SigSpec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ast->type == AST_INTERFACE)
|
||||||
|
current_module->set_bool_attribute("\\is_interface");
|
||||||
current_module->ast = ast_before_simplify;
|
current_module->ast = ast_before_simplify;
|
||||||
current_module->nolatches = flag_nolatches;
|
current_module->nolatches = flag_nolatches;
|
||||||
current_module->nomeminit = flag_nomeminit;
|
current_module->nomeminit = flag_nomeminit;
|
||||||
|
@ -1031,7 +1034,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
||||||
log_assert(current_ast->type == AST_DESIGN);
|
log_assert(current_ast->type == AST_DESIGN);
|
||||||
for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)
|
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)
|
for (auto n : design->verilog_globals)
|
||||||
(*it)->children.push_back(n->clone());
|
(*it)->children.push_back(n->clone());
|
||||||
|
@ -1083,8 +1086,123 @@ AstModule::~AstModule()
|
||||||
delete ast;
|
delete ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
if (this->get_bool_attribute("\\initial_top")) {
|
||||||
|
this->attributes.erase("\\initial_top");
|
||||||
|
is_top = true;
|
||||||
|
}
|
||||||
|
AstModule *newmod = process_module(new_ast, false);
|
||||||
|
design->add(newmod);
|
||||||
|
RTLIL::Module* mod = design->module(original_name);
|
||||||
|
if (is_top)
|
||||||
|
mod->set_bool_attribute("\\top");
|
||||||
|
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
|
||||||
|
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, 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;
|
||||||
|
for(auto &intf : interfaces) {
|
||||||
|
RTLIL::Module * intfmodule = intf.second;
|
||||||
|
std::string intfname = intf.first.str();
|
||||||
|
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;
|
||||||
|
wire->is_input = true;
|
||||||
|
wire->is_output = true;
|
||||||
|
new_ast->children.push_back(wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
design->add(process_module(new_ast, false));
|
||||||
|
design->module(modname)->check();
|
||||||
|
|
||||||
|
RTLIL::Module* mod = design->module(modname);
|
||||||
|
|
||||||
|
for(auto &intf : interfaces) {
|
||||||
|
if(mod->wires_.count(intf.first)) {
|
||||||
|
mod->wires_.erase(intf.first);
|
||||||
|
mod->fixup_ports();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// 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();
|
std::string stripped_name = name.str();
|
||||||
|
|
||||||
|
@ -1156,15 +1274,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
||||||
else
|
else
|
||||||
modname = "$paramod" + stripped_name + para_info;
|
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;
|
return modname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,9 @@ namespace AST
|
||||||
AST_NEGEDGE,
|
AST_NEGEDGE,
|
||||||
AST_EDGE,
|
AST_EDGE,
|
||||||
|
|
||||||
|
AST_INTERFACE,
|
||||||
|
AST_INTERFACEPORT,
|
||||||
|
AST_INTERFACEPORTTYPE,
|
||||||
AST_PACKAGE
|
AST_PACKAGE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,6 +287,9 @@ namespace AST
|
||||||
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
|
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
|
||||||
~AstModule() YS_OVERRIDE;
|
~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, bool mayfail) YS_OVERRIDE;
|
||||||
|
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, 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;
|
RTLIL::Module *clone() const YS_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -854,6 +854,22 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
case AST_GENCASE:
|
case AST_GENCASE:
|
||||||
case AST_PACKAGE:
|
case AST_PACKAGE:
|
||||||
break;
|
break;
|
||||||
|
case AST_INTERFACEPORT: {
|
||||||
|
// If a port in a module with unknown type is found, mark it as "is_interface=true"
|
||||||
|
// 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");
|
||||||
|
wire->upto = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AST_INTERFACEPORTTYPE:
|
||||||
|
break;
|
||||||
|
|
||||||
// remember the parameter, needed for example in techmap
|
// remember the parameter, needed for example in techmap
|
||||||
case AST_PARAMETER:
|
case AST_PARAMETER:
|
||||||
|
@ -949,6 +965,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
{
|
{
|
||||||
RTLIL::Wire *wire = NULL;
|
RTLIL::Wire *wire = NULL;
|
||||||
RTLIL::SigChunk chunk;
|
RTLIL::SigChunk chunk;
|
||||||
|
bool is_interface = false;
|
||||||
|
|
||||||
int add_undef_bits_msb = 0;
|
int add_undef_bits_msb = 0;
|
||||||
int add_undef_bits_lsb = 0;
|
int add_undef_bits_lsb = 0;
|
||||||
|
@ -969,15 +986,41 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
||||||
goto use_const_chunk;
|
goto use_const_chunk;
|
||||||
}
|
}
|
||||||
else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
|
else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
|
||||||
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",
|
log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
|
||||||
str.c_str());
|
str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (id2ast->type == AST_MEMORY)
|
if (id2ast->type == AST_MEMORY)
|
||||||
log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
|
log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
|
||||||
str.c_str());
|
str.c_str());
|
||||||
|
|
||||||
|
// If identifier is an interface, create a RTLIL::SigSpec object and set is_interface to true.
|
||||||
|
// 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];
|
wire = current_module->wires_[str];
|
||||||
chunk.wire = wire;
|
chunk.wire = wire;
|
||||||
chunk.width = wire->width;
|
chunk.width = wire->width;
|
||||||
|
@ -1423,6 +1466,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
|
|
||||||
RTLIL::Cell *cell = current_module->addCell(str, "");
|
RTLIL::Cell *cell = current_module->addCell(str, "");
|
||||||
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||||
|
cell->set_bool_attribute("\\module_not_derived");
|
||||||
|
|
||||||
for (auto it = children.begin(); it != children.end(); it++) {
|
for (auto it = children.begin(); it != children.end(); it++) {
|
||||||
AstNode *child = *it;
|
AstNode *child = *it;
|
||||||
|
|
|
@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
|
|
||||||
if (stage == 0)
|
if (stage == 0)
|
||||||
{
|
{
|
||||||
log_assert(type == AST_MODULE);
|
log_assert(type == AST_MODULE || type == AST_INTERFACE);
|
||||||
last_blocking_assignment_warn = pair<string, int>();
|
last_blocking_assignment_warn = pair<string, int>();
|
||||||
|
|
||||||
deep_recursion_warning = true;
|
deep_recursion_warning = true;
|
||||||
|
|
|
@ -150,6 +150,9 @@ YOSYS_NAMESPACE_END
|
||||||
"specparam" { return TOK_SPECPARAM; }
|
"specparam" { return TOK_SPECPARAM; }
|
||||||
"package" { SV_KEYWORD(TOK_PACKAGE); }
|
"package" { SV_KEYWORD(TOK_PACKAGE); }
|
||||||
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
|
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
|
||||||
|
"interface" { SV_KEYWORD(TOK_INTERFACE); }
|
||||||
|
"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
|
||||||
|
"modport" { SV_KEYWORD(TOK_MODPORT); }
|
||||||
"parameter" { return TOK_PARAMETER; }
|
"parameter" { return TOK_PARAMETER; }
|
||||||
"localparam" { return TOK_LOCALPARAM; }
|
"localparam" { return TOK_LOCALPARAM; }
|
||||||
"defparam" { return TOK_DEFPARAM; }
|
"defparam" { return TOK_DEFPARAM; }
|
||||||
|
@ -295,6 +298,11 @@ supply1 { return TOK_SUPPLY1; }
|
||||||
return TOK_ID;
|
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]*"*/" {
|
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
|
||||||
static bool printed_warning = false;
|
static bool printed_warning = false;
|
||||||
if (!printed_warning) {
|
if (!printed_warning) {
|
||||||
|
|
|
@ -106,6 +106,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
||||||
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
||||||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||||
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
|
%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_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC
|
||||||
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
|
%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
|
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
|
||||||
|
@ -168,6 +169,7 @@ design:
|
||||||
param_decl design |
|
param_decl design |
|
||||||
localparam_decl design |
|
localparam_decl design |
|
||||||
package design |
|
package design |
|
||||||
|
interface design |
|
||||||
/* empty */;
|
/* empty */;
|
||||||
|
|
||||||
attr:
|
attr:
|
||||||
|
@ -320,6 +322,21 @@ module_arg:
|
||||||
}
|
}
|
||||||
delete $1;
|
delete $1;
|
||||||
} module_arg_opt_assignment |
|
} 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 {
|
attr wire_type range TOK_ID {
|
||||||
AstNode *node = $2;
|
AstNode *node = $2;
|
||||||
node->str = *$4;
|
node->str = *$4;
|
||||||
|
@ -357,6 +374,33 @@ package_body:
|
||||||
package_body_stmt:
|
package_body_stmt:
|
||||||
localparam_decl;
|
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:
|
non_opt_delay:
|
||||||
'#' TOK_ID { delete $2; } |
|
'#' TOK_ID { delete $2; } |
|
||||||
'#' TOK_CONSTVAL { delete $2; } |
|
'#' TOK_CONSTVAL { delete $2; } |
|
||||||
|
@ -1280,6 +1324,22 @@ opt_property:
|
||||||
opt_stmt_label:
|
opt_stmt_label:
|
||||||
TOK_ID ':' | /* empty */;
|
TOK_ID ':' | /* empty */;
|
||||||
|
|
||||||
|
modport_stmt:
|
||||||
|
TOK_MODPORT TOK_ID modport_args_opt ';'
|
||||||
|
|
||||||
|
modport_args_opt:
|
||||||
|
'(' ')' | '(' modport_args optional_comma ')';
|
||||||
|
|
||||||
|
modport_args:
|
||||||
|
modport_arg | modport_args ',' modport_arg;
|
||||||
|
|
||||||
|
modport_arg:
|
||||||
|
modport_type_token TOK_ID |
|
||||||
|
TOK_ID
|
||||||
|
|
||||||
|
modport_type_token:
|
||||||
|
TOK_INPUT | TOK_OUTPUT
|
||||||
|
|
||||||
assert:
|
assert:
|
||||||
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
||||||
if (noassert_mode)
|
if (noassert_mode)
|
||||||
|
|
|
@ -639,6 +639,13 @@ RTLIL::Module::~Module()
|
||||||
delete it->second;
|
delete it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTLIL::Module::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces)
|
||||||
|
{
|
||||||
|
log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name));
|
||||||
|
(void)local_interfaces; // To remove build warning
|
||||||
|
(void)design; // To remove build warning
|
||||||
|
}
|
||||||
|
|
||||||
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, bool mayfail)
|
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, bool mayfail)
|
||||||
{
|
{
|
||||||
if (mayfail)
|
if (mayfail)
|
||||||
|
@ -646,6 +653,14 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLI
|
||||||
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
|
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, dict<RTLIL::IdString, RTLIL::Module*> , bool mayfail)
|
||||||
|
{
|
||||||
|
if (mayfail)
|
||||||
|
return RTLIL::IdString();
|
||||||
|
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
|
||||||
|
}
|
||||||
|
|
||||||
size_t RTLIL::Module::count_id(RTLIL::IdString id)
|
size_t RTLIL::Module::count_id(RTLIL::IdString id)
|
||||||
{
|
{
|
||||||
return wires_.count(id) + memories.count(id) + cells_.count(id) + processes.count(id);
|
return wires_.count(id) + memories.count(id) + cells_.count(id) + processes.count(id);
|
||||||
|
|
|
@ -907,7 +907,9 @@ public:
|
||||||
Module();
|
Module();
|
||||||
virtual ~Module();
|
virtual ~Module();
|
||||||
virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail = false);
|
virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail = false);
|
||||||
|
virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, bool mayfail = false);
|
||||||
virtual size_t count_id(RTLIL::IdString id);
|
virtual size_t count_id(RTLIL::IdString id);
|
||||||
|
virtual void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces);
|
||||||
|
|
||||||
virtual void sort();
|
virtual void sort();
|
||||||
virtual void check();
|
virtual void check();
|
||||||
|
|
|
@ -145,9 +145,24 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
||||||
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
|
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
|
||||||
|
dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
|
||||||
for (auto &cell_it : module->cells_)
|
for (auto &cell_it : module->cells_)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = cell_it.second;
|
RTLIL::Cell *cell = cell_it.second;
|
||||||
|
if(cell->get_bool_attribute("\\is_interface")) {
|
||||||
|
RTLIL::Module *intf_module = design->modules_[cell->type];
|
||||||
|
interfaces_in_module[cell->name] = intf_module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &cell_it : module->cells_)
|
||||||
|
{
|
||||||
|
RTLIL::Cell *cell = cell_it.second;
|
||||||
|
bool has_interfaces_not_found = false;
|
||||||
|
|
||||||
|
std::vector<RTLIL::IdString> connections_to_remove;
|
||||||
|
std::vector<RTLIL::IdString> connections_to_add_name;
|
||||||
|
std::vector<RTLIL::SigSpec> connections_to_add_signal;
|
||||||
|
|
||||||
if (cell->type.substr(0, 7) == "$array:") {
|
if (cell->type.substr(0, 7) == "$array:") {
|
||||||
int pos_idx = cell->type.str().find_first_of(':');
|
int pos_idx = cell->type.str().find_first_of(':');
|
||||||
|
@ -158,6 +173,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
||||||
array_cells[cell] = std::pair<int, int>(idx, num);
|
array_cells[cell] = std::pair<int, int>(idx, num);
|
||||||
cell->type = cell->type.str().substr(pos_type + 1);
|
cell->type = cell->type.str().substr(pos_type + 1);
|
||||||
}
|
}
|
||||||
|
dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
|
||||||
|
|
||||||
if (design->modules_.count(cell->type) == 0)
|
if (design->modules_.count(cell->type) == 0)
|
||||||
{
|
{
|
||||||
|
@ -200,11 +216,61 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
||||||
if (design->modules_.count(cell->type) == 0)
|
if (design->modules_.count(cell->type) == 0)
|
||||||
log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
|
log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
|
||||||
did_something = true;
|
did_something = true;
|
||||||
} else
|
} else {
|
||||||
|
|
||||||
|
RTLIL::Module *mod = design->module(cell->type);
|
||||||
|
|
||||||
|
// Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to
|
||||||
|
// some lists, so that they can be replaced further down:
|
||||||
|
for (auto &conn : cell->connections()) {
|
||||||
|
if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list
|
||||||
|
if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) {
|
||||||
|
std::string interface_name_str = conn.second.bits()[0].wire->name.str();
|
||||||
|
interface_name_str.replace(0,23,"");
|
||||||
|
interface_name_str = "\\" + interface_name_str;
|
||||||
|
RTLIL::IdString interface_name = interface_name_str;
|
||||||
|
bool will_do_step = false;
|
||||||
|
if(module->get_bool_attribute("\\interfaces_replaced_in_module")) {
|
||||||
|
if (interfaces_in_module.count(interface_name) > 0) { // Check if the interface instance is present in module
|
||||||
|
RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name);
|
||||||
|
for (auto &mod_wire : mod_replace_ports->wires_) {
|
||||||
|
std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire.first);
|
||||||
|
std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire.first);
|
||||||
|
connections_to_add_name.push_back(RTLIL::IdString(signal_name1));
|
||||||
|
if(module->wires_.count(signal_name2) == 0) {
|
||||||
|
log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), log_id(module->name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RTLIL::Wire *wire_in_parent = module->wire(signal_name2);
|
||||||
|
connections_to_add_signal.push_back(wire_in_parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connections_to_remove.push_back(conn.first);
|
||||||
|
interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name);
|
||||||
|
}
|
||||||
|
else will_do_step = true;
|
||||||
|
}
|
||||||
|
else will_do_step = true;
|
||||||
|
// If the interface instance has not already been derived in the module, we cannot complete at this stage. Set "has_interfaces_not_found"
|
||||||
|
// which will delay the expansion of this cell:
|
||||||
|
if (will_do_step) {
|
||||||
|
// If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error:
|
||||||
|
if(!(module->get_bool_attribute("\\cells_not_processed"))) {
|
||||||
|
log_warning("Could not find interface instance for `%s' in `%s'\n", log_id(interface_name), log_id(module));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Only set has_interfaces_not_found if it would be possible to find them, since otherwiser we will end up in an infinite loop:
|
||||||
|
has_interfaces_not_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
if (flag_check || flag_simcheck)
|
if (flag_check || flag_simcheck)
|
||||||
{
|
{
|
||||||
RTLIL::Module *mod = design->module(cell->type);
|
for (auto &conn : cell->connections()) {
|
||||||
for (auto &conn : cell->connections())
|
|
||||||
if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
|
if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
|
||||||
int id = atoi(conn.first.c_str()+1);
|
int id = atoi(conn.first.c_str()+1);
|
||||||
if (id <= 0 || id > GetSize(mod->ports))
|
if (id <= 0 || id > GetSize(mod->ports))
|
||||||
|
@ -213,11 +279,15 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
||||||
} else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0)
|
} else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0)
|
||||||
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n",
|
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first));
|
log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first));
|
||||||
|
}
|
||||||
for (auto ¶m : cell->parameters)
|
for (auto ¶m : cell->parameters)
|
||||||
if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
|
if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
|
||||||
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n",
|
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
|
log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
RTLIL::Module *mod = design->modules_[cell->type];
|
||||||
|
|
||||||
if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) {
|
if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) {
|
||||||
if (flag_simcheck)
|
if (flag_simcheck)
|
||||||
|
@ -226,14 +296,58 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->parameters.size() == 0)
|
// If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here:
|
||||||
|
if(has_interfaces_not_found) {
|
||||||
|
did_something = true; // waiting for interfaces to be handled
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
RTLIL::Module *mod = design->modules_[cell->type];
|
// Do the actual replacements of the SV interface port connection with the individual signal connections:
|
||||||
cell->type = mod->derive(design, cell->parameters);
|
for(unsigned int i=0;i<connections_to_add_name.size();i++) {
|
||||||
|
cell->connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
|
||||||
|
}
|
||||||
|
// Remove the connection for the interface itself:
|
||||||
|
for(unsigned int i=0;i<connections_to_remove.size();i++) {
|
||||||
|
cell->connections_.erase(connections_to_remove[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type
|
||||||
|
// for the cell:
|
||||||
|
if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute("\\module_not_derived")))) {
|
||||||
|
// If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:",
|
||||||
|
// so that the signals of the interface are added to the parent module.
|
||||||
|
if (mod->get_bool_attribute("\\is_interface")) {
|
||||||
|
goto handle_interface_instance;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule);
|
||||||
cell->parameters.clear();
|
cell->parameters.clear();
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
|
||||||
|
handle_interface_instance:
|
||||||
|
|
||||||
|
// We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter
|
||||||
|
// an interface instance:
|
||||||
|
if (mod->get_bool_attribute("\\is_interface") && cell->get_bool_attribute("\\module_not_derived")) {
|
||||||
|
cell->set_bool_attribute("\\is_interface");
|
||||||
|
RTLIL::Module *derived_module = design->modules_[cell->type];
|
||||||
|
interfaces_in_module[cell->name] = derived_module;
|
||||||
|
did_something = true;
|
||||||
|
}
|
||||||
|
// We unset 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell)
|
||||||
|
cell->attributes.erase("\\module_not_derived");
|
||||||
}
|
}
|
||||||
|
// Setting a flag such that it can be known that we have been through all cells at least once, such that we can know whether to flag
|
||||||
|
// an error because of interface instances not found:
|
||||||
|
module->attributes.erase("\\cells_not_processed");
|
||||||
|
|
||||||
|
if (interfaces_in_module.size() > 0 && !module->get_bool_attribute("\\interfaces_replaced_in_module")) {
|
||||||
|
module->reprocess_module(design, interfaces_in_module);
|
||||||
|
return did_something;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (auto &it : array_cells)
|
for (auto &it : array_cells)
|
||||||
{
|
{
|
||||||
|
@ -341,6 +455,20 @@ int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db)
|
||||||
return db.at(module);
|
return db.at(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod)
|
||||||
|
{
|
||||||
|
if(top_mod != NULL && top_mod->get_bool_attribute("\\initial_top"))
|
||||||
|
return top_mod;
|
||||||
|
else {
|
||||||
|
for (auto mod : design->modules()) {
|
||||||
|
if (mod->get_bool_attribute("\\top")) {
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct HierarchyPass : public Pass {
|
struct HierarchyPass : public Pass {
|
||||||
HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
|
HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
|
||||||
void help() YS_OVERRIDE
|
void help() YS_OVERRIDE
|
||||||
|
@ -568,6 +696,14 @@ struct HierarchyPass : public Pass {
|
||||||
if (flag_simcheck && top_mod == nullptr)
|
if (flag_simcheck && top_mod == nullptr)
|
||||||
log_error("Design has no top module.\n");
|
log_error("Design has no top module.\n");
|
||||||
|
|
||||||
|
if (top_mod != NULL) {
|
||||||
|
for (auto &mod_it : design->modules_)
|
||||||
|
if (mod_it.second == top_mod)
|
||||||
|
mod_it.second->attributes["\\initial_top"] = RTLIL::Const(1);
|
||||||
|
else
|
||||||
|
mod_it.second->attributes.erase("\\initial_top");
|
||||||
|
}
|
||||||
|
|
||||||
bool did_something = true;
|
bool did_something = true;
|
||||||
while (did_something)
|
while (did_something)
|
||||||
{
|
{
|
||||||
|
@ -586,19 +722,41 @@ struct HierarchyPass : public Pass {
|
||||||
if (expand_module(design, module, flag_check, flag_simcheck, libdirs))
|
if (expand_module(design, module, flag_check, flag_simcheck, libdirs))
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RTLIL::Module *tmp_top_mod = check_if_top_has_changed(design, top_mod);
|
||||||
|
if (tmp_top_mod != NULL) {
|
||||||
|
if (tmp_top_mod != top_mod){
|
||||||
|
top_mod = tmp_top_mod;
|
||||||
|
did_something = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<RTLIL::Module *> modules_to_delete;
|
||||||
|
for(auto &mod_it : design->modules_) {
|
||||||
|
if (mod_it.second->get_bool_attribute("\\to_delete")) {
|
||||||
|
modules_to_delete.push_back(mod_it.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(size_t i=0; i<modules_to_delete.size(); i++) {
|
||||||
|
design->remove(modules_to_delete[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (top_mod != NULL) {
|
if (top_mod != NULL) {
|
||||||
log_header(design, "Analyzing design hierarchy..\n");
|
log_header(design, "Analyzing design hierarchy..\n");
|
||||||
hierarchy_clean(design, top_mod, purge_lib);
|
hierarchy_clean(design, top_mod, purge_lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top_mod != NULL) {
|
if (top_mod != NULL) {
|
||||||
for (auto &mod_it : design->modules_)
|
for (auto &mod_it : design->modules_) {
|
||||||
if (mod_it.second == top_mod)
|
if (mod_it.second == top_mod)
|
||||||
mod_it.second->attributes["\\top"] = RTLIL::Const(1);
|
mod_it.second->attributes["\\top"] = RTLIL::Const(1);
|
||||||
else
|
else
|
||||||
mod_it.second->attributes.erase("\\top");
|
mod_it.second->attributes.erase("\\top");
|
||||||
|
mod_it.second->attributes.erase("\\initial_top");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nokeep_asserts) {
|
if (!nokeep_asserts) {
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
|
||||||
|
module TopModule(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
input logic [1:0] sig,
|
||||||
|
output logic [1:0] sig_out);
|
||||||
|
|
||||||
|
MyInterface #(.WIDTH(4)) MyInterfaceInstance();
|
||||||
|
|
||||||
|
SubModule1 u_SubModule1 (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.u_MyInterface(MyInterfaceInstance),
|
||||||
|
.sig (sig)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign sig_out = MyInterfaceInstance.mysig_out;
|
||||||
|
|
||||||
|
|
||||||
|
assign MyInterfaceInstance.setting = 1;
|
||||||
|
assign MyInterfaceInstance.other_setting[2:0] = 3'b101;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
interface MyInterface #(
|
||||||
|
parameter WIDTH = 3)(
|
||||||
|
);
|
||||||
|
|
||||||
|
logic setting;
|
||||||
|
logic [WIDTH-1:0] other_setting;
|
||||||
|
|
||||||
|
logic [1:0] mysig_out;
|
||||||
|
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
|
||||||
|
module SubModule1(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
MyInterface u_MyInterface,
|
||||||
|
input logic [1:0] sig
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge clk or posedge rst)
|
||||||
|
if(rst)
|
||||||
|
u_MyInterface.mysig_out <= 0;
|
||||||
|
else begin
|
||||||
|
if(u_MyInterface.setting)
|
||||||
|
u_MyInterface.mysig_out <= sig;
|
||||||
|
else
|
||||||
|
u_MyInterface.mysig_out <= ~sig;
|
||||||
|
end
|
||||||
|
|
||||||
|
MyInterface #(.WIDTH(22)) MyInterfaceInstanceInSub();
|
||||||
|
|
||||||
|
SubModule2 u_SubModule2 (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.u_MyInterfaceInSub2(u_MyInterface),
|
||||||
|
.sig (sig)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module SubModule2(
|
||||||
|
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
MyInterface u_MyInterfaceInSub2,
|
||||||
|
input logic [1:0] sig
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
Loading…
Reference in New Issue