Fix clearing trigger of events with no sentrees (#5426)
Signed-off-by: Arkadiusz Kozdra <akozdra@antmicro.com>
This commit is contained in:
parent
088862d449
commit
d3fcec3e84
|
|
@ -720,9 +720,18 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
void visit(AstFireEvent* nodep) override {
|
void visit(AstFireEvent* nodep) override {
|
||||||
UASSERT_OBJ(v3Global.hasEvents(), nodep, "Inconsistent");
|
UASSERT_OBJ(v3Global.hasEvents(), nodep, "Inconsistent");
|
||||||
FileLine* const flp = nodep->fileline();
|
FileLine* const flp = nodep->fileline();
|
||||||
|
|
||||||
|
AstNodeExpr* const eventp = nodep->operandp()->unlinkFrBack();
|
||||||
|
|
||||||
|
// Enqueue for clearing 'triggered' state on next eval
|
||||||
|
AstTextBlock* const blockp = new AstTextBlock{flp};
|
||||||
|
blockp->addText(flp, "vlSymsp->fireEvent(", true);
|
||||||
|
blockp->addNodesp(eventp);
|
||||||
|
blockp->addText(flp, ");\n", true);
|
||||||
|
|
||||||
|
AstNode* newp = new AstCStmt{flp, blockp};
|
||||||
if (nodep->isDelayed()) {
|
if (nodep->isDelayed()) {
|
||||||
AstVarRef* const vrefp = VN_AS(nodep->operandp(), VarRef);
|
AstVarRef* const vrefp = VN_AS(eventp, VarRef);
|
||||||
vrefp->unlinkFrBack();
|
|
||||||
const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName();
|
const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName();
|
||||||
AstVarScope* const dlyvscp = createNewVarScope(vrefp->varScopep(), newvarname, 1);
|
AstVarScope* const dlyvscp = createNewVarScope(vrefp->varScopep(), newvarname, 1);
|
||||||
|
|
||||||
|
|
@ -736,24 +745,17 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
{
|
{
|
||||||
AstIf* const ifp = new AstIf{flp, dlyRef(VAccess::READ)};
|
AstIf* const ifp = new AstIf{flp, dlyRef(VAccess::READ)};
|
||||||
postp->addStmtsp(ifp);
|
postp->addStmtsp(ifp);
|
||||||
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "fire"};
|
ifp->addThensp(newp);
|
||||||
callp->dtypeSetVoid();
|
|
||||||
ifp->addThensp(callp->makeStmt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AstActive* const activep = createActiveLike(flp, m_activep);
|
AstActive* const activep = createActiveLike(flp, m_activep);
|
||||||
activep->addStmtsp(prep);
|
activep->addStmtsp(prep);
|
||||||
activep->addStmtsp(postp);
|
activep->addStmtsp(postp);
|
||||||
|
|
||||||
AstAssign* const assignp = new AstAssign{flp, dlyRef(VAccess::WRITE),
|
newp = new AstAssign{flp, dlyRef(VAccess::WRITE),
|
||||||
new AstConst{flp, AstConst::BitTrue{}}};
|
new AstConst{flp, AstConst::BitTrue{}}};
|
||||||
nodep->replaceWith(assignp);
|
|
||||||
} else {
|
|
||||||
AstCMethodHard* const callp
|
|
||||||
= new AstCMethodHard{flp, nodep->operandp()->unlinkFrBack(), "fire"};
|
|
||||||
callp->dtypeSetVoid();
|
|
||||||
nodep->replaceWith(callp->makeStmt());
|
|
||||||
}
|
}
|
||||||
|
nodep->replaceWith(newp);
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -550,22 +550,19 @@ void EmitCSyms::emitSymHdr() {
|
||||||
|
|
||||||
if (v3Global.hasEvents()) {
|
if (v3Global.hasEvents()) {
|
||||||
if (v3Global.assignsEvents()) {
|
if (v3Global.assignsEvents()) {
|
||||||
puts("void enqueueTriggeredEventForClearing(VlAssignableEvent& event) {\n");
|
puts("void fireEvent(VlAssignableEvent& event) {\n");
|
||||||
} else {
|
} else {
|
||||||
puts("void enqueueTriggeredEventForClearing(VlEvent& event) {\n");
|
puts("void fireEvent(VlEvent& event) {\n");
|
||||||
}
|
}
|
||||||
puts("#ifdef VL_DEBUG\n");
|
puts("if (VL_LIKELY(!event.isTriggered())) {\n");
|
||||||
puts("if (VL_UNLIKELY(!event.isTriggered())) {\n");
|
|
||||||
puts("VL_FATAL_MT(__FILE__, __LINE__, __FILE__, \"event passed to "
|
|
||||||
"'enqueueTriggeredEventForClearing' was not triggered\");\n");
|
|
||||||
puts("}\n");
|
|
||||||
puts("#endif\n");
|
|
||||||
if (v3Global.assignsEvents()) {
|
if (v3Global.assignsEvents()) {
|
||||||
puts("__Vm_triggeredEvents.push_back(event);\n");
|
puts("__Vm_triggeredEvents.push_back(event);\n");
|
||||||
} else {
|
} else {
|
||||||
puts("__Vm_triggeredEvents.push_back(&event);\n");
|
puts("__Vm_triggeredEvents.push_back(&event);\n");
|
||||||
}
|
}
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
|
puts("event.fire();\n");
|
||||||
|
puts("}\n");
|
||||||
puts("void clearTriggeredEvents() {\n");
|
puts("void clearTriggeredEvents() {\n");
|
||||||
if (v3Global.assignsEvents()) {
|
if (v3Global.assignsEvents()) {
|
||||||
puts("for (auto& event : __Vm_triggeredEvents) event.clearTriggered();\n");
|
puts("for (auto& event : __Vm_triggeredEvents) event.clearTriggered();\n");
|
||||||
|
|
|
||||||
|
|
@ -192,14 +192,6 @@ class SenExprBuilder final {
|
||||||
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
|
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
|
||||||
clearp->dtypeSetVoid();
|
clearp->dtypeSetVoid();
|
||||||
ifp->addThensp(clearp->makeStmt());
|
ifp->addThensp(clearp->makeStmt());
|
||||||
|
|
||||||
// Enqueue for clearing 'triggered' state on next eval
|
|
||||||
AstTextBlock* const blockp = new AstTextBlock{flp};
|
|
||||||
ifp->addThensp(blockp);
|
|
||||||
const auto add = [&](const string& text) { blockp->addText(flp, text, true); };
|
|
||||||
add("vlSymsp->enqueueTriggeredEventForClearing(");
|
|
||||||
blockp->addNodesp(currp());
|
|
||||||
add(");\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'fired' state
|
// Get 'fired' state
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ module t(/*AUTOARG*/
|
||||||
|
|
||||||
event e1;
|
event e1;
|
||||||
event e2;
|
event e2;
|
||||||
|
event e3;
|
||||||
`ifndef IVERILOG
|
`ifndef IVERILOG
|
||||||
event ev [3:0];
|
event ev [3:0];
|
||||||
`endif
|
`endif
|
||||||
|
|
@ -50,16 +51,21 @@ module t(/*AUTOARG*/
|
||||||
if (last_event != 0) $stop;
|
if (last_event != 0) $stop;
|
||||||
-> e1;
|
-> e1;
|
||||||
if (!e1.triggered) $stop;
|
if (!e1.triggered) $stop;
|
||||||
|
if (e3.triggered) $stop;
|
||||||
|
-> e3;
|
||||||
|
if (!e3.triggered) $stop;
|
||||||
end
|
end
|
||||||
11: begin
|
11: begin
|
||||||
if (last_event != 32'b10) $stop;
|
if (last_event != 32'b10) $stop;
|
||||||
last_event = 0;
|
last_event = 0;
|
||||||
|
if (e3.triggered) $stop;
|
||||||
end
|
end
|
||||||
//
|
//
|
||||||
13: begin
|
13: begin
|
||||||
if (last_event != 0) $stop;
|
if (last_event != 0) $stop;
|
||||||
->> e2;
|
->> e2;
|
||||||
if (e2.triggered) $stop;
|
if (e2.triggered) $stop;
|
||||||
|
if (e3.triggered) $stop;
|
||||||
end
|
end
|
||||||
14: begin
|
14: begin
|
||||||
if (last_event != 32'b100) $stop;
|
if (last_event != 32'b100) $stop;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue