Implemented proper handling of stub placeholder modules

This commit is contained in:
Clifford Wolf 2013-03-28 09:20:10 +01:00
parent 98fcb5daa3
commit 7bfc7b61a8
7 changed files with 70 additions and 16 deletions

6
README
View File

@ -205,6 +205,12 @@ Verilog Attributes and non-standard features
temporary variable within an always block. This is mostly used internally
by yosys to synthesize verilog functions and access arrays.
- The "placeholder" attribute on modules is used to mark empty stub modules
that have the same ports as the real thing but do not contain information
on the internal configuration. This modules are only used by the synthesis
passes to identify input and output ports of cells. The verilog backend
also does not output placeholder modules on default.
- In addition to the (* ... *) attribute syntax, yosys supports
the non-standard {* ... *} attribute syntax to set default attributes
for everything that comes after the {* ... *} statement. (Reset

View File

@ -923,6 +923,11 @@ struct VerilogBackend : public Backend {
log(" without this option all internal cells are converted to verilog\n");
log(" expressions.\n");
log("\n");
log(" -placeholders\n");
log(" usually modules with the 'placeholder' attribute are ignored. with\n");
log(" this option set only the modules with the 'placeholder' attribute\n");
log(" are written to the output file.\n");
log("\n");
}
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
{
@ -933,6 +938,8 @@ struct VerilogBackend : public Backend {
attr2comment = false;
noexpr = false;
bool placeholders = false;
reg_ct.clear();
reg_ct.setup_stdcells_mem();
reg_ct.cell_types.insert("$sr");
@ -958,16 +965,21 @@ struct VerilogBackend : public Backend {
noexpr = true;
continue;
}
if (arg == "-placeholders") {
placeholders = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
for (auto it = design->modules.begin(); it != design->modules.end(); it++) {
log("Dumping module `%s'.\n", it->first.c_str());
if (it != design->modules.begin())
fprintf(f, "\n");
dump_module(f, "", it->second);
}
for (auto it = design->modules.begin(); it != design->modules.end(); it++)
if ((it->second->attributes.count("\\placeholder") > 0) == placeholders) {
if (it != design->modules.begin())
fprintf(f, "\n");
log("Dumping module `%s'.\n", it->first.c_str());
dump_module(f, "", it->second);
}
reg_ct.clear();
}

View File

@ -46,7 +46,7 @@ namespace AST {
// instanciate global variables (private API)
namespace AST_INTERNAL {
bool flag_dump_ast, flag_dump_ast_diff, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg;
bool flag_dump_ast, flag_dump_ast_diff, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
RTLIL::SigSpec *genRTLIL_subst_from = NULL;
@ -679,6 +679,18 @@ static AstModule* process_module(AstNode *ast)
log("--- END OF AST DUMP ---\n");
}
if (flag_lib) {
std::vector<AstNode*> new_children;
for (auto child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output))
new_children.push_back(child);
else
delete child;
}
ast->children.swap(new_children);
ast->attributes["\\placeholder"] = AstNode::mkconst_int(0, false, 0);
}
current_module = new AstModule;
current_module->ast = NULL;
current_module->name = ast->str;
@ -705,11 +717,12 @@ static AstModule* process_module(AstNode *ast)
current_module->nolatches = flag_nolatches;
current_module->nomem2reg = flag_nomem2reg;
current_module->mem2reg = flag_mem2reg;
current_module->lib = flag_lib;
return current_module;
}
// create AstModule instances for all modules in the AST tree and add them to 'design'
void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast, bool dump_ast_diff, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg)
void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast, bool dump_ast_diff, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib)
{
current_ast = ast;
flag_dump_ast = dump_ast;
@ -718,6 +731,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast, bool dump_
flag_nolatches = nolatches;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
flag_lib = lib;
assert(current_ast->type == AST_DESIGN);
for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) {
@ -747,6 +761,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin
flag_nolatches = nolatches;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
flag_lib = lib;
use_internal_line_num();
std::vector<unsigned char> hash_data;
@ -821,6 +836,7 @@ void AstModule::update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes)
flag_nolatches = nolatches;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
flag_lib = lib;
use_internal_line_num();
for (auto it = auto_sizes.begin(); it != auto_sizes.end(); it++) {

View File

@ -189,13 +189,13 @@ namespace AST
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
void process(RTLIL::Design *design, AstNode *ast, bool dump_ast = false, bool dump_ast_diff = false, bool dump_vlog = false, bool nolatches = false, bool nomem2reg = false, bool mem2reg = false);
void process(RTLIL::Design *design, AstNode *ast, bool dump_ast = false, bool dump_ast_diff = false, bool dump_vlog = false, bool nolatches = false, bool nomem2reg = false, bool mem2reg = false, bool lib = false);
// parametric modules are supported directly by the AST library
// therfore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module {
AstNode *ast;
bool nolatches, nomem2reg, mem2reg;
bool nolatches, nomem2reg, mem2reg, lib;
virtual ~AstModule();
virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters);
virtual void update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes);
@ -217,7 +217,7 @@ namespace AST
namespace AST_INTERNAL
{
// internal state variables
extern bool flag_dump_ast, flag_dump_ast_diff, flag_nolatches, flag_nomem2reg, flag_mem2reg;
extern bool flag_dump_ast, flag_dump_ast_diff, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib;
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
extern RTLIL::SigSpec *genRTLIL_subst_from, *genRTLIL_subst_to;

View File

@ -89,6 +89,9 @@ struct VerilogFrontend : public Frontend {
log(" -nopp\n");
log(" do not run the pre-processor\n");
log("\n");
log(" -lib\n");
log(" only create empty placeholder modules\n");
log("\n");
}
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
{
@ -100,6 +103,7 @@ struct VerilogFrontend : public Frontend {
bool flag_mem2reg = false;
bool flag_ppdump = false;
bool flag_nopp = false;
bool flag_lib = false;
frontend_verilog_yydebug = false;
log_header("Executing Verilog-2005 frontend.\n");
@ -144,6 +148,10 @@ struct VerilogFrontend : public Frontend {
flag_nopp = true;
continue;
}
if (arg == "-lib") {
flag_lib = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
@ -173,7 +181,7 @@ struct VerilogFrontend : public Frontend {
frontend_verilog_yyparse();
frontend_verilog_yylex_destroy();
AST::process(design, current_ast, flag_dump_ast, flag_dump_ast_diff, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg);
AST::process(design, current_ast, flag_dump_ast, flag_dump_ast_diff, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib);
if (!flag_nopp)
fclose(fp);

View File

@ -352,8 +352,12 @@ struct ShowWorker
if (!design->selected_module(module->name))
continue;
if (design->selected_whole_module(module->name)) {
if (module->attributes.count("\\placeholder") > 0) {
log("Skipping placeholder module %s.\n", id2cstr(module->name));
continue;
} else
if (module->cells.empty() && module->connections.empty()) {
log("Skipping skeletton module %s.\n", id2cstr(module->name));
log("Skipping empty module %s.\n", id2cstr(module->name));
continue;
} else
log("Dumping module %s to page %d.\n", id2cstr(module->name), ++page_counter);
@ -461,9 +465,14 @@ struct ShowPass : public Pass {
if (format != "ps") {
int modcount = 0;
for (auto &mod_it : design->modules)
for (auto &mod_it : design->modules) {
if (mod_it.second->attributes.count("\\placeholder") > 0)
continue;
if (mod_it.second->cells.empty() && mod_it.second->connections.empty())
continue;
if (design->selected_module(mod_it.first))
modcount++;
}
if (modcount > 1)
log_cmd_error("For formats different than 'ps' only one module must be selected.\n");
}

View File

@ -113,6 +113,7 @@ static void generate(RTLIL::Design *design, const std::vector<std::string> &cell
RTLIL::Module *mod = new RTLIL::Module;
mod->name = celltype;
mod->attributes["\\placeholder"] = RTLIL::Const(0, 0);
design->modules[mod->name] = mod;
for (auto &decl : ports) {
@ -146,6 +147,8 @@ static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool fla
}
if (cell->parameters.size() == 0)
continue;
if (design->modules.at(cell->type)->attributes.count("\\placeholder") > 0)
continue;
RTLIL::Module *mod = design->modules[cell->type];
cell->type = mod->derive(design, cell->parameters);
cell->parameters.clear();
@ -207,7 +210,7 @@ static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool fla
if (auto_sizes.size() > 0) {
module->update_auto_wires(auto_sizes);
log_header("Continuing EXPAND pass.\n");
log_header("Continuing HIERARCHY pass.\n");
did_something = true;
}
@ -269,7 +272,7 @@ struct HierarchyPass : public Pass {
log(" use the specified top module to built a design hierarchy. modules\n");
log(" outside this tree (unused modules) are removed.\n");
log("\n");
log("In -generate mode this pass generates skeletton modules for the given cell\n");
log("In -generate mode this pass generates placeholder modules for the given cell\n");
log("types (wildcards supported). For this the design is searched for cells that\n");
log("match the given types and then the given port declarations are used to\n");
log("determine the direction of the ports. The syntax for a port declaration is:\n");