mirror of
https://github.com/verilator/verilator.git
synced 2025-04-05 04:02:37 +00:00
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 {
|
||||
UASSERT_OBJ(v3Global.hasEvents(), nodep, "Inconsistent");
|
||||
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()) {
|
||||
AstVarRef* const vrefp = VN_AS(nodep->operandp(), VarRef);
|
||||
vrefp->unlinkFrBack();
|
||||
AstVarRef* const vrefp = VN_AS(eventp, VarRef);
|
||||
const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName();
|
||||
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)};
|
||||
postp->addStmtsp(ifp);
|
||||
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "fire"};
|
||||
callp->dtypeSetVoid();
|
||||
ifp->addThensp(callp->makeStmt());
|
||||
ifp->addThensp(newp);
|
||||
}
|
||||
|
||||
AstActive* const activep = createActiveLike(flp, m_activep);
|
||||
activep->addStmtsp(prep);
|
||||
activep->addStmtsp(postp);
|
||||
|
||||
AstAssign* const assignp = new AstAssign{flp, dlyRef(VAccess::WRITE),
|
||||
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());
|
||||
newp = new AstAssign{flp, dlyRef(VAccess::WRITE),
|
||||
new AstConst{flp, AstConst::BitTrue{}}};
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
|
||||
|
@ -550,22 +550,19 @@ void EmitCSyms::emitSymHdr() {
|
||||
|
||||
if (v3Global.hasEvents()) {
|
||||
if (v3Global.assignsEvents()) {
|
||||
puts("void enqueueTriggeredEventForClearing(VlAssignableEvent& event) {\n");
|
||||
puts("void fireEvent(VlAssignableEvent& event) {\n");
|
||||
} else {
|
||||
puts("void enqueueTriggeredEventForClearing(VlEvent& event) {\n");
|
||||
puts("void fireEvent(VlEvent& event) {\n");
|
||||
}
|
||||
puts("#ifdef VL_DEBUG\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");
|
||||
puts("if (VL_LIKELY(!event.isTriggered())) {\n");
|
||||
if (v3Global.assignsEvents()) {
|
||||
puts("__Vm_triggeredEvents.push_back(event);\n");
|
||||
} else {
|
||||
puts("__Vm_triggeredEvents.push_back(&event);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
puts("event.fire();\n");
|
||||
puts("}\n");
|
||||
puts("void clearTriggeredEvents() {\n");
|
||||
if (v3Global.assignsEvents()) {
|
||||
puts("for (auto& event : __Vm_triggeredEvents) event.clearTriggered();\n");
|
||||
|
@ -192,14 +192,6 @@ class SenExprBuilder final {
|
||||
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
|
||||
clearp->dtypeSetVoid();
|
||||
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
|
||||
|
@ -18,6 +18,7 @@ module t(/*AUTOARG*/
|
||||
|
||||
event e1;
|
||||
event e2;
|
||||
event e3;
|
||||
`ifndef IVERILOG
|
||||
event ev [3:0];
|
||||
`endif
|
||||
@ -50,16 +51,21 @@ module t(/*AUTOARG*/
|
||||
if (last_event != 0) $stop;
|
||||
-> e1;
|
||||
if (!e1.triggered) $stop;
|
||||
if (e3.triggered) $stop;
|
||||
-> e3;
|
||||
if (!e3.triggered) $stop;
|
||||
end
|
||||
11: begin
|
||||
if (last_event != 32'b10) $stop;
|
||||
last_event = 0;
|
||||
if (e3.triggered) $stop;
|
||||
end
|
||||
//
|
||||
13: begin
|
||||
if (last_event != 0) $stop;
|
||||
->> e2;
|
||||
if (e2.triggered) $stop;
|
||||
if (e3.triggered) $stop;
|
||||
end
|
||||
14: begin
|
||||
if (last_event != 32'b100) $stop;
|
||||
|
Loading…
Reference in New Issue
Block a user