mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-27 19:05:52 +00:00
Documentation improvements etc.
- Mention new feature in the SystemVerilog section in the README file - Commented changes much better - Rename a few signals to make it clearer - Prevent warning for unused signals in an easier way - Add myself as copyright holder to 2 files - Fix one potential memory leak (delete 'wire' if not in modport)
This commit is contained in:
parent
a36d1701dd
commit
c50afc4246
5 changed files with 77 additions and 38 deletions
|
@ -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
|
||||
|
@ -1086,6 +1087,8 @@ AstModule::~AstModule()
|
|||
delete ast;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
@ -1101,23 +1104,33 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
|
|||
new_ast->children.push_back(wire);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
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;
|
||||
|
@ -1140,9 +1153,12 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
|
||||
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();
|
||||
|
@ -1150,12 +1166,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
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) {
|
||||
if (ch->str == interface_modport) { // Modport found
|
||||
modport = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Iterate over all wires in the interface and add them to the module:
|
||||
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);
|
||||
|
@ -1163,10 +1180,11 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
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) {
|
||||
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;
|
||||
|
@ -1174,9 +1192,12 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
}
|
||||
}
|
||||
}
|
||||
if (found_in_modport) { // If not found in modport, do not create port
|
||||
if (found_in_modport) {
|
||||
new_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;
|
||||
|
@ -1191,10 +1212,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
|
||||
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");
|
||||
}
|
||||
|
@ -1203,6 +1227,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
}
|
||||
}
|
||||
|
||||
// If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
|
||||
if (interfaces.size() > 0) {
|
||||
mod->set_bool_attribute("\\interfaces_replaced_in_module");
|
||||
}
|
||||
|
|
|
@ -857,7 +857,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
case AST_MODPORTMEMBER:
|
||||
break;
|
||||
case AST_INTERFACEPORT: {
|
||||
// If a port in a module with unknown type is found, mark it as "is_interface=true"
|
||||
// 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);
|
||||
|
@ -872,7 +872,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
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) {
|
||||
// Separate the interface instance name from any modports:
|
||||
if (ndots == 0) { // Does not have modport
|
||||
wire->attributes["\\interface_type"] = name_type;
|
||||
}
|
||||
else {
|
||||
|
@ -882,11 +883,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
while(std::getline(name_type_stream, segment, '.')) {
|
||||
seglist.push_back(segment);
|
||||
}
|
||||
if (ndots == 1) {
|
||||
if (ndots == 1) { // Has modport
|
||||
wire->attributes["\\interface_type"] = seglist[0];
|
||||
wire->attributes["\\interface_modport"] = seglist[1];
|
||||
}
|
||||
else {
|
||||
else { // Erroneous port type
|
||||
log_error("More than two '.' in signal port type (%s)\n", name_type.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -1034,7 +1035,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
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 object and set is_interface to true.
|
||||
// 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) {
|
||||
|
@ -1495,6 +1496,7 @@ 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++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue