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 #ifndef __Attrib_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -30,7 +30,7 @@ class Attrib {
public: public:
Attrib(); Attrib();
~Attrib(); virtual ~Attrib();
const verinum&attribute(perm_string key) const; const verinum&attribute(perm_string key) const;
void attribute(perm_string key, const verinum&value); void attribute(perm_string key, const verinum&value);

View File

@ -1,7 +1,7 @@
#ifndef __LineInfo_H #ifndef __LineInfo_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -36,7 +36,7 @@ using namespace std;
class LineInfo { class LineInfo {
public: public:
LineInfo(); LineInfo();
~LineInfo(); virtual ~LineInfo();
// Get a fully formatted file/lineno // Get a fully formatted file/lineno
string get_fileline() const; string get_fileline() const;

View File

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

View File

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

View File

@ -339,6 +339,12 @@ class PEIdent : public PExpr {
NetScope*found, NetScope*found,
const NetExpr*par_msb, const NetExpr*par_msb,
const NetExpr*par_lsb) const; 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, NetExpr*elaborate_expr_net(Design*des,
NetScope*scope, NetScope*scope,
NetNet*net, 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 (localparams.size() > 0) return;
if (events.size() > 0) return; if (events.size() > 0) return;
if (wires.size() > 0) return; if (wires.size() > 0) return;
if (genvars.size() > 0) return;
if (behaviors.size() > 0) return; if (behaviors.size() > 0) return;
if (analog_behaviors.size() > 0) return; if (analog_behaviors.size() > 0) return;

View File

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

View File

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

View File

@ -72,6 +72,8 @@ int cmdfile_stack_ptr = 0;
\n { cflloc.first_line += 1; } \n { cflloc.first_line += 1; }
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; } "+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; } "+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_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 TOK_INTEGER_WIDTH
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING %token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
@ -135,6 +135,13 @@ item
free(tmp); free(tmp);
} }
| TOK_PARAMETER TOK_PLUSARG
{ char*tmp = substitutions($2);
process_parameter(tmp);
free($2);
free(tmp);
}
| TOK_DEFINE TOK_PLUSARG | TOK_DEFINE TOK_PLUSARG
{ process_define($2); { process_define($2);
free($2); free($2);

View File

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

View File

@ -4,10 +4,10 @@ iverilog - Icarus Verilog compiler
.SH SYNOPSIS .SH SYNOPSIS
.B iverilog .B iverilog
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value] [\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] [\-pflag=value]
[-dname] [-g1995|-g2001|-g2005|-g<feature>] [\-dname] [\-g1995|\-g2001|\-g2005|\-g<feature>]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename] [\-Iincludedir] [\-mmodule] [\-Mfile] [\-Nfile] [\-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile [\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
@ -18,7 +18,6 @@ simulation, and \fIfpga\fP for synthesis. Other target
types are added as code generators are implemented. types are added as code generators are implemented.
.SH OPTIONS .SH OPTIONS
.l
\fIiverilog\fP accepts the following options: \fIiverilog\fP accepts the following options:
.TP 8 .TP 8
.B -B\fIbase\fP .B -B\fIbase\fP
@ -260,7 +259,8 @@ after a \fB-Wall\fP argument to suppress isolated warning types.
.TP 8 .TP 8
.B all .B all
This enables the implicit, portbind and timescale warning categories. This enables the implicit, portbind, select-range and timescale warning
categories.
.TP 8 .TP 8
.B implicit .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, connected but probably should be. Dangling input ports, for example,
will generate a warning. 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 .TP 8
.B timescale .B timescale
This enables warnings for inconsistent use of the timescale This enables warnings for inconsistent use of the timescale
@ -369,7 +375,7 @@ on to the next library directory.
.TP 8 .TP 8
.B +libdir+\fIdir\fP .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 .TP 8
.B +libdir-nocase+\fIdir\fP .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: 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: To compile and run explicitly using the vvp runtime:
iverilog -ohello.vvp -tvvp hello.v iverilog \-ohello.vvp \-tvvp hello.v
.SH "AUTHOR" .SH "AUTHOR"
.nf .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_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */ 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. */ /* Function to add a command file name to the FIFO. */
void add_cmd_file(const char* filename) void add_cmd_file(const char* filename)
{ {
@ -469,6 +475,7 @@ static void process_warning_switch(const char*name)
if (strcmp(name,"all") == 0) { if (strcmp(name,"all") == 0) {
process_warning_switch("implicit"); process_warning_switch("implicit");
process_warning_switch("portbind"); process_warning_switch("portbind");
process_warning_switch("select-range");
process_warning_switch("timescale"); process_warning_switch("timescale");
} else if (strcmp(name,"implicit") == 0) { } else if (strcmp(name,"implicit") == 0) {
if (! strchr(warning_flags, 'i')) if (! strchr(warning_flags, 'i'))
@ -476,6 +483,9 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"portbind") == 0) { } else if (strcmp(name,"portbind") == 0) {
if (! strchr(warning_flags, 'p')) if (! strchr(warning_flags, 'p'))
strcat(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) { } else if (strcmp(name,"timescale") == 0) {
if (! strchr(warning_flags, 't')) if (! strchr(warning_flags, 't'))
strcat(warning_flags, "t"); strcat(warning_flags, "t");
@ -496,6 +506,12 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1]; cp[0] = cp[1];
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) { } else if (strcmp(name,"no-timescale") == 0) {
char*cp = strchr(warning_flags, 't'); char*cp = strchr(warning_flags, 't');
if (cp) while (*cp) { if (cp) while (*cp) {
@ -530,6 +546,11 @@ void process_define(const char*name)
fprintf(defines_file,"D:%s\n", 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 * 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 * 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) { switch (opt) {
case 'B': case 'B':
@ -798,6 +819,11 @@ int main(int argc, char **argv)
case 'E': case 'E':
e_flag = 1; e_flag = 1;
break; 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': case 'p':
fprintf(iconfig_file, "flag:%s\n", optarg); fprintf(iconfig_file, "flag:%s\n", optarg);
break; break;
@ -966,6 +992,15 @@ int main(int argc, char **argv)
fprintf(defines_file, "M:%s\n", depfile); 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 /* Finally, process all the remaining words on the command
line as file names. */ line as file names. */
for (idx = optind ; idx < argc ; idx += 1) 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, 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); verinum result (verinum::Vx, wid, true);
for (long idx = 0 ; idx < wid ; idx += 1) { for (long idx = 0 ; idx < wid ; idx += 1) {
long off = idx + lsv - par_lsv; long off = idx + lsv;
if (off < 0) if (off < 0)
result.set(idx, verinum::Vx); result.set(idx, verinum::Vx);
else if (off < (long)par_val.len()) 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 // If the input is a string, and the part select is working on
// byte boundaries, then make the result into a string. // 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.as_string();
return result; 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); const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex); 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); NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this); result_ex->set_line(*this);
return result_ex; 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, NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
const NetExpr*par, const NetExpr*par,
NetScope*found_in, NetScope*found_in,
const NetExpr*par_msb, const NetExpr*par_msb,
const NetExpr*par_lsb) const const NetExpr*par_lsb) const
{ {
long par_msv, par_lsv; long par_msv, par_lsv;
bool flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv); if(! calculate_param_range_(des, scope, par_msb, par_msv,
if (!flag) par_lsb, par_lsv)) return 0;
return 0;
NetExpr*base = calculate_up_do_base_(des, scope); NetExpr*base = calculate_up_do_base_(des, scope);
if (base == 0) if (base == 0) return 0;
return 0;
unsigned long wid = 0; unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid); 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 // Handle the special case that the base is constant. In this
// case, just precalculate the entire constant result. // case, just precalculate the entire constant result.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) { 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 lsv = base_c->value().as_long();
long par_base = par_lsv;
// Watch out for reversed bit numbering. We're making // Watch out for reversed bit numbering. We're making
// the part select from LSB to MSB. // the part select from LSB to MSB.
if (par_msv < par_lsv) if (par_msv < par_lsv) {
lsv = lsv - wid + 1; 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, verinum result = param_part_select_bits(par_ex->value(), wid,
lsv, par_lsv); lsv-par_base);
NetEConst*result_ex = new NetEConst(result); NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this); result_ex->set_line(*this);
return result_ex; return result_ex;
} }
if ((par_msv < par_lsv) && (wid>1)) if (par_msv >= par_lsv) {
base = make_add_expr(base, 1-(long)wid); 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(); NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid); 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, return elaborate_expr_param_idx_up_(des, scope, par, found_in,
par_msb, par_lsb); 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 // NOTE TO SELF (continued): The code below should be
// rewritten in the above format, as I get to it. // rewritten in the above format, as I get to it.
NetExpr*tmp = par->dup_expr(); NetExpr*tmp = par->dup_expr();
if (use_sel == index_component_t::SEL_IDX_DO) { 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);
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) {
ivl_assert(*this, !name_tail.index.empty()); ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back(); const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb); 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 && if (net->sig()->sb_to_idx(lsv) == 0 &&
wid == net->vector_width()) { wid == net->vector_width()) {
delete base; delete base;
net->cast_signed(false);
return net; return net;
} }
long offset = 0;
if (net->msi() < net->lsi()) {
offset = -wid + 1;
}
// Otherwise, make a part select that covers the right // Otherwise, make a part select that covers the right
// range. // 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 { } else {
// Return 'bx for an undefined base. // 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); NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this); 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 (net->msi() > net->lsi()) {
if (long offset = net->lsi()) if (long offset = net->lsi())
base = make_add_expr(base, 0-offset); base = make_add_expr(base, -offset);
} else { } else {
long vwid = net->lsi() - net->msi() + 1; base = make_sub_expr(net->lsi()-wid+1, base);
long offset = net->msi();
base = make_sub_expr(vwid-offset-wid, base);
} }
NetESelect*ss = new NetESelect(net, base, wid); 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) && if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
wid == net->vector_width()) { wid == net->vector_width()) {
delete base; delete base;
net->cast_signed(false);
return net; return net;
} }
long offset = 0;
if (net->msi() > net->lsi()) {
offset = -wid + 1;
}
// Otherwise, make a part select that covers the right // Otherwise, make a part select that covers the right
// range. // 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 { } else {
// Return 'bx for an undefined base. // 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); NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this); ss->set_line(*this);
@ -2847,16 +3021,19 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
return ss; return ss;
} }
long offset = net->lsi(); if (net->msi() > net->lsi()) {
NetExpr*base_adjusted = wid > 1 if (long offset = net->lsi()+wid-1)
? make_add_expr(base,1-(long)wid-offset) base = make_add_expr(base, -offset);
: (offset == 0? base : make_add_expr(base, 0-offset)); } else {
NetESelect*ss = new NetESelect(net, base_adjusted, wid); base = make_sub_expr(net->lsi(), base);
}
NetESelect*ss = new NetESelect(net, base, wid);
ss->set_line(*this); ss->set_line(*this);
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate part " cerr << get_fileline() << ": debug: Elaborate part "
<< "select base="<< *base_adjusted << ", wid="<< wid << endl; << "select base="<< *base << ", wid="<< wid << endl;
} }
return ss; 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); NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
/* Correct the mux for the range of the vector. */ // Handle the special case that the base is constant. For this
if (reg->msb() < reg->lsb()) // case we can reduce the expression.
base = make_sub_expr(reg->lsb(), base); if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
else if (reg->lsb() != 0) // For the undefined case just let the constant pass and
base = make_add_expr(base, - reg->lsb()); // we will handle it in the code generator.
if (base_c->value().is_defined()) {
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1 ) { long lsv = base_c->value().as_long();
base = make_add_expr(base, 1-(long)wid); 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) if (debug_elaborate)

View File

@ -238,15 +238,33 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
return 0; 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. */ /* The width (a constant) is calculated here. */
unsigned long wid = 0; unsigned long wid = 0;
bool flag = calculate_up_do_width_(des, scope, wid); 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; 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) if (index_tail.sel == index_component_t::SEL_IDX_UP)
lidx = sig->sb_to_idx(midx_val+wid-1); 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. */ /* Warn about an indexed part select that is out of range. */
if (midx >= (long)sig->vector_width() || lidx < 0) { if (warn_ob_select && (lidx < 0)) {
cerr << get_fileline() << ": warning: Indexed part " cerr << get_fileline() << ": warning: " << sig->name();
"select " << 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) { if (sig->array_dimensions() > 0) {
cerr << "[]"; cerr << "[]";
} }
@ -272,7 +300,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
} else { } else {
cerr << "-:"; 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. */ /* 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; unsigned midx = sig->vector_width()-1, lidx = 0;
// The default word select is the first. // The default word select is the first.
long widx = 0; 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(); const name_component_t&name_tail = path_.back();
@ -462,8 +493,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0; return 0;
} }
long widx_val = tmp->value().as_long(); widx_val = tmp->value().as_long();
widx = sig->array_index_to_address(widx_val); if (sig->array_index_is_valid(widx_val))
widx = sig->array_index_to_address(widx_val);
else
widx = -1;
delete tmp_ex; delete tmp_ex;
if (debug_elaborate) if (debug_elaborate)
@ -529,7 +563,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (widx < 0 || widx >= (long) sig->pin_count()) { if (widx < 0 || widx >= (long) sig->pin_count()) {
cerr << get_fileline() << ": warning: ignoring out of " cerr << get_fileline() << ": warning: ignoring out of "
"bounds l-value array access " "bounds l-value array access "
<< sig->name() << "[" << widx << "]." << endl; << sig->name() << "[" << widx_val << "]." << endl;
return 0; 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 // Check that the loop_index variable was declared in a
// genvar statement. // 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 " cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'." "generate \"loop\" variable '" << loop_index << "'."
<< endl; << endl;
@ -1021,6 +1024,12 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
void PGenerate::elaborate_subscope_(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, // Scan the generated scope for nested generate schemes,
// and *generate* new scopes, which is slightly different // and *generate* new scopes, which is slightly different
// from simple elaboration. // from simple elaboration.

View File

@ -126,7 +126,7 @@ static void elaborate_sig_funcs(Design*des, NetScope*scope,
hname_t use_name ( (*cur).first ); hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name); NetScope*fscope = scope->child(use_name);
if (scope == 0) { if (fscope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: " cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first << "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl; << " 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 module or primitive, it interprets them as parameter
overrides. Correct that misconception here. */ overrides. Correct that misconception here. */
if (overrides_) { if (overrides_) {
PDelays tmp_del; if (overrides_->count() > 2) {
tmp_del.set_delays(overrides_, false); cerr << get_fileline() << ": error: UDPs take at most two "
tmp_del.eval_delays(des, scope, rise_expr, fall_expr, decay_expr); "delay arguments." << endl;
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;
des->errors += 1; des->errors += 1;
}
if (dynamic_cast<NetEConst*> (fall_expr)) {
} else { } else {
cerr << get_fileline() << ": error: Delay expressions must be " PDelays tmp_del;
<< "constant for primitives." << endl; tmp_del.set_delays(overrides_, false);
cerr << get_fileline() << ": : Cannot calculate " tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
<< *rise_expr << endl; decay_expr);
des->errors += 1;
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); assert(udp);
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp); NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
net->rise_time(rise_expr); net->rise_time(rise_expr);
@ -4235,8 +4226,23 @@ class elaborate_root_scope_t : public elaborator_work_item_t {
virtual void elaborate_runrun() virtual void elaborate_runrun()
{ {
Module::replace_t stub; Module::replace_t root_repl;
if (! rmod_->elaborate_scope(des, scope_, stub)) 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; 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); NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
osig->local_flag(true); osig->local_flag(true);
osig->data_type(expr_type()); osig->data_type(expr_type());
osig->set_signed(has_sign());
perm_string oname = osig->scope()->local_symbol(); perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width); NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
@ -390,6 +391,7 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet::IMPLICIT, width); NetNet::IMPLICIT, width);
osig->set_line(*this); osig->set_line(*this);
osig->data_type(expr_type()); osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true); osig->local_flag(true);
connect(powr->pin_Result(), osig->pin(0)); connect(powr->pin_Result(), osig->pin(0));
@ -426,6 +428,7 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet::IMPLICIT, width); NetNet::IMPLICIT, width);
osig->set_line(*this); osig->set_line(*this);
osig->data_type(expr_type()); osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true); osig->local_flag(true);
connect(mult->pin_Result(), osig->pin(0)); connect(mult->pin_Result(), osig->pin(0));

View File

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

View File

@ -71,11 +71,11 @@ void reset_lexor();
static void line_directive(); static void line_directive();
static void line_directive2(); static void line_directive2();
static verinum*make_unsized_binary(const char*txt); verinum*make_unsized_binary(const char*txt);
static verinum*make_undef_highz_dec(const char*txt); verinum*make_undef_highz_dec(const char*txt);
static verinum*make_unsized_dec(const char*txt); verinum*make_unsized_dec(const char*txt);
static verinum*make_unsized_octal(const char*txt); verinum*make_unsized_octal(const char*txt);
static verinum*make_unsized_hex(const char*txt); verinum*make_unsized_hex(const char*txt);
static int dec_buf_div2(char *buf); static int dec_buf_div2(char *buf);
@ -667,7 +667,7 @@ void lex_end_table()
BEGIN(INITIAL); BEGIN(INITIAL);
} }
static verinum*make_unsized_binary(const char*txt) verinum*make_unsized_binary(const char*txt)
{ {
bool sign_flag = false; bool sign_flag = false;
const char*ptr = txt; 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; bool sign_flag = false;
const char*ptr = txt; 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; bool sign_flag = false;
const char*ptr = txt; 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). */ /* 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; bool signed_flag = false;
@ -972,7 +972,7 @@ static verinum* make_undef_highz_dec(const char* ptr)
* hard to calculate. * hard to calculate.
*/ */
static verinum*make_unsized_dec(const char*ptr) verinum*make_unsized_dec(const char*ptr)
{ {
char buf[4096]; char buf[4096];
bool signed_flag = false; bool signed_flag = false;

View File

@ -115,6 +115,7 @@ bool warn_implicit = false;
bool warn_timescale = false; bool warn_timescale = false;
bool warn_portbinding = false; bool warn_portbinding = false;
bool warn_inf_loop = false; bool warn_inf_loop = false;
bool warn_ob_select = false;
bool error_implicit = false; bool error_implicit = false;
@ -491,6 +492,9 @@ static void read_iconfig_file(const char*ipath)
case 'l': case 'l':
warn_inf_loop = true; warn_inf_loop = true;
break; break;
case 's':
warn_ob_select = true;
break;
case 'p': case 'p':
warn_portbinding = true; warn_portbinding = true;
break; break;
@ -528,8 +532,9 @@ static void read_iconfig_file(const char*ipath)
<< endl; << endl;
flag_errors += 1; flag_errors += 1;
} }
} else if (strcmp(buf,"defparam") == 0) {
} parm_to_defparam_list(cp);
}
} }
fclose(ifile); 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 MINGW PORT OF ICARUS VERILOG
@ -49,7 +54,7 @@ critical, but these are the versions I use.
Mingw32-5.x <http://www.mingw.org> Mingw32-5.x <http://www.mingw.org>
... including the sub-packages binutils, gcc-core and gcc-g++ ... including the sub-packages binutils, gcc-core and gcc-g++
if you are given the option. 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> bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.2.3 <http://gnuwin32.sourceforge.net> zlib-1.2.3 <http://gnuwin32.sourceforge.net>
gperf-3.0.1 <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 self-installing packages. Install msys first, and then msysDTC. Most
likely, you want to install them in c:/msys. (The msysDTK is installed likely, you want to install them in c:/msys. (The msysDTK is installed
in the same location, as it is an add-on.) in the same location, as it is an add-on.)
This install should be easy and reliable. This install should be easy and reliable.
The installation will leave an "msys" icon on your desktop and in the 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 the mingw/bin directory to your path. You will need that to be able to
find the compilers later. 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 * Install GnuWin32 Packages
The GnuWin32 project is a collections of open source programs and 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 gperf-3.0.1.exe
bison-2.1.exe bison-2.1.exe
flex-2.5.4a.exe flex-2.5.4a.exe
readline-5.0-1.exe
I suggest creating a common directory for holding all your gnuwin32 I suggest creating a common directory for holding all your gnuwin32
packages. I use C:\gnuwin32. The download page at the gnuwin32 site 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 Now, configure the source to make the makefiles and configuration
details. Run these commands: details. Run these commands:
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include" $ CPPFLAGS="-Ic:/gnuwin32/include
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib" $ LDFLAGS="-Lc:/gnuwin32/lib
$ export CPPFLAGS LDFLAGS $ export CPPFLAGS LDFLAGS
$ ./configure --prefix=c:/iverilog $ ./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: the d:\iverilog\bin directory. These include:
c:\mingw\bin\mingw10.dll 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\bzip2.dll
c:\gnuwin32\bin\zlib.dll c:\gnuwin32\bin\zlib.dll

View File

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

View File

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

View File

@ -3829,8 +3829,8 @@ class NetESignal : public NetExpr {
const NetNet* sig() const; const NetNet* sig() const;
NetNet* sig(); NetNet* sig();
// Declared vector dimensions for the signal. // Declared vector dimensions for the signal.
unsigned msi() const; long msi() const;
unsigned lsi() const; long lsi() const;
virtual ivl_variable_type_t expr_type() 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_timeunit_decl;
extern bool have_timeprec_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 #endif

188
pform.cc
View File

@ -42,6 +42,160 @@
map<perm_string,Module*> pform_modules; map<perm_string,Module*> pform_modules;
map<perm_string,PUdp*> pform_primitives; 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. * The lexor accesses the vl_* variables.
*/ */
@ -675,20 +829,31 @@ void pform_endmodule(const char*name, bool in_celldefine,
tp_local_flag = false; 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) void pform_genvars(const struct vlltype&li, list<perm_string>*names)
{ {
list<perm_string>::const_iterator cur; list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) { for (cur = names->begin(); cur != names->end() ; *cur++) {
LineInfo*lni = new LineInfo(); if (pform_cur_generate)
FILE_NAME(lni, li); pform_add_genvar(li, *cur, pform_cur_generate->genvars);
if (pform_cur_module->genvars.find(*cur) != else
pform_cur_module->genvars.end()) { pform_add_genvar(li, *cur, pform_cur_module->genvars);
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;
} }
delete names; delete names;
@ -703,7 +868,6 @@ void pform_start_generate_for(const struct vlltype&li,
FILE_NAME(gen, li); FILE_NAME(gen, li);
// For now, assume that generates do not nest.
gen->parent = pform_cur_generate; gen->parent = pform_cur_generate;
pform_cur_generate = gen; pform_cur_generate = gen;
@ -724,7 +888,6 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test)
FILE_NAME(gen, li); FILE_NAME(gen, li);
// For now, assume that generates do not nest.
gen->parent = pform_cur_generate; gen->parent = pform_cur_generate;
pform_cur_generate = gen; pform_cur_generate = gen;
@ -747,7 +910,6 @@ void pform_start_generate_else(const struct vlltype&li)
FILE_NAME(gen, li); FILE_NAME(gen, li);
// For now, assume that generates do not nest.
gen->parent = pform_cur_generate; gen->parent = pform_cur_generate;
pform_cur_generate = gen; 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 * 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); 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, extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*branch); 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. * 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]) if (delay_[0] && delay_[1] && delay_[2])
out << "#(" << *delay_[0] << "," << *delay_[1] << "," << out << "#(" << *delay_[0] << "," << *delay_[1] << "," <<
*delay_[2] << ")"; *delay_[2] << ")";
else if (delay_[0] && delay_[1])
out << "#(" << *delay_[0] << "," << *delay_[1] << ")";
else if (delay_[0]) else if (delay_[0])
out << "#" << *delay_[0]; out << "#" << *delay_[0];
else else
@ -1032,6 +1034,12 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2); (*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() for (list<PGenerate*>::const_iterator idx = generate_schemes.begin()
; idx != generate_schemes.end() ; idx++) { ; idx != generate_schemes.end() ; idx++) {
(*idx)->dump(out, indent+2); (*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: case IVL_LPM_ARRAY:
return net->u_.array.swid; return net->u_.array.swid;
case IVL_LPM_CONCAT: 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: default:
assert(0); assert(0);
return 0; return 0;
@ -1268,6 +1269,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
return net->u_.ufunc.ports - 1; return net->u_.ufunc.ports - 1;
case IVL_LPM_REPEAT: case IVL_LPM_REPEAT:
return net->u_.repeat.count; return net->u_.repeat.count;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
default: default:
assert(0); assert(0);
return 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)); expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_); assert(expr_);
FILE_NAME(expr_, net);
expr_->type_ = IVL_EX_SELECT; expr_->type_ = IVL_EX_SELECT;
expr_->value_= IVL_VT_VECTOR; 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; obj->type = IVL_LPM_PART_PV;
break; break;
} }
FILE_NAME(obj, net);
obj->name = net->name(); // NetPartSelect names are permallocated. obj->name = net->name(); // NetPartSelect names are permallocated.
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, 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 /* 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 * 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 * function. The widths of all the inputs are inferred from the widths
* of the signals connected to the nexus of the inputs. The compiler * 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); unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n", 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)); 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); ivl_nexus_t nex = ivl_lpm_data(net, idx);
unsigned signal_width = width_of_nexus(nex); unsigned signal_width = width_of_nexus(nex);

View File

@ -1,7 +1,7 @@
/* /*
* VHDL code generation for expressions. * 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 * 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 * 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))) { if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) {
// Select from an array // Select from an array
vhdl_expr *vhd_off = translate_expr(off); vhdl_expr *vhd_off = translate_expr(off);
if (NULL == vhd_off) if (NULL == vhd_off) {
delete ref;
return NULL; return NULL;
}
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
ref->set_slice(vhd_off->cast(&integer)); ref->set_slice(vhd_off->cast(&integer));

View File

@ -1,7 +1,7 @@
/* /*
* VHDL code generation for LPM devices. * 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 * 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 * 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 = vhdl_binop_expr *expr =
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type); 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)); vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) if (NULL == e) {
delete expr;
return NULL; return NULL;
}
expr->add_expr(e); 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++) { for (int i = 0; i < 2; i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i)); vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) if (NULL == e) {
delete expr;
return NULL; return NULL;
}
expr->add_expr(e->cast(result_type)); 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++) { for (int i = 0; i < 2; i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i)); vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) if (NULL == e) {
delete expr;
return NULL; return NULL;
}
expr->add_expr(e); 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++) { for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
vhdl_var_ref *ref = readable_ref(scope, ivl_lpm_data(lpm, i)); vhdl_var_ref *ref = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == ref) if (NULL == ref) {
delete fcall;
return NULL; return NULL;
}
fcall->add_expr(ref); 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_type *atype = new vhdl_type(*adecl->get_type());
vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm)); vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm));
if (NULL == select) if (NULL == select) {
delete atype;
return NULL; return NULL;
}
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype); vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
vhdl_type integer(VHDL_TYPE_INTEGER); 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_scope_tname(scope), ivl_process_file(proc),
ivl_process_lineno(proc)); ivl_process_lineno(proc));
// A process should occur in a module scope, therefore it // Skip over any generate and begin scopes until we find
// should have already been assigned a VHDL entity // 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); assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
vhdl_entity *ent = find_entity(scope); vhdl_entity *ent = find_entity(scope);
assert(ent != NULL); 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 // 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()); remember_signal(sig, ent->get_arch()->get_scope());
string name(make_safe_name(sig)); string name(make_safe_name(sig));
name += genvar_unique_suffix(scope);
avoid_name_collision(name, ent->get_arch()->get_scope()); avoid_name_collision(name, ent->get_arch()->get_scope());
rename_signal(sig, name); 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); ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) != IVL_SIP_NONE) 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++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) == IVL_SIP_NONE) 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: case IVL_SCT_MODULE:
create_skeleton_entity_for(scope, depth); create_skeleton_entity_for(scope, depth);
break; break;
case IVL_SCT_GENERATE:
error("No translation for generate statements yet");
return 1;
case IVL_SCT_FORK: case IVL_SCT_FORK:
error("No translation for fork statements yet"); error("No translation for fork statements yet");
return 1; return 1;
@ -901,6 +936,20 @@ static int draw_all_signals(ivl_scope_t scope, void *_parent)
declare_signals(ent, scope); 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); 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) { if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
ivl_scope_t parent = static_cast<ivl_scope_t>(_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)) if (!is_default_scope_instance(parent))
return 0; // Not generating code for the parent instance so return 0; // Not generating code for the parent instance so
// don't generate for the child // don't generate for the child
@ -1054,6 +1107,7 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
// And an instantiation statement // And an instantiation statement
string inst_name(ivl_scope_basename(scope)); 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)) { if (inst_name == ent->get_name() || parent_scope->have_declared(inst_name)) {
// Cannot have instance name the same as type in VHDL // Cannot have instance name the same as type in VHDL
inst_name += "_Inst"; 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. // name should be the same as the Verilog module type name.
// Note that this will return NULL if no entity has been recorded // Note that this will return NULL if no entity has been recorded
// for this scope type. // 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); assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope)); 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 // Manage the set of VHDL entities
void remember_entity(vhdl_entity *ent, ivl_scope_t scope); 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); vhdl_entity* find_entity(const std::string& name);
void emit_all_entities(std::ostream& os, int max_depth); void emit_all_entities(std::ostream& os, int max_depth);
void free_all_vhdl_objects(); void free_all_vhdl_objects();

View File

@ -313,11 +313,11 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
if (NULL == test) if (NULL == test)
return; return;
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
if (!check_valid_assignment(decl->assignment_type(), proc, stmt)) if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
return; return;
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
// True part // True part
{ {
vhdl_abstract_assign_stmt *a = 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", "expression labels can be translated to VHDL",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt), ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
(is_casez ? "z" : "x")); (is_casez ? "z" : "x"));
delete all;
return 1; 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) && if (number_is_immediate(d_rise, 64, 0) &&
number_is_immediate(d_fall, 64, 0) && number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 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", fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise), net, get_number_immediate(d_rise),
get_number_immediate(d_fall), 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_fall, 64, 0) &&
number_is_immediate(d_decay, 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 " fprintf(vvp_out, "L_%p .delay "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", "(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
cptr, get_number_immediate64(d_rise), 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) { if (word_ex) {
/* Some array select have been evaluated. */ /* Some array select have been evaluated. */
if (number_is_immediate(word_ex,IMM_WID, 0)) { if (number_is_immediate(word_ex,IMM_WID, 0)) {
assert(! number_is_unknown(word_ex));
use_word = get_number_immediate(word_ex); use_word = get_number_immediate(word_ex);
word_ex = 0; word_ex = 0;
} }
@ -130,6 +131,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
if (word_ex) { if (word_ex) {
/* Some array select have been evaluated. */ /* Some array select have been evaluated. */
if (number_is_immediate(word_ex, IMM_WID, 0)) { if (number_is_immediate(word_ex, IMM_WID, 0)) {
assert(! number_is_unknown(word_ex));
use_word = get_number_immediate(word_ex); use_word = get_number_immediate(word_ex);
use_word_defined = 1; use_word_defined = 1;
word_ex = 0; 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. */ /* This is a constant bit/part select. */
if (number_is_immediate(bexpr, 64, 1)) { if (number_is_immediate(bexpr, 64, 1)) {
assert(! number_is_unknown(bexpr));
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>", snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
ivl_expr_signal(vexpr), ivl_expr_signal(vexpr),
get_number_immediate(bexpr), get_number_immediate(bexpr),
@ -206,9 +209,19 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
return 0; return 0;
} }
} else { } else {
/* Fallback case: evaluate the expression. */ /* Fallback case: evaluate the expression. */
struct vector_info rv; struct vector_info rv;
rv = draw_eval_expr(bexpr, STUFF_OK_XZ); 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>", snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
ivl_expr_signal(vexpr), ivl_expr_signal(vexpr),
rv.base, rv.wid, 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: case IVL_EX_ULONG:
{ {
assert(number_is_immediate(expr, IMM_WID, 1)); 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); long imm = get_number_immediate(expr);
if (imm >= 0) { if (imm >= 0) {
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", ix, imm); 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; unsigned word = 0;
if (ivl_signal_dimensions(sig) > 0) { if (ivl_signal_dimensions(sig) > 0) {
ivl_expr_t ixe; ivl_expr_t ixe;
char*type = ivl_expr_signed(expr) ? "/s" : "";
/* Detect the special case that this is a /* Detect the special case that this is a
variable array. In this case, the ix/getv 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) { if (ivl_signal_type(sig) == IVL_SIT_REG) {
struct vector_info rv; struct vector_info rv;
rv = draw_eval_expr(expr, 0); rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n", fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
ix, rv.base, rv.wid); type, ix, rv.base, rv.wid);
clr_vector(rv); clr_vector(rv);
break; break;
} }
ixe = ivl_expr_oper1(expr); 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); word = get_number_immediate(ixe);
else { } else {
struct vector_info rv; struct vector_info rv;
rv = draw_eval_expr(expr, 0); rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n", fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
ix, rv.base, rv.wid); type, ix, rv.base, rv.wid);
clr_vector(rv); clr_vector(rv);
break; break;
} }
@ -226,8 +234,14 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
default: { default: {
struct vector_info rv; struct vector_info rv;
rv = draw_eval_expr(expr, 0); rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n", /* Is this a signed expression? */
ix, rv.base, rv.wid); 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); clr_vector(rv);
break; break;
} }
@ -274,7 +288,10 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
{ {
unsigned wid; unsigned wid;
struct vector_info lv; 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); wid = ivl_expr_width(le);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag); 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) unsigned wid)
{ {
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ); 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); unsigned long imm = get_number_immediate(re);
assert(lv.base >= 4); assert(lv.base >= 4);
@ -1241,8 +1260,10 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le,
int signed_flag) int signed_flag)
{ {
struct vector_info lv; 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)); assert(number_is_immediate(re, IMM_WID, 1));
imm = get_number_immediate(re);
lv.base = allocate_vector(wid); lv.base = allocate_vector(wid);
lv.wid = wid; lv.wid = wid;
if (lv.base == 0) { 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); lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid); assert(lv.wid == wid);
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 0));
imm = get_number_immediate(re); imm = get_number_immediate(re);
/* This shouldn't generally happen, because the elaborator /* This shouldn't generally happen, because the elaborator
@ -1308,7 +1331,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
} }
break; break;
case 2: /* Left expression is X or Z */ case 2: /* Left expression is 'bx or 'bz */
case 3: case 3:
lv.base = 2; lv.base = 2;
break; 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); lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid); assert(lv.wid == wid);
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 0));
imm = get_number_immediate(re); imm = get_number_immediate(re);
if (imm == 0) if (imm == 0)
return lv; 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); lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid); assert(lv.wid == wid);
assert(! number_is_unknown(re));
assert(number_is_immediate(re, IMM_WID, 0));
imm = get_number_immediate(re); imm = get_number_immediate(re);
if (imm == 0) if (imm == 0)
return lv; return lv;
@ -2253,7 +2280,7 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
unsigned bit_width, unsigned bit_width,
unsigned wid) unsigned wid)
{ {
unsigned idx; unsigned idx, label;
ivl_signal_t sig = ivl_expr_signal(sube); ivl_signal_t sig = ivl_expr_signal(sube);
/* unsigned sig_wid = ivl_expr_width(sube); */ /* unsigned sig_wid = ivl_expr_width(sube); */
ivl_expr_t ix = ivl_expr_oper1(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); shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
draw_eval_expr_into_integer(ix, 3); 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) if (shiv.base >= 8)
clr_vector(shiv); clr_vector(shiv);
@ -2294,7 +2332,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
/* Use this word of the signal. */ /* Use this word of the signal. */
unsigned use_word = 0; 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 /* 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 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 /* The index is constant, so we can return to direct
readout with the specific word selected. */ readout with the specific word selected. */
assert(! number_is_unknown(ix));
use_word = get_number_immediate(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 the signal (or the entire width). Just load the early bits
in one go. */ in one go. */
if (number_is_immediate(bit_idx, 32, 0) if (number_is_immediate(bit_idx, 32, 0)
&& !number_is_unknown(bit_idx)
&& get_number_immediate(bit_idx) == 0 && get_number_immediate(bit_idx) == 0
&& (ivl_expr_width(sube) >= bit_wid)) { && (ivl_expr_width(sube) >= bit_wid)) {
@ -2343,6 +2383,12 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
res.wid = wid; res.wid = wid;
assert(res.base); 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; use_wid = res.wid;
if (use_wid > bit_wid) if (use_wid > bit_wid)
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", fprintf(vvp_out, " %%movi %u, 0, %u;\n",
res.base + use_wid, res.wid - use_wid); 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; return res;
} }
@ -2371,6 +2422,7 @@ static void draw_select_signal_dest(ivl_expr_t sube,
if ((ivl_signal_dimensions(sig) == 0) if ((ivl_signal_dimensions(sig) == 0)
&& (ivl_expr_width(sube) >= dest.wid) && (ivl_expr_width(sube) >= dest.wid)
&& number_is_immediate(bit_idx, 32, 0) && number_is_immediate(bit_idx, 32, 0)
&& ! number_is_unknown(bit_idx)
&& get_number_immediate(bit_idx) == 0) { && get_number_immediate(bit_idx) == 0) {
unsigned use_word = 0; unsigned use_word = 0;
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Select %u out of %u bits\n", 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); ivl_expr_t shift = ivl_expr_oper2(exp);
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1; int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
int cmp;
unsigned lab_l, lab_end;
res.wid = wid; res.wid = wid;
@ -2444,7 +2498,12 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
return res; 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); clr_vector(shiv);
/* If the subv result is a magic constant, then make a copy in /* 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; 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, " %%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) { if (subv.wid > wid) {
res.base = subv.base; res.base = subv.base;

View File

@ -87,7 +87,8 @@ static void set_to_lvariable(ivl_lval_t lval,
if (part_off_ex == 0) { if (part_off_ex == 0) {
part_off = 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 = get_number_immediate(part_off_ex);
part_off_ex = 0; 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 it to select the word, and pay no further heed to the
expression itself. */ expression itself. */
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) { if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
assert(! number_is_unknown(word_ix));
use_word = get_number_immediate(word_ix); use_word = get_number_immediate(word_ix);
word_ix = 0; 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, static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
unsigned bit, uint64_t delay, ivl_expr_t dexp, unsigned bit, uint64_t delay, ivl_expr_t dexp,
ivl_expr_t part_off_ex, unsigned width, 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) { if (part_off_ex == 0) {
part_off = 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)) {
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex); part_off = get_number_immediate(part_off_ex);
part_off_ex = 0; part_off_ex = 0;
} }
/* This code is common to all the different types of array delays. */ /* This code is common to all the different types of array delays. */
if (number_is_immediate(word_ix, IMM_WID, 0)) { 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", fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
get_number_immediate(word_ix)); get_number_immediate(word_ix));
} else { } else {
@ -317,6 +378,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
if (part_off_ex == 0) { if (part_off_ex == 0) {
part_off = 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)) {
assert(! number_is_unknown(part_off_ex));
part_off = get_number_immediate(part_off_ex); part_off = get_number_immediate(part_off_ex);
part_off_ex = 0; part_off_ex = 0;
} }
@ -643,13 +705,6 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
sig = ivl_lval_sig(lval); sig = ivl_lval_sig(lval);
assert(sig); 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)) { if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
assert(number_is_immediate(del, 64, 0)); assert(number_is_immediate(del, 64, 0));
delay = ivl_expr_delay_val(del); 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 */ /* Evaluate the r-value */
word = draw_eval_real(rval); 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. */ /* We need to calculate the delay expression. */
if (del) { if (del) {
assert(nevents == 0); assert(nevents == 0);
@ -1105,11 +1168,13 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
part_off = 0; part_off = 0;
} else { } else {
assert(number_is_immediate(part_off_ex, IMM_WID, 0)); 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); part_off = get_number_immediate(part_off_ex);
} }
if (word_idx != 0) { if (word_idx != 0) {
assert(number_is_immediate(word_idx, IMM_WID, 0)); assert(number_is_immediate(word_idx, IMM_WID, 0));
assert(! number_is_unknown(word_idx));
use_word = get_number_immediate(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 select (this could give us multiple drivers). */
part_off_ex = ivl_lval_part_off(lval); part_off_ex = ivl_lval_part_off(lval);
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) || 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)) { (part_off_ex && get_number_immediate(part_off_ex) != 0)) {
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to " fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to "
"a bit/part select.\n", ivl_expr_file(rval), "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. */ /* At least for now, only handle force to fixed words of an array. */
if ((lword_idx = ivl_lval_idx(lval)) != 0) { if ((lword_idx = ivl_lval_idx(lval)) != 0) {
assert(number_is_immediate(lword_idx, IMM_WID, 0)); assert(number_is_immediate(lword_idx, IMM_WID, 0));
assert(! number_is_unknown(lword_idx));
use_lword = get_number_immediate(lword_idx); use_lword = get_number_immediate(lword_idx);
} }
if ((rword_idx = ivl_expr_oper1(rval)) != 0) { if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
assert(number_is_immediate(rword_idx, IMM_WID, 0)); assert(number_is_immediate(rword_idx, IMM_WID, 0));
assert(! number_is_unknown(rword_idx));
use_rword = get_number_immediate(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; part_off = 0;
if (part_off_ex != 0) { if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64, 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); part_off = get_number_immediate(part_off_ex);
} }
if (word_idx != 0) { if (word_idx != 0) {
assert(number_is_immediate(word_idx, IMM_WID, 0)); assert(number_is_immediate(word_idx, IMM_WID, 0));
assert(! number_is_unknown(word_idx));
use_word = get_number_immediate(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; part_off = 0;
if (part_off_ex != 0) { if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64, 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); 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) { if (word_idx != 0) {
assert(number_is_immediate(word_idx, IMM_WID, 0)); assert(number_is_immediate(word_idx, IMM_WID, 0));
assert(! number_is_unknown(word_idx));
use_word = get_number_immediate(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(d0, 64, 0));
assert(number_is_immediate(d1, 64, 0)); assert(number_is_immediate(d1, 64, 0));
assert(number_is_immediate(d2, 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) if (d0 == d1 && d1 == d2)
fprintf(vvp_out, " (%lu)", get_number_immediate(d0)); 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 ivl_udp_t *udps = 0x0;
static int nudps = 0; static int nudps = 0;
int i; int i;
unsigned ninp;
const char **input_strings;
for (i=0; i<nudps; i++) for (i=0; i<nudps; i++)
if (udps[i] == udp) if (udps[i] == udp)
@ -628,26 +633,38 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
draw_udp_def(udp); draw_udp_def(udp);
} }
fprintf(vvp_out, "L_%p .udp", lptr); /*
fprintf(vvp_out, " UDP_%s", * We need to process the arguments first so any evaluation code
vvp_mangle_id(ivl_udp_name(udp))); * (.resolv, etc.) can be built before we build the .udp call.
draw_delay(lptr); * This matches what is done for the other primitives.
*/
for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) { ninp = ivl_logic_pins(lptr) - 1;
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx); 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 /* Unlike other logic gates, primitives may have unconnected
inputs. The proper behavior is to attach a HiZ to the inputs. The proper behavior is to attach a HiZ to the
port. */ port. */
if (nex == 0) { if (nex == 0) {
assert(ivl_logic_width(lptr) == 1); assert(ivl_logic_width(lptr) == 1);
fprintf(vvp_out, ", C4<z>"); input_strings[pdx] = "C4<z>";
} else { } 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"); 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)); input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
level = 0; level = 0;
ninp = ivl_logic_pins(lptr) - 1;
while (ninp) { while (ninp) {
int inst; int inst;
for (inst = 0; inst < ninp; inst += 4) { 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(fall_exp,64,0)
&& number_is_immediate(decay_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", fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
lptr, get_number_immediate(rise_exp), lptr, get_number_immediate(rise_exp),
get_number_immediate(fall_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_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0)); assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 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"; dly = "/d";
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n", fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise), 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) static void draw_lpm_concat(ivl_lpm_t net)
{ {
const char*src_table[4]; 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); const char*dly = draw_lpm_output_delay(net);
if (icnt <= 4) { if (icnt <= 4) {

View File

@ -1127,9 +1127,15 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8 *name)
val.format = vpiIntVal; val.format = vpiIntVal;
vpi_get_value(arg, &val); vpi_get_value(arg, &val);
fd_mcd = val.value.integer; 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) || if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF) || ( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
(! fd_mcd)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given " 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; val.format = vpiIntVal;
vpi_get_value(arg, &val); vpi_get_value(arg, &val);
fd_mcd = val.value.integer; 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) || if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF) || ( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
(! fd_mcd)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given " 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); 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 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; val.format = vpiIntVal;
if (mode) { if (mode) {
@ -267,6 +270,9 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
vpi_get_value(arg, &val); vpi_get_value(arg, &val);
fd_mcd = val.value.integer; 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) || if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF) || ( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF) ||
(! fd_mcd)) { (! 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, if (process_params(mitem, start_item, stop_item, callh, name,
&start_addr, &stop_addr, &addr_incr, &start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0; &min_addr, &max_addr)) {
free(fname);
return 0;
}
/* Open the data file. */ /* Open the data file. */
file = fopen(fname, "r"); 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, if (process_params(mitem, start_item, stop_item, callh, name,
&start_addr, &stop_addr, &addr_incr, &start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0; &min_addr, &max_addr)) {
free(fname);
return 0;
}
/* Open the data file. */ /* Open the data file. */
file = fopen(fname, "w"); file = fopen(fname, "w");

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __codes_H #ifndef __codes_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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_AND(vthread_t thr, vvp_code_t code);
extern bool of_ANDI(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_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_AV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVD(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); 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", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 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} }, { "%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",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/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} }, { "%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_vec8_ = vvp_vector8_t(cur_vec4_, 6, 6);
cur_real_ = 0.0; cur_real_ = 0.0;
list_ = 0; list_ = 0;
type_ = UNKNOWN_DELAY;
initial_ = true; initial_ = true;
// Calculate the values used when converting variable delays // Calculate the values used when converting variable delays
// to simulation time units. // to simulation time units.
@ -160,10 +161,48 @@ vvp_fun_delay::~vvp_fun_delay()
delete cur; 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) void vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay)
{ {
if (list_ == 0) assert(list_ != 0);
return;
do { do {
struct event_*cur = list_->next; 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 /* This is an initial value so it needs to be compared to all the
bits (the order the bits are changed is not deterministic). */ bits (the order the bits are changed is not deterministic). */
if (initial_) { if (initial_) {
type_ = VEC4_DELAY;
vvp_bit4_t cur_val = cur_vec4_.value(0); vvp_bit4_t cur_val = cur_vec4_.value(0);
use_delay = delay_.get_delay(cur_val, bit.value(0)); use_delay = delay_.get_delay(cur_val, bit.value(0));
for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) { 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; if (tmp > use_delay) use_delay = tmp;
} }
} else { } else {
assert(type_ == VEC4_DELAY);
/* How many bits to compare? */ /* How many bits to compare? */
unsigned use_wid = cur_vec4_.size(); 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 /* 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 transaction in the queue. This would be a pulse that needs to be
eliminated. */ eliminated. */
clean_pulse_events_(use_delay); if (clean_pulse_events_(use_delay, bit)) return;
vvp_time64_t use_simtime = schedule_simtime() + use_delay; 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 /* This is an initial value so it needs to be compared to all the
bits (the order the bits are changed is not deterministic). */ bits (the order the bits are changed is not deterministic). */
if (initial_) { if (initial_) {
type_ = VEC8_DELAY;
vvp_bit4_t cur_val = cur_vec8_.value(0).value(); vvp_bit4_t cur_val = cur_vec8_.value(0).value();
use_delay = delay_.get_delay(cur_val, bit.value(0).value()); use_delay = delay_.get_delay(cur_val, bit.value(0).value());
for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) { 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; if (tmp > use_delay) use_delay = tmp;
} }
} else { } else {
assert(type_ == VEC8_DELAY);
/* How many bits to compare? */ /* How many bits to compare? */
unsigned use_wid = cur_vec8_.size(); 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 /* 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 transaction in the queue. This would be a pulse that needs to be
eliminated. */ eliminated. */
clean_pulse_events_(use_delay); if (clean_pulse_events_(use_delay, bit)) return;
vvp_time64_t use_simtime = schedule_simtime() + use_delay; 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; return;
} }
if (initial_) type_ = REAL_DELAY;
else assert(type_ == REAL_DELAY);
vvp_time64_t use_delay; vvp_time64_t use_delay;
use_delay = delay_.get_min_delay(); use_delay = delay_.get_min_delay();
/* Eliminate glitches. */ /* 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 /* This must be done after cleaning pulses to avoid propagating
* an incorrect value. */ * 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 { 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_ { struct event_ {
event_(vvp_time64_t s) : sim_time(s) { } event_(vvp_time64_t s) : sim_time(s) { }
void (vvp_fun_delay::*run_run_ptr)(struct vvp_fun_delay::event_*cur); 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: private:
vvp_net_t*net_; vvp_net_t*net_;
vvp_delay_t delay_; vvp_delay_t delay_;
delay_type_t type_;
bool initial_; // Indicates if the value is still the initial value. bool initial_; // Indicates if the value is still the initial value.
vvp_vector4_t cur_vec4_; 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; list_->next = cur->next;
return cur; 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); 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); 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) inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
{ {
return 1 << ((from << 2) | to); return 1 << ((from << 2) | to);

View File

@ -81,6 +81,20 @@ class evctl_array : public evctl {
unsigned off_; 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, extern void schedule_evctl(struct __vpiHandle*handle, double value,
vvp_net_t*event, unsigned long ecount); 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, const vvp_vector4_t&value, unsigned offset,
vvp_net_t*event, unsigned long ecount); 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 * 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()); count_assign_real_pool());
vpi_mcd_printf(1, " ...assign(word) pool=%lu\n", vpi_mcd_printf(1, " ...assign(word) pool=%lu\n",
count_assign_aword_pool()); 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", vpi_mcd_printf(1, " %8lu other events (pool=%lu)\n",
count_gen_events, count_gen_pool()); count_gen_events, count_gen_pool());
} }

View File

@ -65,6 +65,26 @@ means the following:
1 and 1 --> 1 1 and 1 --> 1
otherwise x 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 <array-label>, <delay>, <bit>
* %assign/av/d <array-label>, <delayx>, <bit> * %assign/av/d <array-label>, <delayx>, <bit>
* %assign/av/e <array-label>, <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 read directly from a functor label instead of from thread bits. They
set bit 4 just like %ix/get. 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 This instruction loads an immediate value into the addressed index
register. The index register holds signed 64 bit numeric values, so 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. <high> << 32 | <low> to produce the final value.
* %ix/add <idx>, <low> <high> * %ix/add <idx>, <low>, <high>
* %ix/sub <idx>, <low> <high> * %ix/sub <idx>, <low>, <high>
* %ix/mul <idx>, <low> <high> * %ix/mul <idx>, <low>, <high>
These instructions add, subtract, or multiply the selected index These instructions add, subtract, or multiply the selected index
register by the immediate value. The 64 bit immediate value is built 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 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 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> * %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 the LSB of the vector, and <wid> the width of the vector. The shift is
done in place. Zero values are shifted in. done in place. Zero values are shifted in.
For a negative shift the value is padded with 'bx.
* %shiftr/i0 <bit>, <wid> * %shiftr/i0 <bit>, <wid>
* %shiftr/s/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 %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. 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> * %sub <bit-l>, <bit-r>, <wid>
This instruction arithmetically subtracts the right vector out of the 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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); assert(bit.size() == wid);
vvp_vector4_t tmp = val_; vvp_vector4_t tmp (vwid, BIT4_Z);
if (tmp.size() == 0) tmp.set_vec(base_, val_);
tmp = vvp_vector4_t(vwid);
assert(tmp.size() == vwid);
tmp.set_vec(base, bit); tmp.set_vec(base, bit);
recv_vec4(port, tmp, 0); 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_vector4_t*val = static_cast<vvp_vector4_t*>
(vvp_get_context_item(context, context_idx_)); (vvp_get_context_item(context, context_idx_));
vvp_vector4_t tmp = *val; vvp_vector4_t tmp (vwid, BIT4_Z);
if (tmp.size() == 0) tmp.set_vec(base_, *val);
tmp = vvp_vector4_t(vwid);
assert(tmp.size() == vwid);
tmp.set_vec(base, bit); tmp.set_vec(base, bit);
recv_vec4(port, tmp, context); recv_vec4(port, tmp, context);
} else { } 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, 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) vvp_vector4_t&ref)
{ {
unsigned long tmp; long tmp;
switch (port.port()) { switch (port.port()) {
case 0: case 0:
source = bit; source = bit;
break; break;
case 1: case 1:
tmp = ULONG_MAX; // LONG_MIN is before the vector and is used to
vector4_to_value(bit, tmp); // 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; if (tmp == base) return false;
base = tmp; base = tmp;
break; 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_); vvp_vector4_t res (wid_);
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) { for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
unsigned adr = base+idx; long adr = base+idx;
if (adr >= source.size()) if (adr < 0) continue;
break; 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)) { 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 { struct vvp_fun_part_var_state_s {
vvp_fun_part_var_state_s() : base(0) { } vvp_fun_part_var_state_s() : base(0) { }
unsigned base; long base;
vvp_vector4_t source; vvp_vector4_t source;
vvp_vector4_t ref; vvp_vector4_t ref;
}; };

View File

@ -130,7 +130,7 @@ class vvp_fun_part_var : public vvp_net_fun_t {
protected: protected:
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit, 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); vvp_vector4_t&ref);
unsigned wid_; unsigned wid_;
@ -154,7 +154,7 @@ class vvp_fun_part_var_sa : public vvp_fun_part_var {
vvp_context_t); vvp_context_t);
private: private:
unsigned base_; long base_;
vvp_vector4_t source_; vvp_vector4_t source_;
// Save the last output, for detecting change. // Save the last output, for detecting change.
vvp_vector4_t ref_; 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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); 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 { struct generic_event_s : public event_s {
vvp_gen_event_t obj; vvp_gen_event_t obj;
bool delete_obj_when_done; bool delete_obj_when_done;
@ -641,6 +672,18 @@ void schedule_assign_array_word(vvp_array_t mem,
schedule_event_(cur, delay, SEQ_NBASSIGN); 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) 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); struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);

View File

@ -1,7 +1,7 @@
#ifndef __schedule_H #ifndef __schedule_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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_vector4_t val,
vvp_time64_t delay); 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. * Create an event to propagate the output of a net.
*/ */
extern void schedule_propagate_plucked_vector(vvp_net_t*ptr, extern void schedule_propagate_plucked_vector(vvp_net_t*ptr,
vvp_time64_t delay, vvp_time64_t delay,
const vvp_vector4_t&val, const vvp_vector4_t&val,
unsigned adr, unsigned wid); unsigned adr, unsigned wid);
/* /*
* This is very similar to schedule_assign_vector, but generates an * This is very similar to schedule_assign_vector, but generates an

View File

@ -1,7 +1,7 @@
#ifndef __statistics_H #ifndef __statistics_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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_assign8_pool(void);
extern unsigned long count_assign_real_pool(void); extern unsigned long count_assign_real_pool(void);
extern unsigned long count_assign_aword_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_events;
extern unsigned long count_gen_pool(void); extern unsigned long count_gen_pool(void);

View File

@ -38,6 +38,7 @@
# include <malloc.h> # include <malloc.h>
#endif #endif
# include <stdlib.h> # include <stdlib.h>
# include <limits.h>
# include <string.h> # include <string.h>
# include <assert.h> # include <assert.h>
#ifdef CHECK_WITH_VALGRIND #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 the width is zero then tbase is the constant. */
if (rfp->twid == 0) return rfp->tbase; if (rfp->twid == 0) return rfp->tbase;
/* Get the value from thread space. */
int tval = 0; int tval = 0;
for (unsigned idx = 0 ; idx < rfp->twid ; idx += 1) { for (unsigned idx = 0 ; idx < rfp->twid ; idx += 1) {
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread, vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread,
rfp->tbase + idx); 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; 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; 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> /* %assign/av <array>, <delay>, <bit>
* This generates an assignment event to an array. Index register 0 * This generates an assignment event to an array. Index register 0
* contains the width of the vector (and the word) and index register * 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; unsigned wid = thr->words[0].w_int;
long off = thr->words[1].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 delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1]; unsigned bit = cp->bit_idx[1];
if (adr < 0) return true;
long vwidth = get_array_word_size(cp->array); long vwidth = get_array_word_size(cp->array);
// We fell off the MSB end. // We fell off the MSB end.
if (off >= vwidth) return true; 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; unsigned wid = thr->words[0].w_int;
long off = thr->words[1].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; vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
unsigned bit = cp->bit_idx[1]; unsigned bit = cp->bit_idx[1];
if (adr < 0) return true;
long vwidth = get_array_word_size(cp->array); long vwidth = get_array_word_size(cp->array);
// We fell off the MSB end. // We fell off the MSB end.
if (off >= vwidth) return true; 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; unsigned wid = thr->words[0].w_int;
long off = thr->words[1].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]; unsigned bit = cp->bit_idx[0];
if (adr < 0) return true;
long vwidth = get_array_word_size(cp->array); long vwidth = get_array_word_size(cp->array);
// We fell off the MSB end. // We fell off the MSB end.
if (off >= vwidth) return true; 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 base = cp->bit_idx[1];
unsigned width = cp->number; unsigned width = cp->number;
unsigned long v = 0; uint64_t v = 0;
bool unknown_flag = false; bool unknown_flag = false;
vvp_bit4_t vv = BIT4_0; vvp_bit4_t vv = BIT4_0;
@ -2586,7 +2654,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
break; break;
} }
v |= (unsigned long) vv << i; v |= (uint64_t) vv << i;
if (base >= 4) if (base >= 4)
base += 1; 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. */ /* Sign-extend to fill the integer value. */
if (!unknown_flag) { if (!unknown_flag) {
unsigned long pad = vv; uint64_t pad = vv;
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) { for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
v |= pad << i; 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 bit = cp->bit_idx[0];
unsigned idx = cp->bit_idx[1]; unsigned idx = cp->bit_idx[1];
unsigned adr = thr->words[idx].w_int; 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; thr->words[bit].w_real = word;
return true; return true;
} }
@ -2805,11 +2880,18 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
unsigned wid = cp->bit_idx[1]; unsigned wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int; 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. */ /* Check the address once, before we scan the vector. */
thr_check_addr(thr, bit+wid-1); 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) if (word.size() > wid)
word.resize(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 wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int; 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. /* We need a vector this wide to make the math work correctly.
* Copy the base bits into the vector, but keep the width. */ * Copy the base bits into the vector, but keep the width. */
vvp_vector4_t sig_value(wid, BIT4_0); 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 wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int; 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)); vvp_vector4_t tmp (array_get_word(cp->array, adr));
/* We need a vector this wide to make the math work correctly. /* 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 index = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int; 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); 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); thr_put_bit(thr, bit, BIT4_X);
} else { } else {
thr_put_bit(thr, bit, word.value(use_index)); 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 base = cp->bit_idx[0];
unsigned wid = cp->number; unsigned wid = cp->number;
unsigned long shift = thr->words[0].w_int; long shift = thr->words[0].w_int;
assert(base >= 4); assert(base >= 4);
thr_check_addr(thr, base+wid-1); 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. // The result is 'bx if the shift amount is undefined.
vvp_vector4_t tmp (wid, BIT4_X); vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp); 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 // Shift is so far that all value is shifted out. Write
// in a constant 0 result. // in a constant 0 result.
vvp_vector4_t tmp (wid, BIT4_0); 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 // Fill zeros on the bottom
vvp_vector4_t fil (shift, BIT4_0); vvp_vector4_t fil (shift, BIT4_0);
thr->bits4.set_vec(base, fil); 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; return true;
} }
@ -4134,12 +4252,16 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
{ {
unsigned base = cp->bit_idx[0]; unsigned base = cp->bit_idx[0];
unsigned wid = cp->number; 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) { 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); vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp); thr->bits4.set_vec(base, tmp);
} else if (shift > 0) { } else if (shift > 0) {
unsigned idx; unsigned idx;
for (idx = 0 ; (idx+shift) < wid ; idx += 1) { 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) for ( ; idx < wid ; idx += 1)
thr_put_bit(thr, base+idx, BIT4_0); 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; 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); vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
if (thr_get_bit(thr, 4) == BIT4_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); vvp_vector4_t tmp (wid, BIT4_X);
thr->bits4.set_vec(base, tmp); thr->bits4.set_vec(base, tmp);
} else if (shift >= wid) { } else if (shift >= wid) {

View File

@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine
.SH SYNOPSIS .SH SYNOPSIS
.B vvp .B vvp
[-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...] [\-nNsvV] [\-Mpath] [\-mmodule] [\-llogfile] inputfile [extended-args...]
.SH DESCRIPTION .SH DESCRIPTION
.PP .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. \fIvvp\fP program is invoked to execute the generated output file.
.SH OPTIONS .SH OPTIONS
.l
\fIvvp\fP accepts the following options: \fIvvp\fP accepts the following options:
.TP 8 .TP 8
.B -l\fIlogfile\fP .B -l\fIlogfile\fP
@ -121,7 +120,7 @@ to print information about the annotation.
.TP 8 .TP 8
.B -sdf-verbose .B -sdf-verbose
This is shorthand for -sdf-info -sdf-warn. This is shorthand for \-sdf\-info \-sdf\-warn.
.SH ENVIRONMENT .SH ENVIRONMENT
.PP .PP