Fix DPI export trigger sensitivity in 'nba'

Fixes #3508
This commit is contained in:
Geza Lore 2022-07-21 17:34:12 +01:00
parent f9ecbdc70b
commit 31abe537a0
4 changed files with 112 additions and 22 deletions

View File

@ -416,21 +416,6 @@ struct TriggerKit {
VL_UNCOPYABLE(TriggerKit);
// Create an AstSenTree that is sensitive to the given trigger index. Must not exist yet!
AstSenTree* createTriggerSenTree(AstNetlist* netlistp, uint32_t index) const {
AstTopScope* const topScopep = netlistp->topScopep();
FileLine* const flp = topScopep->fileline();
AstVarRef* const vrefp = new AstVarRef{flp, m_vscp, VAccess::READ};
AstCMethodHard* const callp
= new AstCMethodHard{flp, vrefp, "at", new AstConst{flp, index}};
callp->dtypeSetBit();
callp->pure(true);
AstSenItem* const senItemp = new AstSenItem{flp, VEdgeType::ET_TRUE, callp};
AstSenTree* const resultp = new AstSenTree{flp, senItemp};
topScopep->addSenTreep(resultp);
return resultp;
}
// Utility that assigns the given index trigger to fire when the given variable is zero
void addFirstIterationTriggerAssignment(AstVarScope* counterp, uint32_t index) const {
FileLine* const flp = counterp->fileline();
@ -459,6 +444,20 @@ struct TriggerKit {
}
};
// Create an AstSenTree that is sensitive to the given trigger index. Must not exist yet!
AstSenTree* createTriggerSenTree(AstNetlist* netlistp, AstVarScope* const vscp, uint32_t index) {
AstTopScope* const topScopep = netlistp->topScopep();
FileLine* const flp = topScopep->fileline();
AstVarRef* const vrefp = new AstVarRef{flp, vscp, VAccess::READ};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "at", new AstConst{flp, index}};
callp->dtypeSetBit();
callp->pure(true);
AstSenItem* const senItemp = new AstSenItem{flp, VEdgeType::ET_TRUE, callp};
AstSenTree* const resultp = new AstSenTree{flp, senItemp};
topScopep->addSenTreep(resultp);
return resultp;
}
//============================================================================
// Utility for extra trigger allocation
@ -727,7 +726,8 @@ void createSettle(AstNetlist* netlistp, SenExprBuilder& senExprBulider,
invertAndMergeSenTreeMap(trigToSen, trig.m_map);
// First trigger is for pure combinational triggers (first iteration)
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
AstSenTree* const inputChanged
= createTriggerSenTree(netlistp, trig.m_vscp, firstIterationTrigger);
// Create and the body function
AstCFunc* const stlFuncp = V3Order::order(
@ -800,11 +800,12 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, SenExprBuilder& senExprBuilde
invertAndMergeSenTreeMap(trigToSen, trig.m_map);
// The trigger top level inputs (first iteration)
AstSenTree* const inputChanged = trig.createTriggerSenTree(netlistp, firstIterationTrigger);
AstSenTree* const inputChanged
= createTriggerSenTree(netlistp, trig.m_vscp, firstIterationTrigger);
// The DPI Export trigger
AstSenTree* const dpiExportTriggered
= trig.createTriggerSenTree(netlistp, dpiExportTriggerIndex);
= createTriggerSenTree(netlistp, trig.m_vscp, dpiExportTriggerIndex);
// Create and Order the body function
AstCFunc* const icoFuncp
@ -1077,13 +1078,13 @@ void schedule(AstNetlist* netlistp) {
invertAndMergeSenTreeMap(trigToSenAct, actTrigMap);
// The DPI Export trigger AstSenTree
AstSenTree* const dpiExportTriggered
= actTrig.createTriggerSenTree(netlistp, dpiExportTriggerIndex);
AstSenTree* const dpiExportTriggeredAct
= createTriggerSenTree(netlistp, actTrig.m_vscp, dpiExportTriggerIndex);
AstCFunc* const actFuncp = V3Order::order(
netlistp, {&logicRegions.m_pre, &logicRegions.m_act, &logicReplicas.m_act}, trigToSenAct,
"act", false, false, [=](const AstVarScope* vscp, std::vector<AstSenTree*>& out) {
if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggered);
if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggeredAct);
});
splitCheck(actFuncp);
if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-act");
@ -1098,10 +1099,13 @@ void schedule(AstNetlist* netlistp) {
std::unordered_map<const AstSenItem*, const AstSenTree*> trigToSenNba;
invertAndMergeSenTreeMap(trigToSenNba, nbaTrigMap);
AstSenTree* const dpiExportTriggeredNba
= createTriggerSenTree(netlistp, nbaTrigVscp, dpiExportTriggerIndex);
AstCFunc* const nbaFuncp = V3Order::order(
netlistp, {&logicRegions.m_nba, &logicReplicas.m_nba}, trigToSenNba, "nba",
v3Global.opt.mtasks(), false, [=](const AstVarScope* vscp, std::vector<AstSenTree*>& out) {
if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggered);
if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggeredNba);
});
splitCheck(nbaFuncp);
netlistp->evalNbap(nbaFuncp); // Remember for V3LifePost

View File

@ -0,0 +1,16 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2022 by Geza Lore. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
#include <svdpi.h>
#include <Vt_order_dpi_export_8__Dpi.h>
void call_set_x(svBit val) { set_x(val); }

View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt_all => 1);
compile(
verilator_flags2 => ["--exe", "$Self->{t_dir}/$Self->{name}.cpp"],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,48 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2022 by Geza Lore. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
module testbench(
/*AUTOARG*/
// Inputs
clk
);
input clk; // Top level input clock
bit x = 0;
wire y = x & $c(1);
export "DPI-C" function set_x;
function void set_x(bit val);
x = val;
endfunction;
import "DPI-C" context function void call_set_x(bit val);
bit q = 0;
always @(posedge clk) q <= ~q;
always @(edge q) call_set_x(q);
int n = 0;
always @(edge clk) begin
// This always block needs to evaluate before the NBA to even_other
// above is committed, as setting clocks via the set_other_clk uses
// blocking assignment.
$display("t=%t q=%d x=%d y=%d", $time, q, x, y);
if (y !== q) $stop;
if (n == 20) begin
$write("*-* All Finished *-*\n");
$finish;
end
n += 1;
end
endmodule