Support disable for loop escapes.

This commit is contained in:
Wilson Snyder 2011-06-28 21:26:49 -04:00
parent 2e9471797d
commit 8137f41fc3
7 changed files with 59 additions and 3 deletions

View File

@ -3,6 +3,10 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! 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 * Verilator 3.813 2011/06/28
*** Support bit vectors > 64 bits wide in DPI import and exports. *** Support bit vectors > 64 bits wide in DPI import and exports.

View File

@ -2258,6 +2258,13 @@ not arrays nor structs.
Treated as a "longint"; does not yet warn about operations that are Treated as a "longint"; does not yet warn about operations that are
specified as illegal on chandles. 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 =item priority if, unique if
Priority and unique if's are treated as normal ifs and not asserted to be Priority and unique if's are treated as normal ifs and not asserted to be

View File

@ -1973,6 +1973,18 @@ struct AstContinue : public AstNodeStmt {
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks 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 { struct AstReturn : public AstNodeStmt {
AstReturn(FileLine* fileline, AstNode* lhsp=NULL) AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
: AstNodeStmt (fileline) { : AstNodeStmt (fileline) {

View File

@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
} }
puts(");\n"); puts(");\n");
} }
virtual void visit(AstDisable* nodep, AstNUser*) {
putbs("disable "+nodep->name()+";\n");
}
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstDisplay* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
} }

View File

@ -211,6 +211,27 @@ private:
} }
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL; nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
} }
virtual void visit(AstDisable* nodep, AstNUser*) {
UINFO(8," DISABLE "<<nodep<<endl);
nodep->iterateChildren(*this);
AstBegin* beginp = NULL;
for (BeginStack::reverse_iterator it = m_beginStack.rbegin(); it != m_beginStack.rend(); ++it) {
UINFO(9," UNDERBLK "<<*it<<endl);
if ((*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: "<<nodep->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*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true); if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
} }

View File

@ -1886,7 +1886,7 @@ statement_item<nodep>: // IEEE: statement_item
| statementVerilatorPragmas { $$ = $1; } | statementVerilatorPragmas { $$ = $1; }
// //
// // IEEE: disable_statement // // 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 } //UNSUP yDISABLE yFORK ';' { UNSUP }
// // IEEE: event_trigger // // IEEE: event_trigger
//UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP } //UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP }

View File

@ -92,8 +92,17 @@ module t (/*AUTOARG*/
input [3:0] loop_continue; input [3:0] loop_continue;
integer i; integer i;
// Placeholder Test1 = 0;
return Test0(loop_stop,loop_break,loop_continue); 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 endfunction
function [15:0] Test2; function [15:0] Test2;