Compare commits
75 Commits
04cb67ba17
...
f971bca8a1
Author | SHA1 | Date |
---|---|---|
![]() |
f971bca8a1 | |
![]() |
9f04ee68c8 | |
![]() |
b5126a6abe | |
![]() |
74d4b0c0ea | |
![]() |
7401a8a43a | |
![]() |
7646e7d89c | |
![]() |
a8dca71ed0 | |
![]() |
98b8d43a4a | |
![]() |
d419c49921 | |
![]() |
a50ea2a1a6 | |
![]() |
078bb21a89 | |
![]() |
b8b9478938 | |
![]() |
f535a73ea7 | |
![]() |
641e0e5672 | |
![]() |
9d146eae16 | |
![]() |
7d43a935bd | |
![]() |
9b99d9697f | |
![]() |
a21ecb2ab9 | |
![]() |
28808f38bb | |
![]() |
7a6775ca84 | |
![]() |
e527ff49a3 | |
![]() |
c1506deef9 | |
![]() |
87050670b4 | |
![]() |
fb1373b854 | |
![]() |
7f1011e5f7 | |
![]() |
7a32771c7e | |
![]() |
94b043d6c9 | |
![]() |
8c5ba3a0d7 | |
![]() |
826e5b0826 | |
![]() |
abd509ce53 | |
![]() |
1bf24c7eb4 | |
![]() |
1f0357ba93 | |
![]() |
db6b17fdb4 | |
![]() |
f3e109d8c5 | |
![]() |
371ac07c6f | |
![]() |
caf3522364 | |
![]() |
03e0d49d99 | |
![]() |
e2e5d9eaf1 | |
![]() |
2f199f20cf | |
![]() |
cefe1845df | |
![]() |
1044398f95 | |
![]() |
77180c4020 | |
![]() |
2fc12d951e | |
![]() |
0982260d3b | |
![]() |
58b867c39c | |
![]() |
4e8a8a0398 | |
![]() |
4dc6a31276 | |
![]() |
ce77bac99a | |
![]() |
31c279a7b3 | |
![]() |
9ad0de1efd | |
![]() |
d89df33fcd | |
![]() |
d1462f3120 | |
![]() |
9fc7143fce | |
![]() |
597b973f7b | |
![]() |
a84c5d2010 | |
![]() |
dbfbc657e1 | |
![]() |
8b3a6ba542 | |
![]() |
8ba7cec15b | |
![]() |
f037ac50b4 | |
![]() |
1f0e767b61 | |
![]() |
5777ab75c7 | |
![]() |
e494cf22a4 | |
![]() |
ea62a51589 | |
![]() |
fe02d95d45 | |
![]() |
30eb11ff5c | |
![]() |
be7361b2ad | |
![]() |
686991ef4c | |
![]() |
363d83a770 | |
![]() |
6b908a2edb | |
![]() |
65b7b3489a | |
![]() |
f33d2a9ec4 | |
![]() |
73d2fda3b7 | |
![]() |
2669553147 | |
![]() |
95f89e16fb | |
![]() |
1e1276c4e8 |
|
@ -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
|
||||
)
|
||||
|
|
35
Changes
35
Changes
|
@ -8,7 +8,38 @@ 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 data type, and wire data 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) (#6195). [Igor Zaworski, Ryszard Rozak, 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 virtual interface member propagation (#6175) (#6184). [Yilou Wang]
|
||||
* Fix `--coverage-expr` null pointer dereference (#6181). [Igor Zaworski, Antmicro Ltd.]
|
||||
* Fix conflicting function/class name linking error (#6182). [Igor Zaworski, Antmicro Ltd.]
|
||||
* Fix VPI signal range order (#6189) (#6200). [Ibrahim Burak Yorulmaz]
|
||||
* Fix structure select causing 'Wide Op' error (#6191). [Danny Oler]
|
||||
|
||||
|
||||
Verilator 5.038 2025-07-08
|
||||
==========================
|
||||
|
||||
**Important:**
|
||||
|
@ -47,6 +78,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 +127,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ Anthony Donlon
|
|||
Anthony Moore
|
||||
Arkadiusz Kozdra
|
||||
Arthur Rosa
|
||||
Artur Bieniek
|
||||
Aylon Chaim Porat
|
||||
Bartłomiej Chmiel
|
||||
Brian Li
|
||||
|
@ -36,6 +37,7 @@ Chuxuan Wang
|
|||
Chykon
|
||||
Conor McCullough
|
||||
Dan Petrisko
|
||||
Danny Oler
|
||||
Daniel Bates
|
||||
Dave Sargeant
|
||||
David Horton
|
||||
|
@ -83,6 +85,8 @@ Huang Rui
|
|||
Huanghuang Zhou
|
||||
HungMingWu
|
||||
HyungKi Jeong
|
||||
Ibrahim Burak Yorulmaz
|
||||
Igor Zaworski
|
||||
Ilya Barkov
|
||||
Iru Cai
|
||||
Ivan Vnučec
|
||||
|
@ -155,6 +159,7 @@ Martin Schmidt
|
|||
Martin Stadler
|
||||
Mateusz Gancarz
|
||||
Matthew Ballance
|
||||
Max Wipfli
|
||||
Michael Bikovitsky
|
||||
Michael Killough
|
||||
Michal Czyz
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
:linenos:
|
||||
:emphasize-lines: 3
|
||||
|
||||
int array[5];
|
||||
bit [1:0] rd_addr;
|
||||
wire int rd_value = array[rd_addr]; //<--- Warning
|
||||
logic [31:0] array[5];
|
||||
bit [1:0] rd_addr;
|
||||
wire [31:0] rd_value = array[rd_addr]; //<--- Warning
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
.. code-block:: sv
|
||||
:emphasize-lines: 1
|
||||
|
||||
wire int rd_value = array[{1'b0, rd_addr}]; //<--- Fixed
|
||||
wire [31:0] rd_value = array[{1'b0, rd_addr}]; //<--- Fixed
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. comment: generated by t_lint_widthexpand_docs_bad
|
||||
.. code-block::
|
||||
|
||||
%Warning-WIDTHEXPAND: example.v:3:29 Bit extraction of array[4:0] requires 3 bit index, not 2 bits.
|
||||
%Warning-WIDTHEXPAND: example.v:3:31 Bit extraction of array[4:0] requires 3 bit index, not 2 bits.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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*/`
|
||||
|
|
|
@ -247,6 +247,7 @@ Lesik
|
|||
Libenzi
|
||||
Licker
|
||||
Liland
|
||||
LinkDot
|
||||
Liu
|
||||
Liwei
|
||||
Lockhart
|
||||
|
@ -313,6 +314,7 @@ Noack
|
|||
Nodine
|
||||
Ober
|
||||
Oleg
|
||||
Oler
|
||||
Olof
|
||||
Olofsson
|
||||
Oron
|
||||
|
@ -480,6 +482,7 @@ Wfuture
|
|||
Whatson
|
||||
Wildman
|
||||
Wim
|
||||
Wipfli
|
||||
Wmisleading
|
||||
Wno
|
||||
Wojciech
|
||||
|
@ -599,6 +602,7 @@ coroutines
|
|||
countbits
|
||||
countones
|
||||
cout
|
||||
covergroup
|
||||
cpp
|
||||
cppstyle
|
||||
cpu
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -227,6 +227,7 @@ set(COMMON_SOURCES
|
|||
V3Descope.cpp
|
||||
V3Dfg.cpp
|
||||
V3DfgAstToDfg.cpp
|
||||
V3DfgBreakCycles.cpp
|
||||
V3DfgCache.cpp
|
||||
V3DfgDecomposition.cpp
|
||||
V3DfgDfgToAst.cpp
|
||||
|
|
|
@ -240,6 +240,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3Descope.o \
|
||||
V3Dfg.o \
|
||||
V3DfgAstToDfg.o \
|
||||
V3DfgBreakCycles.o \
|
||||
V3DfgCache.o \
|
||||
V3DfgDecomposition.o \
|
||||
V3DfgDfgToAst.o \
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
@ -3096,14 +3097,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
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1267,8 +1267,12 @@ class ConstVisitor final : public VNVisitor {
|
|||
&& nodep->lhsp()->isPure());
|
||||
}
|
||||
bool operandIsTwo(const AstNode* nodep) {
|
||||
return (VN_IS(nodep, Const) && !VN_AS(nodep, Const)->num().isFourState()
|
||||
&& nodep->width() <= VL_QUADSIZE && VN_AS(nodep, Const)->toUQuad() == 2);
|
||||
const AstConst* const constp = VN_CAST(nodep, Const);
|
||||
if (!constp) return false; // not constant
|
||||
if (constp->num().isFourState()) return false; // four-state
|
||||
if (nodep->width() > VL_QUADSIZE) return false; // too wide
|
||||
if (nodep->isSigned() && constp->num().isNegative()) return false; // signed and negative
|
||||
return constp->toUQuad() == 2;
|
||||
}
|
||||
bool operandIsTwostate(const AstNode* nodep) {
|
||||
return (VN_IS(nodep, Const) && !VN_AS(nodep, Const)->num().isFourState());
|
||||
|
@ -3550,6 +3554,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
|
||||
TREEOP ("AstModDiv{$lhsp, operandIsPowTwo($rhsp)}", "replaceModAnd(nodep)"); // a % 2^n -> a&(2^n-1)
|
||||
TREEOP ("AstPow {operandIsTwo($lhsp), !$rhsp.isZero}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstPowSU {operandIsTwo($lhsp), !$rhsp.isZero}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstSub {$lhsp.castAdd, operandSubAdd(nodep)}", "AstAdd{AstSub{$lhsp->castAdd()->lhsp(),$rhsp}, $lhsp->castAdd()->rhsp()}"); // ((a+x)-y) -> (a+(x-y))
|
||||
TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b)
|
||||
// Trinary ops
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,7 +869,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));
|
||||
|
|
259
src/V3Dfg.cpp
259
src/V3Dfg.cpp
|
@ -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;
|
||||
|
@ -105,8 +246,9 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
|||
AstNode* const nodep = varVtxp->nodep();
|
||||
AstVar* const varp = varVtxp->varp();
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << nodep->name() << "\nW" << varVtxp->width() << " / F"
|
||||
<< varVtxp->fanout() << '"';
|
||||
os << " [label=\"" << nodep->name() << "\n";
|
||||
varVtxp->dtypep()->dumpSmall(os);
|
||||
os << " / F" << varVtxp->fanout() << '"';
|
||||
|
||||
if (varp->direction() == VDirection::INPUT) {
|
||||
os << ", shape=box, style=filled, fillcolor=chartreuse2"; // Green
|
||||
|
@ -132,9 +274,10 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
|||
if (const DfgVarArray* const arrVtxp = vtx.cast<DfgVarArray>()) {
|
||||
AstNode* const nodep = arrVtxp->nodep();
|
||||
AstVar* const varp = arrVtxp->varp();
|
||||
const int elements = VN_AS(arrVtxp->dtypep(), UnpackArrayDType)->elementsConst();
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << nodep->name() << "[" << elements << "]\"";
|
||||
os << " [label=\"" << nodep->name() << "\n";
|
||||
arrVtxp->dtypep()->dumpSmall(os);
|
||||
os << " / F" << arrVtxp->fanout() << '"';
|
||||
if (varp->direction() == VDirection::INPUT) {
|
||||
os << ", shape=box3d, style=filled, fillcolor=chartreuse2"; // Green
|
||||
} else if (varp->direction() == VDirection::OUTPUT) {
|
||||
|
@ -177,8 +320,9 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
|||
const uint32_t lsb = selVtxp->lsb();
|
||||
const uint32_t msb = lsb + selVtxp->width() - 1;
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"SEL\n_[" << msb << ":" << lsb << "]\nW" << vtx.width() << " / F"
|
||||
<< vtx.fanout() << '"';
|
||||
os << " [label=\"SEL\n_[" << msb << ":" << lsb << "]\n";
|
||||
vtx.dtypep()->dumpSmall(os);
|
||||
os << " / F" << vtx.fanout() << '"';
|
||||
if (vtx.hasMultipleSinks()) {
|
||||
os << ", shape=doublecircle";
|
||||
} else {
|
||||
|
@ -188,8 +332,24 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (vtx.is<DfgVertexSplice>()) {
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << vtx.typeName() << "\n";
|
||||
vtx.dtypep()->dumpSmall(os);
|
||||
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() << '"';
|
||||
os << " [label=\"" << vtx.typeName() << "\n";
|
||||
vtx.dtypep()->dumpSmall(os);
|
||||
os << " / F" << vtx.fanout() << '"';
|
||||
if (vtx.hasMultipleSinks()) {
|
||||
os << ", shape=doublecircle";
|
||||
} else {
|
||||
|
@ -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,22 +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;
|
||||
// First variable found
|
||||
if (!resp) {
|
||||
resp = varp;
|
||||
|
@ -569,6 +738,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 {
|
||||
|
|
33
src/V3Dfg.h
33
src/V3Dfg.h
|
@ -230,7 +230,13 @@ public:
|
|||
|
||||
// Retrieve user data, must be current.
|
||||
template <typename T>
|
||||
inline T& getUser();
|
||||
inline const T& getUser() const;
|
||||
|
||||
// Retrieve user data, must be current.
|
||||
template <typename T>
|
||||
T& getUser() {
|
||||
return const_cast<T&>(const_cast<const DfgVertex*>(this)->getUser<T>());
|
||||
}
|
||||
|
||||
// Set user data, becomes current.
|
||||
template <typename T>
|
||||
|
@ -238,8 +244,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 +288,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 +577,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 +711,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;
|
||||
|
||||
|
@ -781,12 +789,12 @@ T& DfgVertex::user() {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
T& DfgVertex::getUser() {
|
||||
const T& DfgVertex::getUser() const {
|
||||
static_assert(sizeof(T) <= sizeof(UserDataStorage),
|
||||
"Size of user data type 'T' is too large for allocated storage");
|
||||
static_assert(alignof(T) <= alignof(UserDataStorage),
|
||||
"Alignment of user data type 'T' is larger than allocated storage");
|
||||
T* const storagep = reinterpret_cast<T*>(&m_userDataStorage);
|
||||
const T* const storagep = reinterpret_cast<const T*>(&m_userDataStorage);
|
||||
#if VL_DEBUG
|
||||
const uint32_t userCurrent = m_graphp->m_userCurrent;
|
||||
UASSERT_OBJ(userCurrent, this, "DfgVertex user data used without reserving");
|
||||
|
@ -911,18 +919,19 @@ 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");
|
||||
UASSERT_OBJ(!m_varp->isSc(), varp, "SystemC variable is not representable by DfgVertexVar");
|
||||
}
|
||||
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");
|
||||
UASSERT_OBJ(!m_varp->isSc(), vscp, "SystemC variable is not representable by DfgVertexVar");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
@ -28,9 +28,12 @@
|
|||
|
||||
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
||||
|
||||
#include "V3Const.h"
|
||||
#include "V3Dfg.h"
|
||||
#include "V3DfgPasses.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
namespace {
|
||||
|
@ -42,6 +45,17 @@ T_Vertex* makeVertex(const T_Node* nodep, DfgGraph& dfg) {
|
|||
return new T_Vertex{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)};
|
||||
}
|
||||
|
||||
template <>
|
||||
DfgArraySel* makeVertex<DfgArraySel, AstArraySel>(const AstArraySel* nodep, DfgGraph& dfg) {
|
||||
// Some earlier passes create malformed ArraySels, just bail on those...
|
||||
// See t_bitsel_wire_array_bad
|
||||
if (VN_IS(nodep->fromp(), Const)) return nullptr;
|
||||
AstUnpackArrayDType* const fromDtypep
|
||||
= VN_CAST(nodep->fromp()->dtypep()->skipRefp(), UnpackArrayDType);
|
||||
if (!fromDtypep) return nullptr;
|
||||
return new DfgArraySel{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)};
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Currently unhandled nodes
|
||||
// LCOV_EXCL_START
|
||||
|
@ -77,17 +91,6 @@ class AstToDfgVisitor final : public VNVisitor {
|
|||
const VNUser1InUse m_user1InUse;
|
||||
|
||||
// TYPES
|
||||
// Represents a driver during canonicalization
|
||||
struct Driver final {
|
||||
FileLine* m_fileline;
|
||||
DfgVertex* m_vtxp;
|
||||
uint32_t m_lsb;
|
||||
Driver(FileLine* flp, uint32_t lsb, DfgVertex* vtxp)
|
||||
: m_fileline{flp}
|
||||
, m_vtxp{vtxp}
|
||||
, m_lsb{lsb} {}
|
||||
};
|
||||
|
||||
using RootType = std::conditional_t<T_Scoped, AstNetlist, AstModule>;
|
||||
using VariableType = std::conditional_t<T_Scoped, AstVarScope, AstVar>;
|
||||
|
||||
|
@ -122,8 +125,9 @@ class AstToDfgVisitor final : public VNVisitor {
|
|||
|
||||
void markReferenced(AstNode* nodep) {
|
||||
nodep->foreach([this](const AstVarRef* refp) {
|
||||
// No need to (and in fact cannot) mark variables with unsupported dtypes
|
||||
if (!DfgVertex::isSupportedDType(refp->varp()->dtypep())) return;
|
||||
// No need to (and in fact cannot) mark variables if:
|
||||
if (!DfgVertex::isSupportedDType(refp->varp()->dtypep())) return; // unsupported type
|
||||
if (refp->varp()->isSc()) return; // SystemC
|
||||
VariableType* const tgtp = getTarget(refp);
|
||||
// Mark vertex as having a module reference outside current DFG
|
||||
getNet(tgtp)->setHasModRefs();
|
||||
|
@ -183,75 +187,144 @@ 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) {
|
||||
std::pair<DfgVertexSplice*, uint32_t> convertLValue(AstNode* nodep) {
|
||||
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 (m_foundUnhandled) return {nullptr, 0};
|
||||
|
||||
// Get the variable vertex
|
||||
DfgVertexVar* const vtxp = getVertex(vrefp)->template as<DfgVertexVar>();
|
||||
// Ensure the Splice driver exists for this variable
|
||||
if (!vtxp->srcp()) {
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
AstNodeDType* const dtypep = vtxp->dtypep();
|
||||
if (vtxp->is<DfgVarPacked>()) {
|
||||
vtxp->srcp(new DfgSplicePacked{*m_dfgp, flp, dtypep});
|
||||
} else if (vtxp->is<DfgVarArray>()) {
|
||||
vtxp->srcp(new DfgSpliceArray{*m_dfgp, flp, dtypep});
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unhandled DfgVertexVar sub-type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
// Return the Splice driver
|
||||
return {vtxp->srcp()->as<DfgVertexSplice>(), 0};
|
||||
}
|
||||
if (AstSel* const selp = VN_CAST(nodep, Sel)) {
|
||||
AstVarRef* const vrefp = VN_CAST(selp->fromp(), VarRef);
|
||||
|
||||
if (AstSel* selp = VN_CAST(nodep, Sel)) {
|
||||
// Only handle constant selects
|
||||
const AstConst* const lsbp = VN_CAST(selp->lsbp(), Const);
|
||||
if (!vrefp || !lsbp) {
|
||||
if (!lsbp) {
|
||||
++m_ctx.m_nonRepLhs;
|
||||
return false;
|
||||
return {nullptr, 0};
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (AstConcat* const concatp = VN_CAST(nodep, Concat)) {
|
||||
AstNode* const lhsp = concatp->lhsp();
|
||||
AstNode* const rhsp = concatp->rhsp();
|
||||
uint32_t lsb = lsbp->toUInt();
|
||||
|
||||
{
|
||||
FileLine* const lFlp = lhsp->fileline();
|
||||
DfgSel* const lVtxp = new DfgSel{*m_dfgp, lFlp, DfgVertex::dtypeFor(lhsp)};
|
||||
// Convert the 'fromp' sub-expression
|
||||
const auto pair = convertLValue(selp->fromp());
|
||||
if (!pair.first) return {nullptr, 0};
|
||||
DfgSplicePacked* const splicep = pair.first->template as<DfgSplicePacked>();
|
||||
// Adjust index.
|
||||
lsb += pair.second;
|
||||
|
||||
// AstSel doesn't change type kind (array vs packed), so we can use
|
||||
// the existing splice driver with adjusted lsb
|
||||
return {splicep, lsb};
|
||||
}
|
||||
|
||||
if (AstArraySel* const aselp = VN_CAST(nodep, ArraySel)) {
|
||||
// Only handle constant selects
|
||||
const AstConst* const indexp = VN_CAST(aselp->bitp(), Const);
|
||||
if (!indexp) {
|
||||
++m_ctx.m_nonRepLhs;
|
||||
return {nullptr, 0};
|
||||
}
|
||||
uint32_t index = indexp->toUInt();
|
||||
|
||||
// Convert the 'fromp' sub-expression
|
||||
const auto pair = convertLValue(aselp->fromp());
|
||||
if (!pair.first) return {nullptr, 0};
|
||||
DfgSpliceArray* const splicep = pair.first->template as<DfgSpliceArray>();
|
||||
// Adjust index. Note pair.second is always 0, but we might handle array slices later..
|
||||
index += pair.second;
|
||||
|
||||
// Ensure the Splice driver exists for this element
|
||||
if (!splicep->driverAt(index)) {
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstNodeDType* const dtypep = DfgVertex::dtypeFor(nodep);
|
||||
if (VN_IS(dtypep, BasicDType)) {
|
||||
splicep->addDriver(flp, index, new DfgSplicePacked{*m_dfgp, flp, dtypep});
|
||||
} else if (VN_IS(dtypep, UnpackArrayDType)) {
|
||||
splicep->addDriver(flp, index, new DfgSpliceArray{*m_dfgp, flp, dtypep});
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unhandled AstNodeDType sub-type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
// Return the splice driver
|
||||
return {splicep->driverAt(index)->as<DfgVertexSplice>(), 0};
|
||||
}
|
||||
|
||||
++m_ctx.m_nonRepLhs;
|
||||
return {nullptr, 0};
|
||||
}
|
||||
|
||||
// Build DfgEdge representing the LValue assignment. Returns false if unsuccessful.
|
||||
bool convertAssignment(FileLine* flp, AstNode* lhsp, DfgVertex* vtxp) {
|
||||
// Simplify the LHS, to get rid of things like SEL(CONCAT(_, _), _)
|
||||
lhsp = V3Const::constifyExpensiveEdit(lhsp);
|
||||
|
||||
// Concatenation on the LHS. Select parts of the driving 'vtxp' then convert each part
|
||||
if (AstConcat* const concatp = VN_CAST(lhsp, Concat)) {
|
||||
AstNode* const cLhsp = concatp->lhsp();
|
||||
AstNode* const cRhsp = concatp->rhsp();
|
||||
|
||||
{ // Convet LHS of concat
|
||||
FileLine* const lFlp = cLhsp->fileline();
|
||||
DfgSel* const lVtxp = new DfgSel{*m_dfgp, lFlp, DfgVertex::dtypeFor(cLhsp)};
|
||||
lVtxp->fromp(vtxp);
|
||||
lVtxp->lsb(rhsp->width());
|
||||
if (!convertAssignment(flp, lhsp, lVtxp)) return false;
|
||||
lVtxp->lsb(cRhsp->width());
|
||||
if (!convertAssignment(flp, cLhsp, lVtxp)) return false;
|
||||
}
|
||||
|
||||
{
|
||||
FileLine* const rFlp = rhsp->fileline();
|
||||
DfgSel* const rVtxp = new DfgSel{*m_dfgp, rFlp, DfgVertex::dtypeFor(rhsp)};
|
||||
{ // Convert RHS of concat
|
||||
FileLine* const rFlp = cRhsp->fileline();
|
||||
DfgSel* const rVtxp = new DfgSel{*m_dfgp, rFlp, DfgVertex::dtypeFor(cRhsp)};
|
||||
rVtxp->fromp(vtxp);
|
||||
rVtxp->lsb(0);
|
||||
return convertAssignment(flp, rhsp, rVtxp);
|
||||
return convertAssignment(flp, cRhsp, rVtxp);
|
||||
}
|
||||
}
|
||||
++m_ctx.m_nonRepLhs;
|
||||
return false;
|
||||
|
||||
// Construct LHS
|
||||
const auto pair = convertLValue(lhsp);
|
||||
if (!pair.first) return false;
|
||||
|
||||
// If successful connect the driver
|
||||
if (DfgSplicePacked* const sPackedp = pair.first->template cast<DfgSplicePacked>()) {
|
||||
sPackedp->addDriver(flp, pair.second, vtxp);
|
||||
} else if (DfgSpliceArray* const sArrayp = pair.first->template cast<DfgSpliceArray>()) {
|
||||
sArrayp->addDriver(flp, pair.second, vtxp);
|
||||
} else {
|
||||
lhsp->v3fatalSrc("Unhandled DfgVertexSplice sub-type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool convertEquation(AstNode* nodep, FileLine* flp, AstNode* lhsp, AstNode* rhsp) {
|
||||
UASSERT_OBJ(m_uncommittedVertices.empty(), nodep, "Should not nest");
|
||||
|
||||
// Currently cannot handle direct assignments between unpacked types. These arise e.g.
|
||||
// when passing an unpacked array through a module port.
|
||||
if (!DfgVertex::isSupportedPackedDType(lhsp->dtypep())
|
||||
|| !DfgVertex::isSupportedPackedDType(rhsp->dtypep())) {
|
||||
// Check data types are compatible.
|
||||
if (!DfgVertex::isSupportedDType(lhsp->dtypep())
|
||||
|| !DfgVertex::isSupportedDType(rhsp->dtypep())) {
|
||||
markReferenced(nodep);
|
||||
++m_ctx.m_nonRepDType;
|
||||
return false;
|
||||
}
|
||||
|
||||
// For now, only direct array assignment is supported (e.g. a = b, but not a = _ ? b : c)
|
||||
if (VN_IS(rhsp->dtypep()->skipRefp(), UnpackArrayDType) && !VN_IS(rhsp, VarRef)) {
|
||||
markReferenced(nodep);
|
||||
++m_ctx.m_nonRepDType;
|
||||
return false;
|
||||
|
@ -294,166 +367,310 @@ class AstToDfgVisitor final : public VNVisitor {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Sometime assignment ranges are coalesced by V3Const,
|
||||
// so we unpack concatenations for better error reporting.
|
||||
void addDriver(FileLine* flp, uint32_t lsb, DfgVertex* vtxp,
|
||||
std::vector<Driver>& drivers) const {
|
||||
if (DfgConcat* const concatp = vtxp->cast<DfgConcat>()) {
|
||||
DfgVertex* const rhsp = concatp->rhsp();
|
||||
auto const rhs_width = rhsp->width();
|
||||
addDriver(rhsp->fileline(), lsb, rhsp, drivers);
|
||||
DfgVertex* const lhsp = concatp->lhsp();
|
||||
addDriver(lhsp->fileline(), lsb + rhs_width, lhsp, drivers);
|
||||
concatp->unlinkDelete(*m_dfgp);
|
||||
} else {
|
||||
drivers.emplace_back(flp, lsb, vtxp);
|
||||
// Prune vertices potentially unused due to resolving multiple drivers.
|
||||
// Having multiple drivers is an error and is hence assumed to be rare,
|
||||
// so performance is not very important, set will suffice.
|
||||
void removeUnused(std::set<DfgVertex*>& prune) {
|
||||
while (!prune.empty()) {
|
||||
// Pop last vertex
|
||||
const auto it = prune.begin();
|
||||
DfgVertex* const vtxp = *it;
|
||||
prune.erase(it);
|
||||
// If used (or a variable), then done
|
||||
if (vtxp->hasSinks() || vtxp->is<DfgVertexVar>()) continue;
|
||||
// If unused, then add sources to work list and delete
|
||||
vtxp->forEachSource([&](DfgVertex& src) { prune.emplace(&src); });
|
||||
vtxp->unlinkDelete(*m_dfgp);
|
||||
}
|
||||
}
|
||||
|
||||
// Canonicalize packed variables
|
||||
void canonicalizePacked() {
|
||||
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) {
|
||||
VL_DO_DANGLING(varp->unlinkDelete(*m_dfgp), varp);
|
||||
// Normalize packed driver - return the normalized vertex and location for 'splicep'
|
||||
std::pair<DfgVertex*, FileLine*> //
|
||||
normalizePacked(DfgVertexVar* varp, const std::string& sub, DfgSplicePacked* const splicep) {
|
||||
// Represents a driver of 'splicep'
|
||||
struct Driver final {
|
||||
FileLine* m_fileline;
|
||||
DfgVertex* m_vtxp;
|
||||
uint32_t m_lsb;
|
||||
Driver() = delete;
|
||||
Driver(FileLine* flp, uint32_t lsb, DfgVertex* vtxp)
|
||||
: m_fileline{flp}
|
||||
, m_vtxp{vtxp}
|
||||
, m_lsb{lsb} {}
|
||||
};
|
||||
|
||||
// The drivers of 'splicep'
|
||||
std::vector<Driver> drivers;
|
||||
drivers.reserve(splicep->arity());
|
||||
|
||||
// Sometime assignment ranges are coalesced by V3Const,
|
||||
// so we unpack concatenations for better error reporting.
|
||||
const std::function<void(FileLine*, uint32_t, DfgVertex*)> gather
|
||||
= [&](FileLine* flp, uint32_t lsb, DfgVertex* vtxp) -> void {
|
||||
if (DfgConcat* const concatp = vtxp->cast<DfgConcat>()) {
|
||||
DfgVertex* const rhsp = concatp->rhsp();
|
||||
auto const rhs_width = rhsp->width();
|
||||
gather(rhsp->fileline(), lsb, rhsp);
|
||||
DfgVertex* const lhsp = concatp->lhsp();
|
||||
gather(lhsp->fileline(), lsb + rhs_width, lhsp);
|
||||
concatp->unlinkDelete(*m_dfgp);
|
||||
} else {
|
||||
drivers.emplace_back(flp, lsb, vtxp);
|
||||
}
|
||||
};
|
||||
|
||||
// Gather and unlink all drivers
|
||||
splicep->forEachSourceEdge([&](DfgEdge& edge, size_t idx) {
|
||||
DfgVertex* const driverp = edge.sourcep();
|
||||
UASSERT(driverp, "Should not have created undriven sources");
|
||||
UASSERT_OBJ(!driverp->is<DfgVertexSplice>(), splicep, "Should not be DfgVertexSplice");
|
||||
gather(splicep->driverFileLine(idx), splicep->driverLsb(idx), driverp);
|
||||
edge.unlinkSource();
|
||||
});
|
||||
|
||||
const auto cmp = [](const Driver& a, const Driver& b) {
|
||||
if (a.m_lsb != b.m_lsb) return a.m_lsb < b.m_lsb;
|
||||
return a.m_fileline->operatorCompare(*b.m_fileline) < 0;
|
||||
};
|
||||
|
||||
// Sort drivers by LSB
|
||||
std::stable_sort(drivers.begin(), drivers.end(), cmp);
|
||||
|
||||
// Vertices that might have become unused due to multiple driver resolution. Having
|
||||
// multiple drivers is an error and is hence assumed to be rare, so performance is
|
||||
// not very important, set will suffice.
|
||||
std::set<DfgVertex*> prune;
|
||||
|
||||
// Fix multiply driven ranges
|
||||
for (auto it = drivers.begin(); it != drivers.end();) {
|
||||
Driver& a = *it++;
|
||||
const uint32_t aWidth = a.m_vtxp->width();
|
||||
const uint32_t aEnd = a.m_lsb + aWidth;
|
||||
while (it != drivers.end()) {
|
||||
Driver& b = *it;
|
||||
// If no overlap, then nothing to do
|
||||
if (b.m_lsb >= aEnd) break;
|
||||
|
||||
const uint32_t bWidth = b.m_vtxp->width();
|
||||
const uint32_t bEnd = b.m_lsb + bWidth;
|
||||
const uint32_t overlapEnd = std::min(aEnd, bEnd) - 1;
|
||||
|
||||
if (a.m_fileline->operatorCompare(*b.m_fileline) != 0
|
||||
&& !varp->varp()->isUsedLoopIdx() // Loop index often abused, so suppress
|
||||
) {
|
||||
AstNode* const vp = varp->varScopep()
|
||||
? static_cast<AstNode*>(varp->varScopep())
|
||||
: static_cast<AstNode*>(varp->varp());
|
||||
|
||||
vp->v3warn( //
|
||||
MULTIDRIVEN,
|
||||
"Bits [" //
|
||||
<< overlapEnd << ":" << b.m_lsb << "] of signal '" << vp->prettyName()
|
||||
<< sub << "' have multiple combinational drivers\n"
|
||||
<< a.m_fileline->warnOther() << "... Location of first driver\n"
|
||||
<< a.m_fileline->warnContextPrimary() << '\n'
|
||||
<< b.m_fileline->warnOther() << "... Location of other driver\n"
|
||||
<< b.m_fileline->warnContextSecondary() << vp->warnOther()
|
||||
<< "... Only the first driver will be respected");
|
||||
}
|
||||
|
||||
// If the first driver completely covers the range of the second driver,
|
||||
// we can just delete the second driver completely, otherwise adjust the
|
||||
// second driver to apply from the end of the range of the first driver.
|
||||
if (aEnd >= bEnd) {
|
||||
prune.emplace(b.m_vtxp);
|
||||
it = drivers.erase(it);
|
||||
} else {
|
||||
const auto dtypep = DfgVertex::dtypeForWidth(bEnd - aEnd);
|
||||
DfgSel* const selp = new DfgSel{*m_dfgp, b.m_vtxp->fileline(), dtypep};
|
||||
selp->fromp(b.m_vtxp);
|
||||
selp->lsb(aEnd - b.m_lsb);
|
||||
b.m_lsb = aEnd;
|
||||
b.m_vtxp = selp;
|
||||
std::stable_sort(it, drivers.end(), cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Coalesce adjacent ranges
|
||||
for (size_t i = 0, j = 1; j < drivers.size(); ++j) {
|
||||
Driver& a = drivers[i];
|
||||
Driver& b = drivers[j];
|
||||
|
||||
// Coalesce adjacent range
|
||||
const uint32_t aWidth = a.m_vtxp->width();
|
||||
const uint32_t bWidth = b.m_vtxp->width();
|
||||
if (a.m_lsb + aWidth == b.m_lsb) {
|
||||
const auto dtypep = DfgVertex::dtypeForWidth(aWidth + bWidth);
|
||||
DfgConcat* const concatp = new DfgConcat{*m_dfgp, a.m_fileline, dtypep};
|
||||
concatp->rhsp(a.m_vtxp);
|
||||
concatp->lhsp(b.m_vtxp);
|
||||
a.m_vtxp = concatp;
|
||||
b.m_vtxp = nullptr; // Mark as moved
|
||||
++m_ctx.m_coalescedAssignments;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Gather (and unlink) all drivers
|
||||
std::vector<Driver> drivers;
|
||||
drivers.reserve(varp->arity());
|
||||
varp->forEachSourceEdge([this, varp, &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);
|
||||
edge.unlinkSource();
|
||||
});
|
||||
++i;
|
||||
|
||||
const auto cmp = [](const Driver& a, const Driver& b) {
|
||||
if (a.m_lsb != b.m_lsb) return a.m_lsb < b.m_lsb;
|
||||
return a.m_fileline->operatorCompare(*b.m_fileline) < 0;
|
||||
};
|
||||
|
||||
// Sort drivers by LSB
|
||||
std::stable_sort(drivers.begin(), drivers.end(), cmp);
|
||||
|
||||
// Vertices that might have become unused due to multiple driver resolution. Having
|
||||
// multiple drivers is an error and is hence assumed to be rare, so performance is
|
||||
// not very important, set will suffice.
|
||||
std::set<DfgVertex*> prune;
|
||||
|
||||
// Fix multiply driven ranges
|
||||
for (auto it = drivers.begin(); it != drivers.end();) {
|
||||
Driver& a = *it++;
|
||||
const uint32_t aWidth = a.m_vtxp->width();
|
||||
const uint32_t aEnd = a.m_lsb + aWidth;
|
||||
while (it != drivers.end()) {
|
||||
Driver& b = *it;
|
||||
// If no overlap, then nothing to do
|
||||
if (b.m_lsb >= aEnd) break;
|
||||
|
||||
const uint32_t bWidth = b.m_vtxp->width();
|
||||
const uint32_t bEnd = b.m_lsb + bWidth;
|
||||
const uint32_t overlapEnd = std::min(aEnd, bEnd) - 1;
|
||||
|
||||
if (a.m_fileline->operatorCompare(*b.m_fileline) != 0
|
||||
&& !varp->varp()->isUsedLoopIdx() // Loop index often abused, so suppress
|
||||
) {
|
||||
AstNode* const vp = varp->varScopep()
|
||||
? static_cast<AstNode*>(varp->varScopep())
|
||||
: static_cast<AstNode*>(varp->varp());
|
||||
vp->v3warn( //
|
||||
MULTIDRIVEN,
|
||||
"Bits [" //
|
||||
<< overlapEnd << ":" << b.m_lsb << "] of signal "
|
||||
<< vp->prettyNameQ() << " have multiple combinational drivers\n"
|
||||
<< a.m_fileline->warnOther() << "... Location of first driver\n"
|
||||
<< a.m_fileline->warnContextPrimary() << '\n'
|
||||
<< b.m_fileline->warnOther() << "... Location of other driver\n"
|
||||
<< b.m_fileline->warnContextSecondary() << vp->warnOther()
|
||||
<< "... Only the first driver will be respected");
|
||||
}
|
||||
|
||||
// If the first driver completely covers the range of the second driver,
|
||||
// we can just delete the second driver completely, otherwise adjust the
|
||||
// second driver to apply from the end of the range of the first driver.
|
||||
if (aEnd >= bEnd) {
|
||||
prune.emplace(b.m_vtxp);
|
||||
it = drivers.erase(it);
|
||||
} else {
|
||||
const auto dtypep = DfgVertex::dtypeForWidth(bEnd - aEnd);
|
||||
DfgSel* const selp = new DfgSel{*m_dfgp, b.m_vtxp->fileline(), dtypep};
|
||||
selp->fromp(b.m_vtxp);
|
||||
selp->lsb(aEnd - b.m_lsb);
|
||||
b.m_lsb = aEnd;
|
||||
b.m_vtxp = selp;
|
||||
std::stable_sort(it, drivers.end(), cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Coalesce adjacent ranges
|
||||
for (size_t i = 0, j = 1; j < drivers.size(); ++j) {
|
||||
Driver& a = drivers[i];
|
||||
Driver& b = drivers[j];
|
||||
|
||||
// Coalesce adjacent range
|
||||
const uint32_t aWidth = a.m_vtxp->width();
|
||||
const uint32_t bWidth = b.m_vtxp->width();
|
||||
if (a.m_lsb + aWidth == b.m_lsb) {
|
||||
const auto dtypep = DfgVertex::dtypeForWidth(aWidth + bWidth);
|
||||
DfgConcat* const concatp = new DfgConcat{*m_dfgp, a.m_fileline, dtypep};
|
||||
concatp->rhsp(a.m_vtxp);
|
||||
concatp->lhsp(b.m_vtxp);
|
||||
a.m_vtxp = concatp;
|
||||
b.m_vtxp = nullptr; // Mark as moved
|
||||
++m_ctx.m_coalescedAssignments;
|
||||
continue;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
// Compact non-adjacent ranges within the vector
|
||||
if (j != i) {
|
||||
Driver& c = drivers[i];
|
||||
UASSERT_OBJ(!c.m_vtxp, c.m_fileline, "Should have been marked moved");
|
||||
c = b;
|
||||
b.m_vtxp = nullptr; // Mark as moved
|
||||
}
|
||||
}
|
||||
|
||||
// Reinsert drivers in order
|
||||
varp->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);
|
||||
}
|
||||
|
||||
// Prune vertices potentially unused due to resolving multiple drivers.
|
||||
while (!prune.empty()) {
|
||||
// Pop last vertex
|
||||
const auto it = prune.begin();
|
||||
DfgVertex* const vtxp = *it;
|
||||
prune.erase(it);
|
||||
// If used (or a variable), then done
|
||||
if (vtxp->hasSinks() || vtxp->is<DfgVertexVar>()) continue;
|
||||
// If unused, then add sources to work list and delete
|
||||
vtxp->forEachSource([&](DfgVertex& src) { prune.emplace(&src); });
|
||||
vtxp->unlinkDelete(*m_dfgp);
|
||||
// Compact non-adjacent ranges within the vector
|
||||
if (j != i) {
|
||||
Driver& c = drivers[i];
|
||||
UASSERT_OBJ(!c.m_vtxp, c.m_fileline, "Should have been marked moved");
|
||||
c = b;
|
||||
b.m_vtxp = nullptr; // Mark as moved
|
||||
}
|
||||
}
|
||||
|
||||
// Reinsert drivers in order
|
||||
splicep->resetSources();
|
||||
for (const Driver& driver : drivers) {
|
||||
if (!driver.m_vtxp) break; // Stop at end of compacted list
|
||||
splicep->addDriver(driver.m_fileline, driver.m_lsb, driver.m_vtxp);
|
||||
}
|
||||
|
||||
removeUnused(prune);
|
||||
|
||||
// If the whole variable is driven whole, we can just use that driver
|
||||
if (splicep->arity() == 1 //
|
||||
&& splicep->driverLsb(0) == 0 //
|
||||
&& splicep->source(0)->width() == splicep->width()) {
|
||||
const auto result = std::make_pair(splicep->source(0), splicep->driverFileLine(0));
|
||||
VL_DO_DANGLING(splicep->unlinkDelete(*m_dfgp), splicep);
|
||||
return result;
|
||||
}
|
||||
return {splicep, splicep->fileline()};
|
||||
}
|
||||
|
||||
// Canonicalize array variables
|
||||
void canonicalizeArray() {
|
||||
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) {
|
||||
VL_DO_DANGLING(varp->unlinkDelete(*m_dfgp), varp);
|
||||
// Normalize array driver - return the normalized vertex and location for 'splicep'
|
||||
std::pair<DfgVertex*, FileLine*> //
|
||||
normalizeArray(DfgVertexVar* varp, const std::string& sub, DfgSpliceArray* const splicep) {
|
||||
// Represents a driver of 'splicep'
|
||||
struct Driver final {
|
||||
FileLine* m_fileline;
|
||||
DfgVertex* m_vtxp;
|
||||
uint32_t m_idx;
|
||||
Driver() = delete;
|
||||
Driver(FileLine* flp, uint32_t idx, DfgVertex* vtxp)
|
||||
: m_fileline{flp}
|
||||
, m_vtxp{vtxp}
|
||||
, m_idx{idx} {}
|
||||
};
|
||||
|
||||
// The drivers of 'splicep'
|
||||
std::vector<Driver> drivers;
|
||||
drivers.reserve(splicep->arity());
|
||||
|
||||
// Normalize, gather, and unlink all drivers
|
||||
splicep->forEachSourceEdge([&](DfgEdge& edge, size_t i) {
|
||||
DfgVertex* const driverp = edge.sourcep();
|
||||
UASSERT(driverp, "Should not have created undriven sources");
|
||||
const uint32_t idx = splicep->driverIndex(i);
|
||||
if (DfgSplicePacked* const spp = driverp->cast<DfgSplicePacked>()) {
|
||||
const auto pair
|
||||
= normalizePacked(varp, sub + "[" + std::to_string(idx) + "]", spp);
|
||||
drivers.emplace_back(pair.second, idx, pair.first);
|
||||
} else if (DfgSpliceArray* const sap = driverp->cast<DfgSpliceArray>()) {
|
||||
const auto pair = normalizeArray(varp, sub + "[" + std::to_string(idx) + "]", sap);
|
||||
drivers.emplace_back(pair.second, idx, pair.first);
|
||||
} else if (driverp->is<DfgVertexSplice>()) {
|
||||
driverp->v3fatalSrc("Unhandled DfgVertexSplice sub-type");
|
||||
} else {
|
||||
drivers.emplace_back(splicep->driverFileLine(i), idx, driverp);
|
||||
}
|
||||
edge.unlinkSource();
|
||||
});
|
||||
|
||||
const auto cmp = [](const Driver& a, const Driver& b) {
|
||||
if (a.m_idx != b.m_idx) return a.m_idx < b.m_idx;
|
||||
return a.m_fileline->operatorCompare(*b.m_fileline) < 0;
|
||||
};
|
||||
|
||||
// Sort drivers by index
|
||||
std::stable_sort(drivers.begin(), drivers.end(), cmp);
|
||||
|
||||
// Vertices that become unused due to multiple driver resolution
|
||||
std::set<DfgVertex*> prune;
|
||||
|
||||
// Fix multiply driven ranges
|
||||
for (auto it = drivers.begin(); it != drivers.end();) {
|
||||
Driver& a = *it++;
|
||||
AstUnpackArrayDType* aArrayDTypep = VN_CAST(a.m_vtxp->dtypep(), UnpackArrayDType);
|
||||
const uint32_t aElements = aArrayDTypep ? aArrayDTypep->elementsConst() : 1;
|
||||
const uint32_t aEnd = a.m_idx + aElements;
|
||||
while (it != drivers.end()) {
|
||||
Driver& b = *it;
|
||||
// If no overlap, then nothing to do
|
||||
if (b.m_idx >= aEnd) break;
|
||||
|
||||
AstUnpackArrayDType* bArrayDTypep = VN_CAST(b.m_vtxp->dtypep(), UnpackArrayDType);
|
||||
const uint32_t bElements = bArrayDTypep ? bArrayDTypep->elementsConst() : 1;
|
||||
const uint32_t bEnd = b.m_idx + bElements;
|
||||
const uint32_t overlapEnd = std::min(aEnd, bEnd) - 1;
|
||||
|
||||
if (a.m_fileline->operatorCompare(*b.m_fileline) != 0) {
|
||||
AstNode* const vp = varp->varScopep()
|
||||
? static_cast<AstNode*>(varp->varScopep())
|
||||
: static_cast<AstNode*>(varp->varp());
|
||||
|
||||
vp->v3warn( //
|
||||
MULTIDRIVEN,
|
||||
"Elements [" //
|
||||
<< overlapEnd << ":" << b.m_idx << "] of signal '" << vp->prettyName()
|
||||
<< sub << "' have multiple combinational drivers\n"
|
||||
<< a.m_fileline->warnOther() << "... Location of first driver\n"
|
||||
<< a.m_fileline->warnContextPrimary() << '\n'
|
||||
<< b.m_fileline->warnOther() << "... Location of other driver\n"
|
||||
<< b.m_fileline->warnContextSecondary() << vp->warnOther()
|
||||
<< "... Only the first driver will be respected");
|
||||
}
|
||||
|
||||
// If the first driver completely covers the range of the second driver,
|
||||
// we can just delete the second driver completely, otherwise adjust the
|
||||
// second driver to apply from the end of the range of the first driver.
|
||||
if (aEnd >= bEnd) {
|
||||
prune.emplace(b.m_vtxp);
|
||||
it = drivers.erase(it);
|
||||
} else {
|
||||
const auto distance = std::distance(drivers.begin(), it);
|
||||
DfgVertex* const bVtxp = b.m_vtxp;
|
||||
FileLine* const flp = b.m_vtxp->fileline();
|
||||
AstNodeDType* const elemDtypep = DfgVertex::dtypeFor(
|
||||
VN_AS(splicep->dtypep(), UnpackArrayDType)->subDTypep());
|
||||
// Remove this driver
|
||||
it = drivers.erase(it);
|
||||
// Add missing items element-wise
|
||||
for (uint32_t i = aEnd; i < bEnd; ++i) {
|
||||
DfgArraySel* const aselp = new DfgArraySel{*m_dfgp, flp, elemDtypep};
|
||||
aselp->fromp(bVtxp);
|
||||
aselp->bitp(new DfgConst{*m_dfgp, flp, 32, i});
|
||||
drivers.emplace_back(flp, i, aselp);
|
||||
}
|
||||
it = drivers.begin();
|
||||
std::advance(it, distance);
|
||||
std::stable_sort(it, drivers.end(), cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reinsert drivers in order
|
||||
splicep->resetSources();
|
||||
for (const Driver& driver : drivers) {
|
||||
if (!driver.m_vtxp) break; // Stop at end of compacted list
|
||||
splicep->addDriver(driver.m_fileline, driver.m_idx, driver.m_vtxp);
|
||||
}
|
||||
|
||||
removeUnused(prune);
|
||||
|
||||
// If the whole variable is driven whole, we can just use that driver
|
||||
if (splicep->arity() == 1 //
|
||||
&& splicep->driverIndex(0) == 0 //
|
||||
&& splicep->source(0)->dtypep()->isSame(splicep->dtypep())) {
|
||||
const auto result = std::make_pair(splicep->source(0), splicep->driverFileLine(0));
|
||||
VL_DO_DANGLING(splicep->unlinkDelete(*m_dfgp), splicep);
|
||||
return result;
|
||||
}
|
||||
return {splicep, splicep->fileline()};
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
@ -593,6 +810,7 @@ class AstToDfgVisitor final : public VNVisitor {
|
|||
|| nodep->varp()->isIfaceRef() // Cannot handle interface references
|
||||
|| nodep->varp()->delayp() // Cannot handle delayed variables
|
||||
|| nodep->classOrPackagep() // Cannot represent cross module references
|
||||
|| nodep->varp()->isSc() // SystemC variables are special and rare, we can ignore
|
||||
) {
|
||||
markReferenced(nodep);
|
||||
m_foundUnhandled = true;
|
||||
|
@ -675,9 +893,32 @@ class AstToDfgVisitor final : public VNVisitor {
|
|||
iterate(&root);
|
||||
UASSERT_OBJ(m_uncommittedVertices.empty(), &root, "Uncommitted vertices remain");
|
||||
|
||||
// Canonicalize variables
|
||||
canonicalizePacked();
|
||||
canonicalizeArray();
|
||||
if (dumpDfgLevel() >= 8) m_dfgp->dumpDotFilePrefixed(ctx.prefix() + "ast2dfg");
|
||||
|
||||
// Normalize variable drivers (remove multiple drivers, remove unnecessary splice vertices)
|
||||
for (DfgVertexVar* const varp : m_dfgp->varVertices().unlinkable()) {
|
||||
// Delete variables with no sinks nor sources (this can happen due to reverting
|
||||
// uncommitted vertices, which does not remove variables)
|
||||
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;
|
||||
|
||||
// The driver of a variable must always be a splice vertex, normalize it
|
||||
std::pair<DfgVertex*, FileLine*> normalizedDriver;
|
||||
if (DfgSpliceArray* const sArrayp = varp->srcp()->cast<DfgSpliceArray>()) {
|
||||
normalizedDriver = normalizeArray(varp, "", sArrayp);
|
||||
} else if (DfgSplicePacked* const sPackedp = varp->srcp()->cast<DfgSplicePacked>()) {
|
||||
normalizedDriver = normalizePacked(varp, "", sPackedp);
|
||||
} else {
|
||||
varp->v3fatalSrc("Unhandled DfgSplicePacked sub-type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
varp->srcp(normalizedDriver.first);
|
||||
varp->driverFileLine(normalizedDriver.second);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
|
|
@ -188,58 +188,57 @@ class DfgToAstVisitor final : DfgVisitor {
|
|||
return resultp;
|
||||
}
|
||||
|
||||
void addResultEquation(const DfgVertexVar* vtxp, FileLine* flp, AstNodeExpr* lhsp,
|
||||
AstNodeExpr* rhsp) {
|
||||
AstAssignW* const assignp = new AstAssignW{flp, lhsp, rhsp};
|
||||
if VL_CONSTEXPR_CXX17 (T_Scoped) {
|
||||
// Add it to the scope holding the target variable
|
||||
getCombActive(vtxp->varScopep()->scopep())->addStmtsp(assignp);
|
||||
} else {
|
||||
// Add it to the parend module of the DfgGraph
|
||||
m_modp->addStmtsp(assignp);
|
||||
void convertDriver(AstScope* scopep, FileLine* flp, AstNodeExpr* lhsp, DfgVertex* driverp) {
|
||||
if (!driverp->is<DfgVertexSplice>()) {
|
||||
// Base case: assign vertex to current lhs
|
||||
AstNodeExpr* const rhsp = convertDfgVertexToAstNodeExpr(driverp);
|
||||
AstAssignW* const assignp = new AstAssignW{flp, lhsp, rhsp};
|
||||
lhsp->foreach([flp](AstNode* nodep) { nodep->fileline(flp); });
|
||||
if VL_CONSTEXPR_CXX17 (T_Scoped) {
|
||||
// Add it to the scope holding the target variable
|
||||
getCombActive(scopep)->addStmtsp(assignp);
|
||||
} else {
|
||||
// Add it to the parend module of the DfgGraph
|
||||
m_modp->addStmtsp(assignp);
|
||||
}
|
||||
++m_ctx.m_resultEquations;
|
||||
return;
|
||||
}
|
||||
++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 {
|
||||
// Variable is driven partially. Render each driver as a separate assignment.
|
||||
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 lsbp = new AstConst{flp, dfgVarp->driverLsb(idx)};
|
||||
if (DfgSplicePacked* const sPackedp = driverp->cast<DfgSplicePacked>()) {
|
||||
// Partial assignment of packed value
|
||||
sPackedp->forEachSourceEdge([&](const DfgEdge& edge, size_t i) {
|
||||
UASSERT_OBJ(edge.sourcep(), sPackedp, "Should have removed undriven sources");
|
||||
// Create Sel
|
||||
FileLine* const dflp = sPackedp->driverFileLine(i);
|
||||
AstConst* const lsbp = new AstConst{dflp, sPackedp->driverLsb(i)};
|
||||
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);
|
||||
AstSel* const nLhsp = new AstSel{dflp, lhsp->cloneTreePure(false), lsbp, width};
|
||||
// Convert source
|
||||
convertDriver(scopep, dflp, nLhsp, edge.sourcep());
|
||||
// Delete Sel if not consumed
|
||||
if (!nLhsp->backp()) VL_DO_DANGLING(nLhsp->deleteTree(), nLhsp);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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 sArrayp = driverp->cast<DfgSpliceArray>()) {
|
||||
// Partial assignment of array variable
|
||||
sArrayp->forEachSourceEdge([&](const DfgEdge& edge, size_t i) {
|
||||
UASSERT_OBJ(edge.sourcep(), sArrayp, "Should have removed undriven sources");
|
||||
// Create ArraySel
|
||||
FileLine* const dflp = sArrayp->driverFileLine(i);
|
||||
AstConst* const idxp = new AstConst{dflp, sArrayp->driverIndex(i)};
|
||||
AstArraySel* const nLhsp = new AstArraySel{dflp, lhsp->cloneTreePure(false), idxp};
|
||||
// Convert source
|
||||
convertDriver(scopep, dflp, nLhsp, edge.sourcep());
|
||||
// Delete ArraySel if not consumed
|
||||
if (!nLhsp->backp()) VL_DO_DANGLING(nLhsp->deleteTree(), nLhsp);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
driverp->v3fatalSrc("Unhandled DfgVertexSplice sub-type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
@ -285,16 +284,15 @@ 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);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Render array variable assignments
|
||||
convertArrayDiver(vtx.as<DfgVarArray>());
|
||||
// Render variable assignments
|
||||
FileLine* const flp = vtx.driverFileLine() ? vtx.driverFileLine() : vtx.fileline();
|
||||
AstScope* const scopep = T_Scoped ? vtx.varScopep()->scopep() : nullptr;
|
||||
AstVarRef* const lhsp = new AstVarRef{flp, getNode(&vtx), VAccess::WRITE};
|
||||
convertDriver(scopep, flp, lhsp, vtx.srcp());
|
||||
// convetDriver clones and might not use up the original lhsp
|
||||
if (!lhsp->backp()) VL_DO_DANGLING(lhsp->deleteTree(), lhsp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
@ -159,18 +169,8 @@ void V3DfgPasses::cse(DfgGraph& dfg, V3DfgCseContext& ctx) {
|
|||
void V3DfgPasses::inlineVars(DfgGraph& dfg) {
|
||||
for (DfgVertexVar& vtx : dfg.varVertices()) {
|
||||
if (DfgVarPacked* const varp = vtx.cast<DfgVarPacked>()) {
|
||||
// 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);
|
||||
|
||||
// We must keep the original driver in certain cases, when swapping them would
|
||||
// not be functionally or technically (implementation reasons) equivalent:
|
||||
// 1. If driven from a SystemC variable (assignment is non-trivial)
|
||||
if (DfgVertexVar* const driverVarp = driverp->cast<DfgVarPacked>()) {
|
||||
if (driverVarp->varp()->isSc()) continue;
|
||||
}
|
||||
|
||||
if (varp->hasSinks() && varp->isDrivenFullyByDfg()) {
|
||||
DfgVertex* const driverp = varp->srcp();
|
||||
varp->forEachSinkEdge([=](DfgEdge& edge) { edge.relinkSource(driverp); });
|
||||
}
|
||||
}
|
||||
|
@ -371,12 +371,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,12 +546,10 @@ 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>()) {
|
||||
// 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;
|
||||
} else if (DfgVarPacked* const driverp = varp->srcp()->cast<DfgVarPacked>()) {
|
||||
// If it's driven from another variable, it can be replaced by that.
|
||||
// Mark it for replacement
|
||||
++ctx.m_varsReplaced;
|
||||
UASSERT_OBJ(!varp->hasSinks(), varp, "Variable inlining should make this impossible");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,16 @@ 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() && !varp->varp()->isForced()) {
|
||||
if (DfgSpliceArray* const splicep = varp->srcp()->cast<DfgSpliceArray>()) {
|
||||
if (DfgVertex* const driverp = splicep->driverAt(idxp->toSizeT())) {
|
||||
if (!driverp->is<DfgVertexSplice>()) {
|
||||
APPLYING(INLINE_ARRAYSEL) {
|
||||
replace(vtxp, driverp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1252,6 +1367,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 +1389,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 +1544,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 +1589,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 +1666,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);
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -45,12 +45,15 @@ class DfgRegularize final {
|
|||
// Ensure intermediate values used multiple times are written to variables
|
||||
for (DfgVertex& vtx : m_dfg.opVertices()) {
|
||||
const bool needsIntermediateVariable = [&]() {
|
||||
// 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 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>() && !snk.is<DfgVertexSplice>();
|
||||
});
|
||||
return hasNonVarSink;
|
||||
}
|
||||
// Operations without multiple sinks need no variables
|
||||
if (!vtx.hasMultipleSinks()) return false;
|
||||
// Array selects need no variables, they are just memory references
|
||||
|
@ -63,26 +66,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 =====================================================
|
||||
|
||||
|
@ -178,20 +193,58 @@ class DfgVarArray final : public DfgVertexVar {
|
|||
friend class DfgVertex;
|
||||
friend class DfgVisitor;
|
||||
|
||||
using DriverData = std::pair<FileLine*, uint32_t>;
|
||||
|
||||
std::vector<DriverData> m_driverData; // Additional data associate with each driver
|
||||
|
||||
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;
|
||||
|
||||
struct DriverData final {
|
||||
FileLine* m_flp; // Location of this driver
|
||||
uint32_t m_index; // Array index driven by this driver (or low index of range)
|
||||
DriverData() = delete;
|
||||
DriverData(FileLine* flp, uint32_t index)
|
||||
: m_flp{flp}
|
||||
, m_index{index} {}
|
||||
};
|
||||
|
||||
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,29 +256,8 @@ 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; }
|
||||
FileLine* driverFileLine(size_t i) const { return m_driverData.at(i).m_flp; }
|
||||
uint32_t driverIndex(size_t i) const { return m_driverData.at(i).m_index; }
|
||||
|
||||
DfgVertex* driverAt(size_t idx) const {
|
||||
const DfgEdge* const edgep = findSourceEdge([this, idx](const DfgEdge&, size_t i) { //
|
||||
|
@ -234,26 +266,33 @@ 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>;
|
||||
struct DriverData final {
|
||||
FileLine* m_flp; // Location of this driver
|
||||
uint32_t m_lsb; // LSB of range driven by this driver
|
||||
DriverData() = delete;
|
||||
DriverData(FileLine* flp, uint32_t lsb)
|
||||
: m_flp{flp}
|
||||
, m_lsb{lsb} {}
|
||||
};
|
||||
std::vector<DriverData> m_driverData; // Additional data associated with each driver
|
||||
|
||||
std::vector<DriverData> m_driverData; // Additional data associate 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 +304,10 @@ public:
|
|||
DfgVertexVariadic::resetSources();
|
||||
}
|
||||
|
||||
// Remove undriven sources
|
||||
void packSources() {
|
||||
// Grab and reset the driver data
|
||||
std::vector<DriverData> driverData;
|
||||
driverData.swap(m_driverData);
|
||||
FileLine* driverFileLine(size_t i) const { return m_driverData.at(i).m_flp; }
|
||||
uint32_t driverLsb(size_t i) const { return m_driverData.at(i).m_lsb; }
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -247,14 +247,14 @@ void EmitCFunc::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const
|
|||
AstNode* argp = nullptr;
|
||||
if (!ignore) {
|
||||
argp = *elistp;
|
||||
// Prep for next parameter
|
||||
*elistp = (*elistp)->nextp();
|
||||
if (VL_UNCOVERABLE(!argp)) {
|
||||
// expectDisplay() checks this first, so internal error if found here
|
||||
dispp->v3error(
|
||||
"Internal: Missing arguments for $display-like format"); // LCOV_EXCL_LINE
|
||||
return; // LCOV_EXCL_LINE
|
||||
}
|
||||
// Prep for next parameter
|
||||
*elistp = (*elistp)->nextp();
|
||||
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
||||
dispp->v3warn(E_UNSUPPORTED, "Unsupported: Exceeded limit of "
|
||||
+ cvtToStr(VL_VALUE_STRING_MAX_WIDTH)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -743,13 +743,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 +760,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");
|
||||
|
@ -964,9 +964,9 @@ void EmitCSyms::emitSymImp() {
|
|||
} else {
|
||||
if (basicp->isRanged()) {
|
||||
bounds += " ,";
|
||||
bounds += cvtToStr(basicp->hi());
|
||||
bounds += cvtToStr(basicp->left());
|
||||
bounds += ",";
|
||||
bounds += cvtToStr(basicp->lo());
|
||||
bounds += cvtToStr(basicp->right());
|
||||
pdim++;
|
||||
}
|
||||
break; // AstBasicDType - nothing below, 1
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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});
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
@ -3493,9 +3589,6 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
UINFO(9, indent() << m_ds.ascii());
|
||||
VL_RESTORER(m_usedPins);
|
||||
m_usedPins.clear();
|
||||
UASSERT_OBJ(m_statep->forPrimary() || VN_IS(nodep->classOrPackageNodep(), ParamTypeDType)
|
||||
|| nodep->classOrPackageSkipp(),
|
||||
nodep, "ClassRef has unlinked class");
|
||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
||||
"class reference parameter not removed by V3Param");
|
||||
{
|
||||
|
@ -3506,6 +3599,10 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, m_ds.m_dotPos != DP_PACKAGE,
|
||||
false, ":: reference");
|
||||
}
|
||||
UASSERT_OBJ(m_statep->forPrimary()
|
||||
|| VN_IS(nodep->classOrPackageNodep(), ParamTypeDType)
|
||||
|| nodep->classOrPackageSkipp(),
|
||||
nodep, "ClassRef has unlinked class");
|
||||
|
||||
// ClassRef's have pins, so track
|
||||
if (nodep->classOrPackageSkipp()) {
|
||||
|
@ -3665,7 +3762,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 +3790,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 +3824,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 +3933,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 +4072,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 +4080,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 +4302,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 +4509,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 +4527,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 +4572,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 +4604,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 +4768,7 @@ void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
|
|||
state.computeIfaceVarSyms();
|
||||
state.computeScopeAliases();
|
||||
state.dumpSelf();
|
||||
{ LinkDotResolveVisitor{rootp, &state}; }
|
||||
LinkDotResolveVisitor visitor{rootp, &state};
|
||||
state.dumpSelf();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -2242,6 +2242,13 @@ V3Number& V3Number::opBufIf1(const V3Number& ens, const V3Number& if1s) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
// Sets all bits in range to the given value
|
||||
V3Number& V3Number::opSetRange(uint32_t lsb, uint32_t width, char bitValue) {
|
||||
const uint32_t msb = lsb + width - 1;
|
||||
for (uint32_t i = lsb; i <= msb; ++i) setBit(i, bitValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opAssign(const V3Number& lhs) { return opAssignNonXZ(lhs, false); }
|
||||
V3Number& V3Number::opAssignNonXZ(const V3Number& lhs, bool ignoreXZ) {
|
||||
// Note may be a width change during the assign.
|
||||
|
|
|
@ -564,7 +564,6 @@ private:
|
|||
}
|
||||
}
|
||||
static string displayPad(size_t fmtsize, char pad, bool left, const string& in) VL_PURE;
|
||||
string displayed(FileLine* fl, const string& vformat) const VL_MT_STABLE;
|
||||
string displayed(const string& vformat) const VL_MT_STABLE {
|
||||
return displayed(m_fileline, vformat);
|
||||
}
|
||||
|
@ -592,6 +591,7 @@ public:
|
|||
// ACCESSORS
|
||||
string ascii(bool prefixed = true, bool cleanVerilog = false) const VL_MT_STABLE;
|
||||
string displayed(AstNode* nodep, const string& vformat) const VL_MT_STABLE;
|
||||
string displayed(FileLine* fl, const string& vformat) const VL_MT_STABLE;
|
||||
static bool displayedFmtLegal(char format, bool isScan); // Is this a valid format letter?
|
||||
int width() const VL_MT_SAFE { return m_data.width(); }
|
||||
int widthToFit() const; // Minimum width that can represent this number (~== log2(num)+1)
|
||||
|
@ -716,6 +716,7 @@ public:
|
|||
V3Number& opWildEq(const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildNeq(const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opBufIf1(const V3Number& ens, const V3Number& if1s);
|
||||
V3Number& opSetRange(uint32_t lsb, uint32_t width, char bitValue);
|
||||
// "standard" math
|
||||
V3Number& opNot(const V3Number& lhs);
|
||||
V3Number& opLogNot(const V3Number& lhs);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -1116,7 +1116,7 @@ class ParamVisitor final : public VNVisitor {
|
|||
} else {
|
||||
cellp->v3fatalSrc("Expected module parameterization");
|
||||
}
|
||||
UASSERT_OBJ(srcModp, cellp, "Unlinked class ref");
|
||||
if (!srcModp) continue;
|
||||
|
||||
// Update path
|
||||
string someInstanceName = modp->someInstanceName();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ class UnrollVisitor final : public VNVisitor {
|
|||
bool m_varModeCheck; // Just checking RHS assignments
|
||||
bool m_varModeReplace; // Replacing varrefs
|
||||
bool m_varAssignHit; // Assign var hit
|
||||
bool m_forkHit; // Fork hit
|
||||
bool m_generate; // Expand single generate For loop
|
||||
string m_beginName; // What name to give begin iterations
|
||||
VDouble0 m_statLoops; // Statistic tracking
|
||||
|
@ -133,6 +134,7 @@ class UnrollVisitor final : public VNVisitor {
|
|||
// Now, make sure there's no assignment to this variable in the loop
|
||||
m_varModeCheck = true;
|
||||
m_varAssignHit = false;
|
||||
m_forkHit = false;
|
||||
m_ignoreIncp = incp;
|
||||
iterateAndNextNull(precondsp);
|
||||
iterateAndNextNull(bodysp);
|
||||
|
@ -141,6 +143,8 @@ class UnrollVisitor final : public VNVisitor {
|
|||
m_ignoreIncp = nullptr;
|
||||
if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop");
|
||||
|
||||
if (m_forkHit) return cantUnroll(nodep, "fork inside loop");
|
||||
|
||||
//
|
||||
if (m_forVscp) {
|
||||
UINFO(8, " Loop Variable: " << m_forVscp);
|
||||
|
@ -463,6 +467,17 @@ class UnrollVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
void visit(AstFork* nodep) override {
|
||||
if (m_varModeCheck) {
|
||||
if (nodep->joinType().joinNone() || nodep->joinType().joinAny()) {
|
||||
// Forks are not allowed to unroll for loops, so we just set a flag
|
||||
m_forkHit = true;
|
||||
}
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
void visit(AstNode* nodep) override {
|
||||
|
@ -489,6 +504,7 @@ public:
|
|||
m_varModeCheck = false;
|
||||
m_varModeReplace = false;
|
||||
m_varAssignHit = false;
|
||||
m_forkHit = false;
|
||||
m_generate = generate;
|
||||
m_beginName = beginName;
|
||||
}
|
||||
|
|
128
src/V3Width.cpp
128
src/V3Width.cpp
|
@ -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());
|
||||
}
|
||||
|
@ -2422,6 +2422,18 @@ class WidthVisitor final : public VNVisitor {
|
|||
nodep->dtypeSetLogicSized(1, bdtypep->numeric());
|
||||
VL_DANGLING(bdtypep);
|
||||
}
|
||||
if (nodep->isNet()) {
|
||||
AstNodeDType* const badDtp = dtypeNot4StateIntegralRecurse(nodep->dtypep());
|
||||
if (badDtp)
|
||||
nodep->v3error(
|
||||
"Net " << nodep->prettyNameQ()
|
||||
<< " data type must be 4-state integral or array/union/struct of such"
|
||||
<< " (IEEE 1800-2023 6.7.1)\n"
|
||||
<< nodep->warnContextPrimary() << '\n'
|
||||
<< badDtp->warnOther() << "... Location of failing data type "
|
||||
<< badDtp->prettyDTypeNameQ() << '\n'
|
||||
<< badDtp->warnContextSecondary());
|
||||
}
|
||||
if (nodep->valuep() && !didchk) {
|
||||
// if (debug()) nodep->dumpTree("- final: ");
|
||||
// AstPattern requires assignments to pass datatype on PRELIM
|
||||
|
@ -2461,11 +2473,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 +2495,15 @@ 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();
|
||||
AstNodeDType* const badDtp = dtypeNotIntAtomOrVecRecurse(nodep->subDTypep());
|
||||
if (badDtp) {
|
||||
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)\n"
|
||||
<< nodep->warnContextPrimary() << '\n'
|
||||
<< badDtp->warnOther() << "... Location of failing data type "
|
||||
<< badDtp->prettyDTypeNameQ() << '\n'
|
||||
<< badDtp->warnContextSecondary());
|
||||
basicp = nodep->findSigned32DType()->basicp();
|
||||
nodep->refDTypep(basicp);
|
||||
}
|
||||
|
@ -2553,9 +2570,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 +6843,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 +6884,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 +6912,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 +6972,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 +7007,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 +7347,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 +7362,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 +7379,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 +7696,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 +8326,39 @@ class WidthVisitor final : public VNVisitor {
|
|||
if (nodep->subDTypep()) return hasOpenArrayIterateDType(nodep->subDTypep()->skipRefp());
|
||||
return false;
|
||||
}
|
||||
AstNodeDType* dtypeNotIntAtomOrVecRecurse(AstNodeDType* nodep, bool ranged = false) {
|
||||
// If node is _not_ integer or atomic, return node that makes it fail
|
||||
nodep = nodep->skipRefToEnump();
|
||||
if (AstBasicDType* const dtp = VN_CAST(nodep, BasicDType)) {
|
||||
if (ranged && (!dtp->isBitLogic() || dtp->isRanged()))
|
||||
return dtp; // Packed when already packed
|
||||
if (dtp->keyword().isIntNumeric()) return nullptr;
|
||||
return dtp;
|
||||
} else if (AstPackArrayDType* const dtp = VN_CAST(nodep, PackArrayDType)) {
|
||||
if (ranged) return dtp; // Packed when already packed
|
||||
return dtypeNotIntAtomOrVecRecurse(nodep->subDTypep(), true);
|
||||
}
|
||||
return nodep;
|
||||
}
|
||||
AstNodeDType* dtypeNot4StateIntegralRecurse(AstNodeDType* nodep) {
|
||||
// If node is _not_ inet valid data type, 4-state integral packed or union, return node
|
||||
// that makes it fail
|
||||
nodep = nodep->skipRefp();
|
||||
if (AstBasicDType* const dtp = VN_CAST(nodep, BasicDType)) {
|
||||
if (!dtp->keyword().isFourstate()) return dtp;
|
||||
return nullptr;
|
||||
} else if (AstNodeArrayDType* const dtp = VN_CAST(nodep, NodeArrayDType)) {
|
||||
return dtypeNot4StateIntegralRecurse(dtp->subDTypep());
|
||||
} else if (AstNodeUOrStructDType* const dtp = VN_CAST(nodep, NodeUOrStructDType)) {
|
||||
for (AstMemberDType* itemp = dtp->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
AstNodeDType* const badDtp = dtypeNot4StateIntegralRecurse(itemp->dtypep());
|
||||
if (badDtp) return badDtp;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return nodep;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// METHODS - special type detection
|
||||
|
|
|
@ -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
|
||||
|
|
24
src/astgen
24
src/astgen
|
@ -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")
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
102
src/verilog.y
102
src/verilog.y
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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();
|
||||
return T::Helper::getter();
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Class2;
|
||||
typedef Class2 Helper;
|
||||
static function int getter();
|
||||
return 13;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
if (Class1#(Class2)::get() != 13) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
|
@ -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()
|
|
@ -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
|
|
@ -0,0 +1,312 @@
|
|||
// // verilator_coverage annotation
|
||||
// DESCRIPTION: Verilator: SystemVerilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2008 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
module t_cover_else_points ;
|
||||
%000002 logic is_su_mode;
|
||||
-000002 point: comment=is_su_mode
|
||||
%000002 logic is_em_emul;
|
||||
-000002 point: comment=is_em_emul
|
||||
%000001 logic is_ata_emul;
|
||||
-000001 point: comment=is_ata_emul
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
%000000 logic [3:0] user_word_cnt;
|
||||
-000002 point: comment=user_word_cnt[0]
|
||||
-000002 point: comment=user_word_cnt[1]
|
||||
-000001 point: comment=user_word_cnt[2]
|
||||
-000000 point: comment=user_word_cnt[3]
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
%000002 logic page;
|
||||
-000002 point: comment=page
|
||||
%000001 logic [6:0] cfg;
|
||||
-000002 point: comment=cfg[0]
|
||||
-000002 point: comment=cfg[1]
|
||||
-000002 point: comment=cfg[2]
|
||||
-000000 point: comment=cfg[3]
|
||||
-000003 point: comment=cfg[4]
|
||||
-000002 point: comment=cfg[5]
|
||||
-000001 point: comment=cfg[6]
|
||||
%000001 initial begin
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h05;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h06;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h10;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h60;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h60;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h40;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 is_su_mode =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_em_emul =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 is_ata_emul =1'b1;
|
||||
-000001 point: comment=block
|
||||
%000001 page =1'b0;
|
||||
-000001 point: comment=block
|
||||
%000001 cfg =7'h50;
|
||||
-000001 point: comment=block
|
||||
%000001 #100;
|
||||
-000001 point: comment=block
|
||||
%000001 $write("*-* All Finished *-*\n");
|
||||
-000001 point: comment=block
|
||||
%000001 $finish;
|
||||
-000001 point: comment=block
|
||||
end
|
||||
a a_inst(
|
||||
.i_is_su_mode ( is_su_mode ),
|
||||
.i_page ( page ),
|
||||
.i_cfg ( cfg ),
|
||||
.i_is_em_emul ( is_em_emul ),
|
||||
.i_is_ata_emul ( is_ata_emul ),
|
||||
.o_user_word_count( user_word_cnt)
|
||||
);
|
||||
endmodule
|
||||
/* verilator lint_off DECLFILENAME */
|
||||
module a (
|
||||
/* verilator lint_on DECLFILENAME */
|
||||
%000002 input logic i_is_su_mode ,
|
||||
-000002 point: comment=i_is_su_mode
|
||||
%000002 input logic i_page ,
|
||||
-000002 point: comment=i_page
|
||||
%000001 input logic [6:0] i_cfg ,
|
||||
-000002 point: comment=i_cfg[0]
|
||||
-000002 point: comment=i_cfg[1]
|
||||
-000002 point: comment=i_cfg[2]
|
||||
-000000 point: comment=i_cfg[3]
|
||||
-000003 point: comment=i_cfg[4]
|
||||
-000002 point: comment=i_cfg[5]
|
||||
-000001 point: comment=i_cfg[6]
|
||||
%000002 input logic i_is_em_emul ,
|
||||
-000002 point: comment=i_is_em_emul
|
||||
%000001 input logic i_is_ata_emul,
|
||||
-000001 point: comment=i_is_ata_emul
|
||||
%000000 output logic [3:0] o_user_word_count
|
||||
-000002 point: comment=o_user_word_count[0]
|
||||
-000002 point: comment=o_user_word_count[1]
|
||||
-000001 point: comment=o_user_word_count[2]
|
||||
-000000 point: comment=o_user_word_count[3]
|
||||
);
|
||||
%000001 always_comb begin
|
||||
-000001 point: comment=block
|
||||
%000001 o_user_word_count='0;
|
||||
-000001 point: comment=block
|
||||
%000001 if (i_is_su_mode == 1'b1) begin
|
||||
-000001 point: comment=elsif
|
||||
%000001 o_user_word_count = 4'b0000;
|
||||
-000001 point: comment=elsif
|
||||
end
|
||||
%000002 else if (i_is_em_emul == 1'b1 ) begin
|
||||
-000002 point: comment=elsif
|
||||
%000002 case(i_cfg[3:0])
|
||||
-000002 point: comment=elsif
|
||||
%000000 4'b0101: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0000;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000002 4'b0110: begin
|
||||
-000002 point: comment=case
|
||||
%000002 o_user_word_count = 4'b0001;
|
||||
-000002 point: comment=case
|
||||
end
|
||||
%000000 4'b0111: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0010;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 4'b1000: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0011;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 4'b1001: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0100;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 4'b1010: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0101;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 4'b1011: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0110;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 4'b1100: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0111;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 4'b1101: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b1000;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 default: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0011;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
endcase
|
||||
end
|
||||
%000000 else if (i_is_ata_emul == 1'b1) begin
|
||||
+000012 point: comment=if
|
||||
-000000 point: comment=else
|
||||
000012 case(i_cfg[6:4])
|
||||
+000012 point: comment=if
|
||||
%000000 3'b000: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0000;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000002 3'b001: begin
|
||||
-000002 point: comment=case
|
||||
%000002 o_user_word_count = 4'b0000;
|
||||
-000002 point: comment=case
|
||||
end
|
||||
%000000 3'b010: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0001;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000000 3'b011: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0010;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
%000002 3'b100: begin
|
||||
-000002 point: comment=case
|
||||
%000000 if (i_page == 1'b1) begin
|
||||
-000002 point: comment=if
|
||||
-000000 point: comment=else
|
||||
%000002 o_user_word_count = 4'b0010;
|
||||
-000002 point: comment=if
|
||||
%000000 end else begin
|
||||
-000000 point: comment=else
|
||||
%000000 o_user_word_count = 4'b0011;
|
||||
-000000 point: comment=else
|
||||
end
|
||||
end
|
||||
%000004 3'b101: begin
|
||||
-000004 point: comment=case
|
||||
%000004 if (i_page == 1'b1) begin
|
||||
-000000 point: comment=if
|
||||
-000004 point: comment=else
|
||||
%000000 o_user_word_count = 4'b0010;
|
||||
-000000 point: comment=if
|
||||
%000004 end else begin
|
||||
-000004 point: comment=else
|
||||
%000004 o_user_word_count = 4'b0100;
|
||||
-000004 point: comment=else
|
||||
end
|
||||
end
|
||||
%000004 3'b110: begin
|
||||
-000004 point: comment=case
|
||||
%000000 if (i_page == 1'b1) begin
|
||||
-000004 point: comment=if
|
||||
-000000 point: comment=else
|
||||
%000004 o_user_word_count = 4'b0010;
|
||||
-000004 point: comment=if
|
||||
%000000 end else begin
|
||||
-000000 point: comment=else
|
||||
%000000 o_user_word_count = 4'b0101;
|
||||
-000000 point: comment=else
|
||||
end
|
||||
end
|
||||
%000000 3'b111: begin
|
||||
-000000 point: comment=case
|
||||
%000000 if (i_page == 1'b1) begin
|
||||
-000000 point: comment=if
|
||||
-000000 point: comment=else
|
||||
%000000 o_user_word_count = 4'b0010;
|
||||
-000000 point: comment=if
|
||||
%000000 end else begin
|
||||
-000000 point: comment=else
|
||||
%000000 o_user_word_count = 4'b0110;
|
||||
-000000 point: comment=else
|
||||
end
|
||||
end
|
||||
%000000 default: begin
|
||||
-000000 point: comment=case
|
||||
%000000 o_user_word_count = 4'b0010;
|
||||
-000000 point: comment=case
|
||||
end
|
||||
endcase
|
||||
end
|
||||
%000000 else begin // default
|
||||
-000000 point: comment=else
|
||||
%000000 o_user_word_count = 4'b0000;
|
||||
-000000 point: comment=else
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(vlt => 1);
|
||||
|
||||
compile(
|
||||
verilator_flags2 => [ "--binary --coverage --timing -Wall" ],
|
||||
);
|
||||
|
||||
execute(
|
||||
all_run_flags => [" +verilator+coverage+file+$Self->{obj_dir}/coverage.dat"],
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
# Read the input .v file and do any CHECK_COVER requests
|
||||
inline_checks();
|
||||
|
||||
run(cmd => ["../bin/verilator_coverage",
|
||||
"--annotate-points",
|
||||
"--annotate", "$Self->{obj_dir}/annotated",
|
||||
"$Self->{obj_dir}/coverage.dat",
|
||||
],
|
||||
verilator_run => 1,
|
||||
) if !$Self->errors && !$Self->skips;
|
||||
|
||||
files_identical("$Self->{obj_dir}/annotated/t_cover_else_points.v", $Self->{golden_filename});
|
||||
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,170 @@
|
|||
// DESCRIPTION: Verilator: SystemVerilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2008 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
module t_cover_else_points ;
|
||||
logic is_su_mode;
|
||||
logic is_em_emul;
|
||||
logic is_ata_emul;
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
logic [3:0] user_word_cnt;
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
logic page;
|
||||
logic [6:0] cfg;
|
||||
initial begin
|
||||
is_su_mode =1'b1;
|
||||
is_em_emul =1'b0;
|
||||
is_ata_emul =1'b0;
|
||||
page =1'b0;
|
||||
cfg =7'h05;
|
||||
#100;
|
||||
is_su_mode =1'b0;
|
||||
is_em_emul =1'b1;
|
||||
is_ata_emul =1'b0;
|
||||
page =1'b0;
|
||||
cfg =7'h06;
|
||||
#100;
|
||||
is_su_mode =1'b0;
|
||||
is_em_emul =1'b0;
|
||||
is_ata_emul =1'b1;
|
||||
page =1'b0;
|
||||
cfg =7'h10;
|
||||
#100;
|
||||
is_su_mode =1'b0;
|
||||
is_em_emul =1'b0;
|
||||
is_ata_emul =1'b1;
|
||||
page =1'b1;
|
||||
cfg =7'h60;
|
||||
#100;
|
||||
is_su_mode =1'b0;
|
||||
is_em_emul =1'b0;
|
||||
is_ata_emul =1'b1;
|
||||
page =1'b1;
|
||||
cfg =7'h60;
|
||||
#100;
|
||||
is_su_mode =1'b0;
|
||||
is_em_emul =1'b0;
|
||||
is_ata_emul =1'b1;
|
||||
page =1'b1;
|
||||
cfg =7'h40;
|
||||
#100;
|
||||
is_su_mode =1'b0;
|
||||
is_em_emul =1'b0;
|
||||
is_ata_emul =1'b1;
|
||||
page =1'b0;
|
||||
cfg =7'h50;
|
||||
#100;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
a a_inst(
|
||||
.i_is_su_mode ( is_su_mode ),
|
||||
.i_page ( page ),
|
||||
.i_cfg ( cfg ),
|
||||
.i_is_em_emul ( is_em_emul ),
|
||||
.i_is_ata_emul ( is_ata_emul ),
|
||||
.o_user_word_count( user_word_cnt)
|
||||
);
|
||||
endmodule
|
||||
/* verilator lint_off DECLFILENAME */
|
||||
module a (
|
||||
/* verilator lint_on DECLFILENAME */
|
||||
input logic i_is_su_mode ,
|
||||
input logic i_page ,
|
||||
input logic [6:0] i_cfg ,
|
||||
input logic i_is_em_emul ,
|
||||
input logic i_is_ata_emul,
|
||||
output logic [3:0] o_user_word_count
|
||||
);
|
||||
always_comb begin
|
||||
o_user_word_count='0;
|
||||
if (i_is_su_mode == 1'b1) begin
|
||||
o_user_word_count = 4'b0000;
|
||||
end
|
||||
else if (i_is_em_emul == 1'b1 ) begin
|
||||
case(i_cfg[3:0])
|
||||
4'b0101: begin
|
||||
o_user_word_count = 4'b0000;
|
||||
end
|
||||
4'b0110: begin
|
||||
o_user_word_count = 4'b0001;
|
||||
end
|
||||
4'b0111: begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end
|
||||
4'b1000: begin
|
||||
o_user_word_count = 4'b0011;
|
||||
end
|
||||
4'b1001: begin
|
||||
o_user_word_count = 4'b0100;
|
||||
end
|
||||
4'b1010: begin
|
||||
o_user_word_count = 4'b0101;
|
||||
end
|
||||
4'b1011: begin
|
||||
o_user_word_count = 4'b0110;
|
||||
end
|
||||
4'b1100: begin
|
||||
o_user_word_count = 4'b0111;
|
||||
end
|
||||
4'b1101: begin
|
||||
o_user_word_count = 4'b1000;
|
||||
end
|
||||
default: begin
|
||||
o_user_word_count = 4'b0011;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
else if (i_is_ata_emul == 1'b1) begin
|
||||
case(i_cfg[6:4])
|
||||
3'b000: begin
|
||||
o_user_word_count = 4'b0000;
|
||||
end
|
||||
3'b001: begin
|
||||
o_user_word_count = 4'b0000;
|
||||
end
|
||||
3'b010: begin
|
||||
o_user_word_count = 4'b0001;
|
||||
end
|
||||
3'b011: begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end
|
||||
3'b100: begin
|
||||
if (i_page == 1'b1) begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end else begin
|
||||
o_user_word_count = 4'b0011;
|
||||
end
|
||||
end
|
||||
3'b101: begin
|
||||
if (i_page == 1'b1) begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end else begin
|
||||
o_user_word_count = 4'b0100;
|
||||
end
|
||||
end
|
||||
3'b110: begin
|
||||
if (i_page == 1'b1) begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end else begin
|
||||
o_user_word_count = 4'b0101;
|
||||
end
|
||||
end
|
||||
3'b111: begin
|
||||
if (i_page == 1'b1) begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end else begin
|
||||
o_user_word_count = 4'b0110;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
o_user_word_count = 4'b0010;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
else begin // default
|
||||
o_user_word_count = 4'b0000;
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue