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 ...]
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.

View File

@ -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

View File

@ -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) {

View File

@ -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());
}

View File

@ -211,6 +211,27 @@ private:
}
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*) {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
}

View File

@ -1886,7 +1886,7 @@ statement_item<nodep>: // 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 }

View File

@ -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;