mirror of
https://github.com/verilator/verilator.git
synced 2025-01-15 02:54:03 +00:00
parent
f9ecbdc70b
commit
31abe537a0
@ -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
|
||||
|
16
test_regress/t/t_order_dpi_export_8.cpp
Normal file
16
test_regress/t/t_order_dpi_export_8.cpp
Normal 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); }
|
22
test_regress/t/t_order_dpi_export_8.pl
Executable file
22
test_regress/t/t_order_dpi_export_8.pl
Executable 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;
|
48
test_regress/t/t_order_dpi_export_8.v
Normal file
48
test_regress/t/t_order_dpi_export_8.v
Normal 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
|
Loading…
Reference in New Issue
Block a user