Merge branch 'master' into vvp-net-out-rework

Conflicts:
	vvp/schedule.cc
	vvp/schedule.h
This commit is contained in:
Stephen Williams 2009-09-05 10:19:20 -07:00
commit 0018cb38b0
76 changed files with 2409 additions and 3885 deletions

View File

@ -1,7 +1,7 @@
#ifndef __Attrib_H
#define __Attrib_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -30,7 +30,7 @@ class Attrib {
public:
Attrib();
~Attrib();
virtual ~Attrib();
const verinum&attribute(perm_string key) const;
void attribute(perm_string key, const verinum&value);

View File

@ -1,7 +1,7 @@
#ifndef __LineInfo_H
#define __LineInfo_H
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -36,7 +36,7 @@ using namespace std;
class LineInfo {
public:
LineInfo();
~LineInfo();
virtual ~LineInfo();
// Get a fully formatted file/lineno
string get_fileline() const;

View File

@ -24,6 +24,8 @@
# include "PWire.h"
# include <assert.h>
list<Module::named_expr_t> Module::user_defparms;
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScope(n)

View File

@ -92,6 +92,7 @@ class Module : public PScope, public LineInfo {
instantiated modules. */
typedef pair<pform_name_t,PExpr*> named_expr_t;
list<named_expr_t>defparms;
static list<named_expr_t>user_defparms;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,

View File

@ -339,6 +339,12 @@ class PEIdent : public PExpr {
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_param_idx_do_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006,2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -55,6 +55,7 @@ void PGenerate::probe_for_direct_nesting_(void)
if (localparams.size() > 0) return;
if (events.size() > 0) return;
if (wires.size() > 0) return;
if (genvars.size() > 0) return;
if (behaviors.size() > 0) return;
if (analog_behaviors.size() > 0) return;

View File

@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -87,6 +87,9 @@ class PGenerate : public LineInfo, public LexicalScope {
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
// genvars declared within this scheme.
map<perm_string,LineInfo*> genvars;
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
PGenerate*parent;
@ -109,8 +112,8 @@ class PGenerate : public LineInfo, public LexicalScope {
bool generate_scope_case_(Design*des, NetScope*container);
bool generate_scope_nblock_(Design*des, NetScope*container);
// Call probe during elaborate_scope to calulate the
// directed_nested_ flag. It is OK to store the direct_nested_
// Call probe during elaborate_scope to calculate the
// direct_nested_ flag. It is OK to store the direct_nested_
// information here because "direct nested" is a property of
// the lexical generate code.
void probe_for_direct_nesting_(void);

View File

@ -82,6 +82,9 @@ extern bool warn_timescale;
/* Warn about legal but questionable module port bindings. */
extern bool warn_portbinding;
/* Warn about constant out of bound selects. */
extern bool warn_ob_select;
/* Warn about structures that may have infinite loops. */
extern bool warn_inf_loop;

965
config.guess vendored

File diff suppressed because it is too large Load Diff

415
config.sub vendored
View File

@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
timestamp='2002-07-03'
timestamp='2009-04-17'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@ -21,14 +22,15 @@ timestamp='2002-07-03'
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
@ -70,8 +72,8 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008 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."
@ -83,11 +85,11 @@ Try \`$me --help' for more information."
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit 0 ;;
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit 0 ;;
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit 0 ;;
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
@ -99,7 +101,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
exit 0;;
exit ;;
* )
break ;;
@ -118,7 +120,10 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@ -144,7 +149,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis)
-apple | -axis | -knuth | -cray)
os=
basic_machine=$1
;;
@ -169,6 +174,10 @@ case $os in
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@ -185,6 +194,10 @@ case $os in
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@ -228,40 +241,57 @@ case $basic_machine in
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k \
| m32r | m68000 | m68k | m88k | mcore \
| ip2k | iq2000 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| openrisc | or32 \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| strongarm \
| tahoe | thumb | tic80 | tron \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xscale | xstormy16 | xtensa \
| z8k)
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
@ -271,6 +301,9 @@ case $basic_machine in
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@ -290,48 +323,67 @@ case $basic_machine in
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c54x-* \
| clipper-* | cydra-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* \
| m32r-* \
| ip2k-* | iq2000-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipstx39 | mipstx39el \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
| xtensa-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-*)
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@ -349,6 +401,9 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
@ -363,6 +418,12 @@ case $basic_machine in
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@ -386,6 +447,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
@ -394,10 +459,22 @@ case $basic_machine in
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@ -422,12 +499,27 @@ case $basic_machine in
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16)
basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@ -450,6 +542,14 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
@ -600,6 +700,14 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
@ -615,6 +723,10 @@ case $basic_machine in
basic_machine=i386-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
@ -628,10 +740,6 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
@ -644,6 +752,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
mvs)
basic_machine=i370-ibm
os=-mvs
@ -719,9 +830,12 @@ case $basic_machine in
basic_machine=hppa1.1-oki
os=-proelf
;;
or32 | or32-*)
openrisc | openrisc-*)
basic_machine=or32-unknown
os=-coff
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
@ -739,55 +853,75 @@ case $basic_machine in
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
pentiumpro | p6 | 6x86 | athlon)
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2)
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-*)
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
;;
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
@ -798,6 +932,10 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@ -818,6 +956,20 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
@ -825,6 +977,12 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
@ -883,7 +1041,7 @@ case $basic_machine in
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
sv1)
basic_machine=sv1-cray
os=-unicos
;;
@ -891,10 +1049,6 @@ case $basic_machine in
basic_machine=i386-sequent
os=-dynix
;;
t3d)
basic_machine=alpha-cray
os=-unicos
;;
t3e)
basic_machine=alphaev5-cray
os=-unicos
@ -907,6 +1061,18 @@ case $basic_machine in
basic_machine=tic54x-unknown
os=-coff
;;
tic55x | c55x*)
basic_machine=tic55x-unknown
os=-coff
;;
tic6x | c6x*)
basic_machine=tic6x-unknown
os=-coff
;;
tile*)
basic_machine=tile-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
;;
@ -920,6 +1086,10 @@ case $basic_machine in
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
@ -941,8 +1111,8 @@ case $basic_machine in
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
@ -963,11 +1133,11 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
windows32)
basic_machine=i386-pc
os=-windows32-msvcrt
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
xps | xps100)
basic_machine=xps100-honeywell
;;
ymp)
@ -978,6 +1148,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@ -997,6 +1171,9 @@ case $basic_machine in
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
@ -1013,16 +1190,13 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparc | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
cydra)
basic_machine=cydra-cydrome
;;
orion)
@ -1037,10 +1211,6 @@ case $basic_machine in
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
c4x*)
basic_machine=c4x-none
os=-coff
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
@ -1092,22 +1262,28 @@ case $os in
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -kopensolaris* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*)
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@ -1119,16 +1295,24 @@ case $os in
;;
esac
;;
-nto-qnx*)
;;
-nto*)
os=-nto-qnx
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
@ -1138,6 +1322,9 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
@ -1159,6 +1346,9 @@ case $os in
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
@ -1169,7 +1359,7 @@ case $os in
os=-rtmk-nova
;;
-ns2 )
os=-nextstep2
os=-nextstep2
;;
-nsk*)
os=-nsk
@ -1181,6 +1371,9 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
@ -1208,8 +1401,20 @@ case $os in
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-none)
;;
@ -1233,6 +1438,12 @@ else
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
@ -1242,11 +1453,14 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
;;
pdp11-*)
pdp11-*)
os=-none
;;
*-dec | vax-*)
@ -1267,6 +1481,9 @@ case $basic_machine in
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
@ -1285,9 +1502,15 @@ case $basic_machine in
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
@ -1339,19 +1562,19 @@ case $basic_machine in
*-next)
os=-nextstep3
;;
*-gould)
*-gould)
os=-sysv
;;
*-highlevel)
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
*-sgi)
os=-irix
;;
*-siemens)
*-siemens)
os=-sysv4
;;
*-masscomp)
@ -1420,9 +1643,15 @@ case $basic_machine in
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
@ -1447,7 +1676,7 @@ case $basic_machine in
esac
echo $basic_machine$os
exit 0
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)

View File

@ -72,6 +72,8 @@ int cmdfile_stack_ptr = 0;
\n { cflloc.first_line += 1; }
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }

View File

@ -57,7 +57,7 @@ static void translate_file_name(char*text)
};
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT TOK_PARAMETER
%token TOK_INTEGER_WIDTH
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
@ -135,6 +135,13 @@ item
free(tmp);
}
| TOK_PARAMETER TOK_PLUSARG
{ char*tmp = substitutions($2);
process_parameter(tmp);
free($2);
free(tmp);
}
| TOK_DEFINE TOK_PLUSARG
{ process_define($2);
free($2);

View File

@ -65,7 +65,10 @@ extern void process_include_dir(const char*name);
/* Add a new -D define. */
extern void process_define(const char*name);
/* Add a new parameter definition */
extern void process_parameter(const char*name);
/* -v */
extern int verbose_flag;

View File

@ -4,10 +4,10 @@ iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value]
[-dname] [-g1995|-g2001|-g2005|-g<feature>]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] [\-pflag=value]
[\-dname] [\-g1995|\-g2001|\-g2005|\-g<feature>]
[\-Iincludedir] [\-mmodule] [\-Mfile] [\-Nfile] [\-ooutputfilename]
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
.SH DESCRIPTION
.PP
@ -18,7 +18,6 @@ simulation, and \fIfpga\fP for synthesis. Other target
types are added as code generators are implemented.
.SH OPTIONS
.l
\fIiverilog\fP accepts the following options:
.TP 8
.B -B\fIbase\fP
@ -260,7 +259,8 @@ after a \fB-Wall\fP argument to suppress isolated warning types.
.TP 8
.B all
This enables the implicit, portbind and timescale warning categories.
This enables the implicit, portbind, select-range and timescale warning
categories.
.TP 8
.B implicit
@ -274,6 +274,12 @@ This enables warnings for ports of module instantiations that are not
connected but probably should be. Dangling input ports, for example,
will generate a warning.
.TP 8
.B select-range
This enables warnings for constant out of bound selects. This includes
partial or fully out of bound selects as well as a select using 'bx as
an index.
.TP 8
.B timescale
This enables warnings for inconsistent use of the timescale
@ -369,7 +375,7 @@ on to the next library directory.
.TP 8
.B +libdir+\fIdir\fP
This is another way to specify library directories. See the -y flag.
This is another way to specify library directories. See the \-y flag.
.TP 8
.B +libdir-nocase+\fIdir\fP
@ -434,11 +440,11 @@ To compile hello.v to an executable file called a.out:
To compile hello.v to an executable file called hello:
iverilog -o hello hello.v
iverilog \-o hello hello.v
To compile and run explicitly using the vvp runtime:
iverilog -ohello.vvp -tvvp hello.v
iverilog \-ohello.vvp \-tvvp hello.v
.SH "AUTHOR"
.nf

View File

@ -167,6 +167,12 @@ typedef struct t_command_file {
p_command_file cmd_file_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
/* Temprarily store parameter definition from command line and
* parse it after we have delt with command file
*/
static const char** defparm_base = 0;
static int defparm_size = 0;
/* Function to add a command file name to the FIFO. */
void add_cmd_file(const char* filename)
{
@ -469,6 +475,7 @@ static void process_warning_switch(const char*name)
if (strcmp(name,"all") == 0) {
process_warning_switch("implicit");
process_warning_switch("portbind");
process_warning_switch("select-range");
process_warning_switch("timescale");
} else if (strcmp(name,"implicit") == 0) {
if (! strchr(warning_flags, 'i'))
@ -476,6 +483,9 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"portbind") == 0) {
if (! strchr(warning_flags, 'p'))
strcat(warning_flags, "p");
} else if (strcmp(name,"select-range") == 0) {
if (! strchr(warning_flags, 's'))
strcat(warning_flags, "s");
} else if (strcmp(name,"timescale") == 0) {
if (! strchr(warning_flags, 't'))
strcat(warning_flags, "t");
@ -496,6 +506,12 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-select-range") == 0) {
char*cp = strchr(warning_flags, 's');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-timescale") == 0) {
char*cp = strchr(warning_flags, 't');
if (cp) while (*cp) {
@ -530,6 +546,11 @@ void process_define(const char*name)
fprintf(defines_file,"D:%s\n", name);
}
void process_parameter(const char*name)
{
fprintf(iconfig_file,"defparam:%s\n", name);
}
/*
* This function is called while processing a file name in a command
* file, or a file name on the command line. Look to see if there is a
@ -774,7 +795,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@ -798,6 +819,11 @@ int main(int argc, char **argv)
case 'E':
e_flag = 1;
break;
case 'P':
defparm_size += 1;
defparm_base = (const char**)realloc(defparm_base, defparm_size*sizeof(char*));
defparm_base[defparm_size-1] = optarg;
break;
case 'p':
fprintf(iconfig_file, "flag:%s\n", optarg);
break;
@ -966,6 +992,15 @@ int main(int argc, char **argv)
fprintf(defines_file, "M:%s\n", depfile);
}
/* Process parameter definition from command line. The last
defined would override previous ones. */
int pitr;
for (pitr = 0; pitr < defparm_size; pitr++)
process_parameter(defparm_base[pitr]);
free(defparm_base);
defparm_base = 0;
defparm_size = 0;
/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)

View File

@ -2210,12 +2210,12 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
static verinum param_part_select_bits(const verinum&par_val, long wid,
long lsv, long par_lsv)
long lsv)
{
verinum result (verinum::Vx, wid, true);
for (long idx = 0 ; idx < wid ; idx += 1) {
long off = idx + lsv - par_lsv;
long off = idx + lsv;
if (off < 0)
result.set(idx, verinum::Vx);
else if (off < (long)par_val.len())
@ -2230,7 +2230,7 @@ static verinum param_part_select_bits(const verinum&par_val, long wid,
// If the input is a string, and the part select is working on
// byte boundaries, then make the result into a string.
if (par_val.is_string() && (labs(lsv-par_lsv)%8 == 0) && (wid%8 == 0))
if (par_val.is_string() && (labs(lsv)%8 == 0) && (wid%8 == 0))
return result.as_string();
return result;
@ -2286,28 +2286,56 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
verinum result = param_part_select_bits(par_ex->value(), wid, lsv, par_lsv);
verinum result = param_part_select_bits(par_ex->value(), wid, lsv-par_lsv);
NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this);
return result_ex;
}
static void warn_param_ob(long par_msv, long par_lsv, bool defined,
long par_base, unsigned long wid, long pwid,
const LineInfo *info, perm_string name, bool up)
{
long par_max;
if (defined) {
if (par_msv < par_lsv) par_max = par_lsv-par_msv;
else par_max = par_msv-par_lsv;
} else {
if (pwid < 0) par_max = integer_width;
else par_max = pwid;
}
/* Is this a select before the start of the parameter? */
if (par_base < 0) {
cerr << info->get_fileline() << ": warning: " << name << "["
<< par_base;
if (up) cerr << "+:";
else cerr << "-:";
cerr << wid << "] is selecting before vector." << endl;
}
/* Is this a select after the end of the parameter? */
if (par_base + (long)wid - 1 > par_max) {
cerr << info->get_fileline() << ": warning: " << name << "["
<< par_base << "+:" << wid << "] is selecting after vector."
<< endl;
}
}
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
{
long par_msv, par_lsv;
bool flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
if (!flag)
return 0;
if(! calculate_param_range_(des, scope, par_msb, par_msv,
par_lsb, par_lsv)) return 0;
NetExpr*base = calculate_up_do_base_(des, scope);
if (base == 0)
return 0;
if (base == 0) return 0;
unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid);
@ -2323,22 +2351,139 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
// Handle the special case that the base is constant. In this
// case, just precalculate the entire constant result.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
if (! base_c->value().is_defined()) {
NetEConst *ex;
ex = new NetEConst(verinum(verinum::Vx, wid, true));
ex->set_line(*this);
if (warn_ob_select) {
perm_string name = peek_tail_name(path_);
cerr << get_fileline() << ": warning: " << name
<< "['bx+:" << wid
<< "] is always outside vector." << endl;
}
return ex;
}
long lsv = base_c->value().as_long();
long par_base = par_lsv;
// Watch out for reversed bit numbering. We're making
// the part select from LSB to MSB.
if (par_msv < par_lsv)
lsv = lsv - wid + 1;
if (par_msv < par_lsv) {
par_base = lsv;
lsv = par_lsv - wid + 1;
}
if (warn_ob_select) {
bool defined = true;
// Check to see if the parameter has a defined range.
if (par_msb == 0) {
assert(par_lsb == 0);
defined = false;
}
// Get the parameter values width.
long pwid = -1;
if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
perm_string name = peek_tail_name(path_);
warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
pwid, this, name, true);
}
verinum result = param_part_select_bits(par_ex->value(), wid,
lsv, par_lsv);
lsv-par_base);
NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this);
return result_ex;
}
if ((par_msv < par_lsv) && (wid>1))
base = make_add_expr(base, 1-(long)wid);
if (par_msv >= par_lsv) {
if (par_lsv != 0) base = make_add_expr(base, -par_lsv);
} else {
base = make_sub_expr(par_lsv-wid+1, base);
}
NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid);
tmp->set_line(*this);
return tmp;
}
NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
{
long par_msv, par_lsv;
if(! calculate_param_range_(des, scope, par_msb, par_msv,
par_lsb, par_lsv)) return 0;
NetExpr*base = calculate_up_do_base_(des, scope);
if (base == 0) return 0;
unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid);
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Calculate part select "
<< "[" << *base << "-:" << wid << "] from range "
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
// Handle the special case that the base is constant. In this
// case, just precalculate the entire constant result.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
if (! base_c->value().is_defined()) {
NetEConst *ex;
ex = new NetEConst(verinum(verinum::Vx, wid, true));
ex->set_line(*this);
if (warn_ob_select) {
perm_string name = peek_tail_name(path_);
cerr << get_fileline() << ": warning: " << name
<< "['bx-:" << wid
<< "] is always outside vector." << endl;
}
return ex;
}
long lsv = base_c->value().as_long();
long par_base = par_lsv + wid - 1;
// Watch out for reversed bit numbering. We're making
// the part select from LSB to MSB.
if (par_msv < par_lsv) {
par_base = lsv;
lsv = par_lsv;
}
if (warn_ob_select) {
bool defined = true;
// Check to see if the parameter has a defined range.
if (par_msb == 0) {
assert(par_lsb == 0);
defined = false;
}
// Get the parameter values width.
long pwid = -1;
if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
perm_string name = peek_tail_name(path_);
warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
pwid, this, name, false);
}
verinum result = param_part_select_bits(par_ex->value(), wid,
lsv-par_base);
NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this);
return result_ex;
}
if (par_msv >= par_lsv) {
if (long offset = par_lsv+wid-1) {
base = make_add_expr(base, -offset);
}
} else {
base = make_sub_expr(par_lsv, base);
}
NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid);
@ -2385,49 +2530,16 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
par_msb, par_lsb);
if (use_sel == index_component_t::SEL_IDX_DO)
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
par_msb, par_lsb);
// NOTE TO SELF (continued): The code below should be
// rewritten in the above format, as I get to it.
NetExpr*tmp = par->dup_expr();
if (use_sel == index_component_t::SEL_IDX_DO) {
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb);
ivl_assert(*this, index_tail.lsb);
/* Get and evaluate the width of the index
select. This must be constant. */
need_constant_expr = true;
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
need_constant_expr = false;
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
if (wid_ec == 0) {
cerr << index_tail.lsb->get_fileline() << ": error: "
<< "Second expression of indexed part select "
<< "most be constant." << endl;
des->errors += 1;
return 0;
}
unsigned wid = wid_ec->value().as_ulong();
NetExpr*idx_ex = elab_and_eval(des, scope, index_tail.msb, -1);
if (idx_ex == 0) {
return 0;
}
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1) {
idx_ex = make_add_expr(idx_ex, 1-(long)wid);
}
/* Wrap the param expression with a part select. */
tmp = new NetESelect(tmp, idx_ex, wid);
} else if (use_sel == index_component_t::SEL_BIT) {
if (use_sel == index_component_t::SEL_BIT) {
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb);
@ -2768,15 +2880,47 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
if (net->sig()->sb_to_idx(lsv) == 0 &&
wid == net->vector_width()) {
delete base;
net->cast_signed(false);
return net;
}
long offset = 0;
if (net->msi() < net->lsi()) {
offset = -wid + 1;
}
// Otherwise, make a part select that covers the right
// range.
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
offset));
if (warn_ob_select) {
long rel_base = net->sig()->sb_to_idx(lsv) + offset;
if (rel_base < 0) {
cerr << get_fileline() << ": warning: "
<< net->name();
if (net->word_index()) cerr << "[]";
cerr << "[" << lsv << "+:" << wid
<< "] is selecting before vector." << endl;
}
if (rel_base + wid > net->vector_width()) {
cerr << get_fileline() << ": warning: "
<< net->name();
if (net->word_index()) cerr << "[]";
cerr << "[" << lsv << "+:" << wid
<< "] is selecting after vector." << endl;
}
}
} else {
// Return 'bx for an undefined base.
ex = new NetEConst(verinum(verinum::Vx, 1, false));
ex = new NetEConst(verinum(verinum::Vx, wid, true));
ex->set_line(*this);
delete base;
if (warn_ob_select) {
cerr << get_fileline() << ": warning: " << net->name();
if (net->word_index()) cerr << "[]";
cerr << "['bx+:" << wid
<< "] is always outside vector." << endl;
}
return ex;
}
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
@ -2787,11 +2931,9 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
if (net->msi() > net->lsi()) {
if (long offset = net->lsi())
base = make_add_expr(base, 0-offset);
base = make_add_expr(base, -offset);
} else {
long vwid = net->lsi() - net->msi() + 1;
long offset = net->msi();
base = make_sub_expr(vwid-offset-wid, base);
base = make_sub_expr(net->lsi()-wid+1, base);
}
NetESelect*ss = new NetESelect(net, base, wid);
@ -2830,15 +2972,47 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
wid == net->vector_width()) {
delete base;
net->cast_signed(false);
return net;
}
long offset = 0;
if (net->msi() > net->lsi()) {
offset = -wid + 1;
}
// Otherwise, make a part select that covers the right
// range.
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)-wid+1));
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
offset));
if (warn_ob_select) {
long rel_base = net->sig()->sb_to_idx(lsv) + offset;
if (rel_base < 0) {
cerr << get_fileline() << ": warning: "
<< net->name();
if (net->word_index()) cerr << "[]";
cerr << "[" << lsv << "+:" << wid
<< "] is selecting before vector." << endl;
}
if (rel_base + wid > net->vector_width()) {
cerr << get_fileline() << ": warning: "
<< net->name();
if (net->word_index()) cerr << "[]";
cerr << "[" << lsv << "-:" << wid
<< "] is selecting after vector." << endl;
}
}
} else {
// Return 'bx for an undefined base.
ex = new NetEConst(verinum(verinum::Vx, 1, false));
ex = new NetEConst(verinum(verinum::Vx, wid, true));
ex->set_line(*this);
delete base;
if (warn_ob_select) {
cerr << get_fileline() << ": warning: " << net->name();
if (net->word_index()) cerr << "[]";
cerr << "['bx-:" << wid
<< "] is always outside vector." << endl;
}
return ex;
}
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
@ -2847,16 +3021,19 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
return ss;
}
long offset = net->lsi();
NetExpr*base_adjusted = wid > 1
? make_add_expr(base,1-(long)wid-offset)
: (offset == 0? base : make_add_expr(base, 0-offset));
NetESelect*ss = new NetESelect(net, base_adjusted, wid);
if (net->msi() > net->lsi()) {
if (long offset = net->lsi()+wid-1)
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(net->lsi(), base);
}
NetESelect*ss = new NetESelect(net, base, wid);
ss->set_line(*this);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate part "
<< "select base="<< *base_adjusted << ", wid="<< wid << endl;
<< "select base="<< *base << ", wid="<< wid << endl;
}
return ss;

View File

@ -476,14 +476,78 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
base = make_sub_expr(reg->lsb(), base);
else if (reg->lsb() != 0)
base = make_add_expr(base, - reg->lsb());
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1 ) {
base = make_add_expr(base, 1-(long)wid);
// Handle the special case that the base is constant. For this
// case we can reduce the expression.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
// For the undefined case just let the constant pass and
// we will handle it in the code generator.
if (base_c->value().is_defined()) {
long lsv = base_c->value().as_long();
long offset = 0;
if (((reg->msb() < reg->lsb()) &&
use_sel == index_component_t::SEL_IDX_UP) ||
((reg->msb() > reg->lsb()) &&
use_sel == index_component_t::SEL_IDX_DO)) {
offset = -wid + 1;
}
delete base;
base = new NetEConst(verinum(reg->sb_to_idx(lsv) + offset));
if (warn_ob_select) {
long rel_base = reg->sb_to_idx(lsv) + offset;
if (rel_base < 0) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is selecting before vector." << endl;
}
if (rel_base + wid > reg->vector_width()) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is selecting after vector." << endl;
}
}
} else {
if (warn_ob_select) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << "['bx";
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is always outside vector." << endl;
}
}
} else {
/* Correct the mux for the range of the vector. */
if (use_sel == index_component_t::SEL_IDX_UP) {
if (reg->msb() > reg->lsb()) {
if (long offset = reg->lsb())
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(reg->lsb()-wid+1, base);
}
} else {
// This is assumed to be a SEL_IDX_DO.
if (reg->msb() > reg->lsb()) {
if (long offset = reg->lsb()+wid-1)
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(reg->lsb(), base);
}
}
}
if (debug_elaborate)

View File

@ -238,15 +238,33 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
return 0;
}
long midx_val = tmp->value().as_long();
midx = sig->sb_to_idx(midx_val);
delete tmp_ex;
/* The width (a constant) is calculated here. */
unsigned long wid = 0;
bool flag = calculate_up_do_width_(des, scope, wid);
if (! flag)
if (! flag) return false;
/* We have an undefined index and that is out of range. */
if (! tmp->value().is_defined()) {
if (warn_ob_select) {
cerr << get_fileline() << ": warning: "
<< sig->name();
if (sig->array_dimensions() > 0) cerr << "[]";
cerr << "['bx";
if (index_tail.sel ==
index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is always outside vector."
<< endl;
}
return false;
}
long midx_val = tmp->value().as_long();
midx = sig->sb_to_idx(midx_val);
delete tmp_ex;
if (index_tail.sel == index_component_t::SEL_IDX_UP)
lidx = sig->sb_to_idx(midx_val+wid-1);
@ -260,9 +278,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
}
/* Warn about an indexed part select that is out of range. */
if (midx >= (long)sig->vector_width() || lidx < 0) {
cerr << get_fileline() << ": warning: Indexed part "
"select " << sig->name();
if (warn_ob_select && (lidx < 0)) {
cerr << get_fileline() << ": warning: " << sig->name();
if (sig->array_dimensions() > 0) cerr << "[]";
cerr << "[" << midx_val;
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is selecting before vector." << endl;
}
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
cerr << get_fileline() << ": warning: " << sig->name();
if (sig->array_dimensions() > 0) {
cerr << "[]";
}
@ -272,7 +300,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
} else {
cerr << "-:";
}
cerr << wid << "] is out of range." << endl;
cerr << wid << "] is selecting after vector." << endl;
}
/* This is completely out side the signal so just skip it. */
@ -424,6 +452,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
unsigned midx = sig->vector_width()-1, lidx = 0;
// The default word select is the first.
long widx = 0;
// The widx_val is the word select as entered in the source
// code. It's used for error messages.
long widx_val = 0;
const name_component_t&name_tail = path_.back();
@ -462,8 +493,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0;
}
long widx_val = tmp->value().as_long();
widx = sig->array_index_to_address(widx_val);
widx_val = tmp->value().as_long();
if (sig->array_index_is_valid(widx_val))
widx = sig->array_index_to_address(widx_val);
else
widx = -1;
delete tmp_ex;
if (debug_elaborate)
@ -529,7 +563,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (widx < 0 || widx >= (long) sig->pin_count()) {
cerr << get_fileline() << ": warning: ignoring out of "
"bounds l-value array access "
<< sig->name() << "[" << widx << "]." << endl;
<< sig->name() << "[" << widx_val << "]." << endl;
return 0;
}

View File

@ -563,7 +563,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// Check that the loop_index variable was declared in a
// genvar statement.
if (container->find_genvar(loop_index) == 0) {
NetScope*scope = container;
while (scope && !scope->find_genvar(loop_index))
scope = scope->parent();
if (!scope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
@ -1021,6 +1024,12 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
// Add the genvars to this scope.
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); cur++ ) {
scope->add_genvar((*cur).first, (*cur).second);
}
// Scan the generated scope for nested generate schemes,
// and *generate* new scopes, which is slightly different
// from simple elaboration.

View File

@ -126,7 +126,7 @@ static void elaborate_sig_funcs(Design*des, NetScope*scope,
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
if (fscope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;

View File

@ -1571,43 +1571,34 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
module or primitive, it interprets them as parameter
overrides. Correct that misconception here. */
if (overrides_) {
PDelays tmp_del;
tmp_del.set_delays(overrides_, false);
tmp_del.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
if (dynamic_cast<NetEConst*> (rise_expr)) {
} else {
cerr << get_fileline() << ": error: Delay expressions must be "
<< "constant for primitives." << endl;
cerr << get_fileline() << ": : Cannot calculate "
<< *rise_expr << endl;
if (overrides_->count() > 2) {
cerr << get_fileline() << ": error: UDPs take at most two "
"delay arguments." << endl;
des->errors += 1;
}
if (dynamic_cast<NetEConst*> (fall_expr)) {
} else {
cerr << get_fileline() << ": error: Delay expressions must be "
<< "constant for primitives." << endl;
cerr << get_fileline() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
PDelays tmp_del;
tmp_del.set_delays(overrides_, false);
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
decay_expr);
if (! dynamic_cast<NetEConst*> (rise_expr)) {
cerr << get_fileline() << ": error: UDP rising delay "
"expression must be constant." << endl;
cerr << get_fileline() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
}
if (! dynamic_cast<NetEConst*> (fall_expr)) {
cerr << get_fileline() << ": error: UDP falling delay "
"expression must be constant." << endl;
cerr << get_fileline() << ": : Cannot calculate "
<< *fall_expr << endl;
des->errors += 1;
}
}
if (dynamic_cast<NetEConst*> (decay_expr)) {
} else {
cerr << get_fileline() << ": error: Delay expressions must be "
<< "constant for primitives." << endl;
cerr << get_fileline() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
}
}
assert(udp);
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
net->rise_time(rise_expr);
@ -4235,8 +4226,23 @@ class elaborate_root_scope_t : public elaborator_work_item_t {
virtual void elaborate_runrun()
{
Module::replace_t stub;
if (! rmod_->elaborate_scope(des, scope_, stub))
Module::replace_t root_repl;
for (list<Module::named_expr_t>::iterator cur = Module::user_defparms.begin()
; cur != Module::user_defparms.end() ; cur++) {
pform_name_t tmp_name = cur->first;
if (peek_head_name(tmp_name) != scope_->basename())
continue;
tmp_name.pop_front();
if (tmp_name.size() != 1)
continue;
NetExpr*tmp_expr = cur->second->elaborate_pexpr(des, scope_);
root_repl[peek_head_name(tmp_name)] = tmp_expr;
}
if (! rmod_->elaborate_scope(des, scope_, root_repl))
des->errors += 1;
}

View File

@ -122,6 +122,7 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
osig->local_flag(true);
osig->data_type(expr_type());
osig->set_signed(has_sign());
perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
@ -390,6 +391,7 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true);
connect(powr->pin_Result(), osig->pin(0));
@ -426,6 +428,7 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true);
connect(mult->pin_Result(), osig->pin(0));

View File

@ -4,7 +4,7 @@ iverilog-vpi - Compile front end for VPI modules
.SH SYNOPSIS
.B iverilog-vpi
[--name=\fIname\fP]
[\-\-name=\fIname\fP]
\fIsourcefile\fP...
.SH DESCRIPTION
@ -20,7 +20,6 @@ first source file is named \fIfoo.c\fP, the output becomes
\fIfoo.vpi\fP.
.SH OPTIONS
.l
\fIiverilog-vpi\fP accepts the following options:
.TP 8
.B -l\fIlibrary\fP
@ -104,9 +103,9 @@ requests a 32bit vpi binary instead of the default 64bit binary.
.P
Example GNU makefile that takes advantage of these flags:
.IP "" 4
CFLAGS = -Wall -O $(CFLAGS_$@)
CFLAGS = \-Wall \-O $(CFLAGS_$@)
.br
VPI_CFLAGS := $(shell iverilog-vpi --cflags)
VPI_CFLAGS := $(shell iverilog-vpi \-\-cflags)
.br
CFLAGS_messagev.o = $(VPI_CFLAGS)
.br

View File

@ -71,11 +71,11 @@ void reset_lexor();
static void line_directive();
static void line_directive2();
static verinum*make_unsized_binary(const char*txt);
static verinum*make_undef_highz_dec(const char*txt);
static verinum*make_unsized_dec(const char*txt);
static verinum*make_unsized_octal(const char*txt);
static verinum*make_unsized_hex(const char*txt);
verinum*make_unsized_binary(const char*txt);
verinum*make_undef_highz_dec(const char*txt);
verinum*make_unsized_dec(const char*txt);
verinum*make_unsized_octal(const char*txt);
verinum*make_unsized_hex(const char*txt);
static int dec_buf_div2(char *buf);
@ -667,7 +667,7 @@ void lex_end_table()
BEGIN(INITIAL);
}
static verinum*make_unsized_binary(const char*txt)
verinum*make_unsized_binary(const char*txt)
{
bool sign_flag = false;
const char*ptr = txt;
@ -725,7 +725,7 @@ static verinum*make_unsized_binary(const char*txt)
}
static verinum*make_unsized_octal(const char*txt)
verinum*make_unsized_octal(const char*txt)
{
bool sign_flag = false;
const char*ptr = txt;
@ -792,7 +792,7 @@ static verinum*make_unsized_octal(const char*txt)
}
static verinum*make_unsized_hex(const char*txt)
verinum*make_unsized_hex(const char*txt)
{
bool sign_flag = false;
const char*ptr = txt;
@ -919,7 +919,7 @@ static int dec_buf_div2(char *buf)
}
/* Support a single x, z or ? as a decimal constant (from 1364-2005). */
static verinum* make_undef_highz_dec(const char* ptr)
verinum* make_undef_highz_dec(const char* ptr)
{
bool signed_flag = false;
@ -972,7 +972,7 @@ static verinum* make_undef_highz_dec(const char* ptr)
* hard to calculate.
*/
static verinum*make_unsized_dec(const char*ptr)
verinum*make_unsized_dec(const char*ptr)
{
char buf[4096];
bool signed_flag = false;

View File

@ -115,6 +115,7 @@ bool warn_implicit = false;
bool warn_timescale = false;
bool warn_portbinding = false;
bool warn_inf_loop = false;
bool warn_ob_select = false;
bool error_implicit = false;
@ -491,6 +492,9 @@ static void read_iconfig_file(const char*ipath)
case 'l':
warn_inf_loop = true;
break;
case 's':
warn_ob_select = true;
break;
case 'p':
warn_portbinding = true;
break;
@ -528,8 +532,9 @@ static void read_iconfig_file(const char*ipath)
<< endl;
flag_errors += 1;
}
}
} else if (strcmp(buf,"defparam") == 0) {
parm_to_defparam_list(cp);
}
}
fclose(ifile);
}

View File

@ -1,3 +1,8 @@
Please NOTE:
These directions are slightly outdated and need to be updated.
The plan is to rewrite all this using the latest MinGW at
some time in the not too distant future (CR Aug. 2009)
MINGW PORT OF ICARUS VERILOG
@ -49,7 +54,7 @@ critical, but these are the versions I use.
Mingw32-5.x <http://www.mingw.org>
... including the sub-packages binutils, gcc-core and gcc-g++
if you are given the option.
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
readline-5.0-1 <http://gnuwin32.sourceforge.net>
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
@ -79,7 +84,7 @@ Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most
likely, you want to install them in c:/msys. (The msysDTK is installed
in the same location, as it is an add-on.)
This install should be easy and reliable.
The installation will leave an "msys" icon on your desktop and in the
@ -110,29 +115,6 @@ Finally, as part of installing the mingw32 compilers, remember to add
the mingw/bin directory to your path. You will need that to be able to
find the compilers later.
* Install Mingw32 Packages
There is a collection of precompiled libraries and add-on packages
that are intended for use with the Mingw32 compiler. These do not come
with simplified Windows installers, but they are pretty easy to
install by hand. Icarus Verilog uses the readline-4.2 package from
that collection.
Since I installed Mingw32 in c:\mingw, I also created a
Mingw-packages directory called c:\mingw-packages. The install, then,
is as easy as this:
<msys shell>
$ cd c:/mingw-packages
$ unzip readline-4.2-20010727.zip
[lots of inflating...]
There is no need to adjust your execution path for this package as we
are only using a library out of here. However, do remember the
directory name, as you will need it later.
Done. On to the next packages.
* Install GnuWin32 Packages
The GnuWin32 project is a collections of open source programs and
@ -148,6 +130,7 @@ You will need these gnuwin32 packages to compile Icarus Verilog:
gperf-3.0.1.exe
bison-2.1.exe
flex-2.5.4a.exe
readline-5.0-1.exe
I suggest creating a common directory for holding all your gnuwin32
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
@ -218,8 +201,8 @@ without white space.
Now, configure the source to make the makefiles and configuration
details. Run these commands:
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
$ CPPFLAGS="-Ic:/gnuwin32/include
$ LDFLAGS="-Lc:/gnuwin32/lib
$ export CPPFLAGS LDFLAGS
$ ./configure --prefix=c:/iverilog
@ -271,7 +254,8 @@ You may find that you need to put some of the prerequisite DLLs into
the d:\iverilog\bin directory. These include:
c:\mingw\bin\mingw10.dll
c:\mingw-packages\bin\libreadline.dll
c:\gnuwin32\bin\readline.dll
c:\gnuwin32\bin\history.dll
c:\gnuwin32\bin\bzip2.dll
c:\gnuwin32\bin\zlib.dll

View File

@ -395,28 +395,18 @@ NetEvent* NetScope::find_event(perm_string name)
return 0;
}
// We only add genvars to a module scope, so we do not need to search
// for the module scope here.
void NetScope::add_genvar(perm_string name, LineInfo *li)
{
assert((type_ == MODULE) || (type_ == GENBLOCK));
genvars_[name] = li;
}
LineInfo* NetScope::find_genvar(perm_string name)
{
// genvars are only added to the module so we need to find it
// if we are in a sub scope.
NetScope *scope = this;
while (scope->type() != NetScope::MODULE) {
scope = scope->parent();
assert(scope != NULL);
}
if (scope->genvars_.find(name) != scope->genvars_.end()) {
return scope->genvars_[name];
}
return 0;
if (genvars_.find(name) != genvars_.end())
return genvars_[name];
else
return 0;
}
void NetScope::add_signal(NetNet*net)

View File

@ -914,9 +914,8 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
pin(1).set_dir(Link::INPUT);
break;
case NetPartSelect::PV:
pin(0).set_dir(Link::INPUT);
pin(1).set_dir(Link::OUTPUT);
break;
/* Only a vector to part can be a variable select. */
assert(0);
}
pin(2).set_dir(Link::INPUT);
@ -2349,12 +2348,12 @@ NetNet* NetESignal::sig()
return net_;
}
unsigned NetESignal::lsi() const
long NetESignal::lsi() const
{
return net_->lsb();
}
unsigned NetESignal::msi() const
long NetESignal::msi() const
{
return net_->msb();
}

View File

@ -3829,8 +3829,8 @@ class NetESignal : public NetExpr {
const NetNet* sig() const;
NetNet* sig();
// Declared vector dimensions for the signal.
unsigned msi() const;
unsigned lsi() const;
long msi() const;
long lsi() const;
virtual ivl_variable_type_t expr_type() const;

View File

@ -77,4 +77,14 @@ extern UCDriveType uc_drive;
extern bool have_timeunit_decl;
extern bool have_timeprec_decl;
/*
* Export there functions because we have to generate PENumber class
* in pform.cc for user defparam definition from command file.
*/
extern verinum*make_unsized_dec(const char*txt);
extern verinum*make_undef_highz_dec(const char*txt);
extern verinum*make_unsized_binary(const char*txt);
extern verinum*make_unsized_octal(const char*txt);
extern verinum*make_unsized_hex(const char*txt);
#endif

188
pform.cc
View File

@ -42,6 +42,160 @@
map<perm_string,Module*> pform_modules;
map<perm_string,PUdp*> pform_primitives;
/*
* Parse configuration file with format <key>=<value>, where key
* is the hierarchical name of a valid parameter name, and value
* is the value user wants to assign to. The value should be constant.
*/
void parm_to_defparam_list(const string&param)
{
char* key;
char* value;
unsigned off = param.find('=');
if (off > param.size()) {
key = strdup(param.c_str());
value = (char*)malloc(1);
*value = '\0';
} else {
key = strdup(param.substr(0, off).c_str());
value = strdup(param.substr(off+1).c_str());
}
// Resolve hierarchical name for defparam. Remember
// to deal with bit select for generate scopes. Bit
// select expression should be constant interger.
pform_name_t name;
char *nkey = key;
char *ptr = strchr(key, '.');
while (ptr != 0) {
*ptr++ = '\0';
// Find if bit select is applied, this would be something
// like - scope[2].param = 10
char *bit_l = strchr(nkey, '[');
if (bit_l !=0) {
*bit_l++ = '\0';
char *bit_r = strchr(bit_l, ']');
if (bit_r == 0) {
cerr << "<command line>: error: missing ']' for defparam: " << nkey << endl;
free(key);
free(value);
return;
}
*bit_r = '\0';
int i = 0;
while (*(bit_l+i) != '\0')
if (!isdigit(*(bit_l+i++))) {
cerr << "<command line>: error: scope index expression is not constant: " << nkey << endl;
free(key);
free(value);
return;
}
name_component_t tmp(lex_strings.make(nkey));
index_component_t index;
index.sel = index_component_t::SEL_BIT;
verinum *seln = new verinum(atoi(bit_l));
PENumber *sel = new PENumber(seln);
index.msb = sel;
index.lsb = sel;
tmp.index.push_back(index);
name.push_back(tmp);
}
else // no bit select
name.push_back(name_component_t(lex_strings.make(nkey)));
nkey = ptr;
ptr = strchr(nkey, '.');
}
name.push_back(name_component_t(lex_strings.make(nkey)));
// Resolve value to PExpr class. Should support all kind of constant
// format including based number, dec number, real number and string.
if (*value == '"') { // string type
char *buf = strdup (value);
char *buf_ptr = buf+1;
// Parse untill another '"' or '\0'
while (*buf_ptr != '"' && *buf_ptr != '\0') {
buf_ptr++;
// Check for escape, especially '\"', which does not mean the
// end of string.
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
buf_ptr += 2;
}
if (*buf_ptr == '\0') // String end without '"'
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
cerr << buf_ptr << endl;
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
<< ". Ignore characters after \'\"\'" << endl;
}
*buf_ptr = '\0';
buf_ptr = buf+1;
// Remember to use 'new' to allocate string for PEString
// because 'delete' is used by its destructor.
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
PEString* ndec = new PEString(nchar);
Module::user_defparms.push_back( make_pair(name, ndec) );
free(buf);
}
else { // number type
char *num = strchr(value, '\'');
if (num != 0) {
verinum *val;
// BASED_NUMBER, somthing like - scope.parameter='b11
// make sure to check 'h' first because 'b'&'d' may be included
// in hex format
if (strchr(num, 'h') || strchr(num, 'H'))
val = make_unsized_hex(num);
else if (strchr(num, 'd') || strchr(num, 'D'))
if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z'))
val = make_undef_highz_dec(num);
else
val = make_unsized_dec(num);
else if (strchr(num, 'b') || strchr(num, 'B')) {
val = make_unsized_binary(num);
}
else if (strchr(num, 'o') || strchr(num, 'O'))
val = make_unsized_octal(num);
else {
cerr << "<command line>: error: value specify error for defparam: " << name << endl;
free(key);
free(value);
return;
}
// BASED_NUMBER with size, something like - scope.parameter=2'b11
if (num != value) {
*num = 0;
verinum *siz = make_unsized_dec(value);
val = pform_verinum_with_size(siz, val, "<command line>", 0);
}
PENumber* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
}
else {
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2
if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) {
verireal *val = new verireal(value);
PEFNumber* nreal = new PEFNumber(val);
Module::user_defparms.push_back( make_pair(name, nreal) );
}
else {
// DEC_NUMBER, something like - scope.parameter=3
verinum *val = make_unsized_dec(value);
PENumber* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
}
}
}
free(key);
free(value);
}
/*
* The lexor accesses the vl_* variables.
*/
@ -675,20 +829,31 @@ void pform_endmodule(const char*name, bool in_celldefine,
tp_local_flag = false;
}
static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
map<perm_string,LineInfo*>&genvars)
{
LineInfo*lni = new LineInfo();
FILE_NAME(lni, li);
if (genvars.find(name) != genvars.end()) {
cerr << lni->get_fileline() << ": error: genvar '"
<< name << "' has already been declared." << endl;
cerr << genvars[name]->get_fileline()
<< ": the previous declaration is here." << endl;
error_count += 1;
delete lni;
} else {
genvars[name] = lni;
}
}
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
{
list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) {
LineInfo*lni = new LineInfo();
FILE_NAME(lni, li);
if (pform_cur_module->genvars.find(*cur) !=
pform_cur_module->genvars.end()) {
cerr << lni->get_fileline() << ": error: duplicate "
"definition for genvar '" << *cur << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
delete lni;
} else pform_cur_module->genvars[*cur] = lni;
if (pform_cur_generate)
pform_add_genvar(li, *cur, pform_cur_generate->genvars);
else
pform_add_genvar(li, *cur, pform_cur_module->genvars);
}
delete names;
@ -703,7 +868,6 @@ void pform_start_generate_for(const struct vlltype&li,
FILE_NAME(gen, li);
// For now, assume that generates do not nest.
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
@ -724,7 +888,6 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test)
FILE_NAME(gen, li);
// For now, assume that generates do not nest.
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
@ -747,7 +910,6 @@ void pform_start_generate_else(const struct vlltype&li)
FILE_NAME(gen, li);
// For now, assume that generates do not nest.
gen->parent = pform_cur_generate;
pform_cur_generate = gen;

10
pform.h
View File

@ -195,7 +195,7 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
/*
* This function takes the list of names as new genvars to declare in
* the current module scope.
* the current module or generate scope.
*/
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
@ -410,6 +410,14 @@ extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*branch);
/*
* Parse configuration file with format <key>=<value>, where key
* is the hierarchical name of a valid parameter name and value
* is the value user wants to assign to. The value should be constant.
*/
extern void parm_to_defparam_list(const string&param);
/*
* Tasks to set the timeunit or timeprecision for SystemVerilog.
*/

View File

@ -410,6 +410,8 @@ void PDelays::dump_delays(ostream&out) const
if (delay_[0] && delay_[1] && delay_[2])
out << "#(" << *delay_[0] << "," << *delay_[1] << "," <<
*delay_[2] << ")";
else if (delay_[0] && delay_[1])
out << "#(" << *delay_[0] << "," << *delay_[1] << ")";
else if (delay_[0])
out << "#" << *delay_[0];
else
@ -1032,6 +1034,12 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2);
}
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
for (genvar_iter_t cur = genvars.begin()
; cur != genvars.end() ; cur++) {
out << setw(indent+2) << "" << "genvar " << ((*cur).first) << ";" << endl;
}
for (list<PGenerate*>::const_iterator idx = generate_schemes.begin()
; idx != generate_schemes.end() ; idx++) {
(*idx)->dump(out, indent+2);

View File

@ -1196,7 +1196,8 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
case IVL_LPM_ARRAY:
return net->u_.array.swid;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
cerr << "error: ivl_lpm_selects() is no longer supported for "
"IVL_LPM_CONCAT, use ivl_lpm_size() instead." << endl;
default:
assert(0);
return 0;
@ -1268,6 +1269,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
return net->u_.ufunc.ports - 1;
case IVL_LPM_REPEAT:
return net->u_.repeat.count;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
default:
assert(0);
return 0;

View File

@ -351,6 +351,7 @@ void dll_target::expr_select(const NetESelect*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_);
FILE_NAME(expr_, net);
expr_->type_ = IVL_EX_SELECT;
expr_->value_= IVL_VT_VECTOR;

View File

@ -2147,6 +2147,7 @@ bool dll_target::part_select(const NetPartSelect*net)
obj->type = IVL_LPM_PART_PV;
break;
}
FILE_NAME(obj, net);
obj->name = net->name(); // NetPartSelect names are permallocated.
assert(net->scope());
obj->scope = find_scope(des_, net->scope());

View File

@ -430,7 +430,7 @@ static void show_lpm_cmp_ne(ivl_lpm_t net)
}
/* IVL_LPM_CONCAT
* The concat device takes N inputs (N=ivl_lpm_selects) and generates
* The concat device takes N inputs (N=ivl_lpm_size) and generates
* a single output. The total output is known from the ivl_lpm_width
* function. The widths of all the inputs are inferred from the widths
* of the signals connected to the nexus of the inputs. The compiler
@ -444,10 +444,10 @@ static void show_lpm_concat(ivl_lpm_t net)
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net));
ivl_lpm_basename(net), width, ivl_lpm_size(net));
fprintf(out, " O: %p\n", ivl_lpm_q(net,0));
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx);
unsigned signal_width = width_of_nexus(nex);

View File

@ -1,7 +1,7 @@
/*
* VHDL code generation for expressions.
*
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -107,8 +107,10 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e)
if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) {
// Select from an array
vhdl_expr *vhd_off = translate_expr(off);
if (NULL == vhd_off)
if (NULL == vhd_off) {
delete ref;
return NULL;
}
vhdl_type integer(VHDL_TYPE_INTEGER);
ref->set_slice(vhd_off->cast(&integer));

View File

@ -1,7 +1,7 @@
/*
* VHDL code generation for LPM devices.
*
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -48,10 +48,12 @@ static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
vhdl_binop_expr *expr =
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
for (int i = ivl_lpm_selects(lpm) - 1; i >= 0; i--) {
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e)
if (NULL == e) {
delete expr;
return NULL;
}
expr->add_expr(e);
}
@ -68,8 +70,10 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
for (int i = 0; i < 2; i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e)
if (NULL == e) {
delete expr;
return NULL;
}
expr->add_expr(e->cast(result_type));
}
@ -95,8 +99,10 @@ static vhdl_expr *rel_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t
for (int i = 0; i < 2; i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e)
if (NULL == e) {
delete expr;
return NULL;
}
expr->add_expr(e);
}
@ -135,8 +141,10 @@ static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
vhdl_var_ref *ref = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == ref)
if (NULL == ref) {
delete fcall;
return NULL;
}
fcall->add_expr(ref);
}
@ -195,8 +203,10 @@ static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
vhdl_type *atype = new vhdl_type(*adecl->get_type());
vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm));
if (NULL == select)
if (NULL == select) {
delete atype;
return NULL;
}
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
vhdl_type integer(VHDL_TYPE_INTEGER);

View File

@ -95,8 +95,13 @@ int draw_process(ivl_process_t proc, void *cd)
ivl_scope_tname(scope), ivl_process_file(proc),
ivl_process_lineno(proc));
// A process should occur in a module scope, therefore it
// should have already been assigned a VHDL entity
// Skip over any generate and begin scopes until we find
// the module that contains them - this is where we will
// generate the process
while (ivl_scope_type(scope) == IVL_SCT_GENERATE
|| ivl_scope_type(scope) == IVL_SCT_BEGIN)
scope = ivl_scope_parent(scope);
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
vhdl_entity *ent = find_entity(scope);
assert(ent != NULL);

View File

@ -472,12 +472,50 @@ static void avoid_name_collision(string& name, vhdl_scope* scope)
}
}
// Concatenate the expanded genvar values together to make a unique
// instance name
// This isn't ideal: it would be better to replace the Verilog
// generate with an equivalent VHDL generate, but this isn't possible
// with the current API
static string genvar_unique_suffix(ivl_scope_t scope)
{
ostringstream suffix;
while (scope && ivl_scope_type(scope) == IVL_SCT_GENERATE) {
for (unsigned i = 0; i < ivl_scope_params(scope); i++) {
ivl_parameter_t param = ivl_scope_param(scope, i);
ivl_expr_t e = ivl_parameter_expr(param);
if (ivl_expr_type(e) == IVL_EX_NUMBER) {
vhdl_expr* value = translate_expr(e);
assert(value);
value = value->cast(vhdl_type::integer());
suffix << "_" << ivl_parameter_basename(param);
value->emit(suffix, 0);
delete value;
}
else {
error("Only numeric genvars supported at the moment");
return "_ERROR"; // Never used
}
}
scope = ivl_scope_parent(scope);
}
return suffix.str();
}
// Declare a single signal in a scope
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig)
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
ivl_scope_t scope)
{
remember_signal(sig, ent->get_arch()->get_scope());
string name(make_safe_name(sig));
name += genvar_unique_suffix(scope);
avoid_name_collision(name, ent->get_arch()->get_scope());
rename_signal(sig, name);
@ -586,14 +624,14 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) != IVL_SIP_NONE)
declare_one_signal(ent, sig);
declare_one_signal(ent, sig, scope);
}
for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
declare_one_signal(ent, sig);
declare_one_signal(ent, sig, scope);
}
}
@ -873,9 +911,6 @@ static int draw_skeleton_scope(ivl_scope_t scope, void *_unused)
case IVL_SCT_MODULE:
create_skeleton_entity_for(scope, depth);
break;
case IVL_SCT_GENERATE:
error("No translation for generate statements yet");
return 1;
case IVL_SCT_FORK:
error("No translation for fork statements yet");
return 1;
@ -901,6 +936,20 @@ static int draw_all_signals(ivl_scope_t scope, void *_parent)
declare_signals(ent, scope);
}
else if (ivl_scope_type(scope) == IVL_SCT_GENERATE) {
// Because generate scopes don't appear in the
// output VHDL all their signals are added to the
// containing entity (after being uniqued)
ivl_scope_t parent = ivl_scope_parent(scope);
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(scope);
vhdl_entity* ent = find_entity(parent);
assert(ent);
declare_signals(ent, scope);
}
return ivl_scope_children(scope, draw_all_signals, scope);
}
@ -1032,6 +1081,10 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
// Skip over any containing generate scopes
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(parent);
if (!is_default_scope_instance(parent))
return 0; // Not generating code for the parent instance so
// don't generate for the child
@ -1054,6 +1107,7 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
// And an instantiation statement
string inst_name(ivl_scope_basename(scope));
inst_name += genvar_unique_suffix(ivl_scope_parent(scope));
if (inst_name == ent->get_name() || parent_scope->have_declared(inst_name)) {
// Cannot have instance name the same as type in VHDL
inst_name += "_Inst";

View File

@ -170,8 +170,12 @@ vhdl_entity* find_entity(const string& name)
// name should be the same as the Verilog module type name.
// Note that this will return NULL if no entity has been recorded
// for this scope type.
vhdl_entity* find_entity(const ivl_scope_t scope)
vhdl_entity* find_entity(ivl_scope_t scope)
{
// Skip over generate scopes
while (ivl_scope_type(scope) == IVL_SCT_GENERATE)
scope = ivl_scope_parent(scope);
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));

View File

@ -39,7 +39,7 @@ ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope)
// Manage the set of VHDL entities
void remember_entity(vhdl_entity *ent, ivl_scope_t scope);
vhdl_entity* find_entity(const ivl_scope_t scope);
vhdl_entity* find_entity(ivl_scope_t scope);
vhdl_entity* find_entity(const std::string& name);
void emit_all_entities(std::ostream& os, int max_depth);
void free_all_vhdl_objects();

View File

@ -313,11 +313,11 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
if (NULL == test)
return;
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
return;
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
// True part
{
vhdl_abstract_assign_stmt *a =
@ -1342,6 +1342,7 @@ int draw_casezx(vhdl_procedural *proc, stmt_container *container,
"expression labels can be translated to VHDL",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
(is_casez ? "z" : "x"));
delete all;
return 1;
}

View File

@ -48,6 +48,11 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
if (number_is_immediate(d_rise, 64, 0) &&
number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 64, 0)) {
assert( ! number_is_unknown(d_rise));
assert( ! number_is_unknown(d_fall));
assert( ! number_is_unknown(d_decay));
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise),
get_number_immediate(d_fall),

View File

@ -388,6 +388,10 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 64, 0)) {
assert(! number_is_unknown(d_rise));
assert(! number_is_unknown(d_fall));
assert(! number_is_unknown(d_decay));
fprintf(vvp_out, "L_%p .delay "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
cptr, get_number_immediate64(d_rise),

View File

@ -109,6 +109,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
if (word_ex) {
/* Some array select have been evaluated. */
if (number_is_immediate(word_ex,IMM_WID, 0)) {
assert(! number_is_unknown(word_ex));
use_word = get_number_immediate(word_ex);
word_ex = 0;
}
@ -130,6 +131,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
if (word_ex) {
/* Some array select have been evaluated. */
if (number_is_immediate(word_ex, IMM_WID, 0)) {
assert(! number_is_unknown(word_ex));
use_word = get_number_immediate(word_ex);
use_word_defined = 1;
word_ex = 0;
@ -185,6 +187,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
/* This is a constant bit/part select. */
if (number_is_immediate(bexpr, 64, 1)) {
assert(! number_is_unknown(bexpr));
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
ivl_expr_signal(vexpr),
get_number_immediate(bexpr),
@ -206,9 +209,19 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
return 0;
}
} else {
/* Fallback case: evaluate the expression. */
/* Fallback case: evaluate the expression. */
struct vector_info rv;
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
/* We need to enhance &PV<> to support a signed index. */
if (ivl_expr_signed(bexpr) &&
(ivl_expr_width(bexpr) < 8*sizeof(int))) {
fprintf(stderr, "%s:%u: tgt-vvp warning: V0.9 may give "
"incorrect results for a select with a "
"signed index less than %d bits.\n",
ivl_expr_file(expr),
ivl_expr_lineno(expr),
8*sizeof(int));
}
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
ivl_expr_signal(vexpr),
rv.base, rv.wid,

View File

@ -174,6 +174,12 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
case IVL_EX_ULONG:
{
assert(number_is_immediate(expr, IMM_WID, 1));
if (number_is_unknown(expr)) {
/* We are loading a 'bx so mimic %ix/get. */
fprintf(vvp_out, " %%ix/load %u, 0, 0;\n", ix);
fprintf(vvp_out, " %%mov 4, 1, 1;\n");
break;
}
long imm = get_number_immediate(expr);
if (imm >= 0) {
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", ix, imm);
@ -192,6 +198,7 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
unsigned word = 0;
if (ivl_signal_dimensions(sig) > 0) {
ivl_expr_t ixe;
char*type = ivl_expr_signed(expr) ? "/s" : "";
/* Detect the special case that this is a
variable array. In this case, the ix/getv
@ -199,20 +206,21 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
if (ivl_signal_type(sig) == IVL_SIT_REG) {
struct vector_info rv;
rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, rv.base, rv.wid);
fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
type, ix, rv.base, rv.wid);
clr_vector(rv);
break;
}
ixe = ivl_expr_oper1(expr);
if (number_is_immediate(ixe, IMM_WID, 0))
if (number_is_immediate(ixe, IMM_WID, 0)) {
assert(! number_is_unknown(ixe));
word = get_number_immediate(ixe);
else {
} else {
struct vector_info rv;
rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, rv.base, rv.wid);
fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
type, ix, rv.base, rv.wid);
clr_vector(rv);
break;
}
@ -226,8 +234,14 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
default: {
struct vector_info rv;
rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, rv.base, rv.wid);
/* Is this a signed expression? */
if (ivl_expr_signed(expr)) {
fprintf(vvp_out, " %%ix/get/s %u, %u, %u;\n",
ix, rv.base, rv.wid);
} else {
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, rv.base, rv.wid);
}
clr_vector(rv);
break;
}
@ -274,7 +288,10 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
{
unsigned wid;
struct vector_info lv;
unsigned long imm = get_number_immediate(re);
unsigned long imm;
assert(number_is_immediate(re, IMM_WID, 0));
assert(! number_is_unknown(re));
imm = get_number_immediate(re);
wid = ivl_expr_width(le);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
@ -991,6 +1008,8 @@ static struct vector_info draw_logic_immediate(ivl_expr_t exp,
unsigned wid)
{
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(number_is_immediate(re, IMM_WID, 0));
assert(! number_is_unknown(re));
unsigned long imm = get_number_immediate(re);
assert(lv.base >= 4);
@ -1241,8 +1260,10 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le,
int signed_flag)
{
struct vector_info lv;
long imm = get_number_immediate(re);
long imm;
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 1));
imm = get_number_immediate(re);
lv.base = allocate_vector(wid);
lv.wid = wid;
if (lv.base == 0) {
@ -1270,6 +1291,8 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 0));
imm = get_number_immediate(re);
/* This shouldn't generally happen, because the elaborator
@ -1308,7 +1331,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
}
break;
case 2: /* Left expression is X or Z */
case 2: /* Left expression is 'bx or 'bz */
case 3:
lv.base = 2;
break;
@ -1335,6 +1358,8 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 0));
imm = get_number_immediate(re);
if (imm == 0)
return lv;
@ -1379,6 +1404,8 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 0));
imm = get_number_immediate(re);
if (imm == 0)
return lv;
@ -2253,7 +2280,7 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
unsigned bit_width,
unsigned wid)
{
unsigned idx;
unsigned idx, label;
ivl_signal_t sig = ivl_expr_signal(sube);
/* unsigned sig_wid = ivl_expr_width(sube); */
ivl_expr_t ix = ivl_expr_oper1(sube);
@ -2263,7 +2290,18 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
draw_eval_expr_into_integer(ix, 3);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
label = local_count++;
/* We can safely skip the bit index load below if the array word
* index is undefined. We need to do this so that the bit index
* load does not reset bit 4 to zero by loading a defined value. */
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, label);
if (ivl_expr_signed(bit_idx)) {
fprintf(vvp_out, " %%ix/get/s 0, %u, %u;\n", shiv.base,
shiv.wid);
} else {
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
}
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, label);
if (shiv.base >= 8)
clr_vector(shiv);
@ -2294,7 +2332,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
/* Use this word of the signal. */
unsigned use_word = 0;
unsigned use_wid;
unsigned use_wid, lab_x, lab_end;
/* If this is an access to an array, try to get the index as a
constant. If it is (and the array is not a reg array then
@ -2311,6 +2349,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
/* The index is constant, so we can return to direct
readout with the specific word selected. */
assert(! number_is_unknown(ix));
use_word = get_number_immediate(ix);
}
@ -2318,6 +2357,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
the signal (or the entire width). Just load the early bits
in one go. */
if (number_is_immediate(bit_idx, 32, 0)
&& !number_is_unknown(bit_idx)
&& get_number_immediate(bit_idx) == 0
&& (ivl_expr_width(sube) >= bit_wid)) {
@ -2343,6 +2383,12 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
res.wid = wid;
assert(res.base);
lab_x = local_count++;
lab_end = local_count++;
/* If the index is 'bx then we just return 'bx. */
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_x);
use_wid = res.wid;
if (use_wid > bit_wid)
use_wid = bit_wid;
@ -2353,6 +2399,11 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
fprintf(vvp_out, " %%movi %u, 0, %u;\n",
res.base + use_wid, res.wid - use_wid);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_end);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_x);
fprintf(vvp_out, " %%mov %u, 2, %u;\n", res.base, res.wid);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_end);
return res;
}
@ -2371,6 +2422,7 @@ static void draw_select_signal_dest(ivl_expr_t sube,
if ((ivl_signal_dimensions(sig) == 0)
&& (ivl_expr_width(sube) >= dest.wid)
&& number_is_immediate(bit_idx, 32, 0)
&& ! number_is_unknown(bit_idx)
&& get_number_immediate(bit_idx) == 0) {
unsigned use_word = 0;
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Select %u out of %u bits\n",
@ -2401,6 +2453,8 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
ivl_expr_t shift = ivl_expr_oper2(exp);
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
int cmp;
unsigned lab_l, lab_end;
res.wid = wid;
@ -2444,7 +2498,12 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
return res;
}
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
if (ivl_expr_signed(shift)) {
fprintf(vvp_out, " %%ix/get/s 0, %u, %u;\n", shiv.base,
shiv.wid);
} else {
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
}
clr_vector(shiv);
/* If the subv result is a magic constant, then make a copy in
@ -2458,7 +2517,27 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
subv = res;
}
lab_l = local_count++;
lab_end = local_count++;
/* If we have an undefined index then just produce a 'bx result. */
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_l);
cmp = allocate_word();
assert(subv.wid >= wid);
/* Determine if we need to shift a 'bx into the top. */
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", cmp, subv.wid - wid);
fprintf(vvp_out, " %%cmp/ws %u, 0;\n", cmp);
clr_word(cmp);
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 5;\n", thread_count, lab_l);
/* Clear the cmp bit if the two values are equal. */
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", subv.base, subv.wid);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_end);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_l);
/* Multiply by -1. */
fprintf(vvp_out, " %%ix/mul 0, %u, %u;\n", 0xFFFFFFFF, 0xFFFFFFFF);
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", subv.base, subv.wid);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_end);
if (subv.wid > wid) {
res.base = subv.base;

View File

@ -87,7 +87,8 @@ static void set_to_lvariable(ivl_lval_t lval,
if (part_off_ex == 0) {
part_off = 0;
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
} else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
!number_is_unknown(part_off_ex)) {
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
@ -96,6 +97,7 @@ static void set_to_lvariable(ivl_lval_t lval,
it to select the word, and pay no further heed to the
expression itself. */
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
assert(! number_is_unknown(word_ix));
use_word = get_number_immediate(word_ix);
word_ix = 0;
}
@ -222,6 +224,63 @@ static void set_to_lvariable(ivl_lval_t lval,
}
}
/* Support a non-blocking assignment to a real array word. */
static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
unsigned bit, uint64_t delay,
ivl_expr_t dexp, unsigned nevents)
{
unsigned skip_assign = transient_id++;
/* This code is common to all the different types of array delays. */
if (number_is_immediate(word_ix, IMM_WID, 0)) {
assert(! number_is_unknown(word_ix));
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
get_number_immediate(word_ix));
} else {
/* Calculate array word index into index register 3 */
draw_eval_expr_into_integer(word_ix, 3);
/* Skip assignment if word expression is not defined. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
}
if (dexp != 0) {
/* Calculated delay... */
int delay_index = allocate_word();
draw_eval_expr_into_integer(dexp, delay_index);
fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig,
delay_index, bit);
clr_word(delay_index);
} else if (nevents != 0) {
/* Event control delay... */
fprintf(vvp_out, " %%assign/ar/e v%p, %u;\n", lsig, bit);
} else {
/* Constant delay... */
unsigned long low_d = delay % UINT64_C(0x100000000);
unsigned long hig_d = delay / UINT64_C(0x100000000);
/*
* The %assign can only take a 32 bit delay. For a larger
* delay we need to put it into an index register.
*/
if (hig_d != 0) {
int delay_index = allocate_word();
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
delay_index, low_d, hig_d);
fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig,
delay_index, bit);
clr_word(delay_index);
} else {
fprintf(vvp_out, " %%assign/ar v%p, %lu, %u;\n",
lsig, low_d, bit);
}
}
fprintf(vvp_out, "t_%u ;\n", skip_assign);
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
clear_expression_lookaside();
}
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
unsigned bit, uint64_t delay, ivl_expr_t dexp,
ivl_expr_t part_off_ex, unsigned width,
@ -233,12 +292,14 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
if (part_off_ex == 0) {
part_off = 0;
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
/* This code is common to all the different types of array delays. */
if (number_is_immediate(word_ix, IMM_WID, 0)) {
assert(! number_is_unknown(word_ix));
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
get_number_immediate(word_ix));
} else {
@ -317,6 +378,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
if (part_off_ex == 0) {
part_off = 0;
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
@ -643,13 +705,6 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
sig = ivl_lval_sig(lval);
assert(sig);
if (ivl_signal_dimensions(sig) > 0) {
word_ix = ivl_lval_idx(lval);
assert(word_ix);
assert(number_is_immediate(word_ix, IMM_WID, 0));
use_word = get_number_immediate(word_ix);
}
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
assert(number_is_immediate(del, 64, 0));
delay = ivl_expr_delay_val(del);
@ -659,6 +714,14 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
/* Evaluate the r-value */
word = draw_eval_real(rval);
if (ivl_signal_dimensions(sig) > 0) {
word_ix = ivl_lval_idx(lval);
assert(word_ix);
assign_to_array_r_word(sig, word_ix, word, delay, del, nevents);
clr_word(word);
return 0;
}
/* We need to calculate the delay expression. */
if (del) {
assert(nevents == 0);
@ -1105,11 +1168,13 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
part_off = 0;
} else {
assert(number_is_immediate(part_off_ex, IMM_WID, 0));
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex);
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, IMM_WID, 0));
assert(! number_is_unknown(word_idx));
use_word = get_number_immediate(word_idx);
}
@ -1174,6 +1239,7 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
* part select (this could give us multiple drivers). */
part_off_ex = ivl_lval_part_off(lval);
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
// Do we need checks for number_is{immediate,unknown} of part_of_ex?
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to "
"a bit/part select.\n", ivl_expr_file(rval),
@ -1184,11 +1250,13 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
/* At least for now, only handle force to fixed words of an array. */
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
assert(number_is_immediate(lword_idx, IMM_WID, 0));
assert(! number_is_unknown(lword_idx));
use_lword = get_number_immediate(lword_idx);
}
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
assert(number_is_immediate(rword_idx, IMM_WID, 0));
assert(! number_is_unknown(rword_idx));
use_rword = get_number_immediate(rword_idx);
}
@ -1272,11 +1340,13 @@ static int show_stmt_deassign(ivl_statement_t net)
part_off = 0;
if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64, 0));
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex);
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, IMM_WID, 0));
assert(! number_is_unknown(word_idx));
use_word = get_number_immediate(word_idx);
}
@ -1567,6 +1637,7 @@ static int show_stmt_release(ivl_statement_t net)
part_off = 0;
if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64, 0));
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex);
}
@ -1581,6 +1652,7 @@ static int show_stmt_release(ivl_statement_t net)
if (word_idx != 0) {
assert(number_is_immediate(word_idx, IMM_WID, 0));
assert(! number_is_unknown(word_idx));
use_word = get_number_immediate(word_idx);
}

View File

@ -558,6 +558,9 @@ static void draw_delay(ivl_net_logic_t lptr)
assert(number_is_immediate(d0, 64, 0));
assert(number_is_immediate(d1, 64, 0));
assert(number_is_immediate(d2, 64, 0));
assert(! number_is_unknown(d0));
assert(! number_is_unknown(d1));
assert(! number_is_unknown(d2));
if (d0 == d1 && d1 == d2)
fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
@ -615,6 +618,8 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
static ivl_udp_t *udps = 0x0;
static int nudps = 0;
int i;
unsigned ninp;
const char **input_strings;
for (i=0; i<nudps; i++)
if (udps[i] == udp)
@ -628,26 +633,38 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
draw_udp_def(udp);
}
fprintf(vvp_out, "L_%p .udp", lptr);
fprintf(vvp_out, " UDP_%s",
vvp_mangle_id(ivl_udp_name(udp)));
draw_delay(lptr);
for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx);
/*
* We need to process the arguments first so any evaluation code
* (.resolv, etc.) can be built before we build the .udp call.
* This matches what is done for the other primitives.
*/
ninp = ivl_logic_pins(lptr) - 1;
input_strings = calloc(ninp, sizeof(char*));
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
/* Unlike other logic gates, primitives may have unconnected
inputs. The proper behavior is to attach a HiZ to the
port. */
if (nex == 0) {
assert(ivl_logic_width(lptr) == 1);
fprintf(vvp_out, ", C4<z>");
input_strings[pdx] = "C4<z>";
} else {
fprintf(vvp_out, ", %s", draw_net_input(nex));
input_strings[pdx] = draw_net_input(nex);
}
}
fprintf(vvp_out, "L_%p .udp", lptr);
fprintf(vvp_out, " UDP_%s",
vvp_mangle_id(ivl_udp_name(udp)));
draw_delay(lptr);
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
fprintf(vvp_out, ", %s", input_strings[pdx]);
}
free(input_strings);
fprintf(vvp_out, ";\n");
}
@ -805,7 +822,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
level = 0;
ninp = ivl_logic_pins(lptr) - 1;
while (ninp) {
int inst;
for (inst = 0; inst < ninp; inst += 4) {
@ -861,6 +877,9 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
&& number_is_immediate(fall_exp,64,0)
&& number_is_immediate(decay_exp,64,0)) {
assert(! number_is_unknown(rise_exp));
assert(! number_is_unknown(fall_exp));
assert(! number_is_unknown(decay_exp));
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
lptr, get_number_immediate(rise_exp),
get_number_immediate(fall_exp),
@ -1066,6 +1085,9 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net)
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
assert(! number_is_unknown(d_rise));
assert(! number_is_unknown(d_fall));
assert(! number_is_unknown(d_decay));
dly = "/d";
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise),
@ -1322,7 +1344,7 @@ static unsigned lpm_concat_inputs(ivl_lpm_t net, unsigned start,
static void draw_lpm_concat(ivl_lpm_t net)
{
const char*src_table[4];
unsigned icnt = ivl_lpm_selects(net);
unsigned icnt = ivl_lpm_size(net);
const char*dly = draw_lpm_output_delay(net);
if (icnt <= 4) {

View File

@ -1127,9 +1127,15 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8 *name)
val.format = vpiIntVal;
vpi_get_value(arg, &val);
fd_mcd = val.value.integer;
/* If the MCD is zero we have nothing to do so just return. */
if (fd_mcd == 0) {
vpi_free_object(argv);
return 0;
}
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF) ||
(! fd_mcd)) {
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given "
@ -1241,9 +1247,15 @@ static PLI_INT32 sys_strobe_calltf(PLI_BYTE8*name)
val.format = vpiIntVal;
vpi_get_value(arg, &val);
fd_mcd = val.value.integer;
/* If the MCD is zero we have nothing to do so just return. */
if (fd_mcd == 0) {
vpi_free_object(argv);
return 0;
}
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF) ||
(! fd_mcd)) {
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given "

View File

@ -153,10 +153,13 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
}
fname = get_filename(callh, name, fileh);
if (fname == 0 && mode) free(mode_string);
/* If either the mode or file name are not valid just return. */
if (fail || fname == 0) return 0;
if (fail || fname == 0) {
free(fname);
if (mode) free(mode_string);
return 0;
}
val.format = vpiIntVal;
if (mode) {
@ -267,6 +270,9 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
vpi_get_value(arg, &val);
fd_mcd = val.value.integer;
/* If the MCD is zero we have nothing to do so just return. */
if (fd_mcd == 0) return 0;
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF) ||
(! fd_mcd)) {

View File

@ -293,7 +293,10 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
if (process_params(mitem, start_item, stop_item, callh, name,
&start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0;
&min_addr, &max_addr)) {
free(fname);
return 0;
}
/* Open the data file. */
file = fopen(fname, "r");
@ -528,7 +531,10 @@ static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
if (process_params(mitem, start_item, stop_item, callh, name,
&start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0;
&min_addr, &max_addr)) {
free(fname);
return 0;
}
/* Open the data file. */
file = fopen(fname, "w");

View File

@ -626,6 +626,7 @@ static PLI_INT32 sys_fscanf_compiletf(PLI_BYTE8*name)
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's first argument (fd) must be numeric.\n", name);
vpi_control(vpiFinish, 1);
vpi_free_object(argv);
return 0;
}
@ -695,6 +696,7 @@ static PLI_INT32 sys_sscanf_compiletf(PLI_BYTE8*name)
vpi_printf("%s's first argument must be a register or constant "
"string.\n", name);
vpi_control(vpiFinish, 1);
vpi_free_object(argv);
return 0;
}

View File

@ -805,6 +805,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
vpi_printf("VCD warning: skipping signal %s, "
"it was previously included.\n",
fullname);
free(scname);
continue;
} else {
add_var = 1;

View File

@ -184,6 +184,7 @@ static PLI_INT32 va_single_argument_compiletf(PLI_BYTE8 *ud)
/* Check that there are arguments. */
if (argv == 0) {
va_error_message(callh, "%s requires one argument.\n", name);
free(fun_data);
return 0;
}
@ -265,6 +266,7 @@ static PLI_INT32 va_double_argument_compiletf(PLI_BYTE8 *ud)
/* Check that there are arguments. */
if (argv == 0) {
va_error_message(callh, "%s requires two arguments.\n", name);
free(fun_data);
return 0;
}

View File

@ -216,6 +216,7 @@ static PLI_INT32 va_single_argument_compiletf(PLI_BYTE8 *ud)
/* Check that there are arguments. */
if (argv == 0) {
va_error_message(callh, "%s requires one argument.\n", name);
free(fun_data);
return 0;
}
@ -303,6 +304,7 @@ static PLI_INT32 va_double_argument_compiletf(PLI_BYTE8 *ud)
/* Check that there are arguments. */
if (argv == 0) {
va_error_message(callh, "%s requires two arguments.\n", name);
free(fun_data);
return 0;
}

View File

@ -1,7 +1,7 @@
#ifndef __codes_H
#define __codes_H
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -40,6 +40,9 @@ extern bool of_ALLOC(vthread_t thr, vvp_code_t code);
extern bool of_AND(vthread_t thr, vvp_code_t code);
extern bool of_ANDI(vthread_t thr, vvp_code_t code);
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t code);

View File

@ -87,6 +87,9 @@ const static struct opcode_table_s opcode_table[] = {
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%assign/ar",of_ASSIGN_AR,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/ar/d",of_ASSIGN_ARD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/ar/e",of_ASSIGN_ARE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/av/e",of_ASSIGN_AVE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },

1364
vvp/config.guess vendored

File diff suppressed because it is too large Load Diff

1457
vvp/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@ -140,6 +140,7 @@ vvp_fun_delay::vvp_fun_delay(vvp_net_t*n, vvp_bit4_t init, const vvp_delay_t&d)
cur_vec8_ = vvp_vector8_t(cur_vec4_, 6, 6);
cur_real_ = 0.0;
list_ = 0;
type_ = UNKNOWN_DELAY;
initial_ = true;
// Calculate the values used when converting variable delays
// to simulation time units.
@ -160,10 +161,48 @@ vvp_fun_delay::~vvp_fun_delay()
delete cur;
}
bool vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay,
const vvp_vector4_t&bit)
{
if (list_ == 0) return false;
/* If the most recent event and the new event have the same
* value then we need to skip the new event. */
if (list_->next->ptr_vec4.eeq(bit)) return true;
clean_pulse_events_(use_delay);
return false;
}
bool vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay,
const vvp_vector8_t&bit)
{
if (list_ == 0) return false;
/* If the most recent event and the new event have the same
* value then we need to skip the new event. */
if (list_->next->ptr_vec8.eeq(bit)) return true;
clean_pulse_events_(use_delay);
return false;
}
bool vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay,
double bit)
{
if (list_ == 0) return false;
/* If the most recent event and the new event have the same
* value then we need to skip the new event. */
if (list_->next->ptr_real == bit) return true;
clean_pulse_events_(use_delay);
return false;
}
void vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay)
{
if (list_ == 0)
return;
assert(list_ != 0);
do {
struct event_*cur = list_->next;
@ -219,6 +258,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
/* This is an initial value so it needs to be compared to all the
bits (the order the bits are changed is not deterministic). */
if (initial_) {
type_ = VEC4_DELAY;
vvp_bit4_t cur_val = cur_vec4_.value(0);
use_delay = delay_.get_delay(cur_val, bit.value(0));
for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) {
@ -227,6 +267,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
if (tmp > use_delay) use_delay = tmp;
}
} else {
assert(type_ == VEC4_DELAY);
/* How many bits to compare? */
unsigned use_wid = cur_vec4_.size();
@ -246,7 +287,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
/* what *should* happen here is we check to see if there is a
transaction in the queue. This would be a pulse that needs to be
eliminated. */
clean_pulse_events_(use_delay);
if (clean_pulse_events_(use_delay, bit)) return;
vvp_time64_t use_simtime = schedule_simtime() + use_delay;
@ -273,6 +314,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
/* This is an initial value so it needs to be compared to all the
bits (the order the bits are changed is not deterministic). */
if (initial_) {
type_ = VEC8_DELAY;
vvp_bit4_t cur_val = cur_vec8_.value(0).value();
use_delay = delay_.get_delay(cur_val, bit.value(0).value());
for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) {
@ -281,6 +323,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
if (tmp > use_delay) use_delay = tmp;
}
} else {
assert(type_ == VEC8_DELAY);
/* How many bits to compare? */
unsigned use_wid = cur_vec8_.size();
@ -302,7 +345,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
/* what *should* happen here is we check to see if there is a
transaction in the queue. This would be a pulse that needs to be
eliminated. */
clean_pulse_events_(use_delay);
if (clean_pulse_events_(use_delay, bit)) return;
vvp_time64_t use_simtime = schedule_simtime() + use_delay;
@ -351,11 +394,14 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
return;
}
if (initial_) type_ = REAL_DELAY;
else assert(type_ == REAL_DELAY);
vvp_time64_t use_delay;
use_delay = delay_.get_min_delay();
/* Eliminate glitches. */
clean_pulse_events_(use_delay);
if (clean_pulse_events_(use_delay, bit)) return;
/* This must be done after cleaning pulses to avoid propagating
* an incorrect value. */

View File

@ -71,6 +71,7 @@ class vvp_delay_t {
*/
class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
enum delay_type_t {UNKNOWN_DELAY, VEC4_DELAY, VEC8_DELAY, REAL_DELAY};
struct event_ {
event_(vvp_time64_t s) : sim_time(s) { }
void (vvp_fun_delay::*run_run_ptr)(struct vvp_fun_delay::event_*cur);
@ -103,6 +104,7 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
private:
vvp_net_t*net_;
vvp_delay_t delay_;
delay_type_t type_;
bool initial_; // Indicates if the value is still the initial value.
vvp_vector4_t cur_vec4_;
@ -133,6 +135,10 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
list_->next = cur->next;
return cur;
}
bool clean_pulse_events_(vvp_time64_t use_delay, const vvp_vector4_t&bit);
bool clean_pulse_events_(vvp_time64_t use_delay, const vvp_vector8_t&bit);
bool clean_pulse_events_(vvp_time64_t use_delay, double bit);
// Delete this when done!
void clean_pulse_events_(vvp_time64_t use_delay);
};

View File

@ -159,6 +159,32 @@ void schedule_evctl(vvp_array_t memory, unsigned index,
ep->last = &((*(ep->last))->next);
}
evctl_array_r::evctl_array_r(vvp_array_t memory, unsigned index,
double value, unsigned long ecount)
:evctl(ecount)
{
mem_ = memory;
idx_ = index;
value_ = value;
}
void evctl_array_r::run_run()
{
array_set_word(mem_, idx_, value_);
}
void schedule_evctl(vvp_array_t memory, unsigned index,
double value,
vvp_net_t*event, unsigned long ecount)
{
// Get the functor we are going to wait on.
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
assert(ep);
// Now add this call to the end of the event list.
*(ep->last) = new evctl_array_r(memory, index, value, ecount);
ep->last = &((*(ep->last))->next);
}
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
{
return 1 << ((from << 2) | to);

View File

@ -81,6 +81,20 @@ class evctl_array : public evctl {
unsigned off_;
};
class evctl_array_r : public evctl {
public:
explicit evctl_array_r(vvp_array_t memory, unsigned index,
double value, unsigned long ecount);
virtual ~evctl_array_r() {}
virtual void run_run();
private:
vvp_array_t mem_;
unsigned idx_;
double value_;
};
extern void schedule_evctl(struct __vpiHandle*handle, double value,
vvp_net_t*event, unsigned long ecount);
@ -92,6 +106,10 @@ extern void schedule_evctl(vvp_array_t memory, unsigned index,
const vvp_vector4_t&value, unsigned offset,
vvp_net_t*event, unsigned long ecount);
extern void schedule_evctl(vvp_array_t memory, unsigned index,
double value,
vvp_net_t*event, unsigned long ecount);
/*
* Event / edge detection functors
*/

View File

@ -1,238 +0,0 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

View File

@ -422,6 +422,8 @@ int main(int argc, char*argv[])
count_assign_real_pool());
vpi_mcd_printf(1, " ...assign(word) pool=%lu\n",
count_assign_aword_pool());
vpi_mcd_printf(1, " ...assign(word/r) pool=%lu\n",
count_assign_arword_pool());
vpi_mcd_printf(1, " %8lu other events (pool=%lu)\n",
count_gen_events, count_gen_pool());
}

View File

@ -65,6 +65,26 @@ means the following:
1 and 1 --> 1
otherwise x
* %assign/ar <array-label>, <delay>, <bit>
* %assign/ar/d <array-label>, <delayx>, <bit>
* %assign/ar/e <array-label>, <bit>
The %assign/ar instruction assigns a real value to a word in the
labeled real array. The <delay> is the delay in simulation time to
the assignment (0 for non-blocking assignment) and <bit> is the
index register that contains the value to write.
The memory word address is read from index register 3. The address is
in canonical form.
The %assign/ar/d variation reads the delay from an integer register that
is given by the <delayx> value. This should not be 3 or the <bit> index,
of course, since these registers contain the word address and the value.
The %assign/ar/e variation uses the information in the thread
event control registers to determine when to perform the assign.
%evctl is used to set the event control information.
* %assign/av <array-label>, <delay>, <bit>
* %assign/av/d <array-label>, <delayx>, <bit>
* %assign/av/e <array-label>, <bit>
@ -417,7 +437,7 @@ These instructions are like the %ix/get instructions, except that they
read directly from a functor label instead of from thread bits. They
set bit 4 just like %ix/get.
* %ix/load <idx>, <low> <high>
* %ix/load <idx>, <low>, <high>
This instruction loads an immediate value into the addressed index
register. The index register holds signed 64 bit numeric values, so
@ -428,9 +448,9 @@ vector. The values are unsigned decimal values and are combined as
<high> << 32 | <low> to produce the final value.
* %ix/add <idx>, <low> <high>
* %ix/sub <idx>, <low> <high>
* %ix/mul <idx>, <low> <high>
* %ix/add <idx>, <low>, <high>
* %ix/sub <idx>, <low>, <high>
* %ix/mul <idx>, <low>, <high>
These instructions add, subtract, or multiply the selected index
register by the immediate value. The 64 bit immediate value is built
@ -491,7 +511,8 @@ vector is sign extended (instead of 0-extended) before the addition.
This instruction is similar to %load/av, but it loads only a single
bit, and the <index> is the selector for the bit to use. If <index> is
out of range, then x is loaded.
out of range, then x is loaded. The index value is incremented by one
if it is defined (bit 4 is not 1).
* %load/v <bit>, <functor-label>, <wid>
@ -758,6 +779,8 @@ bits) by the amount in index register 0. The <bit> is the address of
the LSB of the vector, and <wid> the width of the vector. The shift is
done in place. Zero values are shifted in.
For a negative shift the value is padded with 'bx.
* %shiftr/i0 <bit>, <wid>
* %shiftr/s/i0 <bit>, <wid>
@ -769,6 +792,8 @@ shift is done in place.
%shiftr/i0 is an unsigned down shift, so zeros are shifted into the
top bits. %shiftr/s/i0 is a signed shift, so the value is sign-extended.
For a negative shift %shiftr/i0 will pad the value with 'bx.
* %sub <bit-l>, <bit-r>, <wid>
This instruction arithmetically subtracts the right vector out of the
@ -846,7 +871,7 @@ and leaves the result in the <dst> vector. xor is this:
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU

View File

@ -86,11 +86,8 @@ void vvp_fun_part_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
{
assert(bit.size() == wid);
vvp_vector4_t tmp = val_;
if (tmp.size() == 0)
tmp = vvp_vector4_t(vwid);
assert(tmp.size() == vwid);
vvp_vector4_t tmp (vwid, BIT4_Z);
tmp.set_vec(base_, val_);
tmp.set_vec(base, bit);
recv_vec4(port, tmp, 0);
}
@ -178,11 +175,8 @@ void vvp_fun_part_aa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
(vvp_get_context_item(context, context_idx_));
vvp_vector4_t tmp = *val;
if (tmp.size() == 0)
tmp = vvp_vector4_t(vwid);
assert(tmp.size() == vwid);
vvp_vector4_t tmp (vwid, BIT4_Z);
tmp.set_vec(base_, *val);
tmp.set_vec(base, bit);
recv_vec4(port, tmp, context);
} else {
@ -244,17 +238,20 @@ vvp_fun_part_var::~vvp_fun_part_var()
}
bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
unsigned&base, vvp_vector4_t&source,
long&base, vvp_vector4_t&source,
vvp_vector4_t&ref)
{
unsigned long tmp;
long tmp;
switch (port.port()) {
case 0:
source = bit;
break;
case 1:
tmp = ULONG_MAX;
vector4_to_value(bit, tmp);
// LONG_MIN is before the vector and is used to
// represent a 'bx value on the select input.
tmp = LONG_MIN;
// We need a new &PV<> that knows if the index is signed.
vector4_to_value(bit, tmp, false);
if (tmp == base) return false;
base = tmp;
break;
@ -267,11 +264,11 @@ bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_vector4_t res (wid_);
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
unsigned adr = base+idx;
if (adr >= source.size())
break;
long adr = base+idx;
if (adr < 0) continue;
if ((unsigned)adr >= source.size()) break;
res.set_bit(idx, source.value(adr));
res.set_bit(idx, source.value((unsigned)adr));
}
if (! ref.eeq(res)) {
@ -316,7 +313,7 @@ void vvp_fun_part_var_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&b
struct vvp_fun_part_var_state_s {
vvp_fun_part_var_state_s() : base(0) { }
unsigned base;
long base;
vvp_vector4_t source;
vvp_vector4_t ref;
};

View File

@ -130,7 +130,7 @@ class vvp_fun_part_var : public vvp_net_fun_t {
protected:
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
unsigned&base, vvp_vector4_t&source,
long&base, vvp_vector4_t&source,
vvp_vector4_t&ref);
unsigned wid_;
@ -154,7 +154,7 @@ class vvp_fun_part_var_sa : public vvp_fun_part_var {
vvp_context_t);
private:
unsigned base_;
long base_;
vvp_vector4_t source_;
// Save the last output, for detecting change.
vvp_vector4_t ref_;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -278,6 +278,37 @@ void propagate_vector4_event_s::run_run(void)
net->send_vec4(val, 0);
}
struct assign_array_r_word_s : public event_s {
vvp_array_t mem;
unsigned adr;
double val;
void run_run(void);
static void* operator new(size_t);
static void operator delete(void*);
};
void assign_array_r_word_s::run_run(void)
{
count_assign_events += 1;
array_set_word(mem, adr, val);
}
static const size_t ARRAY_R_W_CHUNK_COUNT = 8192 / sizeof(struct assign_array_r_word_s);
static slab_t<sizeof(assign_array_r_word_s),ARRAY_R_W_CHUNK_COUNT> array_r_w_heap;
inline void* assign_array_r_word_s::operator new(size_t size)
{
assert(size == sizeof(assign_array_r_word_s));
return array_r_w_heap.alloc_slab();
}
void assign_array_r_word_s::operator delete(void*ptr)
{
array_r_w_heap.free_slab(ptr);
}
unsigned long count_assign_arword_pool(void) { return array_r_w_heap.pool; }
struct generic_event_s : public event_s {
vvp_gen_event_t obj;
bool delete_obj_when_done;
@ -641,6 +672,18 @@ void schedule_assign_array_word(vvp_array_t mem,
schedule_event_(cur, delay, SEQ_NBASSIGN);
}
void schedule_assign_array_word(vvp_array_t mem,
unsigned word_addr,
double val,
vvp_time64_t delay)
{
struct assign_array_r_word_s*cur = new struct assign_array_r_word_s;
cur->mem = mem;
cur->adr = word_addr;
cur->val = val;
schedule_event_(cur, delay, SEQ_NBASSIGN);
}
void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);

View File

@ -1,7 +1,7 @@
#ifndef __schedule_H
#define __schedule_H
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -58,13 +58,17 @@ extern void schedule_assign_array_word(vvp_array_t mem,
vvp_vector4_t val,
vvp_time64_t delay);
extern void schedule_assign_array_word(vvp_array_t mem,
unsigned word_address,
double val,
vvp_time64_t delay);
/*
* Create an event to propagate the output of a net.
*/
extern void schedule_propagate_plucked_vector(vvp_net_t*ptr,
vvp_time64_t delay,
vvp_time64_t delay,
const vvp_vector4_t&val,
unsigned adr, unsigned wid);
unsigned adr, unsigned wid);
/*
* This is very similar to schedule_assign_vector, but generates an

View File

@ -1,7 +1,7 @@
#ifndef __statistics_H
#define __statistics_H
/*
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -47,6 +47,7 @@ extern unsigned long count_assign4_pool(void);
extern unsigned long count_assign8_pool(void);
extern unsigned long count_assign_real_pool(void);
extern unsigned long count_assign_aword_pool(void);
extern unsigned long count_assign_arword_pool(void);
extern unsigned long count_gen_events;
extern unsigned long count_gen_pool(void);

View File

@ -38,6 +38,7 @@
# include <malloc.h>
#endif
# include <stdlib.h>
# include <limits.h>
# include <string.h>
# include <assert.h>
#ifdef CHECK_WITH_VALGRIND
@ -1000,12 +1001,24 @@ static int PV_get_base(struct __vpiPV*rfp)
/* If the width is zero then tbase is the constant. */
if (rfp->twid == 0) return rfp->tbase;
/* Get the value from thread space. */
int tval = 0;
for (unsigned idx = 0 ; idx < rfp->twid ; idx += 1) {
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread,
rfp->tbase + idx);
if (bit == BIT4_1) {
switch (bit) {
case BIT4_X:
case BIT4_Z:
/* We use INT_MIN to indicate an X base. */
return INT_MIN;
break;
case BIT4_1:
tval |= 1<<idx;
break;
case BIT4_0:
break; // Do nothing!
}
}

View File

@ -794,6 +794,68 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
return true;
}
/* %assign/ar <array>, <delay>, <bit>
* Generate an assignment event to a real array. Index register 3
* contains the canonical address of the word in the memory. <delay>
* is the delay in simulation time. <bit> is the index register
* containing the real value.
*/
bool of_ASSIGN_AR(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
unsigned delay = cp->bit_idx[0];
double value = thr->words[cp->bit_idx[1]].w_real;
if (adr >= 0) {
schedule_assign_array_word(cp->array, adr, value, delay);
}
return true;
}
/* %assign/ar/d <array>, <delay_idx>, <bit>
* Generate an assignment event to a real array. Index register 3
* contains the canonical address of the word in the memory.
* <delay_idx> is the integer register that contains the delay value.
* <bit> is the index register containing the real value.
*/
bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
double value = thr->words[cp->bit_idx[1]].w_real;
if (adr >= 0) {
schedule_assign_array_word(cp->array, adr, value, delay);
}
return true;
}
/* %assign/ar/e <array>, <bit>
* Generate an assignment event to a real array. Index register 3
* contains the canonical address of the word in the memory. <bit>
* is the index register containing the real value. The event
* information is contained in the thread event control registers
* and is set with %evctl.
*/
bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
double value = thr->words[cp->bit_idx[0]].w_real;
if (adr >= 0) {
if (thr->ecount == 0) {
schedule_assign_array_word(cp->array, adr, value, 0);
} else {
schedule_evctl(cp->array, adr, value, thr->event,
thr->ecount);
}
}
return true;
}
/* %assign/av <array>, <delay>, <bit>
* This generates an assignment event to an array. Index register 0
* contains the width of the vector (and the word) and index register
@ -803,10 +865,12 @@ bool of_ASSIGN_AV(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->words[0].w_int;
long off = thr->words[1].w_int;
unsigned adr = thr->words[3].w_int;
long adr = thr->words[3].w_int;
unsigned delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1];
if (adr < 0) return true;
long vwidth = get_array_word_size(cp->array);
// We fell off the MSB end.
if (off >= vwidth) return true;
@ -840,10 +904,12 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->words[0].w_int;
long off = thr->words[1].w_int;
unsigned adr = thr->words[3].w_int;
long adr = thr->words[3].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
unsigned bit = cp->bit_idx[1];
if (adr < 0) return true;
long vwidth = get_array_word_size(cp->array);
// We fell off the MSB end.
if (off >= vwidth) return true;
@ -871,9 +937,11 @@ bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->words[0].w_int;
long off = thr->words[1].w_int;
unsigned adr = thr->words[3].w_int;
long adr = thr->words[3].w_int;
unsigned bit = cp->bit_idx[0];
if (adr < 0) return true;
long vwidth = get_array_word_size(cp->array);
// We fell off the MSB end.
if (off >= vwidth) return true;
@ -2574,7 +2642,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
unsigned base = cp->bit_idx[1];
unsigned width = cp->number;
unsigned long v = 0;
uint64_t v = 0;
bool unknown_flag = false;
vvp_bit4_t vv = BIT4_0;
@ -2586,7 +2654,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
break;
}
v |= (unsigned long) vv << i;
v |= (uint64_t) vv << i;
if (base >= 4)
base += 1;
@ -2594,7 +2662,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
/* Sign-extend to fill the integer value. */
if (!unknown_flag) {
unsigned long pad = vv;
uint64_t pad = vv;
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
v |= pad << i;
}
@ -2784,8 +2852,15 @@ bool of_LOAD_AR(vthread_t thr, vvp_code_t cp)
unsigned bit = cp->bit_idx[0];
unsigned idx = cp->bit_idx[1];
unsigned adr = thr->words[idx].w_int;
double word;
/* The result is 0.0 if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
word = 0.0;
} else {
word = array_get_word_r(cp->array, adr);
}
double word = array_get_word_r(cp->array, adr);
thr->words[bit].w_real = word;
return true;
}
@ -2805,11 +2880,18 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
unsigned wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int;
vvp_vector4_t word = array_get_word(cp->array, adr);
/* Check the address once, before we scan the vector. */
thr_check_addr(thr, bit+wid-1);
/* The result is 'bx if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(bit, tmp);
return true;
}
vvp_vector4_t word = array_get_word(cp->array, adr);
if (word.size() > wid)
word.resize(wid);
@ -2880,6 +2962,15 @@ bool of_LOAD_AVP0(vthread_t thr, vvp_code_t cp)
unsigned wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int;
/* The result is 'bx if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
unsigned bit = cp->bit_idx[0];
thr_check_addr(thr, bit+wid-1);
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(bit, tmp);
return true;
}
/* We need a vector this wide to make the math work correctly.
* Copy the base bits into the vector, but keep the width. */
vvp_vector4_t sig_value(wid, BIT4_0);
@ -2894,6 +2985,15 @@ bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t cp)
unsigned wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int;
/* The result is 'bx if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
unsigned bit = cp->bit_idx[0];
thr_check_addr(thr, bit+wid-1);
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(bit, tmp);
return true;
}
vvp_vector4_t tmp (array_get_word(cp->array, adr));
/* We need a vector this wide to make the math work correctly.
@ -2920,11 +3020,17 @@ bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t cp)
unsigned index = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int;
unsigned use_index = thr->words[index].w_int;
/* The result is 'bx if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
thr_put_bit(thr, bit, BIT4_X);
return true;
}
long use_index = thr->words[index].w_int;
vvp_vector4_t word = array_get_word(cp->array, adr);
if (use_index >= word.size()) {
if ((use_index >= (long)word.size()) || (use_index < 0)) {
thr_put_bit(thr, bit, BIT4_X);
} else {
thr_put_bit(thr, bit, word.value(use_index));
@ -4096,7 +4202,7 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
{
unsigned base = cp->bit_idx[0];
unsigned wid = cp->number;
unsigned long shift = thr->words[0].w_int;
long shift = thr->words[0].w_int;
assert(base >= 4);
thr_check_addr(thr, base+wid-1);
@ -4105,7 +4211,8 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
// The result is 'bx if the shift amount is undefined.
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp);
} else if (shift >= wid) {
} else if (shift >= (long)wid) {
// Shift is so far that all value is shifted out. Write
// in a constant 0 result.
vvp_vector4_t tmp (wid, BIT4_0);
@ -4118,6 +4225,17 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
// Fill zeros on the bottom
vvp_vector4_t fil (shift, BIT4_0);
thr->bits4.set_vec(base, fil);
} else if (shift < 0) {
// For a negative shift we pad with 'bx.
unsigned idx;
for (idx = 0 ; (idx-shift) < wid ; idx += 1) {
unsigned src = base + idx - shift;
unsigned dst = base + idx;
thr_put_bit(thr, dst, thr_get_bit(thr, src));
}
for ( ; idx < wid ; idx += 1)
thr_put_bit(thr, base+idx, BIT4_X);
}
return true;
}
@ -4134,12 +4252,16 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
{
unsigned base = cp->bit_idx[0];
unsigned wid = cp->number;
unsigned long shift = thr->words[0].w_int;
long shift = thr->words[0].w_int;
assert(base >= 4);
thr_check_addr(thr, base+wid-1);
if (thr_get_bit(thr, 4) == BIT4_1) {
// The result is 'bx if the shift amount is undefined.
// The result is 'bx if the shift amount is undefined.
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp);
} else if (shift > 0) {
unsigned idx;
for (idx = 0 ; (idx+shift) < wid ; idx += 1) {
@ -4149,6 +4271,21 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
}
for ( ; idx < wid ; idx += 1)
thr_put_bit(thr, base+idx, BIT4_0);
} else if (shift < -(long)wid) {
// Negative shift is so far that all the value is shifted out.
// Write in a constant 'bx result.
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp);
} else if (shift < 0) {
// For a negative shift we pad with 'bx.
vvp_vector4_t tmp (thr->bits4, base, wid+shift);
thr->bits4.set_vec(base-shift, tmp);
vvp_vector4_t fil (-shift, BIT4_X);
thr->bits4.set_vec(base, fil);
}
return true;
}
@ -4161,7 +4298,7 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
if (thr_get_bit(thr, 4) == BIT4_1) {
// The result is 'bx if the shift amount is undefined.
// The result is 'bx if the shift amount is undefined.
vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp);
} else if (shift >= wid) {

View File

@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine
.SH SYNOPSIS
.B vvp
[-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
[\-nNsvV] [\-Mpath] [\-mmodule] [\-llogfile] inputfile [extended-args...]
.SH DESCRIPTION
.PP
@ -14,7 +14,6 @@ command is not by itself executable on any platform. Instead, the
\fIvvp\fP program is invoked to execute the generated output file.
.SH OPTIONS
.l
\fIvvp\fP accepts the following options:
.TP 8
.B -l\fIlogfile\fP
@ -121,7 +120,7 @@ to print information about the annotation.
.TP 8
.B -sdf-verbose
This is shorthand for -sdf-info -sdf-warn.
This is shorthand for \-sdf\-info \-sdf\-warn.
.SH ENVIRONMENT
.PP