From 7f1a1759d7cdbbb528c451bf8fc8baf3b7e72893 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 14 Feb 2015 11:21:12 +0100 Subject: Added "read_verilog -nomeminit" and "nomeminit" attribute --- README | 5 +++++ frontends/ast/ast.cc | 8 ++++++-- frontends/ast/ast.h | 6 +++--- frontends/ast/simplify.cc | 6 +++++- frontends/verilog/verilog_frontend.cc | 16 +++++++++++++++- 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/README b/README index 4ef430938..9fe43ec98 100644 --- a/README +++ b/README @@ -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 diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 589b08e1d..0de24013c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -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 current_scope; const dict *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, dictast = ast->clone(); new_mod->nolatches = nolatches; + new_mod->nomeminit = nomeminit; new_mod->nomem2reg = nomem2reg; new_mod->mem2reg = mem2reg; new_mod->lib = lib; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 3523d0754..0c1135620 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -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 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 current_scope; extern const dict *genRTLIL_subst_ptr; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 6e5692011..10b651000 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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) diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 23d35f682..41561e80c 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -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; -- cgit v1.2.3