diff --git a/bin/verilator b/bin/verilator index af9f9edf0..a0dcce80b 100755 --- a/bin/verilator +++ b/bin/verilator @@ -231,7 +231,7 @@ descriptions in the next sections for more information. --bbox-sys Blackbox unknown $system calls --bbox-unsup Blackbox unsupported language features --bin Override Verilator binary - -CFLAGS C++ Compiler flags for makefile + -CFLAGS C++ Compiler flags for makefile --cc Create C++ output --cdc Clock domain crossing analysis --compiler Tune for specified C++ compiler @@ -247,19 +247,19 @@ descriptions in the next sections for more information. --debugi- Enable debugging a source file at a level +define++ Set preprocessor define --dump-tree Enable dumping .tree files - -E Preprocess, but do not compile + -E Preprocess, but do not compile --error-limit Abort after this number of errors --exe Link to create executable -F Parse options from a file, relatively -f Parse options from a file --gdbbt Run Verilator under GDB for backtrace - --help Display this help. + --help Display this help -I Directory to search for includes +incdir+ Directory to search for includes --inhibit-sim Create function to turn off sim --inline-mult Tune module inlining - -LDFLAGS Linker pre-object flags for makefile - -LDLIBS Linker library flags for makefile + -LDFLAGS Linker pre-object flags for makefile + -LDLIBS Linker library flags for makefile --language Language standard to parse +libext++[ext]... Extensions for finding modules --lint-only Lint, but do not make output @@ -273,12 +273,12 @@ descriptions in the next sections for more information. -O0 Disable optimizations -O3 High performance optimizations -O Selectable optimizations - -o Name of final executable + -o Name of final executable --output-split Split .cpp files into pieces --output-split-cfuncs Split .ccp functions --pins-bv Specify types for top level ports --pins-uint8 Specify types for top level ports - --pipe-filter Filter all input through a script + --pipe-filter Filter all input through a script --prefix Name of top level class --profile-cfuncs Name functions for profiling --private Debugging; see docs diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 94dc72306..933f7a9e0 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -182,7 +182,7 @@ private: for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { if (itemp->isDefault()) has_default=true; } - if (nodep->fullPragma()) { + if (nodep->fullPragma() || nodep->priorityPragma()) { // Simply need to add a default if there isn't one already m_statAsFull++; if (!has_default) { @@ -190,7 +190,7 @@ private: newFireAssert(nodep, "synthesis full_case, but non-match found"))); } } - if (nodep->parallelPragma()) { + if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) { // Need to check that one, and only one of the case items match at any moment // If there's a default, we allow none to match, else exactly one must match m_statAsFull++; @@ -207,7 +207,8 @@ private: else propp = onep; } } - AstNode* ohot = (has_default + bool allow_none = has_default || nodep->unique0Pragma(); + AstNode* ohot = (allow_none ? (new AstOneHot0(nodep->fileline(), propp))->castNode() : (new AstOneHot (nodep->fileline(), propp))->castNode()); AstIf* ifp = new AstIf (nodep->fileline(), diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index b178d0387..25e8eece7 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1538,11 +1538,15 @@ private: AstCaseType m_casex; // 0=case, 1=casex, 2=casez bool m_fullPragma; // Synthesis full_case bool m_parallelPragma; // Synthesis parallel_case + bool m_uniquePragma; // unique case + bool m_unique0Pragma; // unique0 case + bool m_priorityPragma; // priority case public: AstCase(FileLine* fileline, AstCaseType casex, AstNode* exprp, AstNode* casesp) : AstNodeCase(fileline, exprp, casesp) { m_casex=casex; m_fullPragma=false; m_parallelPragma=false; + m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false; } ASTNODE_NODE_FUNCS(Case, CASE) virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; } @@ -1554,6 +1558,12 @@ public: void fullPragma(bool flag) { m_fullPragma=flag; } bool parallelPragma() const { return m_parallelPragma; } void parallelPragma(bool flag) { m_parallelPragma=flag; } + bool uniquePragma() const { return m_uniquePragma; } + void uniquePragma(bool flag) { m_uniquePragma=flag; } + bool unique0Pragma() const { return m_unique0Pragma; } + void unique0Pragma(bool flag) { m_unique0Pragma=flag; } + bool priorityPragma() const { return m_priorityPragma; } + void priorityPragma(bool flag) { m_priorityPragma=flag; } }; struct AstCaseItem : public AstNode { @@ -1952,10 +1962,22 @@ struct AstGenIf : public AstNodeIf { }; struct AstIf : public AstNodeIf { +private: + bool m_uniquePragma; // unique case + bool m_unique0Pragma; // unique0 case + bool m_priorityPragma; // priority case +public: AstIf(FileLine* fileline, AstNode* condp, AstNode* ifsp, AstNode* elsesp) : AstNodeIf(fileline, condp, ifsp, elsesp) { + m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false; } ASTNODE_NODE_FUNCS(If, IF) + bool uniquePragma() const { return m_uniquePragma; } + void uniquePragma(bool flag) { m_uniquePragma=flag; } + bool unique0Pragma() const { return m_unique0Pragma; } + void unique0Pragma(bool flag) { m_unique0Pragma=flag; } + bool priorityPragma() const { return m_priorityPragma; } + void priorityPragma(bool flag) { m_priorityPragma=flag; } }; struct AstJumpLabel : public AstNodeStmt { diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 6b5f64a31..eb43aeb7e 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -166,7 +166,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { nodep->iterateChildren(*this); } virtual void visit(AstNodeCase* nodep, AstNUser*) { - putfs(nodep,nodep->verilogKwd()); + putfs(nodep,""); + if (AstCase* casep = nodep->castCase()) { + if (casep->priorityPragma()) puts("priority "); + if (casep->uniquePragma()) puts("unique "); + if (casep->unique0Pragma()) puts("unique0 "); + } + puts(nodep->verilogKwd()); puts(" ("); nodep->exprp()->iterateAndNext(*this); puts(")\n"); @@ -301,7 +307,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { putfs(nodep,"end\n"); } virtual void visit(AstNodeIf* nodep, AstNUser*) { - putfs(nodep,"if ("); + putfs(nodep,""); + if (AstIf* ifp = nodep->castIf()) { + if (ifp->priorityPragma()) puts("priority "); + if (ifp->uniquePragma()) puts("unique "); + if (ifp->unique0Pragma()) puts("unique0 "); + } + puts("if ("); nodep->condp()->iterateAndNext(*this); puts(") begin\n"); nodep->ifsp()->iterateAndNext(*this); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index a864ce757..31252518c 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -38,7 +38,7 @@ class V3Lexer; //====================================================================== // Types (between parser & lexer) -typedef enum { uniq_NONE, uniq_UNIQUE, uniq_PRIORITY } V3UniqState; +typedef enum { uniq_NONE, uniq_UNIQUE, uniq_UNIQUE0, uniq_PRIORITY } V3UniqState; typedef enum { iprop_NONE, iprop_CONTEXT, iprop_PURE } V3ImportProperty; diff --git a/src/verilog.l b/src/verilog.l index dd714e0c2..504b3e0db 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -493,6 +493,7 @@ word [a-zA-Z0-9_]+ { /* Keywords */ "global" { FL; return yGLOBAL__LEX; } + "unique0" { FL; return yUNIQUE0; } /* Generic unsupported warnings */ "accept_on" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } "checker" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } @@ -511,7 +512,6 @@ word [a-zA-Z0-9_]+ "strong" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } "sync_accept_on" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } "sync_reject_on" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } - "unique0" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } "until" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } "until_with" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } "untyped" { yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); } diff --git a/src/verilog.y b/src/verilog.y index db0ae2b0e..3e31ca1bc 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -369,6 +369,7 @@ class AstSenTree; %token yTRUE "true" %token yTYPEDEF "typedef" %token yUNIQUE "unique" +%token yUNIQUE0 "unique0" %token yUNSIGNED "unsigned" %token yVAR "var" %token yVECTORED "vectored" @@ -1819,16 +1820,23 @@ statement_item: // IEEE: statement_item // // // IEEE: case_statement | unique_priorityE caseStart caseAttrE case_itemListE yENDCASE { $$ = $2; if ($4) $2->addItemsp($4); - if ($1 == uniq_UNIQUE) $2->parallelPragma(true); - if ($1 == uniq_PRIORITY) $2->fullPragma(true); } + if ($1 == uniq_UNIQUE) $2->uniquePragma(true); + if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true); + if ($1 == uniq_PRIORITY) $2->priorityPragma(true); } //UNSUP caseStart caseAttrE yMATCHES case_patternListE yENDCASE { } //UNSUP caseStart caseAttrE yINSIDE case_insideListE yENDCASE { } // // // IEEE: conditional_statement | unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE - { $$ = new AstIf($2,$4,$6,NULL); } + { $$ = new AstIf($2,$4,$6,NULL); + if ($1 == uniq_UNIQUE) $$->castIf()->uniquePragma(true); + if ($1 == uniq_UNIQUE0) $$->castIf()->unique0Pragma(true); + if ($1 == uniq_PRIORITY) $$->castIf()->priorityPragma(true); } | unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock - { $$ = new AstIf($2,$4,$6,$8); } + { $$ = new AstIf($2,$4,$6,$8); + if ($1 == uniq_UNIQUE) $$->castIf()->uniquePragma(true); + if ($1 == uniq_UNIQUE0) $$->castIf()->unique0Pragma(true); + if ($1 == uniq_PRIORITY) $$->castIf()->priorityPragma(true); } // | finc_or_dec_expression ';' { $$ = $1; } // // IEEE: inc_or_dec_expression @@ -1961,6 +1969,7 @@ unique_priorityE: // IEEE: unique_priority + empty /*empty*/ { $$ = uniq_NONE; } | yPRIORITY { $$ = uniq_PRIORITY; } | yUNIQUE { $$ = uniq_UNIQUE; } + | yUNIQUE0 { $$ = uniq_UNIQUE0; } ; caseStart: // IEEE: part of case_statement