Support `wait fork` (#4586)
This commit is contained in:
parent
05bb7fa821
commit
83a0085c4d
|
|
@ -120,15 +120,21 @@ public:
|
|||
void attach(VlProcess* childp) { m_children.insert(childp); }
|
||||
void detach(VlProcess* childp) { m_children.erase(childp); }
|
||||
|
||||
int state() { return m_state; }
|
||||
int state() const { return m_state; }
|
||||
void state(int s) { m_state = s; }
|
||||
void disable() {
|
||||
state(KILLED);
|
||||
disable_fork();
|
||||
disableFork();
|
||||
}
|
||||
void disable_fork() {
|
||||
void disableFork() {
|
||||
for (VlProcess* childp : m_children) childp->disable();
|
||||
}
|
||||
bool completed() const { return state() == FINISHED || state() == KILLED; }
|
||||
bool completedFork() const {
|
||||
for (const VlProcess* const childp : m_children)
|
||||
if (!childp->completed()) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string VL_TO_STRING(const VlProcessRef& p) { return std::string("process"); }
|
||||
|
|
|
|||
|
|
@ -617,6 +617,7 @@ public:
|
|||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
bool same(const AstNode* /*samep*/) const override { return true; }
|
||||
bool isPure() override { return pure(); }
|
||||
bool pure() const { return m_pure; }
|
||||
void pure(bool flag) { m_pure = flag; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3325,6 +3325,7 @@ public:
|
|||
explicit AstWaitFork(FileLine* fl)
|
||||
: ASTGEN_SUPER_WaitFork(fl) {}
|
||||
ASTGEN_MEMBERS_AstWaitFork;
|
||||
bool isTimingControl() const override { return true; }
|
||||
};
|
||||
class AstWhile final : public AstNodeStmt {
|
||||
// @astgen op1 := precondsp : List[AstNode]
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ public:
|
|||
puts("]);\n");
|
||||
}
|
||||
}
|
||||
void visit(AstDisableFork* nodep) override { puts("vlProcess->disable_fork();\n"); }
|
||||
void visit(AstDisableFork* nodep) override { puts("vlProcess->disableFork();\n"); }
|
||||
void visit(AstCReturn* nodep) override {
|
||||
puts("return (");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
|||
void visit(AstCExpr* nodep) override {
|
||||
putfs(nodep, "$_CEXPR(");
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(");\n");
|
||||
puts(")");
|
||||
}
|
||||
void visit(AstUCStmt* nodep) override {
|
||||
putfs(nodep, "$c(");
|
||||
|
|
|
|||
|
|
@ -275,6 +275,10 @@ private:
|
|||
visit(static_cast<AstNode*>(nodep));
|
||||
addFlags(m_procp, T_FORCES_PROC | T_NEEDS_PROC);
|
||||
}
|
||||
void visit(AstWaitFork* nodep) override {
|
||||
visit(static_cast<AstNode*>(nodep));
|
||||
addFlags(m_procp, T_FORCES_PROC | T_NEEDS_PROC);
|
||||
}
|
||||
void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_procp);
|
||||
m_procp = nodep;
|
||||
|
|
@ -573,8 +577,11 @@ private:
|
|||
// Returns true if we are under a class or the given tree has any references to locals. These
|
||||
// are cases where static, globally-evaluated triggers are not suitable.
|
||||
bool needDynamicTrigger(AstNode* const nodep) const {
|
||||
return m_classp || nodep->exists([](const AstNodeVarRef* const refp) {
|
||||
return refp->varp()->isFuncLocal();
|
||||
return m_classp || nodep->exists([](AstNode* const nodep) {
|
||||
if (AstNodeVarRef* varp = VN_CAST(nodep, NodeVarRef)) {
|
||||
return varp->varp()->isFuncLocal();
|
||||
}
|
||||
return !nodep->isPure();
|
||||
});
|
||||
}
|
||||
// Returns true if the given trigger expression needs a destructive post update after trigger
|
||||
|
|
@ -1050,6 +1057,13 @@ private:
|
|||
// var
|
||||
alwaysp->addNextHere(nodep);
|
||||
}
|
||||
void visit(AstWaitFork* nodep) override {
|
||||
AstCExpr* const exprp = new AstCExpr{nodep->fileline(), "vlProcess->completedFork()", 1};
|
||||
exprp->pure(false);
|
||||
AstWait* const waitp = new AstWait{nodep->fileline(), exprp, nullptr};
|
||||
nodep->replaceWith(waitp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
void visit(AstWait* nodep) override {
|
||||
// Wait on changed events related to the vars in the wait statement
|
||||
FileLine* const flp = nodep->fileline();
|
||||
|
|
|
|||
|
|
@ -693,6 +693,7 @@ private:
|
|||
if (nodep->fileline()->timingOn()) {
|
||||
if (v3Global.opt.timing().isSetFalse()) {
|
||||
nodep->v3warn(E_NOTIMING, "Support for disable fork statement requires --timing");
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
} else if (!v3Global.opt.timing().isSetTrue()) {
|
||||
nodep->v3warn(E_NEEDTIMINGOPT, "Use --timing or --no-timing to specify how "
|
||||
<< "disable fork should be handled");
|
||||
|
|
@ -700,8 +701,15 @@ private:
|
|||
}
|
||||
}
|
||||
void visit(AstWaitFork* nodep) override {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait fork statements");
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
if (nodep->fileline()->timingOn()) {
|
||||
if (v3Global.opt.timing().isSetFalse()) {
|
||||
nodep->v3warn(E_NOTIMING, "Support for disable fork statement requires --timing");
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
} else if (!v3Global.opt.timing().isSetTrue()) {
|
||||
nodep->v3warn(E_NEEDTIMINGOPT, "Use --timing or --no-timing to specify how "
|
||||
<< "disable fork should be handled");
|
||||
}
|
||||
}
|
||||
}
|
||||
void visit(AstToLowerN* nodep) override {
|
||||
if (m_vup->prelim()) {
|
||||
|
|
|
|||
|
|
@ -14809,9 +14809,7 @@ class uvm_objection extends uvm_report_object;
|
|||
if (m_trace_mode)
|
||||
m_report(obj,source_obj,description,count,"all_dropped");
|
||||
all_dropped(obj,source_obj,description, count);
|
||||
//TODO issue #4465 - Support wait fork
|
||||
//TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:14761:7: Unsupported: wait fork statements
|
||||
//TODO wait fork;
|
||||
wait fork;
|
||||
if (m_source_count.exists(obj) && m_source_count[obj] == 0)
|
||||
m_source_count.delete(obj);
|
||||
if (m_total_count.exists(obj) && m_total_count[obj] == 0)
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
%Error-UNSUPPORTED: t/t_wait_fork.v:17:7: Unsupported: wait fork statements
|
||||
: ... note: In instance 't'
|
||||
17 | wait fork;
|
||||
| ^~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
@ -10,10 +10,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint(
|
||||
verilator_flags2 => ['--lint-only --timing'],
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
compile(
|
||||
verilator_flags2 => ["--exe --main --timing"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
|
|
|||
|
|
@ -8,13 +8,16 @@ module t(/*AUTOARG*/);
|
|||
|
||||
logic never;
|
||||
|
||||
integer n = 0;
|
||||
|
||||
initial begin
|
||||
fork
|
||||
#10;
|
||||
#10;
|
||||
join_none
|
||||
disable fork;
|
||||
fork
|
||||
#10 if (n != 0) $stop; else n = 1;
|
||||
#15 if (n != 1) $stop; else n = 2;
|
||||
join_none
|
||||
wait fork;
|
||||
if (n != 2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue