Compare commits

...

55 Commits

Author SHA1 Message Date
Ryszard Rozak 5bfa11114f
Merge b8d072faf4 into 7d43a935bd 2025-07-19 17:43:29 +03:00
Wilson Snyder 7d43a935bd Add SPECIFYIGN warning for specify constructs that were previously silently ignored. 2025-07-18 19:32:34 -04:00
Yilou Wang 9b99d9697f
Fix virtual interface member propagation (#6175) (#6184) 2025-07-18 09:07:31 -04:00
Ryszard Rozak a21ecb2ab9
Add support for randomize..with on objects of aliased types (#6195) 2025-07-18 13:04:47 +02:00
Ryszard Rozak 28808f38bb
Dump function to which AstAddrOfCFunc points (#6188) 2025-07-18 08:37:00 +02:00
Wilson Snyder 7a6775ca84 Internals: Rename memPeakUsageBytes 2025-07-17 22:16:59 -04:00
Wilson Snyder e527ff49a3 Report `--stats` final results after build phase 2025-07-17 20:41:46 -04:00
Wilson Snyder c1506deef9 Add enum base type checking per IEEE. 2025-07-17 20:20:43 -04:00
Wilson Snyder 87050670b4 Fix structure select causing 'Wide Op' error (#6191). 2025-07-17 18:17:49 -04:00
Wilson Snyder fb1373b854 Tests: Reformat. Ignore whitespace if comparing. No test functional change. 2025-07-16 21:31:40 -04:00
Wilson Snyder 7f1011e5f7 Make some CVTREAL fatal where IEEE requires it. 2025-07-16 18:07:07 -04:00
Wilson Snyder 7a32771c7e Commentary: Changes update 2025-07-16 17:26:01 -04:00
Wilson Snyder 94b043d6c9 Internals: Print versions with `make format` 2025-07-16 17:25:22 -04:00
Igor Zaworski 8c5ba3a0d7
Fix conflicting function/class name linking error (#6182) 2025-07-16 17:25:01 -04:00
Igor Zaworski 826e5b0826
Fix `--coverage-expr` null pointer dereference (#6181) 2025-07-16 12:07:34 -04:00
Artur Bieniek abd509ce53
Support delays in emitted Verilog (#6177) 2025-07-16 11:52:56 -04:00
Ryszard Rozak 1bf24c7eb4
Add support for disabling begin just under fork from outside that begin (#5432 partial) (#6183) 2025-07-16 16:04:17 +02:00
Wilson Snyder 1f0357ba93 Add NOEFFECT warning, replacing previous `foreach` error. 2025-07-16 08:18:57 -04:00
Wilson Snyder db6b17fdb4 Fix error message 2025-07-15 17:41:08 -04:00
Artur Bieniek f3e109d8c5
Support covergroup extends, etc. (#6160) 2025-07-15 09:31:08 -04:00
Wilson Snyder 371ac07c6f Fix CVTREAL not being able to be disabled in e.g. primitive terminals. 2025-07-14 20:08:44 -04:00
Wilson Snyder caf3522364 Support implicit enum declarations with packed dimensions 2025-07-14 19:50:02 -04:00
Geza Lore 03e0d49d99
Optimize DFG partial assignments (#6176)
This is mostly a refactoring, but also enables handling some more
UNOPTFLAT, when the variable is only partially assigned in the cycle.

Previously the way partial assignments to variables were handled were
through the DfgVerexVar types themselves, which kept track of all
drivers. This has been replaced by DfgVertexSplice (which always drives
a DfgVeretexVar), and all DfgVertexVar now only have a single source,
either a DfgVertexSplice, if partially assigned, or an arbitrary
DfgVertex when updated as a whole.
2025-07-14 17:09:34 -04:00
Ryszard Rozak e2e5d9eaf1
Support disabling a fork from outside that fork (#6174) 2025-07-14 06:51:58 -04:00
Wilson Snyder 2f199f20cf Add ENUMITEMWIDTH error, and apply to X-extended and ranged values. 2025-07-12 14:14:17 -04:00
Wilson Snyder cefe1845df Commentary: Changes update 2025-07-11 21:53:29 -04:00
Yilou Wang 1044398f95
Support member-level triggers for virtual interfaces (#5166) (#6148) 2025-07-11 21:04:51 -04:00
Geza Lore 77180c4020
Optimize more cycles in DFG (#6173)
Added a second algorithm to break cycles in DFG by identifying which
bits of a circular variable are actually independent of the variable,
then reuse the existing (but extended) driver tracing algorithm to
eliminate them.

This can fix up things like: `assign gray = binary ^ (gray >> 1)`
2025-07-11 14:19:09 -04:00
github action 2fc12d951e Apply 'make format' 2025-07-11 17:11:31 +00:00
Petr Nohavica 0982260d3b
Fix constructor parameters in inheritance hierarchies (#6036) (#6070) 2025-07-11 13:10:36 -04:00
Artur Bieniek 58b867c39c
Support multiple variables on RHS of a `force` assignment (#6163) 2025-07-10 21:12:44 -04:00
Igor Zaworski 4e8a8a0398
Fix param-dependent class typedef linking (#6171) 2025-07-10 21:11:09 -04:00
Artur Bieniek 4dc6a31276
Fix omitting error when assigning to an input (#6169) 2025-07-10 20:37:55 -04:00
Geza Lore ce77bac99a
Break some combinational cycles in DFG (#6168)
Added an algorithm that can break some combinational cycles in DFG, by
attempting to trace driver logic until we escape the cycle. This can
eliminate a decent portion of UNOPTFLAT warnings. E.g. due to this code:

```systemverilog
assign a[0] = .....;
assign a[1] = ~a[0];
```
2025-07-10 18:46:45 +01:00
Igor Zaworski 31c279a7b3
Support randomize() on class member selects (#6161) 2025-07-10 04:59:05 -04:00
Bartłomiej Chmiel 9ad0de1efd
Fix uninitialized thread PGO counters (#6167) 2025-07-10 04:56:14 -04:00
Wilson Snyder d89df33fcd Change control file `public_flat_*` and other signal attributes to support __ in names (#6140). 2025-07-09 20:48:00 -04:00
Martin Stadler d1462f3120
Fix cmake `-Wno` compiler flag testing (#6145) 2025-07-09 19:31:42 -04:00
Wilson Snyder 9fc7143fce Fix genvar error with `-O0` (#6165). 2025-07-09 19:11:48 -04:00
Wilson Snyder 597b973f7b Internals: Fix some style issues. No functional change. 2025-07-09 18:52:26 -04:00
Wilson Snyder a84c5d2010 Commentary: Changes update 2025-07-09 18:51:49 -04:00
Igor Zaworski dbfbc657e1
Fix class extends dotted error (#6162) 2025-07-09 17:12:11 -04:00
Ryszard Rozak 8b3a6ba542
Support disable dotted references (#6154) 2025-07-09 16:59:26 -04:00
Wilson Snyder 8ba7cec15b devel release 2025-07-08 23:22:58 -04:00
Wilson Snyder f037ac50b4 Version bump 2025-07-08 23:02:26 -04:00
Wilson Snyder 1f0e767b61 Commentary: Changes update 2025-07-08 17:37:21 -04:00
Igor Zaworski 5777ab75c7
Fix crash with --dumpi-V3LinkDot without --debug (#6159) 2025-07-08 10:28:17 -04:00
Geza Lore e494cf22a4
Add DfgPeephole patterns (#6149) 2025-07-07 16:25:29 +01:00
Ryszard Rozak b8d072faf4 Add comments
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-12 08:52:25 +02:00
Ryszard Rozak 7fd0729710 Update tests
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-12 08:52:25 +02:00
Ryszard Rozak 7c4e96362f InsertClean to AstCoverInc expr
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-12 08:52:19 +02:00
Ryszard Rozak a02117e3e0 Increment coverpoint given by value of bit
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-11 08:52:47 +02:00
Ryszard Rozak 140e1f6a0e Pass expr from AstCoverToggle to AstCOverInc
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-11 08:52:47 +02:00
Ryszard Rozak 71d0494ede Reserve 2 counters for one toggle coverage point
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-11 08:52:47 +02:00
Ryszard Rozak b9169e14ef Add isToggle field
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
2025-06-11 08:52:47 +02:00
243 changed files with 9336 additions and 3413 deletions

View File

@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.15)
cmake_policy(SET CMP0091 NEW) # Use MSVC_RUNTIME_LIBRARY to select the runtime
project(
Verilator
VERSION 5.037
VERSION 5.039
HOMEPAGE_URL https://verilator.org
LANGUAGES CXX
)

33
Changes
View File

@ -8,7 +8,36 @@ The changes in each Verilator version are described below. The
contributors that suggested or implemented a given issue are shown in []. Thanks!
Verilator 5.037 devel
Verilator 5.039 devel
==========================
**Other:**
* Add ENUMITEMWIDTH error, and apply to X-extended and ranged values.
* Add NOEFFECT warning, replacing previous `foreach` error.
* Add SPECIFYIGN warning for specify constructs that were previously silently ignored.
* Add enum base type checking per IEEE.
* Support member-level triggers for virtual interfaces (#5166) (#6148). [Yilou Wang]
* Support disabling a fork in additional contexts (#5432 partial) (#6174) (#6183). [Ryszard Rozak, Antmicro Ltd.]
* Support disable dotted references (#6154). [Ryszard Rozak, Antmicro Ltd.]
* Support randomize() on class member selects (#6161). [Igor Zaworski, Antmicro Ltd.]
* Support multiple variables on RHS of a `force` assignment (#6163). [Artur Bieniek, Antmicro Ltd.]]
* Support covergroup extends, etc., as unsupported (#6160). [Artur Bieniek, Antmicro Ltd.]
* Change control file `public_flat_*` and other signal attributes to support __ in names (#6140).
* Fix constructor parameters in inheritance hierarchies (#6036) (#6070). [Petr Nohavica]
* Fix cmake `-Wno` compiler flag testing (#6145). [Martin Stadler]
* Fix class extends dotted error (#6162). [Igor Zaworski, Antmicro Ltd.]
* Fix genvar error with `-O0` (#6165). [Max Wipfli]
* Fix uninitialized thread PGO counters (#6167). [Bartłomiej Chmiel, Antmicro Ltd.]
* Fix additional UNOPTFLAT combinational cycles automatically in DFG (#6168) (#6173) (#6176). [Geza Lore]
* Fix omitting error when assigning to an input (#6169). [Artur Bieniek, Antmicro Ltd.]]
* Fix param-dependent class typedef linking (#6171). [Igor Zaworski, Antmicro Ltd.]
* Fix `--coverage-expr` null pointer dereference (#6181). [Igor Zaworski, Antmicro Ltd.]
* Fix conflicting function/class name linking error (#6182). [Igor Zaworski, Antmicro Ltd.]
* Fix structure select causing 'Wide Op' error (#6191). [Danny Oler]
Verilator 5.038 2025-07-08
==========================
**Important:**
@ -47,6 +76,7 @@ Verilator 5.037 devel
* Optimize DFG variable elimination (#6091). [Geza Lore]
* Optimize DFG PUSH_SEL_THROUGH_CONCAT pattern (#6092). [Geza Lore]
* Optimize DFG before V3Gate (#6141). [Geza Lore]
* Optimize DFG peephole patterns (#6149). [Geza Lore]
* Optimize constification within Expand and Subst stages (#6111). [Geza Lore]
* Fix --x-initial and --x-assign random stability (#2662) (#5958) (#6018) (#6025) (#6075). [Todd Strader]
* Fix trace hierarchical-name runtime errors (#5668) (#6076). [Paul Swirhun]
@ -95,6 +125,7 @@ Verilator 5.037 devel
* Fix wide non-blocking assignment mis-optimization (#6150) (#6152) (#6155). [Todd Strader]
* Fix interface array connections with non-zero low declaration index.
* Fix developer build error on MacOS/Flex2.6.4 (#6153). [Paul Swirhun]
* Fix crash with --dumpi-V3LinkDot without --debug (#6159). [Igor Zaworski, Antmicro Ltd.]
Verilator 5.036 2025-04-27

View File

@ -470,6 +470,7 @@ CLANGFORMAT_FLAGS = -i
CLANGFORMAT_FILES = $(CHECK_CPP) $(CHECK_H) $(CHECK_YL) test_regress/t/*.c* test_regress/t/*.h
format-c clang-format:
$(CLANGFORMAT) --version
@$(CLANGFORMAT) --version | egrep 14.0 > /dev/null \
|| echo "*** You are not using clang-format-14, indents may differ from master's ***"
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
@ -538,6 +539,7 @@ YAPF = yapf3
YAPF_FLAGS = -i --parallel
format-py yapf:
$(YAPF) --version
$(YAPF) $(YAPF_FLAGS) $(PY_FILES)
GERSEMI = gersemi

View File

@ -10,7 +10,7 @@
# Then 'make maintainer-dist'
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[5.037 devel],
AC_INIT([Verilator],[5.039 devel],
[https://verilator.org],
[verilator],[https://verilator.org])

View File

@ -24,6 +24,7 @@ Anthony Donlon
Anthony Moore
Arkadiusz Kozdra
Arthur Rosa
Artur Bieniek
Aylon Chaim Porat
Bartłomiej Chmiel
Brian Li
@ -83,6 +84,7 @@ Huang Rui
Huanghuang Zhou
HungMingWu
HyungKi Jeong
Igor Zaworski
Ilya Barkov
Iru Cai
Ivan Vnučec

View File

@ -68,11 +68,16 @@ pdf:
######################################################################
html latex linkcheck spelling::
html latex linkcheck::
$(MAKE) vl-extract
$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
$(PYTHON3) bin/vl_sphinx_fix _build
spelling::
$(MAKE) vl-extract
$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
sort -o guide/spelling.txt guide/spelling.txt
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)

View File

@ -606,6 +606,10 @@ Summary:
optimizer. Alias for :vlopt:`-fno-dfg-pre-inline`,
:vlopt:`-fno-dfg-post-inline` and :vlopt:`-fno-dfg-scoped`.
.. option:: -fno-dfg-break-cycles
Rarely needed. Disable breaking combinational cycles during DFG.
.. option:: -fno-dfg-peephole
Rarely needed. Disable the DFG peephole optimizer.

View File

@ -458,7 +458,7 @@ List Of Warnings
Warns that Verilator does not support certain forms of
:code:`constraint`, :code:`constraint_mode`, or :code:`rand_mode`, and
the construct was are ignored.
the construct was ignored.
Ignoring this warning may make Verilator randomize() simulations differ
from other simulators.
@ -486,7 +486,7 @@ List Of Warnings
Warns that Verilator does not support certain forms of
:code:`covergroup`, :code:`coverpoint`, and coverage options, and the
construct was are ignored.
construct was ignored.
Disabling the :option:`UNSUPPORTED` error also disables this warning.
@ -709,6 +709,28 @@ List Of Warnings
missing."
.. option:: ENUMITEMWIDTH
An error that an enum item value is being assigned from a value which
would be truncated (similar to :option:`WIDTHTRUNC`), or from a sized
literal constant with a different bit width (similar to
:option:`WIDTHTRUNC` or :option:`WIDTHEXPAND`). IEEE requires this
error, but it may be disabled.
Faulty example:
.. code-block:: sv
:linenos:
:emphasize-lines: 2
typedef enum [3:0] {
WRONG_WIDTH = 33'h3 //<--- Warning
} enum_t;
To repair, correct the size of the item's value directly, or use a cast,
so the resulting width matches the enum's width.
.. option:: ENUMVALUE
An error that an enum data type value is being assigned from another data
@ -1286,6 +1308,21 @@ List Of Warnings
simulate correctly.
.. option:: NOEFFECT
Warns that the statement will have no effect and is roughly equivalent
to not being present. This is only issued when it is "non-obvious",
e.g. a :code:`if (0)` will not result in this warning.
Faulty example:
.. code-block:: sv
foreach (array[]) begin ... end //<--- Warning
For a fix, remove the statement.
.. option:: NOLATCH
.. TODO better example
@ -1742,6 +1779,18 @@ List Of Warnings
simulators.
.. option:: SPECIFYIGN
Warns that Verilator does not support certain constructs in
:code:`specify` blocks, nor :code:`$sdf_annotate`, and the construct was
ignored.
Disabling the :option:`UNSUPPORTED` error also disables this warning.
Ignoring this warning may make Verilator ignore lint checking on the
construct, and get different results from other simulators.
.. option:: SPLITVAR
Warns that a variable with a :option:`/*verilator&32;split_var*/`

View File

@ -247,6 +247,7 @@ Lesik
Libenzi
Licker
Liland
LinkDot
Liu
Liwei
Lockhart
@ -480,6 +481,7 @@ Wfuture
Whatson
Wildman
Wim
Wipfli
Wmisleading
Wno
Wojciech
@ -599,6 +601,7 @@ coroutines
countbits
countones
cout
covergroup
cpp
cppstyle
cpu

View File

@ -3061,7 +3061,7 @@ void VerilatedContext::statsPrintSummary() VL_MT_UNSAFE {
= vl_timescaled_double((cputime != 0.0) ? (simtimeInUnits / cputime) : 0, "%0.3f %s");
VL_PRINTF("- Verilator: %s at %s; walltime %0.3f s; speed %s/s\n", endwhy.c_str(),
simtime.c_str(), walltime, simtimePerf.c_str());
const double modelMB = VlOs::memUsageBytes() / 1024.0 / 1024.0;
const double modelMB = VlOs::memPeakUsageBytes() / 1024.0 / 1024.0;
VL_PRINTF("- Verilator: cpu %0.3f s on %u threads; alloced %0.0f MB\n", cputime,
threadsInModels(), modelMB);
}

View File

@ -218,7 +218,7 @@ class VlPgoProfiler final {
};
// Counters are stored packed, all together to reduce cache effects
std::array<uint64_t, N_Entries> m_counters; // Time spent on this record
std::array<uint64_t, N_Entries> m_counters{}; // Time spent on this record
std::vector<Record> m_records; // Record information
public:

View File

@ -175,6 +175,14 @@ package std;
`endif
endtask
static task killQueue(ref process processQueue[$]);
`ifdef VERILATOR_TIMING
while (processQueue.size() > 0) begin
processQueue.pop_back().kill();
end
`endif
endtask
// Two process references are equal if the different classes' containing
// m_process are equal. Can't yet use <=> as the base class template
// comparisons doesn't define <=> as they don't yet require --timing and C++20.

View File

@ -637,7 +637,7 @@ extern std::string getenvStr(const std::string& envvar,
extern uint16_t getcpu() VL_MT_SAFE;
/// Return memory usage in bytes, or 0 if unknown
extern uint64_t memUsageBytes() VL_MT_SAFE;
extern uint64_t memPeakUsageBytes() VL_MT_SAFE;
// Internal: Record CPU time, starting point on construction, and current delta from that
class DeltaCpuTime final {

View File

@ -102,9 +102,9 @@ uint16_t getcpu() VL_MT_SAFE {
}
//=========================================================================
// VlOs::memUsageBytes implementation
// VlOs::memPeakUsageBytes implementation
uint64_t memUsageBytes() VL_MT_SAFE {
uint64_t memPeakUsageBytes() VL_MT_SAFE {
#if defined(_WIN32) || defined(__MINGW32__)
const HANDLE process = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
@ -124,6 +124,7 @@ uint64_t memUsageBytes() VL_MT_SAFE {
&size, &resident, &share, &text, &lib, &data, &dt);
fclose(fp);
if (VL_UNCOVERABLE(7 != items)) return 0;
// Return the vm size, not the current active set size (/proc/self/status VmRSS + VmSwap)
return (text + data) * getpagesize();
#endif
}

View File

@ -227,6 +227,7 @@ set(COMMON_SOURCES
V3Descope.cpp
V3Dfg.cpp
V3DfgAstToDfg.cpp
V3DfgBreakCycles.cpp
V3DfgCache.cpp
V3DfgDecomposition.cpp
V3DfgDfgToAst.cpp

View File

@ -240,6 +240,7 @@ RAW_OBJS_PCH_ASTNOMT = \
V3Descope.o \
V3Dfg.o \
V3DfgAstToDfg.o \
V3DfgBreakCycles.o \
V3DfgCache.o \
V3DfgDecomposition.o \
V3DfgDfgToAst.o \

View File

@ -2222,6 +2222,9 @@ public:
// ACCESSORS
virtual string name() const VL_MT_STABLE { return ""; }
virtual string origName() const { return ""; }
string prettyOrigOrName() const {
return prettyName(origName().empty() ? name() : origName());
}
virtual void name(const string& name) {
this->v3fatalSrc("name() called on object without name() method");
}

View File

@ -561,6 +561,7 @@ public:
public:
ASTGEN_MEMBERS_AstAddrOfCFunc;
void dump(std::ostream& str) const override;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }

View File

@ -46,6 +46,7 @@ protected:
public:
ASTGEN_MEMBERS_AstNodeBlock;
bool maybePointedTo() const override VL_MT_SAFE { return true; }
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
string name() const override VL_MT_STABLE { return m_name; } // * = Block name
@ -1973,7 +1974,7 @@ class AstVar final : public AstNode {
bool m_isConst : 1; // Table contains constant data
bool m_isContinuously : 1; // Ever assigned continuously (for force/release)
bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier
bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic)
bool m_isStatic : 1; // Static C variable (for Verilog see instead lifetime())
bool m_isPulldown : 1; // Tri0
bool m_isPullup : 1; // Tri1
bool m_isIfaceParent : 1; // dtype is reference to interface present in this module
@ -2988,14 +2989,17 @@ class AstCoverDecl final : public AstNodeStmt {
string m_linescov;
int m_offset; // Offset column numbers to uniq-ify IFs
int m_binNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment
bool m_isToggle;
public:
AstCoverDecl(FileLine* fl, const string& page, const string& comment, const string& linescov,
int offset)
int offset, bool isToggle)
: ASTGEN_SUPER_CoverDecl(fl)
, m_page{page}
, m_text{comment}
, m_linescov{linescov}
, m_offset{offset} {}
, m_offset{offset}
, m_isToggle{isToggle} {}
ASTGEN_MEMBERS_AstCoverDecl;
const char* broken() const override {
if (m_dataDeclp
@ -3015,6 +3019,7 @@ public:
const string& linescov() const { return m_linescov; }
const string& page() const { return m_page; }
const string& hier() const { return m_hier; }
bool isToggle() const { return m_isToggle; }
void hier(const string& flag) { m_hier = flag; }
void comment(const string& flag) { m_text = flag; }
bool sameNode(const AstNode* samep) const override {
@ -3031,6 +3036,8 @@ public:
};
class AstCoverInc final : public AstNodeStmt {
// Coverage analysis point; increment coverage count
// @astgen op1 := toggleExprp : Optional[AstNodeExpr] // [After V3Clock] Expression to which
// the node corresponds. Used only in toggle coverage
//
// @astgen ptr := m_declp : AstCoverDecl // [After V3CoverageJoin] Declaration
public:
@ -3096,14 +3103,18 @@ public:
bool isCycleDelay() const { return m_isCycle; }
};
class AstDisable final : public AstNodeStmt {
string m_name; // Name of block
// @astgen op1 := targetRefp : Optional[AstNodeExpr] // Reference to link in V3LinkDot
// @astgen ptr := m_targetp : Optional[AstNode] // Task or block after V3LinkDot
public:
AstDisable(FileLine* fl, const string& name)
: ASTGEN_SUPER_Disable(fl)
, m_name{name} {}
AstDisable(FileLine* fl, AstNodeExpr* targetRefp)
: ASTGEN_SUPER_Disable(fl) {
this->targetRefp(targetRefp);
}
ASTGEN_MEMBERS_AstDisable;
string name() const override VL_MT_STABLE { return m_name; } // * = Block name
void name(const string& flag) override { m_name = flag; }
const char* broken() const override;
void dump(std::ostream& str) const override;
void targetp(AstNode* nodep) { m_targetp = nodep; }
AstNode* targetp() const { return m_targetp; }
bool isBrancher() const override {
return true; // SPECIAL: We don't process code after breaks
}

View File

@ -189,6 +189,12 @@ void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Numb
}
}
void AstAddrOfCFunc::dump(std::ostream& str) const {
this->AstNodeExpr::dump(str);
str << " -> ";
funcp()->dump(str);
}
void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
AstRange* rangep) {
// wantwidth=0 means figure it out, but if a widthmin is >=0
@ -1110,6 +1116,9 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep, bool overMembers) {
} else if (overMembers && VN_IS(nodep, MemberSel)) {
nodep = VN_AS(nodep, MemberSel)->fromp();
continue;
} else if (overMembers && VN_IS(nodep, StructSel)) {
nodep = VN_AS(nodep, StructSel)->fromp();
continue;
}
// AstNodePreSel stashes the associated variable under an ATTROF
// of VAttrType::VAR_BASE so it isn't constified
@ -2604,6 +2613,8 @@ void AstVar::dump(std::ostream& str) const {
if (isPulldown()) str << " [PULLDOWN]";
if (isUsedClock()) str << " [CLK]";
if (isSigPublic()) str << " [P]";
if (isSigUserRdPublic()) str << " [PRD]";
if (isSigUserRWPublic()) str << " [PWR]";
if (isInternal()) str << " [INTERNAL]";
if (isLatched()) str << " [LATCHED]";
if (isUsedLoopIdx()) str << " [LOOP]";
@ -3177,6 +3188,20 @@ void AstDelay::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isCycleDelay);
dumpJsonGen(str);
}
const char* AstDisable::broken() const {
BROKEN_RTN((m_targetp && targetRefp()) || ((!m_targetp && !targetRefp())));
return nullptr;
}
void AstDisable::dump(std::ostream& str) const {
this->AstNodeStmt::dump(str);
str << " -> ";
if (targetp()) {
targetp()->dump(str);
} else {
str << "UNLINKED";
}
}
const char* AstAnd::widthMismatch() const VL_MT_STABLE {
BROKEN_RTN(lhsp()->widthMin() != rhsp()->widthMin());
BROKEN_RTN(lhsp()->widthMin() != widthMin());

View File

@ -530,7 +530,11 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
}
// The parser validates we don't have "foreach (array[,,,])"
AstNode* const bodyp = nodep->stmtsp();
UASSERT_OBJ(newp, nodep, "foreach has no non-empty loop variable");
if (!newp) {
nodep->v3warn(NOEFFECT, "foreach with no loop variable has no effect");
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return nullptr;
}
if (bodyp) {
bodyPointp->replaceWith(bodyp->unlinkFrBackWithNext());
} else {

View File

@ -57,28 +57,18 @@ class ClassVisitor final : public VNVisitor {
// METHODS
bool recurseImplements(AstClass* nodep, bool setit) {
// Returns true to set useVirtualPublic().
// If there's an implements of an interface class then we have
// multiple classes that point to same object, that need same
// VlClass (the diamond problem). C++ will require we use 'virtual
// public' for VlClass. So, we need the interface class, and all
// classes above, and any below using any implements to use
// 'virtual public' via useVirtualPublic().
if (nodep->useVirtualPublic()) return true; // Short-circuit
if (nodep->isInterfaceClass()) setit = true;
void recurseImplements(AstClass* nodep) {
// In SystemVerilog, we have two inheritance chains:
// - extends of concrete clasess: mapped to non-virtual C++ inheritance
// as there is only single ancestor allowed
// - implements of concrete classes / extends of interface classes: mapped
// to virtual inheritance to allow diamond patterns with multiple ancestors
if (nodep->useVirtualPublic()) return; // Short-circuit to exit diamond cycles
if (nodep->isInterfaceClass()) { nodep->useVirtualPublic(true); }
for (const AstClassExtends* extp = nodep->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) {
if (recurseImplements(extp->classp(), setit)) setit = true;
recurseImplements(extp->classp());
}
if (setit) {
nodep->useVirtualPublic(true);
for (const AstClassExtends* extp = nodep->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) {
(void)recurseImplements(extp->classp(), true);
}
}
return setit;
}
// VISITORS
@ -89,7 +79,7 @@ class ClassVisitor final : public VNVisitor {
nodep->name(m_prefix + nodep->name());
nodep->unlinkFrBack();
v3Global.rootp()->addModulesp(nodep);
(void)recurseImplements(nodep, false);
recurseImplements(nodep);
// Make containing package
// Note origName is the same as the class origName so errors look correct
AstClassPackage* const packagep

View File

@ -251,6 +251,10 @@ class CleanVisitor final : public VNVisitor {
iterateChildren(nodep);
ensureCleanAndNext(nodep->valuep());
}
void visit(AstCoverInc* nodep) override {
iterateChildren(nodep);
if (nodep->toggleExprp()) ensureClean(nodep->toggleExprp());
}
void visit(AstTypedef* nodep) override {
// No cleaning, or would loose pointer to enum
iterateChildren(nodep);

View File

@ -100,11 +100,12 @@ class ClockVisitor final : public VNVisitor {
// if (debug()) nodep->dumpTree("- ct: ");
// COVERTOGGLE(INC, ORIG, CHANGE) ->
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
AstNode* const incp = nodep->incp()->unlinkFrBack();
AstCoverInc* const incp = nodep->incp()->unlinkFrBack();
AstNodeExpr* const origp = nodep->origp()->unlinkFrBack();
AstNodeExpr* const changeWrp = nodep->changep()->unlinkFrBack();
AstNodeExpr* const changeRdp = ConvertWriteRefsToRead::main(changeWrp->cloneTree(false));
AstNodeExpr* comparedp = nullptr;
incp->toggleExprp(origp->cloneTree(false));
// Xor will optimize better than Eq, when CoverToggle has bit selects,
// but can only use Xor with non-opaque types
if (const AstBasicDType* const bdtypep

View File

@ -276,7 +276,7 @@ public:
const VPragmaType pragma = VPragmaType::COVERAGE_BLOCK_OFF;
if (!nodep->unnamed()) {
for (const string& i : m_coverageOffBlocks) {
if (VString::wildmatch(nodep->name(), i)) {
if (VString::wildmatch(nodep->prettyOrigOrName(), i)) {
nodep->addStmtsp(new AstPragma{nodep->fileline(), pragma});
}
}
@ -724,49 +724,50 @@ void V3Control::addVarAttr(FileLine* fl, const string& module, const string& fta
void V3Control::applyCase(AstCase* nodep) {
const string& filename = nodep->fileline()->filename();
V3ControlFile* filep = V3ControlResolver::s().files().resolve(filename);
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filename);
if (filep) filep->applyCase(nodep);
}
void V3Control::applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep) {
const string& filename = nodep->fileline()->filename();
V3ControlFile* filep = V3ControlResolver::s().files().resolve(filename);
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filename);
if (filep) filep->applyBlock(nodep);
const string& modname = modulep->name();
V3ControlModule* modp = V3ControlResolver::s().modules().resolve(modname);
const string& modname = modulep->prettyOrigOrName();
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
if (modp) modp->applyBlock(nodep);
}
void V3Control::applyIgnores(FileLine* filelinep) {
const string& filename = filelinep->filename();
V3ControlFile* filep = V3ControlResolver::s().files().resolve(filename);
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filename);
if (filep) filep->applyIgnores(filelinep);
}
void V3Control::applyModule(AstNodeModule* modulep) {
const string& modname = modulep->origName();
V3ControlModule* modp = V3ControlResolver::s().modules().resolve(modname);
const string& modname = modulep->prettyOrigOrName();
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
if (modp) modp->apply(modulep);
}
void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
const string& modname = modulep->name();
V3ControlModule* modp = V3ControlResolver::s().modules().resolve(modname);
const string& modname = modulep->prettyOrigOrName();
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
if (!modp) return;
const V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->name());
const V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->prettyOrigOrName());
if (ftp) ftp->apply(ftaskp);
}
void V3Control::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) {
V3ControlVar* vp;
V3ControlModule* modp = V3ControlResolver::s().modules().resolve(modulep->name());
V3ControlModule* const modp
= V3ControlResolver::s().modules().resolve(modulep->prettyOrigOrName());
if (!modp) return;
if (ftaskp) {
V3ControlFTask* ftp = modp->ftasks().resolve(ftaskp->name());
V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->prettyOrigOrName());
if (!ftp) return;
vp = ftp->vars().resolve(varp->name());
vp = ftp->vars().resolve(varp->prettyOrigOrName());
} else {
vp = modp->vars().resolve(varp->name());
vp = modp->vars().resolve(varp->prettyOrigOrName());
}
if (vp) vp->apply(varp);
}
@ -797,7 +798,7 @@ bool V3Control::containsMTaskProfileData() {
}
bool V3Control::waive(FileLine* filelinep, V3ErrorCode code, const string& message) {
V3ControlFile* filep = V3ControlResolver::s().files().resolve(filelinep->filename());
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filelinep->filename());
if (!filep) return false;
return filep->waive(code, message);
}

View File

@ -39,17 +39,28 @@ class ExprCoverageEligibleVisitor final : public VNVisitor {
// STATE
bool m_eligible = true;
static bool elemDTypeEligible(const AstNodeDType* dtypep) {
dtypep = dtypep->skipRefp();
if (AstNodeDType* const dtp = dtypep->virtRefDTypep()) {
if (!elemDTypeEligible(dtp)) return false;
}
if (AstNodeDType* const dtp = dtypep->virtRefDType2p()) {
if (!elemDTypeEligible(dtp)) return false;
}
return !VN_IS(dtypep, ClassRefDType);
}
void visit(AstNodeVarRef* nodep) override {
AstNodeDType* dtypep = nodep->varp()->dtypep();
// Class objecs and references not supported for expression coverage
// Class objects and references not supported for expression coverage
// because the object may not persist until the point at which
// coverage data is gathered
// This could be resolved in the future by protecting against dereferrencing
// null pointers when cloning the expression for expression coverage
if (VN_CAST(dtypep, ClassRefDType)) {
m_eligible = false;
} else {
if (dtypep && elemDTypeEligible(dtypep)) {
iterateChildren(nodep);
} else {
m_eligible = false;
}
}
@ -171,7 +182,7 @@ class CoverageVisitor final : public VNVisitor {
AstCoverInc* newCoverInc(FileLine* fl, const string& hier, const string& page_prefix,
const string& comment, const string& linescov, int offset,
const string& trace_var_name) {
const string& trace_var_name, const bool isToggle) {
// We could use the basename of the filename to the page, but seems
// better for code from an include file to be listed under the
// module using it rather than the include file.
@ -180,7 +191,8 @@ class CoverageVisitor final : public VNVisitor {
// Someday the user might be allowed to specify a different page suffix
const string page = page_prefix + "/" + m_modp->prettyName();
AstCoverDecl* const declp = new AstCoverDecl{fl, page, comment, linescov, offset};
AstCoverDecl* const declp
= new AstCoverDecl{fl, page, comment, linescov, offset, isToggle};
declp->hier(hier);
m_modp->addStmtsp(declp);
UINFO(9, "new " << declp);
@ -308,7 +320,7 @@ class CoverageVisitor final : public VNVisitor {
lineTrack(nodep);
AstNode* const newp
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
0, traceNameForLine(nodep, "block"));
0, traceNameForLine(nodep, "block"), false);
insertProcStatement(nodep, newp);
}
}
@ -346,7 +358,7 @@ class CoverageVisitor final : public VNVisitor {
lineTrack(nodep);
AstNode* const newp
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
0, traceNameForLine(nodep, "block"));
0, traceNameForLine(nodep, "block"), false);
insertProcStatement(nodep, newp);
}
}
@ -398,7 +410,7 @@ class CoverageVisitor final : public VNVisitor {
AstCoverToggle* const newp = new AstCoverToggle{
varp->fileline(),
newCoverInc(varp->fileline(), "", "v_toggle",
hierPrefix + varp->name() + above.m_comment, "", 0, ""),
hierPrefix + varp->name() + above.m_comment, "", 0, "", true),
above.m_varRefp->cloneTree(false), above.m_chgRefp->cloneTree(false)};
m_modp->addStmtsp(newp);
}
@ -536,7 +548,7 @@ class CoverageVisitor final : public VNVisitor {
nodep->thenp(new AstExprStmt{thenp->fileline(),
newCoverInc(nodep->fileline(), "", "v_branch",
"cond_then", linesCov(m_state, nodep), 0,
traceNameForLine(nodep, "cond_then")),
traceNameForLine(nodep, "cond_then"), false),
thenp});
m_state = lastState;
createHandle(nodep);
@ -545,7 +557,7 @@ class CoverageVisitor final : public VNVisitor {
nodep->elsep(new AstExprStmt{elsep->fileline(),
newCoverInc(nodep->fileline(), "", "v_branch",
"cond_else", linesCov(m_state, nodep), 1,
traceNameForLine(nodep, "cond_else")),
traceNameForLine(nodep, "cond_else"), false),
elsep});
m_state = lastState;
@ -605,13 +617,13 @@ class CoverageVisitor final : public VNVisitor {
UINFO(4, " COVER-branch: " << nodep);
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_branch", "if",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "if")));
traceNameForLine(nodep, "if"), false));
// The else has a column offset of 1 to uniquify it relative to the if
// As "if" and "else" are more than one character wide, this won't overlap
// another token
nodep->addElsesp(newCoverInc(nodep->fileline(), "", "v_branch", "else",
linesCov(elseState, nodep), 1,
traceNameForLine(nodep, "else")));
traceNameForLine(nodep, "else"), false));
}
// If/else attributes to each block as non-branch coverage
else if (first_elsif || cont_elsif) {
@ -619,7 +631,7 @@ class CoverageVisitor final : public VNVisitor {
if (ifState.lineCoverageOn(nodep)) {
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "elsif")));
traceNameForLine(nodep, "elsif"), false));
}
// and we don't insert the else as the child if-else will do so
} else {
@ -628,13 +640,13 @@ class CoverageVisitor final : public VNVisitor {
UINFO(4, " COVER-half-if: " << nodep);
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "if",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "if")));
traceNameForLine(nodep, "if"), false));
}
if (elseState.lineCoverageOn(nodep)) {
UINFO(4, " COVER-half-el: " << nodep);
nodep->addElsesp(newCoverInc(nodep->fileline(), "", "v_line", "else",
linesCov(elseState, nodep), 1,
traceNameForLine(nodep, "else")));
traceNameForLine(nodep, "else"), false));
}
}
m_state = lastState;
@ -657,7 +669,7 @@ class CoverageVisitor final : public VNVisitor {
UINFO(4, " COVER: " << nodep);
nodep->addStmtsp(newCoverInc(nodep->fileline(), "", "v_line", "case",
linesCov(m_state, nodep), 0,
traceNameForLine(nodep, "case")));
traceNameForLine(nodep, "case"), false));
}
}
}
@ -672,7 +684,7 @@ class CoverageVisitor final : public VNVisitor {
lineTrack(nodep);
nodep->addCoverincsp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
linesCov(m_state, nodep), 0,
m_beginHier + "_vlCoverageUserTrace"));
m_beginHier + "_vlCoverageUserTrace", false));
}
}
void visit(AstStop* nodep) override {
@ -744,8 +756,8 @@ class CoverageVisitor final : public VNVisitor {
}
comment += ") => ";
comment += (m_objective ? '1' : '0');
AstNode* const newp
= newCoverInc(fl, "", "v_expr", comment, "", 0, traceNameForLine(nodep, name));
AstNode* const newp = newCoverInc(fl, "", "v_expr", comment, "", 0,
traceNameForLine(nodep, name), false);
UASSERT_OBJ(condp, nodep, "No terms in expression coverage branch");
AstIf* const ifp = new AstIf{fl, condp, newp, nullptr};
ifp->user2(true);
@ -858,7 +870,6 @@ class CoverageVisitor final : public VNVisitor {
!= strs[!term.m_objective].end())
impossible = true;
}
if (!redundant) expr.push_back(term);
}
if (!impossible) m_exprs.push_back(std::move(expr));

View File

@ -34,6 +34,147 @@ DfgGraph::~DfgGraph() {
forEachVertex([](DfgVertex& vtxp) { delete &vtxp; });
}
std::unique_ptr<DfgGraph> DfgGraph::clone() const {
const bool scoped = !modulep();
DfgGraph* const clonep = new DfgGraph{modulep(), name()};
// Map from original vertex to clone
std::unordered_map<const DfgVertex*, DfgVertex*> vtxp2clonep(size() * 2);
// Clone constVertices
for (const DfgConst& vtx : m_constVertices) {
DfgConst* const cp = new DfgConst{*clonep, vtx.fileline(), vtx.num()};
vtxp2clonep.emplace(&vtx, cp);
}
// Clone variable vertices
for (const DfgVertexVar& vtx : m_varVertices) {
const DfgVertexVar* const vp = vtx.as<DfgVertexVar>();
DfgVertexVar* cp = nullptr;
switch (vtx.type()) {
case VDfgType::atVarArray: {
if (scoped) {
cp = new DfgVarArray{*clonep, vp->varScopep()};
} else {
cp = new DfgVarArray{*clonep, vp->varp()};
}
vtxp2clonep.emplace(&vtx, cp);
break;
}
case VDfgType::atVarPacked: {
if (scoped) {
cp = new DfgVarPacked{*clonep, vp->varScopep()};
} else {
cp = new DfgVarPacked{*clonep, vp->varp()};
}
vtxp2clonep.emplace(&vtx, cp);
break;
}
default: {
vtx.v3fatalSrc("Unhandled variable vertex type: " + vtx.typeName());
VL_UNREACHABLE;
break;
}
}
if (vp->hasDfgRefs()) cp->setHasDfgRefs();
if (vp->hasModRefs()) cp->setHasModRefs();
if (vp->hasExtRefs()) cp->setHasExtRefs();
}
// Clone operation vertices
for (const DfgVertex& vtx : m_opVertices) {
switch (vtx.type()) {
#include "V3Dfg__gen_clone_cases.h" // From ./astgen
case VDfgType::atSel: {
DfgSel* const cp = new DfgSel{*clonep, vtx.fileline(), vtx.dtypep()};
cp->lsb(vtx.as<DfgSel>()->lsb());
vtxp2clonep.emplace(&vtx, cp);
break;
}
case VDfgType::atMux: {
DfgMux* const cp = new DfgMux{*clonep, vtx.fileline(), vtx.dtypep()};
vtxp2clonep.emplace(&vtx, cp);
break;
}
case VDfgType::atSpliceArray: {
DfgSpliceArray* const cp = new DfgSpliceArray{*clonep, vtx.fileline(), vtx.dtypep()};
vtxp2clonep.emplace(&vtx, cp);
break;
}
case VDfgType::atSplicePacked: {
DfgSplicePacked* const cp = new DfgSplicePacked{*clonep, vtx.fileline(), vtx.dtypep()};
vtxp2clonep.emplace(&vtx, cp);
break;
}
default: {
vtx.v3fatalSrc("Unhandled operation vertex type: " + vtx.typeName());
VL_UNREACHABLE;
break;
}
}
}
UASSERT(size() == clonep->size(), "Size of clone should be the same");
// Constants have no inputs
// Hook up inputs of cloned variables
for (const DfgVertexVar& vtx : m_varVertices) {
// All variable vertices are unary
if (DfgVertex* const srcp = vtx.srcp()) {
vtxp2clonep.at(&vtx)->as<DfgVertexVar>()->srcp(vtxp2clonep.at(srcp));
}
}
// Hook up inputs of cloned operation vertices
for (const DfgVertex& vtx : m_opVertices) {
if (vtx.is<DfgVertexVariadic>()) {
switch (vtx.type()) {
case VDfgType::atSpliceArray: {
const DfgSpliceArray* const vp = vtx.as<DfgSpliceArray>();
DfgSpliceArray* const cp = vtxp2clonep.at(vp)->as<DfgSpliceArray>();
vp->forEachSourceEdge([&](const DfgEdge& edge, size_t i) {
if (DfgVertex* const srcp = edge.sourcep()) {
cp->addDriver(vp->driverFileLine(i), //
vp->driverIndex(i), //
vtxp2clonep.at(srcp));
}
});
break;
}
case VDfgType::atSplicePacked: {
const DfgSplicePacked* const vp = vtx.as<DfgSplicePacked>();
DfgSplicePacked* const cp = vtxp2clonep.at(vp)->as<DfgSplicePacked>();
vp->forEachSourceEdge([&](const DfgEdge& edge, size_t i) {
if (DfgVertex* const srcp = edge.sourcep()) {
cp->addDriver(vp->driverFileLine(i), //
vp->driverLsb(i), //
vtxp2clonep.at(srcp));
}
});
break;
}
default: {
vtx.v3fatalSrc("Unhandled DfgVertexVariadic sub type: " + vtx.typeName());
VL_UNREACHABLE;
break;
}
}
} else {
DfgVertex* const cp = vtxp2clonep.at(&vtx);
const auto oSourceEdges = vtx.sourceEdges();
auto cSourceEdges = cp->sourceEdges();
UASSERT_OBJ(oSourceEdges.second == cSourceEdges.second, &vtx,
"Mismatched source count");
for (size_t i = 0; i < oSourceEdges.second; ++i) {
if (DfgVertex* const srcp = oSourceEdges.first[i].sourcep()) {
cSourceEdges.first[i].relinkSource(vtxp2clonep.at(srcp));
}
}
}
}
return std::unique_ptr<DfgGraph>{clonep};
}
void DfgGraph::addGraph(DfgGraph& other) {
m_size += other.m_size;
other.m_size = 0;
@ -188,6 +329,25 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
return;
}
if (vtx.is<DfgVertexSplice>()) {
os << toDotId(vtx);
os << " [label=\"" << vtx.typeName() << "\n";
if (const DfgSpliceArray* const sp = vtx.cast<DfgSpliceArray>()) {
const int elements = VN_AS(sp->dtypep(), UnpackArrayDType)->elementsConst();
os << "_[" << elements << "]";
} else {
os << "W" << vtx.width();
}
os << " / F" << vtx.fanout() << '"';
if (vtx.hasMultipleSinks()) {
os << ", shape=doubleoctagon";
} else {
os << ", shape=octagon";
}
os << "]\n";
return;
}
os << toDotId(vtx);
os << " [label=\"" << vtx.typeName() << "\nW" << vtx.width() << " / F" << vtx.fanout() << '"';
if (vtx.hasMultipleSinks()) {
@ -211,7 +371,7 @@ static void dumpDotVertexAndSourceEdges(std::ostream& os, const DfgVertex& vtx)
vtx.forEachSourceEdge([&](const DfgEdge& edge, size_t idx) { //
if (edge.sourcep()) {
string headLabel;
if (vtx.arity() > 1 || vtx.is<DfgVertexVar>()) headLabel = vtx.srcName(idx);
if (vtx.arity() > 1 || vtx.is<DfgVertexSplice>()) headLabel = vtx.srcName(idx);
dumpDotEdge(os, edge, headLabel);
}
});
@ -396,24 +556,34 @@ bool DfgVertex::selfEquals(const DfgVertex& that) const { return true; }
V3Hash DfgVertex::selfHash() const { return V3Hash{}; }
bool DfgVertex::equals(const DfgVertex& that, EqualsCache& cache) const {
// If same vertex, then equal
if (this == &that) return true;
// If different type, then not equal
if (this->type() != that.type()) return false;
// If different data type, then not equal
if (this->dtypep() != that.dtypep()) return false;
// If different number of inputs, then not equal
auto thisPair = this->sourceEdges();
const DfgEdge* const thisSrcEdgesp = thisPair.first;
const size_t thisArity = thisPair.second;
auto thatPair = that.sourceEdges();
const DfgEdge* const thatSrcEdgesp = thatPair.first;
const size_t thatArity = thatPair.second;
if (thisArity != thatArity) return false;
// Check vertex specifics
if (!this->selfEquals(that)) return false;
// Check sources
const auto key = (this < &that) ? EqualsCache::key_type{this, &that} //
: EqualsCache::key_type{&that, this};
// Note: the recursive invocation can cause a re-hash but that will not invalidate references
uint8_t& result = cache[key];
if (!result) {
result = 2; // Assume equals
auto thisPair = this->sourceEdges();
const DfgEdge* const thisSrcEdgesp = thisPair.first;
const size_t thisArity = thisPair.second;
auto thatPair = that.sourceEdges();
const DfgEdge* const thatSrcEdgesp = thatPair.first;
const size_t thatArity = thatPair.second;
UASSERT_OBJ(thisArity == thatArity, this, "Same type vertices must have same arity!");
for (size_t i = 0; i < thisArity; ++i) {
const DfgVertex* const thisSrcVtxp = thisSrcEdgesp[i].m_sourcep;
const DfgVertex* const thatSrcVtxp = thatSrcEdgesp[i].m_sourcep;
@ -436,7 +606,12 @@ V3Hash DfgVertex::hash() {
// variables, which we rely on.
if (!is<DfgVertexVar>()) {
hash += m_type;
hash += width(); // Currently all non-variable vertices are packed, so this is safe
if (AstUnpackArrayDType* const adtypep = VN_CAST(dtypep(), UnpackArrayDType)) {
hash += adtypep->elementsConst();
// TODO: maybe include sub-dtype, but not hugely important at the moment
} else {
hash += width();
}
const auto pair = sourceEdges();
const DfgEdge* const edgesp = pair.first;
const size_t arity = pair.second;
@ -454,19 +629,16 @@ uint32_t DfgVertex::fanout() const {
return result;
}
DfgVarPacked* DfgVertex::getResultVar() {
UASSERT_OBJ(!this->is<DfgVarArray>(), this, "Arrays are not supported by " << __FUNCTION__);
DfgVertexVar* DfgVertex::getResultVar() {
// It's easy if the vertex is already a variable ...
if (DfgVarPacked* const varp = this->cast<DfgVarPacked>()) return varp;
if (DfgVertexVar* const varp = this->cast<DfgVertexVar>()) return varp;
// Inspect existing variables fully written by this vertex, and choose one
DfgVarPacked* resp = nullptr;
// Inspect existing variables written by this vertex, and choose one
DfgVertexVar* resp = nullptr;
// cppcheck-has-bug-suppress constParameter
this->forEachSink([&resp](DfgVertex& sink) {
DfgVarPacked* const varp = sink.cast<DfgVarPacked>();
DfgVertexVar* const varp = sink.cast<DfgVertexVar>();
if (!varp) return;
if (!varp->isDrivenFullyByDfg()) return;
// Ignore SystemC variables, they cannot participate in expressions or
// be assigned rvalue expressions.
if (varp->varp()->isSc()) return;
@ -569,6 +741,42 @@ bool DfgSel::selfEquals(const DfgVertex& that) const { return lsb() == that.as<D
V3Hash DfgSel::selfHash() const { return V3Hash{lsb()}; }
// DfgSpliceArray ----------
bool DfgSpliceArray::selfEquals(const DfgVertex& that) const {
const DfgSpliceArray* const thatp = that.as<DfgSpliceArray>();
const size_t arity = this->arity();
for (size_t i = 0; i < arity; ++i) {
if (driverIndex(i) != thatp->driverIndex(i)) return false;
}
return true;
}
V3Hash DfgSpliceArray::selfHash() const {
V3Hash hash;
const size_t arity = this->arity();
for (size_t i = 0; i < arity; ++i) hash += driverIndex(i);
return hash;
}
// DfgSplicePacked ----------
bool DfgSplicePacked::selfEquals(const DfgVertex& that) const {
const DfgSplicePacked* const thatp = that.as<DfgSplicePacked>();
const size_t arity = this->arity();
for (size_t i = 0; i < arity; ++i) {
if (driverLsb(i) != thatp->driverLsb(i)) return false;
}
return true;
}
V3Hash DfgSplicePacked::selfHash() const {
V3Hash hash;
const size_t arity = this->arity();
for (size_t i = 0; i < arity; ++i) hash += driverLsb(i);
return hash;
}
// DfgVertexVar ----------
bool DfgVertexVar::selfEquals(const DfgVertex& that) const {

View File

@ -238,8 +238,7 @@ public:
// Width of result
uint32_t width() const {
// This is a hot enough function that this is an expensive check, so in debug build only.
UDEBUGONLY(UASSERT_OBJ(VN_IS(dtypep(), BasicDType), this, "non-packed has no 'width()'"););
UASSERT_OBJ(VN_IS(dtypep(), BasicDType), this, "non-packed has no 'width()'");
return dtypep()->width();
}
@ -283,7 +282,7 @@ public:
// Return a canonical variable vertex that holds the value of this vertex,
// or nullptr if no such variable exists in the graph. This is O(fanout).
DfgVarPacked* getResultVar() VL_MT_DISABLED;
DfgVertexVar* getResultVar() VL_MT_DISABLED;
// Cache type for 'scopep' below
using ScopeCache = std::unordered_map<const DfgVertex*, AstScope*>;
@ -572,7 +571,7 @@ class DfgVertexVariadic VL_NOT_FINAL : public DfgVertex {
protected:
DfgVertexVariadic(DfgGraph& dfg, VDfgType type, FileLine* flp, AstNodeDType* dtypep,
uint32_t initialCapacity = 1)
uint32_t initialCapacity)
: DfgVertex{dfg, type, flp, dtypep}
, m_srcsp{allocSources(initialCapacity)}
, m_srcCap{initialCapacity} {}
@ -706,6 +705,9 @@ public:
// 'const' variant of 'forEachVertex'. No mutation allowed.
inline void forEachVertex(std::function<void(const DfgVertex&)> f) const;
// Return an identical, independent copy of this graph. Vertex and edge order might differ.
std::unique_ptr<DfgGraph> clone() const VL_MT_DISABLED;
// Add contents of other graph to this graph. Leaves other graph empty.
void addGraph(DfgGraph& other) VL_MT_DISABLED;
@ -911,15 +913,14 @@ bool DfgVertex::isOnes() const {
// Inline method definitions - for DfgVertexVar
//------------------------------------------------------------------------------
DfgVertexVar::DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVar* varp, uint32_t initialCapacity)
: DfgVertexVariadic{dfg, type, varp->fileline(), dtypeFor(varp), initialCapacity}
DfgVertexVar::DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVar* varp)
: DfgVertexUnary{dfg, type, varp->fileline(), dtypeFor(varp)}
, m_varp{varp}
, m_varScopep{nullptr} {
UASSERT_OBJ(dfg.modulep(), varp, "Un-scoped DfgVertexVar created in scoped DfgGraph");
}
DfgVertexVar::DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVarScope* vscp,
uint32_t initialCapacity)
: DfgVertexVariadic{dfg, type, vscp->fileline(), dtypeFor(vscp), initialCapacity}
DfgVertexVar::DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVarScope* vscp)
: DfgVertexUnary{dfg, type, vscp->fileline(), dtypeFor(vscp)}
, m_varp{vscp->varp()}
, m_varScopep{vscp} {
UASSERT_OBJ(!dfg.modulep(), vscp, "Scoped DfgVertexVar created in un-scoped DfgGraph");

View File

@ -183,49 +183,37 @@ class AstToDfgVisitor final : public VNVisitor {
return m_foundUnhandled;
}
// Build DfgEdge representing the LValue assignment. Returns false if unsuccessful.
bool convertAssignment(FileLine* flp, AstNode* nodep, DfgVertex* vtxp) {
DfgVertexSplice* convertLValue(AstNode* nodep) {
FileLine* const flp = nodep->fileline();
if (AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
m_foundUnhandled = false;
visit(vrefp);
// cppcheck-has-bug-suppress knownConditionTrueFalse
if (m_foundUnhandled) return false;
getVertex(vrefp)->template as<DfgVarPacked>()->addDriver(flp, 0, vtxp);
return true;
}
if (AstSel* const selp = VN_CAST(nodep, Sel)) {
AstVarRef* const vrefp = VN_CAST(selp->fromp(), VarRef);
const AstConst* const lsbp = VN_CAST(selp->lsbp(), Const);
if (!vrefp || !lsbp) {
++m_ctx.m_nonRepLhs;
return false;
if (m_foundUnhandled) return nullptr;
DfgVertexVar* const vtxp = getVertex(vrefp)->template as<DfgVertexVar>();
// Ensure driving splice vertex exists
if (!vtxp->srcp()) {
if (VN_IS(vtxp->dtypep(), UnpackArrayDType)) {
vtxp->srcp(new DfgSpliceArray{*m_dfgp, flp, vtxp->dtypep()});
} else {
vtxp->srcp(new DfgSplicePacked{*m_dfgp, flp, vtxp->dtypep()});
}
}
m_foundUnhandled = false;
visit(vrefp);
// cppcheck-has-bug-suppress knownConditionTrueFalse
if (m_foundUnhandled) return false;
getVertex(vrefp)->template as<DfgVarPacked>()->addDriver(flp, lsbp->toUInt(), vtxp);
return true;
}
if (AstArraySel* const selp = VN_CAST(nodep, ArraySel)) {
AstVarRef* const vrefp = VN_CAST(selp->fromp(), VarRef);
const AstConst* const idxp = VN_CAST(selp->bitp(), Const);
if (!vrefp || !idxp) {
++m_ctx.m_nonRepLhs;
return false;
}
m_foundUnhandled = false;
visit(vrefp);
// cppcheck-has-bug-suppress knownConditionTrueFalse
if (m_foundUnhandled) return false;
getVertex(vrefp)->template as<DfgVarArray>()->addDriver(flp, idxp->toUInt(), vtxp);
return true;
return vtxp->srcp()->as<DfgVertexSplice>();
}
++m_ctx.m_nonRepLhs;
return nullptr;
}
// Build DfgEdge representing the LValue assignment. Returns false if unsuccessful.
bool convertAssignment(FileLine* flp, AstNode* nodep, DfgVertex* vtxp) {
// Concatenation on the LHS. Select parts of the driving 'vtxp' then convert each part
if (AstConcat* const concatp = VN_CAST(nodep, Concat)) {
AstNode* const lhsp = concatp->lhsp();
AstNode* const rhsp = concatp->rhsp();
{
{ // Convet LHS of concat
FileLine* const lFlp = lhsp->fileline();
DfgSel* const lVtxp = new DfgSel{*m_dfgp, lFlp, DfgVertex::dtypeFor(lhsp)};
lVtxp->fromp(vtxp);
@ -233,7 +221,7 @@ class AstToDfgVisitor final : public VNVisitor {
if (!convertAssignment(flp, lhsp, lVtxp)) return false;
}
{
{ // Convert RHS of concat
FileLine* const rFlp = rhsp->fileline();
DfgSel* const rVtxp = new DfgSel{*m_dfgp, rFlp, DfgVertex::dtypeFor(rhsp)};
rVtxp->fromp(vtxp);
@ -241,7 +229,37 @@ class AstToDfgVisitor final : public VNVisitor {
return convertAssignment(flp, rhsp, rVtxp);
}
}
++m_ctx.m_nonRepLhs;
if (AstSel* const selp = VN_CAST(nodep, Sel)) {
AstVarRef* const vrefp = VN_CAST(selp->fromp(), VarRef);
const AstConst* const lsbp = VN_CAST(selp->lsbp(), Const);
if (!vrefp || !lsbp) {
++m_ctx.m_nonRepLhs;
return false;
}
if (DfgVertexSplice* const splicep = convertLValue(vrefp)) {
splicep->template as<DfgSplicePacked>()->addDriver(flp, lsbp->toUInt(), vtxp);
return true;
}
} else if (AstArraySel* const selp = VN_CAST(nodep, ArraySel)) {
AstVarRef* const vrefp = VN_CAST(selp->fromp(), VarRef);
const AstConst* const idxp = VN_CAST(selp->bitp(), Const);
if (!vrefp || !idxp) {
++m_ctx.m_nonRepLhs;
return false;
}
if (DfgVertexSplice* const splicep = convertLValue(vrefp)) {
splicep->template as<DfgSpliceArray>()->addDriver(flp, idxp->toUInt(), vtxp);
return true;
}
} else if (VN_IS(nodep, VarRef)) {
if (DfgVertexSplice* const splicep = convertLValue(nodep)) {
splicep->template as<DfgSplicePacked>()->addDriver(flp, 0, vtxp);
return true;
}
} else {
++m_ctx.m_nonRepLhs;
}
return false;
}
@ -315,18 +333,23 @@ class AstToDfgVisitor final : public VNVisitor {
for (DfgVarPacked* const varp : m_varPackedps) {
// Delete variables with no sinks nor sources (this can happen due to reverting
// uncommitted vertices, which does not remove variables)
if (!varp->hasSinks() && varp->arity() == 0) {
if (!varp->hasSinks() && !varp->srcp()) {
VL_DO_DANGLING(varp->unlinkDelete(*m_dfgp), varp);
continue;
}
// Nothing to do for un-driven (input) variables
if (!varp->srcp()) continue;
DfgSplicePacked* const splicep = varp->srcp()->as<DfgSplicePacked>();
// Gather (and unlink) all drivers
std::vector<Driver> drivers;
drivers.reserve(varp->arity());
varp->forEachSourceEdge([this, varp, &drivers](DfgEdge& edge, size_t idx) {
drivers.reserve(splicep->arity());
splicep->forEachSourceEdge([this, splicep, &drivers](DfgEdge& edge, size_t idx) {
DfgVertex* const driverp = edge.sourcep();
UASSERT(driverp, "Should not have created undriven sources");
addDriver(varp->driverFileLine(idx), varp->driverLsb(idx), driverp, drivers);
addDriver(splicep->driverFileLine(idx), splicep->driverLsb(idx), driverp, drivers);
edge.unlinkSource();
});
@ -424,10 +447,10 @@ class AstToDfgVisitor final : public VNVisitor {
}
// Reinsert drivers in order
varp->resetSources();
splicep->resetSources();
for (const Driver& driver : drivers) {
if (!driver.m_vtxp) break; // Stop at end of compacted list
varp->addDriver(driver.m_fileline, driver.m_lsb, driver.m_vtxp);
splicep->addDriver(driver.m_fileline, driver.m_lsb, driver.m_vtxp);
}
// Prune vertices potentially unused due to resolving multiple drivers.
@ -442,6 +465,15 @@ class AstToDfgVisitor final : public VNVisitor {
vtxp->forEachSource([&](DfgVertex& src) { prune.emplace(&src); });
vtxp->unlinkDelete(*m_dfgp);
}
// If the whole variable is driven, remove the splice node
if (splicep->arity() == 1 //
&& splicep->driverLsb(0) == 0 //
&& splicep->source(0)->width() == varp->width()) {
varp->srcp(splicep->source(0));
varp->driverFileLine(splicep->driverFileLine(0));
splicep->unlinkDelete(*m_dfgp);
}
}
}
@ -450,7 +482,7 @@ class AstToDfgVisitor final : public VNVisitor {
for (DfgVarArray* const varp : m_varArrayps) {
// Delete variables with no sinks nor sources (this can happen due to reverting
// uncommitted vertices, which does not remove variables)
if (!varp->hasSinks() && varp->arity() == 0) {
if (!varp->hasSinks() && !varp->srcp()) {
VL_DO_DANGLING(varp->unlinkDelete(*m_dfgp), varp);
}
}

1066
src/V3DfgBreakCycles.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -341,32 +341,20 @@ class ExtractCyclicComponents final {
return *clonep;
}
// Fix up non-variable sources of a DfgVertexVar that are in a different component,
// using the provided 'relink' callback
template <typename T_Vertex>
void fixSources(T_Vertex& vtx, std::function<void(T_Vertex&, DfgVertex&, size_t)> relink) {
static_assert(std::is_base_of<DfgVertexVar, T_Vertex>::value,
"'Vertex' must be a 'DfgVertexVar'");
// Fix edges that cross components
void fixEdges(DfgVertexVar& vtx) {
const size_t component = state(vtx).component;
vtx.forEachSourceEdge([&](DfgEdge& edge, size_t idx) {
DfgVertex& source = *edge.sourcep();
// DfgVertexVar sources are fixed up by `fixSinks` on those sources
if (source.is<DfgVertexVar>()) return;
const size_t sourceComponent = state(source).component;
// Same component is OK
if (sourceComponent == component) return;
// Unlink the source edge (source is reconnected by 'relink'
edge.unlinkSource();
// Apply the fixup
// cppcheck-has-bug-suppress constVariable
DfgVertexVar& clone = getClone(vtx, sourceComponent);
relink(*(clone.as<T_Vertex>()), source, idx);
});
}
// Fix up sinks of given variable vertex that are in a different component
void fixSinks(DfgVertexVar& vtx) {
const size_t component = state(vtx).component;
// All variable vertices have at most a single source, and only variable
// vertices can have multiple sinks, therefore the source must be either:
// - in the same component as the variable vertex
// - be a variable vertex itself, which might be in a different component
// The later case will be fixed up when handling the source variable
DfgVertex* const srcp = vtx.srcp();
UASSERT_OBJ(!srcp || srcp->is<DfgVertexVar>() || state(*srcp).component == component, &vtx,
"Driver of DfgVertexVar must be in the same component");
// Fix up sinks in a differetn component
vtx.forEachSinkEdge([&](DfgEdge& edge) {
const size_t sinkComponent = state(*edge.sinkp()).component;
// Same component is OK
@ -376,49 +364,6 @@ class ExtractCyclicComponents final {
});
}
// Fix edges that cross components
void fixEdges(DfgVertexVar& vtx) {
if (DfgVarPacked* const vvtxp = vtx.cast<DfgVarPacked>()) {
fixSources<DfgVarPacked>(
*vvtxp, [&](DfgVarPacked& clone, DfgVertex& driver, size_t driverIdx) {
clone.addDriver(vvtxp->driverFileLine(driverIdx), //
vvtxp->driverLsb(driverIdx), &driver);
});
fixSinks(*vvtxp);
return;
}
if (DfgVarArray* const vvtxp = vtx.cast<DfgVarArray>()) {
fixSources<DfgVarArray>( //
*vvtxp, [&](DfgVarArray& clone, DfgVertex& driver, size_t driverIdx) {
clone.addDriver(vvtxp->driverFileLine(driverIdx), //
vvtxp->driverIndex(driverIdx), &driver);
});
fixSinks(*vvtxp);
return;
}
}
static void packSources(DfgGraph& dfg) {
// Remove undriven variable sources
for (DfgVertexVar* const vtxp : dfg.varVertices().unlinkable()) {
if (DfgVarPacked* const varp = vtxp->cast<DfgVarPacked>()) {
varp->packSources();
if (!varp->hasSinks() && varp->arity() == 0) {
VL_DO_DANGLING(varp->unlinkDelete(dfg), varp);
}
continue;
}
if (DfgVarArray* const varp = vtxp->cast<DfgVarArray>()) {
varp->packSources();
if (!varp->hasSinks() && varp->arity() == 0) {
VL_DO_DANGLING(varp->unlinkDelete(dfg), varp);
}
continue;
}
}
}
template <typename Vertex>
void moveVertices(DfgVertex::List<Vertex>& list) {
for (DfgVertex* const vtxp : list.unlinkable()) {
@ -446,11 +391,6 @@ class ExtractCyclicComponents final {
UASSERT_OBJ(component == state(snk).component, &vtx,
"Edge crossing components without variable involvement");
});
if (const DfgVertexVar* const vtxp = vtx.cast<DfgVertexVar>()) {
vtxp->forEachSourceEdge([](const DfgEdge& edge, size_t) {
UASSERT_OBJ(edge.sourcep(), edge.sinkp(), "Missing source on variable vertex");
});
}
});
}
@ -489,11 +429,6 @@ class ExtractCyclicComponents final {
if (&vtx == lastp) break;
}
// Pack sources of variables to remove the now undriven inputs
// (cloning might have unlinked some of the inputs),
packSources(m_dfg);
for (const auto& dfgp : m_components) packSources(*dfgp);
// Check results for consistency
if (VL_UNLIKELY(m_doExpensiveChecks)) {
checkEdges(m_dfg);

View File

@ -201,45 +201,52 @@ class DfgToAstVisitor final : DfgVisitor {
++m_ctx.m_resultEquations;
}
void convertVarDriver(const DfgVarPacked* dfgVarp) {
if (dfgVarp->isDrivenFullyByDfg()) {
// Whole variable is driven. Render driver and assign directly to whole variable.
FileLine* const flp = dfgVarp->driverFileLine(0);
AstVarRef* const lhsp = new AstVarRef{flp, getNode(dfgVarp), VAccess::WRITE};
AstNodeExpr* const rhsp = convertDfgVertexToAstNodeExpr(dfgVarp->source(0));
addResultEquation(dfgVarp, flp, lhsp, rhsp);
} else {
void convertPackedDriver(const DfgVarPacked* dfgVarp) {
if (DfgSplicePacked* const splicep = dfgVarp->srcp()->cast<DfgSplicePacked>()) {
// Variable is driven partially. Render each driver as a separate assignment.
dfgVarp->forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
splicep->forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
UASSERT_OBJ(edge.sourcep(), dfgVarp, "Should have removed undriven sources");
// Render the rhs expression
AstNodeExpr* const rhsp = convertDfgVertexToAstNodeExpr(edge.sourcep());
// Create select LValue
FileLine* const flp = dfgVarp->driverFileLine(idx);
FileLine* const flp = splicep->driverFileLine(idx);
AstVarRef* const refp = new AstVarRef{flp, getNode(dfgVarp), VAccess::WRITE};
AstConst* const lsbp = new AstConst{flp, dfgVarp->driverLsb(idx)};
AstConst* const lsbp = new AstConst{flp, splicep->driverLsb(idx)};
const int width = static_cast<int>(edge.sourcep()->width());
AstSel* const lhsp = new AstSel{flp, refp, lsbp, width};
// Add assignment of the value to the selected bits
addResultEquation(dfgVarp, flp, lhsp, rhsp);
});
return;
}
// Whole variable is driven. Render driver and assign directly to whole variable.
FileLine* const flp
= dfgVarp->driverFileLine() ? dfgVarp->driverFileLine() : dfgVarp->fileline();
AstVarRef* const lhsp = new AstVarRef{flp, getNode(dfgVarp), VAccess::WRITE};
AstNodeExpr* const rhsp = convertDfgVertexToAstNodeExpr(dfgVarp->srcp());
addResultEquation(dfgVarp, flp, lhsp, rhsp);
}
void convertArrayDiver(const DfgVarArray* dfgVarp) {
// Variable is driven partially. Assign from parts of the canonical var.
dfgVarp->forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
UASSERT_OBJ(edge.sourcep(), dfgVarp, "Should have removed undriven sources");
// Render the rhs expression
AstNodeExpr* const rhsp = convertDfgVertexToAstNodeExpr(edge.sourcep());
// Create select LValue
FileLine* const flp = dfgVarp->driverFileLine(idx);
AstVarRef* const refp = new AstVarRef{flp, getNode(dfgVarp), VAccess::WRITE};
AstConst* const idxp = new AstConst{flp, dfgVarp->driverIndex(idx)};
AstArraySel* const lhsp = new AstArraySel{flp, refp, idxp};
// Add assignment of the value to the selected bits
addResultEquation(dfgVarp, flp, lhsp, rhsp);
});
if (DfgSpliceArray* const splicep = dfgVarp->srcp()->cast<DfgSpliceArray>()) {
// Variable is driven partially. Assign from parts of the canonical var.
splicep->forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
UASSERT_OBJ(edge.sourcep(), dfgVarp, "Should have removed undriven sources");
// Render the rhs expression
AstNodeExpr* const rhsp = convertDfgVertexToAstNodeExpr(edge.sourcep());
// Create select LValue
FileLine* const flp = splicep->driverFileLine(idx);
AstVarRef* const refp = new AstVarRef{flp, getNode(dfgVarp), VAccess::WRITE};
AstConst* const idxp = new AstConst{flp, splicep->driverIndex(idx)};
AstArraySel* const lhsp = new AstArraySel{flp, refp, idxp};
// Add assignment of the value to the selected bits
addResultEquation(dfgVarp, flp, lhsp, rhsp);
});
return;
}
UASSERT_OBJ(false, dfgVarp, "Should not have wholly driven arrays in Dfg");
}
// VISITORS
@ -285,11 +292,11 @@ class DfgToAstVisitor final : DfgVisitor {
// The graph must have been regularized, so we only need to render assignments
for (DfgVertexVar& vtx : dfg.varVertices()) {
// If there is no driver (this vertex is an input to the graph), then nothing to do.
if (!vtx.isDrivenByDfg()) continue;
if (!vtx.srcp()) continue;
// Render packed variable assignments
if (const DfgVarPacked* const dfgVarp = vtx.cast<DfgVarPacked>()) {
convertVarDriver(dfgVarp);
convertPackedDriver(dfgVarp);
continue;
}

View File

@ -240,16 +240,34 @@ static void process(DfgGraph& dfg, V3DfgOptimizationContext& ctx) {
// Extract the cyclic sub-graphs. We do this because a lot of the optimizations assume a
// DAG, and large, mostly acyclic graphs could not be optimized due to the presence of
// small cycles.
const std::vector<std::unique_ptr<DfgGraph>>& cyclicComponents
std::vector<std::unique_ptr<DfgGraph>> cyclicComponents
= dfg.extractCyclicComponents("cyclic");
// Split the remaining acyclic DFG into [weakly] connected components
const std::vector<std::unique_ptr<DfgGraph>>& acyclicComponents
= dfg.splitIntoComponents("acyclic");
std::vector<std::unique_ptr<DfgGraph>> acyclicComponents = dfg.splitIntoComponents("acyclic");
// Quick sanity check
UASSERT_OBJ(dfg.size() == 0, dfg.modulep(), "DfgGraph should have become empty");
// Attempt to convert cyclic components into acyclic ones
if (v3Global.opt.fDfgBreakCyckes()) {
for (auto it = cyclicComponents.begin(); it != cyclicComponents.end();) {
auto result = V3DfgPasses::breakCycles(**it, ctx);
if (!result.first) {
// No improvement, moving on.
++it;
} else if (!result.second) {
// Improved, but still cyclic. Replace the original cyclic component.
*it = std::move(result.first);
++it;
} else {
// Result became acyclic. Move to acyclicComponents, delete original.
acyclicComponents.emplace_back(std::move(result.first));
it = cyclicComponents.erase(it);
}
}
}
// For each acyclic component
for (auto& component : acyclicComponents) {
if (dumpDfgLevel() >= 7) component->dumpDotFilePrefixed(ctx.prefix() + "source");

View File

@ -30,6 +30,16 @@ V3DfgBinToOneHotContext::~V3DfgBinToOneHotContext() {
m_decodersCreated);
}
V3DfgBreakCyclesContext::~V3DfgBreakCyclesContext() {
V3Stats::addStat("Optimizations, DFG " + m_label + " BreakCycles, made acyclic", m_nFixed);
V3Stats::addStat("Optimizations, DFG " + m_label + " BreakCycles, improved", m_nImproved);
V3Stats::addStat("Optimizations, DFG " + m_label + " BreakCycles, left unchanged",
m_nUnchanged);
V3Stats::addStat("Optimizations, DFG " + m_label + " BreakCycles, trivial", m_nTrivial);
V3Stats::addStat("Optimizations, DFG " + m_label + " BreakCycles, changes applied",
m_nImprovements);
}
V3DfgCseContext::~V3DfgCseContext() {
V3Stats::addStat("Optimizations, DFG " + m_label + " CSE, expressions eliminated",
m_eliminated);
@ -162,7 +172,7 @@ void V3DfgPasses::inlineVars(DfgGraph& dfg) {
// Don't inline SystemC variables, as SystemC types are not interchangeable with
// internal types, and hence the variables are not interchangeable either.
if (varp->hasSinks() && varp->isDrivenFullyByDfg() && !varp->varp()->isSc()) {
DfgVertex* const driverp = varp->source(0);
DfgVertex* const driverp = varp->srcp();
// We must keep the original driver in certain cases, when swapping them would
// not be functionally or technically (implementation reasons) equivalent:
@ -371,12 +381,14 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
// The index variable
DfgVarPacked* const idxVtxp = [&]() {
// If there is an existing result variable, use that, otherwise create a new variable
DfgVarPacked* varp = srcp->getResultVar();
if (!varp) {
DfgVarPacked* varp = nullptr;
if (DfgVertexVar* const vp = srcp->getResultVar()) {
varp = vp->as<DfgVarPacked>();
} else {
const std::string name = dfg.makeUniqueName("BinToOneHot_Idx", nTables);
varp = dfg.makeNewVar(flp, name, idxDTypep, nullptr)->as<DfgVarPacked>();
varp->varp()->isInternal(true);
varp->addDriver(flp, 0, srcp);
varp->srcp(srcp);
}
varp->setHasModRefs();
return varp;
@ -544,9 +556,9 @@ void V3DfgPasses::eliminateVars(DfgGraph& dfg, V3DfgEliminateVarsContext& ctx) {
if (!varp->hasModRefs()) {
// If it is only referenced in this DFG, it can be removed
++ctx.m_varsRemoved;
varp->replaceWith(varp->source(0));
varp->replaceWith(varp->srcp());
varp->nodep()->unlinkFrBack()->deleteTree();
} else if (DfgVarPacked* const driverp = varp->source(0)->cast<DfgVarPacked>()) {
} else if (DfgVarPacked* const driverp = varp->srcp()->cast<DfgVarPacked>()) {
// If it's driven from another variable, it can be replaced by that. However, we do not
// want to propagate SystemC variables into the design.
if (driverp->varp()->isSc()) continue;

View File

@ -40,6 +40,20 @@ public:
~V3DfgBinToOneHotContext() VL_MT_DISABLED;
};
class V3DfgBreakCyclesContext final {
const std::string m_label; // Label to apply to stats
public:
VDouble0 m_nFixed; // Number of graphs that became acyclic
VDouble0 m_nImproved; // Number of graphs that were imporoved but still cyclic
VDouble0 m_nUnchanged; // Number of graphs that were left unchanged
VDouble0 m_nTrivial; // Number of graphs that were not changed
VDouble0 m_nImprovements; // Number of changes made to graphs
explicit V3DfgBreakCyclesContext(const std::string& label)
: m_label{label} {}
~V3DfgBreakCyclesContext() VL_MT_DISABLED;
};
class V3DfgCseContext final {
const std::string m_label; // Label to apply to stats
@ -93,6 +107,7 @@ public:
VDouble0 m_resultEquations; // Number of result combinational equations
V3DfgBinToOneHotContext m_binToOneHotContext{m_label};
V3DfgBreakCyclesContext m_breakCyclesContext{m_label};
V3DfgCseContext m_cseContext0{m_label + " 1st"};
V3DfgCseContext m_cseContext1{m_label + " 2nd"};
V3DfgPeepholeContext m_peepholeContext{m_label};
@ -120,6 +135,16 @@ DfgGraph* astToDfg(AstModule&, V3DfgOptimizationContext&) VL_MT_DISABLED;
// Same as above, but for the entire netlist, after V3Scope
DfgGraph* astToDfg(AstNetlist&, V3DfgOptimizationContext&) VL_MT_DISABLED;
// Attempt to make the given cyclic graph into an acyclic, or "less cyclic"
// equivalent. If the returned pointer is null, then no improvement was
// possible on the input graph. Otherwise the returned graph is an improvement
// on the input graph, with at least some cycles eliminated. The returned
// graph is always independent of the original. If an imporoved graph is
// returned, then the returned 'bool' flag indicated if the returned graph is
// acyclic (flag 'true'), or still cyclic (flag 'false').
std::pair<std::unique_ptr<DfgGraph>, bool> breakCycles(const DfgGraph&,
V3DfgOptimizationContext&) VL_MT_DISABLED;
// Optimize the given DfgGraph
void optimize(DfgGraph&, V3DfgOptimizationContext&) VL_MT_DISABLED;

View File

@ -241,6 +241,16 @@ class V3DfgPeephole final : public DfgVisitor {
return make<Vertex>(examplep->fileline(), examplep->dtypep(), operands...);
}
// Check two vertex are the same, or the same constant value
static bool isSame(const DfgVertex* ap, const DfgVertex* bp) {
if (ap == bp) return true;
const DfgConst* const aConstp = ap->cast<DfgConst>();
if (!aConstp) return false;
const DfgConst* const bConstp = bp->cast<DfgConst>();
if (!bConstp) return false;
return aConstp->num().isCaseEq(bConstp->num());
}
// Note: If any of the following transformers return true, then the vertex was replaced and the
// caller must not do any further changes, so the caller must check the return value, otherwise
// there will be hard to debug issues.
@ -417,6 +427,55 @@ class V3DfgPeephole final : public DfgVisitor {
return false;
}
// Transformations that apply to all distributive and associative binary
// vertices 'Other' is the type that is distributive over 'Vertex',
// that is: a Other (b Vertex c) == (a Other b) Vertex (a Other c)
template <typename Other, typename Vertex>
VL_ATTR_WARN_UNUSED_RESULT bool distributiveAndAssociativeBinary(Vertex* vtxp) {
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
if (!lhsp->hasMultipleSinks() && !rhsp->hasMultipleSinks()) {
// Convert '(a Other b) Vertex (a Other c)' and associative
// variations to 'a Other (b Vertex c)'
if (Other* const lp = lhsp->cast<Other>()) {
if (Other* const rp = rhsp->cast<Other>()) {
DfgVertex* const llp = lp->lhsp();
DfgVertex* const lrp = lp->rhsp();
DfgVertex* const rlp = rp->lhsp();
DfgVertex* const rrp = rp->rhsp();
DfgVertex* ap = nullptr;
DfgVertex* bp = nullptr;
DfgVertex* cp = nullptr;
if (llp == rlp) {
ap = llp;
bp = lrp;
cp = rrp;
} else if (llp == rrp) {
ap = llp;
bp = lrp;
cp = rlp;
} else if (lrp == rlp) {
ap = lrp;
bp = llp;
cp = rrp;
} else if (lrp == rrp) {
ap = lrp;
bp = llp;
cp = rlp;
}
if (ap) {
APPLYING(REPLACE_DISTRIBUTIVE_BINARY) {
replace(vtxp, make<Other>(vtxp, ap, make<Vertex>(lhsp, bp, cp)));
return true;
}
}
}
}
}
return false;
}
// Bitwise operation with one side Const, and the other side a Concat
template <typename Vertex>
VL_ATTR_WARN_UNUSED_RESULT bool tryPushBitwiseOpThroughConcat(Vertex* vtxp, DfgConst* constp,
@ -881,15 +940,23 @@ class V3DfgPeephole final : public DfgVisitor {
//=========================================================================
void visit(DfgAnd* vtxp) override {
UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
UASSERT_OBJ(vtxp->dtypep() == lhsp->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->dtypep() == rhsp->dtypep(), vtxp, "Mismatched RHS width");
if (lhsp == rhsp) {
APPLYING(REMOVE_AND_WITH_SELF) {
replace(vtxp, lhsp);
return;
}
}
if (associativeBinary(vtxp)) return;
if (commutativeBinary(vtxp)) return;
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
FileLine* const flp = vtxp->fileline();
// Bubble pushing (De Morgan)
@ -935,6 +1002,8 @@ class V3DfgPeephole final : public DfgVisitor {
}
}
if (distributiveAndAssociativeBinary<DfgOr, DfgAnd>(vtxp)) return;
if (tryPushBitwiseOpThroughReductions(vtxp)) return;
if (DfgNot* const lhsNotp = lhsp->cast<DfgNot>()) {
@ -946,19 +1015,38 @@ class V3DfgPeephole final : public DfgVisitor {
return;
}
}
// ~A & (A & _) or ~A & (_ & A) is all zeroes
if (DfgAnd* const rhsAndp = rhsp->cast<DfgAnd>()) {
if (lhsNotp->srcp() == rhsAndp->lhsp() || lhsNotp->srcp() == rhsAndp->rhsp()) {
APPLYING(REPLACE_CONTRADICTORY_AND_3) {
DfgConst* const replacementp = makeZero(flp, vtxp->width());
replace(vtxp, replacementp);
return;
}
}
}
}
}
void visit(DfgOr* vtxp) override {
UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
UASSERT_OBJ(vtxp->dtypep() == lhsp->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->dtypep() == rhsp->dtypep(), vtxp, "Mismatched RHS width");
if (lhsp == rhsp) {
APPLYING(REMOVE_OR_WITH_SELF) {
replace(vtxp, lhsp);
return;
}
}
if (associativeBinary(vtxp)) return;
if (commutativeBinary(vtxp)) return;
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
FileLine* const flp = vtxp->fileline();
// Bubble pushing (De Morgan)
@ -1027,6 +1115,8 @@ class V3DfgPeephole final : public DfgVisitor {
}
}
if (distributiveAndAssociativeBinary<DfgAnd, DfgOr>(vtxp)) return;
if (tryPushBitwiseOpThroughReductions(vtxp)) return;
if (DfgNot* const lhsNotp = lhsp->cast<DfgNot>()) {
@ -1039,20 +1129,40 @@ class V3DfgPeephole final : public DfgVisitor {
return;
}
}
// ~A | (A | _) or ~A | (_ | A) is all ones
if (DfgOr* const rhsOrp = rhsp->cast<DfgOr>()) {
if (lhsNotp->srcp() == rhsOrp->lhsp() || lhsNotp->srcp() == rhsOrp->rhsp()) {
APPLYING(REPLACE_TAUTOLOGICAL_OR_3) {
DfgConst* const replacementp = makeZero(flp, vtxp->width());
replacementp->num().setAllBits1();
replace(vtxp, replacementp);
return;
}
}
}
}
}
void visit(DfgXor* vtxp) override {
UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
UASSERT_OBJ(vtxp->dtypep() == lhsp->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->dtypep() == rhsp->dtypep(), vtxp, "Mismatched RHS width");
if (lhsp == rhsp) {
APPLYING(REPLACE_XOR_WITH_SELF) {
DfgConst* const replacementp = makeZero(vtxp->fileline(), vtxp->width());
replace(vtxp, replacementp);
return;
}
}
if (associativeBinary(vtxp)) return;
if (commutativeBinary(vtxp)) return;
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
if (DfgConst* const lConstp = lhsp->cast<DfgConst>()) {
if (lConstp->isZero()) {
APPLYING(REMOVE_XOR_WITH_ZERO) {
@ -1092,11 +1202,15 @@ class V3DfgPeephole final : public DfgVisitor {
void visit(DfgArraySel* vtxp) override {
if (DfgConst* const idxp = vtxp->bitp()->cast<DfgConst>()) {
if (DfgVarArray* const varp = vtxp->fromp()->cast<DfgVarArray>()) {
const size_t idx = idxp->toSizeT();
if (DfgVertex* const driverp = varp->driverAt(idx)) {
APPLYING(INLINE_ARRAYSEL) {
replace(vtxp, driverp);
return;
if (varp->srcp()) {
if (DfgSpliceArray* const splicep = varp->srcp()->cast<DfgSpliceArray>()) {
const size_t idx = idxp->toSizeT();
if (DfgVertex* const driverp = splicep->driverAt(idx)) {
APPLYING(INLINE_ARRAYSEL) {
replace(vtxp, driverp);
return;
}
}
}
}
}
@ -1252,6 +1366,16 @@ class V3DfgPeephole final : public DfgVisitor {
void visit(DfgLogAnd* vtxp) override {
if (foldBinary(vtxp)) return;
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
if (lhsp->width() == 1 && rhsp->width() == 1) {
APPLYING(REPLACE_LOGAND_WITH_AND) {
replace(vtxp, make<DfgAnd>(vtxp, lhsp, rhsp));
return;
}
}
}
void visit(DfgLogEq* vtxp) override {
@ -1264,6 +1388,16 @@ class V3DfgPeephole final : public DfgVisitor {
void visit(DfgLogOr* vtxp) override {
if (foldBinary(vtxp)) return;
DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp();
if (lhsp->width() == 1 && rhsp->width() == 1) {
APPLYING(REPLACE_LOGOR_WITH_OR) {
replace(vtxp, make<DfgOr>(vtxp, lhsp, rhsp));
return;
}
}
}
void visit(DfgLt* vtxp) override {
@ -1409,6 +1543,13 @@ class V3DfgPeephole final : public DfgVisitor {
}
}
if (isSame(thenp, elsep)) {
APPLYING(REMOVE_COND_WITH_BRANCHES_SAME) {
replace(vtxp, elsep);
return;
}
}
if (DfgNot* const condNotp = condp->cast<DfgNot>()) {
if (!condp->hasMultipleSinks() || condNotp->hasMultipleSinks()) {
APPLYING(SWAP_COND_WITH_NOT_CONDITION) {
@ -1447,6 +1588,35 @@ class V3DfgPeephole final : public DfgVisitor {
}
}
if (DfgOr* const condOrp = condp->cast<DfgOr>()) {
if (DfgCond* const thenCondp = thenp->cast<DfgCond>()) {
if (!thenCondp->hasMultipleSinks()) {
if (condOrp->lhsp() == thenCondp->condp()) {
// '(a | b) ? (a ? x : y) : z' -> 'a ? x : b ? y : z'
APPLYING(REPLACE_COND_OR_THEN_COND_LHS) {
DfgCond* const replacementp
= make<DfgCond>(vtxp, condOrp->lhsp(), thenCondp->thenp(),
make<DfgCond>(thenCondp, condOrp->rhsp(),
thenCondp->elsep(), elsep));
replace(vtxp, replacementp);
return;
}
}
if (condOrp->rhsp() == thenCondp->condp()) {
// '(a | b) ? (a ? x : y) : z' -> 'a ? x : b ? y : z'
APPLYING(REPLACE_COND_OR_THEN_COND_RHS) {
DfgCond* const replacementp
= make<DfgCond>(vtxp, condOrp->rhsp(), thenCondp->thenp(),
make<DfgCond>(thenCondp, condOrp->lhsp(),
thenCondp->elsep(), elsep));
replace(vtxp, replacementp);
return;
}
}
}
}
}
if (vtxp->width() > 1) {
// 'cond ? a + 1 : a' -> 'a + cond'
if (DfgAdd* const thenAddp = thenp->cast<DfgAdd>()) {
@ -1495,6 +1665,13 @@ class V3DfgPeephole final : public DfgVisitor {
return;
}
}
if (thenp == condp) { // a ? a : b becomes a | b
APPLYING(REPLACE_COND_WITH_THEN_BRANCH_COND) {
DfgOr* const repalcementp = make<DfgOr>(vtxp, condp, elsep);
replace(vtxp, repalcementp);
return;
}
}
if (thenp->isOnes()) { // a ? 1 : b becomes a | b
APPLYING(REPLACE_COND_WITH_THEN_BRANCH_ONES) {
DfgOr* const repalcementp = make<DfgOr>(vtxp, condp, elsep);

View File

@ -48,11 +48,14 @@
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_REPLICATE) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_SHIFTL) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_AND_WITH_ONES) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_AND_WITH_SELF) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_CONCAT_OF_ADJOINING_SELS) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_COND_WITH_BRANCHES_SAME) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_COND_WITH_FALSE_CONDITION) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_COND_WITH_TRUE_CONDITION) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_FULL_WIDTH_SEL) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_NOT_NOT) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_OR_WITH_SELF) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_OR_WITH_ZERO) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_REPLICATE_ONCE) \
@ -68,12 +71,19 @@
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_DEC) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_INC) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_OR_THEN_COND_LHS) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_OR_THEN_COND_RHS) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_ELSE_BRANCH_ONES) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_ELSE_BRANCH_ZERO) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_COND) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_ONES) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_ZERO) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONTRADICTORY_AND) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONTRADICTORY_AND_3) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_DISTRIBUTIVE_BINARY) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_EXTEND) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_LOGAND_WITH_AND) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_LOGOR_WITH_OR) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NOT_EQ) \
@ -86,7 +96,9 @@
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SEL_FROM_SEL) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SUB_WITH_NOT) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_TAUTOLOGICAL_OR) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_TAUTOLOGICAL_OR_3) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_XOR_WITH_ONES) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_XOR_WITH_SELF) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, RIGHT_LEANING_ASSOC) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_COND_WITH_NEQ_CONDITION) \
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_COND_WITH_NOT_CONDITION) \

View File

@ -45,12 +45,23 @@ class DfgRegularize final {
// Ensure intermediate values used multiple times are written to variables
for (DfgVertex& vtx : m_dfg.opVertices()) {
const bool needsIntermediateVariable = [&]() {
// Splice vertices represent partial assignments, so they need a variable
// iff and only if they have a non-variable sink.
if (vtx.is<DfgVertexSplice>()) {
const bool hasNonVarSink
= vtx.findSink<DfgVertex>([](const DfgVertex& snk) { //
return !snk.is<DfgVertexVar>();
});
return hasNonVarSink;
}
// Anything that drives an SC variable needs an intermediate,
// as we can only assign simple variables to SC variables at runtime.
const bool hasScSink = vtx.findSink<DfgVertexVar>([](const DfgVertexVar& var) { //
return var.varp()->isSc();
});
if (hasScSink) return true;
// // Splice vertices always need a variable as they represent partial updates
// if (vtx.is<DfgVertexSplice>()) return true;
// Operations without multiple sinks need no variables
if (!vtx.hasMultipleSinks()) return false;
// Array selects need no variables, they are just memory references
@ -63,26 +74,21 @@ class DfgRegularize final {
// This is an op that requires a result variable. Ensure it is
// assigned to one, and redirect other sinks read that variable.
if (DfgVarPacked* const varp = vtx.getResultVar()) {
// A variable already exists
UASSERT_OBJ(varp->arity() == 1, varp, "Result variable with multiple drivers");
FileLine* const flp = varp->driverFileLine(0);
varp->sourceEdge(0)->unlinkSource();
varp->resetSources();
if (DfgVertexVar* const varp = vtx.getResultVar()) {
varp->sourceEdge<0>()->unlinkSource();
vtx.replaceWith(varp);
varp->addDriver(flp, 0, &vtx);
varp->srcp(&vtx);
} else {
// Need to create an intermediate variable
const std::string name = m_dfg.makeUniqueName("Regularize", m_nTmps);
FileLine* const flp = vtx.fileline();
AstScope* const scopep = scoped ? vtx.scopep(scopeCache) : nullptr;
DfgVarPacked* const newp
= m_dfg.makeNewVar(flp, name, vtx.dtypep(), scopep)->as<DfgVarPacked>();
DfgVertexVar* const newp = m_dfg.makeNewVar(flp, name, vtx.dtypep(), scopep);
++m_nTmps;
++m_ctx.m_temporariesIntroduced;
// Replace vertex with the variable and add back driver
vtx.replaceWith(newp);
newp->addDriver(vtx.fileline(), 0, &vtx);
newp->srcp(&vtx);
}
}
}

View File

@ -38,22 +38,24 @@
// === Abstract base node types (DfgVertex*) ===================================
class DfgVertexVar VL_NOT_FINAL : public DfgVertexVariadic {
class DfgVertexVar VL_NOT_FINAL : public DfgVertexUnary {
AstVar* const m_varp; // The AstVar associated with this vertex (not owned by this vertex)
AstVarScope* const m_varScopep; // The AstVarScope associated with this vertex (not owned)
bool m_hasDfgRefs = false; // This AstVar is referenced in a different DFG of the module
bool m_hasModRefs = false; // This AstVar is referenced outside the DFG, but in the module
bool m_hasExtRefs = false; // This AstVar is referenced from outside the module
// Location of driver of this variable. Only used for converting back to Ast. Might be nullptr.
FileLine* m_driverFileLine = nullptr;
bool selfEquals(const DfgVertex& that) const final VL_MT_DISABLED;
V3Hash selfHash() const final VL_MT_DISABLED;
public:
inline DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVar* varp, uint32_t initialCapacity);
inline DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVarScope* vscp, uint32_t initialCapacity);
inline DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVar* varp);
inline DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVarScope* vscp);
ASTGEN_MEMBERS_DfgVertexVar;
bool isDrivenByDfg() const { return arity() > 0; }
const std::string srcName(size_t) const override { return ""; }
AstVar* varp() const { return m_varp; }
AstVarScope* varScopep() const { return m_varScopep; }
@ -68,6 +70,13 @@ public:
void setHasExtRefs() { m_hasExtRefs = true; }
bool hasNonLocalRefs() const { return hasDfgRefs() || hasModRefs() || hasExtRefs(); }
FileLine* driverFileLine() const { return m_driverFileLine; }
void driverFileLine(FileLine* flp) { m_driverFileLine = flp; }
bool isDrivenFullyByDfg() const {
return srcp() && !srcp()->is<DfgVertexSplice>() && !varp()->isForced();
}
// Variable cannot be removed, even if redundant in the DfgGraph (might be used externally)
bool keep() const {
// Keep if referenced outside this module
@ -82,6 +91,12 @@ public:
return false;
}
};
class DfgVertexSplice VL_NOT_FINAL : public DfgVertexVariadic {
public:
DfgVertexSplice(DfgGraph& dfg, VDfgType type, FileLine* flp, AstNodeDType* dtypep)
: DfgVertexVariadic{dfg, type, flp, dtypep, 1u} {}
ASTGEN_MEMBERS_DfgVertexSplice;
};
// === Concrete node types =====================================================
@ -184,14 +199,49 @@ class DfgVarArray final : public DfgVertexVar {
public:
DfgVarArray(DfgGraph& dfg, AstVar* varp)
: DfgVertexVar{dfg, dfgType(), varp, 4u} {
: DfgVertexVar{dfg, dfgType(), varp} {
UASSERT_OBJ(VN_IS(dtypep(), UnpackArrayDType), varp, "Non array DfgVarArray");
}
DfgVarArray(DfgGraph& dfg, AstVarScope* vscp)
: DfgVertexVar{dfg, dfgType(), vscp, 4u} {
: DfgVertexVar{dfg, dfgType(), vscp} {
UASSERT_OBJ(VN_IS(dtypep(), UnpackArrayDType), vscp, "Non array DfgVarArray");
}
ASTGEN_MEMBERS_DfgVarArray;
};
class DfgVarPacked final : public DfgVertexVar {
friend class DfgVertex;
friend class DfgVisitor;
public:
DfgVarPacked(DfgGraph& dfg, AstVar* varp)
: DfgVertexVar{dfg, dfgType(), varp} {
UASSERT_OBJ(!VN_IS(dtypep(), UnpackArrayDType), varp, "Array DfgVarPacked");
}
DfgVarPacked(DfgGraph& dfg, AstVarScope* vscp)
: DfgVertexVar{dfg, dfgType(), vscp} {
UASSERT_OBJ(!VN_IS(dtypep(), UnpackArrayDType), vscp, "Array DfgVarPacked");
}
ASTGEN_MEMBERS_DfgVarPacked;
};
// === DfgVertexSplice ===
class DfgSpliceArray final : public DfgVertexSplice {
friend class DfgVertex;
friend class DfgVisitor;
using DriverData = std::pair<FileLine*, uint32_t>;
std::vector<DriverData> m_driverData; // Additional data associated with each driver
bool selfEquals(const DfgVertex& that) const override VL_MT_DISABLED;
V3Hash selfHash() const override VL_MT_DISABLED;
public:
DfgSpliceArray(DfgGraph& dfg, FileLine* flp, AstNodeDType* dtypep)
: DfgVertexSplice{dfg, dfgType(), flp, dtypep} {
UASSERT_OBJ(VN_IS(dtypep, UnpackArrayDType), flp, "Non array DfgSpliceArray");
}
ASTGEN_MEMBERS_DfgSpliceArray;
void addDriver(FileLine* flp, uint32_t index, DfgVertex* vtxp) {
m_driverData.emplace_back(flp, index);
@ -203,27 +253,6 @@ public:
DfgVertexVariadic::resetSources();
}
// Remove undriven sources
void packSources() {
// Grab and reset the driver data
std::vector<DriverData> driverData;
driverData.swap(m_driverData);
// Grab and unlink the sources
std::vector<DfgVertex*> sources{arity()};
forEachSourceEdge([&](DfgEdge& edge, size_t idx) {
sources[idx] = edge.sourcep();
edge.unlinkSource();
});
DfgVertexVariadic::resetSources();
// Add back the driven sources
for (size_t i = 0; i < sources.size(); ++i) {
if (!sources[i]) continue;
addDriver(driverData[i].first, driverData[i].second, sources[i]);
}
}
FileLine* driverFileLine(size_t idx) const { return m_driverData[idx].first; }
uint32_t driverIndex(size_t idx) const { return m_driverData[idx].second; }
@ -234,26 +263,27 @@ public:
return edgep ? edgep->sourcep() : nullptr;
}
const string srcName(size_t idx) const override { return cvtToStr(driverIndex(idx)); }
const std::string srcName(size_t idx) const override {
return std::to_string(driverIndex(idx));
}
};
class DfgVarPacked final : public DfgVertexVar {
class DfgSplicePacked final : public DfgVertexSplice {
friend class DfgVertex;
friend class DfgVisitor;
using DriverData = std::pair<FileLine*, uint32_t>;
std::vector<DriverData> m_driverData; // Additional data associate with each driver
std::vector<DriverData> m_driverData; // Additional data associated with each driver
bool selfEquals(const DfgVertex& that) const override VL_MT_DISABLED;
V3Hash selfHash() const override VL_MT_DISABLED;
public:
DfgVarPacked(DfgGraph& dfg, AstVar* varp)
: DfgVertexVar{dfg, dfgType(), varp, 1u} {}
DfgVarPacked(DfgGraph& dfg, AstVarScope* vscp)
: DfgVertexVar{dfg, dfgType(), vscp, 1u} {}
ASTGEN_MEMBERS_DfgVarPacked;
bool isDrivenFullyByDfg() const {
return arity() == 1 && source(0)->dtypep() == dtypep() && !varp()->isForced();
DfgSplicePacked(DfgGraph& dfg, FileLine* flp, AstNodeDType* dtypep)
: DfgVertexSplice{dfg, dfgType(), flp, dtypep} {
UASSERT_OBJ(!VN_IS(dtypep, UnpackArrayDType), flp, "Array DfgSplicePacked");
}
ASTGEN_MEMBERS_DfgSplicePacked;
void addDriver(FileLine* flp, uint32_t lsb, DfgVertex* vtxp) {
m_driverData.emplace_back(flp, lsb);
@ -265,33 +295,10 @@ public:
DfgVertexVariadic::resetSources();
}
// Remove undriven sources
void packSources() {
// Grab and reset the driver data
std::vector<DriverData> driverData;
driverData.swap(m_driverData);
// Grab and unlink the sources
std::vector<DfgVertex*> sources{arity()};
forEachSourceEdge([&](DfgEdge& edge, size_t idx) {
sources[idx] = edge.sourcep();
edge.unlinkSource();
});
DfgVertexVariadic::resetSources();
// Add back the driven sources
for (size_t i = 0; i < sources.size(); ++i) {
if (!sources[i]) continue;
addDriver(driverData[i].first, driverData[i].second, sources[i]);
}
}
FileLine* driverFileLine(size_t idx) const { return m_driverData[idx].first; }
uint32_t driverLsb(size_t idx) const { return m_driverData[idx].second; }
const string srcName(size_t idx) const override {
return isDrivenFullyByDfg() ? "" : cvtToStr(driverLsb(idx));
}
const std::string srcName(size_t idx) const override { return std::to_string(driverLsb(idx)); }
};
#endif

View File

@ -181,7 +181,7 @@ void EmitCBaseVisitorConst::emitCFuncDecl(const AstCFunc* funcp, const AstNodeMo
void EmitCBaseVisitorConst::emitVarDecl(const AstVar* nodep, bool asRef) {
const AstBasicDType* const basicp = nodep->basicp();
bool refNeedParens = VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType);
const bool refNeedParens = VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType);
const auto emitDeclArrayBrackets = [this](const AstVar* nodep) -> void {
// This isn't very robust and may need cleanup for other data types

View File

@ -261,33 +261,57 @@ public:
if (const AstCNew* const cnewp = getSuperNewCallRecursep(nodep->nextp())) return cnewp;
return nullptr;
}
void putConstructorSubinit(const AstClass* classp, AstCFunc* cfuncp, bool top,
std::set<AstClass*>& doneClassesr) {
void putConstructorSubinit(const AstClass* classp, AstCFunc* cfuncp) {
// Virtual bases in depth-first left-to-right order
std::vector<AstClass*> virtualBases;
std::unordered_set<AstClass*> doneClasses;
collectVirtualBasesRecursep(classp, virtualBases);
for (AstClass* vbase : virtualBases) {
if (doneClasses.count(vbase)) continue;
puts(doneClasses.empty() ? "" : "\n , ");
doneClasses.emplace(vbase);
puts(prefixNameProtect(vbase));
if (constructorNeedsProcess(vbase)) {
puts("(vlProcess, vlSymsp)");
} else {
puts("(vlSymsp)");
}
}
const AstCNew* const superNewCallp = getSuperNewCallRecursep(cfuncp->stmtsp());
// Direct non-virtual bases in declaration order
for (const AstClassExtends* extp = classp->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) {
if (extp->classp()->useVirtualPublic()) {
// It's a c++ virtual class (diamond relation)
// Must get the subclasses initialized first
putConstructorSubinit(extp->classp(), cfuncp, false, doneClassesr);
}
// Diamond pattern with same base class twice?
if (doneClassesr.find(extp->classp()) != doneClassesr.end()) continue;
puts(doneClassesr.empty() ? "" : "\n , ");
doneClassesr.emplace(extp->classp());
if (extp->classp()->useVirtualPublic()) continue;
if (doneClasses.count(extp->classp())) continue;
puts(doneClasses.empty() ? "" : "\n , ");
doneClasses.emplace(extp->classp());
puts(prefixNameProtect(extp->classp()));
if (constructorNeedsProcess(extp->classp())) {
puts("(vlProcess, vlSymsp");
} else {
puts("(vlSymsp");
}
if (top) {
const AstCNew* const superNewCallp = getSuperNewCallRecursep(cfuncp->stmtsp());
UASSERT_OBJ(superNewCallp, cfuncp, "super.new call not found");
// Handle super.new() args for the concrete parent
if (!extp->classp()->isInterfaceClass() && superNewCallp) {
putCommaIterateNext(superNewCallp->argsp(), true);
}
puts(")");
top = false;
}
}
void collectVirtualBasesRecursep(const AstClass* classp,
std::vector<AstClass*>& virtualBases) {
std::set<const AstClass*> visited;
collectVirtualBasesRecursep(classp, virtualBases /*ref*/, visited /*ref*/);
}
void collectVirtualBasesRecursep(const AstClass* classp, std::vector<AstClass*>& virtualBases,
std::set<const AstClass*>& visited) {
if (visited.count(classp)) return;
visited.emplace(classp);
for (const AstClassExtends* extp = classp->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) {
// Depth-first: recurse into this base first
collectVirtualBasesRecursep(extp->classp(), virtualBases, visited);
if (extp->classp()->useVirtualPublic()) { virtualBases.push_back(extp->classp()); }
}
}
@ -314,8 +338,7 @@ public:
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
if (nodep->isConstructor() && classp && classp->extendsp()) {
puts("\n : ");
std::set<AstClass*> doneClasses;
putConstructorSubinit(classp, nodep, true, doneClasses /*ref*/);
putConstructorSubinit(classp, nodep);
}
}
puts(" {\n");
@ -639,41 +662,58 @@ public:
iterateChildrenConst(nodep);
}
void visit(AstCoverDecl* nodep) override {
putns(nodep, "vlSelf->__vlCoverInsert("); // As Declared in emitCoverageDecl
puts("&(vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->dataDeclThisp()->binNum()));
puts("])");
// If this isn't the first instantiation of this module under this
// design, don't really count the bucket, and rely on verilator_cov to
// aggregate counts. This is because Verilator combines all
// hierarchies itself, and if verilator_cov also did it, you'd end up
// with (number-of-instant) times too many counts in this bin.
puts(", first"); // Enable, passed from __Vconfigure parameter
puts(", ");
putsQuoted(protect(nodep->fileline()->filename()));
puts(", ");
puts(cvtToStr(nodep->fileline()->lineno()));
puts(", ");
puts(cvtToStr(nodep->offset() + nodep->fileline()->firstColumn()));
puts(", ");
putsQuoted((!nodep->hier().empty() ? "." : "")
+ protectWordsIf(nodep->hier(), nodep->protect()));
puts(", ");
putsQuoted(protectWordsIf(nodep->page(), nodep->protect()));
puts(", ");
putsQuoted(protectWordsIf(nodep->comment(), nodep->protect()));
puts(", ");
putsQuoted(nodep->linescov());
puts(");\n");
std::vector<string> pointSuffixes;
if (nodep->isToggle()) {
// Changes 0 -> 1 and 1 -> 0 have separate counters
pointSuffixes = {"_0", "_1"};
} else {
pointSuffixes = {""};
}
for (size_t i = 0; i < pointSuffixes.size(); i++) {
putns(nodep, "vlSelf->__vlCoverInsert("); // As Declared in emitCoverageDecl
puts("&(vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->dataDeclThisp()->binNum() + i));
puts("])");
// If this isn't the first instantiation of this module under this
// design, don't really count the bucket, and rely on verilator_cov to
// aggregate counts. This is because Verilator combines all
// hierarchies itself, and if verilator_cov also did it, you'd end up
// with (number-of-instant) times too many counts in this bin.
puts(", first"); // Enable, passed from __Vconfigure parameter
puts(", ");
putsQuoted(protect(nodep->fileline()->filename()));
puts(", ");
puts(cvtToStr(nodep->fileline()->lineno()));
puts(", ");
puts(cvtToStr(nodep->offset() + nodep->fileline()->firstColumn()));
puts(", ");
putsQuoted((!nodep->hier().empty() ? "." : "")
+ protectWordsIf(nodep->hier(), nodep->protect()));
puts(", ");
putsQuoted(protectWordsIf(nodep->page(), nodep->protect()));
puts(", ");
putsQuoted(protectWordsIf(nodep->comment() + pointSuffixes[i], nodep->protect()));
puts(", ");
putsQuoted(nodep->linescov());
puts(");\n");
}
}
void visit(AstCoverInc* nodep) override {
if (v3Global.opt.threads() > 1) {
putns(nodep, "vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum()));
if (nodep->toggleExprp()) {
puts(" + ");
iterateConst(nodep->toggleExprp());
}
puts("].fetch_add(1, std::memory_order_relaxed);\n");
} else {
putns(nodep, "++(vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum()));
if (nodep->toggleExprp()) {
puts(" + ");
iterateConst(nodep->toggleExprp());
}
puts("]);\n");
}
}

View File

@ -109,7 +109,8 @@ class EmitCHeader final : public EmitCConstInit {
// Emit variables in consecutive anon and non-anon batches
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isIO() || varp->isSignal() || varp->isClassMember() || varp->isTemp()) {
if (varp->isIO() || varp->isSignal() || varp->isClassMember() || varp->isTemp()
|| varp->isGenVar()) {
const bool anon = isAnonOk(varp);
if (anon != lastAnon) emitCurrentList();
lastAnon = anon;
@ -563,16 +564,20 @@ class EmitCHeader final : public EmitCConstInit {
if (!VN_IS(modp, Class)) puts("alignas(VL_CACHE_LINE_BYTES) ");
puts(prefixNameProtect(modp));
if (const AstClass* const classp = VN_CAST(modp, Class)) {
const string virtpub = classp->useVirtualPublic() ? "virtual public " : "public ";
puts(" : " + virtpub);
puts(" : ");
if (classp->extendsp()) {
bool needComma = false;
for (const AstClassExtends* extp = classp->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) {
if (needComma) puts(", ");
// Use virtual only for interfaces for class inheritance
// (extends)
puts(extp->classp()->useVirtualPublic() ? "virtual public " : "public ");
putns(extp, prefixNameProtect(extp->classp()));
if (extp->nextp()) puts(", " + virtpub);
needComma = true;
}
} else {
puts("VlClass");
puts("public virtual VlClass");
}
} else {
puts(" final : public VerilatedModule");

View File

@ -380,6 +380,11 @@ class EmitCSyms final : EmitCBaseVisitorConst {
// Assign numbers to all bins, so we know how big of an array to use
if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for
nodep->binNum(m_coverBins++);
if (nodep->isToggle()) {
// Toggle coverage coverpoint requires additional counter, because
// changes of values 0 -> 1 and 1 -> 0 are counted separately.
m_coverBins++;
}
}
}
void visit(AstCFunc* nodep) override {
@ -743,13 +748,13 @@ void EmitCSyms::emitSymImp() {
if (!optSystemC()) {
puts("\nvoid " + symClassName() + "::_traceDump() {\n");
// Caller checked for __Vm_dumperp non-nullptr
puts("const VerilatedLockGuard lock(__Vm_dumperMutex);\n");
puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n");
puts("__Vm_dumperp->dump(VL_TIME_Q());\n");
puts("}\n");
}
puts("\nvoid " + symClassName() + "::_traceDumpOpen() {\n");
puts("const VerilatedLockGuard lock(__Vm_dumperMutex);\n");
puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n");
puts("if (VL_UNLIKELY(!__Vm_dumperp)) {\n");
puts("__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n");
puts("__Vm_modelp->trace(__Vm_dumperp, 0, 0);\n");
@ -760,7 +765,7 @@ void EmitCSyms::emitSymImp() {
puts("}\n");
puts("\nvoid " + symClassName() + "::_traceDumpClose() {\n");
puts("const VerilatedLockGuard lock(__Vm_dumperMutex);\n");
puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n");
puts("__Vm_dumping = false;\n");
puts("VL_DO_CLEAR(delete __Vm_dumperp, __Vm_dumperp = nullptr);\n");
puts("}\n");

View File

@ -922,6 +922,20 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
m_sensesp = nodep->sensesp();
iterateAndNextConstNull(nodep->stmtsp());
}
void visit(AstDelay* nodep) override {
puts(""); // this is for proper alignment
puts("#");
iterateConst(nodep->lhsp());
puts(";\n");
iterateAndNextConstNull(nodep->stmtsp());
}
void visit(AstCAwait* nodep) override {
AstCMethodHard* methodp = VN_CAST(nodep->exprp(), CMethodHard);
UASSERT_OBJ(methodp, nodep, "AstCAwait expression must be an AstCMethodHard");
puts(""); // this is for proper alignment
puts("#");
iterateConst(methodp->pinsp());
}
void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); }
void visit(AstNodeText*) override {}
void visit(AstVarScope*) override {}

View File

@ -99,6 +99,7 @@ public:
DEPRECATED, // Feature will be deprecated
ENCAPSULATED, // Error: local/protected violation
ENDLABEL, // End lable name mismatch
ENUMITEMWIDTH, // Error: enum item width mismatch
ENUMVALUE, // Error: enum type needs explicit cast
EOFNEWLINE, // End-of-file missing newline
GENCLK, // Generated Clock. Historical, never issued.
@ -124,6 +125,7 @@ public:
MULTIDRIVEN, // Driven from multiple blocks
MULTITOP, // Multiple top level modules
NEWERSTD, // Newer language standard required
NOEFFECT, // Statement has no effect
NOLATCH, // No latch detected in always_latch block
NONSTD, // Non-standard feature present in other sims
NULLPORT, // Null port detected in module definition
@ -144,6 +146,7 @@ public:
SELRANGE, // Selection index out of range
SHORTREAL, // Shortreal not supported
SIDEEFFECT, // Sideeffect ignored
SPECIFYIGN, // Specify construct ignored
SPLITVAR, // Cannot split the variable
STATICVAR, // Static variable declared in a loop with a declaration assignment
STMTDLY, // Delayed statement
@ -189,40 +192,33 @@ public:
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
constexpr operator en() const VL_MT_SAFE { return m_e; }
const char* ascii() const VL_MT_SAFE {
// clang-format off
static const char* const names[] = {
// Leading spaces indicate it can't be disabled.
" MIN", " INFO", " FATAL", " FATALMANY", " FATALSRC", " ERROR", " FIRST_NAMED",
// Boolean
" I_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_TIMING", " I_TRACING", " I_UNUSED",
" I_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_TIMING",
" I_TRACING", " I_UNUSED",
// Errors
"LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR", "UNSUPPORTED",
// Warnings
" EC_FIRST_WARN",
"ALWCOMBORDER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA", "BADVLTPRAGMA",
"BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA",
"CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG", "COVERIGN",
"DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED",
"ENCAPSULATED", "ENDLABEL", "ENUMVALUE", "EOFNEWLINE", "GENCLK",
"GENUNNAMED", "HIERBLOCK",
"IFDEPTH", "IGNOREDRETURN",
"IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
"LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING",
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOLATCH", "NONSTD", "NULLPORT", "PINCONNECTEMPTY",
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE",
"PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY",
"SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPLITVAR",
"STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT", "TIMESCALEMOD",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP" ,"UNUSEDPARAM", "UNUSEDSIGNAL",
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL",
" MAX"
};
// clang-format on
" EC_FIRST_WARN", "ALWCOMBORDER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA",
"BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE", "CASEINCOMPLETE",
"CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA", "CMPCONST",
"COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG", "COVERIGN", "DECLFILENAME",
"DEFOVERRIDE", "DEFPARAM", "DEPRECATED", "ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH",
"ENUMVALUE", "EOFNEWLINE", "GENCLK", "GENUNNAMED", "HIERBLOCK", "IFDEPTH",
"IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE", "LATCH", "LITENDIAN",
"MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING", "MULTIDRIVEN", "MULTITOP",
"NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT", "PINCONNECTEMPTY",
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT",
"PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO",
"RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR",
"STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSIGNED",
"UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL",
"USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT",
"WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
return names[m_e];
}
// Warnings that default to off
@ -249,9 +245,9 @@ public:
bool pretendError() const VL_MT_SAFE {
return (m_e == ASSIGNIN || m_e == BADSTDPRAGMA || m_e == BADVLTPRAGMA || m_e == BLKANDNBLK
|| m_e == BLKLOOPINIT || m_e == CONTASSREG || m_e == ENCAPSULATED
|| m_e == ENDLABEL || m_e == ENUMVALUE || m_e == IMPURE || m_e == MODMISSING
|| m_e == PINNOTFOUND || m_e == PKGNODECL || m_e == PROCASSWIRE
|| m_e == ZEROREPL // Says IEEE
|| m_e == ENDLABEL || m_e == ENUMITEMWIDTH || m_e == ENUMVALUE || m_e == IMPURE
|| m_e == MODMISSING || m_e == PINNOTFOUND || m_e == PKGNODECL
|| m_e == PROCASSWIRE || m_e == ZEROREPL // Says IEEE
);
}
// Warnings to mention manual

View File

@ -369,6 +369,10 @@ public:
&& m_lastLineno == rhs.m_lastLineno && m_lastColumn == rhs.m_lastColumn
&& m_filenameno == rhs.m_filenameno && m_msgEnIdx == rhs.m_msgEnIdx);
}
bool equalFirstLineCol(const FileLine& rhs) const {
return (m_filenameno == rhs.m_filenameno && m_firstLineno == rhs.m_firstLineno
&& m_firstColumn == rhs.m_firstColumn);
}
// Returns -1 if (*this) should come before rhs after sorted. 1 for the opposite case. 0 for
// equivalent.
int operatorCompare(const FileLine& rhs) const {

View File

@ -150,9 +150,11 @@ private:
// AstVarRef::user2 -> Flag indicating not to replace reference
// AstVarScope::user3 -> AstVarScope*, a `valVscp` force component for each VarScope of
// forced RHS
// AstVarScope::user4p -> AstNodeExpr*, the RHS expression
const VNUser1InUse m_user1InUse;
const VNUser2InUse m_user2InUse;
const VNUser3InUse m_user3InUse;
const VNUser4InUse m_user4InUse;
AstUser1Allocator<AstVar, ForceComponentsVar> m_forceComponentsVar;
AstUser1Allocator<AstVarScope, ForceComponentsVarScope> m_forceComponentsVarScope;
@ -185,6 +187,12 @@ public:
ForceComponentsVarScope* tryGetForceComponents(AstVarRef* nodep) const {
return m_forceComponentsVarScope.tryGet(nodep->varScopep());
}
void setValVscpRhsExpr(AstVarScope* valVscp, AstNodeExpr* rhsExpr) {
valVscp->user4p(rhsExpr);
}
AstNodeExpr* getValVscpRhsExpr(AstVarScope* valVscp) const {
return VN_CAST(valVscp->user4p(), NodeExpr);
}
};
class ForceConvertVisitor final : public VNVisitor {
@ -233,9 +241,8 @@ class ForceConvertVisitor final : public VNVisitor {
= new AstAssign{flp, lhsp->cloneTreePure(false), rhsp->cloneTreePure(false)};
transformWritenVarScopes(setValp->lhsp(), [this, rhsp](AstVarScope* vscp) {
AstVarScope* const valVscp = m_state.getForceComponents(vscp).m_valVscp;
// TODO support multiple VarRefs on RHS
if (AstVarRef* const refp = VN_CAST(rhsp, VarRef))
ForceState::setValVscp(refp, valVscp);
m_state.setValVscpRhsExpr(valVscp, rhsp->cloneTreePure(false));
rhsp->foreach([valVscp](AstVarRef* refp) { ForceState::setValVscp(refp, valVscp); });
return valVscp;
});
@ -267,11 +274,14 @@ class ForceConvertVisitor final : public VNVisitor {
transformWritenVarScopes(resetEnp->lhsp(), [this](AstVarScope* vscp) {
return m_state.getForceComponents(vscp).m_enVscp;
});
// IEEE 1800-2023 10.6.2: If this is a net, and not a variable, then reset the read
// signal directly as well, in case something in the same process reads it later. Also, if
// it is a variable, and not a net, set the original signal to the forced value, as it
// needs to retain the forced value until the next procedural update, which might happen on
// a later eval. Luckily we can do all this in a single assignment.
// IEEE 1800-2023 10.6.2: When released, then if the variable is not driven by a continuous
// assignment and does not currently have an active procedural continuous assignment, the
// variable shall not immediately change value and shall maintain its current value until
// the next procedural assignment to the variable is executed. Releasing a variable that is
// driven by a continuous assignment or currently has an active assign procedural
// continuous assignment shall reestablish that assignment and schedule a reevaluation in
// the continuous assignment's scheduling region.
AstAssign* const resetRdp
= new AstAssign{flp, lhsp->cloneTreePure(false), lhsp->unlinkFrBack()};
// Replace write refs on the LHS
@ -376,10 +386,12 @@ class ForceReplaceVisitor final : public VNVisitor {
if (AstVarScope* const valVscp = ForceState::getValVscp(nodep)) {
FileLine* const flp = nodep->fileline();
AstVarRef* const valp = new AstVarRef{flp, valVscp, VAccess::WRITE};
AstVarRef* const rhsp = new AstVarRef{flp, nodep->varScopep(), VAccess::READ};
AstNodeExpr* rhsp = m_state.getValVscpRhsExpr(valVscp);
UASSERT_OBJ(rhsp, flp, "RHS of force/release must be an AstNodeExpr");
rhsp = rhsp->cloneTreePure(false);
ForceState::markNonReplaceable(valp);
ForceState::markNonReplaceable(rhsp);
rhsp->foreach([](AstVarRef* refp) { ForceState::markNonReplaceable(refp); });
m_stmtp->addNextHere(new AstAssign{flp, valp, rhsp});
}

View File

@ -779,14 +779,51 @@ public:
if (!foundp) baddot = dotname;
return foundp;
}
static bool checkIfClassOrPackage(const VSymEnt* const symp) {
if (VN_IS(symp->nodep(), Class) || VN_IS(symp->nodep(), Package)) return true;
const AstRefDType* refDTypep = nullptr;
if (const AstTypedef* const typedefp = VN_CAST(symp->nodep(), Typedef)) {
if (VN_IS(typedefp->childDTypep(), ClassRefDType)) return true;
if (const AstRefDType* const refp = VN_CAST(typedefp->childDTypep(), RefDType)) {
refDTypep = refp;
}
} else if (const AstParamTypeDType* const paramTypep
= VN_CAST(symp->nodep(), ParamTypeDType)) {
if (const AstRequireDType* const requireDTypep
= VN_CAST(paramTypep->childDTypep(), RequireDType)) {
if (const AstRefDType* const refp = VN_CAST(requireDTypep->lhsp(), RefDType)) {
refDTypep = refp;
} else if (VN_IS(requireDTypep->lhsp(), VoidDType)
|| VN_IS(requireDTypep->lhsp(), BasicDType)
|| VN_IS(requireDTypep->lhsp(), ClassRefDType)) {
return true;
}
}
}
// TODO: this should be handled properly - case when it is known what type is
// referenced by AstRefDType (refDTypep->typeofp() is null or
// refDTypep->classOrPackageOpp() is null)
if (refDTypep && !refDTypep->typeofp() && !refDTypep->classOrPackageOpp()) {
// When still unknown - return because it may be a class, classes may not be
// linked at this point. Return in case it gets resolved to a class in the future
return true;
}
return false;
}
VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool fallback,
bool classOnly, const string& forWhat) {
if (nodep->classOrPackageSkipp()) return getNodeSym(nodep->classOrPackageSkipp());
VSymEnt* foundp;
if (fallback) {
foundp = lookSymp->findIdFallback(nodep->name());
VSymEnt* currentLookSymp = lookSymp;
do {
foundp = currentLookSymp->findIdFlat(nodep->name());
if (foundp && !checkIfClassOrPackage(foundp)) foundp = nullptr;
if (!foundp) currentLookSymp = currentLookSymp->fallbackp();
} while (!foundp && currentLookSymp);
} else {
foundp = lookSymp->findIdFlat(nodep->name());
if (foundp && !checkIfClassOrPackage(foundp)) foundp = nullptr;
}
if (!foundp && v3Global.rootp()->stdPackagep()) { // Look under implied std::
foundp = getNodeSym(v3Global.rootp()->stdPackagep())->findIdFlat(nodep->name());
@ -2365,6 +2402,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
bool m_unresolvedClass; // Unresolved class reference, needs help from V3Param
bool m_genBlk; // Contains gen block reference
AstNode* m_unlinkedScopep; // Unresolved scope, needs corresponding VarXRef
AstDisable* m_disablep; // Disable statement under which the reference is
bool m_dotErr; // Error found in dotted resolution, ignore upwards
string m_dotText; // String of dotted names found in below parseref
DotStates() { init(nullptr); }
@ -2380,6 +2418,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
m_unresolvedClass = false;
m_genBlk = false;
m_unlinkedScopep = nullptr;
m_disablep = nullptr;
}
string ascii() const {
static const char* const names[]
@ -2646,6 +2685,46 @@ class LinkDotResolveVisitor final : public VNVisitor {
m_ds.init(m_curSymp);
iterateNull(nodep);
}
static const AstNodeDType* getElemDTypep(const AstNodeDType* dtypep) {
dtypep = dtypep->skipRefp();
while (true) {
if (const AstBracketArrayDType* const adtypep = VN_CAST(dtypep, BracketArrayDType)) {
dtypep = adtypep->childDTypep()->skipRefp();
} else if (const AstDynArrayDType* const adtypep = VN_CAST(dtypep, DynArrayDType)) {
dtypep = adtypep->childDTypep()->skipRefp();
} else if (const AstQueueDType* const adtypep = VN_CAST(dtypep, QueueDType)) {
dtypep = adtypep->childDTypep()->skipRefp();
} else {
break;
}
}
return dtypep;
}
static const AstNodeDType* getExprDTypep(const AstNodeExpr* selp) {
while (const AstNodePreSel* const sp = VN_CAST(selp, NodePreSel)) selp = sp->fromp();
if (const AstMemberSel* const sp = VN_CAST(selp, MemberSel)) {
if (const AstNodeDType* dtypep = getExprDTypep(sp->fromp())) {
if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
const AstClass* const classp = classRefp->classp();
const bool found = classp->existsMember(
[&dtypep, name = selp->name()](const AstClass*, const AstVar* nodep) {
dtypep = nodep->childDTypep();
return nodep->name() == name;
});
if (found) return getElemDTypep(dtypep);
selp->v3error("Class " << classRefp->prettyNameQ()
<< " does not contain field " << selp->prettyNameQ());
} else {
selp->v3fatalSrc("Member selection on expression of type "
<< dtypep->prettyDTypeNameQ()
<< ", which is not a class type");
}
}
} else if (const AstNodeVarRef* const varRefp = VN_CAST(selp, NodeVarRef)) {
return getElemDTypep(varRefp->varp()->childDTypep());
}
return nullptr;
}
#define LINKDOT_VISIT_START() \
VL_RESTORER(m_indent); \
@ -2762,7 +2841,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (nodep->name() == "__paramNumber1" && m_cellp
&& VN_IS(m_cellp->modp(), Primitive)) {
// Primitive parameter is really a delay we can just ignore
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
} else {
const string suggest
@ -3084,7 +3163,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
bool allowVar = false;
bool allowFTask = false;
bool staticAccess = false;
if (m_ds.m_dotPos == DP_PACKAGE) {
if (m_ds.m_disablep) {
allowScope = true;
allowFTask = true;
expectWhat = "block/task";
} else if (m_ds.m_dotPos == DP_PACKAGE) {
// {package-or-class}::{a}
AstNodeModule* classOrPackagep = nullptr;
expectWhat = "scope/variable/func";
@ -3185,7 +3268,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
}
}
if (!foundp) {
} else if (VN_IS(foundp->nodep(), Cell) || VN_IS(foundp->nodep(), Begin)
} else if (VN_IS(foundp->nodep(), Cell) || VN_IS(foundp->nodep(), NodeBlock)
|| VN_IS(foundp->nodep(), Netlist) // for $root
|| VN_IS(foundp->nodep(), Module)) { // if top
if (allowScope) {
@ -3193,8 +3276,20 @@ class LinkDotResolveVisitor final : public VNVisitor {
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
m_ds.m_dotSymp = foundp;
m_ds.m_dotPos = DP_SCOPE;
if (m_ds.m_disablep && VN_IS(foundp->nodep(), NodeBlock)) {
// Possibly it is not the final link. If we are under dot and not in its
// last component, `targetp()` field will be overwritten by next components
m_ds.m_disablep->targetp(foundp->nodep());
}
if (const AstBegin* const beginp = VN_CAST(foundp->nodep(), Begin)) {
if (beginp->generate()) m_ds.m_genBlk = true;
if (beginp->generate()) {
m_ds.m_genBlk = true;
if (m_ds.m_disablep) {
m_ds.m_disablep->v3warn(
E_UNSUPPORTED,
"Unsupported: Generate block referenced by disable");
}
}
}
// Upper AstDot visitor will handle it from here
} else if (VN_IS(foundp->nodep(), Cell) && allowVar) {
@ -3231,7 +3326,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
taskrefp = new AstFuncRef{nodep->fileline(), nodep->name(), nullptr};
}
nodep->replaceWith(taskrefp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
m_ds = lastStates;
return;
} else if (AstVar* const varp = foundToVarp(foundp, nodep, VAccess::READ)) {
@ -3438,7 +3533,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
m_ds.m_dotPos = DP_MEMBER;
} else {
// Cells/interfaces can't be implicit
const bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText == "" && !foundp);
const bool checkImplicit
= (!m_ds.m_dotp && m_ds.m_dotText == "" && !m_ds.m_disablep && !foundp);
const bool err
= !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name()));
if (err) {
@ -3665,7 +3761,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
AstVarRef* const newrefp
= new AstVarRef{nodep->fileline(), nodep->varp(), nodep->access()};
nodep->replaceWith(newrefp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
}
@ -3693,7 +3789,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
AstVarRef* const newvscp
= new AstVarRef{nodep->fileline(), vscp, nodep->access()};
nodep->replaceWith(newvscp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
UINFO(9, indent() << "new " << newvscp); // Also prints taskp
}
}
@ -3727,17 +3823,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (!fromDtp) {
if (const AstNodeVarRef* const varRefp = VN_CAST(nodep->fromp(), NodeVarRef)) {
fromDtp = varRefp->varp()->subDTypep();
} else if (const AstNodeSel* const selp = VN_CAST(nodep->fromp(), NodeSel)) {
if (const AstNodeVarRef* const varRefp
= VN_CAST(selp->fromp(), NodeVarRef)) {
fromDtp = varRefp->varp()->dtypeSkipRefp()->subDTypep();
}
} else if (const AstNodePreSel* const selp
= VN_CAST(nodep->fromp(), NodePreSel)) {
if (const AstNodeVarRef* const varRefp
= VN_CAST(selp->fromp(), NodeVarRef)) {
fromDtp = varRefp->varp()->dtypeSkipRefp()->subDTypep();
}
} else {
fromDtp = getExprDTypep(nodep->fromp());
}
if (!fromDtp) {
if (VN_IS(nodep->pinsp(), With)) {
@ -3845,7 +3932,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
// HERE function() . method_called_on_function_return_value()
m_ds.m_dotPos = DP_MEMBER;
m_ds.m_dotText = "";
} else {
} else if (!m_ds.m_disablep) {
// visit(AstDisable*) setup the dot handling
checkNoDot(nodep);
}
if (nodep->classOrPackagep() && nodep->taskp()) {
@ -3983,7 +4071,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
AstNode* addp = pinp;
if (AstArg* const argp = VN_CAST(pinp, Arg)) {
addp = argp->exprp()->unlinkFrBack();
VL_DO_DANGLING(pinp->deleteTree(), pinp);
VL_DO_DANGLING(pushDeletep(pinp), pinp);
}
outp = AstNode::addNext(outp, addp);
}
@ -3991,7 +4079,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
newp->dtypep(nodep->dtypep());
}
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
} else {
VSpellCheck speller;
@ -4213,6 +4301,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (nodep->classOrNullp()) return;
LINKDOT_VISIT_START();
if (m_statep->forPrimary()) {
if (nodep->childDTypep()) return;
AstNode* cprp = nodep->classOrPkgsp();
VSymEnt* lookSymp = m_curSymp;
if (AstDot* const dotp = VN_CAST(cprp, Dot)) {
@ -4419,6 +4508,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp());
if (!VN_IS(nodep->classOrPackagep(), Class)
&& !VN_IS(nodep->classOrPackagep(), Package)) {
if (m_statep->forPrimary()) {
// It may be a type that comes from parameter class that is not
// instantioned yet
iterate(cpackagep);
return;
}
// Likely impossible, as error thrown earlier
cpackagerefp->v3error( // LCOV_EXCL_LINE
"'::' expected to reference a class/package but referenced '"
@ -4431,7 +4526,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
cpackagep->v3warn(E_UNSUPPORTED,
"Unsupported: Multiple '::' package/class reference");
}
VL_DO_DANGLING(cpackagep->unlinkFrBack()->deleteTree(), cpackagep);
VL_DO_DANGLING(pushDeletep(cpackagep->unlinkFrBack()), cpackagep);
}
if (m_ds.m_dotp && (m_ds.m_dotPos == DP_PACKAGE || m_ds.m_dotPos == DP_SCOPE)) {
UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
@ -4476,7 +4571,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
= new AstClassRefDType{nodep->fileline(), defp, paramsp};
newp->classOrPackagep(foundp->classOrPackagep());
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
} else if (m_insideClassExtParam) {
return;
@ -4508,25 +4603,49 @@ class LinkDotResolveVisitor final : public VNVisitor {
taskp->dpiExport(true);
if (nodep->cname() != "") taskp->cname(nodep->cname());
}
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
void visit(AstDisable* nodep) override {
LINKDOT_VISIT_START();
checkNoDot(nodep);
VL_RESTORER(m_ds);
m_ds.init(m_curSymp);
m_ds.m_dotPos = DP_FIRST;
m_ds.m_disablep = nodep;
iterateChildren(nodep);
if (nodep->targetRefp()) {
if (AstTaskRef* const taskRefp = VN_CAST(nodep->targetRefp(), TaskRef)) {
nodep->targetp(taskRefp->taskp());
} else if (!VN_IS(nodep->targetRefp(), ParseRef)) {
// If it is a ParseRef, either it couldn't be linked or it is linked to a block
nodep->v3warn(E_UNSUPPORTED, "Node of type "
<< nodep->targetRefp()->prettyTypeName()
<< " referenced by disable");
pushDeletep(nodep->unlinkFrBack());
}
if (nodep->targetp()) {
// If the target is already linked, there is no need to store reference as child
VL_DO_DANGLING(nodep->targetRefp()->unlinkFrBack()->deleteTree(), nodep);
}
}
}
void visit(AstPackageImport* nodep) override {
// No longer needed
LINKDOT_VISIT_START();
checkNoDot(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
void visit(AstPackageExport* nodep) override {
// No longer needed
LINKDOT_VISIT_START();
checkNoDot(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
void visit(AstPackageExportStarStar* nodep) override {
// No longer needed
LINKDOT_VISIT_START();
checkNoDot(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
void visit(AstCellRef* nodep) override {
LINKDOT_VISIT_START();
@ -4648,7 +4767,7 @@ void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
state.computeIfaceVarSyms();
state.computeScopeAliases();
state.dumpSelf();
{ LinkDotResolveVisitor{rootp, &state}; }
LinkDotResolveVisitor visitor{rootp, &state};
state.dumpSelf();
}

View File

@ -35,6 +35,7 @@
#include "V3AstUserAllocator.h"
#include "V3Error.h"
#include "V3UniqueNames.h"
#include <vector>
@ -60,6 +61,8 @@ class LinkJumpVisitor final : public VNVisitor {
int m_modRepeatNum = 0; // Repeat counter
VOptionBool m_unrollFull; // Pragma full, disable, or default unrolling
std::vector<AstNodeBlock*> m_blockStack; // All begin blocks above current node
V3UniqueNames m_queueNames{
"__VprocessQueue"}; // Names for queues needed for 'disable' handling
// METHODS
AstJumpLabel* findAddLabel(AstNode* nodep, bool endOfIter) {
@ -159,6 +162,79 @@ class LinkJumpVisitor final : public VNVisitor {
if (AstNode* const refp = nodep->op4p()) addPrefixToBlocksRecurse(prefix, refp);
if (AstNode* const refp = nodep->nextp()) addPrefixToBlocksRecurse(prefix, refp);
}
static AstNode* getMemberp(const AstNodeModule* const nodep, const std::string& name) {
for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) {
if (itemp->name() == name) return itemp;
}
return nullptr;
}
bool existsBlockAbove(const std::string& name) const {
for (const AstNodeBlock* const stackp : vlstd::reverse_view(m_blockStack)) {
if (stackp->name() == name) return true;
}
return false;
}
static AstStmtExpr* getQueuePushProcessSelfp(AstVarRef* const queueRefp) {
// Constructs queue.push_back(std::process::self()) statement
FileLine* const fl = queueRefp->fileline();
AstClass* const processClassp
= VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class);
AstFunc* const selfMethodp = VN_AS(getMemberp(processClassp, "self"), Func);
AstFuncRef* const processSelfp = new AstFuncRef{fl, selfMethodp, nullptr};
processSelfp->classOrPackagep(processClassp);
return new AstStmtExpr{
fl, new AstMethodCall{fl, queueRefp, "push_back", new AstArg{fl, "", processSelfp}}};
}
void handleDisableOnFork(AstDisable* const nodep, const std::vector<AstBegin*>& forks) {
// The support is limited only to disabling a fork from outside that fork.
// It utilizes the process::kill()` method. For each `disable` a queue of processes is
// declared. At the beginning of each fork that can be disabled, its process handle is
// pushed to the queue. `disable` statement is replaced with calling `kill()` method on
// each element of the queue.
FileLine* const fl = nodep->fileline();
const std::string targetName = nodep->targetp()->name();
if (existsBlockAbove(targetName)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from within same fork");
}
if (m_ftaskp) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from task / function");
}
AstPackage* const topPkgp = v3Global.rootp()->dollarUnitPkgAddp();
AstClass* const processClassp
= VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class);
// Declare queue of processes (as a global variable for simplicity)
AstVar* const processQueuep = new AstVar{
fl, VVarType::VAR, m_queueNames.get(targetName), VFlagChildDType{},
new AstQueueDType{fl, VFlagChildDType{},
new AstClassRefDType{fl, processClassp, nullptr}, nullptr}};
processQueuep->lifetime(VLifetime::STATIC);
topPkgp->addStmtsp(processQueuep);
AstVarRef* const queueWriteRefp
= new AstVarRef{fl, topPkgp, processQueuep, VAccess::WRITE};
AstStmtExpr* pushCurrentProcessp = getQueuePushProcessSelfp(queueWriteRefp);
for (AstBegin* const beginp : forks) {
if (pushCurrentProcessp->backp()) {
pushCurrentProcessp = pushCurrentProcessp->cloneTree(false);
}
if (beginp->stmtsp()) {
// There is no need to add it to empty block
beginp->stmtsp()->addHereThisAsNext(pushCurrentProcessp);
}
}
AstVarRef* const queueRefp = new AstVarRef{fl, topPkgp, processQueuep, VAccess::READWRITE};
AstTaskRef* const killQueueCall
= new AstTaskRef{fl, VN_AS(getMemberp(processClassp, "killQueue"), Task),
new AstArg{fl, "", queueRefp}};
killQueueCall->classOrPackagep(processClassp);
nodep->addNextHere(new AstStmtExpr{fl, killQueueCall});
}
static bool directlyUnderFork(const AstNode* const nodep) {
if (nodep->backp()->nextp() == nodep) return directlyUnderFork(nodep->backp());
if (VN_IS(nodep->backp(), Fork)) return true;
return false;
}
// VISITORS
void visit(AstNodeModule* nodep) override {
@ -337,33 +413,52 @@ class LinkJumpVisitor final : public VNVisitor {
}
void visit(AstDisable* nodep) override {
UINFO(8, " DISABLE " << nodep);
iterateChildren(nodep);
AstNodeBlock* blockp = nullptr;
for (AstNodeBlock* const stackp : vlstd::reverse_view(m_blockStack)) {
UINFO(9, " UNDERBLK " << stackp);
if (stackp->name() == nodep->name()) {
blockp = stackp;
break;
AstNode* const targetp = nodep->targetp();
FileLine* const fl = nodep->fileline();
UASSERT_OBJ(targetp, nodep, "Unlinked disable statement");
if (VN_IS(targetp, Task)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling task by name");
} else if (AstFork* const forkp = VN_CAST(targetp, Fork)) {
std::vector<AstBegin*> forks;
for (AstNode* forkItemp = forkp->stmtsp(); forkItemp; forkItemp = forkItemp->nextp()) {
// Further handling of disable stmt requires all forks to be begin blocks
AstBegin* beginp = VN_CAST(forkItemp, Begin);
if (!beginp) {
beginp = new AstBegin{fl, "", nullptr};
forkItemp->replaceWith(beginp);
beginp->addStmtsp(forkItemp);
// In order to continue the iteration
forkItemp = beginp;
}
forks.push_back(beginp);
}
}
// if (debug() >= 9) { UINFO(0, "\n"); blockp->dumpTree("- labeli: "); }
if (!blockp) {
nodep->v3warn(E_UNSUPPORTED,
"disable isn't underneath a begin with name: " << nodep->prettyNameQ());
} else if (AstBegin* const beginp = VN_CAST(blockp, Begin)) {
if (beginp->user3()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling block that contains a fork");
handleDisableOnFork(nodep, forks);
} else if (AstBegin* const beginp = VN_CAST(targetp, Begin)) {
if (directlyUnderFork(beginp)) {
std::vector<AstBegin*> forks{beginp};
handleDisableOnFork(nodep, forks);
} else {
// Jump to the end of the named block
AstJumpLabel* const labelp = findAddLabel(beginp, false);
nodep->addNextHere(new AstJumpGo{nodep->fileline(), labelp});
const std::string targetName = beginp->name();
if (existsBlockAbove(targetName)) {
if (beginp->user3()) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: disabling block that contains a fork");
} else {
// Jump to the end of the named block
AstJumpLabel* const labelp = findAddLabel(beginp, false);
nodep->addNextHere(new AstJumpGo{nodep->fileline(), labelp});
}
} else {
nodep->v3warn(E_UNSUPPORTED, "disable isn't underneath a begin with name: '"
<< targetName << "'");
}
}
} else {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork by name");
nodep->v3fatalSrc("Disable linked with node of unhandled type "
<< targetp->prettyTypeName());
}
nodep->unlinkFrBack();
VL_DO_DANGLING(pushDeletep(nodep), nodep);
// if (debug() >= 9) { UINFO(0, "\n"); beginp->dumpTree("- labelo: "); }
}
void visit(AstVarRef* nodep) override {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);

View File

@ -267,16 +267,17 @@ class LinkParseVisitor final : public VNVisitor {
const int left = nodep->rangep()->leftConst();
const int right = nodep->rangep()->rightConst();
const int increment = (left > right) ? -1 : 1;
int offset_from_init = 0;
uint32_t offset_from_init = 0;
AstEnumItem* addp = nullptr;
FileLine* const flp = nodep->fileline();
for (int i = left; i != (right + increment); i += increment, offset_from_init++) {
for (int i = left; i != (right + increment); i += increment, ++offset_from_init) {
const string name = nodep->name() + cvtToStr(i);
AstNodeExpr* valuep = nullptr;
if (nodep->valuep()) {
// V3Width looks for Adds with same fileline as the EnumItem
valuep
= new AstAdd{flp, nodep->valuep()->cloneTree(true),
new AstConst(flp, AstConst::Unsized32{}, offset_from_init)};
new AstConst{flp, AstConst::Unsized32{}, offset_from_init}};
}
addp = AstNode::addNext(addp, new AstEnumItem{flp, name, nullptr, valuep});
}
@ -577,7 +578,7 @@ class LinkParseVisitor final : public VNVisitor {
} else if (VN_IS(bracketp, SelLoopVars)) {
// Ok
} else {
nodep->v3error("Syntax error; foreach missing bracketed loop variable"
nodep->v3error("Foreach missing bracketed loop variable is no-operation"
" (IEEE 1800-2023 12.7.3)");
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;

View File

@ -1188,7 +1188,7 @@ uint32_t V3Number::countOnes() const {
uint32_t V3Number::mostSetBitP1() const {
for (int bit = width() - 1; bit >= 0; bit--) {
if (bitIs1(bit)) return bit + 1;
if (!bitIs0(bit)) return bit + 1;
}
return 0;
}

View File

@ -1336,6 +1336,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
m_fDfgPostInline = flag;
m_fDfgScoped = flag;
});
DECL_OPTION("-fdfg-break-cycles", FOnOff, &m_fDfgBreakCycles);
DECL_OPTION("-fdfg-peephole", FOnOff, &m_fDfgPeephole);
DECL_OPTION("-fdfg-peephole-", CbPartialMatch, [this](const char* optp) { //
m_fDfgPeepholeDisabled.erase(optp);
@ -1802,8 +1803,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-Wwarn-UNSUPPORTED", CbCall, []() {
FileLine::globalWarnOff(V3ErrorCode::E_UNSUPPORTED, false);
FileLine::globalWarnOff(V3ErrorCode::COVERIGN, false);
FileLine::globalWarnOff(V3ErrorCode::SPECIFYIGN, false);
V3Error::pretendError(V3ErrorCode::E_UNSUPPORTED, false);
V3Error::pretendError(V3ErrorCode::COVERIGN, false);
V3Error::pretendError(V3ErrorCode::SPECIFYIGN, false);
});
DECL_OPTION("-Wwarn-WIDTH", CbCall, []() {
FileLine::globalWarnOff(V3ErrorCode::WIDTH, false);

View File

@ -420,6 +420,7 @@ private:
bool m_fConstBitOpTree; // main switch: -fno-const-bit-op-tree constant bit op tree
bool m_fConstEager = true; // main switch: -fno-const-eagerly run V3Const during passes
bool m_fDedupe; // main switch: -fno-dedupe: logic deduplication
bool m_fDfgBreakCycles = true; // main switch: -fno-dfg-break-cycles
bool m_fDfgPeephole = true; // main switch: -fno-dfg-peephole
bool m_fDfgPreInline; // main switch: -fno-dfg-pre-inline and -fno-dfg
bool m_fDfgPostInline; // main switch: -fno-dfg-post-inline and -fno-dfg
@ -735,6 +736,7 @@ public:
bool fConstBitOpTree() const { return m_fConstBitOpTree; }
bool fConstEager() const { return m_fConstEager; }
bool fDedupe() const { return m_fDedupe; }
bool fDfgBreakCyckes() const { return m_fDfgBreakCycles; }
bool fDfgPeephole() const { return m_fDfgPeephole; }
bool fDfgPreInline() const { return m_fDfgPreInline; }
bool fDfgPostInline() const { return m_fDfgPostInline; }

View File

@ -293,12 +293,12 @@ public:
void dumpInputsFile() VL_MT_DISABLED;
void dumpTokensAhead(int line) VL_MT_DISABLED;
static void candidatePli(VSpellCheck* spellerp) VL_MT_DISABLED;
void importIfInStd(FileLine* fileline, const string& id);
private:
void preprocDumps(std::ostream& os);
void lexFile(const string& modname) VL_MT_DISABLED;
void yylexReadTok() VL_MT_DISABLED;
void importIfInStd(FileLine* fileline, const string& id);
void tokenPull() VL_MT_DISABLED;
void tokenPipeline() VL_MT_DISABLED; // Internal; called from tokenToBison
int tokenPipelineId(int token) VL_MT_DISABLED;

View File

@ -2198,14 +2198,14 @@ class RandomizeVisitor final : public VNVisitor {
AstClass* classp = nullptr;
if (AstMethodCall* const callp = VN_CAST(nodep, MethodCall)) {
UASSERT_OBJ(callp->fromp()->dtypep(), callp->fromp(), "Object dtype is not linked");
AstClassRefDType* const classrefdtypep
= VN_CAST(callp->fromp()->dtypep(), ClassRefDType);
if (!classrefdtypep) {
nodep->v3warn(E_UNSUPPORTED,
"Inline constraints are not supported for this node type");
return;
}
const AstNodeDType* const fromDTypep = callp->fromp()->dtypep();
UASSERT_OBJ(fromDTypep, callp->fromp(), "Object dtype is not linked");
const AstClassRefDType* const classrefdtypep
= VN_CAST(fromDTypep->skipRefp(), ClassRefDType);
UASSERT_OBJ(classrefdtypep, callp->fromp(),
"Randomize called on expression of non-class type "
<< fromDTypep->skipRefp()->prettyDTypeNameQ()
<< " (it should be detected earlier)");
classp = classrefdtypep->classp();
UASSERT_OBJ(classp, classrefdtypep, "Class type is unlinked to its ref type");
} else {

View File

@ -104,6 +104,17 @@ void invertAndMergeSenTreeMap(
for (const auto& pair : senTreeMap) result.emplace(pair.second, pair.first);
}
AstSenTree* findTriggeredIface(const AstVarScope* vscp,
const VirtIfaceTriggers::IfaceSensMap& vifTrigged,
const VirtIfaceTriggers::IfaceMemberSensMap& vifMemberTriggered) {
const auto ifaceIt = vifTrigged.find(vscp->varp()->sensIfacep());
if (ifaceIt != vifTrigged.end()) return ifaceIt->second;
for (const auto& memberIt : vifMemberTriggered) {
if (memberIt.first.m_ifacep == vscp->varp()->sensIfacep()) { return memberIt.second; }
}
return nullptr;
}
//============================================================================
// Code generation utility functions
@ -955,8 +966,10 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
AstSenTree* const dpiExportTriggered
= dpiExportTriggerVscp ? createTriggerSenTree(netlistp, trig.m_vscp, dpiExportTriggerIndex)
: nullptr;
const auto& vifTriggered
const auto& vifTriggeredIco
= virtIfaceTriggers.makeIfaceToSensMap(netlistp, firstVifTriggerIndex, trig.m_vscp);
const auto& vifMemberTriggeredIco
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifTriggerIndex, trig.m_vscp);
// Create and Order the body function
AstCFunc* const icoFuncp
@ -968,8 +981,9 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
}
if (varp->isWrittenByDpi()) out.push_back(dpiExportTriggered);
if (vscp->varp()->sensIfacep()) {
const auto it = vifTriggered.find(vscp->varp()->sensIfacep());
if (it != vifTriggered.end()) out.push_back(it->second);
AstSenTree* ifaceTriggered = findTriggeredIface(
vscp, vifTriggeredIco, vifMemberTriggeredIco);
out.push_back(ifaceTriggered);
}
});
splitCheck(icoFuncp);
@ -1189,6 +1203,18 @@ VirtIfaceTriggers::makeIfaceToSensMap(AstNetlist* const netlistp, size_t vifTrig
return ifaceToSensMap;
}
VirtIfaceTriggers::IfaceMemberSensMap
VirtIfaceTriggers::makeMemberToSensMap(AstNetlist* const netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const {
IfaceMemberSensMap memberToSensMap;
for (const auto& p : m_memberTriggers) {
memberToSensMap.emplace(
std::make_pair(p.first, createTriggerSenTree(netlistp, trigVscp, vifTriggerIndex)));
++vifTriggerIndex;
}
return memberToSensMap;
}
//============================================================================
// Top level entry-point to scheduling
@ -1359,6 +1385,8 @@ void schedule(AstNetlist* netlistp) {
const auto& vifTriggeredAct
= virtIfaceTriggers.makeIfaceToSensMap(netlistp, firstVifTriggerIndex, actTrig.m_vscp);
const auto& vifMemberTriggeredAct
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifTriggerIndex, actTrig.m_vscp);
AstCFunc* const actFuncp = V3Order::order(
netlistp, {&logicRegions.m_pre, &logicRegions.m_act, &logicReplicas.m_act}, trigToSenAct,
@ -1367,8 +1395,9 @@ void schedule(AstNetlist* netlistp) {
if (it != actTimingDomains.end()) out = it->second;
if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggeredAct);
if (vscp->varp()->sensIfacep()) {
const auto sit = vifTriggeredAct.find(vscp->varp()->sensIfacep());
if (sit != vifTriggeredAct.end()) out.push_back(sit->second);
AstSenTree* ifaceTriggered
= findTriggeredIface(vscp, vifTriggeredAct, vifMemberTriggeredAct);
out.push_back(ifaceTriggered);
}
});
splitCheck(actFuncp);
@ -1396,6 +1425,8 @@ void schedule(AstNetlist* netlistp) {
: nullptr;
const auto& vifTriggered
= virtIfaceTriggers.makeIfaceToSensMap(netlistp, firstVifTriggerIndex, trigVscp);
const auto& vifMemberTriggered
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifTriggerIndex, trigVscp);
const auto& timingDomains = timingKit.remapDomains(trigMap);
AstCFunc* const funcp = V3Order::order(
@ -1405,8 +1436,9 @@ void schedule(AstNetlist* netlistp) {
if (it != timingDomains.end()) out = it->second;
if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggered);
if (vscp->varp()->sensIfacep()) {
const auto sit = vifTriggered.find(vscp->varp()->sensIfacep());
if (sit != vifTriggered.end()) out.push_back(sit->second);
AstSenTree* ifaceTriggered
= findTriggeredIface(vscp, vifTriggered, vifMemberTriggered);
out.push_back(ifaceTriggered);
}
});

View File

@ -153,17 +153,55 @@ public:
};
class VirtIfaceTriggers final {
// Represents a specific member in a virtual interface
struct IfaceMember final {
const AstIface* m_ifacep; // Interface type
const AstVar* m_memberVarp; // pointer to member field
IfaceMember(const AstIface* ifacep, const AstVar* memberVarp)
: m_ifacep(ifacep)
, m_memberVarp(memberVarp) {}
bool operator<(const IfaceMember& other) const {
if (m_ifacep != other.m_ifacep) return m_ifacep < other.m_ifacep;
return m_memberVarp < other.m_memberVarp;
}
};
public:
using IfaceMemberTrigger = std::pair<IfaceMember, AstVarScope*>;
using IfaceMemberTriggerVec = std::vector<IfaceMemberTrigger>;
using IfaceMemberSensMap = std::map<IfaceMember, AstSenTree*>;
using IfaceTrigger = std::pair<const AstIface*, AstVarScope*>;
using IfaceTriggerVec = std::vector<IfaceTrigger>;
using IfaceSensMap = std::map<const AstIface*, AstSenTree*>;
IfaceTriggerVec m_triggers;
public:
void emplace_back(IfaceTrigger&& p) { m_triggers.emplace_back(std::move(p)); }
IfaceTriggerVec::const_iterator begin() const { return m_triggers.begin(); }
IfaceTriggerVec::const_iterator end() const { return m_triggers.end(); }
IfaceMemberTriggerVec m_memberTriggers;
IfaceTriggerVec m_ifaceTriggers;
void addMemberTrigger(const AstIface* ifacep, const AstVar* memberVarp,
AstVarScope* triggerVscp) {
m_memberTriggers.emplace_back(IfaceMember(ifacep, memberVarp), triggerVscp);
}
AstVarScope* findMemberTrigger(const AstIface* ifacep, const AstVar* memberVarp) const {
IfaceMember target{ifacep, memberVarp};
for (const auto& pair : m_memberTriggers) {
if (!(pair.first < target) && !(target < pair.first)) return pair.second;
}
return nullptr;
}
IfaceMemberSensMap makeMemberToSensMap(AstNetlist* netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const;
void emplace_back(IfaceTrigger&& p) { m_ifaceTriggers.emplace_back(std::move(p)); }
IfaceTriggerVec::const_iterator begin() const { return m_ifaceTriggers.begin(); }
IfaceTriggerVec::const_iterator end() const { return m_ifaceTriggers.end(); }
IfaceSensMap makeIfaceToSensMap(AstNetlist* netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const;
VL_UNCOPYABLE(VirtIfaceTriggers);
VirtIfaceTriggers() = default;
VirtIfaceTriggers(VirtIfaceTriggers&&) = default;

View File

@ -49,12 +49,15 @@ private:
// TYPES
using OnWriteToVirtIface = std::function<void(AstVarRef*, AstIface*)>;
using OnWriteToVirtIfaceMember
= std::function<void(AstVarRef*, AstIface*, const std::string&)>;
// STATE
AstNetlist* const m_netlistp; // Root node
AstAssign* m_trigAssignp = nullptr; // Previous/current trigger assignment
AstIface* m_trigAssignIfacep = nullptr; // Interface type whose trigger is assigned
// by m_trigAssignp
AstVar* m_trigAssignMemberVarp; // Member pointer whose trigger is assigned
V3UniqueNames m_vifTriggerNames{"__VvifTrigger"}; // Unique names for virt iface
// triggers
VirtIfaceTriggers m_triggers; // Interfaces and corresponding trigger vars
@ -73,6 +76,25 @@ private:
}
});
}
// For each write across a virtual interface boundary (member-level tracking)
static void foreachWrittenVirtIfaceMember(
AstNode* const nodep, const std::function<void(AstVarRef*, AstIface*, AstVar*)>& onWrite) {
nodep->foreach([&](AstVarRef* const refp) {
if (refp->access().isReadOnly()) return;
if (AstIfaceRefDType* const dtypep = VN_CAST(refp->varp()->dtypep(), IfaceRefDType)) {
if (dtypep->isVirtual()) {
if (AstMemberSel* const memberSelp = VN_CAST(refp->firstAbovep(), MemberSel)) {
// Extract the member varp from the MemberSel node
AstVar* memberVarp = memberSelp->varp();
onWrite(refp, dtypep->ifacep(), memberVarp);
}
}
} else if (AstIface* const ifacep = refp->varp()->sensIfacep()) {
AstVar* memberVarp = refp->varp();
onWrite(refp, ifacep, memberVarp);
}
});
}
// Returns true if there is a write across a virtual interface boundary
static bool writesToVirtIface(const AstNode* const nodep) {
return nodep->exists([](const AstVarRef* const refp) {
@ -103,12 +125,31 @@ private:
return new AstVarRef{flp, VN_AS(ifacep->user1p(), VarScope), VAccess::WRITE};
}
// Create trigger reference for a specific interface member
AstVarRef* createVirtIfaceMemberTriggerRefp(FileLine* const flp, AstIface* ifacep,
const AstVar* memberVarp) {
// Check if we already have a trigger for this specific member
AstVarScope* existingTrigger = m_triggers.findMemberTrigger(ifacep, memberVarp);
if (!existingTrigger) {
AstScope* const scopeTopp = m_netlistp->topScopep()->scopep();
// Create a unique name for this member trigger
const std::string triggerName
= m_vifTriggerNames.get(ifacep) + "_Vtrigm_" + memberVarp->name();
AstVarScope* const vscp = scopeTopp->createTemp(triggerName, 1);
m_triggers.addMemberTrigger(ifacep, memberVarp, vscp);
existingTrigger = vscp;
}
return new AstVarRef{flp, existingTrigger, VAccess::WRITE};
}
// VISITORS
void visit(AstNodeProcedure* nodep) override {
VL_RESTORER(m_trigAssignp);
m_trigAssignp = nullptr;
VL_RESTORER(m_trigAssignIfacep);
m_trigAssignIfacep = nullptr;
VL_RESTORER(m_trigAssignMemberVarp);
m_trigAssignMemberVarp = nullptr;
iterateChildren(nodep);
}
void visit(AstCFunc* nodep) override {
@ -116,6 +157,8 @@ private:
m_trigAssignp = nullptr;
VL_RESTORER(m_trigAssignIfacep);
m_trigAssignIfacep = nullptr;
VL_RESTORER(m_trigAssignMemberVarp);
m_trigAssignMemberVarp = nullptr;
iterateChildren(nodep);
}
void visit(AstAssignW* nodep) override {
@ -140,11 +183,13 @@ private:
{
VL_RESTORER(m_trigAssignp);
VL_RESTORER(m_trigAssignIfacep);
VL_RESTORER(m_trigAssignMemberVarp);
iterateAndNextNull(nodep->thensp());
}
{
VL_RESTORER(m_trigAssignp);
VL_RESTORER(m_trigAssignIfacep);
VL_RESTORER(m_trigAssignMemberVarp);
iterateAndNextNull(nodep->elsesp());
}
if (v3Global.usesTiming()) {
@ -152,6 +197,7 @@ private:
// branch
m_trigAssignp = nullptr;
m_trigAssignIfacep = nullptr;
m_trigAssignMemberVarp = nullptr;
}
}
void visit(AstWhile* nodep) override {
@ -161,18 +207,21 @@ private:
{
VL_RESTORER(m_trigAssignp);
VL_RESTORER(m_trigAssignIfacep);
VL_RESTORER(m_trigAssignMemberVarp);
iterateAndNextNull(nodep->stmtsp());
}
if (v3Global.usesTiming()) {
// Clear the trigger assignment, as there could have been timing controls in the loop
m_trigAssignp = nullptr;
m_trigAssignIfacep = nullptr;
m_trigAssignMemberVarp = nullptr;
}
}
void visit(AstJumpBlock* nodep) override {
{
VL_RESTORER(m_trigAssignp);
VL_RESTORER(m_trigAssignIfacep);
VL_RESTORER(m_trigAssignMemberVarp);
iterateChildren(nodep);
}
if (v3Global.usesTiming()) {
@ -180,29 +229,48 @@ private:
// block
m_trigAssignp = nullptr;
m_trigAssignIfacep = nullptr;
m_trigAssignMemberVarp = nullptr;
}
}
void visit(AstNodeStmt* nodep) override {
if (v3Global.usesTiming()
&& nodep->exists([](AstNode* nodep) { return nodep->isTimingControl(); })) {
m_trigAssignp = nullptr; // Could be after a delay - need new trigger assignment
m_trigAssignp = nullptr;
m_trigAssignIfacep = nullptr;
// No restorer, as following statements should not reuse the old assignment
m_trigAssignMemberVarp = nullptr;
}
FileLine* const flp = nodep->fileline();
foreachWrittenVirtIface(nodep, [&](AstVarRef*, AstIface* ifacep) {
if (ifacep != m_trigAssignIfacep) {
// Write to different interface type than before - need new trigger assignment
// No restorer, as following statements should not reuse the old assignment
foreachWrittenVirtIfaceMember(nodep, [&](AstVarRef*, AstIface* ifacep,
AstVar* memberVarp) {
if (ifacep != m_trigAssignIfacep || memberVarp != m_trigAssignMemberVarp) {
// Write to different interface member than before - need new trigger assignment
m_trigAssignIfacep = ifacep;
m_trigAssignMemberVarp = memberVarp;
m_trigAssignp = nullptr;
}
if (!m_trigAssignp) {
m_trigAssignp = new AstAssign{flp, createVirtIfaceTriggerRefp(flp, ifacep),
new AstConst{flp, AstConst::BitTrue{}}};
m_trigAssignp
= new AstAssign{flp, createVirtIfaceMemberTriggerRefp(flp, ifacep, memberVarp),
new AstConst{flp, AstConst::BitTrue{}}};
nodep->addNextHere(m_trigAssignp);
}
});
// Fallback to whole-interface tracking if no member-specific assignments found
if (!m_trigAssignp) {
foreachWrittenVirtIface(nodep, [&](AstVarRef*, AstIface* ifacep) {
if (ifacep != m_trigAssignIfacep) {
m_trigAssignIfacep = ifacep;
m_trigAssignMemberVarp = nullptr;
m_trigAssignp = nullptr;
}
if (!m_trigAssignp) {
m_trigAssignp = new AstAssign{flp, createVirtIfaceTriggerRefp(flp, ifacep),
new AstConst{flp, AstConst::BitTrue{}}};
nodep->addNextHere(m_trigAssignp);
}
});
}
}
void visit(AstNodeExpr*) override {} // Accelerate
void visit(AstNode* nodep) override { iterateChildren(nodep); }

View File

@ -215,7 +215,7 @@ void V3Stats::statsStage(const string& name) {
V3Stats::addStatPerf("Stage, Elapsed time (sec), " + digitName, wallTimeDelta);
V3Stats::addStatPerf("Stage, Elapsed time (sec), TOTAL", wallTimeDelta);
const double memory = VlOs::memUsageBytes() / 1024.0 / 1024.0;
const double memory = VlOs::memPeakUsageBytes() / 1024.0 / 1024.0;
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
}
@ -266,7 +266,7 @@ void V3Stats::summaryReport() {
<< ", cvt=" << walltimeCvt << ", bld=" << walltimeBuild << "); cpu " << cputime
<< " s on " << std::max(v3Global.opt.verilateJobs(), v3Global.opt.buildJobs())
<< " threads";
const double memory = VlOs::memUsageBytes() / 1024.0 / 1024.0;
const double memory = VlOs::memPeakUsageBytes() / 1024.0 / 1024.0;
if (VL_UNCOVERABLE(memory != 0.0)) std::cout << "; alloced " << memory << " MB";
std::cout << "\n";
}

View File

@ -629,8 +629,8 @@ class WidthVisitor final : public VNVisitor {
iterateCheckString(nodep, "RHS", nodep->rhsp(), BOTH);
nodep->dtypeSetString();
} else {
iterateCheckSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
iterateCheckSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
iterateCheckIntegralSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
iterateCheckIntegralSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
if (m_streamConcat) {
packIfUnpacked(nodep->lhsp());
@ -837,7 +837,7 @@ class WidthVisitor final : public VNVisitor {
if (vdtypep && vdtypep->isString()) {
iterateCheckString(nodep, "LHS", nodep->srcp(), BOTH);
} else {
iterateCheckSelf(nodep, "LHS", nodep->srcp(), SELF, BOTH);
iterateCheckIntegralSelf(nodep, "LHS", nodep->srcp(), SELF, BOTH);
}
if ((vdtypep && vdtypep->isString()) || nodep->srcp()->isString()) {
@ -971,7 +971,7 @@ class WidthVisitor final : public VNVisitor {
if (debug() >= 9) nodep->dumpTree("- selWidth: ");
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p());
userIterateAndNext(nodep->lsbp(), WidthVP{SELF, PRELIM}.p());
checkCvtUS(nodep->fromp());
checkCvtUS(nodep->fromp(), false);
iterateCheckSizedSelf(nodep, "Select LHS", nodep->fromp(), SELF, BOTH);
int width = nodep->widthConst();
if (width <= 0) {
@ -1510,7 +1510,7 @@ class WidthVisitor final : public VNVisitor {
return;
}
checkCvtUS(nodep->lhsp());
checkCvtUS(nodep->lhsp(), false);
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
nodep->dtypeFrom(nodep->lhsp());
}
@ -2461,11 +2461,11 @@ class WidthVisitor final : public VNVisitor {
// if (debug() >= 9) nodep->dumpTree("- VRout: ");
if (nodep->access().isWriteOrRW() && nodep->varp()->direction() == VDirection::CONSTREF) {
nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ());
} else if (!nodep->varp()->isForced() && nodep->access().isWriteOrRW()
&& nodep->varp()->isInput() && !nodep->varp()->isFuncLocal()
&& nodep->varp()->isReadOnly() && (!m_ftaskp || !m_ftaskp->isConstructor())
&& !VN_IS(m_procedurep, InitialAutomatic)
&& !VN_IS(m_procedurep, InitialStatic)) {
} else if (nodep->access().isWriteOrRW() && nodep->varp()->isInput()
&& !nodep->varp()->isFuncLocal() && nodep->varp()->isReadOnly()
&& (!m_ftaskp || !m_ftaskp->isConstructor())
&& !VN_IS(m_procedurep, InitialAutomatic) && !VN_IS(m_procedurep, InitialStatic)
&& !VN_IS(nodep->abovep(), AssignForce) && !VN_IS(nodep->abovep(), Release)) {
nodep->v3warn(ASSIGNIN, "Assigning to input/const variable: " << nodep->prettyNameQ());
} else if (nodep->access().isWriteOrRW() && nodep->varp()->isConst() && !m_paramsOnly
&& (!m_ftaskp || !m_ftaskp->isConstructor())
@ -2483,10 +2483,11 @@ class WidthVisitor final : public VNVisitor {
UINFO(5, " ENUMDTYPE " << nodep);
nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep()));
nodep->dtypep(nodep);
AstBasicDType* basicp = nodep->dtypep()->skipRefp()->basicp();
if (!basicp || !basicp->keyword().isIntNumeric()) {
AstNodeDType* basicp = nodep->dtypep()->skipRefp()->basicp();
if (!dtypeIsIntAtomOrVecRecurse(nodep->subDTypep())) {
nodep->v3error(
"Enum type must be an integer atom or vector type (IEEE 1800-2023 6.19)");
"Enum data type must be an integer atom or vector type (IEEE 1800-2023 6.19), not "
<< nodep->subDTypep()->prettyDTypeNameQ());
basicp = nodep->findSigned32DType()->basicp();
nodep->refDTypep(basicp);
}
@ -2553,9 +2554,16 @@ class WidthVisitor final : public VNVisitor {
// Default type is int, but common to assign narrower values, so minwidth from value
userIterateAndNext(nodep->valuep(), WidthVP{CONTEXT_DET, PRELIM}.p());
bool warnOn = true;
if (const AstConst* const constp = VN_CAST(nodep->valuep(), Const)) {
AstNodeExpr* valuep = nodep->valuep();
if (const AstAdd* const anodep = VN_CAST(valuep, Add)) {
// If constructed by V3LinkParse due to "enumitem[N_REPEATS] value"
if (anodep->fileline()->equalFirstLineCol(*(nodep->fileline())))
valuep = anodep->lhsp();
}
if (const AstConst* const constp = VN_CAST(valuep, Const)) {
if (static_cast<int>(constp->num().mostSetBitP1()) > nodep->width()) {
constp->v3error("Enum value exceeds width of enum type (IEEE 1800-2023 6.19)");
constp->v3warn(ENUMITEMWIDTH,
"Enum value exceeds width of enum type (IEEE 1800-2023 6.19)");
warnOn = false; // Prevent normal WIDTHTRUNC
}
}
@ -6819,7 +6827,7 @@ class WidthVisitor final : public VNVisitor {
UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!");
if (m_vup->prelim()) {
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
if (!real_ok) checkCvtUS(nodep->lhsp());
if (!real_ok) checkCvtUS(nodep->lhsp(), false);
}
if (real_ok && nodep->lhsp()->isDouble()) {
spliceCvtD(nodep->lhsp());
@ -6860,7 +6868,7 @@ class WidthVisitor final : public VNVisitor {
UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!");
if (m_vup->prelim()) {
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
checkCvtUS(nodep->lhsp());
checkCvtUS(nodep->lhsp(), true);
const int width = nodep->lhsp()->width();
AstNodeDType* const expDTypep = nodep->findLogicDType(width, width, rs_out);
nodep->dtypep(expDTypep);
@ -6888,7 +6896,7 @@ class WidthVisitor final : public VNVisitor {
// RHS is self-determined. RHS is always treated as unsigned, has no effect on result.
if (m_vup->prelim()) {
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
checkCvtUS(nodep->lhsp());
checkCvtUS(nodep->lhsp(), false);
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
nodep->dtypeFrom(nodep->lhsp());
}
@ -6948,8 +6956,8 @@ class WidthVisitor final : public VNVisitor {
// Determine expression widths only relying on what's in the subops
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
checkCvtUS(nodep->lhsp());
checkCvtUS(nodep->rhsp());
checkCvtUS(nodep->lhsp(), false);
checkCvtUS(nodep->rhsp(), false);
const int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width());
const int mwidth = std::max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin());
const bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
@ -6983,8 +6991,8 @@ class WidthVisitor final : public VNVisitor {
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
if (!real_ok) {
checkCvtUS(nodep->lhsp());
checkCvtUS(nodep->rhsp());
checkCvtUS(nodep->lhsp(), false);
checkCvtUS(nodep->rhsp(), false);
}
if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) {
spliceCvtD(nodep->lhsp());
@ -7323,8 +7331,12 @@ class WidthVisitor final : public VNVisitor {
}
(void)underp; // cppcheck
}
void iterateCheckIntegralSelf(AstNode* nodep, const char* side, AstNode* underp, Determ determ,
Stage stage) {
iterateCheckSelf(nodep, side, underp, determ, stage, true);
}
void iterateCheckSelf(AstNode* nodep, const char* side, AstNode* underp, Determ determ,
Stage stage) {
Stage stage, bool integralOnly = false) {
// Coerce child to any data type; child is self-determined
// i.e. isolated from expected type.
// e.g. nodep=CONCAT, underp=lhs in CONCAT(lhs,rhs)
@ -7334,7 +7346,8 @@ class WidthVisitor final : public VNVisitor {
if (stage & PRELIM) {
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, PRELIM}.p());
}
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr)) : underp;
underp
= VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr), integralOnly) : underp;
AstNodeDType* const expDTypep = underp->dtypep();
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
(void)underp; // cppcheck
@ -7350,7 +7363,7 @@ class WidthVisitor final : public VNVisitor {
if (stage & PRELIM) {
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, PRELIM}.p());
}
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr)) : underp;
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr), false) : underp;
AstNodeDType* const expDTypep = underp->dtypep();
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
AstNodeDType* const checkDtp = expDTypep->skipRefToEnump();
@ -7667,12 +7680,16 @@ class WidthVisitor final : public VNVisitor {
//----------------------------------------------------------------------
// SIGNED/DOUBLE METHODS
AstNodeExpr* checkCvtUS(AstNodeExpr* nodep) {
if (nodep && nodep->isDouble()) {
nodep->v3error("Expected integral (non-" << nodep->dtypep()->prettyDTypeNameQ()
<< ") input to "
<< nodep->backp()->prettyTypeName());
nodep = spliceCvtS(nodep, true, 32);
AstNodeExpr* checkCvtUS(AstNodeExpr* nodep, bool fatal) {
if (nodep && nodep->dtypep()->skipRefp()->isDouble()) {
if (fatal) {
nodep->v3error("Expected integral input to " << nodep->backp()->prettyTypeName());
} else {
nodep->v3warn(REALCVT,
"Implicit conversion of real to integer; expected integral input to "
<< nodep->backp()->prettyTypeName());
}
nodep = spliceCvtS(nodep, false, 32);
}
return nodep;
}
@ -8293,6 +8310,24 @@ class WidthVisitor final : public VNVisitor {
if (nodep->subDTypep()) return hasOpenArrayIterateDType(nodep->subDTypep()->skipRefp());
return false;
}
bool dtypeIsIntAtomOrVecRecurse(AstNodeDType* nodep, bool ranged = false) {
nodep = nodep->skipRefToEnump();
if (AstBasicDType* const dtp = VN_CAST(nodep, BasicDType)) {
if (ranged && (!dtp->isBitLogic() || dtp->isRanged())) {
UINFO(9, "dtypeIsIntAtomOrVecRecurse false at " << nodep);
return false; // Packed when already packed
}
if (dtp->keyword().isIntNumeric()) return true;
} else if (AstPackArrayDType* const dtp = VN_CAST(nodep, PackArrayDType)) {
if (ranged) {
UINFO(9, "dtypeIsIntAtomOrVecRecurse false at " << nodep);
return false; // Packed when already packed
}
return dtypeIsIntAtomOrVecRecurse(nodep->subDTypep(), true);
}
UINFO(9, "dtypeIsIntAtomOrVecRecurse false at " << nodep);
return false;
}
//----------------------------------------------------------------------
// METHODS - special type detection

View File

@ -649,7 +649,6 @@ static void process() {
// Final statistics
if (v3Global.opt.stats()) V3Stats::statsStage("emit");
reportStatsIfEnabled();
}
static void verilate(const string& argString) {
@ -769,6 +768,7 @@ static void verilate(const string& argString) {
V3Os::filesystemFlushBuildDir(v3Global.opt.makeDir());
if (v3Global.opt.hierTop()) V3Os::filesystemFlushBuildDir(v3Global.opt.hierTopDataDir());
if (v3Global.opt.stats()) V3Stats::statsStage("wrote");
// Final writing shouldn't throw warnings, but...
V3Error::abortIfWarnings();
@ -867,6 +867,7 @@ int main(int argc, char** argv) {
execBuildJob();
}
reportStatsIfEnabled();
V3DiagSarif::output(true);
// Explicitly release resources

View File

@ -1219,6 +1219,29 @@ def write_dfg_auto_classes(filename):
fh.write("\n")
def write_dfg_clone_cases(filename):
with open_file(filename) as fh:
def emitBlock(pattern, **fmt):
fh.write(textwrap.dedent(pattern).format(**fmt))
for node in DfgVertexList:
# Only generate code for automatically derived leaf nodes
if (node.file is not None) or not node.isLeaf:
continue
emitBlock('''\
case VDfgType::at{t}: {{
Dfg{t}* const cp = new Dfg{t}{{*clonep, vtx.fileline(), vtx.dtypep()}};
vtxp2clonep.emplace(&vtx, cp);
break;
}}
''',
t=node.name,
s=node.superClass.name)
fh.write("\n")
def write_dfg_ast_to_dfg(filename):
with open_file(filename) as fh:
for node in DfgVertexList:
@ -1408,6 +1431,7 @@ if Args.classes:
write_type_tests("Dfg", DfgVertexList)
write_dfg_macros("V3Dfg__gen_macros.h")
write_dfg_auto_classes("V3Dfg__gen_auto_classes.h")
write_dfg_clone_cases("V3Dfg__gen_clone_cases.h")
write_dfg_ast_to_dfg("V3Dfg__gen_ast_to_dfg.h")
write_dfg_dfg_to_ast("V3Dfg__gen_dfg_to_ast.h")

View File

@ -270,6 +270,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$rewind" { FL; return yD_REWIND; }
"$rtoi" { FL; return yD_RTOI; }
"$sampled" { FL; return yD_SAMPLED; }
"$sdf_annotate" { FL; return yD_SDF_ANNOTATE; }
"$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yD_SETUPHOLD; }
"$sformat" { FL; return yD_SFORMAT; }

View File

@ -98,6 +98,7 @@ public:
bool m_tracingParse = true; // Tracing disable for parser
bool m_inImplements = false; // Is inside class implements list
bool m_insideProperty = false; // Is inside property declaration
bool m_specifyignWarned = false; // Issued a SPECIFYIGN warning
bool m_typedPropertyPort = false; // Typed property port occurred on port lists
bool m_modportImpExpActive
= false; // Standalone ID is a tf_identifier instead of port_identifier
@ -926,6 +927,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yD_ROSE_GCLK "$rose_gclk"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SAMPLED "$sampled"
%token<fl> yD_SDF_ANNOTATE "$sdf_annotate"
%token<fl> yD_SETUPHOLD "$setuphold"
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SFORMATF "$sformatf"
@ -2226,10 +2228,11 @@ data_typeNoRef<nodeDTypep>: // ==IEEE: data_type, excluding class_ty
new AstDefImplicitDType{$1->fileline(),
"__typeimpsu" + cvtToStr(GRAMMARP->s_typeImpNum++),
VFlagChildDType{}, $1}, $2, true); }
| enumDecl
{ $$ = new AstDefImplicitDType{$1->fileline(),
"__typeimpenum" + cvtToStr(GRAMMARP->s_typeImpNum++),
VFlagChildDType{}, $1}; }
| enumDecl packed_dimensionListE
{ $$ = GRAMMARP->createArray(
new AstDefImplicitDType{$1->fileline(),
"__typeimpenum" + cvtToStr(GRAMMARP->s_typeImpNum++),
VFlagChildDType{}, $1}, $2, true); }
| ySTRING
{ $$ = new AstBasicDType{$1, VBasicDTypeKwd::STRING}; }
| yCHANDLE
@ -3753,10 +3756,10 @@ statement_item<nodep>: // IEEE: statement_item
//
// // IEEE: disable_statement
| yDISABLE yFORK ';' { $$ = new AstDisableFork{$1}; }
| yDISABLE idAny/*UNSUP: hierarchical_identifier-task_or_block*/ ';'
{ $$ = new AstDisable{$1, *$2}; }
| yDISABLE idAny '.' idDottedSel ';'
{ $$ = nullptr; BBUNSUP($4, "Unsupported: disable with '.'"); }
| yDISABLE idDottedSel ';'
{ $$ = new AstDisable{$1, $2};
PARSEP->importIfInStd($1, "process");
}
// // IEEE: event_trigger
| yP_MINUSGT expr ';'
{ $$ = new AstFireEvent{$1, $2, false}; }
@ -4180,6 +4183,7 @@ loop_variables<nodep>: // IEEE: loop_variables
parseRefBase { $$ = $1; }
| loop_variables ',' parseRefBase { $$ = $1->addNext($3); }
| ',' parseRefBase { $$ = new AstEmpty{$1}; $$->addNext($2); }
| ',' { $$ = new AstEmpty{$1}; }
;
//************************************************
@ -4282,6 +4286,7 @@ system_t_call<nodeStmtp>: // IEEE: system_tf_call (as task)
| yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl{$<fl>1, VDumpCtlType::ON}; DEL($3); }
//
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCStmt{$1, $3}); }
| yD_SDF_ANNOTATE '(' exprEListE ')' { $$ = nullptr; $1->v3warn(SPECIFYIGN, "Ignoring unsupported: $sdf_annotate"); }
| yD_STACKTRACE parenE { $$ = new AstStackTraceT{$1}; }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT{$1, $3}; }
//
@ -5351,6 +5356,11 @@ exprList<nodeExprp>:
| exprList ',' expr { $$ = $1->addNext($3); }
;
exprEListE<nodep>: // expression list with empty commas allowed
exprE { $$ = $1; }
| exprEListE ',' exprE { $$ = addNextNull($1, $3); }
;
exprDispList<nodeExprp>: // exprList for within $display
expr { $$ = $1; }
| exprDispList ',' expr { $$ = $1->addNext($3); }
@ -5823,8 +5833,12 @@ tablelVal<udpTableLineValp>:
// Specify
specify_block<nodep>: // ==IEEE: specify_block
ySPECIFY specify_itemList yENDSPECIFY { $$ = $2; }
| ySPECIFY yENDSPECIFY { $$ = nullptr; }
specifyFront specify_itemList yENDSPECIFY { $$ = $2; }
| specifyFront yENDSPECIFY { $$ = nullptr; }
;
specifyFront: // IEEE: specify_block front
ySPECIFY { GRAMMARP->m_specifyignWarned = false; }
;
specify_itemList<nodep>: // IEEE: { specify_item }
@ -5835,7 +5849,13 @@ specify_itemList<nodep>: // IEEE: { specify_item }
specify_item<nodep>: // ==IEEE: specify_item
specparam_declaration { $$ = $1; }
| system_timing_check { $$ = $1; }
| junkToSemiList ';' { $$ = nullptr; }
| junkToSemiList ';'
{ $$ = nullptr;
if (!GRAMMARP->m_specifyignWarned) {
GRAMMARP->m_specifyignWarned = true;
$1->v3warn(SPECIFYIGN, "Ignoring unsupported: specify block construct");
}
}
;
specparam_declaration<nodep>: // ==IEEE: specparam_declaration
@ -5924,9 +5944,9 @@ idAnyE<strp>:
| idAny { $$ = $1; }
;
junkToSemiList:
junkToSemi { } /* ignored */
| junkToSemiList junkToSemi { } /* ignored */
junkToSemiList<fl>:
junkToSemi { $$ = CRELINE(); }
| junkToSemiList junkToSemi { $$ = CRELINE(); }
;
junkToSemi:
@ -6118,6 +6138,8 @@ idArrayedForeach<nodeExprp>: // IEEE: id + select (under foreach expression)
| idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus{$2, $1, $3, $5}; }
// // IEEE: loop_variables (under foreach expression)
// // To avoid conflicts we allow expr as first element, must post-check
| idArrayed '[' ']'
{ $$ = new AstSelLoopVars{$2, $1, new AstEmpty{$3}}; }
| idArrayed '[' expr ',' loop_variables ']'
{ $$ = new AstSelLoopVars{$2, $1, addNextNull(static_cast<AstNode*>($3), $5)}; }
| idArrayed '[' ',' loop_variables ']'
@ -6821,21 +6843,38 @@ covergroup_declaration<nodep>: // ==IEEE: covergroup_declaration
| covergroup_declarationFront '(' tf_port_listE ')'
/*cont*/ coverage_eventE ';' coverage_spec_or_optionListE
/*cont*/ yENDGROUP endLabelE
{ $$ = $1;
{ AstFunc* const newp = new AstFunc{$<fl>1, "new", nullptr, nullptr};
newp->classMethod(true);
newp->isConstructor(true);
newp->dtypep($1->dtypep());
newp->addStmtsp($3);
$1->addMembersp(newp);
$$ = $1;
GRAMMARP->endLabel($<fl>9, $1, $9); }
// // IEEE 1800-2023 added:
| covergroup_declarationFront yEXTENDS idAny/*covergroup_identifier*/
/*cont*/ ';' coverage_spec_or_optionListE
/*cont*/ yENDGROUP endLabelE
{ $$ = $1;
GRAMMARP->endLabel($<fl>7, $1, $7); }
;
covergroup_extendsE<fl>: // IEEE: Part of covergroup_declaration
/* empty */ { $$ = nullptr; }
| yEXTENDS { $$ = $1; }
;
covergroup_declarationFront<classp>: // IEEE: part of covergroup_declaration
yCOVERGROUP idAny
{ $$ = new AstClass{$<fl>2, *$2, PARSEP->libname()};
yCOVERGROUP covergroup_extendsE idAny
{
$$ = new AstClass{$<fl>3, *$3, PARSEP->libname()};
AstFunc* const sample = new AstFunc{$<fl>1, "sample", nullptr, nullptr};
sample->classMethod(true);
sample->dtypep(sample->findVoidDType());
$$->addMembersp(sample);
AstFunc* const getCoverage = new AstFunc{$<fl>1, "get_coverage", nullptr, nullptr};
getCoverage->classMethod(true);
getCoverage->dtypep(getCoverage->findVoidDType());
$$->addMembersp(getCoverage);
BBCOVERIGN($<fl>1, "Ignoring unsupported: covergroup"); }
;
;
cgexpr<nodeExprp>: // IEEE-2012: covergroup_expression, before that just expression
expr { $$ = $1; }
@ -7005,7 +7044,7 @@ cross_itemList<nodep>: // IEEE: part of list_of_cross_items
;
cross_item<nodep>: // ==IEEE: cross_item
idAny/*cover_point_identifier or variable_identifier*/ { $$ = nullptr; /*UNSUP*/ }
idDotted/*cover_point_identifier or variable_identifier*/ { $1->deleteTree(); $$ = nullptr; /*UNSUP*/ }
;
cross_body<nodep>: // ==IEEE: cross_body
@ -7551,7 +7590,12 @@ class_item<nodep>: // ==IEEE: class_item
| class_declaration { $$ = $1; }
| timeunits_declaration { $$ = $1; }
| covergroup_declaration
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup within class"); }
{
const string cgName = $1->name();
$1->name("__vlAnonCG_" + cgName);
AstVar* const newp = new AstVar{$<fl>1, VVarType::VAR, cgName, VFlagChildDType{}, new AstRefDType($<fl>1, $1->name())};
$$ = addNextNull($1, newp);
}
// // local_parameter_declaration under parameter_declaration
| parameter_declaration ';' { $$ = $1; }
| ';' { $$ = nullptr; }
@ -8089,8 +8133,10 @@ vltDModule<strp>: // --module <arg>
;
vltDModuleE<strp>: // [--module <arg>]
/* empty */ { static string unit = "__024unit"; $$ = &unit; }
| vltDModule { $$ = $1; }
/* empty */
{ static string unit = "$unit"; $$ = &unit; } // .vlt uses prettyName
| vltDModule
{ $$ = $1; }
;
vltDScope<strp>: // --scope <arg>

View File

@ -5,290 +5,284 @@
// SPDX-License-Identifier: CC0-1.0
module t_case_huge_sub (/*AUTOARG*/
// Outputs
outa, outb, outc,
// Inputs
index
);
// Outputs
outa, outb, outc,
// Inputs
index
);
input [7:0] index;
output [9:0] outa;
output [1:0] outb;
output outc;
input [7:0] index;
output logic [9:0] outa;
output logic [1:0] outb;
output logic outc;
// =============================
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [9:0] outa;
reg [1:0] outb;
reg outc;
// End of automatics
// =============================
// Created from Python3:
// for i in range(1024):
// print(" 10'h%03x: begin outa = 10'h%03x; outb = 2'b%d%d; outc = 1'b%d; end"
// % (i, random.randint(0,1024), random.randint(0,1),
// random.randint(0,1), random.randint(0,1)))
// =============================
// Created from Python3:
// for i in range(1024):
// print(" 10'h%03x: begin outa = 10'h%03x; outb = 2'b%d%d; outc = 1'b%d; end"
// % (i, random.randint(0,1024), random.randint(0,1),
// random.randint(0,1), random.randint(0,1)))
always @(/*AS*/index) begin
case (index)
8'h00: begin outa = 10'h152; outb = 2'b00; outc = 1'b1; end
8'h01: begin outa = 10'h318; outb = 2'b11; outc = 1'b1; end
8'h02: begin outa = 10'h29f; outb = 2'b11; outc = 1'b0; end
8'h03: begin outa = 10'h392; outb = 2'b01; outc = 1'b1; end
8'h04: begin outa = 10'h1ef; outb = 2'b00; outc = 1'b0; end
8'h05: begin outa = 10'h06c; outb = 2'b10; outc = 1'b1; end
8'h06: begin outa = 10'h29f; outb = 2'b11; outc = 1'b0; end
8'h07: begin outa = 10'h29a; outb = 2'b10; outc = 1'b0; end
8'h08: begin outa = 10'h3ce; outb = 2'b01; outc = 1'b0; end
8'h09: begin outa = 10'h37c; outb = 2'b01; outc = 1'b0; end
8'h0a: begin outa = 10'h058; outb = 2'b10; outc = 1'b0; end
8'h0b: begin outa = 10'h3b2; outb = 2'b01; outc = 1'b1; end
8'h0c: begin outa = 10'h36f; outb = 2'b11; outc = 1'b0; end
8'h0d: begin outa = 10'h2c5; outb = 2'b11; outc = 1'b0; end
8'h0e: begin outa = 10'h23a; outb = 2'b00; outc = 1'b0; end
8'h0f: begin outa = 10'h222; outb = 2'b01; outc = 1'b1; end
8'h10: begin outa = 10'h328; outb = 2'b00; outc = 1'b1; end
8'h11: begin outa = 10'h3c3; outb = 2'b00; outc = 1'b1; end
8'h12: begin outa = 10'h12c; outb = 2'b01; outc = 1'b0; end
8'h13: begin outa = 10'h1d0; outb = 2'b00; outc = 1'b1; end
8'h14: begin outa = 10'h3ff; outb = 2'b01; outc = 1'b1; end
8'h15: begin outa = 10'h115; outb = 2'b11; outc = 1'b1; end
8'h16: begin outa = 10'h3ba; outb = 2'b10; outc = 1'b0; end
8'h17: begin outa = 10'h3ba; outb = 2'b00; outc = 1'b0; end
8'h18: begin outa = 10'h10d; outb = 2'b00; outc = 1'b1; end
8'h19: begin outa = 10'h13b; outb = 2'b01; outc = 1'b1; end
8'h1a: begin outa = 10'h0a0; outb = 2'b10; outc = 1'b1; end
8'h1b: begin outa = 10'h264; outb = 2'b11; outc = 1'b0; end
8'h1c: begin outa = 10'h3a2; outb = 2'b10; outc = 1'b0; end
8'h1d: begin outa = 10'h07c; outb = 2'b00; outc = 1'b1; end
8'h1e: begin outa = 10'h291; outb = 2'b00; outc = 1'b0; end
8'h1f: begin outa = 10'h1d1; outb = 2'b10; outc = 1'b0; end
8'h20: begin outa = 10'h354; outb = 2'b11; outc = 1'b1; end
8'h21: begin outa = 10'h0c0; outb = 2'b00; outc = 1'b1; end
8'h22: begin outa = 10'h191; outb = 2'b00; outc = 1'b0; end
8'h23: begin outa = 10'h379; outb = 2'b01; outc = 1'b0; end
8'h24: begin outa = 10'h073; outb = 2'b00; outc = 1'b0; end
8'h25: begin outa = 10'h2fd; outb = 2'b11; outc = 1'b1; end
8'h26: begin outa = 10'h2e0; outb = 2'b11; outc = 1'b1; end
8'h27: begin outa = 10'h337; outb = 2'b01; outc = 1'b1; end
8'h28: begin outa = 10'h2c7; outb = 2'b11; outc = 1'b1; end
8'h29: begin outa = 10'h19e; outb = 2'b11; outc = 1'b0; end
8'h2a: begin outa = 10'h107; outb = 2'b10; outc = 1'b0; end
8'h2b: begin outa = 10'h06a; outb = 2'b01; outc = 1'b1; end
8'h2c: begin outa = 10'h1c7; outb = 2'b01; outc = 1'b1; end
8'h2d: begin outa = 10'h107; outb = 2'b10; outc = 1'b0; end
8'h2e: begin outa = 10'h0cf; outb = 2'b01; outc = 1'b1; end
8'h2f: begin outa = 10'h009; outb = 2'b11; outc = 1'b1; end
8'h30: begin outa = 10'h09d; outb = 2'b00; outc = 1'b1; end
8'h31: begin outa = 10'h28e; outb = 2'b00; outc = 1'b0; end
8'h32: begin outa = 10'h010; outb = 2'b01; outc = 1'b0; end
8'h33: begin outa = 10'h1e0; outb = 2'b10; outc = 1'b0; end
8'h34: begin outa = 10'h079; outb = 2'b01; outc = 1'b1; end
8'h35: begin outa = 10'h13e; outb = 2'b10; outc = 1'b1; end
8'h36: begin outa = 10'h282; outb = 2'b11; outc = 1'b0; end
8'h37: begin outa = 10'h21c; outb = 2'b11; outc = 1'b1; end
8'h38: begin outa = 10'h148; outb = 2'b00; outc = 1'b1; end
8'h39: begin outa = 10'h3c0; outb = 2'b10; outc = 1'b0; end
8'h3a: begin outa = 10'h176; outb = 2'b01; outc = 1'b1; end
8'h3b: begin outa = 10'h3fc; outb = 2'b10; outc = 1'b1; end
8'h3c: begin outa = 10'h295; outb = 2'b11; outc = 1'b1; end
8'h3d: begin outa = 10'h113; outb = 2'b10; outc = 1'b1; end
8'h3e: begin outa = 10'h354; outb = 2'b01; outc = 1'b1; end
8'h3f: begin outa = 10'h0db; outb = 2'b11; outc = 1'b0; end
8'h40: begin outa = 10'h238; outb = 2'b01; outc = 1'b0; end
8'h41: begin outa = 10'h12b; outb = 2'b01; outc = 1'b1; end
8'h42: begin outa = 10'h1dc; outb = 2'b10; outc = 1'b0; end
8'h43: begin outa = 10'h137; outb = 2'b01; outc = 1'b1; end
8'h44: begin outa = 10'h1e2; outb = 2'b01; outc = 1'b1; end
8'h45: begin outa = 10'h3d5; outb = 2'b11; outc = 1'b1; end
8'h46: begin outa = 10'h30c; outb = 2'b11; outc = 1'b0; end
8'h47: begin outa = 10'h298; outb = 2'b11; outc = 1'b0; end
8'h48: begin outa = 10'h080; outb = 2'b00; outc = 1'b1; end
8'h49: begin outa = 10'h35a; outb = 2'b11; outc = 1'b1; end
8'h4a: begin outa = 10'h01b; outb = 2'b00; outc = 1'b0; end
8'h4b: begin outa = 10'h0a3; outb = 2'b11; outc = 1'b0; end
8'h4c: begin outa = 10'h0b3; outb = 2'b11; outc = 1'b1; end
8'h4d: begin outa = 10'h17a; outb = 2'b00; outc = 1'b0; end
8'h4e: begin outa = 10'h3ae; outb = 2'b11; outc = 1'b0; end
8'h4f: begin outa = 10'h078; outb = 2'b11; outc = 1'b0; end
8'h50: begin outa = 10'h322; outb = 2'b00; outc = 1'b1; end
8'h51: begin outa = 10'h213; outb = 2'b11; outc = 1'b0; end
8'h52: begin outa = 10'h11a; outb = 2'b11; outc = 1'b0; end
8'h53: begin outa = 10'h1a7; outb = 2'b00; outc = 1'b0; end
8'h54: begin outa = 10'h35a; outb = 2'b00; outc = 1'b1; end
8'h55: begin outa = 10'h233; outb = 2'b00; outc = 1'b0; end
8'h56: begin outa = 10'h01d; outb = 2'b01; outc = 1'b1; end
8'h57: begin outa = 10'h2d5; outb = 2'b00; outc = 1'b0; end
8'h58: begin outa = 10'h1a0; outb = 2'b00; outc = 1'b1; end
8'h59: begin outa = 10'h3d0; outb = 2'b00; outc = 1'b1; end
8'h5a: begin outa = 10'h181; outb = 2'b01; outc = 1'b1; end
8'h5b: begin outa = 10'h219; outb = 2'b01; outc = 1'b1; end
8'h5c: begin outa = 10'h26a; outb = 2'b01; outc = 1'b1; end
8'h5d: begin outa = 10'h050; outb = 2'b10; outc = 1'b0; end
8'h5e: begin outa = 10'h189; outb = 2'b10; outc = 1'b0; end
8'h5f: begin outa = 10'h1eb; outb = 2'b01; outc = 1'b1; end
8'h60: begin outa = 10'h224; outb = 2'b00; outc = 1'b1; end
8'h61: begin outa = 10'h2fe; outb = 2'b00; outc = 1'b0; end
8'h62: begin outa = 10'h0ae; outb = 2'b00; outc = 1'b1; end
8'h63: begin outa = 10'h1cd; outb = 2'b00; outc = 1'b0; end
8'h64: begin outa = 10'h273; outb = 2'b10; outc = 1'b1; end
8'h65: begin outa = 10'h268; outb = 2'b10; outc = 1'b0; end
8'h66: begin outa = 10'h111; outb = 2'b01; outc = 1'b0; end
8'h67: begin outa = 10'h1f9; outb = 2'b00; outc = 1'b0; end
8'h68: begin outa = 10'h232; outb = 2'b00; outc = 1'b1; end
8'h69: begin outa = 10'h255; outb = 2'b11; outc = 1'b0; end
8'h6a: begin outa = 10'h34c; outb = 2'b01; outc = 1'b1; end
8'h6b: begin outa = 10'h049; outb = 2'b01; outc = 1'b1; end
8'h6c: begin outa = 10'h197; outb = 2'b11; outc = 1'b0; end
8'h6d: begin outa = 10'h0fe; outb = 2'b11; outc = 1'b0; end
8'h6e: begin outa = 10'h253; outb = 2'b01; outc = 1'b1; end
8'h6f: begin outa = 10'h2de; outb = 2'b11; outc = 1'b0; end
8'h70: begin outa = 10'h13b; outb = 2'b10; outc = 1'b1; end
8'h71: begin outa = 10'h040; outb = 2'b10; outc = 1'b0; end
8'h72: begin outa = 10'h0b4; outb = 2'b00; outc = 1'b1; end
8'h73: begin outa = 10'h233; outb = 2'b11; outc = 1'b1; end
8'h74: begin outa = 10'h198; outb = 2'b00; outc = 1'b1; end
8'h75: begin outa = 10'h018; outb = 2'b00; outc = 1'b1; end
8'h76: begin outa = 10'h2f7; outb = 2'b00; outc = 1'b1; end
8'h77: begin outa = 10'h134; outb = 2'b11; outc = 1'b0; end
8'h78: begin outa = 10'h1ca; outb = 2'b10; outc = 1'b0; end
8'h79: begin outa = 10'h286; outb = 2'b10; outc = 1'b1; end
8'h7a: begin outa = 10'h0e6; outb = 2'b11; outc = 1'b1; end
8'h7b: begin outa = 10'h064; outb = 2'b10; outc = 1'b1; end
8'h7c: begin outa = 10'h257; outb = 2'b00; outc = 1'b1; end
8'h7d: begin outa = 10'h31a; outb = 2'b10; outc = 1'b1; end
8'h7e: begin outa = 10'h247; outb = 2'b01; outc = 1'b0; end
8'h7f: begin outa = 10'h299; outb = 2'b00; outc = 1'b0; end
8'h80: begin outa = 10'h02c; outb = 2'b00; outc = 1'b0; end
8'h81: begin outa = 10'h2bb; outb = 2'b11; outc = 1'b0; end
8'h82: begin outa = 10'h180; outb = 2'b10; outc = 1'b0; end
8'h83: begin outa = 10'h245; outb = 2'b01; outc = 1'b1; end
8'h84: begin outa = 10'h0da; outb = 2'b10; outc = 1'b0; end
8'h85: begin outa = 10'h367; outb = 2'b10; outc = 1'b0; end
8'h86: begin outa = 10'h304; outb = 2'b01; outc = 1'b0; end
8'h87: begin outa = 10'h38b; outb = 2'b11; outc = 1'b0; end
8'h88: begin outa = 10'h09f; outb = 2'b01; outc = 1'b0; end
8'h89: begin outa = 10'h1f0; outb = 2'b10; outc = 1'b1; end
8'h8a: begin outa = 10'h281; outb = 2'b10; outc = 1'b1; end
8'h8b: begin outa = 10'h019; outb = 2'b00; outc = 1'b0; end
8'h8c: begin outa = 10'h1f2; outb = 2'b10; outc = 1'b0; end
8'h8d: begin outa = 10'h0b1; outb = 2'b01; outc = 1'b1; end
8'h8e: begin outa = 10'h058; outb = 2'b01; outc = 1'b1; end
8'h8f: begin outa = 10'h39b; outb = 2'b00; outc = 1'b1; end
8'h90: begin outa = 10'h2ec; outb = 2'b10; outc = 1'b1; end
8'h91: begin outa = 10'h250; outb = 2'b00; outc = 1'b1; end
8'h92: begin outa = 10'h3f4; outb = 2'b10; outc = 1'b1; end
8'h93: begin outa = 10'h057; outb = 2'b10; outc = 1'b1; end
8'h94: begin outa = 10'h18f; outb = 2'b01; outc = 1'b1; end
8'h95: begin outa = 10'h105; outb = 2'b01; outc = 1'b1; end
8'h96: begin outa = 10'h1ae; outb = 2'b00; outc = 1'b1; end
8'h97: begin outa = 10'h04e; outb = 2'b10; outc = 1'b0; end
8'h98: begin outa = 10'h240; outb = 2'b11; outc = 1'b0; end
8'h99: begin outa = 10'h3e4; outb = 2'b01; outc = 1'b0; end
8'h9a: begin outa = 10'h3c6; outb = 2'b01; outc = 1'b0; end
8'h9b: begin outa = 10'h109; outb = 2'b00; outc = 1'b1; end
8'h9c: begin outa = 10'h073; outb = 2'b10; outc = 1'b1; end
8'h9d: begin outa = 10'h19f; outb = 2'b01; outc = 1'b0; end
8'h9e: begin outa = 10'h3b8; outb = 2'b01; outc = 1'b0; end
8'h9f: begin outa = 10'h00e; outb = 2'b00; outc = 1'b1; end
8'ha0: begin outa = 10'h1b3; outb = 2'b11; outc = 1'b1; end
8'ha1: begin outa = 10'h2bd; outb = 2'b11; outc = 1'b0; end
8'ha2: begin outa = 10'h324; outb = 2'b00; outc = 1'b1; end
8'ha3: begin outa = 10'h343; outb = 2'b10; outc = 1'b0; end
8'ha4: begin outa = 10'h1c9; outb = 2'b01; outc = 1'b0; end
8'ha5: begin outa = 10'h185; outb = 2'b00; outc = 1'b1; end
8'ha6: begin outa = 10'h37a; outb = 2'b00; outc = 1'b1; end
8'ha7: begin outa = 10'h0e0; outb = 2'b01; outc = 1'b1; end
8'ha8: begin outa = 10'h0a3; outb = 2'b10; outc = 1'b0; end
8'ha9: begin outa = 10'h019; outb = 2'b11; outc = 1'b0; end
8'haa: begin outa = 10'h099; outb = 2'b00; outc = 1'b1; end
8'hab: begin outa = 10'h376; outb = 2'b01; outc = 1'b1; end
8'hac: begin outa = 10'h077; outb = 2'b00; outc = 1'b1; end
8'had: begin outa = 10'h2b1; outb = 2'b11; outc = 1'b1; end
8'hae: begin outa = 10'h27f; outb = 2'b00; outc = 1'b0; end
8'haf: begin outa = 10'h265; outb = 2'b11; outc = 1'b0; end
8'hb0: begin outa = 10'h156; outb = 2'b10; outc = 1'b1; end
8'hb1: begin outa = 10'h1ce; outb = 2'b00; outc = 1'b0; end
8'hb2: begin outa = 10'h008; outb = 2'b01; outc = 1'b0; end
8'hb3: begin outa = 10'h12e; outb = 2'b11; outc = 1'b1; end
8'hb4: begin outa = 10'h199; outb = 2'b11; outc = 1'b0; end
8'hb5: begin outa = 10'h330; outb = 2'b10; outc = 1'b0; end
8'hb6: begin outa = 10'h1ab; outb = 2'b01; outc = 1'b1; end
8'hb7: begin outa = 10'h3bd; outb = 2'b00; outc = 1'b0; end
8'hb8: begin outa = 10'h0ca; outb = 2'b10; outc = 1'b0; end
8'hb9: begin outa = 10'h367; outb = 2'b00; outc = 1'b0; end
8'hba: begin outa = 10'h334; outb = 2'b00; outc = 1'b0; end
8'hbb: begin outa = 10'h040; outb = 2'b00; outc = 1'b1; end
8'hbc: begin outa = 10'h1a7; outb = 2'b10; outc = 1'b1; end
8'hbd: begin outa = 10'h036; outb = 2'b11; outc = 1'b1; end
8'hbe: begin outa = 10'h223; outb = 2'b11; outc = 1'b1; end
8'hbf: begin outa = 10'h075; outb = 2'b01; outc = 1'b0; end
8'hc0: begin outa = 10'h3c4; outb = 2'b00; outc = 1'b1; end
8'hc1: begin outa = 10'h2cc; outb = 2'b01; outc = 1'b0; end
8'hc2: begin outa = 10'h123; outb = 2'b01; outc = 1'b0; end
8'hc3: begin outa = 10'h3fd; outb = 2'b01; outc = 1'b1; end
8'hc4: begin outa = 10'h11e; outb = 2'b00; outc = 1'b0; end
8'hc5: begin outa = 10'h27c; outb = 2'b11; outc = 1'b1; end
8'hc6: begin outa = 10'h1e2; outb = 2'b11; outc = 1'b0; end
8'hc7: begin outa = 10'h377; outb = 2'b11; outc = 1'b0; end
8'hc8: begin outa = 10'h33a; outb = 2'b11; outc = 1'b0; end
8'hc9: begin outa = 10'h32d; outb = 2'b11; outc = 1'b1; end
8'hca: begin outa = 10'h014; outb = 2'b11; outc = 1'b0; end
8'hcb: begin outa = 10'h332; outb = 2'b10; outc = 1'b0; end
8'hcc: begin outa = 10'h359; outb = 2'b00; outc = 1'b0; end
8'hcd: begin outa = 10'h0a4; outb = 2'b10; outc = 1'b1; end
8'hce: begin outa = 10'h348; outb = 2'b00; outc = 1'b1; end
8'hcf: begin outa = 10'h04b; outb = 2'b11; outc = 1'b1; end
8'hd0: begin outa = 10'h147; outb = 2'b10; outc = 1'b1; end
8'hd1: begin outa = 10'h026; outb = 2'b00; outc = 1'b1; end
8'hd2: begin outa = 10'h103; outb = 2'b00; outc = 1'b0; end
8'hd3: begin outa = 10'h106; outb = 2'b00; outc = 1'b1; end
8'hd4: begin outa = 10'h35a; outb = 2'b00; outc = 1'b0; end
8'hd5: begin outa = 10'h254; outb = 2'b01; outc = 1'b0; end
8'hd6: begin outa = 10'h0cd; outb = 2'b01; outc = 1'b0; end
8'hd7: begin outa = 10'h17c; outb = 2'b11; outc = 1'b1; end
8'hd8: begin outa = 10'h37e; outb = 2'b10; outc = 1'b1; end
8'hd9: begin outa = 10'h0a9; outb = 2'b11; outc = 1'b1; end
8'hda: begin outa = 10'h0fe; outb = 2'b01; outc = 1'b0; end
8'hdb: begin outa = 10'h3c0; outb = 2'b11; outc = 1'b1; end
8'hdc: begin outa = 10'h1d9; outb = 2'b10; outc = 1'b1; end
8'hdd: begin outa = 10'h10e; outb = 2'b00; outc = 1'b1; end
8'hde: begin outa = 10'h394; outb = 2'b01; outc = 1'b0; end
8'hdf: begin outa = 10'h316; outb = 2'b01; outc = 1'b0; end
8'he0: begin outa = 10'h05b; outb = 2'b11; outc = 1'b0; end
8'he1: begin outa = 10'h126; outb = 2'b01; outc = 1'b1; end
8'he2: begin outa = 10'h369; outb = 2'b11; outc = 1'b0; end
8'he3: begin outa = 10'h291; outb = 2'b10; outc = 1'b1; end
8'he4: begin outa = 10'h2ca; outb = 2'b00; outc = 1'b1; end
8'he5: begin outa = 10'h25b; outb = 2'b01; outc = 1'b1; end
8'he6: begin outa = 10'h106; outb = 2'b00; outc = 1'b0; end
8'he7: begin outa = 10'h172; outb = 2'b11; outc = 1'b1; end
8'he8: begin outa = 10'h2f7; outb = 2'b00; outc = 1'b1; end
8'he9: begin outa = 10'h2d3; outb = 2'b11; outc = 1'b1; end
8'hea: begin outa = 10'h182; outb = 2'b00; outc = 1'b0; end
8'heb: begin outa = 10'h327; outb = 2'b00; outc = 1'b1; end
8'hec: begin outa = 10'h1d0; outb = 2'b10; outc = 1'b0; end
8'hed: begin outa = 10'h204; outb = 2'b00; outc = 1'b1; end
8'hee: begin outa = 10'h11f; outb = 2'b00; outc = 1'b1; end
8'hef: begin outa = 10'h365; outb = 2'b11; outc = 1'b1; end
8'hf0: begin outa = 10'h2c2; outb = 2'b01; outc = 1'b1; end
8'hf1: begin outa = 10'h2b5; outb = 2'b10; outc = 1'b0; end
8'hf2: begin outa = 10'h1f8; outb = 2'b10; outc = 1'b1; end
8'hf3: begin outa = 10'h2a7; outb = 2'b01; outc = 1'b1; end
8'hf4: begin outa = 10'h1be; outb = 2'b10; outc = 1'b1; end
8'hf5: begin outa = 10'h25e; outb = 2'b10; outc = 1'b1; end
8'hf6: begin outa = 10'h032; outb = 2'b10; outc = 1'b0; end
8'hf7: begin outa = 10'h2ef; outb = 2'b00; outc = 1'b0; end
8'hf8: begin outa = 10'h02f; outb = 2'b00; outc = 1'b1; end
8'hf9: begin outa = 10'h201; outb = 2'b10; outc = 1'b0; end
8'hfa: begin outa = 10'h054; outb = 2'b01; outc = 1'b1; end
8'hfb: begin outa = 10'h013; outb = 2'b10; outc = 1'b0; end
8'hfc: begin outa = 10'h249; outb = 2'b01; outc = 1'b0; end
8'hfd: begin outa = 10'h09a; outb = 2'b10; outc = 1'b0; end
8'hfe: begin outa = 10'h012; outb = 2'b00; outc = 1'b0; end
8'hff: begin outa = 10'h114; outb = 2'b10; outc = 1'b1; end
endcase
end
always @* begin
// verilog_format: off
case (index)
8'h00: begin outa = 10'h152; outb = 2'b00; outc = 1'b1; end
8'h01: begin outa = 10'h318; outb = 2'b11; outc = 1'b1; end
8'h02: begin outa = 10'h29f; outb = 2'b11; outc = 1'b0; end
8'h03: begin outa = 10'h392; outb = 2'b01; outc = 1'b1; end
8'h04: begin outa = 10'h1ef; outb = 2'b00; outc = 1'b0; end
8'h05: begin outa = 10'h06c; outb = 2'b10; outc = 1'b1; end
8'h06: begin outa = 10'h29f; outb = 2'b11; outc = 1'b0; end
8'h07: begin outa = 10'h29a; outb = 2'b10; outc = 1'b0; end
8'h08: begin outa = 10'h3ce; outb = 2'b01; outc = 1'b0; end
8'h09: begin outa = 10'h37c; outb = 2'b01; outc = 1'b0; end
8'h0a: begin outa = 10'h058; outb = 2'b10; outc = 1'b0; end
8'h0b: begin outa = 10'h3b2; outb = 2'b01; outc = 1'b1; end
8'h0c: begin outa = 10'h36f; outb = 2'b11; outc = 1'b0; end
8'h0d: begin outa = 10'h2c5; outb = 2'b11; outc = 1'b0; end
8'h0e: begin outa = 10'h23a; outb = 2'b00; outc = 1'b0; end
8'h0f: begin outa = 10'h222; outb = 2'b01; outc = 1'b1; end
8'h10: begin outa = 10'h328; outb = 2'b00; outc = 1'b1; end
8'h11: begin outa = 10'h3c3; outb = 2'b00; outc = 1'b1; end
8'h12: begin outa = 10'h12c; outb = 2'b01; outc = 1'b0; end
8'h13: begin outa = 10'h1d0; outb = 2'b00; outc = 1'b1; end
8'h14: begin outa = 10'h3ff; outb = 2'b01; outc = 1'b1; end
8'h15: begin outa = 10'h115; outb = 2'b11; outc = 1'b1; end
8'h16: begin outa = 10'h3ba; outb = 2'b10; outc = 1'b0; end
8'h17: begin outa = 10'h3ba; outb = 2'b00; outc = 1'b0; end
8'h18: begin outa = 10'h10d; outb = 2'b00; outc = 1'b1; end
8'h19: begin outa = 10'h13b; outb = 2'b01; outc = 1'b1; end
8'h1a: begin outa = 10'h0a0; outb = 2'b10; outc = 1'b1; end
8'h1b: begin outa = 10'h264; outb = 2'b11; outc = 1'b0; end
8'h1c: begin outa = 10'h3a2; outb = 2'b10; outc = 1'b0; end
8'h1d: begin outa = 10'h07c; outb = 2'b00; outc = 1'b1; end
8'h1e: begin outa = 10'h291; outb = 2'b00; outc = 1'b0; end
8'h1f: begin outa = 10'h1d1; outb = 2'b10; outc = 1'b0; end
8'h20: begin outa = 10'h354; outb = 2'b11; outc = 1'b1; end
8'h21: begin outa = 10'h0c0; outb = 2'b00; outc = 1'b1; end
8'h22: begin outa = 10'h191; outb = 2'b00; outc = 1'b0; end
8'h23: begin outa = 10'h379; outb = 2'b01; outc = 1'b0; end
8'h24: begin outa = 10'h073; outb = 2'b00; outc = 1'b0; end
8'h25: begin outa = 10'h2fd; outb = 2'b11; outc = 1'b1; end
8'h26: begin outa = 10'h2e0; outb = 2'b11; outc = 1'b1; end
8'h27: begin outa = 10'h337; outb = 2'b01; outc = 1'b1; end
8'h28: begin outa = 10'h2c7; outb = 2'b11; outc = 1'b1; end
8'h29: begin outa = 10'h19e; outb = 2'b11; outc = 1'b0; end
8'h2a: begin outa = 10'h107; outb = 2'b10; outc = 1'b0; end
8'h2b: begin outa = 10'h06a; outb = 2'b01; outc = 1'b1; end
8'h2c: begin outa = 10'h1c7; outb = 2'b01; outc = 1'b1; end
8'h2d: begin outa = 10'h107; outb = 2'b10; outc = 1'b0; end
8'h2e: begin outa = 10'h0cf; outb = 2'b01; outc = 1'b1; end
8'h2f: begin outa = 10'h009; outb = 2'b11; outc = 1'b1; end
8'h30: begin outa = 10'h09d; outb = 2'b00; outc = 1'b1; end
8'h31: begin outa = 10'h28e; outb = 2'b00; outc = 1'b0; end
8'h32: begin outa = 10'h010; outb = 2'b01; outc = 1'b0; end
8'h33: begin outa = 10'h1e0; outb = 2'b10; outc = 1'b0; end
8'h34: begin outa = 10'h079; outb = 2'b01; outc = 1'b1; end
8'h35: begin outa = 10'h13e; outb = 2'b10; outc = 1'b1; end
8'h36: begin outa = 10'h282; outb = 2'b11; outc = 1'b0; end
8'h37: begin outa = 10'h21c; outb = 2'b11; outc = 1'b1; end
8'h38: begin outa = 10'h148; outb = 2'b00; outc = 1'b1; end
8'h39: begin outa = 10'h3c0; outb = 2'b10; outc = 1'b0; end
8'h3a: begin outa = 10'h176; outb = 2'b01; outc = 1'b1; end
8'h3b: begin outa = 10'h3fc; outb = 2'b10; outc = 1'b1; end
8'h3c: begin outa = 10'h295; outb = 2'b11; outc = 1'b1; end
8'h3d: begin outa = 10'h113; outb = 2'b10; outc = 1'b1; end
8'h3e: begin outa = 10'h354; outb = 2'b01; outc = 1'b1; end
8'h3f: begin outa = 10'h0db; outb = 2'b11; outc = 1'b0; end
8'h40: begin outa = 10'h238; outb = 2'b01; outc = 1'b0; end
8'h41: begin outa = 10'h12b; outb = 2'b01; outc = 1'b1; end
8'h42: begin outa = 10'h1dc; outb = 2'b10; outc = 1'b0; end
8'h43: begin outa = 10'h137; outb = 2'b01; outc = 1'b1; end
8'h44: begin outa = 10'h1e2; outb = 2'b01; outc = 1'b1; end
8'h45: begin outa = 10'h3d5; outb = 2'b11; outc = 1'b1; end
8'h46: begin outa = 10'h30c; outb = 2'b11; outc = 1'b0; end
8'h47: begin outa = 10'h298; outb = 2'b11; outc = 1'b0; end
8'h48: begin outa = 10'h080; outb = 2'b00; outc = 1'b1; end
8'h49: begin outa = 10'h35a; outb = 2'b11; outc = 1'b1; end
8'h4a: begin outa = 10'h01b; outb = 2'b00; outc = 1'b0; end
8'h4b: begin outa = 10'h0a3; outb = 2'b11; outc = 1'b0; end
8'h4c: begin outa = 10'h0b3; outb = 2'b11; outc = 1'b1; end
8'h4d: begin outa = 10'h17a; outb = 2'b00; outc = 1'b0; end
8'h4e: begin outa = 10'h3ae; outb = 2'b11; outc = 1'b0; end
8'h4f: begin outa = 10'h078; outb = 2'b11; outc = 1'b0; end
8'h50: begin outa = 10'h322; outb = 2'b00; outc = 1'b1; end
8'h51: begin outa = 10'h213; outb = 2'b11; outc = 1'b0; end
8'h52: begin outa = 10'h11a; outb = 2'b11; outc = 1'b0; end
8'h53: begin outa = 10'h1a7; outb = 2'b00; outc = 1'b0; end
8'h54: begin outa = 10'h35a; outb = 2'b00; outc = 1'b1; end
8'h55: begin outa = 10'h233; outb = 2'b00; outc = 1'b0; end
8'h56: begin outa = 10'h01d; outb = 2'b01; outc = 1'b1; end
8'h57: begin outa = 10'h2d5; outb = 2'b00; outc = 1'b0; end
8'h58: begin outa = 10'h1a0; outb = 2'b00; outc = 1'b1; end
8'h59: begin outa = 10'h3d0; outb = 2'b00; outc = 1'b1; end
8'h5a: begin outa = 10'h181; outb = 2'b01; outc = 1'b1; end
8'h5b: begin outa = 10'h219; outb = 2'b01; outc = 1'b1; end
8'h5c: begin outa = 10'h26a; outb = 2'b01; outc = 1'b1; end
8'h5d: begin outa = 10'h050; outb = 2'b10; outc = 1'b0; end
8'h5e: begin outa = 10'h189; outb = 2'b10; outc = 1'b0; end
8'h5f: begin outa = 10'h1eb; outb = 2'b01; outc = 1'b1; end
8'h60: begin outa = 10'h224; outb = 2'b00; outc = 1'b1; end
8'h61: begin outa = 10'h2fe; outb = 2'b00; outc = 1'b0; end
8'h62: begin outa = 10'h0ae; outb = 2'b00; outc = 1'b1; end
8'h63: begin outa = 10'h1cd; outb = 2'b00; outc = 1'b0; end
8'h64: begin outa = 10'h273; outb = 2'b10; outc = 1'b1; end
8'h65: begin outa = 10'h268; outb = 2'b10; outc = 1'b0; end
8'h66: begin outa = 10'h111; outb = 2'b01; outc = 1'b0; end
8'h67: begin outa = 10'h1f9; outb = 2'b00; outc = 1'b0; end
8'h68: begin outa = 10'h232; outb = 2'b00; outc = 1'b1; end
8'h69: begin outa = 10'h255; outb = 2'b11; outc = 1'b0; end
8'h6a: begin outa = 10'h34c; outb = 2'b01; outc = 1'b1; end
8'h6b: begin outa = 10'h049; outb = 2'b01; outc = 1'b1; end
8'h6c: begin outa = 10'h197; outb = 2'b11; outc = 1'b0; end
8'h6d: begin outa = 10'h0fe; outb = 2'b11; outc = 1'b0; end
8'h6e: begin outa = 10'h253; outb = 2'b01; outc = 1'b1; end
8'h6f: begin outa = 10'h2de; outb = 2'b11; outc = 1'b0; end
8'h70: begin outa = 10'h13b; outb = 2'b10; outc = 1'b1; end
8'h71: begin outa = 10'h040; outb = 2'b10; outc = 1'b0; end
8'h72: begin outa = 10'h0b4; outb = 2'b00; outc = 1'b1; end
8'h73: begin outa = 10'h233; outb = 2'b11; outc = 1'b1; end
8'h74: begin outa = 10'h198; outb = 2'b00; outc = 1'b1; end
8'h75: begin outa = 10'h018; outb = 2'b00; outc = 1'b1; end
8'h76: begin outa = 10'h2f7; outb = 2'b00; outc = 1'b1; end
8'h77: begin outa = 10'h134; outb = 2'b11; outc = 1'b0; end
8'h78: begin outa = 10'h1ca; outb = 2'b10; outc = 1'b0; end
8'h79: begin outa = 10'h286; outb = 2'b10; outc = 1'b1; end
8'h7a: begin outa = 10'h0e6; outb = 2'b11; outc = 1'b1; end
8'h7b: begin outa = 10'h064; outb = 2'b10; outc = 1'b1; end
8'h7c: begin outa = 10'h257; outb = 2'b00; outc = 1'b1; end
8'h7d: begin outa = 10'h31a; outb = 2'b10; outc = 1'b1; end
8'h7e: begin outa = 10'h247; outb = 2'b01; outc = 1'b0; end
8'h7f: begin outa = 10'h299; outb = 2'b00; outc = 1'b0; end
8'h80: begin outa = 10'h02c; outb = 2'b00; outc = 1'b0; end
8'h81: begin outa = 10'h2bb; outb = 2'b11; outc = 1'b0; end
8'h82: begin outa = 10'h180; outb = 2'b10; outc = 1'b0; end
8'h83: begin outa = 10'h245; outb = 2'b01; outc = 1'b1; end
8'h84: begin outa = 10'h0da; outb = 2'b10; outc = 1'b0; end
8'h85: begin outa = 10'h367; outb = 2'b10; outc = 1'b0; end
8'h86: begin outa = 10'h304; outb = 2'b01; outc = 1'b0; end
8'h87: begin outa = 10'h38b; outb = 2'b11; outc = 1'b0; end
8'h88: begin outa = 10'h09f; outb = 2'b01; outc = 1'b0; end
8'h89: begin outa = 10'h1f0; outb = 2'b10; outc = 1'b1; end
8'h8a: begin outa = 10'h281; outb = 2'b10; outc = 1'b1; end
8'h8b: begin outa = 10'h019; outb = 2'b00; outc = 1'b0; end
8'h8c: begin outa = 10'h1f2; outb = 2'b10; outc = 1'b0; end
8'h8d: begin outa = 10'h0b1; outb = 2'b01; outc = 1'b1; end
8'h8e: begin outa = 10'h058; outb = 2'b01; outc = 1'b1; end
8'h8f: begin outa = 10'h39b; outb = 2'b00; outc = 1'b1; end
8'h90: begin outa = 10'h2ec; outb = 2'b10; outc = 1'b1; end
8'h91: begin outa = 10'h250; outb = 2'b00; outc = 1'b1; end
8'h92: begin outa = 10'h3f4; outb = 2'b10; outc = 1'b1; end
8'h93: begin outa = 10'h057; outb = 2'b10; outc = 1'b1; end
8'h94: begin outa = 10'h18f; outb = 2'b01; outc = 1'b1; end
8'h95: begin outa = 10'h105; outb = 2'b01; outc = 1'b1; end
8'h96: begin outa = 10'h1ae; outb = 2'b00; outc = 1'b1; end
8'h97: begin outa = 10'h04e; outb = 2'b10; outc = 1'b0; end
8'h98: begin outa = 10'h240; outb = 2'b11; outc = 1'b0; end
8'h99: begin outa = 10'h3e4; outb = 2'b01; outc = 1'b0; end
8'h9a: begin outa = 10'h3c6; outb = 2'b01; outc = 1'b0; end
8'h9b: begin outa = 10'h109; outb = 2'b00; outc = 1'b1; end
8'h9c: begin outa = 10'h073; outb = 2'b10; outc = 1'b1; end
8'h9d: begin outa = 10'h19f; outb = 2'b01; outc = 1'b0; end
8'h9e: begin outa = 10'h3b8; outb = 2'b01; outc = 1'b0; end
8'h9f: begin outa = 10'h00e; outb = 2'b00; outc = 1'b1; end
8'ha0: begin outa = 10'h1b3; outb = 2'b11; outc = 1'b1; end
8'ha1: begin outa = 10'h2bd; outb = 2'b11; outc = 1'b0; end
8'ha2: begin outa = 10'h324; outb = 2'b00; outc = 1'b1; end
8'ha3: begin outa = 10'h343; outb = 2'b10; outc = 1'b0; end
8'ha4: begin outa = 10'h1c9; outb = 2'b01; outc = 1'b0; end
8'ha5: begin outa = 10'h185; outb = 2'b00; outc = 1'b1; end
8'ha6: begin outa = 10'h37a; outb = 2'b00; outc = 1'b1; end
8'ha7: begin outa = 10'h0e0; outb = 2'b01; outc = 1'b1; end
8'ha8: begin outa = 10'h0a3; outb = 2'b10; outc = 1'b0; end
8'ha9: begin outa = 10'h019; outb = 2'b11; outc = 1'b0; end
8'haa: begin outa = 10'h099; outb = 2'b00; outc = 1'b1; end
8'hab: begin outa = 10'h376; outb = 2'b01; outc = 1'b1; end
8'hac: begin outa = 10'h077; outb = 2'b00; outc = 1'b1; end
8'had: begin outa = 10'h2b1; outb = 2'b11; outc = 1'b1; end
8'hae: begin outa = 10'h27f; outb = 2'b00; outc = 1'b0; end
8'haf: begin outa = 10'h265; outb = 2'b11; outc = 1'b0; end
8'hb0: begin outa = 10'h156; outb = 2'b10; outc = 1'b1; end
8'hb1: begin outa = 10'h1ce; outb = 2'b00; outc = 1'b0; end
8'hb2: begin outa = 10'h008; outb = 2'b01; outc = 1'b0; end
8'hb3: begin outa = 10'h12e; outb = 2'b11; outc = 1'b1; end
8'hb4: begin outa = 10'h199; outb = 2'b11; outc = 1'b0; end
8'hb5: begin outa = 10'h330; outb = 2'b10; outc = 1'b0; end
8'hb6: begin outa = 10'h1ab; outb = 2'b01; outc = 1'b1; end
8'hb7: begin outa = 10'h3bd; outb = 2'b00; outc = 1'b0; end
8'hb8: begin outa = 10'h0ca; outb = 2'b10; outc = 1'b0; end
8'hb9: begin outa = 10'h367; outb = 2'b00; outc = 1'b0; end
8'hba: begin outa = 10'h334; outb = 2'b00; outc = 1'b0; end
8'hbb: begin outa = 10'h040; outb = 2'b00; outc = 1'b1; end
8'hbc: begin outa = 10'h1a7; outb = 2'b10; outc = 1'b1; end
8'hbd: begin outa = 10'h036; outb = 2'b11; outc = 1'b1; end
8'hbe: begin outa = 10'h223; outb = 2'b11; outc = 1'b1; end
8'hbf: begin outa = 10'h075; outb = 2'b01; outc = 1'b0; end
8'hc0: begin outa = 10'h3c4; outb = 2'b00; outc = 1'b1; end
8'hc1: begin outa = 10'h2cc; outb = 2'b01; outc = 1'b0; end
8'hc2: begin outa = 10'h123; outb = 2'b01; outc = 1'b0; end
8'hc3: begin outa = 10'h3fd; outb = 2'b01; outc = 1'b1; end
8'hc4: begin outa = 10'h11e; outb = 2'b00; outc = 1'b0; end
8'hc5: begin outa = 10'h27c; outb = 2'b11; outc = 1'b1; end
8'hc6: begin outa = 10'h1e2; outb = 2'b11; outc = 1'b0; end
8'hc7: begin outa = 10'h377; outb = 2'b11; outc = 1'b0; end
8'hc8: begin outa = 10'h33a; outb = 2'b11; outc = 1'b0; end
8'hc9: begin outa = 10'h32d; outb = 2'b11; outc = 1'b1; end
8'hca: begin outa = 10'h014; outb = 2'b11; outc = 1'b0; end
8'hcb: begin outa = 10'h332; outb = 2'b10; outc = 1'b0; end
8'hcc: begin outa = 10'h359; outb = 2'b00; outc = 1'b0; end
8'hcd: begin outa = 10'h0a4; outb = 2'b10; outc = 1'b1; end
8'hce: begin outa = 10'h348; outb = 2'b00; outc = 1'b1; end
8'hcf: begin outa = 10'h04b; outb = 2'b11; outc = 1'b1; end
8'hd0: begin outa = 10'h147; outb = 2'b10; outc = 1'b1; end
8'hd1: begin outa = 10'h026; outb = 2'b00; outc = 1'b1; end
8'hd2: begin outa = 10'h103; outb = 2'b00; outc = 1'b0; end
8'hd3: begin outa = 10'h106; outb = 2'b00; outc = 1'b1; end
8'hd4: begin outa = 10'h35a; outb = 2'b00; outc = 1'b0; end
8'hd5: begin outa = 10'h254; outb = 2'b01; outc = 1'b0; end
8'hd6: begin outa = 10'h0cd; outb = 2'b01; outc = 1'b0; end
8'hd7: begin outa = 10'h17c; outb = 2'b11; outc = 1'b1; end
8'hd8: begin outa = 10'h37e; outb = 2'b10; outc = 1'b1; end
8'hd9: begin outa = 10'h0a9; outb = 2'b11; outc = 1'b1; end
8'hda: begin outa = 10'h0fe; outb = 2'b01; outc = 1'b0; end
8'hdb: begin outa = 10'h3c0; outb = 2'b11; outc = 1'b1; end
8'hdc: begin outa = 10'h1d9; outb = 2'b10; outc = 1'b1; end
8'hdd: begin outa = 10'h10e; outb = 2'b00; outc = 1'b1; end
8'hde: begin outa = 10'h394; outb = 2'b01; outc = 1'b0; end
8'hdf: begin outa = 10'h316; outb = 2'b01; outc = 1'b0; end
8'he0: begin outa = 10'h05b; outb = 2'b11; outc = 1'b0; end
8'he1: begin outa = 10'h126; outb = 2'b01; outc = 1'b1; end
8'he2: begin outa = 10'h369; outb = 2'b11; outc = 1'b0; end
8'he3: begin outa = 10'h291; outb = 2'b10; outc = 1'b1; end
8'he4: begin outa = 10'h2ca; outb = 2'b00; outc = 1'b1; end
8'he5: begin outa = 10'h25b; outb = 2'b01; outc = 1'b1; end
8'he6: begin outa = 10'h106; outb = 2'b00; outc = 1'b0; end
8'he7: begin outa = 10'h172; outb = 2'b11; outc = 1'b1; end
8'he8: begin outa = 10'h2f7; outb = 2'b00; outc = 1'b1; end
8'he9: begin outa = 10'h2d3; outb = 2'b11; outc = 1'b1; end
8'hea: begin outa = 10'h182; outb = 2'b00; outc = 1'b0; end
8'heb: begin outa = 10'h327; outb = 2'b00; outc = 1'b1; end
8'hec: begin outa = 10'h1d0; outb = 2'b10; outc = 1'b0; end
8'hed: begin outa = 10'h204; outb = 2'b00; outc = 1'b1; end
8'hee: begin outa = 10'h11f; outb = 2'b00; outc = 1'b1; end
8'hef: begin outa = 10'h365; outb = 2'b11; outc = 1'b1; end
8'hf0: begin outa = 10'h2c2; outb = 2'b01; outc = 1'b1; end
8'hf1: begin outa = 10'h2b5; outb = 2'b10; outc = 1'b0; end
8'hf2: begin outa = 10'h1f8; outb = 2'b10; outc = 1'b1; end
8'hf3: begin outa = 10'h2a7; outb = 2'b01; outc = 1'b1; end
8'hf4: begin outa = 10'h1be; outb = 2'b10; outc = 1'b1; end
8'hf5: begin outa = 10'h25e; outb = 2'b10; outc = 1'b1; end
8'hf6: begin outa = 10'h032; outb = 2'b10; outc = 1'b0; end
8'hf7: begin outa = 10'h2ef; outb = 2'b00; outc = 1'b0; end
8'hf8: begin outa = 10'h02f; outb = 2'b00; outc = 1'b1; end
8'hf9: begin outa = 10'h201; outb = 2'b10; outc = 1'b0; end
8'hfa: begin outa = 10'h054; outb = 2'b01; outc = 1'b1; end
8'hfb: begin outa = 10'h013; outb = 2'b10; outc = 1'b0; end
8'hfc: begin outa = 10'h249; outb = 2'b01; outc = 1'b0; end
8'hfd: begin outa = 10'h09a; outb = 2'b10; outc = 1'b0; end
8'hfe: begin outa = 10'h012; outb = 2'b00; outc = 1'b0; end
8'hff: begin outa = 10'h114; outb = 2'b10; outc = 1'b1; end
endcase
// verilog_format: on
end
endmodule

View File

@ -5,290 +5,286 @@
// SPDX-License-Identifier: CC0-1.0
module t_case_huge_sub2 (/*AUTOARG*/
// Outputs
outa,
// Inputs
index
);
// Outputs
outa,
// Inputs
index
);
input [9:0] index;
output [9:0] outa;
input [9:0] index;
output logic [9:0] outa;
// =============================
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [9:0] outa;
// End of automatics
// =============================
// Created from Python3:
// for i in range(1024):
// print(" 10'h%03x: begin outa = 10'h%03x; outb = 2'b%d%d; outc = 1'b%d; end"
// % (i, random.randint(0,1024), random.randint(0,1),
// random.randint(0,1), random.randint(0,1)))
// =============================
// Created from Python3:
// for i in range(1024):
// print(" 10'h%03x: begin outa = 10'h%03x; outb = 2'b%d%d; outc = 1'b%d; end"
// % (i, random.randint(0,1024), random.randint(0,1),
// random.randint(0,1), random.randint(0,1)))
always @(/*AS*/index) begin
case (index[7:0])
`ifdef VERILATOR // Harder test
8'h00: begin outa = $c("0"); end // Makes whole table non-optimizable
always @(/*AS*/index) begin
case (index[7:0])
`ifdef VERILATOR // Harder test
8'h00: begin
outa = $c("0");
end // Makes whole table non-optimizable
`else
8'h00: begin outa = 10'h0; end
8'h00: outa = 10'h0;
`endif
8'h01: begin outa = 10'h318; end
8'h02: begin outa = 10'h29f; end
8'h03: begin outa = 10'h392; end
8'h04: begin outa = 10'h1ef; end
8'h05: begin outa = 10'h06c; end
8'h06: begin outa = 10'h29f; end
8'h07: begin outa = 10'h29a; end
8'h08: begin outa = 10'h3ce; end
8'h09: begin outa = 10'h37c; end
8'h0a: begin outa = 10'h058; end
8'h0b: begin outa = 10'h3b2; end
8'h0c: begin outa = 10'h36f; end
8'h0d: begin outa = 10'h2c5; end
8'h0e: begin outa = 10'h23a; end
8'h0f: begin outa = 10'h222; end
8'h10: begin outa = 10'h328; end
8'h11: begin outa = 10'h3c3; end
8'h12: begin outa = 10'h12c; end
8'h13: begin outa = 10'h1d0; end
8'h14: begin outa = 10'h3ff; end
8'h15: begin outa = 10'h115; end
8'h16: begin outa = 10'h3ba; end
8'h17: begin outa = 10'h3ba; end
8'h18: begin outa = 10'h10d; end
8'h19: begin outa = 10'h13b; end
8'h1a: begin outa = 10'h0a0; end
8'h1b: begin outa = 10'h264; end
8'h1c: begin outa = 10'h3a2; end
8'h1d: begin outa = 10'h07c; end
8'h1e: begin outa = 10'h291; end
8'h1f: begin outa = 10'h1d1; end
8'h20: begin outa = 10'h354; end
8'h21: begin outa = 10'h0c0; end
8'h22: begin outa = 10'h191; end
8'h23: begin outa = 10'h379; end
8'h24: begin outa = 10'h073; end
8'h25: begin outa = 10'h2fd; end
8'h26: begin outa = 10'h2e0; end
8'h27: begin outa = 10'h337; end
8'h28: begin outa = 10'h2c7; end
8'h29: begin outa = 10'h19e; end
8'h2a: begin outa = 10'h107; end
8'h2b: begin outa = 10'h06a; end
8'h2c: begin outa = 10'h1c7; end
8'h2d: begin outa = 10'h107; end
8'h2e: begin outa = 10'h0cf; end
8'h2f: begin outa = 10'h009; end
8'h30: begin outa = 10'h09d; end
8'h31: begin outa = 10'h28e; end
8'h32: begin outa = 10'h010; end
8'h33: begin outa = 10'h1e0; end
8'h34: begin outa = 10'h079; end
8'h35: begin outa = 10'h13e; end
8'h36: begin outa = 10'h282; end
8'h37: begin outa = 10'h21c; end
8'h38: begin outa = 10'h148; end
8'h39: begin outa = 10'h3c0; end
8'h3a: begin outa = 10'h176; end
8'h3b: begin outa = 10'h3fc; end
8'h3c: begin outa = 10'h295; end
8'h3d: begin outa = 10'h113; end
8'h3e: begin outa = 10'h354; end
8'h3f: begin outa = 10'h0db; end
8'h40: begin outa = 10'h238; end
8'h41: begin outa = 10'h12b; end
8'h42: begin outa = 10'h1dc; end
8'h43: begin outa = 10'h137; end
8'h44: begin outa = 10'h1e2; end
8'h45: begin outa = 10'h3d5; end
8'h46: begin outa = 10'h30c; end
8'h47: begin outa = 10'h298; end
8'h48: begin outa = 10'h080; end
8'h49: begin outa = 10'h35a; end
8'h4a: begin outa = 10'h01b; end
8'h4b: begin outa = 10'h0a3; end
8'h4c: begin outa = 10'h0b3; end
8'h4d: begin outa = 10'h17a; end
8'h4e: begin outa = 10'h3ae; end
8'h4f: begin outa = 10'h078; end
8'h50: begin outa = 10'h322; end
8'h51: begin outa = 10'h213; end
8'h52: begin outa = 10'h11a; end
8'h53: begin outa = 10'h1a7; end
8'h54: begin outa = 10'h35a; end
8'h55: begin outa = 10'h233; end
8'h56: begin outa = 10'h01d; end
8'h57: begin outa = 10'h2d5; end
8'h58: begin outa = 10'h1a0; end
8'h59: begin outa = 10'h3d0; end
8'h5a: begin outa = 10'h181; end
8'h5b: begin outa = 10'h219; end
8'h5c: begin outa = 10'h26a; end
8'h5d: begin outa = 10'h050; end
8'h5e: begin outa = 10'h189; end
8'h5f: begin outa = 10'h1eb; end
8'h60: begin outa = 10'h224; end
8'h61: begin outa = 10'h2fe; end
8'h62: begin outa = 10'h0ae; end
8'h63: begin outa = 10'h1cd; end
8'h64: begin outa = 10'h273; end
8'h65: begin outa = 10'h268; end
8'h66: begin outa = 10'h111; end
8'h67: begin outa = 10'h1f9; end
8'h68: begin outa = 10'h232; end
8'h69: begin outa = 10'h255; end
8'h6a: begin outa = 10'h34c; end
8'h6b: begin outa = 10'h049; end
8'h6c: begin outa = 10'h197; end
8'h6d: begin outa = 10'h0fe; end
8'h6e: begin outa = 10'h253; end
8'h6f: begin outa = 10'h2de; end
8'h70: begin outa = 10'h13b; end
8'h71: begin outa = 10'h040; end
8'h72: begin outa = 10'h0b4; end
8'h73: begin outa = 10'h233; end
8'h74: begin outa = 10'h198; end
8'h75: begin outa = 10'h018; end
8'h76: begin outa = 10'h2f7; end
8'h77: begin outa = 10'h134; end
8'h78: begin outa = 10'h1ca; end
8'h79: begin outa = 10'h286; end
8'h7a: begin outa = 10'h0e6; end
8'h7b: begin outa = 10'h064; end
8'h7c: begin outa = 10'h257; end
8'h7d: begin outa = 10'h31a; end
8'h7e: begin outa = 10'h247; end
8'h7f: begin outa = 10'h299; end
8'h80: begin outa = 10'h02c; end
8'h81: begin outa = 10'h2bb; end
8'h82: begin outa = 10'h180; end
8'h83: begin outa = 10'h245; end
8'h84: begin outa = 10'h0da; end
8'h85: begin outa = 10'h367; end
8'h86: begin outa = 10'h304; end
8'h87: begin outa = 10'h38b; end
8'h88: begin outa = 10'h09f; end
8'h89: begin outa = 10'h1f0; end
8'h8a: begin outa = 10'h281; end
8'h8b: begin outa = 10'h019; end
8'h8c: begin outa = 10'h1f2; end
8'h8d: begin outa = 10'h0b1; end
8'h8e: begin outa = 10'h058; end
8'h8f: begin outa = 10'h39b; end
8'h90: begin outa = 10'h2ec; end
8'h91: begin outa = 10'h250; end
8'h92: begin outa = 10'h3f4; end
8'h93: begin outa = 10'h057; end
8'h94: begin outa = 10'h18f; end
8'h95: begin outa = 10'h105; end
8'h96: begin outa = 10'h1ae; end
8'h97: begin outa = 10'h04e; end
8'h98: begin outa = 10'h240; end
8'h99: begin outa = 10'h3e4; end
8'h9a: begin outa = 10'h3c6; end
8'h9b: begin outa = 10'h109; end
8'h9c: begin outa = 10'h073; end
8'h9d: begin outa = 10'h19f; end
8'h9e: begin outa = 10'h3b8; end
8'h9f: begin outa = 10'h00e; end
8'ha0: begin outa = 10'h1b3; end
8'ha1: begin outa = 10'h2bd; end
8'ha2: begin outa = 10'h324; end
8'ha3: begin outa = 10'h343; end
8'ha4: begin outa = 10'h1c9; end
8'ha5: begin outa = 10'h185; end
8'ha6: begin outa = 10'h37a; end
8'ha7: begin outa = 10'h0e0; end
8'ha8: begin outa = 10'h0a3; end
8'ha9: begin outa = 10'h019; end
8'haa: begin outa = 10'h099; end
8'hab: begin outa = 10'h376; end
8'hac: begin outa = 10'h077; end
8'had: begin outa = 10'h2b1; end
8'hae: begin outa = 10'h27f; end
8'haf: begin outa = 10'h265; end
8'hb0: begin outa = 10'h156; end
8'hb1: begin outa = 10'h1ce; end
8'hb2: begin outa = 10'h008; end
8'hb3: begin outa = 10'h12e; end
8'hb4: begin outa = 10'h199; end
8'hb5: begin outa = 10'h330; end
8'hb6: begin outa = 10'h1ab; end
8'hb7: begin outa = 10'h3bd; end
8'hb8: begin outa = 10'h0ca; end
8'hb9: begin outa = 10'h367; end
8'hba: begin outa = 10'h334; end
8'hbb: begin outa = 10'h040; end
8'hbc: begin outa = 10'h1a7; end
8'hbd: begin outa = 10'h036; end
8'hbe: begin outa = 10'h223; end
8'hbf: begin outa = 10'h075; end
8'hc0: begin outa = 10'h3c4; end
8'hc1: begin outa = 10'h2cc; end
8'hc2: begin outa = 10'h123; end
8'hc3: begin outa = 10'h3fd; end
8'hc4: begin outa = 10'h11e; end
8'hc5: begin outa = 10'h27c; end
8'hc6: begin outa = 10'h1e2; end
8'hc7: begin outa = 10'h377; end
8'hc8: begin outa = 10'h33a; end
8'hc9: begin outa = 10'h32d; end
8'hca: begin outa = 10'h014; end
8'hcb: begin outa = 10'h332; end
8'hcc: begin outa = 10'h359; end
8'hcd: begin outa = 10'h0a4; end
8'hce: begin outa = 10'h348; end
8'hcf: begin outa = 10'h04b; end
8'hd0: begin outa = 10'h147; end
8'hd1: begin outa = 10'h026; end
8'hd2: begin outa = 10'h103; end
8'hd3: begin outa = 10'h106; end
8'hd4: begin outa = 10'h35a; end
8'hd5: begin outa = 10'h254; end
8'hd6: begin outa = 10'h0cd; end
8'hd7: begin outa = 10'h17c; end
8'hd8: begin outa = 10'h37e; end
8'hd9: begin outa = 10'h0a9; end
8'hda: begin outa = 10'h0fe; end
8'hdb: begin outa = 10'h3c0; end
8'hdc: begin outa = 10'h1d9; end
8'hdd: begin outa = 10'h10e; end
8'hde: begin outa = 10'h394; end
8'hdf: begin outa = 10'h316; end
8'he0: begin outa = 10'h05b; end
8'he1: begin outa = 10'h126; end
8'he2: begin outa = 10'h369; end
8'he3: begin outa = 10'h291; end
8'he4: begin outa = 10'h2ca; end
8'he5: begin outa = 10'h25b; end
8'he6: begin outa = 10'h106; end
8'he7: begin outa = 10'h172; end
8'he8: begin outa = 10'h2f7; end
8'he9: begin outa = 10'h2d3; end
8'hea: begin outa = 10'h182; end
8'heb: begin outa = 10'h327; end
8'hec: begin outa = 10'h1d0; end
8'hed: begin outa = 10'h204; end
8'hee: begin outa = 10'h11f; end
8'hef: begin outa = 10'h365; end
8'hf0: begin outa = 10'h2c2; end
8'hf1: begin outa = 10'h2b5; end
8'hf2: begin outa = 10'h1f8; end
8'hf3: begin outa = 10'h2a7; end
8'hf4: begin outa = 10'h1be; end
8'hf5: begin outa = 10'h25e; end
8'hf6: begin outa = 10'h032; end
8'hf7: begin outa = 10'h2ef; end
8'hf8: begin outa = 10'h02f; end
8'hf9: begin outa = 10'h201; end
8'hfa: begin outa = 10'h054; end
8'hfb: begin outa = 10'h013; end
8'hfc: begin outa = 10'h249; end
8'hfd: begin outa = 10'h09a; end
8'hfe: begin outa = 10'h012; end
8'hff: begin outa = 10'h114; end
endcase
end
8'h01: outa = 10'h318;
8'h02: outa = 10'h29f;
8'h03: outa = 10'h392;
8'h04: outa = 10'h1ef;
8'h05: outa = 10'h06c;
8'h06: outa = 10'h29f;
8'h07: outa = 10'h29a;
8'h08: outa = 10'h3ce;
8'h09: outa = 10'h37c;
8'h0a: outa = 10'h058;
8'h0b: outa = 10'h3b2;
8'h0c: outa = 10'h36f;
8'h0d: outa = 10'h2c5;
8'h0e: outa = 10'h23a;
8'h0f: outa = 10'h222;
8'h10: outa = 10'h328;
8'h11: outa = 10'h3c3;
8'h12: outa = 10'h12c;
8'h13: outa = 10'h1d0;
8'h14: outa = 10'h3ff;
8'h15: outa = 10'h115;
8'h16: outa = 10'h3ba;
8'h17: outa = 10'h3ba;
8'h18: outa = 10'h10d;
8'h19: outa = 10'h13b;
8'h1a: outa = 10'h0a0;
8'h1b: outa = 10'h264;
8'h1c: outa = 10'h3a2;
8'h1d: outa = 10'h07c;
8'h1e: outa = 10'h291;
8'h1f: outa = 10'h1d1;
8'h20: outa = 10'h354;
8'h21: outa = 10'h0c0;
8'h22: outa = 10'h191;
8'h23: outa = 10'h379;
8'h24: outa = 10'h073;
8'h25: outa = 10'h2fd;
8'h26: outa = 10'h2e0;
8'h27: outa = 10'h337;
8'h28: outa = 10'h2c7;
8'h29: outa = 10'h19e;
8'h2a: outa = 10'h107;
8'h2b: outa = 10'h06a;
8'h2c: outa = 10'h1c7;
8'h2d: outa = 10'h107;
8'h2e: outa = 10'h0cf;
8'h2f: outa = 10'h009;
8'h30: outa = 10'h09d;
8'h31: outa = 10'h28e;
8'h32: outa = 10'h010;
8'h33: outa = 10'h1e0;
8'h34: outa = 10'h079;
8'h35: outa = 10'h13e;
8'h36: outa = 10'h282;
8'h37: outa = 10'h21c;
8'h38: outa = 10'h148;
8'h39: outa = 10'h3c0;
8'h3a: outa = 10'h176;
8'h3b: outa = 10'h3fc;
8'h3c: outa = 10'h295;
8'h3d: outa = 10'h113;
8'h3e: outa = 10'h354;
8'h3f: outa = 10'h0db;
8'h40: outa = 10'h238;
8'h41: outa = 10'h12b;
8'h42: outa = 10'h1dc;
8'h43: outa = 10'h137;
8'h44: outa = 10'h1e2;
8'h45: outa = 10'h3d5;
8'h46: outa = 10'h30c;
8'h47: outa = 10'h298;
8'h48: outa = 10'h080;
8'h49: outa = 10'h35a;
8'h4a: outa = 10'h01b;
8'h4b: outa = 10'h0a3;
8'h4c: outa = 10'h0b3;
8'h4d: outa = 10'h17a;
8'h4e: outa = 10'h3ae;
8'h4f: outa = 10'h078;
8'h50: outa = 10'h322;
8'h51: outa = 10'h213;
8'h52: outa = 10'h11a;
8'h53: outa = 10'h1a7;
8'h54: outa = 10'h35a;
8'h55: outa = 10'h233;
8'h56: outa = 10'h01d;
8'h57: outa = 10'h2d5;
8'h58: outa = 10'h1a0;
8'h59: outa = 10'h3d0;
8'h5a: outa = 10'h181;
8'h5b: outa = 10'h219;
8'h5c: outa = 10'h26a;
8'h5d: outa = 10'h050;
8'h5e: outa = 10'h189;
8'h5f: outa = 10'h1eb;
8'h60: outa = 10'h224;
8'h61: outa = 10'h2fe;
8'h62: outa = 10'h0ae;
8'h63: outa = 10'h1cd;
8'h64: outa = 10'h273;
8'h65: outa = 10'h268;
8'h66: outa = 10'h111;
8'h67: outa = 10'h1f9;
8'h68: outa = 10'h232;
8'h69: outa = 10'h255;
8'h6a: outa = 10'h34c;
8'h6b: outa = 10'h049;
8'h6c: outa = 10'h197;
8'h6d: outa = 10'h0fe;
8'h6e: outa = 10'h253;
8'h6f: outa = 10'h2de;
8'h70: outa = 10'h13b;
8'h71: outa = 10'h040;
8'h72: outa = 10'h0b4;
8'h73: outa = 10'h233;
8'h74: outa = 10'h198;
8'h75: outa = 10'h018;
8'h76: outa = 10'h2f7;
8'h77: outa = 10'h134;
8'h78: outa = 10'h1ca;
8'h79: outa = 10'h286;
8'h7a: outa = 10'h0e6;
8'h7b: outa = 10'h064;
8'h7c: outa = 10'h257;
8'h7d: outa = 10'h31a;
8'h7e: outa = 10'h247;
8'h7f: outa = 10'h299;
8'h80: outa = 10'h02c;
8'h81: outa = 10'h2bb;
8'h82: outa = 10'h180;
8'h83: outa = 10'h245;
8'h84: outa = 10'h0da;
8'h85: outa = 10'h367;
8'h86: outa = 10'h304;
8'h87: outa = 10'h38b;
8'h88: outa = 10'h09f;
8'h89: outa = 10'h1f0;
8'h8a: outa = 10'h281;
8'h8b: outa = 10'h019;
8'h8c: outa = 10'h1f2;
8'h8d: outa = 10'h0b1;
8'h8e: outa = 10'h058;
8'h8f: outa = 10'h39b;
8'h90: outa = 10'h2ec;
8'h91: outa = 10'h250;
8'h92: outa = 10'h3f4;
8'h93: outa = 10'h057;
8'h94: outa = 10'h18f;
8'h95: outa = 10'h105;
8'h96: outa = 10'h1ae;
8'h97: outa = 10'h04e;
8'h98: outa = 10'h240;
8'h99: outa = 10'h3e4;
8'h9a: outa = 10'h3c6;
8'h9b: outa = 10'h109;
8'h9c: outa = 10'h073;
8'h9d: outa = 10'h19f;
8'h9e: outa = 10'h3b8;
8'h9f: outa = 10'h00e;
8'ha0: outa = 10'h1b3;
8'ha1: outa = 10'h2bd;
8'ha2: outa = 10'h324;
8'ha3: outa = 10'h343;
8'ha4: outa = 10'h1c9;
8'ha5: outa = 10'h185;
8'ha6: outa = 10'h37a;
8'ha7: outa = 10'h0e0;
8'ha8: outa = 10'h0a3;
8'ha9: outa = 10'h019;
8'haa: outa = 10'h099;
8'hab: outa = 10'h376;
8'hac: outa = 10'h077;
8'had: outa = 10'h2b1;
8'hae: outa = 10'h27f;
8'haf: outa = 10'h265;
8'hb0: outa = 10'h156;
8'hb1: outa = 10'h1ce;
8'hb2: outa = 10'h008;
8'hb3: outa = 10'h12e;
8'hb4: outa = 10'h199;
8'hb5: outa = 10'h330;
8'hb6: outa = 10'h1ab;
8'hb7: outa = 10'h3bd;
8'hb8: outa = 10'h0ca;
8'hb9: outa = 10'h367;
8'hba: outa = 10'h334;
8'hbb: outa = 10'h040;
8'hbc: outa = 10'h1a7;
8'hbd: outa = 10'h036;
8'hbe: outa = 10'h223;
8'hbf: outa = 10'h075;
8'hc0: outa = 10'h3c4;
8'hc1: outa = 10'h2cc;
8'hc2: outa = 10'h123;
8'hc3: outa = 10'h3fd;
8'hc4: outa = 10'h11e;
8'hc5: outa = 10'h27c;
8'hc6: outa = 10'h1e2;
8'hc7: outa = 10'h377;
8'hc8: outa = 10'h33a;
8'hc9: outa = 10'h32d;
8'hca: outa = 10'h014;
8'hcb: outa = 10'h332;
8'hcc: outa = 10'h359;
8'hcd: outa = 10'h0a4;
8'hce: outa = 10'h348;
8'hcf: outa = 10'h04b;
8'hd0: outa = 10'h147;
8'hd1: outa = 10'h026;
8'hd2: outa = 10'h103;
8'hd3: outa = 10'h106;
8'hd4: outa = 10'h35a;
8'hd5: outa = 10'h254;
8'hd6: outa = 10'h0cd;
8'hd7: outa = 10'h17c;
8'hd8: outa = 10'h37e;
8'hd9: outa = 10'h0a9;
8'hda: outa = 10'h0fe;
8'hdb: outa = 10'h3c0;
8'hdc: outa = 10'h1d9;
8'hdd: outa = 10'h10e;
8'hde: outa = 10'h394;
8'hdf: outa = 10'h316;
8'he0: outa = 10'h05b;
8'he1: outa = 10'h126;
8'he2: outa = 10'h369;
8'he3: outa = 10'h291;
8'he4: outa = 10'h2ca;
8'he5: outa = 10'h25b;
8'he6: outa = 10'h106;
8'he7: outa = 10'h172;
8'he8: outa = 10'h2f7;
8'he9: outa = 10'h2d3;
8'hea: outa = 10'h182;
8'heb: outa = 10'h327;
8'hec: outa = 10'h1d0;
8'hed: outa = 10'h204;
8'hee: outa = 10'h11f;
8'hef: outa = 10'h365;
8'hf0: outa = 10'h2c2;
8'hf1: outa = 10'h2b5;
8'hf2: outa = 10'h1f8;
8'hf3: outa = 10'h2a7;
8'hf4: outa = 10'h1be;
8'hf5: outa = 10'h25e;
8'hf6: outa = 10'h032;
8'hf7: outa = 10'h2ef;
8'hf8: outa = 10'h02f;
8'hf9: outa = 10'h201;
8'hfa: outa = 10'h054;
8'hfb: outa = 10'h013;
8'hfc: outa = 10'h249;
8'hfd: outa = 10'h09a;
8'hfe: outa = 10'h012;
8'hff: outa = 10'h114;
endcase
end
endmodule

View File

@ -5,289 +5,285 @@
// SPDX-License-Identifier: CC0-1.0
module t_case_huge_sub3 (/*AUTOARG*/
// Outputs
outr,
// Inputs
clk, index
);
// Outputs
outr,
// Inputs
clk, index
);
input clk;
input [9:0] index;
output [3:0] outr;
input clk;
input [9:0] index;
output logic [3:0] outr;
// =============================
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [3:0] outr;
// End of automatics
// =============================
// Created from Pthon3:
// for i in range(256):
// print(" 8'h%02x: begin outr <= outr^index[8:5]^4'h%01x; end"
// % (i, random.randint(0,15)))
// =============================
// Created from Pthon3:
// for i in range(256):
// print(" 8'h%02x: begin outr <= outr^index[8:5]^4'h%01x; end"
// % (i, random.randint(0,15)))
// Reset cheating
initial outr = 4'b0;
// Reset cheating
initial outr = 4'b0;
always @(posedge clk) begin
case (index[7:0])
8'h00: begin outr <= 4'h0; end
8'h01: begin /*No Change*/ end
8'h02: begin outr <= outr^index[8:5]^4'ha; end
8'h03: begin outr <= outr^index[8:5]^4'h4; end
8'h04: begin outr <= outr^index[8:5]^4'hd; end
8'h05: begin outr <= outr^index[8:5]^4'h1; end
8'h06: begin outr <= outr^index[8:5]^4'hf; end
8'h07: begin outr <= outr^index[8:5]^4'he; end
8'h08: begin outr <= outr^index[8:5]^4'h0; end
8'h09: begin outr <= outr^index[8:5]^4'h4; end
8'h0a: begin outr <= outr^index[8:5]^4'h5; end
8'h0b: begin outr <= outr^index[8:5]^4'ha; end
8'h0c: begin outr <= outr^index[8:5]^4'h2; end
8'h0d: begin outr <= outr^index[8:5]^4'hf; end
8'h0e: begin outr <= outr^index[8:5]^4'h5; end
8'h0f: begin outr <= outr^index[8:5]^4'h0; end
8'h10: begin outr <= outr^index[8:5]^4'h3; end
8'h11: begin outr <= outr^index[8:5]^4'hb; end
8'h12: begin outr <= outr^index[8:5]^4'h0; end
8'h13: begin outr <= outr^index[8:5]^4'hf; end
8'h14: begin outr <= outr^index[8:5]^4'h3; end
8'h15: begin outr <= outr^index[8:5]^4'h5; end
8'h16: begin outr <= outr^index[8:5]^4'h7; end
8'h17: begin outr <= outr^index[8:5]^4'h2; end
8'h18: begin outr <= outr^index[8:5]^4'h3; end
8'h19: begin outr <= outr^index[8:5]^4'hb; end
8'h1a: begin outr <= outr^index[8:5]^4'h5; end
8'h1b: begin outr <= outr^index[8:5]^4'h4; end
8'h1c: begin outr <= outr^index[8:5]^4'h2; end
8'h1d: begin outr <= outr^index[8:5]^4'hf; end
8'h1e: begin outr <= outr^index[8:5]^4'h0; end
8'h1f: begin outr <= outr^index[8:5]^4'h4; end
8'h20: begin outr <= outr^index[8:5]^4'h6; end
8'h21: begin outr <= outr^index[8:5]^4'ha; end
8'h22: begin outr <= outr^index[8:5]^4'h6; end
8'h23: begin outr <= outr^index[8:5]^4'hb; end
8'h24: begin outr <= outr^index[8:5]^4'ha; end
8'h25: begin outr <= outr^index[8:5]^4'he; end
8'h26: begin outr <= outr^index[8:5]^4'h7; end
8'h27: begin outr <= outr^index[8:5]^4'ha; end
8'h28: begin outr <= outr^index[8:5]^4'h3; end
8'h29: begin outr <= outr^index[8:5]^4'h8; end
8'h2a: begin outr <= outr^index[8:5]^4'h1; end
8'h2b: begin outr <= outr^index[8:5]^4'h8; end
8'h2c: begin outr <= outr^index[8:5]^4'h4; end
8'h2d: begin outr <= outr^index[8:5]^4'h4; end
8'h2e: begin outr <= outr^index[8:5]^4'he; end
8'h2f: begin outr <= outr^index[8:5]^4'h8; end
8'h30: begin outr <= outr^index[8:5]^4'ha; end
8'h31: begin outr <= outr^index[8:5]^4'h7; end
8'h32: begin outr <= outr^index[8:5]^4'h0; end
8'h33: begin outr <= outr^index[8:5]^4'h3; end
8'h34: begin outr <= outr^index[8:5]^4'h1; end
8'h35: begin outr <= outr^index[8:5]^4'h3; end
8'h36: begin outr <= outr^index[8:5]^4'h4; end
8'h37: begin outr <= outr^index[8:5]^4'h6; end
8'h38: begin outr <= outr^index[8:5]^4'h4; end
8'h39: begin outr <= outr^index[8:5]^4'hb; end
8'h3a: begin outr <= outr^index[8:5]^4'h7; end
8'h3b: begin outr <= outr^index[8:5]^4'h1; end
8'h3c: begin outr <= outr^index[8:5]^4'h2; end
8'h3d: begin outr <= outr^index[8:5]^4'h0; end
8'h3e: begin outr <= outr^index[8:5]^4'h2; end
8'h3f: begin outr <= outr^index[8:5]^4'ha; end
8'h40: begin outr <= outr^index[8:5]^4'h7; end
8'h41: begin outr <= outr^index[8:5]^4'h5; end
8'h42: begin outr <= outr^index[8:5]^4'h5; end
8'h43: begin outr <= outr^index[8:5]^4'h4; end
8'h44: begin outr <= outr^index[8:5]^4'h8; end
8'h45: begin outr <= outr^index[8:5]^4'h5; end
8'h46: begin outr <= outr^index[8:5]^4'hf; end
8'h47: begin outr <= outr^index[8:5]^4'h6; end
8'h48: begin outr <= outr^index[8:5]^4'h7; end
8'h49: begin outr <= outr^index[8:5]^4'h4; end
8'h4a: begin outr <= outr^index[8:5]^4'ha; end
8'h4b: begin outr <= outr^index[8:5]^4'hd; end
8'h4c: begin outr <= outr^index[8:5]^4'hb; end
8'h4d: begin outr <= outr^index[8:5]^4'hf; end
8'h4e: begin outr <= outr^index[8:5]^4'hd; end
8'h4f: begin outr <= outr^index[8:5]^4'h7; end
8'h50: begin outr <= outr^index[8:5]^4'h9; end
8'h51: begin outr <= outr^index[8:5]^4'ha; end
8'h52: begin outr <= outr^index[8:5]^4'hf; end
8'h53: begin outr <= outr^index[8:5]^4'h3; end
8'h54: begin outr <= outr^index[8:5]^4'h1; end
8'h55: begin outr <= outr^index[8:5]^4'h0; end
8'h56: begin outr <= outr^index[8:5]^4'h2; end
8'h57: begin outr <= outr^index[8:5]^4'h9; end
8'h58: begin outr <= outr^index[8:5]^4'h2; end
8'h59: begin outr <= outr^index[8:5]^4'h4; end
8'h5a: begin outr <= outr^index[8:5]^4'hc; end
8'h5b: begin outr <= outr^index[8:5]^4'hd; end
8'h5c: begin outr <= outr^index[8:5]^4'h3; end
8'h5d: begin outr <= outr^index[8:5]^4'hb; end
8'h5e: begin outr <= outr^index[8:5]^4'hd; end
8'h5f: begin outr <= outr^index[8:5]^4'h7; end
8'h60: begin outr <= outr^index[8:5]^4'h7; end
8'h61: begin outr <= outr^index[8:5]^4'h3; end
8'h62: begin outr <= outr^index[8:5]^4'h3; end
8'h63: begin outr <= outr^index[8:5]^4'hb; end
8'h64: begin outr <= outr^index[8:5]^4'h9; end
8'h65: begin outr <= outr^index[8:5]^4'h4; end
8'h66: begin outr <= outr^index[8:5]^4'h3; end
8'h67: begin outr <= outr^index[8:5]^4'h6; end
8'h68: begin outr <= outr^index[8:5]^4'h7; end
8'h69: begin outr <= outr^index[8:5]^4'h7; end
8'h6a: begin outr <= outr^index[8:5]^4'hf; end
8'h6b: begin outr <= outr^index[8:5]^4'h6; end
8'h6c: begin outr <= outr^index[8:5]^4'h8; end
8'h6d: begin outr <= outr^index[8:5]^4'he; end
8'h6e: begin outr <= outr^index[8:5]^4'h4; end
8'h6f: begin outr <= outr^index[8:5]^4'h6; end
8'h70: begin outr <= outr^index[8:5]^4'hc; end
8'h71: begin outr <= outr^index[8:5]^4'h9; end
8'h72: begin outr <= outr^index[8:5]^4'h5; end
8'h73: begin outr <= outr^index[8:5]^4'ha; end
8'h74: begin outr <= outr^index[8:5]^4'h7; end
8'h75: begin outr <= outr^index[8:5]^4'h0; end
8'h76: begin outr <= outr^index[8:5]^4'h1; end
8'h77: begin outr <= outr^index[8:5]^4'he; end
8'h78: begin outr <= outr^index[8:5]^4'ha; end
8'h79: begin outr <= outr^index[8:5]^4'h7; end
8'h7a: begin outr <= outr^index[8:5]^4'hf; end
8'h7b: begin outr <= outr^index[8:5]^4'he; end
8'h7c: begin outr <= outr^index[8:5]^4'h6; end
8'h7d: begin outr <= outr^index[8:5]^4'hc; end
8'h7e: begin outr <= outr^index[8:5]^4'hc; end
8'h7f: begin outr <= outr^index[8:5]^4'h0; end
8'h80: begin outr <= outr^index[8:5]^4'h0; end
8'h81: begin outr <= outr^index[8:5]^4'hd; end
8'h82: begin outr <= outr^index[8:5]^4'hb; end
8'h83: begin outr <= outr^index[8:5]^4'hc; end
8'h84: begin outr <= outr^index[8:5]^4'h2; end
8'h85: begin outr <= outr^index[8:5]^4'h8; end
8'h86: begin outr <= outr^index[8:5]^4'h3; end
8'h87: begin outr <= outr^index[8:5]^4'ha; end
8'h88: begin outr <= outr^index[8:5]^4'he; end
8'h89: begin outr <= outr^index[8:5]^4'h9; end
8'h8a: begin outr <= outr^index[8:5]^4'h1; end
8'h8b: begin outr <= outr^index[8:5]^4'h1; end
8'h8c: begin outr <= outr^index[8:5]^4'hc; end
8'h8d: begin outr <= outr^index[8:5]^4'h2; end
8'h8e: begin outr <= outr^index[8:5]^4'h2; end
8'h8f: begin outr <= outr^index[8:5]^4'hd; end
8'h90: begin outr <= outr^index[8:5]^4'h0; end
8'h91: begin outr <= outr^index[8:5]^4'h6; end
8'h92: begin outr <= outr^index[8:5]^4'h7; end
8'h93: begin outr <= outr^index[8:5]^4'hc; end
8'h94: begin outr <= outr^index[8:5]^4'hb; end
8'h95: begin outr <= outr^index[8:5]^4'h3; end
8'h96: begin outr <= outr^index[8:5]^4'h0; end
8'h97: begin outr <= outr^index[8:5]^4'hc; end
8'h98: begin outr <= outr^index[8:5]^4'hc; end
8'h99: begin outr <= outr^index[8:5]^4'hb; end
8'h9a: begin outr <= outr^index[8:5]^4'h6; end
8'h9b: begin outr <= outr^index[8:5]^4'h5; end
8'h9c: begin outr <= outr^index[8:5]^4'h5; end
8'h9d: begin outr <= outr^index[8:5]^4'h4; end
8'h9e: begin outr <= outr^index[8:5]^4'h7; end
8'h9f: begin outr <= outr^index[8:5]^4'he; end
8'ha0: begin outr <= outr^index[8:5]^4'hc; end
8'ha1: begin outr <= outr^index[8:5]^4'hc; end
8'ha2: begin outr <= outr^index[8:5]^4'h0; end
8'ha3: begin outr <= outr^index[8:5]^4'h1; end
8'ha4: begin outr <= outr^index[8:5]^4'hd; end
8'ha5: begin outr <= outr^index[8:5]^4'h3; end
8'ha6: begin outr <= outr^index[8:5]^4'hc; end
8'ha7: begin outr <= outr^index[8:5]^4'h2; end
8'ha8: begin outr <= outr^index[8:5]^4'h3; end
8'ha9: begin outr <= outr^index[8:5]^4'hd; end
8'haa: begin outr <= outr^index[8:5]^4'h5; end
8'hab: begin outr <= outr^index[8:5]^4'hb; end
8'hac: begin outr <= outr^index[8:5]^4'he; end
8'had: begin outr <= outr^index[8:5]^4'h0; end
8'hae: begin outr <= outr^index[8:5]^4'hf; end
8'haf: begin outr <= outr^index[8:5]^4'h9; end
8'hb0: begin outr <= outr^index[8:5]^4'hf; end
8'hb1: begin outr <= outr^index[8:5]^4'h7; end
8'hb2: begin outr <= outr^index[8:5]^4'h9; end
8'hb3: begin outr <= outr^index[8:5]^4'hf; end
8'hb4: begin outr <= outr^index[8:5]^4'he; end
8'hb5: begin outr <= outr^index[8:5]^4'h3; end
8'hb6: begin outr <= outr^index[8:5]^4'he; end
8'hb7: begin outr <= outr^index[8:5]^4'h8; end
8'hb8: begin outr <= outr^index[8:5]^4'hf; end
8'hb9: begin outr <= outr^index[8:5]^4'hd; end
8'hba: begin outr <= outr^index[8:5]^4'h3; end
8'hbb: begin outr <= outr^index[8:5]^4'h5; end
8'hbc: begin outr <= outr^index[8:5]^4'hd; end
8'hbd: begin outr <= outr^index[8:5]^4'ha; end
8'hbe: begin outr <= outr^index[8:5]^4'h7; end
8'hbf: begin outr <= outr^index[8:5]^4'he; end
8'hc0: begin outr <= outr^index[8:5]^4'h2; end
8'hc1: begin outr <= outr^index[8:5]^4'he; end
8'hc2: begin outr <= outr^index[8:5]^4'h9; end
8'hc3: begin outr <= outr^index[8:5]^4'hb; end
8'hc4: begin outr <= outr^index[8:5]^4'h0; end
8'hc5: begin outr <= outr^index[8:5]^4'h5; end
8'hc6: begin outr <= outr^index[8:5]^4'h9; end
8'hc7: begin outr <= outr^index[8:5]^4'h6; end
8'hc8: begin outr <= outr^index[8:5]^4'ha; end
8'hc9: begin outr <= outr^index[8:5]^4'hf; end
8'hca: begin outr <= outr^index[8:5]^4'h3; end
8'hcb: begin outr <= outr^index[8:5]^4'hb; end
8'hcc: begin outr <= outr^index[8:5]^4'he; end
8'hcd: begin outr <= outr^index[8:5]^4'h2; end
8'hce: begin outr <= outr^index[8:5]^4'h5; end
8'hcf: begin outr <= outr^index[8:5]^4'hf; end
8'hd0: begin outr <= outr^index[8:5]^4'h2; end
8'hd1: begin outr <= outr^index[8:5]^4'h9; end
8'hd2: begin outr <= outr^index[8:5]^4'hb; end
8'hd3: begin outr <= outr^index[8:5]^4'h8; end
8'hd4: begin outr <= outr^index[8:5]^4'h0; end
8'hd5: begin outr <= outr^index[8:5]^4'h2; end
8'hd6: begin outr <= outr^index[8:5]^4'hb; end
8'hd7: begin outr <= outr^index[8:5]^4'h2; end
8'hd8: begin outr <= outr^index[8:5]^4'ha; end
8'hd9: begin outr <= outr^index[8:5]^4'hf; end
8'hda: begin outr <= outr^index[8:5]^4'h8; end
8'hdb: begin outr <= outr^index[8:5]^4'h4; end
8'hdc: begin outr <= outr^index[8:5]^4'he; end
8'hdd: begin outr <= outr^index[8:5]^4'h6; end
8'hde: begin outr <= outr^index[8:5]^4'h9; end
8'hdf: begin outr <= outr^index[8:5]^4'h9; end
8'he0: begin outr <= outr^index[8:5]^4'h7; end
8'he1: begin outr <= outr^index[8:5]^4'h0; end
8'he2: begin outr <= outr^index[8:5]^4'h9; end
8'he3: begin outr <= outr^index[8:5]^4'h3; end
8'he4: begin outr <= outr^index[8:5]^4'h2; end
8'he5: begin outr <= outr^index[8:5]^4'h4; end
8'he6: begin outr <= outr^index[8:5]^4'h5; end
8'he7: begin outr <= outr^index[8:5]^4'h5; end
8'he8: begin outr <= outr^index[8:5]^4'hf; end
8'he9: begin outr <= outr^index[8:5]^4'ha; end
8'hea: begin outr <= outr^index[8:5]^4'hc; end
8'heb: begin outr <= outr^index[8:5]^4'hd; end
8'hec: begin outr <= outr^index[8:5]^4'h1; end
8'hed: begin outr <= outr^index[8:5]^4'h5; end
8'hee: begin outr <= outr^index[8:5]^4'h9; end
8'hef: begin outr <= outr^index[8:5]^4'h0; end
8'hf0: begin outr <= outr^index[8:5]^4'hd; end
8'hf1: begin outr <= outr^index[8:5]^4'hf; end
8'hf2: begin outr <= outr^index[8:5]^4'h4; end
8'hf3: begin outr <= outr^index[8:5]^4'ha; end
8'hf4: begin outr <= outr^index[8:5]^4'h8; end
8'hf5: begin outr <= outr^index[8:5]^4'he; end
8'hf6: begin outr <= outr^index[8:5]^4'he; end
8'hf7: begin outr <= outr^index[8:5]^4'h1; end
8'hf8: begin outr <= outr^index[8:5]^4'h6; end
8'hf9: begin outr <= outr^index[8:5]^4'h0; end
8'hfa: begin outr <= outr^index[8:5]^4'h5; end
8'hfb: begin outr <= outr^index[8:5]^4'h1; end
8'hfc: begin outr <= outr^index[8:5]^4'h8; end
8'hfd: begin outr <= outr^index[8:5]^4'h6; end
8'hfe: begin outr <= outr^index[8:5]^4'h1; end
default: begin outr <= outr^index[8:5]^4'h6; end
endcase
end
always @(posedge clk) begin
// verilog_format: off
case (index[7:0])
8'h00: begin outr <= 4'h0; end
8'h01: begin /*No Change*/ end
8'h02: begin outr <= outr^index[8:5]^4'ha; end
8'h03: begin outr <= outr^index[8:5]^4'h4; end
8'h04: begin outr <= outr^index[8:5]^4'hd; end
8'h05: begin outr <= outr^index[8:5]^4'h1; end
8'h06: begin outr <= outr^index[8:5]^4'hf; end
8'h07: begin outr <= outr^index[8:5]^4'he; end
8'h08: begin outr <= outr^index[8:5]^4'h0; end
8'h09: begin outr <= outr^index[8:5]^4'h4; end
8'h0a: begin outr <= outr^index[8:5]^4'h5; end
8'h0b: begin outr <= outr^index[8:5]^4'ha; end
8'h0c: begin outr <= outr^index[8:5]^4'h2; end
8'h0d: begin outr <= outr^index[8:5]^4'hf; end
8'h0e: begin outr <= outr^index[8:5]^4'h5; end
8'h0f: begin outr <= outr^index[8:5]^4'h0; end
8'h10: begin outr <= outr^index[8:5]^4'h3; end
8'h11: begin outr <= outr^index[8:5]^4'hb; end
8'h12: begin outr <= outr^index[8:5]^4'h0; end
8'h13: begin outr <= outr^index[8:5]^4'hf; end
8'h14: begin outr <= outr^index[8:5]^4'h3; end
8'h15: begin outr <= outr^index[8:5]^4'h5; end
8'h16: begin outr <= outr^index[8:5]^4'h7; end
8'h17: begin outr <= outr^index[8:5]^4'h2; end
8'h18: begin outr <= outr^index[8:5]^4'h3; end
8'h19: begin outr <= outr^index[8:5]^4'hb; end
8'h1a: begin outr <= outr^index[8:5]^4'h5; end
8'h1b: begin outr <= outr^index[8:5]^4'h4; end
8'h1c: begin outr <= outr^index[8:5]^4'h2; end
8'h1d: begin outr <= outr^index[8:5]^4'hf; end
8'h1e: begin outr <= outr^index[8:5]^4'h0; end
8'h1f: begin outr <= outr^index[8:5]^4'h4; end
8'h20: begin outr <= outr^index[8:5]^4'h6; end
8'h21: begin outr <= outr^index[8:5]^4'ha; end
8'h22: begin outr <= outr^index[8:5]^4'h6; end
8'h23: begin outr <= outr^index[8:5]^4'hb; end
8'h24: begin outr <= outr^index[8:5]^4'ha; end
8'h25: begin outr <= outr^index[8:5]^4'he; end
8'h26: begin outr <= outr^index[8:5]^4'h7; end
8'h27: begin outr <= outr^index[8:5]^4'ha; end
8'h28: begin outr <= outr^index[8:5]^4'h3; end
8'h29: begin outr <= outr^index[8:5]^4'h8; end
8'h2a: begin outr <= outr^index[8:5]^4'h1; end
8'h2b: begin outr <= outr^index[8:5]^4'h8; end
8'h2c: begin outr <= outr^index[8:5]^4'h4; end
8'h2d: begin outr <= outr^index[8:5]^4'h4; end
8'h2e: begin outr <= outr^index[8:5]^4'he; end
8'h2f: begin outr <= outr^index[8:5]^4'h8; end
8'h30: begin outr <= outr^index[8:5]^4'ha; end
8'h31: begin outr <= outr^index[8:5]^4'h7; end
8'h32: begin outr <= outr^index[8:5]^4'h0; end
8'h33: begin outr <= outr^index[8:5]^4'h3; end
8'h34: begin outr <= outr^index[8:5]^4'h1; end
8'h35: begin outr <= outr^index[8:5]^4'h3; end
8'h36: begin outr <= outr^index[8:5]^4'h4; end
8'h37: begin outr <= outr^index[8:5]^4'h6; end
8'h38: begin outr <= outr^index[8:5]^4'h4; end
8'h39: begin outr <= outr^index[8:5]^4'hb; end
8'h3a: begin outr <= outr^index[8:5]^4'h7; end
8'h3b: begin outr <= outr^index[8:5]^4'h1; end
8'h3c: begin outr <= outr^index[8:5]^4'h2; end
8'h3d: begin outr <= outr^index[8:5]^4'h0; end
8'h3e: begin outr <= outr^index[8:5]^4'h2; end
8'h3f: begin outr <= outr^index[8:5]^4'ha; end
8'h40: begin outr <= outr^index[8:5]^4'h7; end
8'h41: begin outr <= outr^index[8:5]^4'h5; end
8'h42: begin outr <= outr^index[8:5]^4'h5; end
8'h43: begin outr <= outr^index[8:5]^4'h4; end
8'h44: begin outr <= outr^index[8:5]^4'h8; end
8'h45: begin outr <= outr^index[8:5]^4'h5; end
8'h46: begin outr <= outr^index[8:5]^4'hf; end
8'h47: begin outr <= outr^index[8:5]^4'h6; end
8'h48: begin outr <= outr^index[8:5]^4'h7; end
8'h49: begin outr <= outr^index[8:5]^4'h4; end
8'h4a: begin outr <= outr^index[8:5]^4'ha; end
8'h4b: begin outr <= outr^index[8:5]^4'hd; end
8'h4c: begin outr <= outr^index[8:5]^4'hb; end
8'h4d: begin outr <= outr^index[8:5]^4'hf; end
8'h4e: begin outr <= outr^index[8:5]^4'hd; end
8'h4f: begin outr <= outr^index[8:5]^4'h7; end
8'h50: begin outr <= outr^index[8:5]^4'h9; end
8'h51: begin outr <= outr^index[8:5]^4'ha; end
8'h52: begin outr <= outr^index[8:5]^4'hf; end
8'h53: begin outr <= outr^index[8:5]^4'h3; end
8'h54: begin outr <= outr^index[8:5]^4'h1; end
8'h55: begin outr <= outr^index[8:5]^4'h0; end
8'h56: begin outr <= outr^index[8:5]^4'h2; end
8'h57: begin outr <= outr^index[8:5]^4'h9; end
8'h58: begin outr <= outr^index[8:5]^4'h2; end
8'h59: begin outr <= outr^index[8:5]^4'h4; end
8'h5a: begin outr <= outr^index[8:5]^4'hc; end
8'h5b: begin outr <= outr^index[8:5]^4'hd; end
8'h5c: begin outr <= outr^index[8:5]^4'h3; end
8'h5d: begin outr <= outr^index[8:5]^4'hb; end
8'h5e: begin outr <= outr^index[8:5]^4'hd; end
8'h5f: begin outr <= outr^index[8:5]^4'h7; end
8'h60: begin outr <= outr^index[8:5]^4'h7; end
8'h61: begin outr <= outr^index[8:5]^4'h3; end
8'h62: begin outr <= outr^index[8:5]^4'h3; end
8'h63: begin outr <= outr^index[8:5]^4'hb; end
8'h64: begin outr <= outr^index[8:5]^4'h9; end
8'h65: begin outr <= outr^index[8:5]^4'h4; end
8'h66: begin outr <= outr^index[8:5]^4'h3; end
8'h67: begin outr <= outr^index[8:5]^4'h6; end
8'h68: begin outr <= outr^index[8:5]^4'h7; end
8'h69: begin outr <= outr^index[8:5]^4'h7; end
8'h6a: begin outr <= outr^index[8:5]^4'hf; end
8'h6b: begin outr <= outr^index[8:5]^4'h6; end
8'h6c: begin outr <= outr^index[8:5]^4'h8; end
8'h6d: begin outr <= outr^index[8:5]^4'he; end
8'h6e: begin outr <= outr^index[8:5]^4'h4; end
8'h6f: begin outr <= outr^index[8:5]^4'h6; end
8'h70: begin outr <= outr^index[8:5]^4'hc; end
8'h71: begin outr <= outr^index[8:5]^4'h9; end
8'h72: begin outr <= outr^index[8:5]^4'h5; end
8'h73: begin outr <= outr^index[8:5]^4'ha; end
8'h74: begin outr <= outr^index[8:5]^4'h7; end
8'h75: begin outr <= outr^index[8:5]^4'h0; end
8'h76: begin outr <= outr^index[8:5]^4'h1; end
8'h77: begin outr <= outr^index[8:5]^4'he; end
8'h78: begin outr <= outr^index[8:5]^4'ha; end
8'h79: begin outr <= outr^index[8:5]^4'h7; end
8'h7a: begin outr <= outr^index[8:5]^4'hf; end
8'h7b: begin outr <= outr^index[8:5]^4'he; end
8'h7c: begin outr <= outr^index[8:5]^4'h6; end
8'h7d: begin outr <= outr^index[8:5]^4'hc; end
8'h7e: begin outr <= outr^index[8:5]^4'hc; end
8'h7f: begin outr <= outr^index[8:5]^4'h0; end
8'h80: begin outr <= outr^index[8:5]^4'h0; end
8'h81: begin outr <= outr^index[8:5]^4'hd; end
8'h82: begin outr <= outr^index[8:5]^4'hb; end
8'h83: begin outr <= outr^index[8:5]^4'hc; end
8'h84: begin outr <= outr^index[8:5]^4'h2; end
8'h85: begin outr <= outr^index[8:5]^4'h8; end
8'h86: begin outr <= outr^index[8:5]^4'h3; end
8'h87: begin outr <= outr^index[8:5]^4'ha; end
8'h88: begin outr <= outr^index[8:5]^4'he; end
8'h89: begin outr <= outr^index[8:5]^4'h9; end
8'h8a: begin outr <= outr^index[8:5]^4'h1; end
8'h8b: begin outr <= outr^index[8:5]^4'h1; end
8'h8c: begin outr <= outr^index[8:5]^4'hc; end
8'h8d: begin outr <= outr^index[8:5]^4'h2; end
8'h8e: begin outr <= outr^index[8:5]^4'h2; end
8'h8f: begin outr <= outr^index[8:5]^4'hd; end
8'h90: begin outr <= outr^index[8:5]^4'h0; end
8'h91: begin outr <= outr^index[8:5]^4'h6; end
8'h92: begin outr <= outr^index[8:5]^4'h7; end
8'h93: begin outr <= outr^index[8:5]^4'hc; end
8'h94: begin outr <= outr^index[8:5]^4'hb; end
8'h95: begin outr <= outr^index[8:5]^4'h3; end
8'h96: begin outr <= outr^index[8:5]^4'h0; end
8'h97: begin outr <= outr^index[8:5]^4'hc; end
8'h98: begin outr <= outr^index[8:5]^4'hc; end
8'h99: begin outr <= outr^index[8:5]^4'hb; end
8'h9a: begin outr <= outr^index[8:5]^4'h6; end
8'h9b: begin outr <= outr^index[8:5]^4'h5; end
8'h9c: begin outr <= outr^index[8:5]^4'h5; end
8'h9d: begin outr <= outr^index[8:5]^4'h4; end
8'h9e: begin outr <= outr^index[8:5]^4'h7; end
8'h9f: begin outr <= outr^index[8:5]^4'he; end
8'ha0: begin outr <= outr^index[8:5]^4'hc; end
8'ha1: begin outr <= outr^index[8:5]^4'hc; end
8'ha2: begin outr <= outr^index[8:5]^4'h0; end
8'ha3: begin outr <= outr^index[8:5]^4'h1; end
8'ha4: begin outr <= outr^index[8:5]^4'hd; end
8'ha5: begin outr <= outr^index[8:5]^4'h3; end
8'ha6: begin outr <= outr^index[8:5]^4'hc; end
8'ha7: begin outr <= outr^index[8:5]^4'h2; end
8'ha8: begin outr <= outr^index[8:5]^4'h3; end
8'ha9: begin outr <= outr^index[8:5]^4'hd; end
8'haa: begin outr <= outr^index[8:5]^4'h5; end
8'hab: begin outr <= outr^index[8:5]^4'hb; end
8'hac: begin outr <= outr^index[8:5]^4'he; end
8'had: begin outr <= outr^index[8:5]^4'h0; end
8'hae: begin outr <= outr^index[8:5]^4'hf; end
8'haf: begin outr <= outr^index[8:5]^4'h9; end
8'hb0: begin outr <= outr^index[8:5]^4'hf; end
8'hb1: begin outr <= outr^index[8:5]^4'h7; end
8'hb2: begin outr <= outr^index[8:5]^4'h9; end
8'hb3: begin outr <= outr^index[8:5]^4'hf; end
8'hb4: begin outr <= outr^index[8:5]^4'he; end
8'hb5: begin outr <= outr^index[8:5]^4'h3; end
8'hb6: begin outr <= outr^index[8:5]^4'he; end
8'hb7: begin outr <= outr^index[8:5]^4'h8; end
8'hb8: begin outr <= outr^index[8:5]^4'hf; end
8'hb9: begin outr <= outr^index[8:5]^4'hd; end
8'hba: begin outr <= outr^index[8:5]^4'h3; end
8'hbb: begin outr <= outr^index[8:5]^4'h5; end
8'hbc: begin outr <= outr^index[8:5]^4'hd; end
8'hbd: begin outr <= outr^index[8:5]^4'ha; end
8'hbe: begin outr <= outr^index[8:5]^4'h7; end
8'hbf: begin outr <= outr^index[8:5]^4'he; end
8'hc0: begin outr <= outr^index[8:5]^4'h2; end
8'hc1: begin outr <= outr^index[8:5]^4'he; end
8'hc2: begin outr <= outr^index[8:5]^4'h9; end
8'hc3: begin outr <= outr^index[8:5]^4'hb; end
8'hc4: begin outr <= outr^index[8:5]^4'h0; end
8'hc5: begin outr <= outr^index[8:5]^4'h5; end
8'hc6: begin outr <= outr^index[8:5]^4'h9; end
8'hc7: begin outr <= outr^index[8:5]^4'h6; end
8'hc8: begin outr <= outr^index[8:5]^4'ha; end
8'hc9: begin outr <= outr^index[8:5]^4'hf; end
8'hca: begin outr <= outr^index[8:5]^4'h3; end
8'hcb: begin outr <= outr^index[8:5]^4'hb; end
8'hcc: begin outr <= outr^index[8:5]^4'he; end
8'hcd: begin outr <= outr^index[8:5]^4'h2; end
8'hce: begin outr <= outr^index[8:5]^4'h5; end
8'hcf: begin outr <= outr^index[8:5]^4'hf; end
8'hd0: begin outr <= outr^index[8:5]^4'h2; end
8'hd1: begin outr <= outr^index[8:5]^4'h9; end
8'hd2: begin outr <= outr^index[8:5]^4'hb; end
8'hd3: begin outr <= outr^index[8:5]^4'h8; end
8'hd4: begin outr <= outr^index[8:5]^4'h0; end
8'hd5: begin outr <= outr^index[8:5]^4'h2; end
8'hd6: begin outr <= outr^index[8:5]^4'hb; end
8'hd7: begin outr <= outr^index[8:5]^4'h2; end
8'hd8: begin outr <= outr^index[8:5]^4'ha; end
8'hd9: begin outr <= outr^index[8:5]^4'hf; end
8'hda: begin outr <= outr^index[8:5]^4'h8; end
8'hdb: begin outr <= outr^index[8:5]^4'h4; end
8'hdc: begin outr <= outr^index[8:5]^4'he; end
8'hdd: begin outr <= outr^index[8:5]^4'h6; end
8'hde: begin outr <= outr^index[8:5]^4'h9; end
8'hdf: begin outr <= outr^index[8:5]^4'h9; end
8'he0: begin outr <= outr^index[8:5]^4'h7; end
8'he1: begin outr <= outr^index[8:5]^4'h0; end
8'he2: begin outr <= outr^index[8:5]^4'h9; end
8'he3: begin outr <= outr^index[8:5]^4'h3; end
8'he4: begin outr <= outr^index[8:5]^4'h2; end
8'he5: begin outr <= outr^index[8:5]^4'h4; end
8'he6: begin outr <= outr^index[8:5]^4'h5; end
8'he7: begin outr <= outr^index[8:5]^4'h5; end
8'he8: begin outr <= outr^index[8:5]^4'hf; end
8'he9: begin outr <= outr^index[8:5]^4'ha; end
8'hea: begin outr <= outr^index[8:5]^4'hc; end
8'heb: begin outr <= outr^index[8:5]^4'hd; end
8'hec: begin outr <= outr^index[8:5]^4'h1; end
8'hed: begin outr <= outr^index[8:5]^4'h5; end
8'hee: begin outr <= outr^index[8:5]^4'h9; end
8'hef: begin outr <= outr^index[8:5]^4'h0; end
8'hf0: begin outr <= outr^index[8:5]^4'hd; end
8'hf1: begin outr <= outr^index[8:5]^4'hf; end
8'hf2: begin outr <= outr^index[8:5]^4'h4; end
8'hf3: begin outr <= outr^index[8:5]^4'ha; end
8'hf4: begin outr <= outr^index[8:5]^4'h8; end
8'hf5: begin outr <= outr^index[8:5]^4'he; end
8'hf6: begin outr <= outr^index[8:5]^4'he; end
8'hf7: begin outr <= outr^index[8:5]^4'h1; end
8'hf8: begin outr <= outr^index[8:5]^4'h6; end
8'hf9: begin outr <= outr^index[8:5]^4'h0; end
8'hfa: begin outr <= outr^index[8:5]^4'h5; end
8'hfb: begin outr <= outr^index[8:5]^4'h1; end
8'hfc: begin outr <= outr^index[8:5]^4'h8; end
8'hfd: begin outr <= outr^index[8:5]^4'h6; end
8'hfe: begin outr <= outr^index[8:5]^4'h1; end
default: begin outr <= outr^index[8:5]^4'h6; end
endcase
// verilog_format: on
end
endmodule

View File

@ -7,59 +7,56 @@
// verilator lint_off LATCH
module t_case_huge_sub4 (/*AUTOARG*/
// Outputs
outq,
// Inputs
index
);
// Outputs
outq,
// Inputs
index
);
input [7:0] index;
output [9:0] outq;
input [7:0] index;
output logic [9:0] outq;
// =============================
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [9:0] outq;
// End of automatics
// =============================
// =============================
always @(/*AS*/index) begin
case (index)
// default below: no change
8'h00: begin outq = 10'h001; end
8'he0: begin outq = 10'h05b; end
8'he1: begin outq = 10'h126; end
8'he2: begin outq = 10'h369; end
8'he3: begin outq = 10'h291; end
8'he4: begin outq = 10'h2ca; end
8'he5: begin outq = 10'h25b; end
8'he6: begin outq = 10'h106; end
8'he7: begin outq = 10'h172; end
8'he8: begin outq = 10'h2f7; end
8'he9: begin outq = 10'h2d3; end
8'hea: begin outq = 10'h182; end
8'heb: begin outq = 10'h327; end
8'hec: begin outq = 10'h1d0; end
8'hed: begin outq = 10'h204; end
8'hee: begin outq = 10'h11f; end
8'hef: begin outq = 10'h365; end
8'hf0: begin outq = 10'h2c2; end
8'hf1: begin outq = 10'h2b5; end
8'hf2: begin outq = 10'h1f8; end
8'hf3: begin outq = 10'h2a7; end
8'hf4: begin outq = 10'h1be; end
8'hf5: begin outq = 10'h25e; end
8'hf6: begin outq = 10'h032; end
8'hf7: begin outq = 10'h2ef; end
8'hf8: begin outq = 10'h02f; end
8'hf9: begin outq = 10'h201; end
8'hfa: begin outq = 10'h054; end
8'hfb: begin outq = 10'h013; end
8'hfc: begin outq = 10'h249; end
8'hfd: begin outq = 10'h09a; end
8'hfe: begin outq = 10'h012; end
8'hff: begin outq = 10'h114; end
default: ; // No change
endcase
end
always @* begin
// verilog_format: off
case (index)
// default below: no change
8'h00: begin outq = 10'h001; end
8'he0: begin outq = 10'h05b; end
8'he1: begin outq = 10'h126; end
8'he2: begin outq = 10'h369; end
8'he3: begin outq = 10'h291; end
8'he4: begin outq = 10'h2ca; end
8'he5: begin outq = 10'h25b; end
8'he6: begin outq = 10'h106; end
8'he7: begin outq = 10'h172; end
8'he8: begin outq = 10'h2f7; end
8'he9: begin outq = 10'h2d3; end
8'hea: begin outq = 10'h182; end
8'heb: begin outq = 10'h327; end
8'hec: begin outq = 10'h1d0; end
8'hed: begin outq = 10'h204; end
8'hee: begin outq = 10'h11f; end
8'hef: begin outq = 10'h365; end
8'hf0: begin outq = 10'h2c2; end
8'hf1: begin outq = 10'h2b5; end
8'hf2: begin outq = 10'h1f8; end
8'hf3: begin outq = 10'h2a7; end
8'hf4: begin outq = 10'h1be; end
8'hf5: begin outq = 10'h25e; end
8'hf6: begin outq = 10'h032; end
8'hf7: begin outq = 10'h2ef; end
8'hf8: begin outq = 10'h02f; end
8'hf9: begin outq = 10'h201; end
8'hfa: begin outq = 10'h054; end
8'hfb: begin outq = 10'h013; end
8'hfc: begin outq = 10'h249; end
8'hfd: begin outq = 10'h09a; end
8'hfe: begin outq = 10'h012; end
8'hff: begin outq = 10'h114; end
default: ; // No change
endcase
// verilog_format: on
end
endmodule

View File

@ -4,326 +4,326 @@
// any use, without warranty, 2024 by Varun Koyyalagunta, Tenstorrent.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
module t;
localparam W = 23;
localparam W = 23;
localparam [W-1:0] R0 = W'('h200000 + 0);
localparam [W-1:0] R1 = W'('h200000 + 1);
localparam [W-1:0] R2 = W'('h200000 + 2);
localparam [W-1:0] R3 = W'('h200000 + 3);
localparam [W-1:0] R4 = W'('h200000 + 4);
localparam [W-1:0] R5 = W'('h200000 + 5);
localparam [W-1:0] R6 = W'('h200000 + 6);
localparam [W-1:0] R7 = W'('h200000 + 7);
localparam [W-1:0] R8 = W'('h200000 + 8);
localparam [W-1:0] R9 = W'('h200000 + 9);
localparam [W-1:0] R10 = W'('h200000 + 10);
localparam [W-1:0] R11 = W'('h200000 + 11);
localparam [W-1:0] R12 = W'('h200000 + 12);
localparam [W-1:0] R13 = W'('h200000 + 13);
localparam [W-1:0] R14 = W'('h200000 + 14);
localparam [W-1:0] R15 = W'('h200000 + 15);
localparam [W-1:0] R16 = W'('h200000 + 16);
localparam [W-1:0] R17 = W'('h200000 + 17);
localparam [W-1:0] R18 = W'('h200000 + 18);
localparam [W-1:0] R19 = W'('h200000 + 19);
localparam [W-1:0] R20 = W'('h200000 + 20);
localparam [W-1:0] R21 = W'('h200000 + 21);
localparam [W-1:0] R22 = W'('h200000 + 22);
localparam [W-1:0] R23 = W'('h200000 + 23);
localparam [W-1:0] R24 = W'('h200000 + 24);
localparam [W-1:0] R25 = W'('h200000 + 25);
localparam [W-1:0] R26 = W'('h200000 + 26);
localparam [W-1:0] R27 = W'('h200000 + 27);
localparam [W-1:0] R28 = W'('h200000 + 28);
localparam [W-1:0] R29 = W'('h200000 + 29);
localparam [W-1:0] R30 = W'('h200000 + 30);
localparam [W-1:0] R31 = W'('h200000 + 31);
localparam [W-1:0] R32 = W'('h200000 + 32);
localparam [W-1:0] R33 = W'('h200000 + 33);
localparam [W-1:0] R34 = W'('h200000 + 34);
localparam [W-1:0] R35 = W'('h200000 + 35);
localparam [W-1:0] R36 = W'('h200000 + 36);
localparam [W-1:0] R37 = W'('h200000 + 37);
localparam [W-1:0] R38 = W'('h200000 + 38);
localparam [W-1:0] R39 = W'('h200000 + 39);
localparam [W-1:0] R40 = W'('h200000 + 40);
localparam [W-1:0] R41 = W'('h200000 + 41);
localparam [W-1:0] R42 = W'('h200000 + 42);
localparam [W-1:0] R43 = W'('h200000 + 43);
localparam [W-1:0] R44 = W'('h200000 + 44);
localparam [W-1:0] R45 = W'('h200000 + 45);
localparam [W-1:0] R46 = W'('h200000 + 46);
localparam [W-1:0] R47 = W'('h200000 + 47);
localparam [W-1:0] R48 = W'('h200000 + 48);
localparam [W-1:0] R49 = W'('h200000 + 49);
localparam [W-1:0] R50 = W'('h200000 + 50);
localparam [W-1:0] R51 = W'('h200000 + 51);
localparam [W-1:0] R52 = W'('h200000 + 52);
localparam [W-1:0] R53 = W'('h200000 + 53);
localparam [W-1:0] R54 = W'('h200000 + 54);
localparam [W-1:0] R55 = W'('h200000 + 55);
localparam [W-1:0] R56 = W'('h200000 + 56);
localparam [W-1:0] R57 = W'('h200000 + 57);
localparam [W-1:0] R58 = W'('h200000 + 58);
localparam [W-1:0] R59 = W'('h200000 + 59);
localparam [W-1:0] R60 = W'('h200000 + 60);
localparam [W-1:0] R61 = W'('h200000 + 61);
localparam [W-1:0] R62 = W'('h200000 + 62);
localparam [W-1:0] R63 = W'('h200000 + 63);
localparam [W-1:0] R64 = W'('h200000 + 64);
localparam [W-1:0] R65 = W'('h200000 + 65);
localparam [W-1:0] R66 = W'('h200000 + 66);
localparam [W-1:0] R67 = W'('h200000 + 67);
localparam [W-1:0] R68 = W'('h200000 + 68);
localparam [W-1:0] R69 = W'('h200000 + 69);
localparam [W-1:0] R70 = W'('h200000 + 70);
localparam [W-1:0] R71 = W'('h200000 + 71);
localparam [W-1:0] R72 = W'('h200000 + 72);
localparam [W-1:0] R73 = W'('h200000 + 73);
localparam [W-1:0] R74 = W'('h200000 + 74);
localparam [W-1:0] R75 = W'('h200000 + 75);
localparam [W-1:0] R76 = W'('h200000 + 76);
localparam [W-1:0] R77 = W'('h200000 + 77);
localparam [W-1:0] R78 = W'('h200000 + 78);
localparam [W-1:0] R79 = W'('h200000 + 79);
localparam [W-1:0] R80 = W'('h200000 + 80);
localparam [W-1:0] R81 = W'('h200000 + 81);
localparam [W-1:0] R82 = W'('h200000 + 82);
localparam [W-1:0] R83 = W'('h200000 + 83);
localparam [W-1:0] R84 = W'('h200000 + 84);
localparam [W-1:0] R85 = W'('h200000 + 85);
localparam [W-1:0] R86 = W'('h200000 + 86);
localparam [W-1:0] R87 = W'('h200000 + 87);
localparam [W-1:0] R88 = W'('h200000 + 88);
localparam [W-1:0] R89 = W'('h200000 + 89);
localparam [W-1:0] R90 = W'('h200000 + 90);
localparam [W-1:0] R91 = W'('h200000 + 91);
localparam [W-1:0] R92 = W'('h200000 + 92);
localparam [W-1:0] R93 = W'('h200000 + 93);
localparam [W-1:0] R94 = W'('h200000 + 94);
localparam [W-1:0] R95 = W'('h200000 + 95);
localparam [W-1:0] R96 = W'('h200000 + 96);
localparam [W-1:0] R97 = W'('h200000 + 97);
localparam [W-1:0] R98 = W'('h200000 + 98);
localparam [W-1:0] R99 = W'('h200000 + 99);
typedef struct packed {
logic r0;
logic r1;
logic r2;
logic r3;
logic r4;
logic r5;
logic r6;
logic r7;
logic r8;
logic r9;
logic r10;
logic r11;
logic r12;
logic r13;
logic r14;
logic r15;
logic r16;
logic r17;
logic r18;
logic r19;
logic r20;
logic r21;
logic r22;
logic r23;
logic r24;
logic r25;
logic r26;
logic r27;
logic r28;
logic r29;
logic r30;
logic r31;
logic r32;
logic r33;
logic r34;
logic r35;
logic r36;
logic r37;
logic r38;
logic r39;
logic r40;
logic r41;
logic r42;
logic r43;
logic r44;
logic r45;
logic r46;
logic r47;
logic r48;
logic r49;
logic r50;
logic r51;
logic r52;
logic r53;
logic r54;
logic r55;
logic r56;
logic r57;
logic r58;
logic r59;
logic r60;
logic r61;
logic r62;
logic r63;
logic r64;
logic r65;
logic r66;
logic r67;
logic r68;
logic r69;
logic r70;
logic r71;
logic r72;
logic r73;
logic r74;
logic r75;
logic r76;
logic r77;
logic r78;
logic r79;
logic r80;
logic r81;
logic r82;
logic r83;
logic r84;
logic r85;
logic r86;
logic r87;
logic r88;
logic r89;
logic r90;
logic r91;
logic r92;
logic r93;
logic r94;
logic r95;
logic r96;
logic r97;
logic r98;
logic r99;
} hit_t;
function automatic hit_t get_hit(input logic [22:0] a);
hit_t hit = '0;
unique case (a)
R0 : begin hit.r0 = 1'b1; end
R1 : begin hit.r1 = 1'b1; end
R2 : begin hit.r2 = 1'b1; end
R3 : begin hit.r3 = 1'b1; end
R4 : begin hit.r4 = 1'b1; end
R5 : begin hit.r5 = 1'b1; end
R6 : begin hit.r6 = 1'b1; end
R7 : begin hit.r7 = 1'b1; end
R8 : begin hit.r8 = 1'b1; end
R9 : begin hit.r9 = 1'b1; end
R10 : begin hit.r10 = 1'b1; end
R11 : begin hit.r11 = 1'b1; end
R12 : begin hit.r12 = 1'b1; end
R13 : begin hit.r13 = 1'b1; end
R14 : begin hit.r14 = 1'b1; end
R15 : begin hit.r15 = 1'b1; end
R16 : begin hit.r16 = 1'b1; end
R17 : begin hit.r17 = 1'b1; end
R18 : begin hit.r18 = 1'b1; end
R19 : begin hit.r19 = 1'b1; end
R20 : begin hit.r20 = 1'b1; end
R21 : begin hit.r21 = 1'b1; end
R22 : begin hit.r22 = 1'b1; end
R23 : begin hit.r23 = 1'b1; end
R24 : begin hit.r24 = 1'b1; end
R25 : begin hit.r25 = 1'b1; end
R26 : begin hit.r26 = 1'b1; end
R27 : begin hit.r27 = 1'b1; end
R28 : begin hit.r28 = 1'b1; end
R29 : begin hit.r29 = 1'b1; end
R30 : begin hit.r30 = 1'b1; end
R31 : begin hit.r31 = 1'b1; end
R32 : begin hit.r32 = 1'b1; end
R33 : begin hit.r33 = 1'b1; end
R34 : begin hit.r34 = 1'b1; end
R35 : begin hit.r35 = 1'b1; end
R36 : begin hit.r36 = 1'b1; end
R37 : begin hit.r37 = 1'b1; end
R38 : begin hit.r38 = 1'b1; end
R39 : begin hit.r39 = 1'b1; end
R40 : begin hit.r40 = 1'b1; end
R41 : begin hit.r41 = 1'b1; end
R42 : begin hit.r42 = 1'b1; end
R43 : begin hit.r43 = 1'b1; end
R44 : begin hit.r44 = 1'b1; end
R45 : begin hit.r45 = 1'b1; end
R46 : begin hit.r46 = 1'b1; end
R47 : begin hit.r47 = 1'b1; end
R48 : begin hit.r48 = 1'b1; end
R49 : begin hit.r49 = 1'b1; end
R50 : begin hit.r50 = 1'b1; end
R51 : begin hit.r51 = 1'b1; end
R52 : begin hit.r52 = 1'b1; end
R53 : begin hit.r53 = 1'b1; end
R54 : begin hit.r54 = 1'b1; end
R55 : begin hit.r55 = 1'b1; end
R56 : begin hit.r56 = 1'b1; end
R57 : begin hit.r57 = 1'b1; end
R58 : begin hit.r58 = 1'b1; end
R59 : begin hit.r59 = 1'b1; end
R60 : begin hit.r60 = 1'b1; end
R61 : begin hit.r61 = 1'b1; end
R62 : begin hit.r62 = 1'b1; end
R63 : begin hit.r63 = 1'b1; end
R64 : begin hit.r64 = 1'b1; end
R65 : begin hit.r65 = 1'b1; end
R66 : begin hit.r66 = 1'b1; end
R67 : begin hit.r67 = 1'b1; end
R68 : begin hit.r68 = 1'b1; end
R69 : begin hit.r69 = 1'b1; end
R70 : begin hit.r70 = 1'b1; end
R71 : begin hit.r71 = 1'b1; end
R72 : begin hit.r72 = 1'b1; end
R73 : begin hit.r73 = 1'b1; end
R74 : begin hit.r74 = 1'b1; end
R75 : begin hit.r75 = 1'b1; end
R76 : begin hit.r76 = 1'b1; end
R77 : begin hit.r77 = 1'b1; end
R78 : begin hit.r78 = 1'b1; end
R79 : begin hit.r79 = 1'b1; end
R80 : begin hit.r80 = 1'b1; end
R81 : begin hit.r81 = 1'b1; end
R82 : begin hit.r82 = 1'b1; end
R83 : begin hit.r83 = 1'b1; end
R84 : begin hit.r84 = 1'b1; end
R85 : begin hit.r85 = 1'b1; end
R86 : begin hit.r86 = 1'b1; end
R87 : begin hit.r87 = 1'b1; end
R88 : begin hit.r88 = 1'b1; end
R89 : begin hit.r89 = 1'b1; end
R90 : begin hit.r90 = 1'b1; end
R91 : begin hit.r91 = 1'b1; end
R92 : begin hit.r92 = 1'b1; end
R93 : begin hit.r93 = 1'b1; end
R94 : begin hit.r94 = 1'b1; end
R95 : begin hit.r95 = 1'b1; end
R96 : begin hit.r96 = 1'b1; end
R97 : begin hit.r97 = 1'b1; end
R98 : begin hit.r98 = 1'b1; end
R99 : begin hit.r99 = 1'b1; end
default: begin hit = '0; end
endcase
return hit;
endfunction
localparam [W-1:0] R0 = W'('h200000 + 0);
localparam [W-1:0] R1 = W'('h200000 + 1);
localparam [W-1:0] R2 = W'('h200000 + 2);
localparam [W-1:0] R3 = W'('h200000 + 3);
localparam [W-1:0] R4 = W'('h200000 + 4);
localparam [W-1:0] R5 = W'('h200000 + 5);
localparam [W-1:0] R6 = W'('h200000 + 6);
localparam [W-1:0] R7 = W'('h200000 + 7);
localparam [W-1:0] R8 = W'('h200000 + 8);
localparam [W-1:0] R9 = W'('h200000 + 9);
localparam [W-1:0] R10 = W'('h200000 + 10);
localparam [W-1:0] R11 = W'('h200000 + 11);
localparam [W-1:0] R12 = W'('h200000 + 12);
localparam [W-1:0] R13 = W'('h200000 + 13);
localparam [W-1:0] R14 = W'('h200000 + 14);
localparam [W-1:0] R15 = W'('h200000 + 15);
localparam [W-1:0] R16 = W'('h200000 + 16);
localparam [W-1:0] R17 = W'('h200000 + 17);
localparam [W-1:0] R18 = W'('h200000 + 18);
localparam [W-1:0] R19 = W'('h200000 + 19);
localparam [W-1:0] R20 = W'('h200000 + 20);
localparam [W-1:0] R21 = W'('h200000 + 21);
localparam [W-1:0] R22 = W'('h200000 + 22);
localparam [W-1:0] R23 = W'('h200000 + 23);
localparam [W-1:0] R24 = W'('h200000 + 24);
localparam [W-1:0] R25 = W'('h200000 + 25);
localparam [W-1:0] R26 = W'('h200000 + 26);
localparam [W-1:0] R27 = W'('h200000 + 27);
localparam [W-1:0] R28 = W'('h200000 + 28);
localparam [W-1:0] R29 = W'('h200000 + 29);
localparam [W-1:0] R30 = W'('h200000 + 30);
localparam [W-1:0] R31 = W'('h200000 + 31);
localparam [W-1:0] R32 = W'('h200000 + 32);
localparam [W-1:0] R33 = W'('h200000 + 33);
localparam [W-1:0] R34 = W'('h200000 + 34);
localparam [W-1:0] R35 = W'('h200000 + 35);
localparam [W-1:0] R36 = W'('h200000 + 36);
localparam [W-1:0] R37 = W'('h200000 + 37);
localparam [W-1:0] R38 = W'('h200000 + 38);
localparam [W-1:0] R39 = W'('h200000 + 39);
localparam [W-1:0] R40 = W'('h200000 + 40);
localparam [W-1:0] R41 = W'('h200000 + 41);
localparam [W-1:0] R42 = W'('h200000 + 42);
localparam [W-1:0] R43 = W'('h200000 + 43);
localparam [W-1:0] R44 = W'('h200000 + 44);
localparam [W-1:0] R45 = W'('h200000 + 45);
localparam [W-1:0] R46 = W'('h200000 + 46);
localparam [W-1:0] R47 = W'('h200000 + 47);
localparam [W-1:0] R48 = W'('h200000 + 48);
localparam [W-1:0] R49 = W'('h200000 + 49);
localparam [W-1:0] R50 = W'('h200000 + 50);
localparam [W-1:0] R51 = W'('h200000 + 51);
localparam [W-1:0] R52 = W'('h200000 + 52);
localparam [W-1:0] R53 = W'('h200000 + 53);
localparam [W-1:0] R54 = W'('h200000 + 54);
localparam [W-1:0] R55 = W'('h200000 + 55);
localparam [W-1:0] R56 = W'('h200000 + 56);
localparam [W-1:0] R57 = W'('h200000 + 57);
localparam [W-1:0] R58 = W'('h200000 + 58);
localparam [W-1:0] R59 = W'('h200000 + 59);
localparam [W-1:0] R60 = W'('h200000 + 60);
localparam [W-1:0] R61 = W'('h200000 + 61);
localparam [W-1:0] R62 = W'('h200000 + 62);
localparam [W-1:0] R63 = W'('h200000 + 63);
localparam [W-1:0] R64 = W'('h200000 + 64);
localparam [W-1:0] R65 = W'('h200000 + 65);
localparam [W-1:0] R66 = W'('h200000 + 66);
localparam [W-1:0] R67 = W'('h200000 + 67);
localparam [W-1:0] R68 = W'('h200000 + 68);
localparam [W-1:0] R69 = W'('h200000 + 69);
localparam [W-1:0] R70 = W'('h200000 + 70);
localparam [W-1:0] R71 = W'('h200000 + 71);
localparam [W-1:0] R72 = W'('h200000 + 72);
localparam [W-1:0] R73 = W'('h200000 + 73);
localparam [W-1:0] R74 = W'('h200000 + 74);
localparam [W-1:0] R75 = W'('h200000 + 75);
localparam [W-1:0] R76 = W'('h200000 + 76);
localparam [W-1:0] R77 = W'('h200000 + 77);
localparam [W-1:0] R78 = W'('h200000 + 78);
localparam [W-1:0] R79 = W'('h200000 + 79);
localparam [W-1:0] R80 = W'('h200000 + 80);
localparam [W-1:0] R81 = W'('h200000 + 81);
localparam [W-1:0] R82 = W'('h200000 + 82);
localparam [W-1:0] R83 = W'('h200000 + 83);
localparam [W-1:0] R84 = W'('h200000 + 84);
localparam [W-1:0] R85 = W'('h200000 + 85);
localparam [W-1:0] R86 = W'('h200000 + 86);
localparam [W-1:0] R87 = W'('h200000 + 87);
localparam [W-1:0] R88 = W'('h200000 + 88);
localparam [W-1:0] R89 = W'('h200000 + 89);
localparam [W-1:0] R90 = W'('h200000 + 90);
localparam [W-1:0] R91 = W'('h200000 + 91);
localparam [W-1:0] R92 = W'('h200000 + 92);
localparam [W-1:0] R93 = W'('h200000 + 93);
localparam [W-1:0] R94 = W'('h200000 + 94);
localparam [W-1:0] R95 = W'('h200000 + 95);
localparam [W-1:0] R96 = W'('h200000 + 96);
localparam [W-1:0] R97 = W'('h200000 + 97);
localparam [W-1:0] R98 = W'('h200000 + 98);
localparam [W-1:0] R99 = W'('h200000 + 99);
typedef struct packed {
logic r0;
logic r1;
logic r2;
logic r3;
logic r4;
logic r5;
logic r6;
logic r7;
logic r8;
logic r9;
logic r10;
logic r11;
logic r12;
logic r13;
logic r14;
logic r15;
logic r16;
logic r17;
logic r18;
logic r19;
logic r20;
logic r21;
logic r22;
logic r23;
logic r24;
logic r25;
logic r26;
logic r27;
logic r28;
logic r29;
logic r30;
logic r31;
logic r32;
logic r33;
logic r34;
logic r35;
logic r36;
logic r37;
logic r38;
logic r39;
logic r40;
logic r41;
logic r42;
logic r43;
logic r44;
logic r45;
logic r46;
logic r47;
logic r48;
logic r49;
logic r50;
logic r51;
logic r52;
logic r53;
logic r54;
logic r55;
logic r56;
logic r57;
logic r58;
logic r59;
logic r60;
logic r61;
logic r62;
logic r63;
logic r64;
logic r65;
logic r66;
logic r67;
logic r68;
logic r69;
logic r70;
logic r71;
logic r72;
logic r73;
logic r74;
logic r75;
logic r76;
logic r77;
logic r78;
logic r79;
logic r80;
logic r81;
logic r82;
logic r83;
logic r84;
logic r85;
logic r86;
logic r87;
logic r88;
logic r89;
logic r90;
logic r91;
logic r92;
logic r93;
logic r94;
logic r95;
logic r96;
logic r97;
logic r98;
logic r99;
} hit_t;
function automatic hit_t get_hit(input logic [22:0] a);
hit_t hit = '0;
unique case (a)
R0: hit.r0 = 1'b1;
R1: hit.r1 = 1'b1;
R2: hit.r2 = 1'b1;
R3: hit.r3 = 1'b1;
R4: hit.r4 = 1'b1;
R5: hit.r5 = 1'b1;
R6: hit.r6 = 1'b1;
R7: hit.r7 = 1'b1;
R8: hit.r8 = 1'b1;
R9: hit.r9 = 1'b1;
R10: hit.r10 = 1'b1;
R11: hit.r11 = 1'b1;
R12: hit.r12 = 1'b1;
R13: hit.r13 = 1'b1;
R14: hit.r14 = 1'b1;
R15: hit.r15 = 1'b1;
R16: hit.r16 = 1'b1;
R17: hit.r17 = 1'b1;
R18: hit.r18 = 1'b1;
R19: hit.r19 = 1'b1;
R20: hit.r20 = 1'b1;
R21: hit.r21 = 1'b1;
R22: hit.r22 = 1'b1;
R23: hit.r23 = 1'b1;
R24: hit.r24 = 1'b1;
R25: hit.r25 = 1'b1;
R26: hit.r26 = 1'b1;
R27: hit.r27 = 1'b1;
R28: hit.r28 = 1'b1;
R29: hit.r29 = 1'b1;
R30: hit.r30 = 1'b1;
R31: hit.r31 = 1'b1;
R32: hit.r32 = 1'b1;
R33: hit.r33 = 1'b1;
R34: hit.r34 = 1'b1;
R35: hit.r35 = 1'b1;
R36: hit.r36 = 1'b1;
R37: hit.r37 = 1'b1;
R38: hit.r38 = 1'b1;
R39: hit.r39 = 1'b1;
R40: hit.r40 = 1'b1;
R41: hit.r41 = 1'b1;
R42: hit.r42 = 1'b1;
R43: hit.r43 = 1'b1;
R44: hit.r44 = 1'b1;
R45: hit.r45 = 1'b1;
R46: hit.r46 = 1'b1;
R47: hit.r47 = 1'b1;
R48: hit.r48 = 1'b1;
R49: hit.r49 = 1'b1;
R50: hit.r50 = 1'b1;
R51: hit.r51 = 1'b1;
R52: hit.r52 = 1'b1;
R53: hit.r53 = 1'b1;
R54: hit.r54 = 1'b1;
R55: hit.r55 = 1'b1;
R56: hit.r56 = 1'b1;
R57: hit.r57 = 1'b1;
R58: hit.r58 = 1'b1;
R59: hit.r59 = 1'b1;
R60: hit.r60 = 1'b1;
R61: hit.r61 = 1'b1;
R62: hit.r62 = 1'b1;
R63: hit.r63 = 1'b1;
R64: hit.r64 = 1'b1;
R65: hit.r65 = 1'b1;
R66: hit.r66 = 1'b1;
R67: hit.r67 = 1'b1;
R68: hit.r68 = 1'b1;
R69: hit.r69 = 1'b1;
R70: hit.r70 = 1'b1;
R71: hit.r71 = 1'b1;
R72: hit.r72 = 1'b1;
R73: hit.r73 = 1'b1;
R74: hit.r74 = 1'b1;
R75: hit.r75 = 1'b1;
R76: hit.r76 = 1'b1;
R77: hit.r77 = 1'b1;
R78: hit.r78 = 1'b1;
R79: hit.r79 = 1'b1;
R80: hit.r80 = 1'b1;
R81: hit.r81 = 1'b1;
R82: hit.r82 = 1'b1;
R83: hit.r83 = 1'b1;
R84: hit.r84 = 1'b1;
R85: hit.r85 = 1'b1;
R86: hit.r86 = 1'b1;
R87: hit.r87 = 1'b1;
R88: hit.r88 = 1'b1;
R89: hit.r89 = 1'b1;
R90: hit.r90 = 1'b1;
R91: hit.r91 = 1'b1;
R92: hit.r92 = 1'b1;
R93: hit.r93 = 1'b1;
R94: hit.r94 = 1'b1;
R95: hit.r95 = 1'b1;
R96: hit.r96 = 1'b1;
R97: hit.r97 = 1'b1;
R98: hit.r98 = 1'b1;
R99: hit.r99 = 1'b1;
default: hit = '0;
endcase
return hit;
endfunction
initial begin
if (get_hit(R30) !== hit_t'{r30: 1'b1, default: '0}) $stop;
if (get_hit('1) !== '0) $stop;
if (get_hit('0) !== '0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
initial begin
if (get_hit(R30) !== hit_t'{r30: 1'b1, default: '0}) $stop;
if (get_hit('1) !== '0) $stop;
if (get_hit('0) !== '0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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()
test.execute()
test.passes()

View File

@ -0,0 +1,88 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Petr Nohavica
// SPDX-License-Identifier: CC0-1.0
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
interface class IBottomMid;
pure virtual function void moo(int i);
endclass
interface class IBottom;
pure virtual function bit foo();
endclass
interface class IMid extends IBottomMid;
pure virtual function string bar();
endclass
class bottom_class implements IBottom;
string name;
function new(string name);
this.name = name;
endfunction
virtual function bit foo();
$display("%s", name);
endfunction
endclass
class middle_class extends bottom_class implements IMid, IBottom;
function new(string name);
super.new($sformatf("middle %0s", name));
endfunction
virtual function bit foo();
$display("%s", name);
return 0;
endfunction
virtual function void moo(int i);
$display("moo: %d", i);
endfunction
virtual function string bar();
return name;
endfunction
endclass
class top_class extends middle_class;
int i;
function new(string name, int i);
super.new($sformatf("%0s %0d", name, i));
this.i = i;
endfunction
endclass
class sky_class extends top_class;
function new(string name);
super.new(name, 42);
endfunction
endclass
module t;
initial begin
sky_class s = new("ahoj");
bottom_class b = s;
top_class t = s;
IMid im;
`checks( b.name, "middle ahoj 42" );
`checks( s.name, "middle ahoj 42" );
`checks( t.name, "middle ahoj 42" );
`checkh( t.i, 42);
`checks(s.bar(), "middle ahoj 42");
im = s;
im.moo(42);
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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()
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1 #(type T);
static function int get_p();
return 7;
endfunction
endclass
class Class2 #(type T) extends Class1 #(T);
static function int get_p2;
return T::get_p();
endfunction
endclass
module t;
initial begin
typedef Class2#(Class1#(int)) Class;
if (Class::get_p2() != Class1#(int)::get_p()) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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()
test.passes()

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class setup_coefficients;
static function int create();
return 1;
endfunction
endclass
class biquad_vseq;
int c_setup = setup_coefficients::create();
function void setup_coefficients();
endfunction
endclass: biquad_vseq

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[15];
for (int j = 0; j < 15; j = j + 1) begin
Class1 x = new;
q[j] = x;
end
while (i < 15) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[int] = '{};
for (int j = 0; j < 15; j = j + 1) begin
Class1 x = new;
q[j] = x;
end
while (i < 15) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[] = new [15];
for (int j = 0; j < 15; j = j + 1) begin
Class1 x = new;
q[j] = x;
end
while (i < 15) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[$];
repeat(15) begin
Class1 x = new;
q = { q, x };
end
while (i < q.size()) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -10,7 +10,7 @@
clk, check_real, check_array_real, check_string
);
000019 input clk;
~000010 input clk;
input real check_real; // Check issue #2741
input real check_array_real [1:0];
input string check_string; // Check issue #2766
@ -23,9 +23,9 @@
logic b;
} str_t;
%000002 reg toggle; initial toggle='0;
%000001 reg toggle; initial toggle='0;
%000002 str_t stoggle; initial stoggle='0;
%000001 str_t stoggle; initial stoggle='0;
union {
real val1; // TODO use bit [7:0] here
@ -34,11 +34,11 @@
const reg aconst = '0;
%000002 reg [1:0][1:0] ptoggle; initial ptoggle=0;
%000001 reg [1:0][1:0] ptoggle; initial ptoggle=0;
integer cyc; initial cyc=1;
~000011 wire [7:0] cyc_copy = cyc[7:0];
%000002 wire toggle_up;
%000006 wire [7:0] cyc_copy = cyc[7:0];
%000001 wire toggle_up;
typedef struct {
int q[$];
@ -120,29 +120,40 @@
// t.a1 and t.a2 collapse to a count of 2
000038 input clk;
000020 input clk;
%000004 input toggle;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000002 input toggle;
// CHECK_COVER(-1,"top.t.a*","toggle_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_1",2)
// (t.a1 and t.a2)
~000022 input [7:0] cyc_copy;
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
~000012 input [7:0] cyc_copy;
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]_0",10)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[0]_1",12)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[1]_0",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[1]_1",6)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[2]_0",2)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[2]_1",2)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[3]_0",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[3]_1",2)
// CHECK_COVER(-9,"top.t.a*","cyc_copy[4]_0",0)
// CHECK_COVER(-10,"top.t.a*","cyc_copy[4]_1",0)
// CHECK_COVER(-11,"top.t.a*","cyc_copy[5]_0",0)
// CHECK_COVER(-12,"top.t.a*","cyc_copy[5]_1",0)
// CHECK_COVER(-13,"top.t.a*","cyc_copy[6]_0",0)
// CHECK_COVER(-14,"top.t.a*","cyc_copy[6]_1",0)
// CHECK_COVER(-15,"top.t.a*","cyc_copy[7]_0",0)
// CHECK_COVER(-16,"top.t.a*","cyc_copy[7]_1",0)
%000004 reg toggle_internal;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000002 reg toggle_internal;
// CHECK_COVER(-1,"top.t.a*","toggle_internal_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_internal_1",2)
// (t.a1 and t.a2)
%000004 output reg toggle_up;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000002 output reg toggle_up;
// CHECK_COVER(-1,"top.t.a*","toggle_up_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_up_1",2)
// (t.a1 and t.a2)
always @ (posedge clk) begin
toggle_internal <= toggle;
@ -155,10 +166,11 @@
clk, toggle_up
);
000019 input clk;
~000010 input clk;
%000002 input toggle_up;
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
%000001 input toggle_up;
// CHECK_COVER(-1,"top.t.b1","toggle_up_0",1)
// CHECK_COVER(-2,"top.t.b1","toggle_up_1",1)
/* verilator public_module */
@ -177,8 +189,9 @@
// CHECK_COVER_MISSING(-1)
// verilator coverage_on
%000002 input toggle;
// CHECK_COVER(-1,"top.t.o1","toggle",2)
%000001 input toggle;
// CHECK_COVER(-1,"top.t.o1","toggle_0",1)
// CHECK_COVER(-2,"top.t.o1","toggle_1",1)
endmodule
@ -187,18 +200,18 @@
clk, toggle
);
000019 input clk;
%000002 input toggle;
~000010 input clk;
%000001 input toggle;
%000001 logic z;
for (genvar i = 0; i < P; i++) begin
%000002 logic x;
%000001 logic x;
always @ (posedge clk) begin
x <= toggle;
end
for (genvar j = 0; j < 3; j++) begin
%000003 logic [2:0] y;
%000002 logic [2:0] y;
always @ (negedge clk) begin
y <= {toggle, ~toggle, 1'b1};
end

View File

@ -122,26 +122,37 @@ module alpha (/*AUTOARG*/
input clk;
input toggle;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
// CHECK_COVER(-1,"top.t.a*","toggle_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_1",2)
// (t.a1 and t.a2)
input [7:0] cyc_copy;
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]_0",10)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[0]_1",12)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[1]_0",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[1]_1",6)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[2]_0",2)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[2]_1",2)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[3]_0",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[3]_1",2)
// CHECK_COVER(-9,"top.t.a*","cyc_copy[4]_0",0)
// CHECK_COVER(-10,"top.t.a*","cyc_copy[4]_1",0)
// CHECK_COVER(-11,"top.t.a*","cyc_copy[5]_0",0)
// CHECK_COVER(-12,"top.t.a*","cyc_copy[5]_1",0)
// CHECK_COVER(-13,"top.t.a*","cyc_copy[6]_0",0)
// CHECK_COVER(-14,"top.t.a*","cyc_copy[6]_1",0)
// CHECK_COVER(-15,"top.t.a*","cyc_copy[7]_0",0)
// CHECK_COVER(-16,"top.t.a*","cyc_copy[7]_1",0)
reg toggle_internal;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
// CHECK_COVER(-1,"top.t.a*","toggle_internal_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_internal_1",2)
// (t.a1 and t.a2)
output reg toggle_up;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
// CHECK_COVER(-1,"top.t.a*","toggle_up_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_up_1",2)
// (t.a1 and t.a2)
always @ (posedge clk) begin
toggle_internal <= toggle;
@ -157,7 +168,8 @@ module beta (/*AUTOARG*/
input clk;
input toggle_up;
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
// CHECK_COVER(-1,"top.t.b1","toggle_up_0",1)
// CHECK_COVER(-2,"top.t.b1","toggle_up_1",1)
/* verilator public_module */
@ -177,7 +189,8 @@ module off (/*AUTOARG*/
// verilator coverage_on
input toggle;
// CHECK_COVER(-1,"top.t.o1","toggle",2)
// CHECK_COVER(-1,"top.t.o1","toggle_0",1)
// CHECK_COVER(-2,"top.t.o1","toggle_1",1)
endmodule

View File

@ -10,8 +10,9 @@
clk, check_real, check_array_real, check_string
);
000019 input clk;
+000019 point: comment=clk hier=top.t
~000010 input clk;
-000009 point: comment=clk_0 hier=top.t
+000010 point: comment=clk_1 hier=top.t
input real check_real; // Check issue #2741
input real check_array_real [1:0];
input string check_string; // Check issue #2766
@ -24,12 +25,15 @@
logic b;
} str_t;
%000002 reg toggle; initial toggle='0;
-000002 point: comment=toggle hier=top.t
%000001 reg toggle; initial toggle='0;
-000001 point: comment=toggle_0 hier=top.t
-000001 point: comment=toggle_1 hier=top.t
%000002 str_t stoggle; initial stoggle='0;
-000002 point: comment=stoggle.b hier=top.t
-000002 point: comment=stoggle.u.ua hier=top.t
%000001 str_t stoggle; initial stoggle='0;
-000001 point: comment=stoggle.b_0 hier=top.t
-000001 point: comment=stoggle.b_1 hier=top.t
-000001 point: comment=stoggle.u.ua_0 hier=top.t
-000001 point: comment=stoggle.u.ua_1 hier=top.t
union {
real val1; // TODO use bit [7:0] here
@ -38,24 +42,37 @@
const reg aconst = '0;
%000002 reg [1:0][1:0] ptoggle; initial ptoggle=0;
-000002 point: comment=ptoggle[0][0] hier=top.t
-000000 point: comment=ptoggle[0][1] hier=top.t
-000000 point: comment=ptoggle[1][0] hier=top.t
-000000 point: comment=ptoggle[1][1] hier=top.t
%000001 reg [1:0][1:0] ptoggle; initial ptoggle=0;
-000001 point: comment=ptoggle[0][0]_0 hier=top.t
-000001 point: comment=ptoggle[0][0]_1 hier=top.t
-000000 point: comment=ptoggle[0][1]_0 hier=top.t
-000000 point: comment=ptoggle[0][1]_1 hier=top.t
-000000 point: comment=ptoggle[1][0]_0 hier=top.t
-000000 point: comment=ptoggle[1][0]_1 hier=top.t
-000000 point: comment=ptoggle[1][1]_0 hier=top.t
-000000 point: comment=ptoggle[1][1]_1 hier=top.t
integer cyc; initial cyc=1;
~000011 wire [7:0] cyc_copy = cyc[7:0];
+000011 point: comment=cyc_copy[0] hier=top.t
-000005 point: comment=cyc_copy[1] hier=top.t
-000002 point: comment=cyc_copy[2] hier=top.t
-000001 point: comment=cyc_copy[3] hier=top.t
-000000 point: comment=cyc_copy[4] hier=top.t
-000000 point: comment=cyc_copy[5] hier=top.t
-000000 point: comment=cyc_copy[6] hier=top.t
-000000 point: comment=cyc_copy[7] hier=top.t
%000002 wire toggle_up;
-000002 point: comment=toggle_up hier=top.t
%000006 wire [7:0] cyc_copy = cyc[7:0];
-000005 point: comment=cyc_copy[0]_0 hier=top.t
-000006 point: comment=cyc_copy[0]_1 hier=top.t
-000002 point: comment=cyc_copy[1]_0 hier=top.t
-000003 point: comment=cyc_copy[1]_1 hier=top.t
-000001 point: comment=cyc_copy[2]_0 hier=top.t
-000001 point: comment=cyc_copy[2]_1 hier=top.t
-000000 point: comment=cyc_copy[3]_0 hier=top.t
-000001 point: comment=cyc_copy[3]_1 hier=top.t
-000000 point: comment=cyc_copy[4]_0 hier=top.t
-000000 point: comment=cyc_copy[4]_1 hier=top.t
-000000 point: comment=cyc_copy[5]_0 hier=top.t
-000000 point: comment=cyc_copy[5]_1 hier=top.t
-000000 point: comment=cyc_copy[6]_0 hier=top.t
-000000 point: comment=cyc_copy[6]_1 hier=top.t
-000000 point: comment=cyc_copy[7]_0 hier=top.t
-000000 point: comment=cyc_copy[7]_1 hier=top.t
%000001 wire toggle_up;
-000001 point: comment=toggle_up_0 hier=top.t
-000001 point: comment=toggle_up_1 hier=top.t
typedef struct {
int q[$];
@ -98,30 +115,54 @@
.toggle (toggle));
%000001 reg [1:0] memory[121:110];
-000001 point: comment=memory[110][0] hier=top.t
-000000 point: comment=memory[110][1] hier=top.t
-000000 point: comment=memory[111][0] hier=top.t
-000000 point: comment=memory[111][1] hier=top.t
-000000 point: comment=memory[112][0] hier=top.t
-000000 point: comment=memory[112][1] hier=top.t
-000000 point: comment=memory[113][0] hier=top.t
-000000 point: comment=memory[113][1] hier=top.t
-000000 point: comment=memory[114][0] hier=top.t
-000000 point: comment=memory[114][1] hier=top.t
-000000 point: comment=memory[115][0] hier=top.t
-000000 point: comment=memory[115][1] hier=top.t
-000000 point: comment=memory[116][0] hier=top.t
-000000 point: comment=memory[116][1] hier=top.t
-000000 point: comment=memory[117][0] hier=top.t
-000000 point: comment=memory[117][1] hier=top.t
-000000 point: comment=memory[118][0] hier=top.t
-000000 point: comment=memory[118][1] hier=top.t
-000000 point: comment=memory[119][0] hier=top.t
-000000 point: comment=memory[119][1] hier=top.t
-000000 point: comment=memory[120][0] hier=top.t
-000000 point: comment=memory[120][1] hier=top.t
-000000 point: comment=memory[121][0] hier=top.t
-000000 point: comment=memory[121][1] hier=top.t
-000000 point: comment=memory[110][0]_0 hier=top.t
-000001 point: comment=memory[110][0]_1 hier=top.t
-000000 point: comment=memory[110][1]_0 hier=top.t
-000000 point: comment=memory[110][1]_1 hier=top.t
-000000 point: comment=memory[111][0]_0 hier=top.t
-000000 point: comment=memory[111][0]_1 hier=top.t
-000000 point: comment=memory[111][1]_0 hier=top.t
-000000 point: comment=memory[111][1]_1 hier=top.t
-000000 point: comment=memory[112][0]_0 hier=top.t
-000000 point: comment=memory[112][0]_1 hier=top.t
-000000 point: comment=memory[112][1]_0 hier=top.t
-000000 point: comment=memory[112][1]_1 hier=top.t
-000000 point: comment=memory[113][0]_0 hier=top.t
-000000 point: comment=memory[113][0]_1 hier=top.t
-000000 point: comment=memory[113][1]_0 hier=top.t
-000000 point: comment=memory[113][1]_1 hier=top.t
-000000 point: comment=memory[114][0]_0 hier=top.t
-000000 point: comment=memory[114][0]_1 hier=top.t
-000000 point: comment=memory[114][1]_0 hier=top.t
-000000 point: comment=memory[114][1]_1 hier=top.t
-000000 point: comment=memory[115][0]_0 hier=top.t
-000000 point: comment=memory[115][0]_1 hier=top.t
-000000 point: comment=memory[115][1]_0 hier=top.t
-000000 point: comment=memory[115][1]_1 hier=top.t
-000000 point: comment=memory[116][0]_0 hier=top.t
-000000 point: comment=memory[116][0]_1 hier=top.t
-000000 point: comment=memory[116][1]_0 hier=top.t
-000000 point: comment=memory[116][1]_1 hier=top.t
-000000 point: comment=memory[117][0]_0 hier=top.t
-000000 point: comment=memory[117][0]_1 hier=top.t
-000000 point: comment=memory[117][1]_0 hier=top.t
-000000 point: comment=memory[117][1]_1 hier=top.t
-000000 point: comment=memory[118][0]_0 hier=top.t
-000000 point: comment=memory[118][0]_1 hier=top.t
-000000 point: comment=memory[118][1]_0 hier=top.t
-000000 point: comment=memory[118][1]_1 hier=top.t
-000000 point: comment=memory[119][0]_0 hier=top.t
-000000 point: comment=memory[119][0]_1 hier=top.t
-000000 point: comment=memory[119][1]_0 hier=top.t
-000000 point: comment=memory[119][1]_1 hier=top.t
-000000 point: comment=memory[120][0]_0 hier=top.t
-000000 point: comment=memory[120][0]_1 hier=top.t
-000000 point: comment=memory[120][1]_0 hier=top.t
-000000 point: comment=memory[120][1]_1 hier=top.t
-000000 point: comment=memory[121][0]_0 hier=top.t
-000000 point: comment=memory[121][0]_1 hier=top.t
-000000 point: comment=memory[121][1]_0 hier=top.t
-000000 point: comment=memory[121][1]_1 hier=top.t
wire [1023:0] largeish = {992'h0, cyc};
// CHECK_COVER_MISSING(-1)
@ -161,41 +202,64 @@
// t.a1 and t.a2 collapse to a count of 2
000038 input clk;
+000038 point: comment=clk hier=top.t.a*
000020 input clk;
+000018 point: comment=clk_0 hier=top.t.a*
+000020 point: comment=clk_1 hier=top.t.a*
%000004 input toggle;
-000004 point: comment=toggle hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000002 input toggle;
-000002 point: comment=toggle_0 hier=top.t.a*
-000002 point: comment=toggle_1 hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*","toggle_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_1",2)
// (t.a1 and t.a2)
~000022 input [7:0] cyc_copy;
+000022 point: comment=cyc_copy[0] hier=top.t.a*
+000010 point: comment=cyc_copy[1] hier=top.t.a*
-000004 point: comment=cyc_copy[2] hier=top.t.a*
-000002 point: comment=cyc_copy[3] hier=top.t.a*
-000000 point: comment=cyc_copy[4] hier=top.t.a*
-000000 point: comment=cyc_copy[5] hier=top.t.a*
-000000 point: comment=cyc_copy[6] hier=top.t.a*
-000000 point: comment=cyc_copy[7] hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
~000012 input [7:0] cyc_copy;
+000010 point: comment=cyc_copy[0]_0 hier=top.t.a*
+000012 point: comment=cyc_copy[0]_1 hier=top.t.a*
-000004 point: comment=cyc_copy[1]_0 hier=top.t.a*
-000006 point: comment=cyc_copy[1]_1 hier=top.t.a*
-000002 point: comment=cyc_copy[2]_0 hier=top.t.a*
-000002 point: comment=cyc_copy[2]_1 hier=top.t.a*
-000000 point: comment=cyc_copy[3]_0 hier=top.t.a*
-000002 point: comment=cyc_copy[3]_1 hier=top.t.a*
-000000 point: comment=cyc_copy[4]_0 hier=top.t.a*
-000000 point: comment=cyc_copy[4]_1 hier=top.t.a*
-000000 point: comment=cyc_copy[5]_0 hier=top.t.a*
-000000 point: comment=cyc_copy[5]_1 hier=top.t.a*
-000000 point: comment=cyc_copy[6]_0 hier=top.t.a*
-000000 point: comment=cyc_copy[6]_1 hier=top.t.a*
-000000 point: comment=cyc_copy[7]_0 hier=top.t.a*
-000000 point: comment=cyc_copy[7]_1 hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]_0",10)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[0]_1",12)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[1]_0",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[1]_1",6)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[2]_0",2)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[2]_1",2)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[3]_0",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[3]_1",2)
// CHECK_COVER(-9,"top.t.a*","cyc_copy[4]_0",0)
// CHECK_COVER(-10,"top.t.a*","cyc_copy[4]_1",0)
// CHECK_COVER(-11,"top.t.a*","cyc_copy[5]_0",0)
// CHECK_COVER(-12,"top.t.a*","cyc_copy[5]_1",0)
// CHECK_COVER(-13,"top.t.a*","cyc_copy[6]_0",0)
// CHECK_COVER(-14,"top.t.a*","cyc_copy[6]_1",0)
// CHECK_COVER(-15,"top.t.a*","cyc_copy[7]_0",0)
// CHECK_COVER(-16,"top.t.a*","cyc_copy[7]_1",0)
%000004 reg toggle_internal;
-000004 point: comment=toggle_internal hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000002 reg toggle_internal;
-000002 point: comment=toggle_internal_0 hier=top.t.a*
-000002 point: comment=toggle_internal_1 hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*","toggle_internal_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_internal_1",2)
// (t.a1 and t.a2)
%000004 output reg toggle_up;
-000004 point: comment=toggle_up hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000002 output reg toggle_up;
-000002 point: comment=toggle_up_0 hier=top.t.a*
-000002 point: comment=toggle_up_1 hier=top.t.a*
// CHECK_COVER(-1,"top.t.a*","toggle_up_0",2)
// CHECK_COVER(-2,"top.t.a*","toggle_up_1",2)
// (t.a1 and t.a2)
always @ (posedge clk) begin
toggle_internal <= toggle;
@ -208,12 +272,15 @@
clk, toggle_up
);
000019 input clk;
+000019 point: comment=clk hier=top.t.b1
~000010 input clk;
-000009 point: comment=clk_0 hier=top.t.b1
+000010 point: comment=clk_1 hier=top.t.b1
%000002 input toggle_up;
-000002 point: comment=toggle_up hier=top.t.b1
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
%000001 input toggle_up;
-000001 point: comment=toggle_up_0 hier=top.t.b1
-000001 point: comment=toggle_up_1 hier=top.t.b1
// CHECK_COVER(-1,"top.t.b1","toggle_up_0",1)
// CHECK_COVER(-2,"top.t.b1","toggle_up_1",1)
/* verilator public_module */
@ -232,9 +299,11 @@
// CHECK_COVER_MISSING(-1)
// verilator coverage_on
%000002 input toggle;
-000002 point: comment=toggle hier=top.t.o1
// CHECK_COVER(-1,"top.t.o1","toggle",2)
%000001 input toggle;
-000001 point: comment=toggle_0 hier=top.t.o1
-000001 point: comment=toggle_1 hier=top.t.o1
// CHECK_COVER(-1,"top.t.o1","toggle_0",1)
// CHECK_COVER(-2,"top.t.o1","toggle_1",1)
endmodule
@ -243,54 +312,90 @@
clk, toggle
);
000019 input clk;
+000019 point: comment=clk hier=top.t.p2
+000019 point: comment=clk hier=top.t.p1
%000002 input toggle;
-000002 point: comment=toggle hier=top.t.p2
-000002 point: comment=toggle hier=top.t.p1
~000010 input clk;
-000009 point: comment=clk_0 hier=top.t.p2
+000010 point: comment=clk_1 hier=top.t.p2
-000009 point: comment=clk_0 hier=top.t.p1
+000010 point: comment=clk_1 hier=top.t.p1
%000001 input toggle;
-000001 point: comment=toggle_0 hier=top.t.p2
-000001 point: comment=toggle_1 hier=top.t.p2
-000001 point: comment=toggle_0 hier=top.t.p1
-000001 point: comment=toggle_1 hier=top.t.p1
%000001 logic z;
-000001 point: comment=z hier=top.t.p2
-000000 point: comment=z hier=top.t.p1
-000000 point: comment=z_0 hier=top.t.p2
-000001 point: comment=z_1 hier=top.t.p2
-000000 point: comment=z_0 hier=top.t.p1
-000000 point: comment=z_1 hier=top.t.p1
for (genvar i = 0; i < P; i++) begin
%000002 logic x;
-000002 point: comment=genblk1[0].x hier=top.t.p2
-000002 point: comment=genblk1[1].x hier=top.t.p2
-000002 point: comment=genblk1[0].x hier=top.t.p1
%000001 logic x;
-000001 point: comment=genblk1[0].x_0 hier=top.t.p2
-000001 point: comment=genblk1[0].x_1 hier=top.t.p2
-000001 point: comment=genblk1[1].x_0 hier=top.t.p2
-000001 point: comment=genblk1[1].x_1 hier=top.t.p2
-000001 point: comment=genblk1[0].x_0 hier=top.t.p1
-000001 point: comment=genblk1[0].x_1 hier=top.t.p1
always @ (posedge clk) begin
x <= toggle;
end
for (genvar j = 0; j < 3; j++) begin
%000003 logic [2:0] y;
-000001 point: comment=genblk1[0].genblk1[0].y[0] hier=top.t.p2
-000003 point: comment=genblk1[0].genblk1[0].y[1] hier=top.t.p2
-000002 point: comment=genblk1[0].genblk1[0].y[2] hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[1].y[0] hier=top.t.p2
-000003 point: comment=genblk1[0].genblk1[1].y[1] hier=top.t.p2
-000002 point: comment=genblk1[0].genblk1[1].y[2] hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[2].y[0] hier=top.t.p2
-000003 point: comment=genblk1[0].genblk1[2].y[1] hier=top.t.p2
-000002 point: comment=genblk1[0].genblk1[2].y[2] hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[0].y[0] hier=top.t.p2
-000003 point: comment=genblk1[1].genblk1[0].y[1] hier=top.t.p2
-000002 point: comment=genblk1[1].genblk1[0].y[2] hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[1].y[0] hier=top.t.p2
-000003 point: comment=genblk1[1].genblk1[1].y[1] hier=top.t.p2
-000002 point: comment=genblk1[1].genblk1[1].y[2] hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[2].y[0] hier=top.t.p2
-000003 point: comment=genblk1[1].genblk1[2].y[1] hier=top.t.p2
-000002 point: comment=genblk1[1].genblk1[2].y[2] hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[0].y[0] hier=top.t.p1
-000003 point: comment=genblk1[0].genblk1[0].y[1] hier=top.t.p1
-000002 point: comment=genblk1[0].genblk1[0].y[2] hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[1].y[0] hier=top.t.p1
-000003 point: comment=genblk1[0].genblk1[1].y[1] hier=top.t.p1
-000002 point: comment=genblk1[0].genblk1[1].y[2] hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[2].y[0] hier=top.t.p1
-000003 point: comment=genblk1[0].genblk1[2].y[1] hier=top.t.p1
-000002 point: comment=genblk1[0].genblk1[2].y[2] hier=top.t.p1
%000002 logic [2:0] y;
-000000 point: comment=genblk1[0].genblk1[0].y[0]_0 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[0].y[0]_1 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[0].y[1]_0 hier=top.t.p2
-000002 point: comment=genblk1[0].genblk1[0].y[1]_1 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[0].y[2]_0 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[0].y[2]_1 hier=top.t.p2
-000000 point: comment=genblk1[0].genblk1[1].y[0]_0 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[1].y[0]_1 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[1].y[1]_0 hier=top.t.p2
-000002 point: comment=genblk1[0].genblk1[1].y[1]_1 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[1].y[2]_0 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[1].y[2]_1 hier=top.t.p2
-000000 point: comment=genblk1[0].genblk1[2].y[0]_0 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[2].y[0]_1 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[2].y[1]_0 hier=top.t.p2
-000002 point: comment=genblk1[0].genblk1[2].y[1]_1 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[2].y[2]_0 hier=top.t.p2
-000001 point: comment=genblk1[0].genblk1[2].y[2]_1 hier=top.t.p2
-000000 point: comment=genblk1[1].genblk1[0].y[0]_0 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[0].y[0]_1 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[0].y[1]_0 hier=top.t.p2
-000002 point: comment=genblk1[1].genblk1[0].y[1]_1 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[0].y[2]_0 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[0].y[2]_1 hier=top.t.p2
-000000 point: comment=genblk1[1].genblk1[1].y[0]_0 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[1].y[0]_1 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[1].y[1]_0 hier=top.t.p2
-000002 point: comment=genblk1[1].genblk1[1].y[1]_1 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[1].y[2]_0 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[1].y[2]_1 hier=top.t.p2
-000000 point: comment=genblk1[1].genblk1[2].y[0]_0 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[2].y[0]_1 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[2].y[1]_0 hier=top.t.p2
-000002 point: comment=genblk1[1].genblk1[2].y[1]_1 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[2].y[2]_0 hier=top.t.p2
-000001 point: comment=genblk1[1].genblk1[2].y[2]_1 hier=top.t.p2
-000000 point: comment=genblk1[0].genblk1[0].y[0]_0 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[0].y[0]_1 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[0].y[1]_0 hier=top.t.p1
-000002 point: comment=genblk1[0].genblk1[0].y[1]_1 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[0].y[2]_0 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[0].y[2]_1 hier=top.t.p1
-000000 point: comment=genblk1[0].genblk1[1].y[0]_0 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[1].y[0]_1 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[1].y[1]_0 hier=top.t.p1
-000002 point: comment=genblk1[0].genblk1[1].y[1]_1 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[1].y[2]_0 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[1].y[2]_1 hier=top.t.p1
-000000 point: comment=genblk1[0].genblk1[2].y[0]_0 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[2].y[0]_1 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[2].y[1]_0 hier=top.t.p1
-000002 point: comment=genblk1[0].genblk1[2].y[1]_1 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[2].y[2]_0 hier=top.t.p1
-000001 point: comment=genblk1[0].genblk1[2].y[2]_1 hier=top.t.p1
always @ (negedge clk) begin
y <= {toggle, ~toggle, 1'b1};
end

View File

@ -1,14 +1,20 @@
TN:verilator_coverage
SF:t/t_cover_toggle_min.v
DA:10,1
BRDA:10,0,0,1
BRDA:10,0,1,0
BRDA:10,0,0,0
BRDA:10,0,1,1
BRDA:10,0,2,0
BRDA:10,0,3,0
DA:11,1
BRDA:11,0,0,0
BRDA:11,0,1,1
DA:12,2
BRDA:12,0,0,2
BRDA:11,0,1,0
BRDA:11,0,2,0
BRDA:11,0,3,1
DA:12,1
BRDA:12,0,0,1
BRDA:12,0,1,1
BRF:6
BRDA:12,0,2,0
BRDA:12,0,3,1
BRF:12
BRH:0
end_of_record

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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('vlt')
test.compile()
test.passes()

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
module t;
covergroup cgArgs(int var1, int var2=42);
endgroup
cgArgs cov1 = new(69, 77);
cgArgs cov2 = new(69);
function x();
cov1.sample();
cov2.get_coverage();
endfunction;
endmodule

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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('vlt')
test.compile()
test.passes()

View File

@ -0,0 +1,39 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
module t;
class base;
enum {red, green, blue} color;
covergroup g1 (bit [3:0] a) with function sample(bit b);
option.weight = 10;
option.per_instance = 1;
coverpoint a;
coverpoint b;
c: coverpoint color;
endgroup
function new();
g1 = new(0);
endfunction
endclass
class derived extends base;
bit d;
covergroup extends g1;
option.weight = 1; // overrides the weight from base g1
// uses per_instance = 1 from base g1
c: coverpoint color // overrides the c coverpoint in base g1
{
ignore_bins ignore = {blue};
}
coverpoint d; // adds new coverpoint
cross a, d; // crosses new coverpoint with inherited one
endgroup :g1
function new();
super.new();
endfunction
endclass
endmodule

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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('vlt')
test.compile()
test.passes()

View File

@ -0,0 +1,39 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
module t;
class base;
function new();
g1 = new(0);
endfunction
enum {red, green, blue} color;
covergroup g1 (bit [3:0] a) with function sample(bit b);
option.weight = 10;
option.per_instance = 1;
coverpoint a;
coverpoint b;
c: coverpoint color;
endgroup
endclass
class derived extends base;
bit d;
function new();
super.new();
endfunction
covergroup extends g1;
option.weight = 1; // overrides the weight from base g1
// uses per_instance = 1 from base g1
c: coverpoint color // overrides the c coverpoint in base g1
{
ignore_bins ignore = {blue};
}
coverpoint d; // adds new coverpoint
cross a, d; // crosses new coverpoint with inherited one
endgroup :g1
endclass
endmodule

View File

@ -0,0 +1,5 @@
%Error: t/t_covergroup_func_override_bad.v:10:5: syntax error, unexpected function
10 | function sample();
| ^~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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')
if test.vlt_all:
test.lint(fails=True, expect_filename=test.golden_filename)
else:
test.compile(nc_flags2=["-coverage", "functional"])
test.execute()
test.passes()

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
module t();
covergroup cg;
function sample();
endfunction
function get_coverage();
endfunction
endgroup
endmodule

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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('vlt')
test.compile()
test.passes()

View File

@ -0,0 +1,18 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
class myClass;
covergroup embeddedCg;
endgroup
function new();
embeddedCg = new();
embeddedCg.sample();
embeddedCg.get_coverage();
endfunction
endclass

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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('vlt')
test.compile()
test.passes()

View File

@ -0,0 +1,30 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
class myClass;
covergroup embeddedCg;
endgroup
function new();
embeddedCg = new();
embeddedCg.sample();
embeddedCg.get_coverage();
endfunction
endclass
class secondClass;
covergroup embeddedCg;
endgroup
function new();
embeddedCg = new();
embeddedCg.sample();
embeddedCg.get_coverage();
endfunction
endclass

Some files were not shown because too many files have changed in this diff Show More