From 8137f41fc393303573d085c04bb46111ee04ec8b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 28 Jun 2011 21:26:49 -0400 Subject: [PATCH] Support disable for loop escapes. --- Changes | 4 ++++ bin/verilator | 7 +++++++ src/V3AstNodes.h | 12 ++++++++++++ src/V3EmitV.cpp | 3 +++ src/V3LinkJump.cpp | 21 +++++++++++++++++++++ src/verilog.y | 2 +- test_regress/t/t_for_break.v | 13 +++++++++++-- 7 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 457dbefeb..206d397d3 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,10 @@ Revision history for Verilator The contributors that suggested a given feature are shown in []. [by ...] indicates the contributor was also the author of the fix; Thanks! +* Verilator 3.814**** + +*** Support disable for loop escapes. + * Verilator 3.813 2011/06/28 *** Support bit vectors > 64 bits wide in DPI import and exports. diff --git a/bin/verilator b/bin/verilator index 538dfc26a..8f9598f7c 100755 --- a/bin/verilator +++ b/bin/verilator @@ -2258,6 +2258,13 @@ not arrays nor structs. Treated as a "longint"; does not yet warn about operations that are specified as illegal on chandles. +=item disable + +Disable statements may be used only if the block being disabled is a block +the disable statement itself is inside. This is commonly used to provide +loop break and continue functionality before SystemVerilog added the break +and continue keywords. + =item priority if, unique if Priority and unique if's are treated as normal ifs and not asserted to be diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 235fe93b8..479dce113 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1973,6 +1973,18 @@ struct AstContinue : public AstNodeStmt { virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks }; +struct AstDisable : public AstNodeStmt { +private: + string m_name; // Name of block +public: + AstDisable(FileLine* fileline, const string& name) + : AstNodeStmt(fileline), m_name(name) {} + ASTNODE_NODE_FUNCS(Disable, DISABLE) + virtual string name() const { return m_name; } // * = Block name + void name(const string& flag) { m_name=flag; } + virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks +}; + struct AstReturn : public AstNodeStmt { AstReturn(FileLine* fileline, AstNode* lhsp=NULL) : AstNodeStmt (fileline) { diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index a72422278..e17b563a5 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts(");\n"); } + virtual void visit(AstDisable* nodep, AstNUser*) { + putbs("disable "+nodep->name()+";\n"); + } virtual void visit(AstDisplay* nodep, AstNUser*) { visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index a12c50b85..4f73b4321 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -211,6 +211,27 @@ private: } nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL; } + virtual void visit(AstDisable* nodep, AstNUser*) { + UINFO(8," DISABLE "<iterateChildren(*this); + AstBegin* beginp = NULL; + for (BeginStack::reverse_iterator it = m_beginStack.rbegin(); it != m_beginStack.rend(); ++it) { + UINFO(9," UNDERBLK "<<*it<name() == nodep->name()) { + beginp = *it; + break; + } + } + //if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labeli: "); } + if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<name()); } + else { + // Jump to the end of the named begin + AstJumpLabel* labelp = findAddLabel(beginp, false); + nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp)); + } + nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL; + //if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labelo: "); } + } virtual void visit(AstVarRef* nodep, AstNUser*) { if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true); } diff --git a/src/verilog.y b/src/verilog.y index c8c24b39c..e284ea022 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1886,7 +1886,7 @@ statement_item: // IEEE: statement_item | statementVerilatorPragmas { $$ = $1; } // // // IEEE: disable_statement - //UNSUP yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { UNSUP } + | yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); } //UNSUP yDISABLE yFORK ';' { UNSUP } // // IEEE: event_trigger //UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP } diff --git a/test_regress/t/t_for_break.v b/test_regress/t/t_for_break.v index d7bb3aa27..748be3015 100644 --- a/test_regress/t/t_for_break.v +++ b/test_regress/t/t_for_break.v @@ -92,8 +92,17 @@ module t (/*AUTOARG*/ input [3:0] loop_continue; integer i; - // Placeholder - return Test0(loop_stop,loop_break,loop_continue); + Test1 = 0; + begin : outer_block + for (i=1; i<20; i=i+1) begin : inner_block + Test1 = Test1 + 1; + // continue, IE jump to end-of-inner_block. Must be inside inner_block. + if (i[3:0] == loop_continue) disable inner_block; + // break, IE jump to end-of-outer_block. Must be inside outer_block. + if (i[3:0] == loop_break) disable outer_block; + Test1 = Test1 + i[15:0]; + end : inner_block + end : outer_block endfunction function [15:0] Test2;