Merge branch 'steveicarus:master' into fix-issue-1344

This commit is contained in:
Ralf Habacker 2026-07-15 14:03:33 +02:00 committed by GitHub
commit 612936aa1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
240 changed files with 6277 additions and 1132 deletions

43
.gitignore vendored
View File

@ -35,16 +35,19 @@ Makefile
/_pli_types.h
config.h
/tgt-pcb/pcb_config.h
/tgt-pcb/fp.cc
/tgt-pcb/fp.h
/tgt-pcb/fp.output
/tgt-pcb/fp_lex.cc
/tgt-vvp/vvp_config.h
/tgt-vhdl/vhdl_config.h
/vhdlpp/vhdlpp_config.h
/vpi/vpi_config.h
stamp-*-h
/version.h
/version_tag.h
/version_base.h
/driver-vpi/iverilog-vpi.man
/driver-vpi/res.rc
/driver/iverilog.man
/vvp/libvvp.pc
/vvp/vvp.man
# Directories
autom4te.cache
@ -56,8 +59,6 @@ dep
*.vpi
/cadpli/cadpli.vpl
/tgt-blif/Makefile
# lex, yacc and gperf output
/driver/cflexor.c
/driver/cfparse.c
@ -66,14 +67,6 @@ dep
/ivlpp/lexor.c
/vhdlpp/lexor.cc
/vhdlpp/lexor_keyword.cc
/vhdlpp/parse.cc
/vhdlpp/parse.h
/vhdlpp/parse.output
/vhdlpp/vhdlpp_config.h
/vhdlpp/vhdlpp
/lexor.cc
/lexor_keyword.cc
/parse.cc
@ -82,6 +75,17 @@ dep
/syn-rules.cc
/syn-rules.output
/tgt-pcb/fp.cc
/tgt-pcb/fp.h
/tgt-pcb/fp.output
/tgt-pcb/fp_lex.cc
/vhdlpp/lexor.cc
/vhdlpp/lexor_keyword.cc
/vhdlpp/parse.cc
/vhdlpp/parse.h
/vhdlpp/parse.output
/vpi/sdf_lexor.c
/vpi/sdf_parse.c
/vpi/sdf_parse.h
@ -101,17 +105,13 @@ dep
# Program created files
/vvp/tables.cc
/iverilog-vpi.man
/driver-vpi/res.rc
/driver/iverilog.man
/vvp/vvp.man
# The executables.
*.exe
/driver/iverilog
/iverilog-vpi
/driver-vpi/iverilog-vpi
/ivl
/ivlpp/ivlpp
/vhdlpp/vhdlpp
/vvp/vvp
/ivl.exp
@ -119,3 +119,4 @@ dep
# Check output
/check.vvp
/driver/top.vvp

View File

@ -812,6 +812,10 @@ result is pushed back on the vec4 stack.
This opcode multiplies two real words together.
* %neg/wr
This opcode negates the real value on top of the real stack.
* %nand
Perform the bitwise NAND of two vec4 vectors, and push the result. Each

View File

@ -85,6 +85,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
YACC_CONFLICT_FLAGS = -Werror=conflicts-sr -Werror=conflicts-rr
MAN = @MAN@
PS2PDF = @PS2PDF@
GROFF = @GROFF@
@ -241,10 +242,10 @@ parse.o: parse.cc
# Use pattern rules to avoid parallel build issues (see pr3462585)
parse%cc parse%h: $(srcdir)/parse%y
$(YACC) --verbose -t -p VL --defines=parse.h -o parse.cc $<
$(YACC) --verbose $(YACC_CONFLICT_FLAGS) -t -p VL --defines=parse.h -o parse.cc $<
syn-rules.cc: $(srcdir)/syn-rules.y
$(YACC) --verbose -t -p syn_ -o $@ $<
$(YACC) --verbose $(YACC_CONFLICT_FLAGS) -t -p syn_ -o $@ $<
lexor.cc: $(srcdir)/lexor.lex
$(LEX) -s -t $< > $@

View File

@ -108,6 +108,16 @@ PEAssignPattern::~PEAssignPattern()
{
}
bool PEAssignPattern::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (const auto *parm : parms_) {
if (parm)
flag = parm->has_aa_term(des, scope) || flag;
}
return flag;
}
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r)
{
@ -261,26 +271,47 @@ PECallFunction::PECallFunction(perm_string n, const list<named_pexpr_t> &parms)
{
}
PECallFunction::PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const vector<named_pexpr_t> &parms)
: path_(method), parms_(parms), chain_prefix_(chain_prefix), is_overridden_(false)
{
}
PECallFunction::PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const list<named_pexpr_t> &parms)
: path_(method), parms_(parms.begin(), parms.end()),
chain_prefix_(chain_prefix), is_overridden_(false)
{
}
PECallFunction::~PECallFunction()
{
delete chain_prefix_;
}
void PECallFunction::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
if (chain_prefix_) {
chain_prefix_->declare_implicit_nets(scope, type);
}
for (const auto &parm : parms_) {
if (parm.parm)
if (parm.parm) {
parm.parm->declare_implicit_nets(scope, type);
}
}
}
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
if (chain_prefix_ && chain_prefix_->has_aa_term(des, scope)) {
return true;
}
for (const auto &parm : parms_) {
if (parm.parm)
flag |= parm.parm->has_aa_term(des, scope);
if (parm.parm && parm.parm->has_aa_term(des, scope)) {
return true;
}
}
return flag;
return false;
}
PEConcat::PEConcat(const list<PExpr*>&p, PExpr*r)

69
PExpr.h
View File

@ -37,6 +37,7 @@ class NetExpr;
class NetScope;
class PPackage;
struct symbol_search_results;
class netclass_t;
/*
* The PExpr class hierarchy supports the description of
@ -208,6 +209,8 @@ class PEAssignPattern : public PExpr {
void dump(std::ostream&) const override;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const override;
@ -488,18 +491,12 @@ class PEIdent : public PExpr {
const NetScope*found_in,
ivl_type_t par_type,
unsigned expr_wid) const;
NetExpr*elaborate_expr_param_idx_up_(Design*des,
NetScope*scope,
const NetExpr*par,
const NetScope*found_in,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_do_(Design*des,
NetScope*scope,
const NetExpr*par,
const NetScope*found_in,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_up_do_(Design*des,
NetScope*scope,
const NetExpr*par,
const NetScope*found_in,
ivl_type_t par_type,
bool up, bool need_const) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
@ -517,16 +514,11 @@ class PEIdent : public PExpr {
NetESignal*net,
NetScope*found,
unsigned expr_wid) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_idx_up_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool up, bool need_const) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetESignal*net,
@ -928,8 +920,18 @@ class PECallFunction : public PExpr {
explicit PECallFunction(const pform_name_t &n, const std::list<named_pexpr_t> &parms);
explicit PECallFunction(perm_string n, const std::list<named_pexpr_t> &parms);
// SystemVerilog: prefix().method(args) — prefix elaborates to a class handle.
explicit PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const std::vector<named_pexpr_t> &parms);
explicit PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const std::list<named_pexpr_t> &parms);
~PECallFunction() override;
// For chained-call resolution (path is only the final method name).
const pform_scoped_name_t& peek_path(void) const { return path_; }
const PExpr* peek_chain_prefix(void) const { return chain_prefix_; }
virtual void dump(std::ostream &) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
@ -948,6 +950,8 @@ class PECallFunction : public PExpr {
private:
pform_scoped_name_t path_;
std::vector<named_pexpr_t> parms_;
// If non-null, this call is prefix().tail_name(...) (SV method chain).
PExpr* chain_prefix_ = nullptr;
// For system functions.
bool is_overridden_;
@ -985,7 +989,26 @@ class PECallFunction : public PExpr {
unsigned elaborate_arguments_(Design*des, NetScope*scope,
const NetFuncDef*def, bool need_const,
std::vector<NetExpr*>&parms,
unsigned parm_off) const;
unsigned parm_off,
const std::vector<named_pexpr_t>*src_parms = nullptr) const;
NetExpr* elaborate_class_method_net_(Design*des, NetScope*scope,
NetNet*net, const netclass_t*class_type,
perm_string method_name,
const std::vector<named_pexpr_t>*src_parms) const;
NetExpr* elaborate_class_method_net_this_(Design*des, NetScope*scope,
NetExpr* this_expr,
const netclass_t*class_type,
perm_string method_name,
const std::vector<named_pexpr_t>*src_parms) const;
NetExpr* elaborate_expr_method_chained_(Design*des, NetScope*scope,
symbol_search_results&search_results) const;
NetExpr* elaborate_expr_chain_(Design*des, NetScope*scope, unsigned flags) const;
unsigned test_width_chain_(Design*des, NetScope*scope, width_mode_t&mode);
};
/*

View File

@ -26,10 +26,12 @@
# include <list>
# include <map>
# include <valarray>
# include <vector>
# include "pform_types.h"
class Design;
class NetScope;
class PClass;
class PExpr;
class PFunction;
class PProcess;
@ -92,9 +94,11 @@ class PGenerate : public PNamedItem, public LexicalScope {
std::list<PGate*> gates;
void add_gate(PGate*);
// Tasks instantiated within this scheme.
// Definitions instantiated within this scheme.
std::map<perm_string,PTask*> tasks;
std::map<perm_string,PFunction*>funcs;
std::map<perm_string,PClass*> classes;
std::vector<PClass*> classes_lexical;
// Generate schemes can contain further generate schemes.
std::list<PGenerate*> generate_schemes;

View File

@ -40,6 +40,8 @@ class NetCAssign;
class NetDeassign;
class NetForce;
class NetScope;
class NetNet;
class netdarray_t;
/*
* The PProcess is the root of a behavioral process. Each process gets
@ -261,16 +263,42 @@ class PCallTask : public Statement {
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names = {}) const;
NetProc*elaborate_sys_task_property_method_(Design*des, NetScope*scope,
NetNet*net, int property_idx,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names = {}) const;
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const;
NetProc*elaborate_queue_property_method_(Design*des, NetScope*scope,
NetNet*net, int property_idx,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const;
NetProc*elaborate_method_func_(NetScope*scope,
NetNet*net,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const;
NetProc*elaborate_method_property_func_(NetScope*scope,
NetNet*net, int property_idx,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const;
NetProc*elaborate_queue_method_expr_(Design*des, NetScope*scope,
NetExpr*queue_base,
const netdarray_t*use_darray,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const;
NetProc*elaborate_method_func_expr_(NetScope*scope,
NetExpr*queue_base,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, const NetScope*scope) const;
PPackage*package_;

17
config.guess vendored
View File

@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2025 Free Software Foundation, Inc.
# Copyright 1992-2026 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
timestamp='2025-07-10'
timestamp='2026-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -60,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2025 Free Software Foundation, Inc.
Copyright 1992-2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -150,7 +150,7 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
Ironclad|Linux|GNU|GNU/*)
LIBC=unknown
set_cc_for_build
@ -167,6 +167,8 @@ Linux|GNU|GNU/*)
LIBC=gnu
#elif defined(__LLVM_LIBC__)
LIBC=llvm
#elif defined(__mlibc__)
LIBC=mlibc
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
@ -1186,6 +1188,9 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
sw_64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
tile*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
@ -1598,10 +1603,10 @@ EOF
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*)
GUESS=$UNAME_MACHINE-pc-ironclad-mlibc
GUESS=$UNAME_MACHINE-pc-ironclad-$LIBC
;;
*:[Ii]ronclad:*:*)
GUESS=$UNAME_MACHINE-unknown-ironclad-mlibc
GUESS=$UNAME_MACHINE-unknown-ironclad-$LIBC
;;
esac

11
config.sub vendored
View File

@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2025 Free Software Foundation, Inc.
# Copyright 1992-2026 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
timestamp='2025-07-10'
timestamp='2026-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2025 Free Software Foundation, Inc.
Copyright 1992-2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -1432,6 +1432,7 @@ case $cpu-$vendor in
| sparcv9v \
| spu \
| sv1 \
| sw_64 \
| sx* \
| tahoe \
| thumbv7* \
@ -1525,7 +1526,7 @@ EOF
;;
ironclad*)
kernel=ironclad
os=`echo "$basic_os" | sed -e 's|ironclad|mlibc|'`
os=`echo "$basic_os" | sed -e 's|ironclad|gnu|'`
;;
linux*)
kernel=linux
@ -2220,7 +2221,7 @@ case $kernel-$os-$obj in
;;
uclinux-uclibc*- | uclinux-gnu*- )
;;
ironclad-mlibc*-)
ironclad-gnu*- | ironclad-mlibc*- )
;;
managarm-mlibc*- | managarm-kernel*- )
;;

View File

@ -1138,7 +1138,7 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
if (rval())
o << *rval() << ";" << endl;
else
o << "rval elaboration error>;" << endl;
o << "<rval elaboration error>;" << endl;
}

File diff suppressed because it is too large Load Diff

View File

@ -298,6 +298,15 @@ NetAssign_*PEIdent::elaborate_lval_var_(Design *des, NetScope *scope,
// Past this point, we should have taken care of the cases
// where the name is a member/method of a struct/class.
// XXXX ivl_assert(*this, method_name.nil());
if (!tail_path.empty()) {
cerr << get_fileline() << ": error: Variable "
<< reg->name()
<< " does not have a field named: "
<< tail_path << "." << endl;
des->errors += 1;
return nullptr;
}
ivl_assert(*this, tail_path.empty());
bool need_const_idx = is_cassign || is_force;
@ -883,8 +892,10 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
calculate_up_do_width_(des, scope, wid);
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
if (!base)
return false;
if (base && base->expr_type() == IVL_VT_REAL) {
if (base->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: Indexed part select base "
"expression for ";
cerr << lv->sig()->name() << "[" << *base;

View File

@ -1322,6 +1322,10 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
collect_scope_signals(scope, wires);
elaborate_scope_enumerations(des, scope, enum_sets);
elaborate_scope_classes(des, scope, classes_lexical);
// Run through the defparams for this scope and save the result
// in a table for later final override.
@ -1662,6 +1666,8 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
collect_scope_signals(scope, wires);
elaborate_scope_enumerations(des, scope, enum_sets);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@ -1682,6 +1688,8 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
collect_scope_signals(scope, wires);
elaborate_scope_enumerations(des, scope, enum_sets);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@ -1732,6 +1740,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
collect_scope_signals(my_scope, wires);
elaborate_scope_enumerations(des, my_scope, enum_sets);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);
}

View File

@ -404,11 +404,6 @@ void netclass_t::elaborate_sig(Design*des, PClass*pclass)
<< " type=" << *use_type << endl;
}
if (dynamic_cast<const netqueue_t *> (use_type)) {
cerr << cur->second.get_fileline() << ": sorry: "
<< "Queues inside classes are not yet supported." << endl;
des->errors++;
}
set_property(cur->first, cur->second.qual, use_type);
if (! cur->second.qual.test_static())
@ -607,6 +602,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
elaborate_sig_classes(des, scope, classes);
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()

View File

@ -47,6 +47,7 @@
# include "netenum.h"
# include "netvector.h"
# include "netdarray.h"
# include "netqueue.h"
# include "netparray.h"
# include "netscalar.h"
# include "netclass.h"
@ -3250,15 +3251,6 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
NetEvWait*event = 0;
if (count_ != 0 || event_ != 0) {
if (count_ != 0) {
if (scope->is_auto() && count_->has_aa_term(des, scope)) {
cerr << get_fileline() << ": error: automatically "
"allocated variables may not be referenced "
"in intra-assignment event controls of "
"non-blocking assignments." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, event_ != 0);
count = elab_and_eval(des, scope, count_, -1);
if (count == 0) {
@ -4073,19 +4065,66 @@ NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
return sys;
}
/*
* This private method is called to elaborate queue push methods. The
* sys_task_name is the internal system-task name to use.
*/
NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const
NetProc* PCallTask::elaborate_sys_task_property_method_(Design*des, NetScope*scope,
NetNet*net, int property_idx,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const
{
NetESignal*sig = new NetESignal(net);
sig->set_line(*this);
NetEProperty*prop = new NetEProperty(net, property_idx, 0);
prop->set_line(*this);
unsigned nparms = parms_.size();
vector<NetExpr*>argv (1 + nparms);
argv[0] = prop;
if (method_name == "delete") {
const netclass_t*cls = dynamic_cast<const netclass_t*>(net->net_type());
ivl_assert(*this, cls);
ivl_type_t pt = cls->get_prop_type(property_idx);
bool is_queue = pt && pt->base_type() == IVL_VT_QUEUE;
if (is_queue) {
if (nparms > 1) {
cerr << get_fileline() << ": error: queue delete() "
<< "method takes zero or one argument." << endl;
des->errors += 1;
}
} else if (nparms > 0) {
cerr << get_fileline() << ": error: darray delete() "
<< "method takes no arguments." << endl;
des->errors += 1;
}
} else if (parm_names.size() != parms_.size()) {
cerr << get_fileline() << ": error: " << method_name
<< "() method takes " << parm_names.size() << " arguments, got "
<< parms_.size() << "." << endl;
des->errors++;
}
auto args = map_named_args(des, parm_names, parms_);
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
argv[idx + 1] = elab_sys_task_arg(des, scope, method_name,
idx, args[idx]);
}
NetSTask*sys = new NetSTask(sys_task_name, IVL_SFUNC_AS_TASK_IGNORE, argv);
sys->set_line(*this);
return sys;
}
/*
* Common implementation for queue push/insert methods. The queue_base
* expression is either a NetESignal or NetEProperty; use_darray
* supplies the element type.
*/
NetProc* PCallTask::elaborate_queue_method_expr_(Design*des, NetScope*scope,
NetExpr*queue_base,
const netdarray_t*use_darray,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const
{
unsigned nparms = parms_.size();
// insert() requires two arguments.
if ((method_name == "insert") && (nparms != 2)) {
@ -4099,21 +4138,10 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
<< "() method requires a single argument." << endl;
des->errors += 1;
}
// Get the context width if this is a logic type.
ivl_variable_type_t base_type = net->darray_type()->element_base_type();
int context_width = -1;
switch (base_type) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
context_width = net->darray_type()->element_width();
break;
default:
break;
}
vector<NetExpr*>argv (nparms+1);
argv[0] = sig;
ivl_type_t element_type = use_darray->element_type();
unsigned expected_nparms = method_name == "insert" ? 2 : 1;
vector<NetExpr*>argv (expected_nparms+1);
argv[0] = queue_base;
auto args = map_named_args(des, parm_names, parms_);
if (method_name != "insert") {
@ -4123,8 +4151,8 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
<< "() methods first argument is missing." << endl;
des->errors += 1;
} else {
argv[1] = elab_and_eval(des, scope, args[0], context_width,
false, false, base_type);
argv[1] = elaborate_rval_expr(des, scope, element_type,
args[0]);
}
} else {
if (nparms == 0 || !args[0]) {
@ -4133,8 +4161,9 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
<< "() methods first argument is missing." << endl;
des->errors += 1;
} else {
argv[1] = elab_and_eval(des, scope, args[0], context_width,
false, false, IVL_VT_LOGIC);
argv[1] = elaborate_rval_expr(des, scope,
netvector_t::integer_type(),
args[0]);
}
if (nparms < 2 || !args[1]) {
@ -4143,8 +4172,8 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
<< "() methods second argument is missing." << endl;
des->errors += 1;
} else {
argv[2] = elab_and_eval(des, scope, args[1], context_width,
false, false, base_type);
argv[2] = elaborate_rval_expr(des, scope, element_type,
args[1]);
}
}
@ -4153,14 +4182,55 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
return sys;
}
/*
* This private method is called to elaborate queue push methods. The
* sys_task_name is the internal system-task name to use.
*/
NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const
{
NetESignal*sig = new NetESignal(net);
sig->set_line(*this);
const netdarray_t*use_darray = net->darray_type();
ivl_assert(*this, use_darray);
return elaborate_queue_method_expr_(des, scope, sig, use_darray,
method_name, sys_task_name,
parm_names);
}
NetProc* PCallTask::elaborate_queue_property_method_(Design*des, NetScope*scope,
NetNet*net, int property_idx,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const
{
const netclass_t*cls = dynamic_cast<const netclass_t*>(net->net_type());
ivl_assert(*this, cls);
ivl_type_t ptype = cls->get_prop_type(property_idx);
const netdarray_t*use_darray = dynamic_cast<const netdarray_t*>(ptype);
ivl_assert(*this, use_darray);
NetEProperty*prop = new NetEProperty(net, property_idx, 0);
prop->set_line(*this);
return elaborate_queue_method_expr_(des, scope, prop, use_darray,
method_name, sys_task_name,
parm_names);
}
/*
* This is used for array/queue function methods called as tasks.
*/
NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
NetNet*net,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const
NetProc* PCallTask::elaborate_method_func_expr_(NetScope*scope,
NetExpr*queue_base,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const
{
if (!void_cast_) {
cerr << get_fileline() << ": warning: method function '"
@ -4170,9 +4240,7 @@ NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
// Generate the function.
NetESFunc*sys_expr = new NetESFunc(sys_task_name, type, 1);
sys_expr->set_line(*this);
NetESignal*arg = new NetESignal(net);
arg->set_line(*net);
sys_expr->parm(0, arg);
sys_expr->parm(0, queue_base);
// Create a L-value that matches the function return type.
NetNet*tmp;
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, type);
@ -4184,6 +4252,30 @@ NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
return cur;
}
NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
NetNet*net,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const
{
NetESignal*arg = new NetESignal(net);
arg->set_line(*this);
return elaborate_method_func_expr_(scope, arg, type,
method_name, sys_task_name);
}
NetProc* PCallTask::elaborate_method_property_func_(NetScope*scope,
NetNet*net, int property_idx,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const
{
NetEProperty*prop = new NetEProperty(net, property_idx, 0);
prop->set_line(*this);
return elaborate_method_func_expr_(scope, prop, type,
method_name, sys_task_name);
}
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag) const
{
@ -4232,13 +4324,93 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
<< net->name() << ".data_type() --> " << net->data_type() << endl;
}
// Class handle with one path_tail component: queue/darray property method
// e.g. c.q.push_back(x) => sr.path_tail = {q}, method_name = push_back
if (sr.path_tail.size() == 1) {
const netclass_t*cls = dynamic_cast<const netclass_t*>(sr.type);
if (!cls && net->net_type()) {
cls = dynamic_cast<const netclass_t*>(net->net_type());
}
if (cls) {
perm_string prop_name = sr.path_tail.front().name;
int pidx = cls->property_idx_from_name(prop_name);
if (pidx >= 0) {
ivl_type_t ptype = cls->get_prop_type(pidx);
if (ptype && dynamic_cast<const netqueue_t*>(ptype)) {
const netdarray_t*use_darray = dynamic_cast<const netdarray_t*>(ptype);
ivl_assert(*this, use_darray);
if (method_name == "push_back") {
static const std::vector<perm_string> parm_names = {
perm_string::literal("item")
};
return elaborate_queue_property_method_(des, scope, net, pidx,
method_name,
"$ivl_queue_method$push_back",
parm_names);
}
if (method_name == "push_front") {
static const std::vector<perm_string> parm_names = {
perm_string::literal("item")
};
return elaborate_queue_property_method_(des, scope, net, pidx,
method_name,
"$ivl_queue_method$push_front",
parm_names);
}
if (method_name == "insert") {
static const std::vector<perm_string> parm_names = {
perm_string::literal("index"),
perm_string::literal("item")
};
return elaborate_queue_property_method_(des, scope, net, pidx,
method_name,
"$ivl_queue_method$insert",
parm_names);
}
if (method_name == "pop_front") {
return elaborate_method_property_func_(scope, net, pidx,
use_darray->element_type(),
method_name,
"$ivl_queue_method$pop_front");
}
if (method_name == "pop_back") {
return elaborate_method_property_func_(scope, net, pidx,
use_darray->element_type(),
method_name,
"$ivl_queue_method$pop_back");
}
if (method_name == "size") {
return elaborate_method_property_func_(scope, net, pidx,
&netvector_t::atom2s32,
method_name, "$size");
}
} else if (ptype && ptype->base_type() == IVL_VT_DARRAY) {
if (method_name == "delete") {
static const std::vector<perm_string> parm_names = {
perm_string::literal("index")
};
return elaborate_sys_task_property_method_(des, scope, net, pidx,
method_name,
"$ivl_darray_method$delete",
parm_names);
}
if (method_name == "size") {
return elaborate_method_property_func_(scope, net, pidx,
&netvector_t::atom2s32,
method_name, "$size");
}
}
}
}
}
// Is this a method of a "string" type?
if (dynamic_cast<const netstring_t*>(net->net_type())) {
if (method_name == "itoa") {
static const std::vector<perm_string> parm_names = {
perm_string::literal("i")
};
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_string_method$itoa",
parm_names);
@ -4246,7 +4418,6 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
static const std::vector<perm_string> parm_names = {
perm_string::literal("i")
};
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_string_method$hextoa",
parm_names);
@ -4254,7 +4425,6 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
static const std::vector<perm_string> parm_names = {
perm_string::literal("i")
};
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_string_method$octtoa",
parm_names);
@ -4262,7 +4432,6 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
static const std::vector<perm_string> parm_names = {
perm_string::literal("i")
};
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_string_method$bintoa",
parm_names);
@ -4270,7 +4439,6 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
static const std::vector<perm_string> parm_names = {
perm_string::literal("r")
};
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_string_method$realtoa",
parm_names);
@ -4283,7 +4451,6 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
static const std::vector<perm_string> parm_names = {
perm_string::literal("index")
};
return elaborate_sys_task_method_(des, scope, net, method_name,
"$ivl_darray_method$delete",
parm_names);
@ -4320,7 +4487,6 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
}
if (net->queue_type()) {
const netdarray_t*use_darray = net->darray_type();
if (method_name == "push_back") {
static const std::vector<perm_string> parm_names = {
perm_string::literal("item")
@ -4347,11 +4513,13 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
"$ivl_queue_method$insert",
parm_names);
} else if (method_name == "pop_front") {
const netdarray_t*use_darray = net->darray_type();
return elaborate_method_func_(scope, net,
use_darray->element_type(),
method_name,
"$ivl_queue_method$pop_front");
} else if (method_name == "pop_back") {
const netdarray_t*use_darray = net->darray_type();
return elaborate_method_func_(scope, net,
use_darray->element_type(),
method_name,
@ -7237,6 +7405,7 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
if (result_flag) {
elaborate_functions(des, scope, funcs);
elaborate_tasks(des, scope, tasks);
elaborate_classes(des, scope, classes);
for (const auto gt : gates) gt->elaborate(des, scope);

View File

@ -26,6 +26,7 @@
# include <cmath>
# include "netlist.h"
# include "netclass.h"
# include "ivl_assert.h"
# include "netmisc.h"
@ -2182,6 +2183,25 @@ static bool get_array_info(const NetExpr*arg, long dim,
left = range.get_msb();
right = range.get_lsb();
return false;
}
/* Class property (e.g. queue field): size is dynamic; defer to runtime
* instead of folding to all-X in evaluate_array_funcs_. */
if (const NetEProperty*prop = dynamic_cast<const NetEProperty*>(arg)) {
const NetNet*obj = prop->get_sig();
const netclass_t*cls = dynamic_cast<const netclass_t*>(obj->net_type());
if (cls == 0) return true;
ivl_type_t ptype = cls->get_prop_type(prop->property_idx());
if (ptype == 0) return true;
switch (ptype->base_type()) {
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
case IVL_VT_STRING:
defer = true;
return true;
default:
break;
}
return true;
}
/* The argument must be a signal that has enough dimensions. */
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);

View File

@ -337,6 +337,7 @@ ivl_type_packed_width
ivl_type_prop_name
ivl_type_prop_type
ivl_type_properties
ivl_type_queue_max
ivl_type_signed
ivl_udp_init

View File

@ -2400,6 +2400,10 @@ extern int ivl_type_properties(ivl_type_t net);
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
/* Maximum element count for a queue type (0 = unbounded). Only valid
* when ivl_type_base(net) == IVL_VT_QUEUE. */
extern unsigned ivl_type_queue_max(ivl_type_t net);
#if defined(__MINGW32__) || defined (__CYGWIN__)
# define DLLEXPORT __declspec(dllexport)

View File

@ -2368,6 +2368,8 @@ void reset_lexor(FILE* out, char* paths[])
isp->stringify_flag = 0;
isp->comment = NULL;
yyout = out;
if (isp->file == 0) {
perror(paths[0]);
error_count += 1;
@ -2382,8 +2384,6 @@ void reset_lexor(FILE* out, char* paths[])
}
}
yyout = out;
yyrestart(isp->file);
assert(istack == 0);

View File

@ -1,18 +1,5 @@
./ivltests/br1005.v:2: sorry: Queues inside classes are not yet supported.
./ivltests/br1005.v:15: error: Enable of unknown task ``a.q.push_back''.
./ivltests/br1005.v:16: error: Enable of unknown task ``a.q.push_back''.
./ivltests/br1005.v:17: error: Enable of unknown task ``a.q.push_back''.
./ivltests/br1005.v:18: error: Enable of unknown task ``a.q.push_back''.
./ivltests/br1005.v:19: sorry: Method name nesting is not supported yet.
./ivltests/br1005.v:19: : method path: q.pop_front
./ivltests/br1005.v:19: error: Object test.a has no method "q.pop_front(...)".
./ivltests/br1005.v:22: sorry: Method name nesting is not supported yet.
./ivltests/br1005.v:22: : method path: q.pop_front
./ivltests/br1005.v:22: error: Object test.a has no method "q.pop_front(...)".
./ivltests/br1005.v:25: sorry: Method name nesting is not supported yet.
./ivltests/br1005.v:25: : method path: q.pop_front
./ivltests/br1005.v:25: error: Object test.a has no method "q.pop_front(...)".
./ivltests/br1005.v:28: sorry: Method name nesting is not supported yet.
./ivltests/br1005.v:28: : method path: q.pop_front
./ivltests/br1005.v:28: error: Object test.a has no method "q.pop_front(...)".
9 error(s) during elaboration.
1
2
3
4
PASSED

View File

@ -1,4 +1,3 @@
./ivltests/br_gh1175c.v:3: syntax error
./ivltests/br_gh1175c.v:3: errors in UDP table
./ivltests/br_gh1175c.v:1: error: Invalid table for UDP primitive id_0.

View File

@ -1,4 +1,3 @@
./ivltests/br_gh1175d.v:3: syntax error
./ivltests/br_gh1175d.v:3: errors in UDP table
./ivltests/br_gh1175d.v:1: error: Invalid table for UDP primitive id_0.

View File

@ -1,4 +1,3 @@
./ivltests/br_gh1175e.v:3: syntax error
./ivltests/br_gh1175e.v:3: errors in UDP table
./ivltests/br_gh1175e.v:1: error: Invalid table for UDP primitive id_0.

View File

@ -3,4 +3,4 @@
./ivltests/br_gh72b_fail.v:8: error: too few arguments for `macro2
./ivltests/br_gh72b_fail.v:9: error: too few arguments for `macro2
./ivltests/br_gh72b_fail.v:10: error: too many arguments for `macro2
Preprocessor failed with 5 errors.
Preprocessor failed with 5 error(s).

View File

@ -0,0 +1,2 @@
ivltests/udp_empty_table_fail.v:7: error: Empty UDP table.
ivltests/udp_empty_table_fail.v:3: error: Invalid table for UDP primitive udp_empty_table_fail.

View File

@ -0,0 +1,50 @@
// Check that classes declared inside generate blocks can be used.
module test;
reg failed;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
if (1) begin : g
class C;
int value;
function new(int value);
this.value = value;
endfunction
endclass
C c = new(42);
end
for (genvar i = 0; i < 2; i = i + 1) begin : h
class C;
int value;
function new(int value);
this.value = value + i;
endfunction
endclass
C c = new(10);
end
initial begin
failed = 1'b0;
`check(g.c.value, 42);
`check(h[0].c.value, 10);
`check(h[1].c.value, 11);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,39 @@
// Check that enum literals declared inside generate blocks are available in
// the generated scope.
module test;
reg failed;
`define check(val, exp) do begin \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end \
end while (0)
if (1) begin : g
typedef enum logic [3:0] {
A = 4'd1,
B = 4'd2
} EN_T;
EN_T e = A;
initial begin
failed = 1'b0;
#1;
`check(e, A);
e = B;
`check(e, B);
if (!failed) begin
$display("PASSED");
end
end
end
endmodule

View File

@ -0,0 +1,37 @@
// Check that enum literals declared inside named blocks are available in
// the block scope.
module test;
reg failed;
`define check(val, exp) do begin \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end \
end while (0)
initial begin : b
typedef enum logic [3:0] {
A = 4'd1,
B = 4'd2
} EN_T;
static EN_T e = A;
failed = 1'b0;
#1;
`check(e, A);
e = B;
`check(e, B);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,41 @@
// Check that enum literals declared inside tasks are available in the task
// scope.
module test;
reg failed;
`define check(val, exp) do begin \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end \
end while (0)
task check_task_enum;
typedef enum logic [3:0] {
A = 4'd1,
B = 4'd2
} EN_T;
static EN_T e = A;
`check(e, A);
e = B;
`check(e, B);
endtask
initial begin
failed = 1'b0;
#1;
check_task_enum();
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,39 @@
// Check that enum literals declared inside functions are available in the
// function scope.
module test;
reg failed;
`define check(val, exp) do begin \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end \
end while (0)
function logic [3:0] check_func_enum;
typedef enum logic [3:0] {
A = 4'd1,
B = 4'd2
} EN_T;
static EN_T e = A;
e = B;
check_func_enum = e;
endfunction
initial begin
failed = 1'b0;
#1;
`check(check_func_enum(), 4'd2);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,37 @@
// Regression test for GitHub issue #670.
// Check that a class function can have the same name as the class.
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
class test;
int value;
function void test();
value = 32'd42;
endfunction
endclass
initial begin
test tst;
failed = 1'b0;
tst = new;
tst.test();
`check(tst.value, 32'd42, "Class function name did not hide class name");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,52 @@
// Check that case statement muxes work with array word inputs.
module test;
reg [7:0] mem [0:3];
reg [1:0] sel;
reg [7:0] out;
reg failed;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
always @* begin
case (sel)
2'd0: out = mem[0];
2'd1: out = mem[1];
2'd2: out = mem[2];
2'd3: out = mem[3];
endcase
end
(* ivl_synthesis_off *)
initial begin
failed = 1'b0;
mem[0] = 8'h12;
mem[1] = 8'h34;
mem[2] = 8'h56;
mem[3] = 8'h78;
sel = 2'd0;
#1 `check(out, 8'h12);
sel = 2'd1;
#1 `check(out, 8'h34);
sel = 2'd2;
#1 `check(out, 8'h56);
sel = 2'd3;
#1 `check(out, 8'h78);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,12 @@
// Check that final context is preserved when elaborating nested blocks.
module test;
task t;
endtask
final begin : nested
t;
end
endmodule

View File

@ -0,0 +1,21 @@
// Check that function context is preserved when elaborating nested blocks.
module test;
reg x;
integer y;
function integer f;
input a;
begin : nested
x <= a;
f = 0;
end
endfunction
initial begin
y = f(1'b1);
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,46 @@
// Check that non-blocking event control repeat counts can use automatic terms.
module test;
reg clk;
reg failed;
reg [3:0] result;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
task automatic schedule_update;
input integer count;
begin
result <= repeat(count) @(posedge clk) 4'ha;
end
endtask
always #5 clk = ~clk;
initial begin
clk = 1'b0;
failed = 1'b0;
result = 4'h0;
schedule_update(2);
@(posedge clk);
#1;
`check(result, 4'h0);
@(posedge clk);
#1;
`check(result, 4'ha);
if (!failed) begin
$display("PASSED");
end
$finish;
end
endmodule

View File

@ -0,0 +1,36 @@
// Regression test: comparing a `string` parameter to a string constant of
// a different length must constant-fold cleanly instead of tripping the
// "lv.len() == rv.len()" assertion in the NetEBComp evaluation functions.
// Covers ==, !=, ===, !==, ==? and !=? with the string operand on either
// side and both shorter and longer than the other operand.
module main #(parameter string Target = "A",
parameter string Long = "ABC");
integer errors = 0;
// Equality / inequality, parameter shorter than the literal.
if (Target == "AA") initial begin errors += 1; $display("FAILED: Target == \"AA\""); end
if (Target != "A") initial begin errors += 1; $display("FAILED: Target != \"A\""); end
// Literal on the left.
if ("AA" == Target) initial begin errors += 1; $display("FAILED: \"AA\" == Target"); end
// Parameter longer than the literal.
if (Long == "AB") initial begin errors += 1; $display("FAILED: Long == \"AB\""); end
if (Long != "ABC") initial begin errors += 1; $display("FAILED: Long != \"ABC\""); end
// Two string parameters of different lengths.
if (Target == Long) initial begin errors += 1; $display("FAILED: Target == Long"); end
// Case equality.
if (Target === "AA") initial begin errors += 1; $display("FAILED: Target === \"AA\""); end
if (Target !== "A") initial begin errors += 1; $display("FAILED: Target !== \"A\""); end
// Wildcard equality.
if (Target ==? "AA") initial begin errors += 1; $display("FAILED: Target ==? \"AA\""); end
if (Target !=? "A") initial begin errors += 1; $display("FAILED: Target !=? \"A\""); end
initial #1 if (errors == 0) $display("PASSED");
endmodule

View File

@ -0,0 +1,20 @@
// Check that blocking intra-assignment delays can assign real values.
module test;
real r;
reg failed;
initial begin
failed = 1'b0;
r = #1 1.25;
if (r != 1.25) begin
$display("FAILED(%0d). Expected 1.25, got %0.2f", `__LINE__, r);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,35 @@
// Check that the vvp code generator preserves the sign of a negative zero
// real constant. The sign used to be detected with (value < 0), which is
// false for IEEE 754 -0.0, so a -0.0 constant was emitted as +0.0 and the
// compiled value no longer matched the runtime real value.
module test;
real nz;
real pz;
initial begin
nz = -0.0;
pz = 0.0;
// The sign bit is the only thing that tells -0.0 from +0.0.
if ($realtobits(nz) !== 64'h8000_0000_0000_0000) begin
$display("FAILED: -0.0 stored as %h", $realtobits(nz));
$finish;
end
if ($realtobits(pz) !== 64'h0000_0000_0000_0000) begin
$display("FAILED: 0.0 stored as %h", $realtobits(pz));
$finish;
end
// The reciprocal makes the sign observable: 1.0/-0.0 is -inf.
if (1.0 / nz >= 0.0) begin
$display("FAILED: 1.0/-0.0 = %g", 1.0 / nz);
$finish;
end
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that unary real minus preserves infinities.
module test;
reg failed;
real inf;
real result;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %h, got %h", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
inf = $bitstoreal(64'h7ff0000000000000);
result = -inf;
`check($realtobits(result), 64'hfff0000000000000);
result = -result;
`check($realtobits(result), 64'h7ff0000000000000);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that unary real minus preserves NaN bits.
module test;
reg failed;
real nan;
real result;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %h, got %h", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
nan = $bitstoreal(64'h7ff8000000000001);
result = -nan;
`check($realtobits(result), 64'hfff8000000000001);
result = -result;
`check($realtobits(result), 64'h7ff8000000000001);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that unary real minus preserves the sign of zero.
module test;
reg failed;
real zero;
real result;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %h, got %h", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
zero = 0.0;
result = -zero;
`check($realtobits(result), 64'h8000000000000000);
result = -result;
`check($realtobits(result), 64'h0000000000000000);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,19 @@
// Check that assignment patterns cannot reference automatic variables in
// procedural force statements.
module test;
reg [3:0] result;
task automatic t;
input [3:0] value;
begin
force result = '{value[3], value[2], value[1], value[0]};
end
endtask
initial begin
t(4'ha);
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that bogus member access on procedural l-values reports an error.
module test;
logic r;
initial begin
r.bad = 1'b1;
end
endmodule

View File

@ -0,0 +1,25 @@
// Chained call: function returns class handle, then method on result (a().b()).
module test;
class C;
function int f;
f = 7;
endfunction
endclass
function C get_c;
get_c = new;
endfunction
initial begin
int x;
x = get_c().f();
if (x !== 7) begin
$display("FAILED");
end else begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,37 @@
// Check that a class property can have the same name as the class.
module test;
bit failed = 1'b0;
`define check(val, exp) do \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end \
while(0)
class C;
int C;
function int get;
return C;
endfunction
endclass
C obj;
initial begin
obj = new;
obj.C = 23;
`check(obj.get(), 23);
`check(obj.C, 23);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,40 @@
// Check that multi-dimensional packed vector class properties are supported.
module test;
bit failed = 1'b0;
`define check(val, exp) do begin \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0h, got %0h", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end \
end while (0)
class C;
logic [1:0][3:0] x;
bit [0:1][0:3] y;
endclass
C c;
initial begin
c = new;
c.x = 8'h5a;
c.y = 8'hc3;
`check(c.x, 8'h5a);
`check(c.y, 8'hc3);
c.x += 8'h01;
c.y ^= 8'hff;
`check(c.x, 8'h5b);
`check(c.y, 8'h3c);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,39 @@
// Check that a class property can have the same name as an outer type.
module test;
typedef int T;
bit failed = 1'b0;
`define check(val, exp) do \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end \
while(0)
class C;
int T;
function int get;
return T;
endfunction
endclass
C obj;
initial begin
obj = new;
obj.T = 11;
`check(obj.get(), 11);
`check(obj.T, 11);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,45 @@
// Check that a class property can shadow a wildcard-imported type name.
package P;
typedef int T;
endpackage
module test;
import P::*;
bit failed = 1'b0;
`define check(val, exp) do \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end \
while(0)
class C;
int T;
function int get;
return T;
endfunction
endclass
C obj;
initial begin
obj = new;
obj.T = 47;
`check(obj.get(), 47);
`check(obj.T, 47);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,39 @@
// Regression: queue-typed class properties push_front/push_back and
// pop_front/pop_back. (VVP asm must recognize %store/prop/qf/* and
// %qpop/prop/*; opcode_table must stay lexicographically sorted.)
module test;
bit failed = 1'b0;
`define check(val, exp) do \
if (val !== exp) begin \
$display("FAILED(%0d). expected %0d, got %0d", `__LINE__, exp, val); \
failed = 1'b1; \
end \
while(0)
class C;
int q[$];
endclass
C c;
int t;
initial begin
c = new;
c.q.push_back(1);
c.q.push_front(0);
c.q.push_back(2);
t = c.q.pop_back();
`check(t, 32'd2);
`check(c.q.size(), 32'd2);
t = c.q.pop_front();
`check(t, 32'd0);
`check(c.q[0], 32'd1);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,19 @@
// Check that using a class task as an expression reports an error.
module test;
class C;
task t;
endtask
endclass
C c;
initial begin
int x;
c = new;
x = c.t();
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that invalid indexed part-select l-value bases report an error.
module test;
reg [31:0] a;
initial begin
a[does_not_exist -: 2] = 2'b00;
end
endmodule

View File

@ -0,0 +1,33 @@
// Check variable selects of packed arrays with negative bounds.
module test;
reg failed;
reg [-8:-1][3:0] a;
reg signed [2:0] i;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
a = '0;
i = -1;
a[i] = 4'ha;
i = -2;
a[i] = 4'h5;
`check(a[-1], 4'ha);
`check(a[-2], 4'h5);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,33 @@
// Check that assignment patterns are supported for queue method arguments.
module test;
bit failed;
bit [1:0][3:0] q[$];
`define check(val, exp) do begin \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0h, got %0h", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end \
end while (0)
initial begin
failed = 1'b0;
q.push_back('{4'h1, 4'h2});
q.push_front('{4'h3, 4'h4});
q.insert(1, '{4'h5, 4'h6});
`check(q.size(), 3);
`check(q[0], 8'h34);
`check(q[1], 8'h56);
`check(q[2], 8'h12);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that queue insert() rejects too few arguments.
module test;
int q[$];
initial begin
q.insert(0);
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that queue insert() rejects too many arguments.
module test;
int q[$];
initial begin
q.insert(0, 1, 2);
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that queue push_back() rejects too few arguments.
module test;
int q[$];
initial begin
q.push_back();
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that queue push_back() rejects too many arguments.
module test;
int q[$];
initial begin
q.push_back(1, 2);
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that queue push_front() rejects too few arguments.
module test;
int q[$];
initial begin
q.push_front();
end
endmodule

View File

@ -0,0 +1,9 @@
// Check that queue push_front() rejects too many arguments.
module test;
int q[$];
initial begin
q.push_front(1, 2);
end
endmodule

View File

@ -0,0 +1,10 @@
// Check that string substr() rejects too few arguments.
module test;
string s;
string t;
initial begin
t = s.substr(0);
end
endmodule

View File

@ -0,0 +1,18 @@
// Check that nature name fields can shadow visible type identifiers.
typedef int ACCESS_NAME;
typedef int IDT_NAME;
typedef int DDT_NAME;
nature type_id_nature;
units = "V";
access = ACCESS_NAME;
idt_nature = IDT_NAME;
ddt_nature = DDT_NAME;
endnature
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,12 @@
// Check that attribute names can match visible type identifiers.
typedef int ATTR;
(* ATTR = 1 *)
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,23 @@
// Check that $attribute targets can match visible type identifiers.
primitive ATTR_TYPE (out, in);
output out;
input in;
table
0 : 0;
1 : 1;
endtable
endprimitive
typedef int ATTR_TYPE;
$attribute(ATTR_TYPE, "test", "true")
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,28 @@
// Check that block labels can shadow visible type identifiers.
typedef int T;
module test;
reg failed;
reg value;
initial begin
failed = 1'b0;
value = 0;
begin : T
value = value + 1;
end : T
if (value !== 1) begin
$display("FAILED(%0d). block labels did not hide typedefs", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,13 @@
// Check that a config name can shadow a visible type identifier.
typedef int CFG_NAME;
config CFG_NAME;
design test;
endconfig
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,25 @@
// Check that discipline names can match visible type identifiers.
nature potential_nature;
units = "V";
access = POTENTIAL_ACCESS;
endnature
nature flow_nature;
units = "A";
access = FLOW_ACCESS;
endnature
typedef int DISCIPLINE_NAME;
discipline DISCIPLINE_NAME;
potential potential_nature;
flow flow_nature;
domain continuous;
enddiscipline
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,26 @@
// Check that discipline nature references can match visible type identifiers.
nature potential_nature;
units = "V";
access = POTENTIAL_ACCESS;
endnature
nature flow_nature;
units = "A";
access = FLOW_ACCESS;
endnature
typedef int potential_nature;
typedef int flow_nature;
discipline electrical;
potential potential_nature;
flow flow_nature;
domain continuous;
enddiscipline
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,40 @@
// Check that enum item names can shadow visible type identifiers.
typedef int T;
typedef int U;
typedef int V;
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
enum {
T = 3,
U[2] = 5,
V[3:4] = 9
} e;
initial begin
failed = 1'b0;
e = T;
`check(e, 3, "Enum item name did not hide typedef");
`check(U0, 5, "Enum item sequence name did not hide typedef");
`check(U1, 6, "Enum item sequence value mismatch");
`check(V3, 9, "Enum item range name did not hide typedef");
`check(V4, 10, "Enum item range value mismatch");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that event names can shadow visible type identifiers.
typedef int T;
module test;
reg failed;
reg seen;
event T;
initial begin
failed = 1'b0;
seen = 1'b0;
#1 -> T;
#1;
if (seen !== 1'b1) begin
$display("FAILED(%0d). Event T was not triggered", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
always @T seen = 1'b1;
endmodule

View File

@ -0,0 +1,32 @@
// Check that for loop variables can shadow visible type identifiers.
typedef int T;
module test;
reg failed;
int unsigned values [3];
initial begin
int unsigned total;
failed = 1'b0;
total = 0;
for (int unsigned T = 0; T < 3; T += 1) begin
total += T;
values[T] = 10 + T;
end
if (total != 3 || values[0] != 10 ||
values[1] != 11 || values[2] != 12) begin
$display("FAILED(%0d). for loop variable did not hide typedef", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,25 @@
// Check that foreach array expressions can shadow visible type identifiers.
typedef int A;
module test;
reg failed;
initial begin
failed = 1'b0;
// The array declaration follows the foreach loop, so the lexer only sees
// the visible typedef when parsing the array expression name.
foreach (A[]) begin
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
int unsigned A [3];
endmodule

View File

@ -0,0 +1,29 @@
// Check that foreach loop variables can shadow visible type identifiers.
typedef int I;
typedef int J;
module test;
reg failed;
int array [2][2];
initial begin
failed = 1'b0;
foreach (array[I,J]) begin
array[I][J] = I * 10 + J;
end
if (array[0][0] != 0 || array[0][1] != 1 ||
array[1][0] != 10 || array[1][1] != 11) begin
$display("FAILED(%0d). foreach indices did not hide typedefs", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,28 @@
// Check that fork block labels can shadow visible type identifiers.
typedef int T;
module test;
reg failed;
reg value;
initial begin
failed = 1'b0;
value = 1'b0;
fork : T
value = 1'b1;
join : T
if (value !== 1'b1) begin
$display("FAILED(%0d). fork label did not hide typedef", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,51 @@
// Check that function names can shadow visible type identifiers.
typedef int T;
typedef int U;
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
function int T(input int value);
return value + 32'd1;
endfunction
function U;
U = 1'b1;
endfunction
class C;
function int T(input int value);
return value + 32'd2;
endfunction
function int C(input int value);
return value + 32'd3;
endfunction
endclass
initial begin
C c;
failed = 1'b0;
c = new;
`check(T(32'd41), 32'd42, "Function name did not hide typedef");
`check(U(), 1'b1, "Implicit function name did not hide typedef");
`check(c.T(32'd40), 32'd42, "Class function name did not hide typedef");
`check(c.C(32'd39), 32'd42, "Class function name did not hide class name");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,25 @@
// Check that generate block labels can shadow visible type identifiers.
typedef int G;
module test;
reg failed;
if (1) begin : G
localparam int VALUE = 1;
end : G
initial begin
failed = 1'b0;
if (G.VALUE != 1) begin
$display("FAILED(%0d). generate labels did not hide typedefs", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,27 @@
// Check that a genvar name can shadow a visible type identifier.
typedef int G;
module test;
reg failed;
genvar G;
generate
for (G = 0; G < 2; G = G + 1) begin : gen_block
localparam int VALUE = G;
end
endgenerate
initial begin
failed = 1'b0;
if (gen_block[0].VALUE != 0 || gen_block[1].VALUE != 1) begin
$display("FAILED(%0d). genvar name did not hide typedef", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,19 @@
// Check that a modport name can shadow a visible type identifier.
typedef int M;
interface type_id_modport_ifc;
logic value;
modport M(input value);
endinterface
module test;
type_id_modport_ifc i_ifc();
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,18 @@
// Check that a modport simple port selector can shadow a visible typedef name.
interface I;
typedef int T;
logic value;
modport m(input .T(value));
endinterface
module test;
I i();
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,17 @@
// Check that a module name can shadow a visible type identifier.
package p;
typedef int M;
endpackage
import p::*;
module M;
initial begin
$display("PASSED");
end
endmodule
module test;
M i();
endmodule

View File

@ -0,0 +1,36 @@
// Check that a named constructor argument selector can match a visible typedef name.
module test;
class C;
integer value;
function new(input integer T, input integer B);
value = T + B;
endfunction
endclass
typedef int T;
reg failed;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
C c;
failed = 1'b0;
c = new(.T(40), .B(2));
`check(c.value, 42);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that a named function argument selector can match a visible typedef name.
module test;
function integer f(input integer T, input integer B);
f = T + B;
endfunction
typedef int T;
reg failed;
integer value;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
value = f(.T(40), .B(2));
`check(value, 42);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,33 @@
// Check that a named parameter override selector can match a visible typedef name.
module M #(parameter integer T = 0) (output [31:0] Y);
assign Y = T;
endmodule
module test;
typedef int T;
reg failed;
wire [31:0] y;
M #(.T(32'd42)) i_m(.Y(y));
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
#1;
`check(y, 32'd42);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,35 @@
// Check that a named port connection selector can match a visible typedef name.
module M(input [3:0] T, output [3:0] Y);
assign Y = T;
endmodule
module test;
typedef int T;
reg failed;
reg [3:0] value;
wire [3:0] y;
M i_m(.T(value), .Y(y));
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0h, got %0h", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
value = 4'ha;
#1;
`check(y, 4'ha);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that a named task argument selector can match a visible typedef name.
module test;
task t(input integer T, output integer result);
result = T;
endtask
typedef int T;
reg failed;
integer value;
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \
`"val`", exp, val); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
t(.T(42), .result(value));
`check(value, 42);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,14 @@
// Check that nature names can match visible type identifiers.
typedef int NATURE_NAME;
nature NATURE_NAME;
units = "V";
access = NATURE_ACCESS;
endnature
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,103 @@
// Check that net names can shadow visible type identifiers.
typedef logic [7:0] T;
typedef int U;
typedef logic [5:0] V;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
module net_name(output reg failed);
wire T = 1'b1;
initial begin
failed = 1'b0;
`check(T, 1'b1, "wire T did not declare a one-bit net");
end
endmodule
module net_list(output reg failed);
wire T, U;
assign T = 1'b0;
assign U = 1'b1;
initial begin
failed = 1'b0;
`check(T, 1'b0, "type identifier net list first value mismatch");
`check(U, 1'b1, "type identifier net list continuation mismatch");
end
endmodule
module net_array(output reg failed);
wire T [1:0];
assign T[0] = 1'b0;
assign T[1] = 1'b1;
initial begin
failed = 1'b0;
`check(T[0], 1'b0, "type identifier net array first value mismatch");
`check(T[1], 1'b1, "type identifier net array second value mismatch");
end
endmodule
module net_type(output reg failed);
wire T x = 8'ha5;
wire T [1:0] y = 16'h5aa5;
wire V v0, V;
wire T T;
assign v0 = 6'h2a;
assign V = 6'h15;
assign T = 8'h3c;
initial begin
failed = 1'b0;
`check($bits(x), 8, "typed net declaration width regressed");
`check(x, 8'ha5, "typed net declaration value regressed");
`check($bits(y), 16, "typed packed net declaration width regressed");
`check(y, 16'h5aa5, "typed packed net declaration value regressed");
`check($bits(v0), 6, "type identifier net declaration list first width mismatch");
`check($bits(V), 6, "type identifier net declaration list did not allow typedef name as continuation");
`check(V, 6'h15, "type identifier net declaration list value mismatch");
`check($bits(T), 8, "type-name net declaration did not keep typedef type");
`check(T, 8'h3c, "type-name net declaration value mismatch");
end
endmodule
module test;
reg failed;
wire f0;
wire f1;
wire f2;
wire f3;
net_name m0(f0);
net_list m1(f1);
net_array m2(f2);
net_type m3(f3);
initial begin
failed = 1'b0;
#1;
`check(f0, 1'b0, "wire T module failed");
`check(f1, 1'b0, "wire T, U module failed");
`check(f2, 1'b0, "wire T array module failed");
`check(f3, 1'b0, "typed wire T module failed");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,31 @@
// Check that package import and export items can name a type identifier.
package type_id_name_pkg;
typedef logic [3:0] T;
endpackage
package type_id_name_export_pkg;
import type_id_name_pkg::T;
export type_id_name_pkg::T;
endpackage
module test;
import type_id_name_export_pkg::T;
reg failed;
T value;
initial begin
failed = 1'b0;
value = 4'ha;
if ($bits(value) != 4 || value != 4'ha) begin
$display("FAILED(%0d). Imported type mismatch", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,30 @@
// Check that package names can shadow visible type identifiers.
package p;
typedef int T;
endpackage
import p::*;
package T;
parameter int VALUE = 23;
endpackage
module test;
reg failed;
initial begin
failed = 1'b0;
if (T::VALUE !== 23) begin
$display("FAILED(%0d). Package name did not hide typedef", `__LINE__);
failed = 1'b1;
end
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,35 @@
// Check that parameter declaration names can shadow visible type identifiers.
typedef int L;
typedef int P;
typedef int Q;
typedef int R;
module test;
reg failed;
parameter P = 7, R = 13;
localparam Q = 11, L = 17;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
`check(P, 7, "parameter name did not hide typedef");
`check(R, 13, "parameter list continuation did not hide typedef");
`check(Q, 11, "localparam name did not hide typedef");
`check(L, 17, "localparam list continuation did not hide typedef");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,85 @@
// Check that parameter port declaration names can shadow visible type identifiers.
typedef int P;
typedef int Q;
typedef int R;
typedef logic [7:0] T;
typedef int TP;
package p;
typedef logic [5:0] PT;
endpackage
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
module M #(
parameter int P = 5,
Q = 9,
int R = 13,
T typed_value = 8'ha5,
T T = 8'h3c,
p::PT pkg_value = 6'h2a,
parameter type TP = logic [5:0]
) (output reg failed);
TP type_param_value;
initial begin
failed = 1'b0;
type_param_value = 6'h15;
`check(P, 5, "parameter port typed value mismatch");
`check(Q, 9, "parameter port untyped continuation mismatch");
`check(R, 13, "parameter port atomic type continuation mismatch");
`check($bits(typed_value), 8, "parameter port typedef type continuation width mismatch");
`check(typed_value, 8'ha5, "parameter port typedef type continuation value mismatch");
`check($bits(T), 8, "parameter port type-name continuation did not keep typedef type");
`check(T, 8'h3c, "parameter port type-name continuation value mismatch");
`check($bits(pkg_value), 6, "parameter port package type continuation width mismatch");
`check(pkg_value, 6'h2a, "parameter port package type continuation value mismatch");
`check($bits(type_param_value), 6, "parameter port type parameter mismatch");
`check(type_param_value, 6'h15, "parameter port type parameter value mismatch");
end
endmodule
module N #(P = 3, T typed_value = 8'h5a) (output reg failed);
initial begin
failed = 1'b0;
`check(P, 3, "omitted parameter keyword mismatch");
`check($bits(typed_value), 8, "omitted parameter keyword typedef width mismatch");
`check(typed_value, 8'h5a, "omitted parameter keyword typedef value mismatch");
end
endmodule
module test;
reg failed;
wire failed_m;
wire failed_n;
M i_m(failed_m);
N i_n(failed_n);
initial begin
failed = 1'b0;
#1;
`check(failed_m, 1'b0, "parameter port module failed");
`check(failed_n, 1'b0, "omitted parameter keyword module failed");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,41 @@
// Check that typed parameter declaration names can shadow visible type identifiers.
typedef int P;
typedef logic [7:0] T;
typedef logic [6:0] U;
module test;
reg failed;
parameter int P = 13;
parameter T typed_value = 8'ha5;
parameter T T = 8'h3c;
parameter U u0 = 7'h2a, U = 7'h15;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
`check(P, 13, "typed parameter name did not hide typedef");
`check($bits(typed_value), 8, "typed parameter width mismatch");
`check(typed_value, 8'ha5, "typed parameter value mismatch");
`check($bits(T), 8, "type-name parameter did not keep typedef type");
`check(T, 8'h3c, "type-name parameter value mismatch");
`check($bits(u0), 7, "parameter list first declaration did not keep typedef type");
`check(u0, 7'h2a, "parameter list first value mismatch");
`check($bits(U), 7, "parameter list continuation did not allow typedef name as parameter name");
`check(U, 7'h15, "parameter list continuation value mismatch");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,32 @@
// Check that type parameter declaration names can shadow visible type identifiers.
typedef int TP;
module test;
reg failed;
parameter type TP = logic [3:0];
TP type_param_value;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
initial begin
failed = 1'b0;
type_param_value = 4'hc;
`check($bits(type_param_value), 4, "type parameter name did not hide typedef");
`check(type_param_value, 4'hc, "type parameter value mismatch");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,236 @@
// Check that module port names can shadow visible type identifiers.
typedef logic [3:0] T;
package p;
typedef logic [5:0] PT;
endpackage
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
module ansi_name(input T);
endmodule
module ansi_type(input T x);
endmodule
module ansi_name_dim(input T [1:0]);
endmodule
module ansi_type_dim(input T [1:0] x);
endmodule
module ansi_name_list(input T, U);
endmodule
module ansi_type_list(input T x, y);
endmodule
module ansi_type_list_shadow(input T x, T);
endmodule
module ansi_type_name(input T T, output logic ok);
initial ok = ($bits(T) == 4);
endmodule
module ansi_type_redecl(input n, T x);
endmodule
module ansi_type_redecl_dim(input n, T [1:0] x);
endmodule
module ansi_name_redecl_dim(input n, T [1:0]);
endmodule
module ansi_pkg_type_redecl(input n, p::PT x);
endmodule
module ansi_pkg_type_redecl_dim(input n, p::PT [1:0] x);
endmodule
module decl_name(T);
input T;
endmodule
module decl_type(x);
input T x;
endmodule
module decl_type_dim(x);
input T [1:0] x;
endmodule
module decl_external(.T(x));
input x;
endmodule
module decl_name_list(T, U);
input T, U;
endmodule
module decl_type_list(x, y);
input T x, y;
endmodule
module decl_type_list_shadow(x, T);
input T x, T;
endmodule
module decl_type_name(T, ok);
input T T;
output logic ok;
initial ok = ($bits(T) == 4);
endmodule
module test;
reg failed;
logic n;
T t;
logic n_dim [1:0];
T [1:0] t_dim;
logic n0, n1;
T t0, t1;
logic rn;
T rt;
T [1:0] rt_dim;
logic rn_dim;
logic rt_name_dim [1:0];
logic rp_n;
logic [5:0] rp_t;
logic rp_dim_n;
logic [1:0][5:0] rp_t_dim;
logic d_n;
T d_t;
T [1:0] d_t_dim;
logic d_ext;
logic d_n0, d_n1;
T d_t0, d_t1;
T s_t0, s_t1;
T d_s_t0, d_s_t1;
T p_tn;
T d_p_tn;
logic p_tn_ok;
logic d_p_tn_ok;
ansi_name m0(n);
ansi_type m1(t);
ansi_name_dim m2(n_dim);
ansi_type_dim m3(t_dim);
ansi_name_list m4(n0, n1);
ansi_type_list m5(t0, t1);
ansi_type_list_shadow m17(s_t0, s_t1);
ansi_type_name m19(p_tn, p_tn_ok);
ansi_type_redecl m12(rn, rt);
ansi_type_redecl_dim m13(rn, rt_dim);
ansi_name_redecl_dim m14(rn_dim, rt_name_dim);
ansi_pkg_type_redecl m15(rp_n, rp_t);
ansi_pkg_type_redecl_dim m16(rp_dim_n, rp_t_dim);
decl_name m6(d_n);
decl_type m7(d_t);
decl_type_dim m8(d_t_dim);
decl_external m9(d_ext);
decl_name_list m10(d_n0, d_n1);
decl_type_list m11(d_t0, d_t1);
decl_type_list_shadow m18(d_s_t0, d_s_t1);
decl_type_name m20(d_p_tn, d_p_tn_ok);
initial begin
failed = 1'b0;
n = 1'b1;
t = 4'ha;
n_dim[0] = 1'b0;
n_dim[1] = 1'b1;
t_dim[0] = 4'h3;
t_dim[1] = 4'hc;
n0 = 1'b0;
n1 = 1'b1;
t0 = 4'h5;
t1 = 4'ha;
s_t0 = 4'h6;
s_t1 = 4'h9;
p_tn = 4'h3;
rn = 1'b1;
rt = 4'hc;
rt_dim[0] = 4'h3;
rt_dim[1] = 4'ha;
rn_dim = 1'b0;
rt_name_dim[0] = 1'b1;
rt_name_dim[1] = 1'b0;
rp_n = 1'b1;
rp_t = 6'h2a;
rp_dim_n = 1'b0;
rp_t_dim[0] = 6'h15;
rp_t_dim[1] = 6'h2a;
d_n = 1'b1;
d_t = 4'h6;
d_t_dim[0] = 4'h7;
d_t_dim[1] = 4'h8;
d_ext = 1'b0;
d_n0 = 1'b1;
d_n1 = 1'b0;
d_t0 = 4'h9;
d_t1 = 4'h6;
d_s_t0 = 4'h5;
d_s_t1 = 4'ha;
d_p_tn = 4'hc;
#1;
`check($bits(n), 1, "input T was not parsed as a port name");
`check($bits(t), 4, "input T x was not parsed as a typed port");
`check($bits(n_dim), 2, "input T [1:0] was not parsed as a port array");
`check($bits(t_dim), 8, "input T [1:0] x was not parsed as a typed port array");
`check($bits(n0), 1, "input T, U first port did not keep implicit type");
`check($bits(n1), 1, "input T, U continuation did not keep implicit type");
`check($bits(t0), 4, "input T x, y first port did not keep typedef type");
`check($bits(t1), 4, "input T x, y continuation did not keep typedef type");
`check(t0, 4'h5, "Typed port list first value mismatch");
`check(t1, 4'ha, "Typed port list continuation mismatch");
`check($bits(s_t0), 4, "input T x, T first port did not keep typedef type");
`check($bits(s_t1), 4, "input T x, T continuation did not allow typedef name as port name");
`check(s_t1, 4'h9, "Typed port list shadowing value mismatch");
`check($bits(p_tn), 4, "input T T did not keep typedef type");
`check(p_tn_ok, 1'b1, "input T T was not available as a typed port");
`check($bits(rn), 1, "input n, T x first port did not keep implicit type");
`check($bits(rt), 4, "input n, T x second port did not keep typedef type");
`check(rt, 4'hc, "Inherited-direction typedef port value mismatch");
`check($bits(rt_dim), 8, "input n, T [1:0] x did not keep typedef packed dimensions");
`check(rt_dim[0], 4'h3, "Inherited-direction typedef packed array value mismatch");
`check(rt_dim[1], 4'ha, "Inherited-direction typedef packed array value mismatch");
`check($bits(rn_dim), 1, "input n, T [1:0] first port did not keep implicit type");
`check($bits(rt_name_dim), 2, "input n, T [1:0] second port was not parsed as a port array");
`check($bits(rp_t), 6, "input n, p::PT x second port did not keep package typedef type");
`check(rp_t, 6'h2a, "Inherited-direction package typedef port value mismatch");
`check($bits(rp_t_dim), 12, "input n, p::PT [1:0] x did not keep package typedef packed dimensions");
`check(rp_t_dim[0], 6'h15, "Inherited-direction package typedef packed array value mismatch");
`check(rp_t_dim[1], 6'h2a, "Inherited-direction package typedef packed array value mismatch");
`check($bits(d_n), 1, "input T was not parsed as a port declaration name");
`check($bits(d_t), 4, "input T x was not parsed as a typed port declaration");
`check($bits(d_t_dim), 8, "input T [1:0] x was not parsed as a typed port declaration array");
`check($bits(d_ext), 1, ".T(x) was not parsed as an external port name");
`check($bits(d_n0), 1, "input T, U first declaration did not keep implicit type");
`check($bits(d_n1), 1, "input T, U continuation declaration did not keep implicit type");
`check($bits(d_t0), 4, "input T x, y first declaration did not keep typedef type");
`check($bits(d_t1), 4, "input T x, y continuation declaration did not keep typedef type");
`check(d_t0, 4'h9, "Typed port declaration list first value mismatch");
`check(d_t1, 4'h6, "Typed port declaration list continuation mismatch");
`check($bits(d_s_t0), 4, "input T x, T first declaration did not keep typedef type");
`check($bits(d_s_t1), 4, "input T x, T declaration did not allow typedef name as port name");
`check(d_s_t1, 4'ha, "Typed port declaration list shadowing value mismatch");
`check($bits(d_p_tn), 4, "non-ANSI input T T did not keep typedef type");
`check(d_p_tn_ok, 1'b1, "non-ANSI input T T was not available as a typed port");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,14 @@
// Check that a specparam name can shadow a visible type identifier.
typedef int SP_DELAY;
module test(input in, output out);
specify
specparam SP_DELAY = 1;
(in => out) = SP_DELAY;
endspecify
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,120 @@
// Check that task and function argument names can shadow visible type identifiers.
typedef int T;
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
function int f_name(input T);
return ($bits(T) == 1 && T === 1'b1) ? 32'd33 : -1;
endfunction
function int f_type(input T value);
return ($bits(value) == 32) ? value : -1;
endfunction
function int f_type_list(input T value, T);
return $bits(value) + $bits(T);
endfunction
function int f_type_name(input T T);
return $bits(T);
endfunction
function int f_decl_name;
input T;
return $bits(T);
endfunction
function int f_decl_type;
input T value;
return $bits(value);
endfunction
function int f_decl_type_name;
input T T;
return $bits(T);
endfunction
task t_name(input T, output int value);
value = ($bits(T) == 1 && T === 1'b1) ? 32'd44 : -1;
endtask
task t_type(input T value, output int result);
result = ($bits(value) == 32) ? value : -1;
endtask
task t_type_list(input T value, T, output int result);
result = $bits(value) + $bits(T);
endtask
task t_type_name(input T T, output int value);
value = $bits(T);
endtask
task t_decl_name;
input T;
output int value;
value = $bits(T);
endtask
task t_decl_type;
input T value;
output int result;
result = $bits(value);
endtask
task t_decl_type_name;
input T T;
output int value;
value = $bits(T);
endtask
initial begin
int r0;
int r1;
int r2;
int r3;
int r4;
int r5;
int r6;
failed = 1'b0;
t_name(1'b1, r0);
t_type(32'd55, r1);
t_type_list(32'd11, 32'd22, r2);
t_decl_name(1'b1, r3);
t_decl_type(32'd33, r4);
t_type_name(32'd44, r5);
t_decl_type_name(32'd55, r6);
`check(f_name(1'b1), 32'd33, "Function argument did not hide typedef");
`check(f_type(32'd66), 32'd66, "Function typed argument regressed");
`check(f_type_list(32'd11, 32'd22), 64, "Function typed argument list shadowing mismatch");
`check(f_type_name(32'd33), 32, "Function type-name argument did not keep typedef type");
`check(f_decl_name(1'b1), 1, "Function non-ANSI argument did not hide typedef");
`check(f_decl_type(32'd66), 32, "Function non-ANSI typed argument regressed");
`check(f_decl_type_name(32'd77), 32, "Function non-ANSI type-name argument did not keep typedef type");
`check(r0, 32'd44, "Task argument did not hide typedef");
`check(r1, 32'd55, "Task typed argument regressed");
`check(r2, 64, "Task typed argument list shadowing mismatch");
`check(r3, 1, "Task non-ANSI argument did not hide typedef");
`check(r4, 32, "Task non-ANSI typed argument regressed");
`check(r5, 32, "Task type-name argument did not keep typedef type");
`check(r6, 32, "Task non-ANSI type-name argument did not keep typedef type");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,62 @@
// Check that task names can shadow visible type identifiers.
typedef int T;
typedef int U;
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
task T(input int value, output int result);
result = value + 32'd1;
endtask
task U;
output int result;
result = 32'd33;
endtask
class C;
task T(input int value, output int result);
result = value + 32'd2;
endtask
task C(input int value, output int result);
result = value + 32'd3;
endtask
endclass
initial begin
C c;
int r0;
int r1;
int r2;
int r3;
failed = 1'b0;
c = new;
T(32'd41, r0);
U(r1);
c.T(32'd40, r2);
c.C(32'd39, r3);
`check(r0, 32'd42, "Task name did not hide typedef");
`check(r1, 32'd33, "Non-ANSI task name did not hide typedef");
`check(r2, 32'd42, "Class task name did not hide typedef");
`check(r3, 32'd42, "Class task name did not hide class name");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,25 @@
// Check that ANSI-style UDP names can shadow visible type identifiers.
package p;
typedef int ANSI_UDP;
typedef int Y;
typedef int I0;
typedef int I1;
endpackage
import p::*;
primitive ANSI_UDP (output Y, input I0, input I1);
table
00 : 0;
01 : 0;
10 : 0;
11 : 1;
endtable
endprimitive
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,29 @@
// Check that old-style UDP names can shadow visible type identifiers.
package p;
typedef int OLD_UDP;
typedef int Q;
typedef int A;
typedef int B;
endpackage
import p::*;
primitive OLD_UDP (Q, A, B);
output reg Q;
input A, B;
initial Q = 0;
table
00 : ? : 0;
01 : ? : 0;
10 : ? : 0;
11 : ? : 1;
endtable
endprimitive
module test;
initial begin
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,152 @@
// Check that variable names can shadow visible type identifiers.
typedef logic [7:0] T;
typedef int V;
typedef int W;
typedef logic [6:0] A;
typedef logic [5:0] B;
typedef logic [4:0] C;
typedef logic [3:0] D;
typedef logic [2:0] E;
typedef logic [1:0] F;
typedef logic [2:0] G;
typedef logic [3:0] H;
typedef logic [4:0] I;
typedef logic [2:0] P;
bit X;
package p;
var C;
var D x, D;
var P P;
endpackage
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
typedef logic [3:0] X;
T outer;
T a, b;
A a0, A;
E E;
int T, U;
var V;
var B b0, B;
var F F;
X x;
function int f;
int T;
T = 32'd11;
return T;
endfunction
function int f_type_name;
H H;
H = 4'ha;
return $bits(H) + H;
endfunction
task t(output int value);
int T;
T = 32'd22;
value = T;
endtask
task t_type_name(output int value);
I I;
I = 5'h15;
value = $bits(I) + I;
endtask
initial begin
int r;
int r_type_name;
int tr_type_name;
var W;
failed = 1'b0;
outer = 8'ha5;
a = 8'h33;
b = 8'hcc;
a0 = 7'h2a;
A = 7'h15;
E = 3'h5;
T = 32'd23;
U = 32'd41;
V = 1'b1;
b0 = 6'h2a;
B = 6'h15;
F = 2'h2;
W = 1'b0;
x = 4'hc;
t(r);
t_type_name(tr_type_name);
begin : block_scope
int T;
T = 32'd7;
`check(T, 32'd7, "Block declaration did not hide typedef");
end
begin : block_type_name
G G;
G = 3'h3;
`check($bits(G), 3, "Block type-name declaration did not keep typedef type");
`check(G, 3'h3, "Block type-name declaration value mismatch");
end
r_type_name = f_type_name();
`check(outer, 8'ha5, "Typedef value changed");
`check(T, 32'd23, "Module declaration did not hide typedef");
`check(U, 32'd41, "Declaration list continuation mismatch");
`check($bits(V), 1, "Module var declaration did not hide typedef width");
`check(V, 1'b1, "Module var declaration did not hide typedef value");
`check($bits(W), 1, "Block var declaration did not hide typedef width");
`check(W, 1'b0, "Block var declaration did not hide typedef value");
`check(a, 8'h33, "Type declaration list first value mismatch");
`check(b, 8'hcc, "Type declaration list continuation mismatch");
`check($bits(a0), 7, "Type declaration list did not keep typedef type");
`check($bits(A), 7, "Type declaration list did not allow typedef name as continuation");
`check(A, 7'h15, "Type declaration list shadowing value mismatch");
`check($bits(E), 3, "Type-name declaration did not keep typedef type");
`check(E, 3'h5, "Type-name declaration value mismatch");
`check($bits(b0), 6, "Var declaration list did not keep typedef type");
`check($bits(B), 6, "Var declaration list did not allow typedef name as continuation");
`check(B, 6'h15, "Var declaration list shadowing value mismatch");
`check($bits(F), 2, "Var type-name declaration did not keep typedef type");
`check(F, 2'h2, "Var type-name declaration value mismatch");
`check($bits(p::C), 1, "Package var declaration did not hide typedef width");
`check($bits(p::x), 4, "Package type declaration list first width mismatch");
`check($bits(p::D), 4, "Package type declaration list did not allow typedef name as continuation");
`check($bits(p::P), 3, "Package type-name declaration did not keep typedef type");
`check(f(), 32'd11, "Function declaration did not hide typedef");
`check(r_type_name, 14, "Function type-name declaration mismatch");
`check(r, 32'd22, "Task declaration did not hide typedef");
`check(tr_type_name, 26, "Task type-name declaration mismatch");
`check($bits(x), 4, "Local typedef did not hide outer identifier");
`check(x, 4'hc, "Local typedef value mismatch");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,8 @@
// Check that an ANSI-style UDP output initializer requires a reg output.
primitive udp_ansi_initial_nonreg_fail (output o = 1'b0, input i);
table
0 : 0;
1 : 1;
endtable
endprimitive

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