Added "read_verilog -nomeminit" and "nomeminit" attribute

This commit is contained in:
Clifford Wolf 2015-02-14 11:21:12 +01:00
parent a8e9d37c14
commit 7f1a1759d7
5 changed files with 34 additions and 7 deletions

5
README
View File

@ -257,6 +257,11 @@ Verilog Attributes and non-standard features
- The "mem2reg" attribute on modules or arrays forces the early
conversion of arrays to separate registers.
- The "nomeminit" attribute on modules or arrays prohibits the
creation of initialized memories. This effectively puts "mem2reg"
on all memories that are written to in an "initial" block and
are not ROMs.
- The "nolatches" attribute on modules or always-blocks
prohibits the generation of logic-loops for latches. Instead
all not explicitly assigned values default to x-bits. This does

View File

@ -53,7 +53,7 @@ namespace AST {
// instanciate global variables (private API)
namespace AST_INTERNAL {
bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
@ -958,6 +958,7 @@ static AstModule* process_module(AstNode *ast, bool defer)
current_module->ast = ast_before_simplify;
current_module->nolatches = flag_nolatches;
current_module->nomeminit = flag_nomeminit;
current_module->nomem2reg = flag_nomem2reg;
current_module->mem2reg = flag_mem2reg;
current_module->lib = flag_lib;
@ -969,13 +970,14 @@ static AstModule* process_module(AstNode *ast, bool defer)
}
// 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_ast1, bool dump_ast2, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire)
void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire)
{
current_ast = ast;
flag_dump_ast1 = dump_ast1;
flag_dump_ast2 = dump_ast2;
flag_dump_vlog = dump_vlog;
flag_nolatches = nolatches;
flag_nomeminit = nomeminit;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
flag_lib = lib;
@ -1037,6 +1039,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
flag_dump_ast2 = false;
flag_dump_vlog = false;
flag_nolatches = nolatches;
flag_nomeminit = nomeminit;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
flag_lib = lib;
@ -1103,6 +1106,7 @@ RTLIL::Module *AstModule::clone() const
new_mod->ast = ast->clone();
new_mod->nolatches = nolatches;
new_mod->nomeminit = nomeminit;
new_mod->nomem2reg = nomem2reg;
new_mod->mem2reg = mem2reg;
new_mod->lib = lib;

View File

@ -265,13 +265,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_ast1, bool dump_ast2, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire);
void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire);
// 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, lib, noopt, icells, autowire;
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
virtual ~AstModule();
virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters);
virtual RTLIL::Module *clone() const;
@ -295,7 +295,7 @@ namespace AST
namespace AST_INTERNAL
{
// internal state variables
extern bool flag_dump_ast1, flag_dump_ast2, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
extern bool flag_dump_ast1, flag_dump_ast2, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr;

View File

@ -83,11 +83,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
AstNode *mem = it.first;
uint32_t memflags = it.second;
bool this_nomeminit = flag_nomeminit;
log_assert((memflags & ~0x00ffff00) == 0);
if (mem->get_bool_attribute("\\nomem2reg"))
continue;
if (mem->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit"))
this_nomeminit = true;
if (memflags & AstNode::MEM2REG_FL_FORCED)
goto silent_activate;
@ -97,7 +101,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (memflags & AstNode::MEM2REG_FL_SET_ASYNC)
goto verbose_activate;
if ((memflags & AstNode::MEM2REG_FL_SET_INIT) && (memflags & AstNode::MEM2REG_FL_SET_ELSE))
if ((memflags & AstNode::MEM2REG_FL_SET_INIT) && (memflags & AstNode::MEM2REG_FL_SET_ELSE) && this_nomeminit)
goto verbose_activate;
if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)

View File

@ -83,11 +83,20 @@ struct VerilogFrontend : public Frontend {
log(" this can also be achieved by setting the 'nomem2reg'\n");
log(" attribute on the respective module or register.\n");
log("\n");
log(" This is potentially dangerous. Usually the front-end has good\n");
log(" reasons for converting an array to a list of registers.\n");
log(" Prohibiting this step will likely result in incorrect synthesis\n");
log(" results.\n");
log("\n");
log(" -mem2reg\n");
log(" always convert memories to registers. this can also be\n");
log(" achieved by setting the 'mem2reg' attribute on the respective\n");
log(" module or register.\n");
log("\n");
log(" -nomeminit\n");
log(" do not infer $meminit cells and instead convert initialized\n");
log(" memories to registers directly in the front-end.\n");
log("\n");
log(" -ppdump\n");
log(" dump verilog code after pre-processor\n");
log("\n");
@ -139,6 +148,7 @@ struct VerilogFrontend : public Frontend {
bool flag_dump_ast2 = false;
bool flag_dump_vlog = false;
bool flag_nolatches = false;
bool flag_nomeminit = false;
bool flag_nomem2reg = false;
bool flag_mem2reg = false;
bool flag_ppdump = false;
@ -186,6 +196,10 @@ struct VerilogFrontend : public Frontend {
flag_nolatches = true;
continue;
}
if (arg == "-nomeminit") {
flag_nomeminit = true;
continue;
}
if (arg == "-nomem2reg") {
flag_nomem2reg = true;
continue;
@ -288,7 +302,7 @@ struct VerilogFrontend : public Frontend {
child->attributes[attr] = AST::AstNode::mkconst_int(1, false);
}
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);
if (!flag_nopp)
delete lexin;