diff options
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/ast.cc | 40 | ||||
-rw-r--r-- | frontends/ast/ast.h | 4 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 29 |
3 files changed, 68 insertions, 5 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 256c08776..10fd5277a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1118,7 +1118,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT } // 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) +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); @@ -1143,14 +1143,46 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R for(auto &intf : interfaces) { RTLIL::Module * intfmodule = intf.second; std::string intfname = intf.first.str(); + 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; + for (auto &ch : ast_node_of_interface->children) { + if (ch->type == AST_MODPORT) { + if (ch->str == interface_modport) { + modport = ch; + } + } + } + } 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); + if (modport != NULL) { + bool found_in_modport = false; + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { // If not found in modport, do not create port + new_ast->children.push_back(wire); + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } } } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 6b93832b4..8187b1ac6 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -145,6 +145,8 @@ namespace AST AST_INTERFACE, AST_INTERFACEPORT, AST_INTERFACEPORTTYPE, + AST_MODPORT, + AST_MODPORTMEMBER, AST_PACKAGE }; @@ -287,7 +289,7 @@ 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, 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; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 1dd1a9130..d87163dc2 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -853,6 +853,8 @@ 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 as "is_interface=true" @@ -865,6 +867,33 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) 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::string name_type = children[i]->str; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + if (ndots == 0) { + wire->attributes["\\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) { + wire->attributes["\\interface_type"] = seglist[0]; + wire->attributes["\\interface_modport"] = seglist[1]; + } + else { + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + break; + } + } + } wire->upto = 0; } break; |