Merge branch 'master' into vvp-net-out-rework
Conflicts: vvp/schedule.cc vvp/schedule.h
This commit is contained in:
commit
0018cb38b0
4
Attrib.h
4
Attrib.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __Attrib_H
|
||||
#define __Attrib_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -30,7 +30,7 @@ class Attrib {
|
|||
|
||||
public:
|
||||
Attrib();
|
||||
~Attrib();
|
||||
virtual ~Attrib();
|
||||
|
||||
const verinum&attribute(perm_string key) const;
|
||||
void attribute(perm_string key, const verinum&value);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __LineInfo_H
|
||||
#define __LineInfo_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -36,7 +36,7 @@ using namespace std;
|
|||
class LineInfo {
|
||||
public:
|
||||
LineInfo();
|
||||
~LineInfo();
|
||||
virtual ~LineInfo();
|
||||
|
||||
// Get a fully formatted file/lineno
|
||||
string get_fileline() const;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
list<Module::named_expr_t> Module::user_defparms;
|
||||
|
||||
/* n is a permallocated string. */
|
||||
Module::Module(perm_string n)
|
||||
: PScope(n)
|
||||
|
|
|
|||
1
Module.h
1
Module.h
|
|
@ -92,6 +92,7 @@ class Module : public PScope, public LineInfo {
|
|||
instantiated modules. */
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
static list<named_expr_t>user_defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
|
|
|
|||
6
PExpr.h
6
PExpr.h
|
|
@ -339,6 +339,12 @@ class PEIdent : public PExpr {
|
|||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_param_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2006,2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -55,6 +55,7 @@ void PGenerate::probe_for_direct_nesting_(void)
|
|||
if (localparams.size() > 0) return;
|
||||
if (events.size() > 0) return;
|
||||
if (wires.size() > 0) return;
|
||||
if (genvars.size() > 0) return;
|
||||
if (behaviors.size() > 0) return;
|
||||
if (analog_behaviors.size() > 0) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2006-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -87,6 +87,9 @@ class PGenerate : public LineInfo, public LexicalScope {
|
|||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*>funcs;
|
||||
|
||||
// genvars declared within this scheme.
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
|
||||
// Generate schemes can contain further generate schemes.
|
||||
list<PGenerate*> generate_schemes;
|
||||
PGenerate*parent;
|
||||
|
|
@ -109,8 +112,8 @@ class PGenerate : public LineInfo, public LexicalScope {
|
|||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||
|
||||
// Call probe during elaborate_scope to calulate the
|
||||
// directed_nested_ flag. It is OK to store the direct_nested_
|
||||
// Call probe during elaborate_scope to calculate the
|
||||
// direct_nested_ flag. It is OK to store the direct_nested_
|
||||
// information here because "direct nested" is a property of
|
||||
// the lexical generate code.
|
||||
void probe_for_direct_nesting_(void);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ extern bool warn_timescale;
|
|||
/* Warn about legal but questionable module port bindings. */
|
||||
extern bool warn_portbinding;
|
||||
|
||||
/* Warn about constant out of bound selects. */
|
||||
extern bool warn_ob_select;
|
||||
|
||||
/* Warn about structures that may have infinite loops. */
|
||||
extern bool warn_inf_loop;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,9 +1,10 @@
|
|||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2002-07-03'
|
||||
timestamp='2009-04-17'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
|
|
@ -21,14 +22,15 @@ timestamp='2002-07-03'
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
#
|
||||
|
|
@ -70,8 +72,8 @@ Report bugs and patches to <config-patches@gnu.org>."
|
|||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
|
@ -83,11 +85,11 @@ Try \`$me --help' for more information."
|
|||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
--time-stamp | --time* | -t )
|
||||
echo "$timestamp" ; exit 0 ;;
|
||||
echo "$timestamp" ; exit ;;
|
||||
--version | -v )
|
||||
echo "$version" ; exit 0 ;;
|
||||
echo "$version" ; exit ;;
|
||||
--help | --h* | -h )
|
||||
echo "$usage"; exit 0 ;;
|
||||
echo "$usage"; exit ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
- ) # Use stdin as input.
|
||||
|
|
@ -99,7 +101,7 @@ while test $# -gt 0 ; do
|
|||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo $1
|
||||
exit 0;;
|
||||
exit ;;
|
||||
|
||||
* )
|
||||
break ;;
|
||||
|
|
@ -118,7 +120,10 @@ esac
|
|||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
|
|
@ -144,7 +149,7 @@ case $os in
|
|||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis)
|
||||
-apple | -axis | -knuth | -cray)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
|
|
@ -169,6 +174,10 @@ case $os in
|
|||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco6)
|
||||
os=-sco5v6
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5)
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
|
|
@ -185,6 +194,10 @@ case $os in
|
|||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5v6*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco*)
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
|
|
@ -228,40 +241,57 @@ case $basic_machine in
|
|||
| a29k \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| fido | fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k \
|
||||
| m32r | m68000 | m68k | m88k | mcore \
|
||||
| ip2k | iq2000 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
| mips64octeon | mips64octeonel \
|
||||
| mips64orion | mips64orionel \
|
||||
| mips64r5900 | mips64r5900el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
| ns16k | ns32k \
|
||||
| openrisc | or32 \
|
||||
| or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| tahoe | thumb | tic80 | tron \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xscale | xstormy16 | xtensa \
|
||||
| z8k)
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
|
|
@ -271,6 +301,9 @@ case $basic_machine in
|
|||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||
;;
|
||||
ms1)
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
|
|
@ -290,48 +323,67 @@ case $basic_machine in
|
|||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c54x-* \
|
||||
| clipper-* | cydra-* \
|
||||
| avr-* | avr32-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* \
|
||||
| m32r-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | mcore-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
| mips64octeon-* | mips64octeonel-* \
|
||||
| mips64orion-* | mips64orionel-* \
|
||||
| mips64r5900-* | mips64r5900el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nios-* | nios2-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
||||
| xtensa-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
| z8k-* | z80-*)
|
||||
;;
|
||||
# Recognize the basic CPU types without company name, with glob match.
|
||||
xtensa*)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
|
|
@ -349,6 +401,9 @@ case $basic_machine in
|
|||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
basic_machine=m68010-adobe
|
||||
os=-scout
|
||||
|
|
@ -363,6 +418,12 @@ case $basic_machine in
|
|||
basic_machine=a29k-none
|
||||
os=-bsd
|
||||
;;
|
||||
amd64)
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
amd64-*)
|
||||
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
os=-sysv
|
||||
|
|
@ -386,6 +447,10 @@ case $basic_machine in
|
|||
basic_machine=m68k-apollo
|
||||
os=-bsd
|
||||
;;
|
||||
aros)
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
|
|
@ -394,10 +459,22 @@ case $basic_machine in
|
|||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
blackfin)
|
||||
basic_machine=bfin-unknown
|
||||
os=-linux
|
||||
;;
|
||||
blackfin-*)
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
convex-c1)
|
||||
basic_machine=c1-convex
|
||||
os=-bsd
|
||||
|
|
@ -422,12 +499,27 @@ case $basic_machine in
|
|||
basic_machine=j90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
craynv)
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
crisv32 | crisv32-* | etraxfs*)
|
||||
basic_machine=crisv32-axis
|
||||
;;
|
||||
cris | cris-* | etrax*)
|
||||
basic_machine=cris-axis
|
||||
;;
|
||||
crx)
|
||||
basic_machine=crx-unknown
|
||||
os=-elf
|
||||
;;
|
||||
da30 | da30-*)
|
||||
basic_machine=m68k-da30
|
||||
;;
|
||||
|
|
@ -450,6 +542,14 @@ case $basic_machine in
|
|||
basic_machine=m88k-motorola
|
||||
os=-sysv3
|
||||
;;
|
||||
dicos)
|
||||
basic_machine=i686-pc
|
||||
os=-dicos
|
||||
;;
|
||||
djgpp)
|
||||
basic_machine=i586-pc
|
||||
os=-msdosdjgpp
|
||||
;;
|
||||
dpx20 | dpx20-*)
|
||||
basic_machine=rs6000-bull
|
||||
os=-bosx
|
||||
|
|
@ -600,6 +700,14 @@ case $basic_machine in
|
|||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
;;
|
||||
m68knommu-*)
|
||||
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
|
|
@ -615,6 +723,10 @@ case $basic_machine in
|
|||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
basic_machine=arm-unknown
|
||||
os=-mingw32ce
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
|
|
@ -628,10 +740,6 @@ case $basic_machine in
|
|||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
|
|
@ -644,6 +752,9 @@ case $basic_machine in
|
|||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
;;
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
|
|
@ -719,9 +830,12 @@ case $basic_machine in
|
|||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
or32 | or32-*)
|
||||
openrisc | openrisc-*)
|
||||
basic_machine=or32-unknown
|
||||
os=-coff
|
||||
;;
|
||||
os400)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-os400
|
||||
;;
|
||||
OSE68000 | ose68000)
|
||||
basic_machine=m68000-ericsson
|
||||
|
|
@ -739,55 +853,75 @@ case $basic_machine in
|
|||
basic_machine=i860-intel
|
||||
os=-osf
|
||||
;;
|
||||
parisc)
|
||||
basic_machine=hppa-unknown
|
||||
os=-linux
|
||||
;;
|
||||
parisc-*)
|
||||
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
pbd)
|
||||
basic_machine=sparc-tti
|
||||
;;
|
||||
pbb)
|
||||
basic_machine=m68k-tti
|
||||
;;
|
||||
pc532 | pc532-*)
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pc98)
|
||||
basic_machine=i386-pc
|
||||
;;
|
||||
pc98-*)
|
||||
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
pentiumpro | p6 | 6x86 | athlon)
|
||||
pentiumpro | p6 | 6x86 | athlon | athlon_*)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentiumii | pentium2)
|
||||
pentiumii | pentium2 | pentiumiii | pentium3)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium4)
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumii-* | pentium2-*)
|
||||
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium4-*)
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
;;
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
;;
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
;;
|
||||
;;
|
||||
ppcle-* | powerpclittle-*)
|
||||
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64) basic_machine=powerpc64-unknown
|
||||
;;
|
||||
;;
|
||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||
basic_machine=powerpc64le-unknown
|
||||
;;
|
||||
;;
|
||||
ppc64le-* | powerpc64little-*)
|
||||
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
|
|
@ -798,6 +932,10 @@ case $basic_machine in
|
|||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
|
|
@ -818,6 +956,20 @@ case $basic_machine in
|
|||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
sb1)
|
||||
basic_machine=mipsisa64sb1-unknown
|
||||
;;
|
||||
sb1el)
|
||||
basic_machine=mipsisa64sb1el-unknown
|
||||
;;
|
||||
sde)
|
||||
basic_machine=mipsisa32-sde
|
||||
os=-elf
|
||||
;;
|
||||
sei)
|
||||
basic_machine=mips-sei
|
||||
os=-seiux
|
||||
;;
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
|
|
@ -825,6 +977,12 @@ case $basic_machine in
|
|||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparclite-wrs | simso-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
|
|
@ -883,7 +1041,7 @@ case $basic_machine in
|
|||
sun386 | sun386i | roadrunner)
|
||||
basic_machine=i386-sun
|
||||
;;
|
||||
sv1)
|
||||
sv1)
|
||||
basic_machine=sv1-cray
|
||||
os=-unicos
|
||||
;;
|
||||
|
|
@ -891,10 +1049,6 @@ case $basic_machine in
|
|||
basic_machine=i386-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
t3d)
|
||||
basic_machine=alpha-cray
|
||||
os=-unicos
|
||||
;;
|
||||
t3e)
|
||||
basic_machine=alphaev5-cray
|
||||
os=-unicos
|
||||
|
|
@ -907,6 +1061,18 @@ case $basic_machine in
|
|||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
|
|
@ -920,6 +1086,10 @@ case $basic_machine in
|
|||
tower | tower-32)
|
||||
basic_machine=m68k-ncr
|
||||
;;
|
||||
tpf)
|
||||
basic_machine=s390x-ibm
|
||||
os=-tpf
|
||||
;;
|
||||
udi29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
|
|
@ -941,8 +1111,8 @@ case $basic_machine in
|
|||
os=-vms
|
||||
;;
|
||||
vpp*|vx|vx-*)
|
||||
basic_machine=f301-fujitsu
|
||||
;;
|
||||
basic_machine=f301-fujitsu
|
||||
;;
|
||||
vxworks960)
|
||||
basic_machine=i960-wrs
|
||||
os=-vxworks
|
||||
|
|
@ -963,11 +1133,11 @@ case $basic_machine in
|
|||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
windows32)
|
||||
basic_machine=i386-pc
|
||||
os=-windows32-msvcrt
|
||||
xbox)
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
xps | xps100)
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
ymp)
|
||||
|
|
@ -978,6 +1148,10 @@ case $basic_machine in
|
|||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
;;
|
||||
z80-*-coff)
|
||||
basic_machine=z80-unknown
|
||||
os=-sim
|
||||
;;
|
||||
none)
|
||||
basic_machine=none-none
|
||||
os=-none
|
||||
|
|
@ -997,6 +1171,9 @@ case $basic_machine in
|
|||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
mmix)
|
||||
basic_machine=mmix-knuth
|
||||
;;
|
||||
rs6000)
|
||||
basic_machine=rs6000-ibm
|
||||
;;
|
||||
|
|
@ -1013,16 +1190,13 @@ case $basic_machine in
|
|||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
|
||||
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparc | sparcv9 | sparcv9b)
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
cydra)
|
||||
basic_machine=cydra-cydrome
|
||||
;;
|
||||
orion)
|
||||
|
|
@ -1037,10 +1211,6 @@ case $basic_machine in
|
|||
pmac | pmac-mpw)
|
||||
basic_machine=powerpc-apple
|
||||
;;
|
||||
c4x*)
|
||||
basic_machine=c4x-none
|
||||
os=-coff
|
||||
;;
|
||||
*-unknown)
|
||||
# Make sure to match an already-canonicalized machine name.
|
||||
;;
|
||||
|
|
@ -1092,22 +1262,28 @@ case $os in
|
|||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -kopensolaris* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* \
|
||||
| -aos* | -aros* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -openbsd* | -solidbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*)
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
|
|
@ -1119,16 +1295,24 @@ case $os in
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
-nto-qnx*)
|
||||
;;
|
||||
-nto*)
|
||||
os=-nto-qnx
|
||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
os=`echo $os | sed -e 's|mac|macos|'`
|
||||
;;
|
||||
-linux-dietlibc)
|
||||
os=-linux-dietlibc
|
||||
;;
|
||||
-linux*)
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
-sunos5*)
|
||||
os=`echo $os | sed -e 's|sunos5|solaris2|'`
|
||||
;;
|
||||
|
|
@ -1138,6 +1322,9 @@ case $os in
|
|||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
os=-wince
|
||||
;;
|
||||
|
|
@ -1159,6 +1346,9 @@ case $os in
|
|||
-atheos*)
|
||||
os=-atheos
|
||||
;;
|
||||
-syllable*)
|
||||
os=-syllable
|
||||
;;
|
||||
-386bsd)
|
||||
os=-bsd
|
||||
;;
|
||||
|
|
@ -1169,7 +1359,7 @@ case $os in
|
|||
os=-rtmk-nova
|
||||
;;
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
os=-nextstep2
|
||||
;;
|
||||
-nsk*)
|
||||
os=-nsk
|
||||
|
|
@ -1181,6 +1371,9 @@ case $os in
|
|||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
os=-sysv3
|
||||
;;
|
||||
|
|
@ -1208,8 +1401,20 @@ case $os in
|
|||
-xenix)
|
||||
os=-xenix
|
||||
;;
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
os=-mint
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
os=-mint
|
||||
;;
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
|
|
@ -1233,6 +1438,12 @@ else
|
|||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
|
|
@ -1242,11 +1453,14 @@ case $basic_machine in
|
|||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
;;
|
||||
pdp11-*)
|
||||
pdp11-*)
|
||||
os=-none
|
||||
;;
|
||||
*-dec | vax-*)
|
||||
|
|
@ -1267,6 +1481,9 @@ case $basic_machine in
|
|||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
|
|
@ -1285,9 +1502,15 @@ case $basic_machine in
|
|||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-haiku)
|
||||
os=-haiku
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
|
|
@ -1339,19 +1562,19 @@ case $basic_machine in
|
|||
*-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
*-gould)
|
||||
*-gould)
|
||||
os=-sysv
|
||||
;;
|
||||
*-highlevel)
|
||||
*-highlevel)
|
||||
os=-bsd
|
||||
;;
|
||||
*-encore)
|
||||
os=-bsd
|
||||
;;
|
||||
*-sgi)
|
||||
*-sgi)
|
||||
os=-irix
|
||||
;;
|
||||
*-siemens)
|
||||
*-siemens)
|
||||
os=-sysv4
|
||||
;;
|
||||
*-masscomp)
|
||||
|
|
@ -1420,9 +1643,15 @@ case $basic_machine in
|
|||
-mvs* | -opened*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-os400*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-ptx*)
|
||||
vendor=sequent
|
||||
;;
|
||||
-tpf*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-vxsim* | -vxworks* | -windiss*)
|
||||
vendor=wrs
|
||||
;;
|
||||
|
|
@ -1447,7 +1676,7 @@ case $basic_machine in
|
|||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
exit 0
|
||||
exit
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ int cmdfile_stack_ptr = 0;
|
|||
\n { cflloc.first_line += 1; }
|
||||
|
||||
|
||||
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
|
||||
|
||||
"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
|
||||
|
||||
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static void translate_file_name(char*text)
|
|||
};
|
||||
|
||||
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
|
||||
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT
|
||||
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT TOK_PARAMETER
|
||||
%token TOK_INTEGER_WIDTH
|
||||
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
||||
|
||||
|
|
@ -135,6 +135,13 @@ item
|
|||
free(tmp);
|
||||
}
|
||||
|
||||
| TOK_PARAMETER TOK_PLUSARG
|
||||
{ char*tmp = substitutions($2);
|
||||
process_parameter(tmp);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
| TOK_DEFINE TOK_PLUSARG
|
||||
{ process_define($2);
|
||||
free($2);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,10 @@ extern void process_include_dir(const char*name);
|
|||
|
||||
/* Add a new -D define. */
|
||||
extern void process_define(const char*name);
|
||||
|
||||
|
||||
/* Add a new parameter definition */
|
||||
extern void process_parameter(const char*name);
|
||||
|
||||
/* -v */
|
||||
extern int verbose_flag;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ iverilog - Icarus Verilog compiler
|
|||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-dname] [-g1995|-g2001|-g2005|-g<feature>]
|
||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] [\-pflag=value]
|
||||
[\-dname] [\-g1995|\-g2001|\-g2005|\-g<feature>]
|
||||
[\-Iincludedir] [\-mmodule] [\-Mfile] [\-Nfile] [\-ooutputfilename]
|
||||
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
|
|
@ -18,7 +18,6 @@ simulation, and \fIfpga\fP for synthesis. Other target
|
|||
types are added as code generators are implemented.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
\fIiverilog\fP accepts the following options:
|
||||
.TP 8
|
||||
.B -B\fIbase\fP
|
||||
|
|
@ -260,7 +259,8 @@ after a \fB-Wall\fP argument to suppress isolated warning types.
|
|||
|
||||
.TP 8
|
||||
.B all
|
||||
This enables the implicit, portbind and timescale warning categories.
|
||||
This enables the implicit, portbind, select-range and timescale warning
|
||||
categories.
|
||||
|
||||
.TP 8
|
||||
.B implicit
|
||||
|
|
@ -274,6 +274,12 @@ This enables warnings for ports of module instantiations that are not
|
|||
connected but probably should be. Dangling input ports, for example,
|
||||
will generate a warning.
|
||||
|
||||
.TP 8
|
||||
.B select-range
|
||||
This enables warnings for constant out of bound selects. This includes
|
||||
partial or fully out of bound selects as well as a select using 'bx as
|
||||
an index.
|
||||
|
||||
.TP 8
|
||||
.B timescale
|
||||
This enables warnings for inconsistent use of the timescale
|
||||
|
|
@ -369,7 +375,7 @@ on to the next library directory.
|
|||
|
||||
.TP 8
|
||||
.B +libdir+\fIdir\fP
|
||||
This is another way to specify library directories. See the -y flag.
|
||||
This is another way to specify library directories. See the \-y flag.
|
||||
|
||||
.TP 8
|
||||
.B +libdir-nocase+\fIdir\fP
|
||||
|
|
@ -434,11 +440,11 @@ To compile hello.v to an executable file called a.out:
|
|||
|
||||
To compile hello.v to an executable file called hello:
|
||||
|
||||
iverilog -o hello hello.v
|
||||
iverilog \-o hello hello.v
|
||||
|
||||
To compile and run explicitly using the vvp runtime:
|
||||
|
||||
iverilog -ohello.vvp -tvvp hello.v
|
||||
iverilog \-ohello.vvp \-tvvp hello.v
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
|
|
|
|||
|
|
@ -167,6 +167,12 @@ typedef struct t_command_file {
|
|||
p_command_file cmd_file_head = NULL; /* The FIFO head */
|
||||
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
|
||||
|
||||
/* Temprarily store parameter definition from command line and
|
||||
* parse it after we have delt with command file
|
||||
*/
|
||||
static const char** defparm_base = 0;
|
||||
static int defparm_size = 0;
|
||||
|
||||
/* Function to add a command file name to the FIFO. */
|
||||
void add_cmd_file(const char* filename)
|
||||
{
|
||||
|
|
@ -469,6 +475,7 @@ static void process_warning_switch(const char*name)
|
|||
if (strcmp(name,"all") == 0) {
|
||||
process_warning_switch("implicit");
|
||||
process_warning_switch("portbind");
|
||||
process_warning_switch("select-range");
|
||||
process_warning_switch("timescale");
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags, 'i'))
|
||||
|
|
@ -476,6 +483,9 @@ static void process_warning_switch(const char*name)
|
|||
} else if (strcmp(name,"portbind") == 0) {
|
||||
if (! strchr(warning_flags, 'p'))
|
||||
strcat(warning_flags, "p");
|
||||
} else if (strcmp(name,"select-range") == 0) {
|
||||
if (! strchr(warning_flags, 's'))
|
||||
strcat(warning_flags, "s");
|
||||
} else if (strcmp(name,"timescale") == 0) {
|
||||
if (! strchr(warning_flags, 't'))
|
||||
strcat(warning_flags, "t");
|
||||
|
|
@ -496,6 +506,12 @@ static void process_warning_switch(const char*name)
|
|||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-select-range") == 0) {
|
||||
char*cp = strchr(warning_flags, 's');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-timescale") == 0) {
|
||||
char*cp = strchr(warning_flags, 't');
|
||||
if (cp) while (*cp) {
|
||||
|
|
@ -530,6 +546,11 @@ void process_define(const char*name)
|
|||
fprintf(defines_file,"D:%s\n", name);
|
||||
}
|
||||
|
||||
void process_parameter(const char*name)
|
||||
{
|
||||
fprintf(iconfig_file,"defparam:%s\n", name);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called while processing a file name in a command
|
||||
* file, or a file name on the command line. Look to see if there is a
|
||||
|
|
@ -774,7 +795,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
|
|
@ -798,6 +819,11 @@ int main(int argc, char **argv)
|
|||
case 'E':
|
||||
e_flag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
defparm_size += 1;
|
||||
defparm_base = (const char**)realloc(defparm_base, defparm_size*sizeof(char*));
|
||||
defparm_base[defparm_size-1] = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
fprintf(iconfig_file, "flag:%s\n", optarg);
|
||||
break;
|
||||
|
|
@ -966,6 +992,15 @@ int main(int argc, char **argv)
|
|||
fprintf(defines_file, "M:%s\n", depfile);
|
||||
}
|
||||
|
||||
/* Process parameter definition from command line. The last
|
||||
defined would override previous ones. */
|
||||
int pitr;
|
||||
for (pitr = 0; pitr < defparm_size; pitr++)
|
||||
process_parameter(defparm_base[pitr]);
|
||||
free(defparm_base);
|
||||
defparm_base = 0;
|
||||
defparm_size = 0;
|
||||
|
||||
/* Finally, process all the remaining words on the command
|
||||
line as file names. */
|
||||
for (idx = optind ; idx < argc ; idx += 1)
|
||||
|
|
|
|||
311
elab_expr.cc
311
elab_expr.cc
|
|
@ -2210,12 +2210,12 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
static verinum param_part_select_bits(const verinum&par_val, long wid,
|
||||
long lsv, long par_lsv)
|
||||
long lsv)
|
||||
{
|
||||
verinum result (verinum::Vx, wid, true);
|
||||
|
||||
for (long idx = 0 ; idx < wid ; idx += 1) {
|
||||
long off = idx + lsv - par_lsv;
|
||||
long off = idx + lsv;
|
||||
if (off < 0)
|
||||
result.set(idx, verinum::Vx);
|
||||
else if (off < (long)par_val.len())
|
||||
|
|
@ -2230,7 +2230,7 @@ static verinum param_part_select_bits(const verinum&par_val, long wid,
|
|||
|
||||
// If the input is a string, and the part select is working on
|
||||
// byte boundaries, then make the result into a string.
|
||||
if (par_val.is_string() && (labs(lsv-par_lsv)%8 == 0) && (wid%8 == 0))
|
||||
if (par_val.is_string() && (labs(lsv)%8 == 0) && (wid%8 == 0))
|
||||
return result.as_string();
|
||||
|
||||
return result;
|
||||
|
|
@ -2286,28 +2286,56 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
|
|||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
||||
verinum result = param_part_select_bits(par_ex->value(), wid, lsv, par_lsv);
|
||||
verinum result = param_part_select_bits(par_ex->value(), wid, lsv-par_lsv);
|
||||
NetEConst*result_ex = new NetEConst(result);
|
||||
result_ex->set_line(*this);
|
||||
|
||||
return result_ex;
|
||||
}
|
||||
|
||||
static void warn_param_ob(long par_msv, long par_lsv, bool defined,
|
||||
long par_base, unsigned long wid, long pwid,
|
||||
const LineInfo *info, perm_string name, bool up)
|
||||
{
|
||||
long par_max;
|
||||
|
||||
if (defined) {
|
||||
if (par_msv < par_lsv) par_max = par_lsv-par_msv;
|
||||
else par_max = par_msv-par_lsv;
|
||||
} else {
|
||||
if (pwid < 0) par_max = integer_width;
|
||||
else par_max = pwid;
|
||||
}
|
||||
|
||||
/* Is this a select before the start of the parameter? */
|
||||
if (par_base < 0) {
|
||||
cerr << info->get_fileline() << ": warning: " << name << "["
|
||||
<< par_base;
|
||||
if (up) cerr << "+:";
|
||||
else cerr << "-:";
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
|
||||
/* Is this a select after the end of the parameter? */
|
||||
if (par_base + (long)wid - 1 > par_max) {
|
||||
cerr << info->get_fileline() << ": warning: " << name << "["
|
||||
<< par_base << "+:" << wid << "] is selecting after vector."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
{
|
||||
|
||||
long par_msv, par_lsv;
|
||||
bool flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
|
||||
if (!flag)
|
||||
return 0;
|
||||
if(! calculate_param_range_(des, scope, par_msb, par_msv,
|
||||
par_lsb, par_lsv)) return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
if (base == 0)
|
||||
return 0;
|
||||
if (base == 0) return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
|
@ -2323,22 +2351,139 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
|||
// Handle the special case that the base is constant. In this
|
||||
// case, just precalculate the entire constant result.
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
if (! base_c->value().is_defined()) {
|
||||
NetEConst *ex;
|
||||
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||
ex->set_line(*this);
|
||||
if (warn_ob_select) {
|
||||
perm_string name = peek_tail_name(path_);
|
||||
cerr << get_fileline() << ": warning: " << name
|
||||
<< "['bx+:" << wid
|
||||
<< "] is always outside vector." << endl;
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
long lsv = base_c->value().as_long();
|
||||
long par_base = par_lsv;
|
||||
|
||||
// Watch out for reversed bit numbering. We're making
|
||||
// the part select from LSB to MSB.
|
||||
if (par_msv < par_lsv)
|
||||
lsv = lsv - wid + 1;
|
||||
if (par_msv < par_lsv) {
|
||||
par_base = lsv;
|
||||
lsv = par_lsv - wid + 1;
|
||||
}
|
||||
|
||||
if (warn_ob_select) {
|
||||
bool defined = true;
|
||||
// Check to see if the parameter has a defined range.
|
||||
if (par_msb == 0) {
|
||||
assert(par_lsb == 0);
|
||||
defined = false;
|
||||
}
|
||||
// Get the parameter values width.
|
||||
long pwid = -1;
|
||||
if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
|
||||
perm_string name = peek_tail_name(path_);
|
||||
warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
|
||||
pwid, this, name, true);
|
||||
}
|
||||
verinum result = param_part_select_bits(par_ex->value(), wid,
|
||||
lsv, par_lsv);
|
||||
lsv-par_base);
|
||||
NetEConst*result_ex = new NetEConst(result);
|
||||
result_ex->set_line(*this);
|
||||
return result_ex;
|
||||
}
|
||||
|
||||
if ((par_msv < par_lsv) && (wid>1))
|
||||
base = make_add_expr(base, 1-(long)wid);
|
||||
if (par_msv >= par_lsv) {
|
||||
if (par_lsv != 0) base = make_add_expr(base, -par_lsv);
|
||||
} else {
|
||||
base = make_sub_expr(par_lsv-wid+1, base);
|
||||
}
|
||||
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
tmp = new NetESelect(tmp, base, wid);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
{
|
||||
long par_msv, par_lsv;
|
||||
if(! calculate_param_range_(des, scope, par_msb, par_msv,
|
||||
par_lsb, par_lsv)) return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
if (base == 0) return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Calculate part select "
|
||||
<< "[" << *base << "-:" << wid << "] from range "
|
||||
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
|
||||
|
||||
// Handle the special case that the base is constant. In this
|
||||
// case, just precalculate the entire constant result.
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
if (! base_c->value().is_defined()) {
|
||||
NetEConst *ex;
|
||||
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||
ex->set_line(*this);
|
||||
if (warn_ob_select) {
|
||||
perm_string name = peek_tail_name(path_);
|
||||
cerr << get_fileline() << ": warning: " << name
|
||||
<< "['bx-:" << wid
|
||||
<< "] is always outside vector." << endl;
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
long lsv = base_c->value().as_long();
|
||||
long par_base = par_lsv + wid - 1;
|
||||
|
||||
// Watch out for reversed bit numbering. We're making
|
||||
// the part select from LSB to MSB.
|
||||
if (par_msv < par_lsv) {
|
||||
par_base = lsv;
|
||||
lsv = par_lsv;
|
||||
}
|
||||
|
||||
if (warn_ob_select) {
|
||||
bool defined = true;
|
||||
// Check to see if the parameter has a defined range.
|
||||
if (par_msb == 0) {
|
||||
assert(par_lsb == 0);
|
||||
defined = false;
|
||||
}
|
||||
// Get the parameter values width.
|
||||
long pwid = -1;
|
||||
if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
|
||||
perm_string name = peek_tail_name(path_);
|
||||
warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
|
||||
pwid, this, name, false);
|
||||
}
|
||||
|
||||
verinum result = param_part_select_bits(par_ex->value(), wid,
|
||||
lsv-par_base);
|
||||
NetEConst*result_ex = new NetEConst(result);
|
||||
result_ex->set_line(*this);
|
||||
return result_ex;
|
||||
}
|
||||
|
||||
if (par_msv >= par_lsv) {
|
||||
if (long offset = par_lsv+wid-1) {
|
||||
base = make_add_expr(base, -offset);
|
||||
}
|
||||
} else {
|
||||
base = make_sub_expr(par_lsv, base);
|
||||
}
|
||||
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
tmp = new NetESelect(tmp, base, wid);
|
||||
|
|
@ -2385,49 +2530,16 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
|
||||
// NOTE TO SELF (continued): The code below should be
|
||||
// rewritten in the above format, as I get to it.
|
||||
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO) {
|
||||
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
ivl_assert(*this, index_tail.lsb);
|
||||
|
||||
/* Get and evaluate the width of the index
|
||||
select. This must be constant. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
need_constant_expr = false;
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
if (idx_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1) {
|
||||
idx_ex = make_add_expr(idx_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
|
||||
/* Wrap the param expression with a part select. */
|
||||
tmp = new NetESelect(tmp, idx_ex, wid);
|
||||
|
||||
|
||||
} else if (use_sel == index_component_t::SEL_BIT) {
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
|
|
@ -2768,15 +2880,47 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
if (net->sig()->sb_to_idx(lsv) == 0 &&
|
||||
wid == net->vector_width()) {
|
||||
delete base;
|
||||
net->cast_signed(false);
|
||||
return net;
|
||||
}
|
||||
|
||||
long offset = 0;
|
||||
if (net->msi() < net->lsi()) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
// Otherwise, make a part select that covers the right
|
||||
// range.
|
||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
|
||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
|
||||
offset));
|
||||
if (warn_ob_select) {
|
||||
long rel_base = net->sig()->sb_to_idx(lsv) + offset;
|
||||
if (rel_base < 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "[" << lsv << "+:" << wid
|
||||
<< "] is selecting before vector." << endl;
|
||||
}
|
||||
if (rel_base + wid > net->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "[" << lsv << "+:" << wid
|
||||
<< "] is selecting after vector." << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Return 'bx for an undefined base.
|
||||
ex = new NetEConst(verinum(verinum::Vx, 1, false));
|
||||
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||
ex->set_line(*this);
|
||||
delete base;
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: " << net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "['bx+:" << wid
|
||||
<< "] is always outside vector." << endl;
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
|
@ -2787,11 +2931,9 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
|
||||
if (net->msi() > net->lsi()) {
|
||||
if (long offset = net->lsi())
|
||||
base = make_add_expr(base, 0-offset);
|
||||
base = make_add_expr(base, -offset);
|
||||
} else {
|
||||
long vwid = net->lsi() - net->msi() + 1;
|
||||
long offset = net->msi();
|
||||
base = make_sub_expr(vwid-offset-wid, base);
|
||||
base = make_sub_expr(net->lsi()-wid+1, base);
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(net, base, wid);
|
||||
|
|
@ -2830,15 +2972,47 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
|
||||
wid == net->vector_width()) {
|
||||
delete base;
|
||||
net->cast_signed(false);
|
||||
return net;
|
||||
}
|
||||
|
||||
long offset = 0;
|
||||
if (net->msi() > net->lsi()) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
// Otherwise, make a part select that covers the right
|
||||
// range.
|
||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)-wid+1));
|
||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
|
||||
offset));
|
||||
if (warn_ob_select) {
|
||||
long rel_base = net->sig()->sb_to_idx(lsv) + offset;
|
||||
if (rel_base < 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "[" << lsv << "+:" << wid
|
||||
<< "] is selecting before vector." << endl;
|
||||
}
|
||||
if (rel_base + wid > net->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "[" << lsv << "-:" << wid
|
||||
<< "] is selecting after vector." << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Return 'bx for an undefined base.
|
||||
ex = new NetEConst(verinum(verinum::Vx, 1, false));
|
||||
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||
ex->set_line(*this);
|
||||
delete base;
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: " << net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "['bx-:" << wid
|
||||
<< "] is always outside vector." << endl;
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
|
@ -2847,16 +3021,19 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
return ss;
|
||||
}
|
||||
|
||||
long offset = net->lsi();
|
||||
NetExpr*base_adjusted = wid > 1
|
||||
? make_add_expr(base,1-(long)wid-offset)
|
||||
: (offset == 0? base : make_add_expr(base, 0-offset));
|
||||
NetESelect*ss = new NetESelect(net, base_adjusted, wid);
|
||||
if (net->msi() > net->lsi()) {
|
||||
if (long offset = net->lsi()+wid-1)
|
||||
base = make_add_expr(base, -offset);
|
||||
} else {
|
||||
base = make_sub_expr(net->lsi(), base);
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(net, base, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate part "
|
||||
<< "select base="<< *base_adjusted << ", wid="<< wid << endl;
|
||||
<< "select base="<< *base << ", wid="<< wid << endl;
|
||||
}
|
||||
|
||||
return ss;
|
||||
|
|
|
|||
80
elab_lval.cc
80
elab_lval.cc
|
|
@ -476,14 +476,78 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
|
||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
base = make_sub_expr(reg->lsb(), base);
|
||||
else if (reg->lsb() != 0)
|
||||
base = make_add_expr(base, - reg->lsb());
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1 ) {
|
||||
base = make_add_expr(base, 1-(long)wid);
|
||||
// Handle the special case that the base is constant. For this
|
||||
// case we can reduce the expression.
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
// For the undefined case just let the constant pass and
|
||||
// we will handle it in the code generator.
|
||||
if (base_c->value().is_defined()) {
|
||||
long lsv = base_c->value().as_long();
|
||||
long offset = 0;
|
||||
if (((reg->msb() < reg->lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((reg->msb() > reg->lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
delete base;
|
||||
base = new NetEConst(verinum(reg->sb_to_idx(lsv) + offset));
|
||||
if (warn_ob_select) {
|
||||
long rel_base = reg->sb_to_idx(lsv) + offset;
|
||||
if (rel_base < 0) {
|
||||
cerr << get_fileline() << ": warning: " << reg->name();
|
||||
if (reg->array_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << lsv;
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
if (rel_base + wid > reg->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: " << reg->name();
|
||||
if (reg->array_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << lsv;
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: " << reg->name();
|
||||
if (reg->array_dimensions() > 0) cerr << "[]";
|
||||
cerr << "['bx";
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is always outside vector." << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
if (reg->msb() > reg->lsb()) {
|
||||
if (long offset = reg->lsb())
|
||||
base = make_add_expr(base, -offset);
|
||||
} else {
|
||||
base = make_sub_expr(reg->lsb()-wid+1, base);
|
||||
}
|
||||
} else {
|
||||
// This is assumed to be a SEL_IDX_DO.
|
||||
if (reg->msb() > reg->lsb()) {
|
||||
if (long offset = reg->lsb()+wid-1)
|
||||
base = make_add_expr(base, -offset);
|
||||
} else {
|
||||
base = make_sub_expr(reg->lsb(), base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate)
|
||||
|
|
|
|||
58
elab_net.cc
58
elab_net.cc
|
|
@ -238,15 +238,33 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
return 0;
|
||||
}
|
||||
|
||||
long midx_val = tmp->value().as_long();
|
||||
midx = sig->sb_to_idx(midx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
/* The width (a constant) is calculated here. */
|
||||
unsigned long wid = 0;
|
||||
bool flag = calculate_up_do_width_(des, scope, wid);
|
||||
if (! flag)
|
||||
if (! flag) return false;
|
||||
|
||||
/* We have an undefined index and that is out of range. */
|
||||
if (! tmp->value().is_defined()) {
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< sig->name();
|
||||
if (sig->array_dimensions() > 0) cerr << "[]";
|
||||
cerr << "['bx";
|
||||
if (index_tail.sel ==
|
||||
index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is always outside vector."
|
||||
<< endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
long midx_val = tmp->value().as_long();
|
||||
midx = sig->sb_to_idx(midx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(midx_val+wid-1);
|
||||
|
|
@ -260,9 +278,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
}
|
||||
|
||||
/* Warn about an indexed part select that is out of range. */
|
||||
if (midx >= (long)sig->vector_width() || lidx < 0) {
|
||||
cerr << get_fileline() << ": warning: Indexed part "
|
||||
"select " << sig->name();
|
||||
if (warn_ob_select && (lidx < 0)) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->array_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->array_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
|
|
@ -272,7 +300,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is out of range." << endl;
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
|
|
@ -424,6 +452,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||
// The default word select is the first.
|
||||
long widx = 0;
|
||||
// The widx_val is the word select as entered in the source
|
||||
// code. It's used for error messages.
|
||||
long widx_val = 0;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
|
|
@ -462,8 +493,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
long widx_val = tmp->value().as_long();
|
||||
widx = sig->array_index_to_address(widx_val);
|
||||
widx_val = tmp->value().as_long();
|
||||
if (sig->array_index_is_valid(widx_val))
|
||||
widx = sig->array_index_to_address(widx_val);
|
||||
else
|
||||
widx = -1;
|
||||
delete tmp_ex;
|
||||
|
||||
if (debug_elaborate)
|
||||
|
|
@ -529,7 +563,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
if (widx < 0 || widx >= (long) sig->pin_count()) {
|
||||
cerr << get_fileline() << ": warning: ignoring out of "
|
||||
"bounds l-value array access "
|
||||
<< sig->name() << "[" << widx << "]." << endl;
|
||||
<< sig->name() << "[" << widx_val << "]." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -563,7 +563,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
{
|
||||
// Check that the loop_index variable was declared in a
|
||||
// genvar statement.
|
||||
if (container->find_genvar(loop_index) == 0) {
|
||||
NetScope*scope = container;
|
||||
while (scope && !scope->find_genvar(loop_index))
|
||||
scope = scope->parent();
|
||||
if (!scope) {
|
||||
cerr << get_fileline() << ": error: genvar is missing for "
|
||||
"generate \"loop\" variable '" << loop_index << "'."
|
||||
<< endl;
|
||||
|
|
@ -1021,6 +1024,12 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
|
|||
|
||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
{
|
||||
// Add the genvars to this scope.
|
||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); cur++ ) {
|
||||
scope->add_genvar((*cur).first, (*cur).second);
|
||||
}
|
||||
|
||||
// Scan the generated scope for nested generate schemes,
|
||||
// and *generate* new scopes, which is slightly different
|
||||
// from simple elaboration.
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
|||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
if (scope == 0) {
|
||||
if (fscope == 0) {
|
||||
cerr << (*cur).second->get_fileline() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
|
|
|
|||
74
elaborate.cc
74
elaborate.cc
|
|
@ -1571,43 +1571,34 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
|||
module or primitive, it interprets them as parameter
|
||||
overrides. Correct that misconception here. */
|
||||
if (overrides_) {
|
||||
PDelays tmp_del;
|
||||
tmp_del.set_delays(overrides_, false);
|
||||
tmp_del.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
|
||||
|
||||
if (dynamic_cast<NetEConst*> (rise_expr)) {
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Delay expressions must be "
|
||||
<< "constant for primitives." << endl;
|
||||
cerr << get_fileline() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
if (overrides_->count() > 2) {
|
||||
cerr << get_fileline() << ": error: UDPs take at most two "
|
||||
"delay arguments." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (dynamic_cast<NetEConst*> (fall_expr)) {
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Delay expressions must be "
|
||||
<< "constant for primitives." << endl;
|
||||
cerr << get_fileline() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
PDelays tmp_del;
|
||||
tmp_del.set_delays(overrides_, false);
|
||||
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
|
||||
decay_expr);
|
||||
|
||||
if (! dynamic_cast<NetEConst*> (rise_expr)) {
|
||||
cerr << get_fileline() << ": error: UDP rising delay "
|
||||
"expression must be constant." << endl;
|
||||
cerr << get_fileline() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (! dynamic_cast<NetEConst*> (fall_expr)) {
|
||||
cerr << get_fileline() << ": error: UDP falling delay "
|
||||
"expression must be constant." << endl;
|
||||
cerr << get_fileline() << ": : Cannot calculate "
|
||||
<< *fall_expr << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamic_cast<NetEConst*> (decay_expr)) {
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Delay expressions must be "
|
||||
<< "constant for primitives." << endl;
|
||||
cerr << get_fileline() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
assert(udp);
|
||||
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
|
||||
net->rise_time(rise_expr);
|
||||
|
|
@ -4235,8 +4226,23 @@ class elaborate_root_scope_t : public elaborator_work_item_t {
|
|||
|
||||
virtual void elaborate_runrun()
|
||||
{
|
||||
Module::replace_t stub;
|
||||
if (! rmod_->elaborate_scope(des, scope_, stub))
|
||||
Module::replace_t root_repl;
|
||||
for (list<Module::named_expr_t>::iterator cur = Module::user_defparms.begin()
|
||||
; cur != Module::user_defparms.end() ; cur++) {
|
||||
|
||||
pform_name_t tmp_name = cur->first;
|
||||
if (peek_head_name(tmp_name) != scope_->basename())
|
||||
continue;
|
||||
|
||||
tmp_name.pop_front();
|
||||
if (tmp_name.size() != 1)
|
||||
continue;
|
||||
|
||||
NetExpr*tmp_expr = cur->second->elaborate_pexpr(des, scope_);
|
||||
root_repl[peek_head_name(tmp_name)] = tmp_expr;
|
||||
}
|
||||
|
||||
if (! rmod_->elaborate_scope(des, scope_, root_repl))
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(expr_type());
|
||||
osig->set_signed(has_sign());
|
||||
|
||||
perm_string oname = osig->scope()->local_symbol();
|
||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||
|
|
@ -390,6 +391,7 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(expr_type());
|
||||
osig->set_signed(has_sign());
|
||||
osig->local_flag(true);
|
||||
|
||||
connect(powr->pin_Result(), osig->pin(0));
|
||||
|
|
@ -426,6 +428,7 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(expr_type());
|
||||
osig->set_signed(has_sign());
|
||||
osig->local_flag(true);
|
||||
|
||||
connect(mult->pin_Result(), osig->pin(0));
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ iverilog-vpi - Compile front end for VPI modules
|
|||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog-vpi
|
||||
[--name=\fIname\fP]
|
||||
[\-\-name=\fIname\fP]
|
||||
\fIsourcefile\fP...
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
|
@ -20,7 +20,6 @@ first source file is named \fIfoo.c\fP, the output becomes
|
|||
\fIfoo.vpi\fP.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
\fIiverilog-vpi\fP accepts the following options:
|
||||
.TP 8
|
||||
.B -l\fIlibrary\fP
|
||||
|
|
@ -104,9 +103,9 @@ requests a 32bit vpi binary instead of the default 64bit binary.
|
|||
.P
|
||||
Example GNU makefile that takes advantage of these flags:
|
||||
.IP "" 4
|
||||
CFLAGS = -Wall -O $(CFLAGS_$@)
|
||||
CFLAGS = \-Wall \-O $(CFLAGS_$@)
|
||||
.br
|
||||
VPI_CFLAGS := $(shell iverilog-vpi --cflags)
|
||||
VPI_CFLAGS := $(shell iverilog-vpi \-\-cflags)
|
||||
.br
|
||||
CFLAGS_messagev.o = $(VPI_CFLAGS)
|
||||
.br
|
||||
|
|
|
|||
20
lexor.lex
20
lexor.lex
|
|
@ -71,11 +71,11 @@ void reset_lexor();
|
|||
static void line_directive();
|
||||
static void line_directive2();
|
||||
|
||||
static verinum*make_unsized_binary(const char*txt);
|
||||
static verinum*make_undef_highz_dec(const char*txt);
|
||||
static verinum*make_unsized_dec(const char*txt);
|
||||
static verinum*make_unsized_octal(const char*txt);
|
||||
static verinum*make_unsized_hex(const char*txt);
|
||||
verinum*make_unsized_binary(const char*txt);
|
||||
verinum*make_undef_highz_dec(const char*txt);
|
||||
verinum*make_unsized_dec(const char*txt);
|
||||
verinum*make_unsized_octal(const char*txt);
|
||||
verinum*make_unsized_hex(const char*txt);
|
||||
|
||||
static int dec_buf_div2(char *buf);
|
||||
|
||||
|
|
@ -667,7 +667,7 @@ void lex_end_table()
|
|||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
static verinum*make_unsized_binary(const char*txt)
|
||||
verinum*make_unsized_binary(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
|
|
@ -725,7 +725,7 @@ static verinum*make_unsized_binary(const char*txt)
|
|||
}
|
||||
|
||||
|
||||
static verinum*make_unsized_octal(const char*txt)
|
||||
verinum*make_unsized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
|
|
@ -792,7 +792,7 @@ static verinum*make_unsized_octal(const char*txt)
|
|||
}
|
||||
|
||||
|
||||
static verinum*make_unsized_hex(const char*txt)
|
||||
verinum*make_unsized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
|
|
@ -919,7 +919,7 @@ static int dec_buf_div2(char *buf)
|
|||
}
|
||||
|
||||
/* Support a single x, z or ? as a decimal constant (from 1364-2005). */
|
||||
static verinum* make_undef_highz_dec(const char* ptr)
|
||||
verinum* make_undef_highz_dec(const char* ptr)
|
||||
{
|
||||
bool signed_flag = false;
|
||||
|
||||
|
|
@ -972,7 +972,7 @@ static verinum* make_undef_highz_dec(const char* ptr)
|
|||
* hard to calculate.
|
||||
*/
|
||||
|
||||
static verinum*make_unsized_dec(const char*ptr)
|
||||
verinum*make_unsized_dec(const char*ptr)
|
||||
{
|
||||
char buf[4096];
|
||||
bool signed_flag = false;
|
||||
|
|
|
|||
9
main.cc
9
main.cc
|
|
@ -115,6 +115,7 @@ bool warn_implicit = false;
|
|||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_inf_loop = false;
|
||||
bool warn_ob_select = false;
|
||||
|
||||
bool error_implicit = false;
|
||||
|
||||
|
|
@ -491,6 +492,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
case 'l':
|
||||
warn_inf_loop = true;
|
||||
break;
|
||||
case 's':
|
||||
warn_ob_select = true;
|
||||
break;
|
||||
case 'p':
|
||||
warn_portbinding = true;
|
||||
break;
|
||||
|
|
@ -528,8 +532,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
<< endl;
|
||||
flag_errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
} else if (strcmp(buf,"defparam") == 0) {
|
||||
parm_to_defparam_list(cp);
|
||||
}
|
||||
}
|
||||
fclose(ifile);
|
||||
}
|
||||
|
|
|
|||
40
mingw.txt
40
mingw.txt
|
|
@ -1,3 +1,8 @@
|
|||
Please NOTE:
|
||||
|
||||
These directions are slightly outdated and need to be updated.
|
||||
The plan is to rewrite all this using the latest MinGW at
|
||||
some time in the not too distant future (CR Aug. 2009)
|
||||
|
||||
|
||||
MINGW PORT OF ICARUS VERILOG
|
||||
|
|
@ -49,7 +54,7 @@ critical, but these are the versions I use.
|
|||
Mingw32-5.x <http://www.mingw.org>
|
||||
... including the sub-packages binutils, gcc-core and gcc-g++
|
||||
if you are given the option.
|
||||
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
|
||||
readline-5.0-1 <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
||||
|
|
@ -79,7 +84,7 @@ Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
|||
self-installing packages. Install msys first, and then msysDTC. Most
|
||||
likely, you want to install them in c:/msys. (The msysDTK is installed
|
||||
in the same location, as it is an add-on.)
|
||||
|
||||
|
||||
This install should be easy and reliable.
|
||||
|
||||
The installation will leave an "msys" icon on your desktop and in the
|
||||
|
|
@ -110,29 +115,6 @@ Finally, as part of installing the mingw32 compilers, remember to add
|
|||
the mingw/bin directory to your path. You will need that to be able to
|
||||
find the compilers later.
|
||||
|
||||
* Install Mingw32 Packages
|
||||
|
||||
There is a collection of precompiled libraries and add-on packages
|
||||
that are intended for use with the Mingw32 compiler. These do not come
|
||||
with simplified Windows installers, but they are pretty easy to
|
||||
install by hand. Icarus Verilog uses the readline-4.2 package from
|
||||
that collection.
|
||||
|
||||
Since I installed Mingw32 in c:\mingw, I also created a
|
||||
Mingw-packages directory called c:\mingw-packages. The install, then,
|
||||
is as easy as this:
|
||||
|
||||
<msys shell>
|
||||
$ cd c:/mingw-packages
|
||||
$ unzip readline-4.2-20010727.zip
|
||||
[lots of inflating...]
|
||||
|
||||
There is no need to adjust your execution path for this package as we
|
||||
are only using a library out of here. However, do remember the
|
||||
directory name, as you will need it later.
|
||||
|
||||
Done. On to the next packages.
|
||||
|
||||
* Install GnuWin32 Packages
|
||||
|
||||
The GnuWin32 project is a collections of open source programs and
|
||||
|
|
@ -148,6 +130,7 @@ You will need these gnuwin32 packages to compile Icarus Verilog:
|
|||
gperf-3.0.1.exe
|
||||
bison-2.1.exe
|
||||
flex-2.5.4a.exe
|
||||
readline-5.0-1.exe
|
||||
|
||||
I suggest creating a common directory for holding all your gnuwin32
|
||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||
|
|
@ -218,8 +201,8 @@ without white space.
|
|||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run these commands:
|
||||
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=c:/iverilog
|
||||
|
||||
|
|
@ -271,7 +254,8 @@ You may find that you need to put some of the prerequisite DLLs into
|
|||
the d:\iverilog\bin directory. These include:
|
||||
|
||||
c:\mingw\bin\mingw10.dll
|
||||
c:\mingw-packages\bin\libreadline.dll
|
||||
c:\gnuwin32\bin\readline.dll
|
||||
c:\gnuwin32\bin\history.dll
|
||||
c:\gnuwin32\bin\bzip2.dll
|
||||
c:\gnuwin32\bin\zlib.dll
|
||||
|
||||
|
|
|
|||
20
net_scope.cc
20
net_scope.cc
|
|
@ -395,28 +395,18 @@ NetEvent* NetScope::find_event(perm_string name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// We only add genvars to a module scope, so we do not need to search
|
||||
// for the module scope here.
|
||||
void NetScope::add_genvar(perm_string name, LineInfo *li)
|
||||
{
|
||||
assert((type_ == MODULE) || (type_ == GENBLOCK));
|
||||
genvars_[name] = li;
|
||||
}
|
||||
|
||||
LineInfo* NetScope::find_genvar(perm_string name)
|
||||
{
|
||||
// genvars are only added to the module so we need to find it
|
||||
// if we are in a sub scope.
|
||||
NetScope *scope = this;
|
||||
while (scope->type() != NetScope::MODULE) {
|
||||
scope = scope->parent();
|
||||
assert(scope != NULL);
|
||||
}
|
||||
|
||||
if (scope->genvars_.find(name) != scope->genvars_.end()) {
|
||||
return scope->genvars_[name];
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (genvars_.find(name) != genvars_.end())
|
||||
return genvars_[name];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_signal(NetNet*net)
|
||||
|
|
|
|||
|
|
@ -914,9 +914,8 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
|||
pin(1).set_dir(Link::INPUT);
|
||||
break;
|
||||
case NetPartSelect::PV:
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(1).set_dir(Link::OUTPUT);
|
||||
break;
|
||||
/* Only a vector to part can be a variable select. */
|
||||
assert(0);
|
||||
}
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
|
||||
|
|
@ -2349,12 +2348,12 @@ NetNet* NetESignal::sig()
|
|||
return net_;
|
||||
}
|
||||
|
||||
unsigned NetESignal::lsi() const
|
||||
long NetESignal::lsi() const
|
||||
{
|
||||
return net_->lsb();
|
||||
}
|
||||
|
||||
unsigned NetESignal::msi() const
|
||||
long NetESignal::msi() const
|
||||
{
|
||||
return net_->msb();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3829,8 +3829,8 @@ class NetESignal : public NetExpr {
|
|||
const NetNet* sig() const;
|
||||
NetNet* sig();
|
||||
// Declared vector dimensions for the signal.
|
||||
unsigned msi() const;
|
||||
unsigned lsi() const;
|
||||
long msi() const;
|
||||
long lsi() const;
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
|
||||
|
|
|
|||
10
parse_misc.h
10
parse_misc.h
|
|
@ -77,4 +77,14 @@ extern UCDriveType uc_drive;
|
|||
extern bool have_timeunit_decl;
|
||||
extern bool have_timeprec_decl;
|
||||
|
||||
/*
|
||||
* Export there functions because we have to generate PENumber class
|
||||
* in pform.cc for user defparam definition from command file.
|
||||
*/
|
||||
extern verinum*make_unsized_dec(const char*txt);
|
||||
extern verinum*make_undef_highz_dec(const char*txt);
|
||||
extern verinum*make_unsized_binary(const char*txt);
|
||||
extern verinum*make_unsized_octal(const char*txt);
|
||||
extern verinum*make_unsized_hex(const char*txt);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
188
pform.cc
188
pform.cc
|
|
@ -42,6 +42,160 @@
|
|||
map<perm_string,Module*> pform_modules;
|
||||
map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
|
||||
/*
|
||||
* Parse configuration file with format <key>=<value>, where key
|
||||
* is the hierarchical name of a valid parameter name, and value
|
||||
* is the value user wants to assign to. The value should be constant.
|
||||
*/
|
||||
void parm_to_defparam_list(const string¶m)
|
||||
{
|
||||
char* key;
|
||||
char* value;
|
||||
unsigned off = param.find('=');
|
||||
if (off > param.size()) {
|
||||
key = strdup(param.c_str());
|
||||
value = (char*)malloc(1);
|
||||
*value = '\0';
|
||||
|
||||
} else {
|
||||
key = strdup(param.substr(0, off).c_str());
|
||||
value = strdup(param.substr(off+1).c_str());
|
||||
}
|
||||
|
||||
// Resolve hierarchical name for defparam. Remember
|
||||
// to deal with bit select for generate scopes. Bit
|
||||
// select expression should be constant interger.
|
||||
pform_name_t name;
|
||||
char *nkey = key;
|
||||
char *ptr = strchr(key, '.');
|
||||
while (ptr != 0) {
|
||||
*ptr++ = '\0';
|
||||
// Find if bit select is applied, this would be something
|
||||
// like - scope[2].param = 10
|
||||
char *bit_l = strchr(nkey, '[');
|
||||
if (bit_l !=0) {
|
||||
*bit_l++ = '\0';
|
||||
char *bit_r = strchr(bit_l, ']');
|
||||
if (bit_r == 0) {
|
||||
cerr << "<command line>: error: missing ']' for defparam: " << nkey << endl;
|
||||
free(key);
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
*bit_r = '\0';
|
||||
int i = 0;
|
||||
while (*(bit_l+i) != '\0')
|
||||
if (!isdigit(*(bit_l+i++))) {
|
||||
cerr << "<command line>: error: scope index expression is not constant: " << nkey << endl;
|
||||
free(key);
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
name_component_t tmp(lex_strings.make(nkey));
|
||||
index_component_t index;
|
||||
index.sel = index_component_t::SEL_BIT;
|
||||
verinum *seln = new verinum(atoi(bit_l));
|
||||
PENumber *sel = new PENumber(seln);
|
||||
index.msb = sel;
|
||||
index.lsb = sel;
|
||||
tmp.index.push_back(index);
|
||||
name.push_back(tmp);
|
||||
}
|
||||
else // no bit select
|
||||
name.push_back(name_component_t(lex_strings.make(nkey)));
|
||||
|
||||
nkey = ptr;
|
||||
ptr = strchr(nkey, '.');
|
||||
}
|
||||
name.push_back(name_component_t(lex_strings.make(nkey)));
|
||||
|
||||
// Resolve value to PExpr class. Should support all kind of constant
|
||||
// format including based number, dec number, real number and string.
|
||||
if (*value == '"') { // string type
|
||||
char *buf = strdup (value);
|
||||
char *buf_ptr = buf+1;
|
||||
// Parse untill another '"' or '\0'
|
||||
while (*buf_ptr != '"' && *buf_ptr != '\0') {
|
||||
buf_ptr++;
|
||||
// Check for escape, especially '\"', which does not mean the
|
||||
// end of string.
|
||||
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
|
||||
buf_ptr += 2;
|
||||
}
|
||||
if (*buf_ptr == '\0') // String end without '"'
|
||||
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
|
||||
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
|
||||
cerr << buf_ptr << endl;
|
||||
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
|
||||
<< ". Ignore characters after \'\"\'" << endl;
|
||||
}
|
||||
|
||||
*buf_ptr = '\0';
|
||||
buf_ptr = buf+1;
|
||||
// Remember to use 'new' to allocate string for PEString
|
||||
// because 'delete' is used by its destructor.
|
||||
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
|
||||
PEString* ndec = new PEString(nchar);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
free(buf);
|
||||
}
|
||||
else { // number type
|
||||
char *num = strchr(value, '\'');
|
||||
if (num != 0) {
|
||||
verinum *val;
|
||||
// BASED_NUMBER, somthing like - scope.parameter='b11
|
||||
// make sure to check 'h' first because 'b'&'d' may be included
|
||||
// in hex format
|
||||
if (strchr(num, 'h') || strchr(num, 'H'))
|
||||
val = make_unsized_hex(num);
|
||||
else if (strchr(num, 'd') || strchr(num, 'D'))
|
||||
if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z'))
|
||||
val = make_undef_highz_dec(num);
|
||||
else
|
||||
val = make_unsized_dec(num);
|
||||
else if (strchr(num, 'b') || strchr(num, 'B')) {
|
||||
val = make_unsized_binary(num);
|
||||
}
|
||||
else if (strchr(num, 'o') || strchr(num, 'O'))
|
||||
val = make_unsized_octal(num);
|
||||
else {
|
||||
cerr << "<command line>: error: value specify error for defparam: " << name << endl;
|
||||
free(key);
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
|
||||
// BASED_NUMBER with size, something like - scope.parameter=2'b11
|
||||
if (num != value) {
|
||||
*num = 0;
|
||||
verinum *siz = make_unsized_dec(value);
|
||||
val = pform_verinum_with_size(siz, val, "<command line>", 0);
|
||||
}
|
||||
|
||||
PENumber* ndec = new PENumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
|
||||
}
|
||||
else {
|
||||
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2
|
||||
if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) {
|
||||
verireal *val = new verireal(value);
|
||||
PEFNumber* nreal = new PEFNumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, nreal) );
|
||||
}
|
||||
else {
|
||||
// DEC_NUMBER, something like - scope.parameter=3
|
||||
verinum *val = make_unsized_dec(value);
|
||||
PENumber* ndec = new PENumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
}
|
||||
}
|
||||
}
|
||||
free(key);
|
||||
free(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* The lexor accesses the vl_* variables.
|
||||
*/
|
||||
|
|
@ -675,20 +829,31 @@ void pform_endmodule(const char*name, bool in_celldefine,
|
|||
tp_local_flag = false;
|
||||
}
|
||||
|
||||
static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
|
||||
map<perm_string,LineInfo*>&genvars)
|
||||
{
|
||||
LineInfo*lni = new LineInfo();
|
||||
FILE_NAME(lni, li);
|
||||
if (genvars.find(name) != genvars.end()) {
|
||||
cerr << lni->get_fileline() << ": error: genvar '"
|
||||
<< name << "' has already been declared." << endl;
|
||||
cerr << genvars[name]->get_fileline()
|
||||
<< ": the previous declaration is here." << endl;
|
||||
error_count += 1;
|
||||
delete lni;
|
||||
} else {
|
||||
genvars[name] = lni;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||
{
|
||||
list<perm_string>::const_iterator cur;
|
||||
for (cur = names->begin(); cur != names->end() ; *cur++) {
|
||||
LineInfo*lni = new LineInfo();
|
||||
FILE_NAME(lni, li);
|
||||
if (pform_cur_module->genvars.find(*cur) !=
|
||||
pform_cur_module->genvars.end()) {
|
||||
cerr << lni->get_fileline() << ": error: duplicate "
|
||||
"definition for genvar '" << *cur << "' in '"
|
||||
<< pform_cur_module->mod_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
delete lni;
|
||||
} else pform_cur_module->genvars[*cur] = lni;
|
||||
if (pform_cur_generate)
|
||||
pform_add_genvar(li, *cur, pform_cur_generate->genvars);
|
||||
else
|
||||
pform_add_genvar(li, *cur, pform_cur_module->genvars);
|
||||
}
|
||||
|
||||
delete names;
|
||||
|
|
@ -703,7 +868,6 @@ void pform_start_generate_for(const struct vlltype&li,
|
|||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
// For now, assume that generates do not nest.
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
|
|
@ -724,7 +888,6 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test)
|
|||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
// For now, assume that generates do not nest.
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
|
|
@ -747,7 +910,6 @@ void pform_start_generate_else(const struct vlltype&li)
|
|||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
// For now, assume that generates do not nest.
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
|
|
|
|||
10
pform.h
10
pform.h
|
|
@ -195,7 +195,7 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
|||
|
||||
/*
|
||||
* This function takes the list of names as new genvars to declare in
|
||||
* the current module scope.
|
||||
* the current module or generate scope.
|
||||
*/
|
||||
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
|
||||
|
||||
|
|
@ -410,6 +410,14 @@ extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
|||
|
||||
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
||||
char*name, char*branch);
|
||||
|
||||
/*
|
||||
* Parse configuration file with format <key>=<value>, where key
|
||||
* is the hierarchical name of a valid parameter name and value
|
||||
* is the value user wants to assign to. The value should be constant.
|
||||
*/
|
||||
extern void parm_to_defparam_list(const string¶m);
|
||||
|
||||
/*
|
||||
* Tasks to set the timeunit or timeprecision for SystemVerilog.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -410,6 +410,8 @@ void PDelays::dump_delays(ostream&out) const
|
|||
if (delay_[0] && delay_[1] && delay_[2])
|
||||
out << "#(" << *delay_[0] << "," << *delay_[1] << "," <<
|
||||
*delay_[2] << ")";
|
||||
else if (delay_[0] && delay_[1])
|
||||
out << "#(" << *delay_[0] << "," << *delay_[1] << ")";
|
||||
else if (delay_[0])
|
||||
out << "#" << *delay_[0];
|
||||
else
|
||||
|
|
@ -1032,6 +1034,12 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
|||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
|
||||
for (genvar_iter_t cur = genvars.begin()
|
||||
; cur != genvars.end() ; cur++) {
|
||||
out << setw(indent+2) << "" << "genvar " << ((*cur).first) << ";" << endl;
|
||||
}
|
||||
|
||||
for (list<PGenerate*>::const_iterator idx = generate_schemes.begin()
|
||||
; idx != generate_schemes.end() ; idx++) {
|
||||
(*idx)->dump(out, indent+2);
|
||||
|
|
|
|||
|
|
@ -1196,7 +1196,8 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
|||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.swid;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
cerr << "error: ivl_lpm_selects() is no longer supported for "
|
||||
"IVL_LPM_CONCAT, use ivl_lpm_size() instead." << endl;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1268,6 +1269,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
|||
return net->u_.ufunc.ports - 1;
|
||||
case IVL_LPM_REPEAT:
|
||||
return net->u_.repeat.count;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -351,6 +351,7 @@ void dll_target::expr_select(const NetESelect*net)
|
|||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr_);
|
||||
FILE_NAME(expr_, net);
|
||||
|
||||
expr_->type_ = IVL_EX_SELECT;
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
|
|
|
|||
1
t-dll.cc
1
t-dll.cc
|
|
@ -2147,6 +2147,7 @@ bool dll_target::part_select(const NetPartSelect*net)
|
|||
obj->type = IVL_LPM_PART_PV;
|
||||
break;
|
||||
}
|
||||
FILE_NAME(obj, net);
|
||||
obj->name = net->name(); // NetPartSelect names are permallocated.
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ static void show_lpm_cmp_ne(ivl_lpm_t net)
|
|||
}
|
||||
|
||||
/* IVL_LPM_CONCAT
|
||||
* The concat device takes N inputs (N=ivl_lpm_selects) and generates
|
||||
* The concat device takes N inputs (N=ivl_lpm_size) and generates
|
||||
* a single output. The total output is known from the ivl_lpm_width
|
||||
* function. The widths of all the inputs are inferred from the widths
|
||||
* of the signals connected to the nexus of the inputs. The compiler
|
||||
|
|
@ -444,10 +444,10 @@ static void show_lpm_concat(ivl_lpm_t net)
|
|||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n",
|
||||
ivl_lpm_basename(net), width, ivl_lpm_selects(net));
|
||||
ivl_lpm_basename(net), width, ivl_lpm_size(net));
|
||||
fprintf(out, " O: %p\n", ivl_lpm_q(net,0));
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
|
||||
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_data(net, idx);
|
||||
unsigned signal_width = width_of_nexus(nex);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* VHDL code generation for expressions.
|
||||
*
|
||||
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
|
||||
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -107,8 +107,10 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e)
|
|||
if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) {
|
||||
// Select from an array
|
||||
vhdl_expr *vhd_off = translate_expr(off);
|
||||
if (NULL == vhd_off)
|
||||
if (NULL == vhd_off) {
|
||||
delete ref;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||
ref->set_slice(vhd_off->cast(&integer));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* VHDL code generation for LPM devices.
|
||||
*
|
||||
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
|
||||
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -48,10 +48,12 @@ static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
|||
vhdl_binop_expr *expr =
|
||||
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
|
||||
|
||||
for (int i = ivl_lpm_selects(lpm) - 1; i >= 0; i--) {
|
||||
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
|
||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||
if (NULL == e)
|
||||
if (NULL == e) {
|
||||
delete expr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expr->add_expr(e);
|
||||
}
|
||||
|
|
@ -68,8 +70,10 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
|
|||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||
if (NULL == e)
|
||||
if (NULL == e) {
|
||||
delete expr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expr->add_expr(e->cast(result_type));
|
||||
}
|
||||
|
|
@ -95,8 +99,10 @@ static vhdl_expr *rel_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t
|
|||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||
if (NULL == e)
|
||||
if (NULL == e) {
|
||||
delete expr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expr->add_expr(e);
|
||||
}
|
||||
|
|
@ -135,8 +141,10 @@ static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
|||
|
||||
for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
|
||||
vhdl_var_ref *ref = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||
if (NULL == ref)
|
||||
if (NULL == ref) {
|
||||
delete fcall;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fcall->add_expr(ref);
|
||||
}
|
||||
|
|
@ -195,8 +203,10 @@ static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
|||
vhdl_type *atype = new vhdl_type(*adecl->get_type());
|
||||
|
||||
vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm));
|
||||
if (NULL == select)
|
||||
if (NULL == select) {
|
||||
delete atype;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
|
||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||
|
|
|
|||
|
|
@ -95,8 +95,13 @@ int draw_process(ivl_process_t proc, void *cd)
|
|||
ivl_scope_tname(scope), ivl_process_file(proc),
|
||||
ivl_process_lineno(proc));
|
||||
|
||||
// A process should occur in a module scope, therefore it
|
||||
// should have already been assigned a VHDL entity
|
||||
// Skip over any generate and begin scopes until we find
|
||||
// the module that contains them - this is where we will
|
||||
// generate the process
|
||||
while (ivl_scope_type(scope) == IVL_SCT_GENERATE
|
||||
|| ivl_scope_type(scope) == IVL_SCT_BEGIN)
|
||||
scope = ivl_scope_parent(scope);
|
||||
|
||||
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
|
||||
vhdl_entity *ent = find_entity(scope);
|
||||
assert(ent != NULL);
|
||||
|
|
|
|||
|
|
@ -472,12 +472,50 @@ static void avoid_name_collision(string& name, vhdl_scope* scope)
|
|||
}
|
||||
}
|
||||
|
||||
// Concatenate the expanded genvar values together to make a unique
|
||||
// instance name
|
||||
// This isn't ideal: it would be better to replace the Verilog
|
||||
// generate with an equivalent VHDL generate, but this isn't possible
|
||||
// with the current API
|
||||
static string genvar_unique_suffix(ivl_scope_t scope)
|
||||
{
|
||||
ostringstream suffix;
|
||||
while (scope && ivl_scope_type(scope) == IVL_SCT_GENERATE) {
|
||||
for (unsigned i = 0; i < ivl_scope_params(scope); i++) {
|
||||
ivl_parameter_t param = ivl_scope_param(scope, i);
|
||||
ivl_expr_t e = ivl_parameter_expr(param);
|
||||
|
||||
if (ivl_expr_type(e) == IVL_EX_NUMBER) {
|
||||
vhdl_expr* value = translate_expr(e);
|
||||
assert(value);
|
||||
|
||||
value = value->cast(vhdl_type::integer());
|
||||
|
||||
suffix << "_" << ivl_parameter_basename(param);
|
||||
value->emit(suffix, 0);
|
||||
|
||||
delete value;
|
||||
}
|
||||
else {
|
||||
error("Only numeric genvars supported at the moment");
|
||||
return "_ERROR"; // Never used
|
||||
}
|
||||
}
|
||||
|
||||
scope = ivl_scope_parent(scope);
|
||||
}
|
||||
|
||||
return suffix.str();
|
||||
}
|
||||
|
||||
// Declare a single signal in a scope
|
||||
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig)
|
||||
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
|
||||
ivl_scope_t scope)
|
||||
{
|
||||
remember_signal(sig, ent->get_arch()->get_scope());
|
||||
|
||||
string name(make_safe_name(sig));
|
||||
name += genvar_unique_suffix(scope);
|
||||
avoid_name_collision(name, ent->get_arch()->get_scope());
|
||||
|
||||
rename_signal(sig, name);
|
||||
|
|
@ -586,14 +624,14 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
|
|||
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
||||
|
||||
if (ivl_signal_port(sig) != IVL_SIP_NONE)
|
||||
declare_one_signal(ent, sig);
|
||||
declare_one_signal(ent, sig, scope);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nsigs; i++) {
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
declare_one_signal(ent, sig);
|
||||
declare_one_signal(ent, sig, scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -873,9 +911,6 @@ static int draw_skeleton_scope(ivl_scope_t scope, void *_unused)
|
|||
case IVL_SCT_MODULE:
|
||||
create_skeleton_entity_for(scope, depth);
|
||||
break;
|
||||
case IVL_SCT_GENERATE:
|
||||
error("No translation for generate statements yet");
|
||||
return 1;
|
||||
case IVL_SCT_FORK:
|
||||
error("No translation for fork statements yet");
|
||||
return 1;
|
||||
|
|
@ -901,6 +936,20 @@ static int draw_all_signals(ivl_scope_t scope, void *_parent)
|
|||
|
||||
declare_signals(ent, scope);
|
||||
}
|
||||
else if (ivl_scope_type(scope) == IVL_SCT_GENERATE) {
|
||||
// Because generate scopes don't appear in the
|
||||
// output VHDL all their signals are added to the
|
||||
// containing entity (after being uniqued)
|
||||
|
||||
ivl_scope_t parent = ivl_scope_parent(scope);
|
||||
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
|
||||
parent = ivl_scope_parent(scope);
|
||||
|
||||
vhdl_entity* ent = find_entity(parent);
|
||||
assert(ent);
|
||||
|
||||
declare_signals(ent, scope);
|
||||
}
|
||||
|
||||
return ivl_scope_children(scope, draw_all_signals, scope);
|
||||
}
|
||||
|
|
@ -1032,6 +1081,10 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
|
|||
if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
|
||||
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
|
||||
|
||||
// Skip over any containing generate scopes
|
||||
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
|
||||
parent = ivl_scope_parent(parent);
|
||||
|
||||
if (!is_default_scope_instance(parent))
|
||||
return 0; // Not generating code for the parent instance so
|
||||
// don't generate for the child
|
||||
|
|
@ -1054,6 +1107,7 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
|
|||
|
||||
// And an instantiation statement
|
||||
string inst_name(ivl_scope_basename(scope));
|
||||
inst_name += genvar_unique_suffix(ivl_scope_parent(scope));
|
||||
if (inst_name == ent->get_name() || parent_scope->have_declared(inst_name)) {
|
||||
// Cannot have instance name the same as type in VHDL
|
||||
inst_name += "_Inst";
|
||||
|
|
|
|||
|
|
@ -170,8 +170,12 @@ vhdl_entity* find_entity(const string& name)
|
|||
// name should be the same as the Verilog module type name.
|
||||
// Note that this will return NULL if no entity has been recorded
|
||||
// for this scope type.
|
||||
vhdl_entity* find_entity(const ivl_scope_t scope)
|
||||
vhdl_entity* find_entity(ivl_scope_t scope)
|
||||
{
|
||||
// Skip over generate scopes
|
||||
while (ivl_scope_type(scope) == IVL_SCT_GENERATE)
|
||||
scope = ivl_scope_parent(scope);
|
||||
|
||||
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
|
||||
|
||||
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope)
|
|||
|
||||
// Manage the set of VHDL entities
|
||||
void remember_entity(vhdl_entity *ent, ivl_scope_t scope);
|
||||
vhdl_entity* find_entity(const ivl_scope_t scope);
|
||||
vhdl_entity* find_entity(ivl_scope_t scope);
|
||||
vhdl_entity* find_entity(const std::string& name);
|
||||
void emit_all_entities(std::ostream& os, int max_depth);
|
||||
void free_all_vhdl_objects();
|
||||
|
|
|
|||
|
|
@ -313,11 +313,11 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
|
|||
if (NULL == test)
|
||||
return;
|
||||
|
||||
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
|
||||
|
||||
if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
|
||||
return;
|
||||
|
||||
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
|
||||
|
||||
// True part
|
||||
{
|
||||
vhdl_abstract_assign_stmt *a =
|
||||
|
|
@ -1342,6 +1342,7 @@ int draw_casezx(vhdl_procedural *proc, stmt_container *container,
|
|||
"expression labels can be translated to VHDL",
|
||||
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
|
||||
(is_casez ? "z" : "x"));
|
||||
delete all;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
|
|||
if (number_is_immediate(d_rise, 64, 0) &&
|
||||
number_is_immediate(d_fall, 64, 0) &&
|
||||
number_is_immediate(d_decay, 64, 0)) {
|
||||
|
||||
assert( ! number_is_unknown(d_rise));
|
||||
assert( ! number_is_unknown(d_fall));
|
||||
assert( ! number_is_unknown(d_decay));
|
||||
|
||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||
net, get_number_immediate(d_rise),
|
||||
get_number_immediate(d_fall),
|
||||
|
|
|
|||
|
|
@ -388,6 +388,10 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
number_is_immediate(d_fall, 64, 0) &&
|
||||
number_is_immediate(d_decay, 64, 0)) {
|
||||
|
||||
assert(! number_is_unknown(d_rise));
|
||||
assert(! number_is_unknown(d_fall));
|
||||
assert(! number_is_unknown(d_decay));
|
||||
|
||||
fprintf(vvp_out, "L_%p .delay "
|
||||
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
||||
cptr, get_number_immediate64(d_rise),
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
|||
if (word_ex) {
|
||||
/* Some array select have been evaluated. */
|
||||
if (number_is_immediate(word_ex,IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(word_ex));
|
||||
use_word = get_number_immediate(word_ex);
|
||||
word_ex = 0;
|
||||
}
|
||||
|
|
@ -130,6 +131,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
|||
if (word_ex) {
|
||||
/* Some array select have been evaluated. */
|
||||
if (number_is_immediate(word_ex, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(word_ex));
|
||||
use_word = get_number_immediate(word_ex);
|
||||
use_word_defined = 1;
|
||||
word_ex = 0;
|
||||
|
|
@ -185,6 +187,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
|||
|
||||
/* This is a constant bit/part select. */
|
||||
if (number_is_immediate(bexpr, 64, 1)) {
|
||||
assert(! number_is_unknown(bexpr));
|
||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
||||
ivl_expr_signal(vexpr),
|
||||
get_number_immediate(bexpr),
|
||||
|
|
@ -206,9 +209,19 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
|||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Fallback case: evaluate the expression. */
|
||||
/* Fallback case: evaluate the expression. */
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
|
||||
/* We need to enhance &PV<> to support a signed index. */
|
||||
if (ivl_expr_signed(bexpr) &&
|
||||
(ivl_expr_width(bexpr) < 8*sizeof(int))) {
|
||||
fprintf(stderr, "%s:%u: tgt-vvp warning: V0.9 may give "
|
||||
"incorrect results for a select with a "
|
||||
"signed index less than %d bits.\n",
|
||||
ivl_expr_file(expr),
|
||||
ivl_expr_lineno(expr),
|
||||
8*sizeof(int));
|
||||
}
|
||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
|
||||
ivl_expr_signal(vexpr),
|
||||
rv.base, rv.wid,
|
||||
|
|
|
|||
|
|
@ -174,6 +174,12 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
case IVL_EX_ULONG:
|
||||
{
|
||||
assert(number_is_immediate(expr, IMM_WID, 1));
|
||||
if (number_is_unknown(expr)) {
|
||||
/* We are loading a 'bx so mimic %ix/get. */
|
||||
fprintf(vvp_out, " %%ix/load %u, 0, 0;\n", ix);
|
||||
fprintf(vvp_out, " %%mov 4, 1, 1;\n");
|
||||
break;
|
||||
}
|
||||
long imm = get_number_immediate(expr);
|
||||
if (imm >= 0) {
|
||||
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", ix, imm);
|
||||
|
|
@ -192,6 +198,7 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
unsigned word = 0;
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
ivl_expr_t ixe;
|
||||
char*type = ivl_expr_signed(expr) ? "/s" : "";
|
||||
|
||||
/* Detect the special case that this is a
|
||||
variable array. In this case, the ix/getv
|
||||
|
|
@ -199,20 +206,21 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
|
||||
type, ix, rv.base, rv.wid);
|
||||
clr_vector(rv);
|
||||
break;
|
||||
}
|
||||
|
||||
ixe = ivl_expr_oper1(expr);
|
||||
if (number_is_immediate(ixe, IMM_WID, 0))
|
||||
if (number_is_immediate(ixe, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(ixe));
|
||||
word = get_number_immediate(ixe);
|
||||
else {
|
||||
} else {
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
|
||||
type, ix, rv.base, rv.wid);
|
||||
clr_vector(rv);
|
||||
break;
|
||||
}
|
||||
|
|
@ -226,8 +234,14 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
default: {
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
/* Is this a signed expression? */
|
||||
if (ivl_expr_signed(expr)) {
|
||||
fprintf(vvp_out, " %%ix/get/s %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
}
|
||||
clr_vector(rv);
|
||||
break;
|
||||
}
|
||||
|
|
@ -274,7 +288,10 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
|||
{
|
||||
unsigned wid;
|
||||
struct vector_info lv;
|
||||
unsigned long imm = get_number_immediate(re);
|
||||
unsigned long imm;
|
||||
assert(number_is_immediate(re, IMM_WID, 0));
|
||||
assert(! number_is_unknown(re));
|
||||
imm = get_number_immediate(re);
|
||||
|
||||
wid = ivl_expr_width(le);
|
||||
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
|
||||
|
|
@ -991,6 +1008,8 @@ static struct vector_info draw_logic_immediate(ivl_expr_t exp,
|
|||
unsigned wid)
|
||||
{
|
||||
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(number_is_immediate(re, IMM_WID, 0));
|
||||
assert(! number_is_unknown(re));
|
||||
unsigned long imm = get_number_immediate(re);
|
||||
|
||||
assert(lv.base >= 4);
|
||||
|
|
@ -1241,8 +1260,10 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
|||
int signed_flag)
|
||||
{
|
||||
struct vector_info lv;
|
||||
long imm = get_number_immediate(re);
|
||||
long imm;
|
||||
assert(! number_is_unknown(re));
|
||||
assert(number_is_immediate(re, IMM_WID, 1));
|
||||
imm = get_number_immediate(re);
|
||||
lv.base = allocate_vector(wid);
|
||||
lv.wid = wid;
|
||||
if (lv.base == 0) {
|
||||
|
|
@ -1270,6 +1291,8 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
|
|||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(lv.wid == wid);
|
||||
|
||||
assert(! number_is_unknown(re));
|
||||
assert(number_is_immediate(re, IMM_WID, 0));
|
||||
imm = get_number_immediate(re);
|
||||
|
||||
/* This shouldn't generally happen, because the elaborator
|
||||
|
|
@ -1308,7 +1331,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
|
|||
}
|
||||
break;
|
||||
|
||||
case 2: /* Left expression is X or Z */
|
||||
case 2: /* Left expression is 'bx or 'bz */
|
||||
case 3:
|
||||
lv.base = 2;
|
||||
break;
|
||||
|
|
@ -1335,6 +1358,8 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
|
|||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(lv.wid == wid);
|
||||
|
||||
assert(! number_is_unknown(re));
|
||||
assert(number_is_immediate(re, IMM_WID, 0));
|
||||
imm = get_number_immediate(re);
|
||||
if (imm == 0)
|
||||
return lv;
|
||||
|
|
@ -1379,6 +1404,8 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
|
|||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(lv.wid == wid);
|
||||
|
||||
assert(! number_is_unknown(re));
|
||||
assert(number_is_immediate(re, IMM_WID, 0));
|
||||
imm = get_number_immediate(re);
|
||||
if (imm == 0)
|
||||
return lv;
|
||||
|
|
@ -2253,7 +2280,7 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
|
|||
unsigned bit_width,
|
||||
unsigned wid)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned idx, label;
|
||||
ivl_signal_t sig = ivl_expr_signal(sube);
|
||||
/* unsigned sig_wid = ivl_expr_width(sube); */
|
||||
ivl_expr_t ix = ivl_expr_oper1(sube);
|
||||
|
|
@ -2263,7 +2290,18 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
|
|||
|
||||
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
|
||||
draw_eval_expr_into_integer(ix, 3);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
label = local_count++;
|
||||
/* We can safely skip the bit index load below if the array word
|
||||
* index is undefined. We need to do this so that the bit index
|
||||
* load does not reset bit 4 to zero by loading a defined value. */
|
||||
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, label);
|
||||
if (ivl_expr_signed(bit_idx)) {
|
||||
fprintf(vvp_out, " %%ix/get/s 0, %u, %u;\n", shiv.base,
|
||||
shiv.wid);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
}
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, label);
|
||||
if (shiv.base >= 8)
|
||||
clr_vector(shiv);
|
||||
|
||||
|
|
@ -2294,7 +2332,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
|
||||
/* Use this word of the signal. */
|
||||
unsigned use_word = 0;
|
||||
unsigned use_wid;
|
||||
unsigned use_wid, lab_x, lab_end;
|
||||
|
||||
/* If this is an access to an array, try to get the index as a
|
||||
constant. If it is (and the array is not a reg array then
|
||||
|
|
@ -2311,6 +2349,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
|
||||
/* The index is constant, so we can return to direct
|
||||
readout with the specific word selected. */
|
||||
assert(! number_is_unknown(ix));
|
||||
use_word = get_number_immediate(ix);
|
||||
}
|
||||
|
||||
|
|
@ -2318,6 +2357,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
the signal (or the entire width). Just load the early bits
|
||||
in one go. */
|
||||
if (number_is_immediate(bit_idx, 32, 0)
|
||||
&& !number_is_unknown(bit_idx)
|
||||
&& get_number_immediate(bit_idx) == 0
|
||||
&& (ivl_expr_width(sube) >= bit_wid)) {
|
||||
|
||||
|
|
@ -2343,6 +2383,12 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
res.wid = wid;
|
||||
assert(res.base);
|
||||
|
||||
lab_x = local_count++;
|
||||
lab_end = local_count++;
|
||||
|
||||
/* If the index is 'bx then we just return 'bx. */
|
||||
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_x);
|
||||
|
||||
use_wid = res.wid;
|
||||
if (use_wid > bit_wid)
|
||||
use_wid = bit_wid;
|
||||
|
|
@ -2353,6 +2399,11 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
fprintf(vvp_out, " %%movi %u, 0, %u;\n",
|
||||
res.base + use_wid, res.wid - use_wid);
|
||||
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_end);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_x);
|
||||
fprintf(vvp_out, " %%mov %u, 2, %u;\n", res.base, res.wid);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_end);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -2371,6 +2422,7 @@ static void draw_select_signal_dest(ivl_expr_t sube,
|
|||
if ((ivl_signal_dimensions(sig) == 0)
|
||||
&& (ivl_expr_width(sube) >= dest.wid)
|
||||
&& number_is_immediate(bit_idx, 32, 0)
|
||||
&& ! number_is_unknown(bit_idx)
|
||||
&& get_number_immediate(bit_idx) == 0) {
|
||||
unsigned use_word = 0;
|
||||
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Select %u out of %u bits\n",
|
||||
|
|
@ -2401,6 +2453,8 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
|||
ivl_expr_t shift = ivl_expr_oper2(exp);
|
||||
|
||||
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
|
||||
int cmp;
|
||||
unsigned lab_l, lab_end;
|
||||
|
||||
res.wid = wid;
|
||||
|
||||
|
|
@ -2444,7 +2498,12 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
|||
return res;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
if (ivl_expr_signed(shift)) {
|
||||
fprintf(vvp_out, " %%ix/get/s 0, %u, %u;\n", shiv.base,
|
||||
shiv.wid);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
}
|
||||
clr_vector(shiv);
|
||||
|
||||
/* If the subv result is a magic constant, then make a copy in
|
||||
|
|
@ -2458,7 +2517,27 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
|||
subv = res;
|
||||
}
|
||||
|
||||
lab_l = local_count++;
|
||||
lab_end = local_count++;
|
||||
/* If we have an undefined index then just produce a 'bx result. */
|
||||
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_l);
|
||||
|
||||
cmp = allocate_word();
|
||||
assert(subv.wid >= wid);
|
||||
/* Determine if we need to shift a 'bx into the top. */
|
||||
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", cmp, subv.wid - wid);
|
||||
fprintf(vvp_out, " %%cmp/ws %u, 0;\n", cmp);
|
||||
clr_word(cmp);
|
||||
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 5;\n", thread_count, lab_l);
|
||||
/* Clear the cmp bit if the two values are equal. */
|
||||
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
|
||||
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", subv.base, subv.wid);
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_end);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_l);
|
||||
/* Multiply by -1. */
|
||||
fprintf(vvp_out, " %%ix/mul 0, %u, %u;\n", 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", subv.base, subv.wid);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_end);
|
||||
|
||||
if (subv.wid > wid) {
|
||||
res.base = subv.base;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
|
||||
!number_is_unknown(part_off_ex)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
|
@ -96,6 +97,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
it to select the word, and pay no further heed to the
|
||||
expression itself. */
|
||||
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(word_ix));
|
||||
use_word = get_number_immediate(word_ix);
|
||||
word_ix = 0;
|
||||
}
|
||||
|
|
@ -222,6 +224,63 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
}
|
||||
}
|
||||
|
||||
/* Support a non-blocking assignment to a real array word. */
|
||||
static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
unsigned bit, uint64_t delay,
|
||||
ivl_expr_t dexp, unsigned nevents)
|
||||
{
|
||||
unsigned skip_assign = transient_id++;
|
||||
|
||||
/* This code is common to all the different types of array delays. */
|
||||
if (number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(word_ix));
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
|
||||
get_number_immediate(word_ix));
|
||||
} else {
|
||||
/* Calculate array word index into index register 3 */
|
||||
draw_eval_expr_into_integer(word_ix, 3);
|
||||
/* Skip assignment if word expression is not defined. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
}
|
||||
|
||||
if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig,
|
||||
delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
fprintf(vvp_out, " %%assign/ar/e v%p, %u;\n", lsig, bit);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||
|
||||
/*
|
||||
* The %assign can only take a 32 bit delay. For a larger
|
||||
* delay we need to put it into an index register.
|
||||
*/
|
||||
if (hig_d != 0) {
|
||||
int delay_index = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||
delay_index, low_d, hig_d);
|
||||
fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig,
|
||||
delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%assign/ar v%p, %lu, %u;\n",
|
||||
lsig, low_d, bit);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
|
||||
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
|
||||
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
unsigned bit, uint64_t delay, ivl_expr_t dexp,
|
||||
ivl_expr_t part_off_ex, unsigned width,
|
||||
|
|
@ -233,12 +292,14 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(part_off_ex));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
/* This code is common to all the different types of array delays. */
|
||||
if (number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(word_ix));
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
|
||||
get_number_immediate(word_ix));
|
||||
} else {
|
||||
|
|
@ -317,6 +378,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||
assert(! number_is_unknown(part_off_ex));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
|
@ -643,13 +705,6 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
sig = ivl_lval_sig(lval);
|
||||
assert(sig);
|
||||
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
word_ix = ivl_lval_idx(lval);
|
||||
assert(word_ix);
|
||||
assert(number_is_immediate(word_ix, IMM_WID, 0));
|
||||
use_word = get_number_immediate(word_ix);
|
||||
}
|
||||
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
||||
assert(number_is_immediate(del, 64, 0));
|
||||
delay = ivl_expr_delay_val(del);
|
||||
|
|
@ -659,6 +714,14 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
/* Evaluate the r-value */
|
||||
word = draw_eval_real(rval);
|
||||
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
word_ix = ivl_lval_idx(lval);
|
||||
assert(word_ix);
|
||||
assign_to_array_r_word(sig, word_ix, word, delay, del, nevents);
|
||||
clr_word(word);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need to calculate the delay expression. */
|
||||
if (del) {
|
||||
assert(nevents == 0);
|
||||
|
|
@ -1105,11 +1168,13 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, IMM_WID, 0));
|
||||
assert(! number_is_unknown(part_off_ex));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
if (word_idx != 0) {
|
||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(word_idx));
|
||||
use_word = get_number_immediate(word_idx);
|
||||
}
|
||||
|
||||
|
|
@ -1174,6 +1239,7 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
|||
* part select (this could give us multiple drivers). */
|
||||
part_off_ex = ivl_lval_part_off(lval);
|
||||
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
|
||||
// Do we need checks for number_is{immediate,unknown} of part_of_ex?
|
||||
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
|
||||
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to "
|
||||
"a bit/part select.\n", ivl_expr_file(rval),
|
||||
|
|
@ -1184,11 +1250,13 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
|||
/* At least for now, only handle force to fixed words of an array. */
|
||||
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
|
||||
assert(number_is_immediate(lword_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(lword_idx));
|
||||
use_lword = get_number_immediate(lword_idx);
|
||||
}
|
||||
|
||||
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
||||
assert(number_is_immediate(rword_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(rword_idx));
|
||||
use_rword = get_number_immediate(rword_idx);
|
||||
}
|
||||
|
||||
|
|
@ -1272,11 +1340,13 @@ static int show_stmt_deassign(ivl_statement_t net)
|
|||
part_off = 0;
|
||||
if (part_off_ex != 0) {
|
||||
assert(number_is_immediate(part_off_ex, 64, 0));
|
||||
assert(! number_is_unknown(part_off_ex));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
if (word_idx != 0) {
|
||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(word_idx));
|
||||
use_word = get_number_immediate(word_idx);
|
||||
}
|
||||
|
||||
|
|
@ -1567,6 +1637,7 @@ static int show_stmt_release(ivl_statement_t net)
|
|||
part_off = 0;
|
||||
if (part_off_ex != 0) {
|
||||
assert(number_is_immediate(part_off_ex, 64, 0));
|
||||
assert(! number_is_unknown(part_off_ex));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
|
|
@ -1581,6 +1652,7 @@ static int show_stmt_release(ivl_statement_t net)
|
|||
|
||||
if (word_idx != 0) {
|
||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(word_idx));
|
||||
use_word = get_number_immediate(word_idx);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -558,6 +558,9 @@ static void draw_delay(ivl_net_logic_t lptr)
|
|||
assert(number_is_immediate(d0, 64, 0));
|
||||
assert(number_is_immediate(d1, 64, 0));
|
||||
assert(number_is_immediate(d2, 64, 0));
|
||||
assert(! number_is_unknown(d0));
|
||||
assert(! number_is_unknown(d1));
|
||||
assert(! number_is_unknown(d2));
|
||||
|
||||
if (d0 == d1 && d1 == d2)
|
||||
fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
|
||||
|
|
@ -615,6 +618,8 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
|
|||
static ivl_udp_t *udps = 0x0;
|
||||
static int nudps = 0;
|
||||
int i;
|
||||
unsigned ninp;
|
||||
const char **input_strings;
|
||||
|
||||
for (i=0; i<nudps; i++)
|
||||
if (udps[i] == udp)
|
||||
|
|
@ -628,26 +633,38 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
|
|||
draw_udp_def(udp);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "L_%p .udp", lptr);
|
||||
fprintf(vvp_out, " UDP_%s",
|
||||
vvp_mangle_id(ivl_udp_name(udp)));
|
||||
draw_delay(lptr);
|
||||
|
||||
for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
|
||||
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx);
|
||||
/*
|
||||
* We need to process the arguments first so any evaluation code
|
||||
* (.resolv, etc.) can be built before we build the .udp call.
|
||||
* This matches what is done for the other primitives.
|
||||
*/
|
||||
ninp = ivl_logic_pins(lptr) - 1;
|
||||
input_strings = calloc(ninp, sizeof(char*));
|
||||
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
|
||||
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
|
||||
|
||||
/* Unlike other logic gates, primitives may have unconnected
|
||||
inputs. The proper behavior is to attach a HiZ to the
|
||||
port. */
|
||||
if (nex == 0) {
|
||||
assert(ivl_logic_width(lptr) == 1);
|
||||
fprintf(vvp_out, ", C4<z>");
|
||||
input_strings[pdx] = "C4<z>";
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, ", %s", draw_net_input(nex));
|
||||
input_strings[pdx] = draw_net_input(nex);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "L_%p .udp", lptr);
|
||||
fprintf(vvp_out, " UDP_%s",
|
||||
vvp_mangle_id(ivl_udp_name(udp)));
|
||||
draw_delay(lptr);
|
||||
|
||||
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
|
||||
fprintf(vvp_out, ", %s", input_strings[pdx]);
|
||||
}
|
||||
free(input_strings);
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
|
|
@ -805,7 +822,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
|
||||
|
||||
level = 0;
|
||||
ninp = ivl_logic_pins(lptr) - 1;
|
||||
while (ninp) {
|
||||
int inst;
|
||||
for (inst = 0; inst < ninp; inst += 4) {
|
||||
|
|
@ -861,6 +877,9 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
&& number_is_immediate(fall_exp,64,0)
|
||||
&& number_is_immediate(decay_exp,64,0)) {
|
||||
|
||||
assert(! number_is_unknown(rise_exp));
|
||||
assert(! number_is_unknown(fall_exp));
|
||||
assert(! number_is_unknown(decay_exp));
|
||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||
lptr, get_number_immediate(rise_exp),
|
||||
get_number_immediate(fall_exp),
|
||||
|
|
@ -1066,6 +1085,9 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net)
|
|||
assert(number_is_immediate(d_rise, 64, 0));
|
||||
assert(number_is_immediate(d_fall, 64, 0));
|
||||
assert(number_is_immediate(d_decay, 64, 0));
|
||||
assert(! number_is_unknown(d_rise));
|
||||
assert(! number_is_unknown(d_fall));
|
||||
assert(! number_is_unknown(d_decay));
|
||||
dly = "/d";
|
||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||
net, get_number_immediate(d_rise),
|
||||
|
|
@ -1322,7 +1344,7 @@ static unsigned lpm_concat_inputs(ivl_lpm_t net, unsigned start,
|
|||
static void draw_lpm_concat(ivl_lpm_t net)
|
||||
{
|
||||
const char*src_table[4];
|
||||
unsigned icnt = ivl_lpm_selects(net);
|
||||
unsigned icnt = ivl_lpm_size(net);
|
||||
const char*dly = draw_lpm_output_delay(net);
|
||||
|
||||
if (icnt <= 4) {
|
||||
|
|
|
|||
|
|
@ -1127,9 +1127,15 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8 *name)
|
|||
val.format = vpiIntVal;
|
||||
vpi_get_value(arg, &val);
|
||||
fd_mcd = val.value.integer;
|
||||
|
||||
/* If the MCD is zero we have nothing to do so just return. */
|
||||
if (fd_mcd == 0) {
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF) ||
|
||||
(! fd_mcd)) {
|
||||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor/MCD (0x%x) given "
|
||||
|
|
@ -1241,9 +1247,15 @@ static PLI_INT32 sys_strobe_calltf(PLI_BYTE8*name)
|
|||
val.format = vpiIntVal;
|
||||
vpi_get_value(arg, &val);
|
||||
fd_mcd = val.value.integer;
|
||||
|
||||
/* If the MCD is zero we have nothing to do so just return. */
|
||||
if (fd_mcd == 0) {
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF) ||
|
||||
(! fd_mcd)) {
|
||||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor/MCD (0x%x) given "
|
||||
|
|
|
|||
|
|
@ -153,10 +153,13 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
}
|
||||
|
||||
fname = get_filename(callh, name, fileh);
|
||||
if (fname == 0 && mode) free(mode_string);
|
||||
|
||||
/* If either the mode or file name are not valid just return. */
|
||||
if (fail || fname == 0) return 0;
|
||||
if (fail || fname == 0) {
|
||||
free(fname);
|
||||
if (mode) free(mode_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val.format = vpiIntVal;
|
||||
if (mode) {
|
||||
|
|
@ -267,6 +270,9 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
|
|||
vpi_get_value(arg, &val);
|
||||
fd_mcd = val.value.integer;
|
||||
|
||||
/* If the MCD is zero we have nothing to do so just return. */
|
||||
if (fd_mcd == 0) return 0;
|
||||
|
||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF) ||
|
||||
(! fd_mcd)) {
|
||||
|
|
|
|||
|
|
@ -293,7 +293,10 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
|
|||
|
||||
if (process_params(mitem, start_item, stop_item, callh, name,
|
||||
&start_addr, &stop_addr, &addr_incr,
|
||||
&min_addr, &max_addr)) return 0;
|
||||
&min_addr, &max_addr)) {
|
||||
free(fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the data file. */
|
||||
file = fopen(fname, "r");
|
||||
|
|
@ -528,7 +531,10 @@ static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
|
|||
|
||||
if (process_params(mitem, start_item, stop_item, callh, name,
|
||||
&start_addr, &stop_addr, &addr_incr,
|
||||
&min_addr, &max_addr)) return 0;
|
||||
&min_addr, &max_addr)) {
|
||||
free(fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the data file. */
|
||||
file = fopen(fname, "w");
|
||||
|
|
|
|||
|
|
@ -626,6 +626,7 @@ static PLI_INT32 sys_fscanf_compiletf(PLI_BYTE8*name)
|
|||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's first argument (fd) must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -695,6 +696,7 @@ static PLI_INT32 sys_sscanf_compiletf(PLI_BYTE8*name)
|
|||
vpi_printf("%s's first argument must be a register or constant "
|
||||
"string.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -805,6 +805,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
|
|||
vpi_printf("VCD warning: skipping signal %s, "
|
||||
"it was previously included.\n",
|
||||
fullname);
|
||||
free(scname);
|
||||
continue;
|
||||
} else {
|
||||
add_var = 1;
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ static PLI_INT32 va_single_argument_compiletf(PLI_BYTE8 *ud)
|
|||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
va_error_message(callh, "%s requires one argument.\n", name);
|
||||
free(fun_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +266,7 @@ static PLI_INT32 va_double_argument_compiletf(PLI_BYTE8 *ud)
|
|||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
va_error_message(callh, "%s requires two arguments.\n", name);
|
||||
free(fun_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ static PLI_INT32 va_single_argument_compiletf(PLI_BYTE8 *ud)
|
|||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
va_error_message(callh, "%s requires one argument.\n", name);
|
||||
free(fun_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +304,7 @@ static PLI_INT32 va_double_argument_compiletf(PLI_BYTE8 *ud)
|
|||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
va_error_message(callh, "%s requires two arguments.\n", name);
|
||||
free(fun_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __codes_H
|
||||
#define __codes_H
|
||||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -40,6 +40,9 @@ extern bool of_ALLOC(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_AND(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ANDI(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_AR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%assign/ar",of_ASSIGN_AR,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/ar/d",of_ASSIGN_ARD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/ar/e",of_ASSIGN_ARE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
||||
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/av/e",of_ASSIGN_AVE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
56
vvp/delay.cc
56
vvp/delay.cc
|
|
@ -140,6 +140,7 @@ vvp_fun_delay::vvp_fun_delay(vvp_net_t*n, vvp_bit4_t init, const vvp_delay_t&d)
|
|||
cur_vec8_ = vvp_vector8_t(cur_vec4_, 6, 6);
|
||||
cur_real_ = 0.0;
|
||||
list_ = 0;
|
||||
type_ = UNKNOWN_DELAY;
|
||||
initial_ = true;
|
||||
// Calculate the values used when converting variable delays
|
||||
// to simulation time units.
|
||||
|
|
@ -160,10 +161,48 @@ vvp_fun_delay::~vvp_fun_delay()
|
|||
delete cur;
|
||||
}
|
||||
|
||||
bool vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay,
|
||||
const vvp_vector4_t&bit)
|
||||
{
|
||||
if (list_ == 0) return false;
|
||||
|
||||
/* If the most recent event and the new event have the same
|
||||
* value then we need to skip the new event. */
|
||||
if (list_->next->ptr_vec4.eeq(bit)) return true;
|
||||
|
||||
clean_pulse_events_(use_delay);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay,
|
||||
const vvp_vector8_t&bit)
|
||||
{
|
||||
if (list_ == 0) return false;
|
||||
|
||||
/* If the most recent event and the new event have the same
|
||||
* value then we need to skip the new event. */
|
||||
if (list_->next->ptr_vec8.eeq(bit)) return true;
|
||||
|
||||
clean_pulse_events_(use_delay);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay,
|
||||
double bit)
|
||||
{
|
||||
if (list_ == 0) return false;
|
||||
|
||||
/* If the most recent event and the new event have the same
|
||||
* value then we need to skip the new event. */
|
||||
if (list_->next->ptr_real == bit) return true;
|
||||
|
||||
clean_pulse_events_(use_delay);
|
||||
return false;
|
||||
}
|
||||
|
||||
void vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay)
|
||||
{
|
||||
if (list_ == 0)
|
||||
return;
|
||||
assert(list_ != 0);
|
||||
|
||||
do {
|
||||
struct event_*cur = list_->next;
|
||||
|
|
@ -219,6 +258,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
/* This is an initial value so it needs to be compared to all the
|
||||
bits (the order the bits are changed is not deterministic). */
|
||||
if (initial_) {
|
||||
type_ = VEC4_DELAY;
|
||||
vvp_bit4_t cur_val = cur_vec4_.value(0);
|
||||
use_delay = delay_.get_delay(cur_val, bit.value(0));
|
||||
for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) {
|
||||
|
|
@ -227,6 +267,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
if (tmp > use_delay) use_delay = tmp;
|
||||
}
|
||||
} else {
|
||||
assert(type_ == VEC4_DELAY);
|
||||
|
||||
/* How many bits to compare? */
|
||||
unsigned use_wid = cur_vec4_.size();
|
||||
|
|
@ -246,7 +287,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
/* what *should* happen here is we check to see if there is a
|
||||
transaction in the queue. This would be a pulse that needs to be
|
||||
eliminated. */
|
||||
clean_pulse_events_(use_delay);
|
||||
if (clean_pulse_events_(use_delay, bit)) return;
|
||||
|
||||
vvp_time64_t use_simtime = schedule_simtime() + use_delay;
|
||||
|
||||
|
|
@ -273,6 +314,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
/* This is an initial value so it needs to be compared to all the
|
||||
bits (the order the bits are changed is not deterministic). */
|
||||
if (initial_) {
|
||||
type_ = VEC8_DELAY;
|
||||
vvp_bit4_t cur_val = cur_vec8_.value(0).value();
|
||||
use_delay = delay_.get_delay(cur_val, bit.value(0).value());
|
||||
for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) {
|
||||
|
|
@ -281,6 +323,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
if (tmp > use_delay) use_delay = tmp;
|
||||
}
|
||||
} else {
|
||||
assert(type_ == VEC8_DELAY);
|
||||
|
||||
/* How many bits to compare? */
|
||||
unsigned use_wid = cur_vec8_.size();
|
||||
|
|
@ -302,7 +345,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
/* what *should* happen here is we check to see if there is a
|
||||
transaction in the queue. This would be a pulse that needs to be
|
||||
eliminated. */
|
||||
clean_pulse_events_(use_delay);
|
||||
if (clean_pulse_events_(use_delay, bit)) return;
|
||||
|
||||
vvp_time64_t use_simtime = schedule_simtime() + use_delay;
|
||||
|
||||
|
|
@ -351,11 +394,14 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
|
|||
return;
|
||||
}
|
||||
|
||||
if (initial_) type_ = REAL_DELAY;
|
||||
else assert(type_ == REAL_DELAY);
|
||||
|
||||
vvp_time64_t use_delay;
|
||||
use_delay = delay_.get_min_delay();
|
||||
|
||||
/* Eliminate glitches. */
|
||||
clean_pulse_events_(use_delay);
|
||||
if (clean_pulse_events_(use_delay, bit)) return;
|
||||
|
||||
/* This must be done after cleaning pulses to avoid propagating
|
||||
* an incorrect value. */
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class vvp_delay_t {
|
|||
*/
|
||||
class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
|
||||
|
||||
enum delay_type_t {UNKNOWN_DELAY, VEC4_DELAY, VEC8_DELAY, REAL_DELAY};
|
||||
struct event_ {
|
||||
event_(vvp_time64_t s) : sim_time(s) { }
|
||||
void (vvp_fun_delay::*run_run_ptr)(struct vvp_fun_delay::event_*cur);
|
||||
|
|
@ -103,6 +104,7 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
private:
|
||||
vvp_net_t*net_;
|
||||
vvp_delay_t delay_;
|
||||
delay_type_t type_;
|
||||
bool initial_; // Indicates if the value is still the initial value.
|
||||
|
||||
vvp_vector4_t cur_vec4_;
|
||||
|
|
@ -133,6 +135,10 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
list_->next = cur->next;
|
||||
return cur;
|
||||
}
|
||||
bool clean_pulse_events_(vvp_time64_t use_delay, const vvp_vector4_t&bit);
|
||||
bool clean_pulse_events_(vvp_time64_t use_delay, const vvp_vector8_t&bit);
|
||||
bool clean_pulse_events_(vvp_time64_t use_delay, double bit);
|
||||
// Delete this when done!
|
||||
void clean_pulse_events_(vvp_time64_t use_delay);
|
||||
};
|
||||
|
||||
|
|
|
|||
26
vvp/event.cc
26
vvp/event.cc
|
|
@ -159,6 +159,32 @@ void schedule_evctl(vvp_array_t memory, unsigned index,
|
|||
ep->last = &((*(ep->last))->next);
|
||||
}
|
||||
|
||||
evctl_array_r::evctl_array_r(vvp_array_t memory, unsigned index,
|
||||
double value, unsigned long ecount)
|
||||
:evctl(ecount)
|
||||
{
|
||||
mem_ = memory;
|
||||
idx_ = index;
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
void evctl_array_r::run_run()
|
||||
{
|
||||
array_set_word(mem_, idx_, value_);
|
||||
}
|
||||
|
||||
void schedule_evctl(vvp_array_t memory, unsigned index,
|
||||
double value,
|
||||
vvp_net_t*event, unsigned long ecount)
|
||||
{
|
||||
// Get the functor we are going to wait on.
|
||||
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
|
||||
assert(ep);
|
||||
// Now add this call to the end of the event list.
|
||||
*(ep->last) = new evctl_array_r(memory, index, value, ecount);
|
||||
ep->last = &((*(ep->last))->next);
|
||||
}
|
||||
|
||||
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
|
||||
{
|
||||
return 1 << ((from << 2) | to);
|
||||
|
|
|
|||
18
vvp/event.h
18
vvp/event.h
|
|
@ -81,6 +81,20 @@ class evctl_array : public evctl {
|
|||
unsigned off_;
|
||||
};
|
||||
|
||||
class evctl_array_r : public evctl {
|
||||
|
||||
public:
|
||||
explicit evctl_array_r(vvp_array_t memory, unsigned index,
|
||||
double value, unsigned long ecount);
|
||||
virtual ~evctl_array_r() {}
|
||||
virtual void run_run();
|
||||
|
||||
private:
|
||||
vvp_array_t mem_;
|
||||
unsigned idx_;
|
||||
double value_;
|
||||
};
|
||||
|
||||
extern void schedule_evctl(struct __vpiHandle*handle, double value,
|
||||
vvp_net_t*event, unsigned long ecount);
|
||||
|
||||
|
|
@ -92,6 +106,10 @@ extern void schedule_evctl(vvp_array_t memory, unsigned index,
|
|||
const vvp_vector4_t&value, unsigned offset,
|
||||
vvp_net_t*event, unsigned long ecount);
|
||||
|
||||
extern void schedule_evctl(vvp_array_t memory, unsigned index,
|
||||
double value,
|
||||
vvp_net_t*event, unsigned long ecount);
|
||||
|
||||
/*
|
||||
* Event / edge detection functors
|
||||
*/
|
||||
|
|
|
|||
238
vvp/install-sh
238
vvp/install-sh
|
|
@ -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
|
||||
|
|
@ -422,6 +422,8 @@ int main(int argc, char*argv[])
|
|||
count_assign_real_pool());
|
||||
vpi_mcd_printf(1, " ...assign(word) pool=%lu\n",
|
||||
count_assign_aword_pool());
|
||||
vpi_mcd_printf(1, " ...assign(word/r) pool=%lu\n",
|
||||
count_assign_arword_pool());
|
||||
vpi_mcd_printf(1, " %8lu other events (pool=%lu)\n",
|
||||
count_gen_events, count_gen_pool());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,26 @@ means the following:
|
|||
1 and 1 --> 1
|
||||
otherwise x
|
||||
|
||||
* %assign/ar <array-label>, <delay>, <bit>
|
||||
* %assign/ar/d <array-label>, <delayx>, <bit>
|
||||
* %assign/ar/e <array-label>, <bit>
|
||||
|
||||
The %assign/ar instruction assigns a real value to a word in the
|
||||
labeled real array. The <delay> is the delay in simulation time to
|
||||
the assignment (0 for non-blocking assignment) and <bit> is the
|
||||
index register that contains the value to write.
|
||||
|
||||
The memory word address is read from index register 3. The address is
|
||||
in canonical form.
|
||||
|
||||
The %assign/ar/d variation reads the delay from an integer register that
|
||||
is given by the <delayx> value. This should not be 3 or the <bit> index,
|
||||
of course, since these registers contain the word address and the value.
|
||||
|
||||
The %assign/ar/e variation uses the information in the thread
|
||||
event control registers to determine when to perform the assign.
|
||||
%evctl is used to set the event control information.
|
||||
|
||||
* %assign/av <array-label>, <delay>, <bit>
|
||||
* %assign/av/d <array-label>, <delayx>, <bit>
|
||||
* %assign/av/e <array-label>, <bit>
|
||||
|
|
@ -417,7 +437,7 @@ These instructions are like the %ix/get instructions, except that they
|
|||
read directly from a functor label instead of from thread bits. They
|
||||
set bit 4 just like %ix/get.
|
||||
|
||||
* %ix/load <idx>, <low> <high>
|
||||
* %ix/load <idx>, <low>, <high>
|
||||
|
||||
This instruction loads an immediate value into the addressed index
|
||||
register. The index register holds signed 64 bit numeric values, so
|
||||
|
|
@ -428,9 +448,9 @@ vector. The values are unsigned decimal values and are combined as
|
|||
<high> << 32 | <low> to produce the final value.
|
||||
|
||||
|
||||
* %ix/add <idx>, <low> <high>
|
||||
* %ix/sub <idx>, <low> <high>
|
||||
* %ix/mul <idx>, <low> <high>
|
||||
* %ix/add <idx>, <low>, <high>
|
||||
* %ix/sub <idx>, <low>, <high>
|
||||
* %ix/mul <idx>, <low>, <high>
|
||||
|
||||
These instructions add, subtract, or multiply the selected index
|
||||
register by the immediate value. The 64 bit immediate value is built
|
||||
|
|
@ -491,7 +511,8 @@ vector is sign extended (instead of 0-extended) before the addition.
|
|||
|
||||
This instruction is similar to %load/av, but it loads only a single
|
||||
bit, and the <index> is the selector for the bit to use. If <index> is
|
||||
out of range, then x is loaded.
|
||||
out of range, then x is loaded. The index value is incremented by one
|
||||
if it is defined (bit 4 is not 1).
|
||||
|
||||
* %load/v <bit>, <functor-label>, <wid>
|
||||
|
||||
|
|
@ -758,6 +779,8 @@ bits) by the amount in index register 0. The <bit> is the address of
|
|||
the LSB of the vector, and <wid> the width of the vector. The shift is
|
||||
done in place. Zero values are shifted in.
|
||||
|
||||
For a negative shift the value is padded with 'bx.
|
||||
|
||||
* %shiftr/i0 <bit>, <wid>
|
||||
* %shiftr/s/i0 <bit>, <wid>
|
||||
|
||||
|
|
@ -769,6 +792,8 @@ shift is done in place.
|
|||
%shiftr/i0 is an unsigned down shift, so zeros are shifted into the
|
||||
top bits. %shiftr/s/i0 is a signed shift, so the value is sign-extended.
|
||||
|
||||
For a negative shift %shiftr/i0 will pad the value with 'bx.
|
||||
|
||||
* %sub <bit-l>, <bit-r>, <wid>
|
||||
|
||||
This instruction arithmetically subtracts the right vector out of the
|
||||
|
|
@ -846,7 +871,7 @@ and leaves the result in the <dst> vector. xor is this:
|
|||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
|
|||
35
vvp/part.cc
35
vvp/part.cc
|
|
@ -86,11 +86,8 @@ void vvp_fun_part_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
{
|
||||
assert(bit.size() == wid);
|
||||
|
||||
vvp_vector4_t tmp = val_;
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid);
|
||||
|
||||
assert(tmp.size() == vwid);
|
||||
vvp_vector4_t tmp (vwid, BIT4_Z);
|
||||
tmp.set_vec(base_, val_);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp, 0);
|
||||
}
|
||||
|
|
@ -178,11 +175,8 @@ void vvp_fun_part_aa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
vvp_vector4_t tmp = *val;
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid);
|
||||
|
||||
assert(tmp.size() == vwid);
|
||||
vvp_vector4_t tmp (vwid, BIT4_Z);
|
||||
tmp.set_vec(base_, *val);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp, context);
|
||||
} else {
|
||||
|
|
@ -244,17 +238,20 @@ vvp_fun_part_var::~vvp_fun_part_var()
|
|||
}
|
||||
|
||||
bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned&base, vvp_vector4_t&source,
|
||||
long&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref)
|
||||
{
|
||||
unsigned long tmp;
|
||||
long tmp;
|
||||
switch (port.port()) {
|
||||
case 0:
|
||||
source = bit;
|
||||
break;
|
||||
case 1:
|
||||
tmp = ULONG_MAX;
|
||||
vector4_to_value(bit, tmp);
|
||||
// LONG_MIN is before the vector and is used to
|
||||
// represent a 'bx value on the select input.
|
||||
tmp = LONG_MIN;
|
||||
// We need a new &PV<> that knows if the index is signed.
|
||||
vector4_to_value(bit, tmp, false);
|
||||
if (tmp == base) return false;
|
||||
base = tmp;
|
||||
break;
|
||||
|
|
@ -267,11 +264,11 @@ bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
vvp_vector4_t res (wid_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
unsigned adr = base+idx;
|
||||
if (adr >= source.size())
|
||||
break;
|
||||
long adr = base+idx;
|
||||
if (adr < 0) continue;
|
||||
if ((unsigned)adr >= source.size()) break;
|
||||
|
||||
res.set_bit(idx, source.value(adr));
|
||||
res.set_bit(idx, source.value((unsigned)adr));
|
||||
}
|
||||
|
||||
if (! ref.eeq(res)) {
|
||||
|
|
@ -316,7 +313,7 @@ void vvp_fun_part_var_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&b
|
|||
struct vvp_fun_part_var_state_s {
|
||||
vvp_fun_part_var_state_s() : base(0) { }
|
||||
|
||||
unsigned base;
|
||||
long base;
|
||||
vvp_vector4_t source;
|
||||
vvp_vector4_t ref;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class vvp_fun_part_var : public vvp_net_fun_t {
|
|||
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned&base, vvp_vector4_t&source,
|
||||
long&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref);
|
||||
|
||||
unsigned wid_;
|
||||
|
|
@ -154,7 +154,7 @@ class vvp_fun_part_var_sa : public vvp_fun_part_var {
|
|||
vvp_context_t);
|
||||
|
||||
private:
|
||||
unsigned base_;
|
||||
long base_;
|
||||
vvp_vector4_t source_;
|
||||
// Save the last output, for detecting change.
|
||||
vvp_vector4_t ref_;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -278,6 +278,37 @@ void propagate_vector4_event_s::run_run(void)
|
|||
net->send_vec4(val, 0);
|
||||
}
|
||||
|
||||
struct assign_array_r_word_s : public event_s {
|
||||
vvp_array_t mem;
|
||||
unsigned adr;
|
||||
double val;
|
||||
void run_run(void);
|
||||
|
||||
static void* operator new(size_t);
|
||||
static void operator delete(void*);
|
||||
};
|
||||
|
||||
void assign_array_r_word_s::run_run(void)
|
||||
{
|
||||
count_assign_events += 1;
|
||||
array_set_word(mem, adr, val);
|
||||
}
|
||||
static const size_t ARRAY_R_W_CHUNK_COUNT = 8192 / sizeof(struct assign_array_r_word_s);
|
||||
static slab_t<sizeof(assign_array_r_word_s),ARRAY_R_W_CHUNK_COUNT> array_r_w_heap;
|
||||
|
||||
inline void* assign_array_r_word_s::operator new(size_t size)
|
||||
{
|
||||
assert(size == sizeof(assign_array_r_word_s));
|
||||
return array_r_w_heap.alloc_slab();
|
||||
}
|
||||
|
||||
void assign_array_r_word_s::operator delete(void*ptr)
|
||||
{
|
||||
array_r_w_heap.free_slab(ptr);
|
||||
}
|
||||
|
||||
unsigned long count_assign_arword_pool(void) { return array_r_w_heap.pool; }
|
||||
|
||||
struct generic_event_s : public event_s {
|
||||
vvp_gen_event_t obj;
|
||||
bool delete_obj_when_done;
|
||||
|
|
@ -641,6 +672,18 @@ void schedule_assign_array_word(vvp_array_t mem,
|
|||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_assign_array_word(vvp_array_t mem,
|
||||
unsigned word_addr,
|
||||
double val,
|
||||
vvp_time64_t delay)
|
||||
{
|
||||
struct assign_array_r_word_s*cur = new struct assign_array_r_word_s;
|
||||
cur->mem = mem;
|
||||
cur->adr = word_addr;
|
||||
cur->val = val;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __schedule_H
|
||||
#define __schedule_H
|
||||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -58,13 +58,17 @@ extern void schedule_assign_array_word(vvp_array_t mem,
|
|||
vvp_vector4_t val,
|
||||
vvp_time64_t delay);
|
||||
|
||||
extern void schedule_assign_array_word(vvp_array_t mem,
|
||||
unsigned word_address,
|
||||
double val,
|
||||
vvp_time64_t delay);
|
||||
/*
|
||||
* Create an event to propagate the output of a net.
|
||||
*/
|
||||
extern void schedule_propagate_plucked_vector(vvp_net_t*ptr,
|
||||
vvp_time64_t delay,
|
||||
vvp_time64_t delay,
|
||||
const vvp_vector4_t&val,
|
||||
unsigned adr, unsigned wid);
|
||||
unsigned adr, unsigned wid);
|
||||
|
||||
/*
|
||||
* This is very similar to schedule_assign_vector, but generates an
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __statistics_H
|
||||
#define __statistics_H
|
||||
/*
|
||||
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -47,6 +47,7 @@ extern unsigned long count_assign4_pool(void);
|
|||
extern unsigned long count_assign8_pool(void);
|
||||
extern unsigned long count_assign_real_pool(void);
|
||||
extern unsigned long count_assign_aword_pool(void);
|
||||
extern unsigned long count_assign_arword_pool(void);
|
||||
|
||||
extern unsigned long count_gen_events;
|
||||
extern unsigned long count_gen_pool(void);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
|
|
@ -1000,12 +1001,24 @@ static int PV_get_base(struct __vpiPV*rfp)
|
|||
/* If the width is zero then tbase is the constant. */
|
||||
if (rfp->twid == 0) return rfp->tbase;
|
||||
|
||||
/* Get the value from thread space. */
|
||||
int tval = 0;
|
||||
for (unsigned idx = 0 ; idx < rfp->twid ; idx += 1) {
|
||||
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread,
|
||||
rfp->tbase + idx);
|
||||
if (bit == BIT4_1) {
|
||||
switch (bit) {
|
||||
case BIT4_X:
|
||||
case BIT4_Z:
|
||||
/* We use INT_MIN to indicate an X base. */
|
||||
return INT_MIN;
|
||||
break;
|
||||
|
||||
case BIT4_1:
|
||||
tval |= 1<<idx;
|
||||
break;
|
||||
|
||||
case BIT4_0:
|
||||
break; // Do nothing!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
169
vvp/vthread.cc
169
vvp/vthread.cc
|
|
@ -794,6 +794,68 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* %assign/ar <array>, <delay>, <bit>
|
||||
* Generate an assignment event to a real array. Index register 3
|
||||
* contains the canonical address of the word in the memory. <delay>
|
||||
* is the delay in simulation time. <bit> is the index register
|
||||
* containing the real value.
|
||||
*/
|
||||
bool of_ASSIGN_AR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
long adr = thr->words[3].w_int;
|
||||
unsigned delay = cp->bit_idx[0];
|
||||
double value = thr->words[cp->bit_idx[1]].w_real;
|
||||
|
||||
if (adr >= 0) {
|
||||
schedule_assign_array_word(cp->array, adr, value, delay);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* %assign/ar/d <array>, <delay_idx>, <bit>
|
||||
* Generate an assignment event to a real array. Index register 3
|
||||
* contains the canonical address of the word in the memory.
|
||||
* <delay_idx> is the integer register that contains the delay value.
|
||||
* <bit> is the index register containing the real value.
|
||||
*/
|
||||
bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
long adr = thr->words[3].w_int;
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
double value = thr->words[cp->bit_idx[1]].w_real;
|
||||
|
||||
if (adr >= 0) {
|
||||
schedule_assign_array_word(cp->array, adr, value, delay);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* %assign/ar/e <array>, <bit>
|
||||
* Generate an assignment event to a real array. Index register 3
|
||||
* contains the canonical address of the word in the memory. <bit>
|
||||
* is the index register containing the real value. The event
|
||||
* information is contained in the thread event control registers
|
||||
* and is set with %evctl.
|
||||
*/
|
||||
bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
long adr = thr->words[3].w_int;
|
||||
double value = thr->words[cp->bit_idx[0]].w_real;
|
||||
|
||||
if (adr >= 0) {
|
||||
if (thr->ecount == 0) {
|
||||
schedule_assign_array_word(cp->array, adr, value, 0);
|
||||
} else {
|
||||
schedule_evctl(cp->array, adr, value, thr->event,
|
||||
thr->ecount);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* %assign/av <array>, <delay>, <bit>
|
||||
* This generates an assignment event to an array. Index register 0
|
||||
* contains the width of the vector (and the word) and index register
|
||||
|
|
@ -803,10 +865,12 @@ bool of_ASSIGN_AV(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
long adr = thr->words[3].w_int;
|
||||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
if (adr < 0) return true;
|
||||
|
||||
long vwidth = get_array_word_size(cp->array);
|
||||
// We fell off the MSB end.
|
||||
if (off >= vwidth) return true;
|
||||
|
|
@ -840,10 +904,12 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
long adr = thr->words[3].w_int;
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
if (adr < 0) return true;
|
||||
|
||||
long vwidth = get_array_word_size(cp->array);
|
||||
// We fell off the MSB end.
|
||||
if (off >= vwidth) return true;
|
||||
|
|
@ -871,9 +937,11 @@ bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
long adr = thr->words[3].w_int;
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
|
||||
if (adr < 0) return true;
|
||||
|
||||
long vwidth = get_array_word_size(cp->array);
|
||||
// We fell off the MSB end.
|
||||
if (off >= vwidth) return true;
|
||||
|
|
@ -2574,7 +2642,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
|||
unsigned base = cp->bit_idx[1];
|
||||
unsigned width = cp->number;
|
||||
|
||||
unsigned long v = 0;
|
||||
uint64_t v = 0;
|
||||
bool unknown_flag = false;
|
||||
|
||||
vvp_bit4_t vv = BIT4_0;
|
||||
|
|
@ -2586,7 +2654,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
|||
break;
|
||||
}
|
||||
|
||||
v |= (unsigned long) vv << i;
|
||||
v |= (uint64_t) vv << i;
|
||||
|
||||
if (base >= 4)
|
||||
base += 1;
|
||||
|
|
@ -2594,7 +2662,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/* Sign-extend to fill the integer value. */
|
||||
if (!unknown_flag) {
|
||||
unsigned long pad = vv;
|
||||
uint64_t pad = vv;
|
||||
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
|
||||
v |= pad << i;
|
||||
}
|
||||
|
|
@ -2784,8 +2852,15 @@ bool of_LOAD_AR(vthread_t thr, vvp_code_t cp)
|
|||
unsigned bit = cp->bit_idx[0];
|
||||
unsigned idx = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
double word;
|
||||
|
||||
/* The result is 0.0 if the address is undefined. */
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
word = 0.0;
|
||||
} else {
|
||||
word = array_get_word_r(cp->array, adr);
|
||||
}
|
||||
|
||||
double word = array_get_word_r(cp->array, adr);
|
||||
thr->words[bit].w_real = word;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2805,11 +2880,18 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
|
|||
unsigned wid = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
vvp_vector4_t word = array_get_word(cp->array, adr);
|
||||
|
||||
/* Check the address once, before we scan the vector. */
|
||||
thr_check_addr(thr, bit+wid-1);
|
||||
|
||||
/* The result is 'bx if the address is undefined. */
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(bit, tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
vvp_vector4_t word = array_get_word(cp->array, adr);
|
||||
|
||||
if (word.size() > wid)
|
||||
word.resize(wid);
|
||||
|
||||
|
|
@ -2880,6 +2962,15 @@ bool of_LOAD_AVP0(vthread_t thr, vvp_code_t cp)
|
|||
unsigned wid = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
/* The result is 'bx if the address is undefined. */
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
thr_check_addr(thr, bit+wid-1);
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(bit, tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We need a vector this wide to make the math work correctly.
|
||||
* Copy the base bits into the vector, but keep the width. */
|
||||
vvp_vector4_t sig_value(wid, BIT4_0);
|
||||
|
|
@ -2894,6 +2985,15 @@ bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t cp)
|
|||
unsigned wid = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
/* The result is 'bx if the address is undefined. */
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
thr_check_addr(thr, bit+wid-1);
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(bit, tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
vvp_vector4_t tmp (array_get_word(cp->array, adr));
|
||||
|
||||
/* We need a vector this wide to make the math work correctly.
|
||||
|
|
@ -2920,11 +3020,17 @@ bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t cp)
|
|||
unsigned index = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
unsigned use_index = thr->words[index].w_int;
|
||||
/* The result is 'bx if the address is undefined. */
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
thr_put_bit(thr, bit, BIT4_X);
|
||||
return true;
|
||||
}
|
||||
|
||||
long use_index = thr->words[index].w_int;
|
||||
|
||||
vvp_vector4_t word = array_get_word(cp->array, adr);
|
||||
|
||||
if (use_index >= word.size()) {
|
||||
if ((use_index >= (long)word.size()) || (use_index < 0)) {
|
||||
thr_put_bit(thr, bit, BIT4_X);
|
||||
} else {
|
||||
thr_put_bit(thr, bit, word.value(use_index));
|
||||
|
|
@ -4096,7 +4202,7 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned base = cp->bit_idx[0];
|
||||
unsigned wid = cp->number;
|
||||
unsigned long shift = thr->words[0].w_int;
|
||||
long shift = thr->words[0].w_int;
|
||||
|
||||
assert(base >= 4);
|
||||
thr_check_addr(thr, base+wid-1);
|
||||
|
|
@ -4105,7 +4211,8 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
|||
// The result is 'bx if the shift amount is undefined.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
} else if (shift >= wid) {
|
||||
|
||||
} else if (shift >= (long)wid) {
|
||||
// Shift is so far that all value is shifted out. Write
|
||||
// in a constant 0 result.
|
||||
vvp_vector4_t tmp (wid, BIT4_0);
|
||||
|
|
@ -4118,6 +4225,17 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
|||
// Fill zeros on the bottom
|
||||
vvp_vector4_t fil (shift, BIT4_0);
|
||||
thr->bits4.set_vec(base, fil);
|
||||
|
||||
} else if (shift < 0) {
|
||||
// For a negative shift we pad with 'bx.
|
||||
unsigned idx;
|
||||
for (idx = 0 ; (idx-shift) < wid ; idx += 1) {
|
||||
unsigned src = base + idx - shift;
|
||||
unsigned dst = base + idx;
|
||||
thr_put_bit(thr, dst, thr_get_bit(thr, src));
|
||||
}
|
||||
for ( ; idx < wid ; idx += 1)
|
||||
thr_put_bit(thr, base+idx, BIT4_X);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4134,12 +4252,16 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned base = cp->bit_idx[0];
|
||||
unsigned wid = cp->number;
|
||||
unsigned long shift = thr->words[0].w_int;
|
||||
long shift = thr->words[0].w_int;
|
||||
|
||||
assert(base >= 4);
|
||||
thr_check_addr(thr, base+wid-1);
|
||||
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift > 0) {
|
||||
unsigned idx;
|
||||
for (idx = 0 ; (idx+shift) < wid ; idx += 1) {
|
||||
|
|
@ -4149,6 +4271,21 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
for ( ; idx < wid ; idx += 1)
|
||||
thr_put_bit(thr, base+idx, BIT4_0);
|
||||
|
||||
} else if (shift < -(long)wid) {
|
||||
// Negative shift is so far that all the value is shifted out.
|
||||
// Write in a constant 'bx result.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift < 0) {
|
||||
|
||||
// For a negative shift we pad with 'bx.
|
||||
vvp_vector4_t tmp (thr->bits4, base, wid+shift);
|
||||
thr->bits4.set_vec(base-shift, tmp);
|
||||
|
||||
vvp_vector4_t fil (-shift, BIT4_X);
|
||||
thr->bits4.set_vec(base, fil);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4161,7 +4298,7 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
|
|||
vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
|
||||
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
} else if (shift >= wid) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine
|
|||
|
||||
.SH SYNOPSIS
|
||||
.B vvp
|
||||
[-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
|
||||
[\-nNsvV] [\-Mpath] [\-mmodule] [\-llogfile] inputfile [extended-args...]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
|
|
@ -14,7 +14,6 @@ command is not by itself executable on any platform. Instead, the
|
|||
\fIvvp\fP program is invoked to execute the generated output file.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
\fIvvp\fP accepts the following options:
|
||||
.TP 8
|
||||
.B -l\fIlogfile\fP
|
||||
|
|
@ -121,7 +120,7 @@ to print information about the annotation.
|
|||
|
||||
.TP 8
|
||||
.B -sdf-verbose
|
||||
This is shorthand for -sdf-info -sdf-warn.
|
||||
This is shorthand for \-sdf\-info \-sdf\-warn.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.PP
|
||||
|
|
|
|||
Loading…
Reference in New Issue