Fix splitting eval functions with --output-split-cfuncs (#2368).
This commit is contained in:
parent
4003e01283
commit
f7f3d3fd43
2
Changes
2
Changes
|
|
@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
**** Fix class constructor error on assignments to const.
|
**** Fix class constructor error on assignments to const.
|
||||||
|
|
||||||
|
**** Fix splitting eval functions with --output-split-cfuncs (#2368). [Geza Lore]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 4.040 2020-08-15
|
* Verilator 4.040 2020-08-15
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,43 @@ private:
|
||||||
m_lastSenp = nullptr;
|
m_lastSenp = nullptr;
|
||||||
m_lastIfp = nullptr;
|
m_lastIfp = nullptr;
|
||||||
}
|
}
|
||||||
|
void splitCheck(AstCFunc* ofuncp) {
|
||||||
|
if (!v3Global.opt.outputSplitCFuncs() || !ofuncp->stmtsp()) return;
|
||||||
|
if (EmitCBaseCounterVisitor(ofuncp->stmtsp()).count() < v3Global.opt.outputSplitCFuncs())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int funcnum = 0;
|
||||||
|
int func_stmts = 0;
|
||||||
|
AstCFunc* funcp = nullptr;
|
||||||
|
|
||||||
|
// Unlink all statements, then add item by item to new sub-functions
|
||||||
|
AstBegin* tempp = new AstBegin{ofuncp->fileline(), "[EditWrapper]",
|
||||||
|
ofuncp->stmtsp()->unlinkFrBackWithNext()};
|
||||||
|
if (ofuncp->finalsp()) tempp->addStmtsp(ofuncp->finalsp()->unlinkFrBackWithNext());
|
||||||
|
while (tempp->stmtsp()) {
|
||||||
|
AstNode* itemp = tempp->stmtsp()->unlinkFrBack();
|
||||||
|
int stmts = EmitCBaseCounterVisitor(itemp).count();
|
||||||
|
if (!funcp || (func_stmts + stmts) > v3Global.opt.outputSplitCFuncs()) {
|
||||||
|
// Make a new function
|
||||||
|
funcp = new AstCFunc{ofuncp->fileline(), ofuncp->name() + cvtToStr(++funcnum),
|
||||||
|
m_topScopep->scopep()};
|
||||||
|
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
|
funcp->dontCombine(true);
|
||||||
|
funcp->symProlog(true);
|
||||||
|
funcp->isStatic(true);
|
||||||
|
funcp->slow(ofuncp->slow());
|
||||||
|
m_topScopep->scopep()->addActivep(funcp);
|
||||||
|
//
|
||||||
|
AstCCall* callp = new AstCCall{funcp->fileline(), funcp};
|
||||||
|
callp->argTypes("vlSymsp");
|
||||||
|
ofuncp->addStmtsp(callp);
|
||||||
|
func_stmts = 0;
|
||||||
|
}
|
||||||
|
funcp->addStmtsp(itemp);
|
||||||
|
func_stmts += stmts;
|
||||||
|
}
|
||||||
|
VL_DO_DANGLING(tempp->deleteTree(), tempp);
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstTopScope* nodep) override {
|
virtual void visit(AstTopScope* nodep) override {
|
||||||
|
|
@ -172,28 +209,29 @@ private:
|
||||||
AstNode::user1ClearTree();
|
AstNode::user1ClearTree();
|
||||||
// Make top functions
|
// Make top functions
|
||||||
{
|
{
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
|
AstCFunc* funcp = new AstCFunc{nodep->fileline(), "_eval", m_topScopep->scopep()};
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
funcp->dontCombine(true);
|
funcp->dontCombine(true);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
funcp->isStatic(true);
|
funcp->isStatic(true);
|
||||||
funcp->entryPoint(true);
|
funcp->entryPoint(true);
|
||||||
m_scopep->addActivep(funcp);
|
m_topScopep->scopep()->addActivep(funcp);
|
||||||
m_evalFuncp = funcp;
|
m_evalFuncp = funcp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
|
AstCFunc* funcp
|
||||||
|
= new AstCFunc{nodep->fileline(), "_eval_initial", m_topScopep->scopep()};
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
funcp->dontCombine(true);
|
funcp->dontCombine(true);
|
||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
funcp->isStatic(true);
|
funcp->isStatic(true);
|
||||||
funcp->entryPoint(true);
|
funcp->entryPoint(true);
|
||||||
m_scopep->addActivep(funcp);
|
m_topScopep->scopep()->addActivep(funcp);
|
||||||
m_initFuncp = funcp;
|
m_initFuncp = funcp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
|
AstCFunc* funcp = new AstCFunc{nodep->fileline(), "final", m_topScopep->scopep()};
|
||||||
funcp->skipDecl(true);
|
funcp->skipDecl(true);
|
||||||
funcp->dontCombine(true);
|
funcp->dontCombine(true);
|
||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
|
|
@ -204,22 +242,29 @@ private:
|
||||||
+ " = this->__VlSymsp;\n"));
|
+ " = this->__VlSymsp;\n"));
|
||||||
funcp->addInitsp(
|
funcp->addInitsp(
|
||||||
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
|
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
|
||||||
m_scopep->addActivep(funcp);
|
m_topScopep->scopep()->addActivep(funcp);
|
||||||
m_finalFuncp = funcp;
|
m_finalFuncp = funcp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
|
AstCFunc* funcp
|
||||||
|
= new AstCFunc{nodep->fileline(), "_eval_settle", m_topScopep->scopep()};
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
funcp->dontCombine(true);
|
funcp->dontCombine(true);
|
||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
funcp->isStatic(true);
|
funcp->isStatic(true);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
funcp->entryPoint(true);
|
funcp->entryPoint(true);
|
||||||
m_scopep->addActivep(funcp);
|
m_topScopep->scopep()->addActivep(funcp);
|
||||||
m_settleFuncp = funcp;
|
m_settleFuncp = funcp;
|
||||||
}
|
}
|
||||||
// Process the activates
|
// Process the activates
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
UINFO(4, " TOPSCOPE iter done " << nodep << endl);
|
||||||
|
// Split large functions
|
||||||
|
splitCheck(m_evalFuncp);
|
||||||
|
splitCheck(m_initFuncp);
|
||||||
|
splitCheck(m_finalFuncp);
|
||||||
|
splitCheck(m_settleFuncp);
|
||||||
// Done, clear so we can detect errors
|
// Done, clear so we can detect errors
|
||||||
UINFO(4, " TOPSCOPEDONE " << nodep << endl);
|
UINFO(4, " TOPSCOPEDONE " << nodep << endl);
|
||||||
clearLastSen();
|
clearLastSen();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/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
|
||||||
|
|
||||||
|
sub check_evals {
|
||||||
|
my $got = 0;
|
||||||
|
foreach my $file (glob("$Self->{obj_dir}/*.cpp")) {
|
||||||
|
my $fh = IO::File->new("<$file");
|
||||||
|
local $/; undef $/;
|
||||||
|
my $wholefile = <$fh>;
|
||||||
|
|
||||||
|
if ($wholefile =~ /::_eval[0-9]+/) {
|
||||||
|
++$got;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$got >= 3 or error("Too few _eval functions found: $got");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
scenarios(vlt_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
v_flags2 => ["--output-split 1 --output-split-cfuncs 1 --exe ../$Self->{main_filename}"],
|
||||||
|
# verilator_make_gmake => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
# Very slow to compile, so generally skip it
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
check_evals();
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
cnt0, cnt1,
|
||||||
|
// Inputs
|
||||||
|
clk, clk1
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
input clk1;
|
||||||
|
|
||||||
|
output int cnt0;
|
||||||
|
output int cnt1;
|
||||||
|
|
||||||
|
always @ (posedge clk) cnt0 <= cnt0 + 1;
|
||||||
|
always @ (posedge clk1) cnt1 <= cnt1 + 1;
|
||||||
|
|
||||||
|
final if (cnt0 == 0) $stop;
|
||||||
|
final if (cnt1 != 0) $stop;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
if (cnt0==99) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue