Add "read_verilog -pwires" feature, closes #1106
authorClifford Wolf <clifford@clifford.at>
Wed, 19 Jun 2019 12:38:50 +0000 (14:38 +0200)
committerClifford Wolf <clifford@clifford.at>
Wed, 19 Jun 2019 12:38:50 +0000 (14:38 +0200)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
README.md
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/verilog/verilog_frontend.cc
frontends/verilog/verilog_parser.y

index 637703a7f2faf766d38b726d5e1dc43d18955f5a..42f972c8e203cad2eaca268bda19cfc9525f60d0 100644 (file)
--- a/README.md
+++ b/README.md
@@ -354,6 +354,10 @@ Verilog Attributes and non-standard features
   module inputs. The attribute is attached to the input wire by the HDL
   front-end when the input is declared with a default value.
 
+- The ``parameter`` and ``localparam`` attributes are used to mark wires
+  that represent module parameters or localparams (when the HDL front-end
+  is run in -pwires mode).
+
 - 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
index b5b968e9ed5c736a112f3816760acb25664ac874..3d066af53c2d32efbccb513c3151d3695ace8635 100644 (file)
@@ -46,7 +46,7 @@ namespace AST {
 // instantiate global variables (private API)
 namespace AST_INTERNAL {
        bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
-       bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_autowire;
+       bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, 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;
@@ -1112,6 +1112,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
        current_module->nowb = flag_nowb;
        current_module->noopt = flag_noopt;
        current_module->icells = flag_icells;
+       current_module->pwires = flag_pwires;
        current_module->autowire = flag_autowire;
        current_module->fixup_ports();
 
@@ -1126,7 +1127,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
 
 // 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 no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
-               bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
+               bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire)
 {
        current_ast = ast;
        flag_dump_ast1 = dump_ast1;
@@ -1144,6 +1145,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
        flag_nowb = nowb;
        flag_noopt = noopt;
        flag_icells = icells;
+       flag_pwires = pwires;
        flag_autowire = autowire;
 
        log_assert(current_ast->type == AST_DESIGN);
@@ -1480,6 +1482,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
        flag_nowb = nowb;
        flag_noopt = noopt;
        flag_icells = icells;
+       flag_pwires = pwires;
        flag_autowire = autowire;
        use_internal_line_num();
 
@@ -1551,6 +1554,7 @@ RTLIL::Module *AstModule::clone() const
        new_mod->lib = lib;
        new_mod->noopt = noopt;
        new_mod->icells = icells;
+       new_mod->pwires = pwires;
        new_mod->autowire = autowire;
 
        return new_mod;
index b8cde060e7d1db2659527333b12ef1e64f6aedf7..54b2fb31920bbfcda56938e00aee951a5945a35a 100644 (file)
@@ -286,13 +286,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 no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit,
-                       bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
+                       bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire);
 
        // parametric modules are supported directly by the AST library
        // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
        struct AstModule : RTLIL::Module {
                AstNode *ast;
-               bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, autowire;
+               bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, 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, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
@@ -325,7 +325,7 @@ namespace AST_INTERNAL
 {
        // internal state variables
        extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
-       extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
+       extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_pwires, 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;
index 32ed401eb02fe61221ecfbe00633f83a9d41b296..079fc11e5dce10168734c2c44e277bc9cbbea6f3 100644 (file)
@@ -853,7 +853,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        case AST_FUNCTION:
        case AST_DPI_FUNCTION:
        case AST_AUTOWIRE:
-       case AST_LOCALPARAM:
        case AST_DEFPARAM:
        case AST_GENVAR:
        case AST_GENFOR:
@@ -895,6 +894,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        // remember the parameter, needed for example in techmap
        case AST_PARAMETER:
                current_module->avail_parameters.insert(str);
+               /* fall through */
+       case AST_LOCALPARAM:
+               if (flag_pwires)
+               {
+                       if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT)
+                               log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str());
+
+                       RTLIL::Const val = children[0]->bitsAsConst();
+                       RTLIL::Wire *wire = current_module->addWire(str, GetSize(val));
+                       current_module->connect(wire, val);
+
+                       wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
+                       wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1;
+
+                       for (auto &attr : attributes) {
+                               if (attr.second->type != AST_CONSTANT)
+                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
+                               wire->attributes[attr.first] = attr.second->asAttrConst();
+                       }
+               }
                break;
 
        // create an RTLIL::Wire for an AST_WIRE node
index 01e589efbca60c443e1c6b9c08854b2a4a5ec00c..0e2bead6f905a99dd1d2e146235038c18052d152 100644 (file)
@@ -168,6 +168,9 @@ struct VerilogFrontend : public Frontend {
                log("    -icells\n");
                log("        interpret cell types starting with '$' as internal cell types\n");
                log("\n");
+               log("    -pwires\n");
+               log("        add a wire for each module parameter\n");
+               log("\n");
                log("    -nooverwrite\n");
                log("        ignore re-definitions of modules. (the default behavior is to\n");
                log("        create an error message if the existing module is not a black box\n");
@@ -228,6 +231,7 @@ struct VerilogFrontend : public Frontend {
                bool flag_nodpi = false;
                bool flag_noopt = false;
                bool flag_icells = false;
+               bool flag_pwires = false;
                bool flag_nooverwrite = false;
                bool flag_overwrite = false;
                bool flag_defer = false;
@@ -368,6 +372,10 @@ struct VerilogFrontend : public Frontend {
                                flag_icells = true;
                                continue;
                        }
+                       if (arg == "-pwires") {
+                               flag_pwires = true;
+                               continue;
+                       }
                        if (arg == "-ignore_redef" || arg == "-nooverwrite") {
                                flag_nooverwrite = true;
                                flag_overwrite = false;
@@ -458,7 +466,7 @@ struct VerilogFrontend : public Frontend {
                        error_on_dpi_function(current_ast);
 
                AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
-                               flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
+                               flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
 
                if (!flag_nopp)
                        delete lexin;
index ebb4369c37f482a717f617171328426cc00ae8b4..8234479cca97bef3f06465fdea35b779105d66d9 100644 (file)
@@ -319,15 +319,17 @@ module_para_list:
 
 single_module_para:
        /* empty */ |
-       TOK_PARAMETER {
+       attr TOK_PARAMETER {
                if (astbuf1) delete astbuf1;
                astbuf1 = new AstNode(AST_PARAMETER);
                astbuf1->children.push_back(AstNode::mkconst_int(0, true));
+               append_attr(astbuf1, $1);
        } param_signed param_integer param_range single_param_decl |
-       TOK_LOCALPARAM {
+       attr TOK_LOCALPARAM {
                if (astbuf1) delete astbuf1;
                astbuf1 = new AstNode(AST_LOCALPARAM);
                astbuf1->children.push_back(AstNode::mkconst_int(0, true));
+               append_attr(astbuf1, $1);
        } param_signed param_integer param_range single_param_decl |
        single_param_decl;
 
@@ -1217,6 +1219,7 @@ param_decl:
        attr TOK_PARAMETER {
                astbuf1 = new AstNode(AST_PARAMETER);
                astbuf1->children.push_back(AstNode::mkconst_int(0, true));
+               append_attr(astbuf1, $1);
        } param_signed param_integer param_real param_range param_decl_list ';' {
                delete astbuf1;
        };
@@ -1225,6 +1228,7 @@ localparam_decl:
        attr TOK_LOCALPARAM {
                astbuf1 = new AstNode(AST_LOCALPARAM);
                astbuf1->children.push_back(AstNode::mkconst_int(0, true));
+               append_attr(astbuf1, $1);
        } param_signed param_integer param_real param_range param_decl_list ';' {
                delete astbuf1;
        };