mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add --fno-slice
to disable array assignment slicing (#5644).
This commit is contained in:
parent
e0ad430cd9
commit
7a8f71e7d8
3
Changes
3
Changes
@ -24,6 +24,8 @@ Verilator 5.031 devel
|
|||||||
* Add `--no-std-package` as subset-alias of `--no-std` (#5607).
|
* Add `--no-std-package` as subset-alias of `--no-std` (#5607).
|
||||||
* Add `lint_off --contents` in configuration files (#5606).
|
* Add `lint_off --contents` in configuration files (#5606).
|
||||||
* Add `--waiver-multiline` for context-sensitive `--waiver-output` (#5608).
|
* Add `--waiver-multiline` for context-sensitive `--waiver-output` (#5608).
|
||||||
|
* Add `--fno-inline-funcs` to disable function inlining.
|
||||||
|
* Add `--fno-slice` to disable array assignment slicing (#5644).
|
||||||
* Add error on illegal enum base type (#3010). [Iztok Jeras]
|
* Add error on illegal enum base type (#3010). [Iztok Jeras]
|
||||||
* Add error on `wait` with missing `.triggered` (#4457).
|
* Add error on `wait` with missing `.triggered` (#4457).
|
||||||
* Add error when improperly storing to parameter (#5147). [Gökçe Aydos]
|
* Add error when improperly storing to parameter (#5147). [Gökçe Aydos]
|
||||||
@ -31,7 +33,6 @@ Verilator 5.031 devel
|
|||||||
* Add coverage point hierarchy to coverage reports (#5575) (#5576). [Andrew Nolte]
|
* Add coverage point hierarchy to coverage reports (#5575) (#5576). [Andrew Nolte]
|
||||||
* Add warning on global constraints (#5625). [Ryszard Rozak, Antmicro Ltd.]
|
* Add warning on global constraints (#5625). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
* Add error on `solve before` or soft constraints of `randc` variable.
|
* Add error on `solve before` or soft constraints of `randc` variable.
|
||||||
* Add `--fno-inline-funcs` to disable function inlining.
|
|
||||||
* Improve concatenation performance (#5598) (#5599) (#5602). [Geza Lore]
|
* Improve concatenation performance (#5598) (#5599) (#5602). [Geza Lore]
|
||||||
* Fix dotted reference in delay value (#2410).
|
* Fix dotted reference in delay value (#2410).
|
||||||
* Fix `function fork...join_none` regression with unknown type (#4449).
|
* Fix `function fork...join_none` regression with unknown type (#4449).
|
||||||
|
@ -617,6 +617,8 @@ Summary:
|
|||||||
|
|
||||||
.. option:: -fno-reorder
|
.. option:: -fno-reorder
|
||||||
|
|
||||||
|
.. option:: -fno-slice
|
||||||
|
|
||||||
.. option:: -fno-split
|
.. option:: -fno-split
|
||||||
|
|
||||||
.. option:: -fno-subst
|
.. option:: -fno-subst
|
||||||
|
@ -1332,6 +1332,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||||||
DECL_OPTION("-fmerge-const-pool", FOnOff, &m_fMergeConstPool);
|
DECL_OPTION("-fmerge-const-pool", FOnOff, &m_fMergeConstPool);
|
||||||
DECL_OPTION("-freloop", FOnOff, &m_fReloop);
|
DECL_OPTION("-freloop", FOnOff, &m_fReloop);
|
||||||
DECL_OPTION("-freorder", FOnOff, &m_fReorder);
|
DECL_OPTION("-freorder", FOnOff, &m_fReorder);
|
||||||
|
DECL_OPTION("-fslice", FOnOff, &m_fSlice);
|
||||||
DECL_OPTION("-fsplit", FOnOff, &m_fSplit);
|
DECL_OPTION("-fsplit", FOnOff, &m_fSplit);
|
||||||
DECL_OPTION("-fsubst", FOnOff, &m_fSubst);
|
DECL_OPTION("-fsubst", FOnOff, &m_fSubst);
|
||||||
DECL_OPTION("-fsubst-const", FOnOff, &m_fSubstConst);
|
DECL_OPTION("-fsubst-const", FOnOff, &m_fSubstConst);
|
||||||
|
@ -399,6 +399,7 @@ private:
|
|||||||
bool m_fMergeConstPool = true; // main switch: -fno-merge-const-pool
|
bool m_fMergeConstPool = true; // main switch: -fno-merge-const-pool
|
||||||
bool m_fReloop; // main switch: -fno-reloop: reform loops
|
bool m_fReloop; // main switch: -fno-reloop: reform loops
|
||||||
bool m_fReorder; // main switch: -fno-reorder: reorder assignments in blocks
|
bool m_fReorder; // main switch: -fno-reorder: reorder assignments in blocks
|
||||||
|
bool m_fSlice = true; // main switch: -fno-slice: array assignment slicing
|
||||||
bool m_fSplit; // main switch: -fno-split: always assignment splitting
|
bool m_fSplit; // main switch: -fno-split: always assignment splitting
|
||||||
bool m_fSubst; // main switch: -fno-subst: substitute expression temp values
|
bool m_fSubst; // main switch: -fno-subst: substitute expression temp values
|
||||||
bool m_fSubstConst; // main switch: -fno-subst-const: final constant substitution
|
bool m_fSubstConst; // main switch: -fno-subst-const: final constant substitution
|
||||||
@ -696,6 +697,7 @@ public:
|
|||||||
bool fMergeConstPool() const { return m_fMergeConstPool; }
|
bool fMergeConstPool() const { return m_fMergeConstPool; }
|
||||||
bool fReloop() const { return m_fReloop; }
|
bool fReloop() const { return m_fReloop; }
|
||||||
bool fReorder() const { return m_fReorder; }
|
bool fReorder() const { return m_fReorder; }
|
||||||
|
bool fSlice() const { return m_fSlice; }
|
||||||
bool fSplit() const { return m_fSplit; }
|
bool fSplit() const { return m_fSplit; }
|
||||||
bool fSubst() const { return m_fSubst; }
|
bool fSubst() const { return m_fSubst; }
|
||||||
bool fSubstConst() const { return m_fSubstConst; }
|
bool fSubstConst() const { return m_fSubstConst; }
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
#include "V3Slice.h"
|
#include "V3Slice.h"
|
||||||
|
|
||||||
|
#include "V3Stats.h"
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
@ -54,6 +56,9 @@ class SliceVisitor final : public VNVisitor {
|
|||||||
// AstInitItem::user2() -> Corresponding first elemIdx
|
// AstInitItem::user2() -> Corresponding first elemIdx
|
||||||
const VNUser2InUse m_inuser2;
|
const VNUser2InUse m_inuser2;
|
||||||
|
|
||||||
|
// STATE - across all visitors
|
||||||
|
VDouble0 m_statAssigns; // Statistic tracking
|
||||||
|
|
||||||
// STATE - for current visit position (use VL_RESTORER)
|
// STATE - for current visit position (use VL_RESTORER)
|
||||||
AstNode* m_assignp = nullptr; // Assignment we are under
|
AstNode* m_assignp = nullptr; // Assignment we are under
|
||||||
bool m_assignError = false; // True if the current assign already has an error
|
bool m_assignError = false; // True if the current assign already has an error
|
||||||
@ -218,6 +223,46 @@ class SliceVisitor final : public VNVisitor {
|
|||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool assignOptimize(AstNodeAssign* nodep) {
|
||||||
|
// Return true if did optimization
|
||||||
|
AstNodeDType* const dtp = nodep->lhsp()->dtypep()->skipRefp();
|
||||||
|
AstNode* stp = nodep->rhsp();
|
||||||
|
const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType);
|
||||||
|
if (!arrayp) return false;
|
||||||
|
if (VN_IS(stp, CvtPackedToArray)) return false;
|
||||||
|
|
||||||
|
// Any isSc variables must be expanded regardless of --fno-slice
|
||||||
|
const bool hasSc
|
||||||
|
= nodep->exists([&](const AstVarRef* refp) -> bool { return refp->varp()->isSc(); });
|
||||||
|
if (!hasSc && !v3Global.opt.fSlice()) {
|
||||||
|
m_okInitArray = true; // VL_RESTORER in visit(AstNodeAssign)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINFO(4, "Slice optimizing " << nodep << endl);
|
||||||
|
++m_statAssigns;
|
||||||
|
|
||||||
|
// Left and right could have different ascending/descending range,
|
||||||
|
// but #elements is common and all variables are realigned to start at zero
|
||||||
|
// Assign of an ascending range slice to a descending range one must reverse
|
||||||
|
// the elements
|
||||||
|
AstNodeAssign* newlistp = nullptr;
|
||||||
|
const int elements = arrayp->rangep()->elementsConst();
|
||||||
|
for (int elemIdx = 0; elemIdx < elements; ++elemIdx) {
|
||||||
|
AstNodeAssign* const newp
|
||||||
|
= nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx),
|
||||||
|
cloneAndSel(nodep->rhsp(), elements, elemIdx));
|
||||||
|
if (debug() >= 9) newp->dumpTree("- new: ");
|
||||||
|
newlistp = AstNode::addNext(newlistp, newp);
|
||||||
|
}
|
||||||
|
if (debug() >= 9) nodep->dumpTree("- Deslice-Dn: ");
|
||||||
|
nodep->replaceWith(newlistp);
|
||||||
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
|
// Normal edit iterator will now iterate on all of the expansion assignments
|
||||||
|
// This will potentially call this function again to resolve next level of slicing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void visit(AstNodeAssign* nodep) override {
|
void visit(AstNodeAssign* nodep) override {
|
||||||
// Called recursively on newly created assignments
|
// Called recursively on newly created assignments
|
||||||
if (nodep->user1SetOnce()) return; // Process once
|
if (nodep->user1SetOnce()) return; // Process once
|
||||||
@ -225,34 +270,10 @@ class SliceVisitor final : public VNVisitor {
|
|||||||
if (debug() >= 9) nodep->dumpTree("- Deslice-In: ");
|
if (debug() >= 9) nodep->dumpTree("- Deslice-In: ");
|
||||||
VL_RESTORER(m_assignError);
|
VL_RESTORER(m_assignError);
|
||||||
VL_RESTORER(m_assignp);
|
VL_RESTORER(m_assignp);
|
||||||
|
VL_RESTORER(m_okInitArray); // Set in assignOptimize
|
||||||
m_assignError = false;
|
m_assignError = false;
|
||||||
m_assignp = nodep;
|
m_assignp = nodep;
|
||||||
AstNodeDType* const dtp = nodep->lhsp()->dtypep()->skipRefp();
|
if (assignOptimize(nodep)) return;
|
||||||
AstNode* stp = nodep->rhsp();
|
|
||||||
if (const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType)) {
|
|
||||||
if (!VN_IS(stp, CvtPackedToArray)) {
|
|
||||||
// Left and right could have different ascending/descending range,
|
|
||||||
// but #elements is common and all variables are realigned to start at zero
|
|
||||||
// Assign of an ascending range slice to a descending range one must reverse
|
|
||||||
// the elements
|
|
||||||
AstNodeAssign* newlistp = nullptr;
|
|
||||||
const int elements = arrayp->rangep()->elementsConst();
|
|
||||||
for (int elemIdx = 0; elemIdx < elements; ++elemIdx) {
|
|
||||||
AstNodeAssign* const newp
|
|
||||||
= nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx),
|
|
||||||
cloneAndSel(nodep->rhsp(), elements, elemIdx));
|
|
||||||
if (debug() >= 9) newp->dumpTree("- new: ");
|
|
||||||
newlistp = AstNode::addNext(newlistp, newp);
|
|
||||||
}
|
|
||||||
if (debug() >= 9) nodep->dumpTree("- Deslice-Dn: ");
|
|
||||||
nodep->replaceWith(newlistp);
|
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
|
||||||
// Normal edit iterator will now iterate on all of the expansion assignments
|
|
||||||
// This will potentially call this function again to resolve next level of
|
|
||||||
// slicing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +358,9 @@ class SliceVisitor final : public VNVisitor {
|
|||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit SliceVisitor(AstNetlist* nodep) { iterate(nodep); }
|
explicit SliceVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||||
~SliceVisitor() override = default;
|
~SliceVisitor() override {
|
||||||
|
V3Stats::addStat("Optimizations, Slice array assignments", m_statAssigns);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
18
test_regress/t/t_opt_slice.py
Executable file
18
test_regress/t/t_opt_slice.py
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=['--sc', '--stats'])
|
||||||
|
|
||||||
|
test.file_grep(test.stats, r'Optimizations, Slice array assignments\s+(\d+)', 3)
|
||||||
|
|
||||||
|
test.passes()
|
23
test_regress/t/t_opt_slice.v
Normal file
23
test_regress/t/t_opt_slice.v
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2024 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
o1a2,
|
||||||
|
// Inputs
|
||||||
|
i1a2
|
||||||
|
);
|
||||||
|
|
||||||
|
input i1a2 [1:0];
|
||||||
|
output logic o1a2 [1:0];
|
||||||
|
|
||||||
|
always o1a2 = i1a2;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
19
test_regress/t/t_opt_slice_no.py
Executable file
19
test_regress/t/t_opt_slice_no.py
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
test.top_filename = 't/t_opt_slice.v'
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=['--sc', '--stats', '-fno-slice'])
|
||||||
|
|
||||||
|
test.file_grep(test.stats, r'Optimizations, Slice array assignments\s+(\d+)', 2)
|
||||||
|
|
||||||
|
test.passes()
|
Loading…
Reference in New Issue
Block a user