Support disable for loop escapes.
This commit is contained in:
parent
2e9471797d
commit
8137f41fc3
4
Changes
4
Changes
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue