Merge branch 'master' into develop-v5

This commit is contained in:
Wilson Snyder 2022-09-27 22:19:04 -04:00
commit c6bce636ee
24 changed files with 371 additions and 106 deletions

View File

@ -10,11 +10,11 @@ on:
jobs:
format:
runs-on: ubuntu-20.04
name: Ubuntu 20.04 | format
runs-on: ubuntu-22.04
name: Ubuntu 22.04 | format
env:
CI_OS_NAME: linux
CI_RUNS_ON: ubuntu-20.04
CI_RUNS_ON: ubuntu-22.04
CI_COMMIT: ${{ github.sha }}
CI_M32: 0
steps:
@ -27,14 +27,14 @@ jobs:
CI_BUILD_STAGE_NAME: build
run: |
bash ci/ci-install.bash &&
sudo apt-get install clang-format-11 yapf3 &&
sudo apt-get install clang-format-14 yapf3 &&
git config --global user.email "action@example.com" &&
git config --global user.name "github action"
- name: Format code
run: |
autoconf &&
./configure &&
make -j 2 format CLANGFORMAT=clang-format-11 &&
make -j 2 format CLANGFORMAT=clang-format-14 &&
git status
- name: Push
run: |

View File

@ -346,13 +346,13 @@ analyzer-include:
format: clang-format yapf format-pl-exec
CLANGFORMAT = clang-format-11
CLANGFORMAT = clang-format-14
CLANGFORMAT_FLAGS = -i
CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* test_regress/t/*.h
clang-format:
@$(CLANGFORMAT) --version | egrep 11.0 > /dev/null \
|| echo "*** You are not using clang-format 11.0, indents may differ from master's ***"
@$(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)
PY_PROGRAMS = \

View File

@ -44,6 +44,7 @@ HyungKi Jeong
Iru Cai
Ivan Vnučec
Iztok Jeras
Jake Merdich
James Hanlon
James Hutchinson
James Pallister

View File

@ -13,6 +13,7 @@ from datetime import datetime
import os
import re
import sys
sys.path.insert(0, os.path.abspath('./_ext'))
import sphinx_rtd_theme # pylint: disable=wrong-import-position,

View File

@ -124,7 +124,7 @@ Those developing Verilator itself may also want these (see internals.rst):
::
sudo apt-get install gdb graphviz cmake clang clang-format-11 gprof lcov
sudo apt-get install gdb graphviz cmake clang clang-format-14 gprof lcov
sudo apt-get install yapf3
sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe
cpan install Pod::Perldoc

View File

@ -16,12 +16,13 @@ from shutil import copy2
class VlFileCopy:
def __init__(
self,
verilator_args, # presently all verilator options are passed-thru
# ideally this script would check against options mentioned in help
self,
verilator_args, # presently all verilator options are passed-thru
# ideally this script would check against options mentioned in help
debug=0,
output_dir='copied'): # directory name we output file uses
output_dir='copied'): # directory name we output file uses
self.debug = debug

View File

@ -14,12 +14,13 @@ import xml.etree.ElementTree as ET
class VlHierGraph:
def __init__(
self,
verilator_args, # presently all verilator options are passed-thru
# ideally this script would check against options mentioned in help
self,
verilator_args, # presently all verilator options are passed-thru
# ideally this script would check against options mentioned in help
debug=0,
output_filename='graph.dot'): # output filename
output_filename='graph.dot'): # output filename
self.debug = debug
self.next_vertex_number = 0
self.name_to_number = {}

View File

@ -96,7 +96,7 @@ public:
*(reinterpret_cast<uint32_t*>(newp)) = activeMagic();
return newp + 8;
}
static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE {
static void operator delete(void* obj, size_t /*size*/) VL_MT_SAFE {
uint8_t* const oldp = (static_cast<uint8_t*>(obj)) - 8;
if (VL_UNLIKELY(*(reinterpret_cast<uint32_t*>(oldp)) != activeMagic())) {
VL_FATAL_MT(__FILE__, __LINE__, "",

View File

@ -58,10 +58,14 @@
//
// Another thing done in this phase is signal strength handling.
// Currently they are only supported in assignments and gates parsed as assignments (see verilog.y)
// and only in case when the strongest assignment has RHS marked as non-tristate. It is the case
// when they can be statically resolved.
// If the RHS is equal to z, that assignment has to be skipped. Since the value may be not known at
// verilation time, cases with tristates on RHS can't be handled statically.
// when any of the cases occurs:
// - it is possible to statically resolve all drivers,
// - all assignments that passed the static resolution have symmetric strengths (the same strength
// is related to both 0 and 1 values).
//
// It is possible to statically resolve all drivers when the strongest assignment has RHS marked as
// non-tristate. If the RHS is equal to z, that assignment has to be skipped. Since the value may
// be not known at verilation time, cases with tristates on RHS can't be handled statically.
//
// Static resolution is split into 2 parts.
// First part can be done before tristate propagation. It is about removing assignments that are
@ -85,7 +89,26 @@
// - The assignment with non-tristate RHS with the greatest weaker strength has to be found.
// - Then all not stronger assignments can be removed.
//
// All assignments that are stronger than the strongest with non-tristate RHS are left as they are.
// All assignments that are stronger than the strongest with non-tristate RHS are then tried to be
// handled dynamically. Currently it is supported only on assignments with symmetric strengths.
// In this case, the exact value of the RHS doesn't matter. It only matters if it equals z or not.
// Such assignments are handled by changing the values to z of these bits that are overwritten by
// stronger assignments. Then all assignments can be aggregated as they would have equal strengths
// (by | on them and their __en expressions). To change the value to z, the RHS should be & with
// negation of __en expression of stronger assignments. Changing RHS's __en expression is not
// needed, because it will be then aggregated with __en expression of stronger assignments using |,
// so & with the negation can be safely skipped.
// So the values of overwritten bits are actually changed to 0, which doesn't affect stronger
// assignments, because | operation was used.
//
// Dynamic handling is implemented in the following way:
// - group the assignments by their strengths,
// - handle assignments of the same strength by aggregating values with |
// - assign results to var__strength and var__strength__en variables
// - aggregate the results:
// orp = orp | (var__strength & ~enp)
// enp = enp | var__strength__en,
// where orp is aggregated value and enp is aggregated __en value.
//
// There is a possible problem with equally strong assignments, because multiple assignments with
// the same strength, but different values should result in x value, but these values are
@ -384,8 +407,15 @@ class TristateVisitor final : public TristateBaseVisitor {
const VNUser5InUse m_inuser5;
// TYPES
using RefVec = std::vector<AstVarRef*>;
using VarMap = std::unordered_map<AstVar*, RefVec*>;
struct RefStrength {
AstVarRef* m_varrefp;
VStrength m_strength;
RefStrength(AstVarRef* varrefp, VStrength strength)
: m_varrefp{varrefp}
, m_strength{strength} {}
};
using RefStrengthVec = std::vector<RefStrength>;
using VarMap = std::unordered_map<AstVar*, RefStrengthVec*>;
using Assigns = std::vector<AstAssignW*>;
using VarToAssignsMap = std::map<AstVar*, Assigns>;
enum : uint8_t {
@ -403,6 +433,8 @@ class TristateVisitor final : public TristateBaseVisitor {
VarToAssignsMap m_assigns; // Assigns in current module
int m_unique = 0;
bool m_alhs = false; // On LHS of assignment
VStrength m_currentStrength = VStrength::STRONG; // Current strength of assignment,
// Used only on LHS of assignment
const AstNode* m_logicp = nullptr; // Current logic being built
TristateGraph m_tgraph; // Logic graph
@ -485,11 +517,11 @@ class TristateVisitor final : public TristateBaseVisitor {
const auto it = m_lhsmap.find(key);
UINFO(9, " mapInsertLhsVarRef " << nodep << endl);
if (it == m_lhsmap.end()) { // Not found
RefVec* const refsp = new RefVec;
refsp->push_back(nodep);
RefStrengthVec* const refsp = new RefStrengthVec;
refsp->push_back(RefStrength{nodep, m_currentStrength});
m_lhsmap.emplace(key, refsp);
} else {
it->second->push_back(nodep);
it->second->push_back(RefStrength{nodep, m_currentStrength});
}
}
@ -567,7 +599,7 @@ class TristateVisitor final : public TristateBaseVisitor {
nextit = it;
++nextit;
AstVar* const invarp = it->first;
const RefVec* const refsp = it->second;
RefStrengthVec* refsp = it->second;
// Figure out if this var needs tristate expanded.
if (m_tgraph.isTristate(invarp)) {
insertTristatesSignal(nodep, invarp, refsp);
@ -580,8 +612,64 @@ class TristateVisitor final : public TristateBaseVisitor {
}
}
void insertTristatesSignal(AstNodeModule* nodep, AstVar* const invarp,
const RefVec* const refsp) {
void aggregateTriSameStrength(AstNodeModule* nodep, AstVar* const varp, AstVar* const envarp,
RefStrengthVec::iterator beginStrength,
RefStrengthVec::iterator endStrength) {
// For each driver seperate variables (normal and __en) are created and initialized with
// values. In case of normal variable, the original expression is reused. Their values are
// aggregated using | to form one expression, which are assigned to varp end envarp.
AstNode* orp = nullptr;
AstNode* enp = nullptr;
for (auto it = beginStrength; it != endStrength; it++) {
AstVarRef* refp = it->m_varrefp;
const int w = varp->width();
// create the new lhs driver for this var
AstVar* const newLhsp = new AstVar{varp->fileline(), VVarType::MODULETEMP,
varp->name() + "__out" + cvtToStr(m_unique),
VFlagBitPacked{}, w}; // 2-state ok; sep enable
UINFO(9, " newout " << newLhsp << endl);
nodep->addStmtsp(newLhsp);
refp->varp(newLhsp); // assign the new var to the varref
refp->name(newLhsp->name());
// create a new var for this drivers enable signal
AstVar* const newEnLhsp = new AstVar{varp->fileline(), VVarType::MODULETEMP,
varp->name() + "__en" + cvtToStr(m_unique++),
VFlagBitPacked{}, w}; // 2-state ok
UINFO(9, " newenlhsp " << newEnLhsp << endl);
nodep->addStmtsp(newEnLhsp);
AstNode* const enLhspAssignp = new AstAssignW{
refp->fileline(), new AstVarRef{refp->fileline(), newEnLhsp, VAccess::WRITE},
getEnp(refp)};
UINFO(9, " newenlhspAssignp " << enLhspAssignp << endl);
nodep->addStmtsp(enLhspAssignp);
// now append this driver to the driver logic.
AstNode* const ref1p = new AstVarRef{refp->fileline(), newLhsp, VAccess::READ};
AstNode* const ref2p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ};
AstNode* const andp = new AstAnd{refp->fileline(), ref1p, ref2p};
// or this to the others
orp = (!orp) ? andp : new AstOr{refp->fileline(), orp, andp};
AstNode* const ref3p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ};
enp = (!enp) ? ref3p : new AstOr{ref3p->fileline(), enp, ref3p};
}
AstNode* const assp = new AstAssignW{
varp->fileline(), new AstVarRef{varp->fileline(), varp, VAccess::WRITE}, orp};
UINFO(9, " newassp " << assp << endl);
nodep->addStmtsp(assp);
AstNode* const enAssp = new AstAssignW{
envarp->fileline(), new AstVarRef{envarp->fileline(), envarp, VAccess::WRITE}, enp};
UINFO(9, " newenassp " << enAssp << endl);
nodep->addStmtsp(enAssp);
}
void insertTristatesSignal(AstNodeModule* nodep, AstVar* const invarp, RefStrengthVec* refsp) {
UINFO(8, " TRISTATE EXPANDING:" << invarp << endl);
++m_statTriSigs;
m_tgraph.didProcess(invarp);
@ -615,76 +703,103 @@ class TristateVisitor final : public TristateBaseVisitor {
AstNode* orp = nullptr;
AstNode* enp = nullptr;
AstNode* undrivenp = nullptr;
const int w = lhsp->width();
// loop through the lhs drivers to build the driver resolution logic
for (auto refp : *refsp) {
const int w = lhsp->width();
std::sort(refsp->begin(), refsp->end(),
[](RefStrength a, RefStrength b) { return a.m_strength > b.m_strength; });
// create the new lhs driver for this var
AstVar* const newlhsp = new AstVar(lhsp->fileline(), VVarType::MODULETEMP,
lhsp->name() + "__out" + cvtToStr(m_unique),
VFlagBitPacked(), w); // 2-state ok; sep enable
UINFO(9, " newout " << newlhsp << endl);
nodep->addStmtsp(newlhsp);
refp->varp(newlhsp); // assign the new var to the varref
refp->name(newlhsp->name());
auto beginStrength = refsp->begin();
while (beginStrength != refsp->end()) {
auto endStrength = beginStrength + 1;
while (endStrength != refsp->end()
&& endStrength->m_strength == beginStrength->m_strength)
endStrength++;
// create a new var for this drivers enable signal
AstVar* const newenp = new AstVar(lhsp->fileline(), VVarType::MODULETEMP,
lhsp->name() + "__en" + cvtToStr(m_unique++),
VFlagBitPacked(), w); // 2-state ok
UINFO(9, " newenp " << newenp << endl);
nodep->addStmtsp(newenp);
FileLine* const fl = beginStrength->m_varrefp->fileline();
const string strengthVarName = lhsp->name() + "__" + beginStrength->m_strength.ascii();
AstNode* const enassp = new AstAssignW(
refp->fileline(), new AstVarRef(refp->fileline(), newenp, VAccess::WRITE),
getEnp(refp));
UINFO(9, " newass " << enassp << endl);
nodep->addStmtsp(enassp);
// var__strength variable
AstVar* varStrengthp = new AstVar{fl, VVarType::MODULETEMP, strengthVarName,
VFlagBitPacked{}, w}; // 2-state ok; sep enable;
UINFO(9, " newstrength " << varStrengthp << endl);
nodep->addStmtsp(varStrengthp);
// now append this driver to the driver logic.
AstNode* const ref1p = new AstVarRef(refp->fileline(), newlhsp, VAccess::READ);
AstNode* const ref2p = new AstVarRef(refp->fileline(), newenp, VAccess::READ);
AstNode* const andp = new AstAnd(refp->fileline(), ref1p, ref2p);
// var__strength__en variable
AstVar* enVarStrengthp = new AstVar{fl, VVarType::MODULETEMP, strengthVarName + "__en",
VFlagBitPacked{}, w}; // 2-state ok;
UINFO(9, " newenstrength " << enVarStrengthp << endl);
nodep->addStmtsp(enVarStrengthp);
// or this to the others
orp = (!orp) ? andp : new AstOr(refp->fileline(), orp, andp);
aggregateTriSameStrength(nodep, varStrengthp, enVarStrengthp, beginStrength,
endStrength);
if (envarp) {
AstNode* const ref3p = new AstVarRef(refp->fileline(), newenp, VAccess::READ);
enp = (!enp) ? ref3p : new AstOr(ref3p->fileline(), enp, ref3p);
AstNode* exprCurrentStrengthp;
if (enp) {
// If weaker driver should be overwritten by a stronger, replace its value with z
exprCurrentStrengthp
= new AstAnd{fl, new AstVarRef{fl, varStrengthp, VAccess::READ},
new AstNot{fl, enp->cloneTree(false)}};
} else {
exprCurrentStrengthp = new AstVarRef{fl, varStrengthp, VAccess::READ};
}
AstNode* const tmp = new AstNot(
newenp->fileline(), new AstVarRef(newenp->fileline(), newenp, VAccess::READ));
undrivenp = ((!undrivenp) ? tmp : new AstAnd(refp->fileline(), tmp, undrivenp));
}
if (!undrivenp) { // No drivers on the bus
undrivenp = newAllZerosOrOnes(invarp, true);
orp = (!orp) ? exprCurrentStrengthp : new AstOr{fl, orp, exprCurrentStrengthp};
AstNode* enVarStrengthRefp = new AstVarRef{fl, enVarStrengthp, VAccess::READ};
enp = (!enp) ? enVarStrengthRefp : new AstOr{fl, enp, enVarStrengthRefp};
beginStrength = endStrength;
}
if (!outvarp) {
// This is the final pre-forced resolution of the tristate, so we apply
// the pull direction to any undriven pins.
const AstPull* const pullp = static_cast<AstPull*>(lhsp->user3p());
bool pull1 = pullp && pullp->direction() == 1; // Else default is down
AstNode* undrivenp;
if (envarp) {
undrivenp = new AstNot{envarp->fileline(),
new AstVarRef{envarp->fileline(), envarp, VAccess::READ}};
} else {
if (enp) {
undrivenp = new AstNot{enp->fileline(), enp};
} else {
undrivenp = newAllZerosOrOnes(invarp, true);
}
}
undrivenp
= new AstAnd{invarp->fileline(), undrivenp, newAllZerosOrOnes(invarp, pull1)};
orp = new AstOr(invarp->fileline(), orp, undrivenp);
} else {
VL_DO_DANGLING(undrivenp->deleteTree(), undrivenp);
orp = new AstOr{invarp->fileline(), orp, undrivenp};
}
if (envarp) {
nodep->addStmtsp(new AstAssignW(
enp->fileline(), new AstVarRef(envarp->fileline(), envarp, VAccess::WRITE), enp));
AstAssignW* const enAssp = new AstAssignW{
enp->fileline(), new AstVarRef{envarp->fileline(), envarp, VAccess::WRITE}, enp};
if (debug() >= 9) enAssp->dumpTree(cout, "enAssp: ");
nodep->addStmtsp(enAssp);
}
// __out (child) or <in> (parent) = drive-value expression
AstNode* const assp = new AstAssignW(
lhsp->fileline(), new AstVarRef(lhsp->fileline(), lhsp, VAccess::WRITE), orp);
AstNode* const assp = new AstAssignW{
lhsp->fileline(), new AstVarRef{lhsp->fileline(), lhsp, VAccess::WRITE}, orp};
assp->user2(U2_BOTH); // Don't process further; already resolved
if (debug() >= 9) assp->dumpTree(cout, "-lhsp-eqn: ");
nodep->addStmtsp(assp);
}
bool isOnlyAssignmentIsToLhsVar(AstAssignW* const nodep) {
if (AstVarRef* const varRefp = VN_CAST(nodep->lhsp(), VarRef)) {
auto foundIt = m_assigns.find(varRefp->varp());
if (foundIt != m_assigns.end()) {
auto const& assignsToVar = foundIt->second;
if (assignsToVar.size() == 1 && assignsToVar[0] == nodep) return true;
}
}
return false;
}
void addToAssignmentList(AstAssignW* nodep) {
if (AstVarRef* const varRefp = VN_CAST(nodep->lhsp(), VarRef)) {
if (varRefp->varp()->isNet()) {
@ -1109,7 +1224,26 @@ class TristateVisitor final : public TristateBaseVisitor {
m_tgraph.didProcess(nodep);
}
m_alhs = true; // And user1p() will indicate tristate equation, if any
if (AstAssignW* const assignWp = VN_CAST(nodep, AssignW)) {
if (AstStrengthSpec* const specp = assignWp->strengthSpecp()) {
if (specp->strength0() != specp->strength1()) {
// Unequal strengths are not a problem if the assignment is the only
// assignment to its variable. Unfortunately, m_assigns map stores only
// assignments to var. Selects are not inserted, so they may be handled
// improperly
if (!isOnlyAssignmentIsToLhsVar(assignWp)) {
assignWp->v3warn(
E_UNSUPPORTED,
"Unsupported: Unable to resolve unequal strength specifier");
}
} else {
m_currentStrength = specp->strength0();
}
}
}
iterateAndNextNull(nodep->lhsp());
// back to default strength
m_currentStrength = VStrength::STRONG;
m_alhs = false;
}
}

View File

@ -12,6 +12,7 @@ import textwrap
class Node:
def __init__(self, name, superClass, file, lineno):
self._name = name
self._superClass = superClass
@ -181,6 +182,7 @@ Stages = {}
class Cpt:
def __init__(self):
self.did_out_tree = False
self.in_filename = ""

View File

@ -24,8 +24,8 @@
// clang-format on
#include "V3Number.h"
#include "V3ParseImp.h" // Defines YYTYPE; before including bison header
#include "V3ParseBison.h" // Generated by bison
#include "V3ParseImp.h" // Defines YYTYPE; before including bison header
#define STATE_VERILOG_RECENT S17 // State name for most recent Verilog Version

View File

@ -23,12 +23,12 @@
#endif
// clang-format on
#include "V3Ast.h"
#include "V3Global.h"
#include "V3Config.h"
#include "V3Global.h"
#include "V3ParseImp.h" // Defines YYTYPE; before including bison header
#include <cstdlib>
#include <cstdarg>
#include <cstdlib>
#include <stack>
#define YYERROR_VERBOSE 1 // For prior to Bison 3.6

View File

@ -13,36 +13,37 @@ scenarios(vlt => 1);
if (!$Self->cfg_with_ccache) {
skip("Requires configuring with ccache");
}
else {
top_filename("t_a1_first_cc.v");
top_filename("t_a1_first_cc.v");
# This test requires rebuilding the object files to check the ccache log
foreach my $filename (glob("$Self->{obj_dir}/*.o")) {
print "rm $filename\n" if $Self->{verbose};
unlink $filename;
}
# This test requires rebuilding the object files to check the ccache log
foreach my $filename (glob("$Self->{obj_dir}/*.o")) {
print "rm $filename\n" if $Self->{verbose};
unlink $filename;
compile(
verilator_flags2 => ['--trace'],
make_flags => "ccache-report"
);
my $report = "$Self->{obj_dir}/$Self->{VM_PREFIX}__ccache_report.txt";
# We do not actually want to make this test depend on whether the file was
# cached or not, so trim the report to ignore actual caching behaviour
run(cmd => ["sed", "-i", "-e", "'s/ : .*/ : IGNORED/; /|/s/.*/IGNORED/;'", $report]);
files_identical($report, "t/$Self->{name}__ccache_report_initial.out");
# Now rebuild again (should be all up to date)
run(
logfile => "$Self->{obj_dir}/rebuild.log",
cmd => ["make", "-C", $Self->{obj_dir},
"-f", "$Self->{VM_PREFIX}.mk",
$Self->{VM_PREFIX}, "ccache-report"]
);
files_identical($report, "t/$Self->{name}__ccache_report_rebuild.out");
}
compile(
verilator_flags2 => ['--trace'],
make_flags => "ccache-report"
);
my $report = "$Self->{obj_dir}/$Self->{VM_PREFIX}__ccache_report.txt";
# We do not actually want to make this test depend on whether the file was
# cached or not, so trim the report to ignore actual caching behaviour
run(cmd => ["sed", "-i", "-e", "'s/ : .*/ : IGNORED/; /|/s/.*/IGNORED/;'", $report]);
files_identical($report, "t/$Self->{name}__ccache_report_initial.out");
# Now rebuild again (should be all up to date)
run(
logfile => "$Self->{obj_dir}/rebuild.log",
cmd => ["make", "-C", $Self->{obj_dir},
"-f", "$Self->{VM_PREFIX}.mk",
$Self->{VM_PREFIX}, "ccache-report"]
);
files_identical($report, "t/$Self->{name}__ccache_report_rebuild.out");
ok(1);
1;

View File

@ -1,3 +1,9 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t
(/*AUTOARG*/
// Inputs

View File

@ -0,0 +1,10 @@
%Error-UNSUPPORTED: t/t_strength_2_uneq_assign.v:10:30: Unsupported: Unable to resolve unequal strength specifier
: ... In instance t
10 | assign (weak0, strong1) a = clk ? 'z : '0;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_strength_2_uneq_assign.v:11:30: Unsupported: Unable to resolve unequal strength specifier
: ... In instance t
11 | assign (strong0, pull1) a = 6'b110001;
| ^
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Antmicro Ltd. 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(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (clk);
input clk;
wire [5:0] a;
assign (weak0, strong1) a = clk ? 'z : '0;
assign (strong0, pull1) a = 6'b110001;
initial begin
if (a === 6'b110001) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Antmicro Ltd. 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(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,48 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
interface inter (input logic cond, output wire a);
parameter W;
// Example:
wire (weak0, weak1) [W-1:0] b = '1;
assign (strong0, strong1) b = cond ? 'b0 : 'bz;
assign a = b[10];
endinterface
module t (clk1, clk2);
input wire clk1;
input wire clk2;
wire (weak0, weak1) a = 0;
assign (supply0, supply1) a = 1'bz;
assign (pull0, pull1) a = 1;
wire [2:0] b;
assign b = 3'b101;
assign (supply0, supply1) b = 3'b01z;
wire c;
and (weak0, weak1) (c, clk1, clk2);
assign (strong0, strong1) c = 'z;
assign (pull0, pull1) c = 0;
wire d;
inter #(.W(32)) i(.cond(1'b1), .a(d));
always begin
if (a === 1 && b === 3'b011 && c === 0 && d === 0) begin
$write("*-* All Finished *-*\n");
$finish;
end
else begin
$write("Error: a = %b, b = %b, c = %b, d = %b", a, b, c, d);
$write("expected: a = %b, b = %b, c = %b, d = %b\n", clk1, 3'b011, 0, 0);
$stop;
end
end
endmodule

View File

@ -21,6 +21,7 @@
// General headers
#include "verilated.h"
#include "systemc.h"
VM_PREFIX* ap;