mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-24 06:46:52 +02:00
Compare commits
217
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb444b6178 | ||
|
|
7442c14689 | ||
|
|
0082795967 | ||
|
|
ac4f4cf1a0 | ||
|
|
676d23f973 | ||
|
|
6069cbfc3c | ||
|
|
cfbc90812b | ||
|
|
e530b4e642 | ||
|
|
6a3edc63d5 | ||
|
|
3069b8dd51 | ||
|
|
7db01d8ded | ||
|
|
e4694cb6cb | ||
|
|
08e5aa021a | ||
|
|
4304fd503e | ||
|
|
5438464d67 | ||
|
|
6df2979998 | ||
|
|
9de4ced133 | ||
|
|
45dc13e496 | ||
|
|
9e3f1ef1ff | ||
|
|
1b3e321d35 | ||
|
|
a27274aa04 | ||
|
|
f1be16be7c | ||
|
|
9ac374501c | ||
|
|
250b278d0e | ||
|
|
52275deb0e | ||
|
|
120ad59017 | ||
|
|
2ac8a555e1 | ||
|
|
8d845ae49f | ||
|
|
352175d921 | ||
|
|
e78205eacf | ||
|
|
c6e618350d | ||
|
|
301a7e587b | ||
|
|
3cee5d4567 | ||
|
|
e1ae5020c4 | ||
|
|
22d15f9ca9 | ||
|
|
19d966e235 | ||
|
|
c8fe897446 | ||
|
|
5101b3b64b | ||
|
|
bed5ee4529 | ||
|
|
7c0a191626 | ||
|
|
cfa43c7742 | ||
|
|
a5138e238f | ||
|
|
d352d8ead3 | ||
|
|
02ee3874e7 | ||
|
|
f9fef5d00b | ||
|
|
891399185f | ||
|
|
5dc1396eea | ||
|
|
ccf7c042c9 | ||
|
|
560b9530fd | ||
|
|
b89c059153 | ||
|
|
8326fe843b | ||
|
|
1cbc38100e | ||
|
|
ba31252226 | ||
|
|
008affe557 | ||
|
|
0ca856d4e8 | ||
|
|
2a210dfee1 | ||
|
|
83d721232d | ||
|
|
d5ffb55bfd | ||
|
|
ab9a8ccbf3 | ||
|
|
e6525ec35f | ||
|
|
afaedbd06d | ||
|
|
d4237774a5 | ||
|
|
2f2539e557 | ||
|
|
11a86794d9 | ||
|
|
3b14797075 | ||
|
|
e006f9e132 | ||
|
|
437dc10341 | ||
|
|
102d2d534f | ||
|
|
5e437145bf | ||
|
|
d1dc98b7f7 | ||
|
|
50b45dac7b | ||
|
|
295e4e7dfb | ||
|
|
807ad8002d | ||
|
|
d3229b9068 | ||
|
|
099bb427bc | ||
|
|
d406545331 | ||
|
|
1de3fb1625 | ||
|
|
e33b8b4dde | ||
|
|
9128eb67b9 | ||
|
|
afbda099fb | ||
|
|
4b0d220671 | ||
|
|
a42b056b24 | ||
|
|
1852c5ab9d | ||
|
|
24be13d825 | ||
|
|
bddfcac823 | ||
|
|
ea1c07e234 | ||
|
|
8e0ae733ca | ||
|
|
feb710a186 | ||
|
|
62abb199d7 | ||
|
|
7373bf2224 | ||
|
|
ae629f8c41 | ||
|
|
03e0e96832 | ||
|
|
3c38b2972d | ||
|
|
4f1fc6e302 | ||
|
|
f1436fbe62 | ||
|
|
a79533ddc9 | ||
|
|
d47afb588b | ||
|
|
386774ac19 | ||
|
|
9ca754b6db | ||
|
|
0f0bef32f2 | ||
|
|
cd55f30a27 | ||
|
|
5884879b02 | ||
|
|
a1a4f47894 | ||
|
|
e569e07d4e | ||
|
|
ee840391d6 | ||
|
|
0046e9eca0 | ||
|
|
f51c037432 | ||
|
|
763c6fe3c9 | ||
|
|
49b6ddf93c | ||
|
|
12b4914b63 | ||
|
|
fc0728ab6f | ||
|
|
46c41f9be2 | ||
|
|
cdf18de10e | ||
|
|
19ff6a434b | ||
|
|
5349ca9a55 | ||
|
|
5b7b980ead | ||
|
|
a1c2a8e605 | ||
|
|
8777cd8e7c | ||
|
|
11bb7ac348 | ||
|
|
9de69f2f24 | ||
|
|
dae3410dcd | ||
|
|
1a367c84b6 | ||
|
|
8a854affa6 | ||
|
|
60077f4f06 | ||
|
|
51ce9f1a60 | ||
|
|
48265ecd9b | ||
|
|
abbcea64d0 | ||
|
|
25c3798248 | ||
|
|
90293d8e0a | ||
|
|
621cf37339 | ||
|
|
6d75af86e6 | ||
|
|
5d26f0e28d | ||
|
|
774609fbbb | ||
|
|
9ba7694484 | ||
|
|
870a826225 | ||
|
|
2ecfed0baa | ||
|
|
56e410f386 | ||
|
|
d4dd635bf6 | ||
|
|
c287281bbe | ||
|
|
962330f20a | ||
|
|
777e7e0a3d | ||
|
|
839f9cd7ae | ||
|
|
b8b2f53027 | ||
|
|
9b3bd039bb | ||
|
|
51b9191021 | ||
|
|
756c9ceccf | ||
|
|
8b3667f76e | ||
|
|
a52242745a | ||
|
|
ff5b696569 | ||
|
|
b05a19dffc | ||
|
|
e6b22a2bea | ||
|
|
a02ebc3114 | ||
|
|
0592ba042e | ||
|
|
bcca3cf395 | ||
|
|
01ba41afd8 | ||
|
|
84c592b068 | ||
|
|
bb93a585b6 | ||
|
|
47688d234b | ||
|
|
b3425d6cf3 | ||
|
|
40ae1051d4 | ||
|
|
21c60b38e1 | ||
|
|
78c6b3cad2 | ||
|
|
a04104077f | ||
|
|
0e3a758894 | ||
|
|
d682029240 | ||
|
|
1ffcd40336 | ||
|
|
09439c55ab | ||
|
|
c858dea2d5 | ||
|
|
228a3f123a | ||
|
|
074f7a7a49 | ||
|
|
f642313e1b | ||
|
|
dd9d96eb07 | ||
|
|
35401f0e2c | ||
|
|
b6e16aea6b | ||
|
|
eeaf23041b | ||
|
|
e8096eda80 | ||
|
|
961d6a8f3b | ||
|
|
288ebf011c | ||
|
|
0ae304b6a8 | ||
|
|
5e61bb64b7 | ||
|
|
3f847fd927 | ||
|
|
4a41a53b42 | ||
|
|
a1630e1d30 | ||
|
|
bca84d9dbb | ||
|
|
e61ed48914 | ||
|
|
d29a6d134f | ||
|
|
6310b47538 | ||
|
|
9c75a4b96b | ||
|
|
c57e68292c | ||
|
|
0fecdcbeda | ||
|
|
23ad62f317 | ||
|
|
ac20008606 | ||
|
|
96d181efed | ||
|
|
18bfe7d497 | ||
|
|
86562e60ba | ||
|
|
b400532169 | ||
|
|
6fd10dedb6 | ||
|
|
c8255952a3 | ||
|
|
71c4ea36e8 | ||
|
|
5df179cd5f | ||
|
|
ce5c4ca8ba | ||
|
|
6aa8e49b09 | ||
|
|
f29f4ff4e3 | ||
|
|
3ccc59eaa3 | ||
|
|
0282b8450c | ||
|
|
43841af2f3 | ||
|
|
b2d8d41e3f | ||
|
|
0e38843ae9 | ||
|
|
96472e5537 | ||
|
|
48b0fed29e | ||
|
|
1efa220773 | ||
|
|
2d6622e543 | ||
|
|
edf112b900 | ||
|
|
f0a0ab100f | ||
|
|
c28188618b | ||
|
|
0d7daf5862 | ||
|
|
60ab1daa1f |
@@ -0,0 +1,2 @@
|
||||
# gperf in MSYS chokes on DOS line endings
|
||||
*.gperf text eol=lf
|
||||
+3
-3
@@ -118,8 +118,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
|
||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
|
||||
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
|
||||
PGenerate.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||
Statement.o AStatement.o $M $(FF) $(TT)
|
||||
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
|
||||
PFunction.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
|
||||
|
||||
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
|
||||
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
|
||||
@@ -292,7 +292,7 @@ endif
|
||||
version_tag.h version:
|
||||
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
|
||||
echo "Using git-describe for VERSION_TAG"; \
|
||||
tmp=`$(GIT) --git-dir $(srcdir)/.git describe --always --dirty \
|
||||
tmp=`(cd $(srcdir) && $(GIT) describe --always --dirty) \
|
||||
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
|
||||
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
|
||||
elif test -r $(srcdir)/version_tag.h; then \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_Module_H
|
||||
#define IVL_Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* 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,6 +35,7 @@ class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
class PGenerate;
|
||||
class PModport;
|
||||
class PSpecPath;
|
||||
class PTask;
|
||||
class PFunction;
|
||||
@@ -47,6 +48,10 @@ class NetScope;
|
||||
* A module is a named container and scope. A module holds a bunch of
|
||||
* semantic quantities such as wires and gates. The module is
|
||||
* therefore the handle for grasping the described circuit.
|
||||
*
|
||||
* SystemVerilog introduces program blocks and interfaces. These have
|
||||
* much in common with modules, so the Module class is used to represent
|
||||
* these containers as well.
|
||||
*/
|
||||
|
||||
class Module : public PScopeExtra, public LineInfo {
|
||||
@@ -64,7 +69,7 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
|
||||
public:
|
||||
/* The name passed here is the module name, not the instance
|
||||
name. This make must be a permallocated string. */
|
||||
name. This name must be a permallocated string. */
|
||||
explicit Module(LexicalScope*parent, perm_string name);
|
||||
~Module();
|
||||
|
||||
@@ -81,6 +86,11 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
restrictions and slightly modify scheduling semantics. */
|
||||
bool program_block;
|
||||
|
||||
/* This is true if the module represents a interface
|
||||
instead of a module/cell. Interfaces have different
|
||||
content restrictions and some extra allowed items. */
|
||||
bool is_interface;
|
||||
|
||||
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||
UCDriveType uc_drive;
|
||||
|
||||
@@ -125,6 +135,11 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
unless they are instantiated, implicitly or explicitly. */
|
||||
std::map<perm_string,Module*> nested_modules;
|
||||
|
||||
/* An interface can contain one or more named modport lists.
|
||||
The parser will ensure these don't appear in modules or
|
||||
program blocks. */
|
||||
map<perm_string,PModport*> modports;
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
|
||||
// The mod_name() is the name of the module type.
|
||||
|
||||
@@ -436,7 +436,7 @@ class PEIdent : public PExpr {
|
||||
const perm_string&) const;
|
||||
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
||||
NetAssign_*,
|
||||
const perm_string&) const;
|
||||
const name_component_t&) const;
|
||||
bool elaborate_lval_darray_bit_(Design*, NetScope*,
|
||||
NetAssign_*) const;
|
||||
|
||||
@@ -917,8 +917,10 @@ class PECallFunction : public PExpr {
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
@@ -997,6 +999,9 @@ class PECastType : public PExpr {
|
||||
|
||||
void dump(ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PModport.h"
|
||||
|
||||
PModport::PModport(perm_string n)
|
||||
: name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PModport::~PModport()
|
||||
{
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#ifndef IVL_PModport_H
|
||||
#define IVL_PModport_H
|
||||
/*
|
||||
* Copyright (c) 2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "PScope.h"
|
||||
# include "StringHeap.h"
|
||||
# include "netlist.h"
|
||||
# include <vector>
|
||||
|
||||
/*
|
||||
* The PModport class represents a parsed SystemVerilog modport list.
|
||||
*/
|
||||
class PModport : public LineInfo {
|
||||
|
||||
public:
|
||||
// The name is a perm-allocated string. It is the simple name
|
||||
// of the modport, without any scope.
|
||||
explicit PModport(perm_string name);
|
||||
~PModport();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
map<perm_string,simple_port_t> simple_ports;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
private: // not implemented
|
||||
PModport(const PModport&);
|
||||
PModport& operator= (const PModport&);
|
||||
};
|
||||
|
||||
#endif /* IVL_PModport_H */
|
||||
Vendored
+2
-1
@@ -223,8 +223,9 @@ AC_SUBST(strip_dynamic)
|
||||
# -------------
|
||||
AC_DEFUN([AX_C99_STRTOD],
|
||||
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
|
||||
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
|
||||
case "${host}" in
|
||||
*-*-mingw*)
|
||||
*-*-mingw32)
|
||||
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
|
||||
;;
|
||||
esac
|
||||
|
||||
Vendored
+324
-447
File diff suppressed because it is too large
Load Diff
Vendored
+225
-101
@@ -1,44 +1,40 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-04-17'
|
||||
timestamp='2015-03-08'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# 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., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# 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.
|
||||
# the same distribution terms that you use for the rest of that
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
|
||||
# Please send patches to <[email protected]>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
# Please send patches to <[email protected]>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
# that are meaningful with *any* GNU software.
|
||||
@@ -72,8 +68,7 @@ Report bugs and patches to <[email protected]>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright 1992-2015 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."
|
||||
@@ -120,13 +115,18 @@ 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* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
android-linux)
|
||||
os=-linux-android
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
@@ -149,10 +149,13 @@ 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 | -knuth | -cray)
|
||||
-apple | -axis | -knuth | -cray | -microblaze*)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
@@ -167,10 +170,10 @@ case $os in
|
||||
os=-chorusos
|
||||
basic_machine=$1
|
||||
;;
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
basic_machine=$1
|
||||
;;
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
@@ -215,6 +218,12 @@ case $os in
|
||||
-isc*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-lynx*178)
|
||||
os=-lynxos178
|
||||
;;
|
||||
-lynx*5)
|
||||
os=-lynxos5
|
||||
;;
|
||||
-lynx*)
|
||||
os=-lynxos
|
||||
;;
|
||||
@@ -239,20 +248,28 @@ case $basic_machine in
|
||||
# Some are omitted here because they have special meanings below.
|
||||
1750a | 580 \
|
||||
| a29k \
|
||||
| aarch64 | aarch64_be \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@@ -266,36 +283,55 @@ case $basic_machine in
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa32r6 | mipsisa32r6el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64r6 | mipsisa64r6el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| or32 \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| 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 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| spu \
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| we32k \
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
# Motorola 68HC11/12.
|
||||
c54x)
|
||||
basic_machine=tic54x-unknown
|
||||
;;
|
||||
c55x)
|
||||
basic_machine=tic55x-unknown
|
||||
;;
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
leon|leon[3-9])
|
||||
basic_machine=sparc-$basic_machine
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
@@ -305,6 +341,21 @@ case $basic_machine in
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
strongarm | thumb | xscale)
|
||||
basic_machine=arm-unknown
|
||||
;;
|
||||
xgate)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
xscaleeb)
|
||||
basic_machine=armeb-unknown
|
||||
;;
|
||||
|
||||
xscaleel)
|
||||
basic_machine=armel-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
@@ -319,25 +370,31 @@ case $basic_machine in
|
||||
# Recognize the basic CPU types with company name.
|
||||
580-* \
|
||||
| a29k-* \
|
||||
| aarch64-* | aarch64_be-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| microblaze-* | microblazeel-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
@@ -351,32 +408,42 @@ case $basic_machine in
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa32r6-* | mipsisa32r6el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64r6-* | mipsisa64r6el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nios-* | nios2-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| or1k*-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| 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-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-* | z80-*)
|
||||
@@ -401,7 +468,7 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
@@ -451,6 +518,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -467,11 +537,24 @@ case $basic_machine in
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c54x-*)
|
||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c55x-*)
|
||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c6x-*)
|
||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
@@ -503,7 +586,7 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16)
|
||||
cr16 | cr16-*)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
@@ -661,7 +744,6 @@ case $basic_machine in
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i*86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
@@ -700,6 +782,9 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
@@ -719,8 +804,15 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze*)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-mingw64
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
@@ -748,6 +840,10 @@ case $basic_machine in
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
moxiebox)
|
||||
basic_machine=moxie-unknown
|
||||
os=-moxiebox
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
@@ -755,10 +851,18 @@ case $basic_machine in
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
msys)
|
||||
basic_machine=i686-pc
|
||||
os=-msys
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
nacl)
|
||||
basic_machine=le32-unknown
|
||||
os=-nacl
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
@@ -823,6 +927,12 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
neo-tandem)
|
||||
basic_machine=neo-tandem
|
||||
;;
|
||||
nse-tandem)
|
||||
basic_machine=nse-tandem
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@@ -905,9 +1015,10 @@ case $basic_machine in
|
||||
;;
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
@@ -932,7 +1043,11 @@ case $basic_machine in
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
rdos | rdos64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rdos32)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
@@ -1001,6 +1116,9 @@ case $basic_machine in
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
strongarm-* | thumb-*)
|
||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
@@ -1057,20 +1175,8 @@ case $basic_machine in
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
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
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
@@ -1140,6 +1246,9 @@ case $basic_machine in
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
xscale-* | xscalee[bl]-*)
|
||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
@@ -1237,9 +1346,12 @@ esac
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
;;
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
@@ -1260,30 +1372,31 @@ case $os in
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -kopensolaris* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -openbsd* | -solidbsd* \
|
||||
| -bitrig* | -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* | -cegcc* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -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* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1322,7 +1435,7 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
@@ -1371,7 +1484,7 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
@@ -1407,15 +1520,14 @@ case $os in
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1438,10 +1550,10 @@ else
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
@@ -1453,8 +1565,23 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c8051-*)
|
||||
os=-elf
|
||||
;;
|
||||
hexagon-*)
|
||||
os=-elf
|
||||
;;
|
||||
tic54x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic55x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic6x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
@@ -1474,14 +1601,11 @@ case $basic_machine in
|
||||
;;
|
||||
m68000-sun)
|
||||
os=-sunos3
|
||||
# This also exists in the configure program, but was not the
|
||||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
@@ -1508,7 +1632,7 @@ case $basic_machine in
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
@@ -1613,7 +1737,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
|
||||
+5
-1
@@ -82,7 +82,7 @@ CFLAGS="$iverilog_temp_cflags"
|
||||
|
||||
AC_SUBST(DEPENDENCY_FLAG, [-MD])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CC, [""])
|
||||
AC_SUBST(WARNING_FLAGS_CC, ["-Wstrict-prototypes"])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, [""])
|
||||
fi
|
||||
|
||||
@@ -223,6 +223,10 @@ case "${host}" in
|
||||
CPPFLAGS="-mieee $CPPFLAGS"
|
||||
CFLAGS="-mieee $CFLAGS"
|
||||
;;
|
||||
*-*-mingw*)
|
||||
CXXFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CXXFLAGS"
|
||||
CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CFLAGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Do some more operating system specific setup. We put the file64_support
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
// These are correct and are used to find the base (zero) pin.
|
||||
thisSubtraction:netlist.h:4938
|
||||
thisSubtraction:netlist.h:4947
|
||||
thisSubtraction:netlist.h:4976
|
||||
thisSubtraction:netlist.h:4985
|
||||
|
||||
@@ -1375,6 +1375,7 @@ void NetScope::dump(ostream&o) const
|
||||
if (is_cell()) o << " (cell)";
|
||||
if (nested_module()) o << " (nested)";
|
||||
if (program_block()) o << " (program)";
|
||||
if (is_interface()) o << " (interface)";
|
||||
o << " " << children_.size() << " children, "
|
||||
<< classes_.size() << " classes" << endl;
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o res.o
|
||||
@@ -80,6 +81,7 @@ config.h: $(srcdir)/config.h.in Makefile
|
||||
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);g' \
|
||||
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
|
||||
-e 's;@IVLCXXFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@SHARED@;@shared@;' $< > $@
|
||||
|
||||
# Windows specific...
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define IVERILOG_VPI_CC "@IVLCC@"
|
||||
#define IVERILOG_VPI_CXX "@IVLCXX@"
|
||||
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
|
||||
#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@"
|
||||
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
|
||||
#define IVERILOG_SUFFIX "@SUFFIX@"
|
||||
|
||||
+169
-164
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Gus Baldauf ([email protected])
|
||||
* Copyright (c) 2015 Martin Whitaker
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -20,7 +21,7 @@
|
||||
/*
|
||||
* iverilog-vpi.c
|
||||
*
|
||||
* this program provides the functionality of iverilog-vpi.sh under Win32
|
||||
* this program provides the functionality of iverilog-vpi.sh under Windows
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static void setup_ivl_environment();
|
||||
static void setup_ivl_environment(void);
|
||||
static void assign(char **ptr, char *str);
|
||||
|
||||
/* The compile options: compiler, flags, etc. are in here */
|
||||
@@ -43,16 +44,17 @@ static void assign(char **ptr, char *str);
|
||||
static struct global_strings {
|
||||
char *pCCSRC; /* list of C source files (*.c) */
|
||||
char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pMINGW; /* path to MinGW directory */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCFLAGS; /* CFLAGS option */
|
||||
char *pLDLIBS; /* LDLIBS option */
|
||||
char *pNewPath; /* new PATH environment variable setting */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCCFLAGS; /* compiler flags for compiling C source files */
|
||||
char *pCXFLAGS; /* compiler flags for compiling C++ source files */
|
||||
char *pLDLIBS; /* linker flags for final linking stage */
|
||||
char *pCCNAME; /* base name of compiler */
|
||||
char *pLD; /* what to use for a linker */
|
||||
} gstr;
|
||||
|
||||
@@ -75,21 +77,21 @@ static void myExit(int exitVal)
|
||||
deInitDynString(gstr.pOUT);
|
||||
deInitDynString(gstr.pMINGW);
|
||||
deInitDynString(gstr.pIVL);
|
||||
deInitDynString(gstr.pCFLAGS);
|
||||
deInitDynString(gstr.pCCFLAGS);
|
||||
deInitDynString(gstr.pCXFLAGS);
|
||||
deInitDynString(gstr.pLDLIBS);
|
||||
deInitDynString(gstr.pNewPath);
|
||||
free(gstr.pLD);
|
||||
deInitDynString(gstr.pCCNAME);
|
||||
deInitDynString(gstr.pLD);
|
||||
|
||||
exit(exitVal);
|
||||
}
|
||||
|
||||
/* display usage summary and exit */
|
||||
|
||||
static void usage()
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
|
||||
fprintf(stderr, "usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n");
|
||||
fprintf(stderr, " or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ static void initDynString(char **str)
|
||||
*str = (char *) malloc(1);
|
||||
|
||||
if (!*str) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
|
||||
@@ -107,8 +109,10 @@ static void initDynString(char **str)
|
||||
|
||||
/* initialize dynamic memory buffers */
|
||||
|
||||
static void init()
|
||||
static void init(void)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
initDynString(&gstr.pCCSRC);
|
||||
initDynString(&gstr.pCXSRC);
|
||||
initDynString(&gstr.pOBJ);
|
||||
@@ -118,9 +122,17 @@ static void init()
|
||||
initDynString(&gstr.pOUT);
|
||||
initDynString(&gstr.pMINGW);
|
||||
initDynString(&gstr.pIVL);
|
||||
initDynString(&gstr.pCFLAGS);
|
||||
initDynString(&gstr.pCCFLAGS);
|
||||
initDynString(&gstr.pCXFLAGS);
|
||||
initDynString(&gstr.pLDLIBS);
|
||||
initDynString(&gstr.pNewPath);
|
||||
initDynString(&gstr.pCCNAME);
|
||||
initDynString(&gstr.pLD);
|
||||
|
||||
/* Get the base name of the C compiler. */
|
||||
assign(&gstr.pCCNAME, IVERILOG_VPI_CC);
|
||||
ptr = strchr(gstr.pCCNAME, ' ');
|
||||
if (ptr != NULL) *ptr = '\0';
|
||||
|
||||
/* By default use the C compiler to link the programs. */
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CC);
|
||||
}
|
||||
@@ -136,7 +148,7 @@ static int endsIn (char *end, char *str)
|
||||
|
||||
ext = str + (strlen(str) - strlen(end));
|
||||
|
||||
return stricmp(end,ext) ? 0 : 1;
|
||||
return stricmp(end, ext) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* return true if "str" begins with "prefix", case insensitive */
|
||||
@@ -146,35 +158,35 @@ static int startsWith (char *prefix, char *str)
|
||||
if (strlen(prefix) >= strlen(str))
|
||||
return 0;
|
||||
|
||||
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
|
||||
return strnicmp(prefix, str, strlen(prefix)) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "app" */
|
||||
|
||||
static void appendn (char **ptr, char *app, int count)
|
||||
static void appendn (char **ptr, char *app, size_t count)
|
||||
{
|
||||
char *nptr = (char *) realloc(*ptr, strlen(*ptr) +
|
||||
(count?count:strlen(app)) + 1);
|
||||
(count ? count : strlen(app)) + 1);
|
||||
|
||||
if (nptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
free(*ptr);
|
||||
myExit(4);
|
||||
}
|
||||
*ptr = nptr;
|
||||
|
||||
if (count)
|
||||
strncat(*ptr,app,count);
|
||||
strncat(*ptr, app, count);
|
||||
else
|
||||
strcat(*ptr,app);
|
||||
strcat(*ptr, app);
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
|
||||
static void append (char **ptr, char *app)
|
||||
{
|
||||
appendn(ptr,app,0);
|
||||
appendn(ptr, app, 0);
|
||||
}
|
||||
|
||||
/* if the string does not end with a backslash, add one */
|
||||
@@ -182,36 +194,36 @@ static void append (char **ptr, char *app)
|
||||
static void appendBackSlash(char **str)
|
||||
{
|
||||
if ((*str)[strlen(*str)-1] != '\\')
|
||||
append(str,"\\");
|
||||
append(str, "\\");
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "str" */
|
||||
|
||||
static void assignn (char **ptr, char *str, int count)
|
||||
static void assignn (char **ptr, char *str, size_t count)
|
||||
{
|
||||
char *nptr = (char *) realloc(*ptr, (count?count:strlen(str)) + 1);
|
||||
char *nptr = (char *) realloc(*ptr, (count ? count : strlen(str)) + 1);
|
||||
|
||||
if (nptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
free(*ptr);
|
||||
myExit(4);
|
||||
}
|
||||
*ptr = nptr;
|
||||
|
||||
if (count) {
|
||||
strncpy(*ptr,str,count);
|
||||
strncpy(*ptr, str, count);
|
||||
(*ptr)[count] = 0;
|
||||
}
|
||||
else
|
||||
strcpy(*ptr,str);
|
||||
strcpy(*ptr, str);
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
|
||||
static void assign (char **ptr, char *str)
|
||||
{
|
||||
assignn(ptr,str,0);
|
||||
assignn(ptr, str, 0);
|
||||
}
|
||||
|
||||
/* get a copy of a Icarus Verilog registry string key */
|
||||
@@ -223,11 +235,11 @@ static int GetRegistryKey(char *key, char **value)
|
||||
char *regKeyBuffer;
|
||||
DWORD regKeyType, regKeySize;
|
||||
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, KEY_QUERY_VALUE, &hkKey);
|
||||
if (lrv != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,NULL,®KeySize);
|
||||
lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType, NULL, ®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
return 0;
|
||||
@@ -236,7 +248,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
regKeyBuffer = (char *) malloc(regKeySize+1);
|
||||
if (!regKeyBuffer) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
|
||||
@@ -252,7 +264,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
assign(value,regKeyBuffer);
|
||||
assign(value, regKeyBuffer);
|
||||
free(regKeyBuffer);
|
||||
|
||||
return 1;
|
||||
@@ -262,27 +274,30 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
static void SetRegistryKey(char *key, char *value)
|
||||
{
|
||||
long lrv;
|
||||
HKEY hkKey;
|
||||
DWORD res;
|
||||
|
||||
if (RegCreateKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"Software\\Icarus Verilog",
|
||||
0,
|
||||
"",
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,NULL,
|
||||
&hkKey,
|
||||
&res) != ERROR_SUCCESS)
|
||||
return;
|
||||
lrv = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, "",
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, &res);
|
||||
if (lrv != ERROR_SUCCESS) {
|
||||
char message[1024];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lrv, LANG_USER_DEFAULT,
|
||||
message, sizeof(message), NULL);
|
||||
fprintf(stderr, "error: couldn't write to registry - %s\n", message);
|
||||
if (lrv == ERROR_ACCESS_DENIED) {
|
||||
fprintf(stderr, " try running as administrator\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* This needs an unsigned char *, but for MinGW the char is signed. */
|
||||
RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value,
|
||||
strlen(value)+1);
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
printf("info: storing %s in Windows' registry entry\n",value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
|
||||
printf("info: storing %s in Windows' registry entry\n", value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n", key);
|
||||
}
|
||||
|
||||
/* parse the command line, assign results to global variable strings */
|
||||
@@ -299,7 +314,6 @@ static int parse(int argc, char *argv[])
|
||||
char lib_option[] = "-l";
|
||||
char inc_option[] = "-I";
|
||||
char mingw_option[] = "-mingw=";
|
||||
char ivl_option[] = "-ivl=";
|
||||
char def_option[] = "-D";
|
||||
|
||||
if (argc == 1) return 0;
|
||||
@@ -339,7 +353,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for compiled object files */
|
||||
else if (endsIn(dot_o_ext, argv[idx])) {
|
||||
++srcFileCnt;
|
||||
append(&gstr.pOBJ," ");
|
||||
append(&gstr.pOBJ, " ");
|
||||
append(&gstr.pOBJ, argv[idx]);
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT, argv[idx],
|
||||
@@ -349,10 +363,6 @@ static int parse(int argc, char *argv[])
|
||||
else if (startsWith(mingw_option, argv[idx]))
|
||||
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
|
||||
strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
/* Check for the -ivl option */
|
||||
else if (startsWith(ivl_option, argv[idx]))
|
||||
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
|
||||
strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
/* Check for the --name option */
|
||||
else if (startsWith(name_option, argv[idx])) {
|
||||
assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1,
|
||||
@@ -376,7 +386,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --cflags option */
|
||||
else if (stricmp("--cflags", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\n", gstr.pCFLAGS);
|
||||
printf("%s\n", gstr.pCCFLAGS);
|
||||
myExit(0);
|
||||
}
|
||||
/* Check for the --ldflags option */
|
||||
@@ -393,7 +403,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --install-dir option */
|
||||
else if (stricmp("--install-dir", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
|
||||
printf("%s\\lib\\ivl" IVERILOG_SUFFIX "\\.\n", gstr.pIVL);
|
||||
myExit(0);
|
||||
}
|
||||
/* This is different than iverilog-vpi.sh, we don't
|
||||
@@ -402,15 +412,16 @@ static int parse(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* In case there is a --name without source/object files */
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT,"");
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT, "");
|
||||
|
||||
/* Normally it's an error if there are no source or object files */
|
||||
/* Unless we are setting the IVL or MinGW registry entries */
|
||||
if (!*gstr.pOUT) {
|
||||
if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
|
||||
} else
|
||||
if (*gstr.pOUT) {
|
||||
/* We have a valid result file so add the .vpi extension */
|
||||
append(&gstr.pOUT, ".vpi");
|
||||
} else {
|
||||
/* Unless we are setting the MinGW registry entry, it's
|
||||
an error if there are no source or object files */
|
||||
if (!*gstr.pMINGW) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -421,58 +432,27 @@ static void checkMingwDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path, *comp, *cp;
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\");
|
||||
/* Get just the compiler name (the first word) */
|
||||
comp = strdup(IVERILOG_VPI_CC);
|
||||
cp = strchr(comp, ' ');
|
||||
if (cp != NULL) *cp = '\0';
|
||||
append(&path, comp);
|
||||
append(&path,".exe");
|
||||
free(comp);
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
|
||||
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
/* do minimal check that the Icarus Verilog root directory looks valid */
|
||||
|
||||
static void checkIvlDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path;
|
||||
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
assign(&path, gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
|
||||
append(&path, "bin\\");
|
||||
append(&path, gstr.pCCNAME);
|
||||
append(&path, ".exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
|
||||
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
|
||||
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
fprintf(stderr, "error: %s\n", root);
|
||||
fprintf(stderr, " does not appear to be the valid root directory of\n");
|
||||
fprintf(stderr, " MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr, " point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr, " shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr, " For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr, " -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,68 +460,98 @@ static void checkIvlDir(char *root)
|
||||
|
||||
#define IVL_REGKEY_MINGW "MingwDir"
|
||||
|
||||
static void setup_mingw_environment()
|
||||
static void setup_mingw_environment(void)
|
||||
{
|
||||
char *pOldPATH = getenv("PATH"); /* get current path */
|
||||
char buffer[1]; /* doesn't matter how big this is, as we don't use the result */
|
||||
char *path;
|
||||
|
||||
if (*gstr.pMINGW) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
|
||||
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
|
||||
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr," a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
if (!*gstr.pOUT) SetRegistryKey(IVL_REGKEY_MINGW, gstr.pMINGW);
|
||||
|
||||
} else if (GetRegistryKey(IVL_REGKEY_MINGW, &gstr.pMINGW)) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
} else if (SearchPath(NULL, gstr.pCCNAME, ".exe", sizeof(buffer), buffer, NULL)) {
|
||||
return;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "error: cannot locate the MinGW C compiler - either add its location\n");
|
||||
fprintf(stderr, " to the PATH environment variable or use the -mingw option of\n");
|
||||
fprintf(stderr, " iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr, " a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr, " -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr, " something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
|
||||
/* Create new path with MinGW in it */
|
||||
assign(&gstr.pNewPath,"PATH=");
|
||||
append(&gstr.pNewPath,gstr.pMINGW);
|
||||
appendBackSlash(&gstr.pNewPath);
|
||||
append(&gstr.pNewPath, "\\");
|
||||
append(&gstr.pNewPath,"bin;");
|
||||
append(&gstr.pNewPath,pOldPATH);
|
||||
initDynString(&path);
|
||||
assign(&path, "PATH=");
|
||||
append(&path, gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path, "bin;");
|
||||
append(&path, getenv("PATH"));
|
||||
|
||||
/* Place new path in environment */
|
||||
_putenv(gstr.pNewPath);
|
||||
_putenv(path);
|
||||
deInitDynString(path);
|
||||
}
|
||||
|
||||
/* see if we can find iverilog root */
|
||||
/* find the iverilog root and initialise the compiler options */
|
||||
|
||||
#define IVL_REGKEY_IVL "InstallDir"
|
||||
|
||||
static void setup_ivl_environment()
|
||||
static void setup_ivl_environment(void)
|
||||
{
|
||||
if (*gstr.pIVL) {
|
||||
checkIvlDir(gstr.pIVL);
|
||||
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
|
||||
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
|
||||
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," For a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
|
||||
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
}
|
||||
char path[4096];
|
||||
char *ptr;
|
||||
|
||||
/* Build up the CFLAGS option string */
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I\"");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX);
|
||||
/* Extract the Icarus Verilog root directory from the path to the
|
||||
command. The command path will look something like this:
|
||||
|
||||
C:\iverilog\bin\iverilog-vpi.exe
|
||||
|
||||
The corresponding root directory is
|
||||
|
||||
C:\iverilog
|
||||
|
||||
so we chop off the file name and the last directory. */
|
||||
GetModuleFileName(NULL, path, sizeof(path));
|
||||
ptr = strrchr(path, '\\');
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "error: couldn't find start of program name in command path '%s'\n", path);
|
||||
myExit(6);
|
||||
}
|
||||
*ptr = 0;
|
||||
ptr = strrchr(path, '\\');
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "error: couldn't find start of bin directory in command path '%s'\n", path);
|
||||
myExit(6);
|
||||
}
|
||||
*ptr = 0;
|
||||
assign(&gstr.pIVL, path);
|
||||
|
||||
/* Build up the CCFLAGS option string */
|
||||
assign(&gstr.pCCFLAGS, IVERILOG_VPI_CFLAGS " -I\"");
|
||||
append(&gstr.pCCFLAGS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCCFLAGS);
|
||||
append(&gstr.pCCFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the CXFLAGS option string */
|
||||
assign(&gstr.pCXFLAGS, IVERILOG_VPI_CXXFLAGS " -I\"");
|
||||
append(&gstr.pCXFLAGS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCXFLAGS);
|
||||
append(&gstr.pCXFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the LDFLAGS option string */
|
||||
assign(&gstr.pLDLIBS,"-L\"");
|
||||
append(&gstr.pLDLIBS,gstr.pIVL);
|
||||
assign(&gstr.pLDLIBS, "-L\"");
|
||||
append(&gstr.pLDLIBS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pLDLIBS);
|
||||
append(&gstr.pLDLIBS,"\\lib\" " IVERILOG_VPI_LDLIBS);
|
||||
append(&gstr.pLDLIBS, "lib\" " IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
|
||||
/* compile source modules */
|
||||
|
||||
static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
|
||||
static void compile(char *pSource, char *pFlags, char **pObject, int *compile_errors, char *compiler)
|
||||
{
|
||||
char *ptr1 = pSource;
|
||||
char *ptr2 = strchr(ptr1, ' ');
|
||||
@@ -568,7 +578,7 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pDEFS);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pCFLAGS);
|
||||
append(&buf, pFlags);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pINCS);
|
||||
append(&buf, " ");
|
||||
@@ -593,27 +603,22 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
|
||||
/* using the global strings, compile and link */
|
||||
|
||||
static void compile_and_link()
|
||||
static void compile_and_link(void)
|
||||
{
|
||||
char *buf=0;
|
||||
int iRet, compile_errors = 0;
|
||||
|
||||
/* To make the output match iverilog-vpi.sh do not print out the
|
||||
* root directories */
|
||||
|
||||
// printf("MinGW root directory: %s.\n", gstr.pMINGW);
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
// printf("Icarus Verilog root directory: %s.\n", gstr.pIVL);
|
||||
checkIvlDir(gstr.pIVL);
|
||||
|
||||
/* compile the C source files (*.c) */
|
||||
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
compile(gstr.pCCSRC, gstr.pCCFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
/* compile the C++ source files (*.cc, *.cpp) */
|
||||
compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
compile(gstr.pCXSRC, gstr.pCXFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
|
||||
if (compile_errors) {
|
||||
fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
fprintf(stderr, "iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
compile_errors);
|
||||
myExit(2);
|
||||
}
|
||||
@@ -644,7 +649,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
init();
|
||||
|
||||
if (!parse(argc,argv)) usage();
|
||||
if (!parse(argc, argv)) usage();
|
||||
|
||||
setup_mingw_environment();
|
||||
setup_ivl_environment();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog 1 "May 10th, 2015" "" "Version %M.%m.%n %E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
@@ -213,6 +213,12 @@ a reference to a key temporary file that passes information to the
|
||||
compiler proper. To keep that file from being deleted at the end
|
||||
of the process, provide a file name of your own in the environment
|
||||
variable \fBIVERILOG_ICONFIG\fP.
|
||||
|
||||
If the selected target is \fIvvp\fP, the \fB\-v\fP switch is appended
|
||||
to the shebang line in the compiler output file, so directly executing
|
||||
the compiler output file will turn on verbose messages in \fIvvp\fP.
|
||||
This extra verbosity can be avoided by using the \fIvvp\fP command to
|
||||
indirectly execute the compiler output file.
|
||||
.TP 8
|
||||
.B -V
|
||||
Print the version of the compiler, and exit.
|
||||
@@ -514,14 +520,14 @@ Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
.BR "<http://iverilog.icarus.com/>"
|
||||
|
||||
Tips on using, debugging, and developing the compiler can be found at
|
||||
.BR "<http://iverilog.wikia.com/>"
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2014 Stephen Williams
|
||||
Copyright \(co 2002\-2015 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -568,6 +568,9 @@ static void process_warning_switch(const char*name)
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Ignoring unknown warning class "
|
||||
"%s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+90
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2015 Stephen Williams ([email protected])
|
||||
* Copyright CERN 2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -657,10 +657,13 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
lp->expr_type() == IVL_VT_STRING ||
|
||||
rp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_STRING) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< " operator may not have REAL operands." << endl;
|
||||
<< " operator may not have REAL or STRING operands."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -785,8 +788,11 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
right_ = tmp;
|
||||
}
|
||||
NetEConst*rc = dynamic_cast<NetEConst*> (rp);
|
||||
if (rc && (r_width < sizeof(long)*8))
|
||||
r_val = rc->value().as_long();
|
||||
// Adjust the expression width that can be converter depending
|
||||
// on if the R-value is signed or not.
|
||||
unsigned c_width = sizeof(long)*8;
|
||||
if (! right_->has_sign()) c_width -= 1;
|
||||
if (rc && (r_width <= c_width)) r_val = rc->value().as_long();
|
||||
|
||||
if (debug_elaborate && rc) {
|
||||
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
|
||||
@@ -1072,7 +1078,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
if (name=="$ivlh_to_unsigned") {
|
||||
ivl_assert(*this, parms_.size() == 2);
|
||||
// The Icarus Verilog specific $ivl_unsigned() system
|
||||
// The Icarus Verilog specific $ivlh_to_unsigned() system
|
||||
// task takes a second argument which is the output
|
||||
// size. This can be an arbitrary constant function.
|
||||
PExpr*pexpr = parms_[1];
|
||||
@@ -1094,6 +1100,11 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
||||
bool rc = eval_as_long(value, nexpr);
|
||||
ivl_assert(*this, rc && value>=0);
|
||||
|
||||
// The argument type/width is self-determined and doesn't
|
||||
// affect the result type/width.
|
||||
width_mode_t arg_mode = SIZED;
|
||||
parms_[0]->test_width(des, scope, arg_mode);
|
||||
|
||||
expr_width_ = value;
|
||||
signed_flag_= false;
|
||||
return expr_width_;
|
||||
@@ -1443,7 +1454,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
ivl_assert(*this, expr);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr->expr_width(), flags);
|
||||
return cast_to_width_(sub, expr_wid);
|
||||
}
|
||||
|
||||
@@ -2178,6 +2189,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const
|
||||
{
|
||||
const netdarray_t*darray = dynamic_cast<const netdarray_t*>(type);
|
||||
assert(darray);
|
||||
return elaborate_expr(des, scope, darray->element_type()->packed_width(), flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
@@ -2259,6 +2278,9 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
|
||||
func->set_line(*this);
|
||||
|
||||
if(res->darray_type())
|
||||
return func;
|
||||
|
||||
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
@@ -2522,11 +2544,44 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
||||
expr_width_ = t->packed_width();
|
||||
}
|
||||
|
||||
signed_flag_= t->get_signed();
|
||||
signed_flag_ = t->get_signed();
|
||||
min_width_ = expr_width_;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned) const
|
||||
{
|
||||
const netdarray_t*darray = NULL;
|
||||
const netvector_t*vector = NULL;
|
||||
|
||||
// Casting array of vectors to dynamic array type
|
||||
if((darray = dynamic_cast<const netdarray_t*>(type)) &&
|
||||
(vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
unsigned use_wid = base_->test_width(des, scope, mode);
|
||||
NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
|
||||
|
||||
assert(vector->packed_width() > 0);
|
||||
assert(base->expr_width() > 0);
|
||||
|
||||
// Find rounded up length that can fit the whole casted array of vectors
|
||||
int len = base->expr_width() + vector->packed_width() - 1;
|
||||
if(base->expr_width() > vector->packed_width()) {
|
||||
len /= vector->packed_width();
|
||||
} else {
|
||||
len /= base->expr_width();
|
||||
}
|
||||
|
||||
// Number of words in the created dynamic array
|
||||
NetEConst*len_expr = new NetEConst(verinum(len));
|
||||
return new NetENew(type, len_expr, base);
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return elaborate_expr(des, scope, (unsigned) 0, 0);
|
||||
}
|
||||
|
||||
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned, unsigned) const
|
||||
{
|
||||
@@ -2822,6 +2877,25 @@ NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
|
||||
list<long>&prefix_indices) const
|
||||
{
|
||||
unsigned dimensions = net->unpacked_dimensions() + net->packed_dimensions();
|
||||
switch (net->data_type()) {
|
||||
case IVL_VT_STRING:
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
dimensions += 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (path_.back().index.size() > dimensions) {
|
||||
cerr << get_fileline() << ": error: the number of indices ("
|
||||
<< path_.back().index.size()
|
||||
<< ") is greater than the number of dimensions ("
|
||||
<< dimensions
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
list<index_component_t> index;
|
||||
index = path_.back().index;
|
||||
ivl_assert(*this, index.size() >= net->unpacked_dimensions());
|
||||
@@ -4578,7 +4652,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long> prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
long msv, lsv;
|
||||
bool parts_defined_flag;
|
||||
@@ -4718,7 +4793,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
@@ -4820,7 +4896,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
@@ -4908,7 +4985,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
+23
-7
@@ -157,7 +157,7 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
|
||||
pform_name_t use_path = cur_path;
|
||||
perm_string tmp_name = peek_tail_name(use_path);
|
||||
name_component_t tail = use_path.back();
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet* reg = 0;
|
||||
@@ -171,18 +171,32 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
|
||||
tmp = new NetAssign_(tmp);
|
||||
tmp->set_property(tmp_name);
|
||||
tmp->set_property(tail.name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (reg->struct_type()) {
|
||||
if (reg->struct_type() && reg->struct_type()->packed()) {
|
||||
NetAssign_*tmp = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, scope, tmp, tail);
|
||||
return tmp;
|
||||
}
|
||||
#if 0
|
||||
if (reg->struct_type() && reg->struct_type()->packed()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with struct " << use_path << endl;
|
||||
<< "I don't know what to do with packed struct " << use_path
|
||||
<< " with member " << tail << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (reg->struct_type() && !reg->struct_type()->packed()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with unpacked struct " << use_path
|
||||
<< " with member " << tail << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->class_type()) {
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -316,7 +330,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
if (reg->struct_type() && !method_name.nil()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, method_name);
|
||||
name_component_t tmp_name (method_name);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, tmp_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -1117,8 +1132,9 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
||||
|
||||
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
NetAssign_*lv,
|
||||
const perm_string&member_name) const
|
||||
const name_component_t&member_comp) const
|
||||
{
|
||||
const perm_string&member_name = member_comp.name;
|
||||
NetNet*reg = lv->sig();
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
|
||||
+9
-22
@@ -201,16 +201,15 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
verinum one_value ((uint64_t)1, enum_width);
|
||||
one_value.has_sign(enum_type->signed_flag);
|
||||
// Find the maximum allowed enumeration value.
|
||||
verinum min_value (0);
|
||||
verinum max_value (0);
|
||||
if (enum_type->signed_flag) {
|
||||
min_value = -pow(verinum(2), verinum(enum_width-1));
|
||||
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
|
||||
} else {
|
||||
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
|
||||
}
|
||||
min_value.has_sign(true);
|
||||
max_value.has_sign(enum_type->signed_flag);
|
||||
// Variable to indicate when a defined value wraps.
|
||||
bool implicit_wrapped = false;
|
||||
// Process the enumeration definition.
|
||||
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
||||
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
|
||||
@@ -229,6 +228,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
cur_value = val_const->value();
|
||||
// Clear the implicit wrapped flag if a parameter is given.
|
||||
implicit_wrapped = false;
|
||||
|
||||
// A 2-state value can not have a constant with X/Z bits.
|
||||
if (enum_type->base_type==IVL_VT_BOOL &&
|
||||
@@ -335,24 +336,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cast any undefined bits to zero so the comparisons below
|
||||
// return just true (1) or false (0).
|
||||
verinum two_state_value = cur_value;
|
||||
two_state_value.cast_to_int2();
|
||||
|
||||
// The enumeration value must fit into the enumeration bits.
|
||||
if (!cur_value.is_defined()) {
|
||||
if (cur_value.len() > (unsigned long)use_enum->packed_width()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " value=" << cur_value
|
||||
<< " is too wide for enumeration base type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
} else if ((two_state_value > max_value) ||
|
||||
(cur_value.has_sign() && (two_state_value < min_value))) {
|
||||
|
||||
// Check to see if an implicitly wrapped value is used.
|
||||
if (implicit_wrapped) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " has an inferred value that overflowed." << endl;
|
||||
@@ -385,6 +370,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
// In case the next name has an implicit value,
|
||||
// increment the current value by one.
|
||||
if (cur_value.is_defined()) {
|
||||
if (cur_value == max_value) implicit_wrapped = true;
|
||||
cur_value = cur_value + one_value;
|
||||
}
|
||||
}
|
||||
@@ -1756,7 +1742,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
// scope searches will continue into the parent scope.
|
||||
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
|
||||
bound_type_? true : false,
|
||||
mod->program_block);
|
||||
mod->program_block,
|
||||
mod->is_interface);
|
||||
my_scope->set_line(get_file(), mod->get_file(),
|
||||
get_lineno(), mod->get_lineno());
|
||||
my_scope->set_module_name(mod->mod_name());
|
||||
|
||||
+19
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -909,6 +909,11 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
|
||||
*/
|
||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
// This sets the vector or array dimension size that will
|
||||
// cause a warning. For now, these warnings are permanently
|
||||
// enabled.
|
||||
const long warn_dimension_size = 1 << 30;
|
||||
|
||||
NetNet::Type wtype = type_;
|
||||
bool is_implicit_scalar = false;
|
||||
if (wtype == NetNet::IMPLICIT) {
|
||||
@@ -1042,7 +1047,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
packed_dimensions = nlist;
|
||||
wid = netrange_width(packed_dimensions);
|
||||
|
||||
if (wid > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Vector size "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned nattrib = 0;
|
||||
@@ -1063,6 +1072,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// put all the packed dimensions there.
|
||||
if (use_lidx==0 && use_ridx==0) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
@@ -1073,6 +1083,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// declaration, which is the dimensions [null:<nil>].
|
||||
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netqueue_t(vec);
|
||||
@@ -1114,6 +1125,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
index_l = lval.as_long();
|
||||
index_r = rval.as_long();
|
||||
}
|
||||
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Array dimension "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
|
||||
}
|
||||
@@ -1194,7 +1210,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, use_type);
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
|
||||
+46
-33
@@ -32,6 +32,44 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Some types have a list of ranges that need to be elaborated. This
|
||||
* function elaborates the ranges referenced by "dims" into the vector
|
||||
* "ranges".
|
||||
*/
|
||||
static void elaborate_array_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&ranges,
|
||||
const list<pform_range_t>*dims)
|
||||
{
|
||||
if (dims == 0)
|
||||
return;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = dims->begin()
|
||||
; cur != dims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ranges.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborations of types may vary depending on the scope that it is
|
||||
* done in, so keep a per-scope cache of the results.
|
||||
@@ -120,33 +158,7 @@ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
vector<netrange_t> packed;
|
||||
|
||||
if (pdims.get()) {
|
||||
for (list<pform_range_t>::const_iterator cur = pdims->begin()
|
||||
; cur != pdims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
packed.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
elaborate_array_ranges(des, scope, packed, pdims.get());
|
||||
|
||||
netvector_t*tmp = new netvector_t(packed, base_type);
|
||||
tmp->set_signed(signed_flag);
|
||||
@@ -171,13 +183,14 @@ ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_fileline() << " : sorry: "
|
||||
<< "Packed arrays are not currently supported in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
vector<netrange_t>packed;
|
||||
elaborate_array_ranges(des, scope, packed, dims.get());
|
||||
|
||||
ivl_type_t etype = base_type->elaborate_type(des, scope);
|
||||
|
||||
return new netparray_t(packed, etype);
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
|
||||
+34
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -2282,11 +2282,18 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
rval_->test_width(des, scope, mode);
|
||||
// Create a L-value that matches the function return type.
|
||||
NetNet*tmp;
|
||||
netvector_t*tmp_vec = new netvector_t(rval_->expr_type(),
|
||||
rval_->expr_width()-1, 0,
|
||||
rval_->has_sign());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::REG, tmp_vec);
|
||||
|
||||
if(rval_->expr_type() == IVL_VT_DARRAY) {
|
||||
netdarray_t*darray = new netdarray_t(tmp_vec);
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, darray);
|
||||
} else {
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, tmp_vec);
|
||||
}
|
||||
|
||||
tmp->set_file(rval_->get_file());
|
||||
tmp->set_lineno(rval_->get_lineno());
|
||||
NetAssign_*lv = new NetAssign_(tmp);
|
||||
@@ -4882,7 +4889,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
sig->data_type(), sig->vector_width(),
|
||||
expr1_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
if (debug_elaborate && initial_expr) {
|
||||
cerr << get_fileline() << ": debug: FOR initial assign: "
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
@@ -4893,34 +4900,29 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
reported so it's OK that the netlist is bogus. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
|
||||
|
||||
/* Now elaborate the for_step statement. I really should do
|
||||
some error checking here to make sure the step statement
|
||||
really does step the variable. */
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate for_step statement "
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
|
||||
NetProc*step = step_->elaborate(des, scope);
|
||||
|
||||
|
||||
/* Elaborate the condition expression. Try to evaluate it too,
|
||||
in case it is a constant. This is an interesting case
|
||||
worthy of a warning. */
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
if (ce == 0) {
|
||||
delete sub;
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dynamic_cast<NetEConst*>(ce)) {
|
||||
cerr << get_fileline() << ": warning: condition expression "
|
||||
"of for-loop is constant." << endl;
|
||||
}
|
||||
|
||||
|
||||
/* Error recovery - if we failed to elaborate any of the loop
|
||||
expressions, give up now. */
|
||||
if (initial_expr == 0 || ce == 0 || step == 0 || sub == 0) {
|
||||
delete initial_expr;
|
||||
delete ce;
|
||||
delete step;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
/* All done, build up the loop. */
|
||||
|
||||
NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step);
|
||||
@@ -5013,6 +5015,10 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
// If the expression is real, convert to an integer. 64 bits
|
||||
// should be more enough for any real use case.
|
||||
if (expr->expr_type() == IVL_VT_REAL)
|
||||
expr = cast_to_int4(expr, 64);
|
||||
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
if (stat == 0) return 0;
|
||||
@@ -5193,9 +5199,14 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetWhile*loop = new NetWhile(tmp, statement_->elaborate(des, scope));
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
NetWhile*loop = new NetWhile(ce, sub);
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
@@ -6086,7 +6097,8 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
// Make the root scope. This makes a NetScope object and
|
||||
// pushes it into the list of root scopes in the Design.
|
||||
NetScope*scope = des->make_root_scope(*root, rmod->program_block);
|
||||
NetScope*scope = des->make_root_scope(*root, rmod->program_block,
|
||||
rmod->is_interface);
|
||||
|
||||
// Collect some basic properties of this scope from the
|
||||
// Module definition.
|
||||
|
||||
+20
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2015 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
|
||||
@@ -1138,18 +1138,29 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
if (sub->vector_width() == expr_width())
|
||||
return sub;
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
|
||||
net_vec->set_signed(has_sign());
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, net_vec);
|
||||
net->set_line(*this);
|
||||
net->local_flag(true);
|
||||
if (has_sign()) {
|
||||
|
||||
// It may still happen that the expression is wider than the selection,
|
||||
// and there was no part select created earlier (size casting).
|
||||
if(expr_width() < sub->vector_width()) {
|
||||
NetPartSelect*sel = new NetPartSelect(sub, 0, expr_width(),
|
||||
NetPartSelect::VP, has_sign());
|
||||
sel->set_line(*this);
|
||||
des->add_node(sel);
|
||||
|
||||
connect(net->pin(0), sel->pin(0));
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
} else if (has_sign()) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope,
|
||||
scope->local_symbol(),
|
||||
expr_width());
|
||||
@@ -1166,7 +1177,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
cat->set_line(*this);
|
||||
des->add_node(cat);
|
||||
|
||||
assert(expr_width() > sub->vector_width());
|
||||
unsigned pad_width = expr_width() - sub->vector_width();
|
||||
verinum pad((uint64_t)0, pad_width);
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(),
|
||||
@@ -1278,6 +1288,8 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
net_->vector_width()-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, tmp_vec);
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width());
|
||||
NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val);
|
||||
tmp_const->set_line(*this);
|
||||
|
||||
+34
-47
@@ -1,10 +1,10 @@
|
||||
.TH iverilog-vpi 1 "April 17th, 2009" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%m.%n %E"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog-vpi
|
||||
[\-\-name=\fIname\fP]
|
||||
[options]
|
||||
\fIsourcefile\fP...
|
||||
|
||||
.SH DESCRIPTION
|
||||
@@ -15,9 +15,9 @@ list of C or C++ source files, and generates as output a linked VPI
|
||||
module. See the \fBvvp\fP(1) man page for a description of how the
|
||||
linked module is loaded by a simulation.
|
||||
|
||||
The output is named after the first source file. For example, if the
|
||||
first source file is named \fIfoo.c\fP, the output becomes
|
||||
\fIfoo.vpi\fP.
|
||||
By default the output is named after the first source file. For
|
||||
example, if the first source file is named \fIfoo.c\fP, the output
|
||||
becomes \fIfoo.vpi\fP.
|
||||
|
||||
.SH OPTIONS
|
||||
\fIiverilog\-vpi\fP accepts the following options:
|
||||
@@ -28,8 +28,8 @@ VPI modules to further reference external libraries.
|
||||
|
||||
.TP 8
|
||||
.B -I\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be search for
|
||||
header files.
|
||||
Add \fIdirectory\fP to the list of directories that will be searched
|
||||
for header files.
|
||||
|
||||
.TP 8
|
||||
.B -D\fIdefine\fP
|
||||
@@ -41,46 +41,38 @@ Normally, the output VPI module will be named after the first source
|
||||
file passed to the command. This flag sets the name (without the .vpi
|
||||
suffix) of the output vpi module.
|
||||
|
||||
.TP 8
|
||||
.B --install-dir
|
||||
This flag causes the program to print the install directory for VPI
|
||||
modules, then exit. It is a convenience for makefiles or automated
|
||||
plug-in installers.
|
||||
|
||||
.TP 8
|
||||
.B --cflags, --ldflags and --ldlibs
|
||||
These flags provide compile time information.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog\-vpi\fP includes two special flags needed to
|
||||
support the more intractable development environment. These flags help
|
||||
the program locate parts that it needs.
|
||||
When built as a native Windows program (using the MinGW toolchain),
|
||||
by default \fIiverilog\-vpi\fP will attempt to locate the MinGW tools
|
||||
needed to compile a VPI module on the system path (as set by the PATH
|
||||
environment variable). As an alternative, the user may specify the
|
||||
location of the MinGW tools via the following option.
|
||||
|
||||
.TP 8
|
||||
.B -mingw=\fIpath\fP
|
||||
Tell the program the root of the Mingw compiler tool suite. The
|
||||
Tell the program the root of the MinGW compiler tool suite. The
|
||||
\fBvvp\fP runtime is compiled with this compiler, and this is the
|
||||
compiler that \fIiverilog\-vpi\fP expects to use to compile your source
|
||||
code. This is normally not needed, and if you do use it, it is only
|
||||
needed once. The compiler will save the \fIpath\fP in the registry for
|
||||
use later.
|
||||
compiler that \fIiverilog\-vpi\fP expects to use to compile your
|
||||
source code. If this option accompanies a list of files, it will
|
||||
apply to the current build only. If this option is provided on its
|
||||
own, \fIiverilog\-vpi\fP will save the \fIpath\fP in the registry
|
||||
and use that path in preference to the system path for subsequent
|
||||
operations, avoiding the need to specify it on the command line
|
||||
every time.
|
||||
|
||||
.SH "INFORMATIONAL OPTIONS"
|
||||
|
||||
\fIiverilog\-vpi\fP includes additional flags to let Makefile gurus
|
||||
peek at the configuration of the \fIiverilog\fP installation. This way,
|
||||
Makefiles can be written that handle complex VPI builds natively, and
|
||||
without hard-coding values that depend on the system and installation.
|
||||
If used at all, these options must be used one at a time, and without
|
||||
any other options or directives.
|
||||
|
||||
.TP 8
|
||||
.B -ivl=\fIpath\fP
|
||||
Set for the use during compilation the root if the Icarus Verilog
|
||||
install. This is the place where you installed Icarus Verilog when you
|
||||
ran the installer. This flag is also only needed once, and the path is
|
||||
stored in the registry for future use.
|
||||
|
||||
.SH "UNIX-ONLY OPTIONS"
|
||||
|
||||
The UNIX version of \fIiverilog\-vpi\fP includes additional flags to
|
||||
let Makefile gurus peek at the configuration of the \fIiverilog\fP
|
||||
installation. This way, Makefiles can be written that handle complex VPI
|
||||
builds natively, and without hard-coding values that depend on the
|
||||
system and installation. If used at all, these options must be
|
||||
used one at a time, and without any other options or directives.
|
||||
.B --install-dir
|
||||
Print the install directory for VPI modules.
|
||||
|
||||
.TP 8
|
||||
.B --cflags
|
||||
@@ -95,11 +87,6 @@ Print the linker flags (LDFLAGS) needed to link a VPI module.
|
||||
.B --ldlibs
|
||||
Print the libraries (LDLIBS) needed to link a VPI module.
|
||||
|
||||
.TP 8
|
||||
.B -m32
|
||||
On 64bit systems that support it (and support vvp32) this flag
|
||||
requests a 32bit vpi binary instead of the default 64bit binary.
|
||||
|
||||
.P
|
||||
Example GNU makefile that takes advantage of these flags:
|
||||
.IP "" 4
|
||||
@@ -123,12 +110,12 @@ Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>",
|
||||
.BR "<http://www.mingw.org>",
|
||||
.BR "<http://iverilog.icarus.com/>",
|
||||
.BR "<http://mingw-w64.yaxm.org/>",
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2009 Stephen Williams
|
||||
Copyright \(co 2002\-2015 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+140
-305
@@ -136,21 +136,11 @@ static void ifdef_leave(void)
|
||||
* we assume that the non-file part is from this file. */
|
||||
if (istack->path != NULL && cur->path != NULL &&
|
||||
strcmp(istack->path,cur->path) != 0) {
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: warning: This `endif matches an ifdef in another file.\n",
|
||||
istack->path,
|
||||
istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: warning: This `endif matches an ifdef "
|
||||
"in another file.\n", istack->path, istack->lineno+1);
|
||||
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: This is the odd matched `ifdef.\n",
|
||||
cur->path,
|
||||
cur->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: This is the odd matched `ifdef.\n",
|
||||
cur->path, cur->lineno+1);
|
||||
}
|
||||
|
||||
free(cur->path);
|
||||
@@ -243,12 +233,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
<PCOMENT>`{keywords} {
|
||||
emit_pathline(istack);
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
|
||||
yytext
|
||||
);
|
||||
fprintf(stderr, "error: macro names cannot be directive keywords "
|
||||
"('%s'); replaced with nothing.\n", yytext);
|
||||
}
|
||||
|
||||
<PCOMENT>`[a-zA-Z][a-zA-Z0-9_$]* {
|
||||
@@ -285,12 +271,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
<PPINCLUDE>`{keywords} {
|
||||
emit_pathline(istack);
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
|
||||
yytext
|
||||
);
|
||||
fprintf(stderr, "error: macro names cannot be directive keywords "
|
||||
"('%s'); replaced with nothing.\n", yytext);
|
||||
}
|
||||
|
||||
<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* {
|
||||
@@ -342,11 +324,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
emit_pathline(istack);
|
||||
error_count += 1;
|
||||
BEGIN(ERROR_LINE);
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"error: malformed `define directive: macro names cannot be directive keywords\n"
|
||||
);
|
||||
fprintf(stderr, "error: malformed `define directive: macro names "
|
||||
"cannot be directive keywords\n");
|
||||
}
|
||||
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
|
||||
@@ -483,73 +462,45 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
|
||||
`ifdef {
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: `ifdef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
}
|
||||
|
||||
`ifndef {
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: `ifndef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
}
|
||||
|
||||
`elsif {
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: `elsif without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
}
|
||||
|
||||
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: `elsif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
}
|
||||
|
||||
`else {
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: `else without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
}
|
||||
|
||||
`endif {
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: `endif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
}
|
||||
|
||||
`{keywords} {
|
||||
emit_pathline(istack);
|
||||
error_count += 1;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
|
||||
yytext
|
||||
);
|
||||
fprintf(stderr, "error: macro names cannot be directive keywords "
|
||||
"('%s'); replaced with nothing.\n", yytext);
|
||||
}
|
||||
|
||||
/* This pattern notices macros and arranges for them to be replaced. */
|
||||
@@ -722,17 +673,14 @@ static struct define_t* magic_table = &def_LINE;
|
||||
*/
|
||||
static struct define_t* def_lookup_internal(const char*name, struct define_t*cur)
|
||||
{
|
||||
if (cur == 0)
|
||||
return 0;
|
||||
if (cur == 0) return 0;
|
||||
|
||||
assert(cur->up == 0);
|
||||
|
||||
while (cur)
|
||||
{
|
||||
while (cur) {
|
||||
int cmp = strcmp(name, cur->name);
|
||||
|
||||
if (cmp == 0)
|
||||
return cur;
|
||||
if (cmp == 0) return cur;
|
||||
|
||||
cur = (cmp < 0) ? cur->left : cur->right;
|
||||
}
|
||||
@@ -743,11 +691,9 @@ static struct define_t* def_lookup_internal(const char*name, struct define_t*cur
|
||||
static struct define_t* def_lookup(const char*name)
|
||||
{
|
||||
// first, try a magic macro
|
||||
if(name[0] == '_' && name[1] == '_' && name[2] != '\0')
|
||||
{
|
||||
if(name[0] == '_' && name[1] == '_' && name[2] != '\0') {
|
||||
struct define_t* result = def_lookup_internal(name, magic_table);
|
||||
if(result)
|
||||
{
|
||||
if(result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -806,8 +752,7 @@ static /* inline */ char* def_argv(int arg)
|
||||
|
||||
static void check_for_max_args(void)
|
||||
{
|
||||
if (def_argc == MAX_DEF_ARG)
|
||||
{
|
||||
if (def_argc == MAX_DEF_ARG) {
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: too many macro arguments - aborting\n");
|
||||
exit(1);
|
||||
@@ -839,14 +784,12 @@ static void def_add_arg(void)
|
||||
check_for_max_args();
|
||||
|
||||
/* Remove trailing white space and, if necessary, opening brace. */
|
||||
while (isspace((int)yytext[length - 1]))
|
||||
length--;
|
||||
while (isspace((int)yytext[length - 1])) length--;
|
||||
|
||||
/* This can happen because we are also processing "argv[0]", the
|
||||
macro name, as a pseudo-argument. The lexor will match that
|
||||
as name(, so chop off the ( here. */
|
||||
if (yytext[length - 1] == '(')
|
||||
length--;
|
||||
if (yytext[length - 1] == '(') length--;
|
||||
|
||||
yytext[length] = 0;
|
||||
|
||||
@@ -921,41 +864,32 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||
}
|
||||
}
|
||||
|
||||
if (def_table == 0)
|
||||
if (def_table == 0) {
|
||||
def_table = def;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
struct define_t* cur = def_table;
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
int cmp = strcmp(def->name, cur->name);
|
||||
|
||||
if (cmp == 0)
|
||||
{
|
||||
if (cmp == 0) {
|
||||
free(cur->value);
|
||||
cur->value = def->value;
|
||||
free(def->name);
|
||||
free(def);
|
||||
break;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{
|
||||
if (cur->left != 0)
|
||||
} else if (cmp < 0) {
|
||||
if (cur->left != 0) {
|
||||
cur = cur->left;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cur->left = def;
|
||||
def->up = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur->right != 0)
|
||||
} else {
|
||||
if (cur->right != 0) {
|
||||
cur = cur->right;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cur->right = def;
|
||||
def->up = cur;
|
||||
break;
|
||||
@@ -973,8 +907,7 @@ static void free_macro(struct define_t* def)
|
||||
free_macro(def->right);
|
||||
free(def->name);
|
||||
free(def->value);
|
||||
for (idx = 0 ; idx < def->argc ; idx += 1)
|
||||
free(def->defaults[idx]);
|
||||
for (idx = 0 ; idx < def->argc ; idx += 1) free(def->defaults[idx]);
|
||||
free(def->defaults);
|
||||
free(def);
|
||||
}
|
||||
@@ -1069,25 +1002,19 @@ static void do_define(void)
|
||||
*/
|
||||
cp = strchr(yytext, '/');
|
||||
|
||||
while (cp && *cp)
|
||||
{
|
||||
while (cp && *cp) {
|
||||
if (cp[1] == '/') {
|
||||
*cp = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cp[1] == '*')
|
||||
{
|
||||
if (cp[1] == '*') {
|
||||
tail = strstr(cp+2, "*/");
|
||||
|
||||
if (tail == 0)
|
||||
{
|
||||
if (tail == 0) {
|
||||
*cp = 0;
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: Unterminated comment in define\n",
|
||||
istack->path, istack->lineno+1
|
||||
fprintf(stderr, "%s:%u: Unterminated comment in define\n",
|
||||
istack->path, istack->lineno+1
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -1101,10 +1028,8 @@ static void do_define(void)
|
||||
|
||||
/* Trim trailing white space. */
|
||||
cp = yytext + strlen(yytext);
|
||||
while (cp > yytext)
|
||||
{
|
||||
if (!isspace((int)cp[-1]))
|
||||
break;
|
||||
while (cp > yytext) {
|
||||
if (!isspace((int)cp[-1])) break;
|
||||
|
||||
cp -= 1;
|
||||
*cp = 0;
|
||||
@@ -1114,8 +1039,7 @@ static void do_define(void)
|
||||
* and the white space that precedes it, then replace all that
|
||||
* with a single newline.
|
||||
*/
|
||||
if ((cp > yytext) && (cp[-1] == '\\'))
|
||||
{
|
||||
if ((cp > yytext) && (cp[-1] == '\\')) {
|
||||
cp -= 1;
|
||||
cp[0] = 0;
|
||||
|
||||
@@ -1143,18 +1067,13 @@ static void do_define(void)
|
||||
/* If the text for a macro with arguments contains occurrences
|
||||
* of ARG_MARK, issue an error message and suppress the macro.
|
||||
*/
|
||||
if ((def_argc > 1) && strchr(head, ARG_MARK))
|
||||
{
|
||||
if ((def_argc > 1) && strchr(head, ARG_MARK)) {
|
||||
emit_pathline(istack);
|
||||
error_count += 1;
|
||||
def_argc = 0;
|
||||
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"error: implementation restriction - macro text may not contain a %s character\n",
|
||||
_STR2(ARG_MARK)
|
||||
);
|
||||
fprintf(stderr, "error: implementation restriction - "
|
||||
"macro text may not contain a %s character\n", _STR2(ARG_MARK));
|
||||
}
|
||||
|
||||
/* Look for formal argument names in the definition, and replace
|
||||
@@ -1162,18 +1081,15 @@ static void do_define(void)
|
||||
* the formal argument index number.
|
||||
*/
|
||||
added_cnt = 0;
|
||||
for (arg = 1; arg < def_argc; arg++)
|
||||
{
|
||||
for (arg = 1; arg < def_argc; arg++) {
|
||||
int argl = def_argl[arg];
|
||||
|
||||
cp = find_arg(head, head, def_argv(arg));
|
||||
|
||||
while (cp && *cp)
|
||||
{
|
||||
while (cp && *cp) {
|
||||
added_cnt += 2 - argl;
|
||||
|
||||
if (added_cnt > 0)
|
||||
{
|
||||
if (added_cnt > 0) {
|
||||
char* base = define_text;
|
||||
|
||||
define_cnt += added_cnt;
|
||||
@@ -1216,13 +1132,11 @@ static void def_finish(void)
|
||||
{
|
||||
define_continue_flag = 0;
|
||||
|
||||
if (def_argc <= 0)
|
||||
return;
|
||||
if (def_argc <= 0) return;
|
||||
|
||||
if (!define_text)
|
||||
if (!define_text) {
|
||||
define_macro(def_argv(0), "", 0, def_argc);
|
||||
else
|
||||
{
|
||||
} else {
|
||||
define_macro(def_argv(0), define_text, 0, def_argc);
|
||||
|
||||
free(define_text);
|
||||
@@ -1251,24 +1165,18 @@ static void def_undefine(void)
|
||||
if (cur == 0) return;
|
||||
if (cur->magic) return;
|
||||
|
||||
if (cur->up == 0)
|
||||
{
|
||||
if ((cur->left == 0) && (cur->right == 0))
|
||||
if (cur->up == 0) {
|
||||
if ((cur->left == 0) && (cur->right == 0)) {
|
||||
def_table = 0;
|
||||
else if (cur->left == 0)
|
||||
{
|
||||
} else if (cur->left == 0) {
|
||||
def_table = cur->right;
|
||||
if (cur->right)
|
||||
cur->right->up = 0;
|
||||
}
|
||||
else if (cur->right == 0)
|
||||
{
|
||||
} else if (cur->right == 0) {
|
||||
assert(cur->left);
|
||||
def_table = cur->left;
|
||||
def_table->up = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
tail = cur->left;
|
||||
while (tail->right)
|
||||
tail = tail->right;
|
||||
@@ -1279,50 +1187,40 @@ static void def_undefine(void)
|
||||
def_table = cur->left;
|
||||
def_table->up = 0;
|
||||
}
|
||||
}
|
||||
else if (cur->left == 0)
|
||||
{
|
||||
if (cur->up->left == cur)
|
||||
} else if (cur->left == 0) {
|
||||
if (cur->up->left == cur) {
|
||||
cur->up->left = cur->right;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assert(cur->up->right == cur);
|
||||
cur->up->right = cur->right;
|
||||
}
|
||||
|
||||
if (cur->right)
|
||||
cur->right->up = cur->up;
|
||||
if (cur->right) cur->right->up = cur->up;
|
||||
}
|
||||
else if (cur->right == 0)
|
||||
{
|
||||
else if (cur->right == 0) {
|
||||
assert(cur->left);
|
||||
|
||||
if (cur->up->left == cur)
|
||||
if (cur->up->left == cur) {
|
||||
cur->up->left = cur->left;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assert(cur->up->right == cur);
|
||||
cur->up->right = cur->left;
|
||||
}
|
||||
|
||||
cur->left->up = cur->up;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
tail = cur->left;
|
||||
|
||||
assert(cur->left && cur->right);
|
||||
|
||||
while (tail->right)
|
||||
tail = tail->right;
|
||||
while (tail->right) tail = tail->right;
|
||||
|
||||
tail->right = cur->right;
|
||||
tail->right->up = tail;
|
||||
|
||||
if (cur->up->left == cur)
|
||||
if (cur->up->left == cur) {
|
||||
cur->up->left = cur->left;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assert(cur->up->right == cur);
|
||||
cur->up->right = cur->left;
|
||||
}
|
||||
@@ -1332,8 +1230,7 @@ static void def_undefine(void)
|
||||
|
||||
free(cur->name);
|
||||
free(cur->value);
|
||||
for (idx = 0 ; idx < cur->argc ; idx += 1)
|
||||
free(cur->defaults[idx]);
|
||||
for (idx = 0 ; idx < cur->argc ; idx += 1) free(cur->defaults[idx]);
|
||||
free(cur->defaults);
|
||||
free(cur);
|
||||
}
|
||||
@@ -1350,10 +1247,9 @@ static int macro_needs_args(const char*text)
|
||||
{
|
||||
cur_macro = def_lookup(text);
|
||||
|
||||
if (cur_macro)
|
||||
if (cur_macro) {
|
||||
return (cur_macro->argc > 1);
|
||||
else
|
||||
{
|
||||
} else {
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "warning: macro %s undefined (and assumed null) at this point.\n", text);
|
||||
return 0;
|
||||
@@ -1386,8 +1282,7 @@ static void macro_add_to_arg(int is_white_space)
|
||||
check_for_max_args();
|
||||
|
||||
/* Replace any run of white space with a single space */
|
||||
if (is_white_space)
|
||||
{
|
||||
if (is_white_space) {
|
||||
yytext[0] = ' ';
|
||||
yytext[1] = 0;
|
||||
length = 1;
|
||||
@@ -1435,8 +1330,7 @@ static int exp_buf_free = 0;
|
||||
|
||||
static void exp_buf_grow_to_fit(int length)
|
||||
{
|
||||
while (length >= exp_buf_free)
|
||||
{
|
||||
while (length >= exp_buf_free) {
|
||||
exp_buf_size += EXP_BUF_CHUNK;
|
||||
exp_buf_free += EXP_BUF_CHUNK;
|
||||
exp_buf = realloc(exp_buf, exp_buf_size);
|
||||
@@ -1451,8 +1345,7 @@ static void expand_using_args(void)
|
||||
int arg;
|
||||
int length;
|
||||
|
||||
if (def_argc != cur_macro->argc)
|
||||
{
|
||||
if (def_argc != cur_macro->argc) {
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: wrong number of arguments for `%s\n", cur_macro->name);
|
||||
return;
|
||||
@@ -1461,12 +1354,10 @@ static void expand_using_args(void)
|
||||
head = cur_macro->value;
|
||||
tail = head;
|
||||
|
||||
while (*tail)
|
||||
{
|
||||
if (*tail != ARG_MARK)
|
||||
while (*tail) {
|
||||
if (*tail != ARG_MARK) {
|
||||
tail++;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
arg = tail[1]; assert(arg < def_argc);
|
||||
|
||||
char*use_argv;
|
||||
@@ -1508,17 +1399,14 @@ static void expand_using_args(void)
|
||||
*/
|
||||
static void do_expand(int use_args)
|
||||
{
|
||||
if (cur_macro)
|
||||
{
|
||||
if (cur_macro) {
|
||||
struct include_stack_t*isp;
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
const char *cp;
|
||||
unsigned escapes = 0;
|
||||
char *str_buf = 0;
|
||||
|
||||
if (cur_macro->keyword)
|
||||
{
|
||||
if (cur_macro->keyword) {
|
||||
fprintf(yyout, "%s", cur_macro->value);
|
||||
if (do_expand_stringify_flag) {
|
||||
do_expand_stringify_flag = 0;
|
||||
@@ -1527,33 +1415,27 @@ static void do_expand(int use_args)
|
||||
return;
|
||||
}
|
||||
|
||||
if (use_args)
|
||||
{
|
||||
if (use_args) {
|
||||
int tail = 0;
|
||||
head = exp_buf_size - exp_buf_free;
|
||||
expand_using_args();
|
||||
tail = exp_buf_size - exp_buf_free;
|
||||
exp_buf_free += tail - head;
|
||||
|
||||
if (tail == head)
|
||||
return;
|
||||
if (tail == head) return;
|
||||
}
|
||||
|
||||
isp = (struct include_stack_t*) calloc(1, sizeof(struct include_stack_t));
|
||||
|
||||
isp->stringify_flag = do_expand_stringify_flag;
|
||||
do_expand_stringify_flag = 0;
|
||||
if (use_args)
|
||||
{
|
||||
if (use_args) {
|
||||
isp->str = &exp_buf[head];
|
||||
}
|
||||
else if(cur_macro->magic)
|
||||
{
|
||||
} else if(cur_macro->magic) {
|
||||
// cast const char * to char * to suppress warning, since we won't
|
||||
// be modifying isp->str in place.
|
||||
isp->str = (char*)do_magic(cur_macro->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
isp->str = cur_macro->value;
|
||||
}
|
||||
|
||||
@@ -1588,8 +1470,7 @@ static void do_expand(int use_args)
|
||||
exp_buf_free -= idx;
|
||||
|
||||
isp->str = str_buf;
|
||||
} else
|
||||
isp->str = strdup(isp->str);
|
||||
} else isp->str = strdup(isp->str);
|
||||
|
||||
isp->orig_str = isp->str;
|
||||
isp->next = istack;
|
||||
@@ -1612,21 +1493,16 @@ static const char* do_magic(const char*name)
|
||||
{
|
||||
size_t desired_cnt = 0;
|
||||
|
||||
if(!magic_text)
|
||||
{
|
||||
magic_text = malloc(24); // unimportant initial size
|
||||
}
|
||||
if(!magic_text) magic_text = malloc(24); // unimportant initial size
|
||||
|
||||
if(!strcmp(name, "__LINE__"))
|
||||
{
|
||||
if(!strcmp(name, "__LINE__")) {
|
||||
// istack->lineno is unsigned. the largest it could be is 64 bits.
|
||||
// 2^64 is between 10^19 and 10^20. So the decimal representation of
|
||||
// lineno can't possibly be longer than 23 bytes. I'm generous but
|
||||
// bytes are cheap and this is nobody's critical path.
|
||||
desired_cnt = 24;
|
||||
|
||||
if(magic_cnt < desired_cnt)
|
||||
{
|
||||
if(magic_cnt < desired_cnt) {
|
||||
magic_text = realloc(magic_text, desired_cnt);
|
||||
assert(magic_text);
|
||||
magic_cnt = desired_cnt;
|
||||
@@ -1637,17 +1513,12 @@ static const char* do_magic(const char*name)
|
||||
assert(actual_len >= 0);
|
||||
assert((unsigned) actual_len < desired_cnt);
|
||||
return magic_text;
|
||||
}
|
||||
else if(!strcmp(name, "__FILE__"))
|
||||
{
|
||||
} else if(!strcmp(name, "__FILE__")) {
|
||||
const char *path = get_path(istack);
|
||||
if(path)
|
||||
{
|
||||
|
||||
if(path) {
|
||||
desired_cnt = strlen(path)+2+1; // two quotes and a null
|
||||
|
||||
if(magic_cnt < desired_cnt)
|
||||
{
|
||||
if(magic_cnt < desired_cnt) {
|
||||
magic_text = realloc(magic_text, desired_cnt);
|
||||
assert(magic_text);
|
||||
magic_cnt = desired_cnt;
|
||||
@@ -1689,19 +1560,17 @@ static const char* do_magic(const char*name)
|
||||
|
||||
static void output_init(void)
|
||||
{
|
||||
if (line_direct_flag)
|
||||
if (line_direct_flag) {
|
||||
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
|
||||
}
|
||||
}
|
||||
|
||||
static void include_filename(void)
|
||||
{
|
||||
if(standby) {
|
||||
emit_pathline(istack);
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"error: malformed `include directive. Extra junk on line?\n"
|
||||
);
|
||||
fprintf(stderr,
|
||||
"error: malformed `include directive. Extra junk on line?\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1728,8 +1597,7 @@ static void do_include(void)
|
||||
|
||||
/* Add the current path to the start of the include_dir list. */
|
||||
isp = istack;
|
||||
while(isp && (isp->path == NULL))
|
||||
isp = isp->next;
|
||||
while(isp && (isp->path == NULL)) isp = isp->next;
|
||||
|
||||
assert(isp);
|
||||
|
||||
@@ -1775,8 +1643,9 @@ code_that_switches_buffers:
|
||||
}
|
||||
}
|
||||
|
||||
if (line_direct_flag)
|
||||
if (line_direct_flag) {
|
||||
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
|
||||
}
|
||||
|
||||
standby->next = istack;
|
||||
standby->stringify_flag = 0;
|
||||
@@ -1796,8 +1665,7 @@ code_that_switches_buffers:
|
||||
*/
|
||||
static unsigned get_line(struct include_stack_t* isp)
|
||||
{
|
||||
while(isp && (isp->path == NULL))
|
||||
isp = isp->next;
|
||||
while(isp && (isp->path == NULL)) isp = isp->next;
|
||||
|
||||
assert(isp);
|
||||
|
||||
@@ -1811,8 +1679,7 @@ static unsigned get_line(struct include_stack_t* isp)
|
||||
*/
|
||||
static const char* get_path(struct include_stack_t* isp)
|
||||
{
|
||||
while(isp && (isp->path == NULL))
|
||||
isp = isp->next;
|
||||
while(isp && (isp->path == NULL)) isp = isp->next;
|
||||
|
||||
assert(isp);
|
||||
|
||||
@@ -1827,8 +1694,7 @@ static const char* get_path(struct include_stack_t* isp)
|
||||
*/
|
||||
static void emit_pathline(struct include_stack_t* isp)
|
||||
{
|
||||
while(isp && (isp->path == NULL))
|
||||
isp = isp->next;
|
||||
while(isp && (isp->path == NULL)) isp = isp->next;
|
||||
|
||||
assert(isp);
|
||||
|
||||
@@ -1837,17 +1703,12 @@ static void emit_pathline(struct include_stack_t* isp)
|
||||
|
||||
static void lexor_done(void)
|
||||
{
|
||||
while (ifdef_stack)
|
||||
{
|
||||
while (ifdef_stack) {
|
||||
struct ifdef_stack_t*cur = ifdef_stack;
|
||||
ifdef_stack = cur->next;
|
||||
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
"%s:%u: error: This `ifdef lacks an `endif.\n",
|
||||
cur->path, cur->lineno+1
|
||||
);
|
||||
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
|
||||
cur->path, cur->lineno+1);
|
||||
|
||||
free(cur->path);
|
||||
free(cur);
|
||||
@@ -1904,8 +1765,7 @@ static void open_input_file(struct include_stack_t*isp)
|
||||
char*cmd = malloc(cmdlen);
|
||||
snprintf(cmd, cmdlen, "%s -w\"%s\"%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
|
||||
|
||||
if (verbose_flag)
|
||||
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
|
||||
if (verbose_flag) fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
|
||||
|
||||
isp->file = popen(cmd, "r");
|
||||
isp->file_close = pclose;
|
||||
@@ -1943,29 +1803,23 @@ static int load_next_input(void)
|
||||
isp->comment = NULL;
|
||||
}
|
||||
|
||||
if (isp->file)
|
||||
{
|
||||
if (isp->file) {
|
||||
free(isp->path);
|
||||
assert(isp->file_close);
|
||||
isp->file_close(isp->file);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* If I am printing line directives and I just finished
|
||||
* macro substitution, I should terminate the line and
|
||||
* arrange for a new directive to be printed.
|
||||
*/
|
||||
if (line_direct_flag && istack && istack->path && isp->lineno)
|
||||
if (line_direct_flag && istack && istack->path && isp->lineno) {
|
||||
fprintf(yyout, "\n");
|
||||
else
|
||||
line_mask_flag = 1;
|
||||
} else line_mask_flag = 1;
|
||||
|
||||
free(isp->orig_str);
|
||||
}
|
||||
|
||||
if (isp->stringify_flag) {
|
||||
fputc('"', yyout);
|
||||
}
|
||||
if (isp->stringify_flag) fputc('"', yyout);
|
||||
|
||||
free(isp);
|
||||
|
||||
@@ -1974,10 +1828,8 @@ static int load_next_input(void)
|
||||
* queue. If none are there, give up. Otherwise, open the file
|
||||
* and continue parsing.
|
||||
*/
|
||||
if (istack == 0)
|
||||
{
|
||||
if (file_queue == 0)
|
||||
{
|
||||
if (istack == 0) {
|
||||
if (file_queue == 0) {
|
||||
lexor_done();
|
||||
return 0;
|
||||
}
|
||||
@@ -1989,15 +1841,15 @@ static int load_next_input(void)
|
||||
istack->lineno = 0;
|
||||
open_input_file(istack);
|
||||
|
||||
if (istack->file == 0)
|
||||
{
|
||||
if (istack->file == 0) {
|
||||
perror(istack->path);
|
||||
error_count += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (line_direct_flag)
|
||||
if (line_direct_flag) {
|
||||
fprintf(yyout, "\n`line 1 \"%s\" 0\n", istack->path);
|
||||
}
|
||||
|
||||
if (depend_file) {
|
||||
if (dep_mode == 'p') {
|
||||
@@ -2022,8 +1874,9 @@ static int load_next_input(void)
|
||||
*/
|
||||
yy_switch_to_buffer(istack->yybs);
|
||||
|
||||
if (line_direct_flag && istack->path && !line_mask_flag)
|
||||
if (line_direct_flag && istack->path && !line_mask_flag) {
|
||||
fprintf(yyout, "\n`line %u \"%s\" 2\n", istack->lineno+1, istack->path);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2045,23 +1898,16 @@ static int load_next_input(void)
|
||||
static void do_dump_precompiled_defines(FILE* out, struct define_t* table)
|
||||
{
|
||||
if (!table->keyword)
|
||||
#ifdef __MINGW32__ /* MinGW does not know about z. */
|
||||
fprintf(out, "%s:%d:%d:%s\n", table->name, table->argc, strlen(table->value), table->value);
|
||||
#else
|
||||
fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value);
|
||||
#endif
|
||||
|
||||
if (table->left)
|
||||
do_dump_precompiled_defines(out, table->left);
|
||||
if (table->left) do_dump_precompiled_defines(out, table->left);
|
||||
|
||||
if (table->right)
|
||||
do_dump_precompiled_defines(out, table->right);
|
||||
if (table->right) do_dump_precompiled_defines(out, table->right);
|
||||
}
|
||||
|
||||
void dump_precompiled_defines(FILE* out)
|
||||
{
|
||||
if (def_table)
|
||||
do_dump_precompiled_defines(out, def_table);
|
||||
if (def_table) do_dump_precompiled_defines(out, def_table);
|
||||
}
|
||||
|
||||
void load_precompiled_defines(FILE* src)
|
||||
@@ -2070,8 +1916,7 @@ void load_precompiled_defines(FILE* src)
|
||||
size_t buf_len = 4096;
|
||||
int ch;
|
||||
|
||||
while ((ch = fgetc(src)) != EOF)
|
||||
{
|
||||
while ((ch = fgetc(src)) != EOF) {
|
||||
char* cp = buf;
|
||||
char* name = 0;
|
||||
|
||||
@@ -2086,26 +1931,21 @@ void load_precompiled_defines(FILE* src)
|
||||
assert( (size_t)(cp-buf) < buf_len );
|
||||
}
|
||||
|
||||
if (ch != ':')
|
||||
return;
|
||||
if (ch != ':') return;
|
||||
|
||||
/* Terminate the name string. */
|
||||
*cp++ = 0;
|
||||
assert( (size_t)(cp-buf) < buf_len );
|
||||
|
||||
/* Read the argc number. (this doesn't need buffer space) */
|
||||
while (isdigit(ch = fgetc(src)))
|
||||
argc = 10*argc + ch-'0';
|
||||
while (isdigit(ch = fgetc(src))) argc = 10*argc + ch-'0';
|
||||
|
||||
if (ch != ':')
|
||||
return;
|
||||
if (ch != ':') return;
|
||||
|
||||
/* Read the value len (this doesn't need buffer space) */
|
||||
while (isdigit(ch = fgetc(src)))
|
||||
len = 10*len + ch-'0';
|
||||
while (isdigit(ch = fgetc(src))) len = 10*len + ch-'0';
|
||||
|
||||
if (ch != ':')
|
||||
return;
|
||||
if (ch != ':') return;
|
||||
|
||||
/* Save the name, and start the buffer over. */
|
||||
name = strdup(buf);
|
||||
@@ -2119,8 +1959,7 @@ void load_precompiled_defines(FILE* src)
|
||||
|
||||
cp = buf;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
while (len > 0) {
|
||||
ch = fgetc(src);
|
||||
if (ch == EOF) {
|
||||
free(name);
|
||||
@@ -2165,8 +2004,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
isp->stringify_flag = 0;
|
||||
isp->comment = NULL;
|
||||
|
||||
if (isp->file == 0)
|
||||
{
|
||||
if (isp->file == 0) {
|
||||
perror(paths[0]);
|
||||
exit(1);
|
||||
}
|
||||
@@ -2189,8 +2027,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
/* Now build up a queue of all the remaining file names, so
|
||||
* that load_next_input() can pull them when needed.
|
||||
*/
|
||||
for (idx = 1 ; paths[idx] ; idx += 1)
|
||||
{
|
||||
for (idx = 1 ; paths[idx] ; idx += 1) {
|
||||
isp = malloc(sizeof(struct include_stack_t));
|
||||
isp->path = strdup(paths[idx]);
|
||||
isp->file = 0;
|
||||
@@ -2200,10 +2037,8 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
isp->stringify_flag = 0;
|
||||
isp->comment = NULL;
|
||||
|
||||
if (tail)
|
||||
tail->next = isp;
|
||||
else
|
||||
file_queue = isp;
|
||||
if (tail) tail->next = isp;
|
||||
else file_queue = isp;
|
||||
|
||||
tail = isp;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ double acc_fetch_paramval(handle object)
|
||||
fprintf(pli_trace, "acc_fetch_paramval(%s) --> \"%s\"\n",
|
||||
vpi_get_str(vpiName, object), val.value.str);
|
||||
}
|
||||
return (double) (long)val.value.str;
|
||||
return (double) (intptr_t)val.value.str;
|
||||
|
||||
default:
|
||||
vpi_printf("XXXX: parameter %s has type %d\n",
|
||||
|
||||
+20
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -45,6 +45,14 @@ bool Nexus::drivers_constant() const
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we are connected to a tran, there may be a driver
|
||||
on the other side of the tran. We could try checking
|
||||
for this, but for now, be pessimistic. */
|
||||
if (dynamic_cast<const NetTran*>(cur->get_obj())) {
|
||||
driven_ = VAR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Link::DIR cur_dir = cur->get_dir();
|
||||
if (cur_dir == Link::INPUT)
|
||||
continue;
|
||||
@@ -267,11 +275,17 @@ vector<bool> Nexus::driven_mask(void) const
|
||||
}
|
||||
|
||||
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
|
||||
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
|
||||
continue;
|
||||
if (obj_ps && cur->get_pin()!=1)
|
||||
continue;
|
||||
if (obj_ps) {
|
||||
if(obj_ps) {
|
||||
if (obj_ps->dir()==NetPartSelect::VP) {
|
||||
if(cur->get_pin() != 0)
|
||||
continue;
|
||||
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||
mask[idx] = true;
|
||||
return mask;
|
||||
} else {
|
||||
if (cur->get_pin() != 1)
|
||||
continue;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
|
||||
size_t bit = idx + obj_ps->base();
|
||||
ivl_assert(*obj, bit < mask.size());
|
||||
|
||||
@@ -859,6 +859,7 @@ int main(int argc, char*argv[])
|
||||
# if defined(HAVE_TIMES)
|
||||
times_flag = true;
|
||||
# endif
|
||||
flags["VVP_EXTRA_ARGS"] = strdup(" -v");
|
||||
break;
|
||||
case 'V':
|
||||
version_flag = true;
|
||||
|
||||
@@ -1,282 +1,4 @@
|
||||
Please NOTE:
|
||||
Please see the Icarus Verilog Wiki for instruction on building and installing
|
||||
Icarus Verilog as a native Windows application using the MinGW tools:
|
||||
|
||||
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
|
||||
|
||||
Copyright 2006 Stephen Williams <[email protected]>
|
||||
|
||||
|
||||
Icarus Verilog source can be compiled with the mingw C/C++ compilers
|
||||
to get a Windows binary that does not require the POSIX compatibility
|
||||
cruft of the Cygwin.dll library. The resulting program can be run with
|
||||
or without Cygwin, so this is the preferred Windows distribution form.
|
||||
The configure scripts automatically detect that the compilers in use
|
||||
are the mingw compilers and will configure the Makefiles appropriately.
|
||||
|
||||
The mingw patch doesn't contain tools beyond the compiler, but there
|
||||
is the "msys" package that the makers of Mingw publish that has enough
|
||||
extra tools to get most everything else working. There are a few extra
|
||||
packages needed beyond mingw and msys, and the following instructions
|
||||
explain how to get them and install them.
|
||||
|
||||
* Some Preliminary Comments -- PLEASE READ ME --
|
||||
|
||||
The Windows port of Icarus Verilog is the most difficult of all the
|
||||
ports. The Windows system off the shelf is completely stripped, devoid
|
||||
of any support for software development. Everything needed to compile
|
||||
Icarus Verilog must be collected from various sources and stitched
|
||||
together by hand. Normal human beings with a basic understanding of
|
||||
software development can do this, but some patience (and access to the
|
||||
Internet) is required. You may choose to print these instructions. FOR
|
||||
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
|
||||
|
||||
NOTE that if you have Cygwin installed, it is best to not use a cygwin
|
||||
window to do the build, as the Cygwin tools will intermix with the
|
||||
mingw tools such that it is hard to be sure you are using the right
|
||||
compiler. Thus, it is recommended that these steps be *not* done in a
|
||||
Cygwin window. Use an MSYS window instead, and be careful that your
|
||||
msys/mingw tools are not masked by paths that point to Cygwin binaries.
|
||||
|
||||
I have no plans to intentionally support MSVC++ compilation. Don't ask.
|
||||
|
||||
* Summary of Prerequisites
|
||||
|
||||
This is a brief list of prerequisite packages, along with the URL
|
||||
where each can be found. In most cases, the specific version is not
|
||||
critical, but these are the versions I use.
|
||||
|
||||
msys-1.0 <http://www.mingw/org>
|
||||
msysDTK-1.0 <http://www.mingw.org>
|
||||
Mingw32-5.x <http://www.mingw.org>
|
||||
... including the sub-packages binutils, gcc-core and gcc-g++
|
||||
if you are given the option.
|
||||
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>
|
||||
bison-2.1 <http://gnuwin32.sourceforge.net>
|
||||
flex-2.5.4a <http://gnuwin32.sourceforge.net>
|
||||
|
||||
The above table lists the packages required. It is convenient to
|
||||
install them in the above order. Many of these packages are also
|
||||
collected into the directory:
|
||||
|
||||
<ftp://icarus.com/pub/eda/verilog/win32-build-parts>
|
||||
|
||||
Incidentally, besides Mingw32, none of these packages are needed after
|
||||
installation of Icarus Verilog is complete. These are only needed to
|
||||
build the compiler. The Mingw32 package can be used to compile VPI
|
||||
modules if you choose.
|
||||
|
||||
* Install MSYS and msysDTK
|
||||
|
||||
The msys package is available from the mingw download site. This is
|
||||
not the compiler but a collection of *nix tools ported to Windows and
|
||||
wrapped in a convenient installer. The msys package is all the various
|
||||
basic tools (shells, file utils, etc) and the msysDTK is extra
|
||||
developer tools other than the compiler.
|
||||
|
||||
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
|
||||
mingw sub-menu of your Start menu. This icon brings up a shell window
|
||||
(a command line) that has paths all set up for executing msys and
|
||||
mingw commands. This is what you will want to use while executing
|
||||
commands below.
|
||||
|
||||
* Install Mingw32
|
||||
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
|
||||
is a convenient remote installer. Download this program and run
|
||||
it. The installer will ask which components you want to install. You
|
||||
need only the base C compiler and the C++ compiler. (You may install
|
||||
other languages if you wish.)
|
||||
|
||||
When I install Mingw32 (using the installer) I typically set a
|
||||
destination directory of d:\mingw or the like. You will be using
|
||||
that path later.
|
||||
|
||||
NOTES:
|
||||
If you intend to compile VPI modules for Icarus Verilog, you
|
||||
need Mingw32, even if you are using a precompiled binary. VPI
|
||||
modules only require Mingw32, and none of the other libraries.
|
||||
|
||||
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 GnuWin32 Packages
|
||||
|
||||
The GnuWin32 project is a collections of open source programs and
|
||||
libraries ported to Windows. These also work well with the Mingw
|
||||
compiler, and in fact Icarus Verilog uses a few pieces from this
|
||||
collection.
|
||||
|
||||
You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||
|
||||
<http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3.exe
|
||||
zlib-1.2.3.exe
|
||||
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
|
||||
has a "setup" link for each of these packages. Click the setup to
|
||||
download the installer for each of the desired programs, then execute
|
||||
the downloaded .exe files to invoke the installer. Install into the
|
||||
c:\gunwin32 directory.
|
||||
|
||||
NOTES:
|
||||
You need the binaries and the developer files, but you do not
|
||||
need the source to these packages. The installer gives you the
|
||||
choice.
|
||||
|
||||
After you are done installing the gnuwin32 tools, you should add the
|
||||
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
|
||||
your Windows path. The msys shell will pick up your Windows path.
|
||||
|
||||
* Unpack Icarus Verilog source
|
||||
|
||||
Unpack the compressed tar file (.tar.gz) of the source with a command
|
||||
like this:
|
||||
|
||||
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
|
||||
|
||||
This will create a directory "verilog-xxxxxxxx" that contains all the
|
||||
source for Icarus Verilog. Descend into that directory, as that is
|
||||
where we will work from now on.
|
||||
|
||||
$ cd verilog-xxxxxxxx
|
||||
|
||||
NOTES:
|
||||
The exact name of the file will vary according to the
|
||||
snapshot. The 20030303 name is only an example.
|
||||
|
||||
Unpack the source into a directory that has no spaces. The
|
||||
makefiles included in the source get confused by white space in
|
||||
directory names.
|
||||
|
||||
* Preconfigure Icarus Verilog (Not normally needed)
|
||||
|
||||
Under certain cases, you may need to "preconfigure" the Icarus Verilog
|
||||
source tree. You should only need to do this if you are getting the
|
||||
Icarus Verilog source tree from git, or you are using an existing
|
||||
source tree that you've patched to cause configure.in files to change.
|
||||
|
||||
NOTE: If you are building from a fresh, bundled source tree that
|
||||
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
|
||||
the "Configure Icarus Verilog" step below.
|
||||
|
||||
First, remove any autom4te.cache directories that may exist in your
|
||||
source tree. These can make a mess of autoconf runs. Then, generate
|
||||
configure scripts with this command:
|
||||
|
||||
$ sh autoconf.sh
|
||||
|
||||
This script will run the "autoconf" command (part of the msysDTK) to
|
||||
generate all the necessary "configure" scripts. This will take a few
|
||||
minutes. This should go smoothly.
|
||||
|
||||
* Configure Icarus Verilog
|
||||
|
||||
Now we are all set to configure and compile Icarus Verilog. Choose a
|
||||
destination path where you will want to install the binaries. I chose
|
||||
on my system the directory "D:\iverilog". This choice is not
|
||||
permanent, so don't get too much angst over it. Just choose a name
|
||||
without white space.
|
||||
|
||||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run these commands:
|
||||
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=c:/iverilog
|
||||
|
||||
NOTES:
|
||||
The CPPFLAGS and LDFLAGS variables tell configure where
|
||||
the gnuwin32 packages are. The configure program will
|
||||
write these values into the Makefiles, so you only need to
|
||||
keep these variables long enough for the configure program
|
||||
to work.
|
||||
|
||||
Your PATH variable was set in the previous step.
|
||||
|
||||
Use forward slashes as directory characters. All the various
|
||||
tools prefer the forward slash.
|
||||
|
||||
Substitute your chosen directory for the prefix. This will cause the
|
||||
makefiles to build and the source code to configure. The configure
|
||||
program will detect that this is a mingw environment and set things up
|
||||
to build properly.
|
||||
|
||||
(For a prefix, use the drive letter notation; the mingw compiled parts
|
||||
require it, and the Cygwin tools should be able to handle it. You may
|
||||
need to check or upgrade your Cygwin installation if this causes
|
||||
problems for you.)
|
||||
|
||||
|
||||
* Compile Icarus Verilog
|
||||
|
||||
This, believe it or not, should be the easy part:
|
||||
|
||||
$ make
|
||||
|
||||
It could take a while. Now is a good time to go get some coffee or
|
||||
take a tea break.
|
||||
|
||||
|
||||
* Install Icarus Verilog
|
||||
|
||||
If the compile ran OK, then next you install Icarus Verilog in the
|
||||
directory you have chosen. When you are ready, install like this:
|
||||
|
||||
$ make install
|
||||
|
||||
This is part of what the configure program did for you. The Makefiles
|
||||
now know to put the files under the D:\iverilog directory (or whatever
|
||||
directory you chose) and away you go.
|
||||
|
||||
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:\gnuwin32\bin\readline.dll
|
||||
c:\gnuwin32\bin\history.dll
|
||||
c:\gnuwin32\bin\bzip2.dll
|
||||
c:\gnuwin32\bin\zlib.dll
|
||||
|
||||
If you already have these in your Windows path (i.e. your system32
|
||||
directory) then you do not need to copy them into the iverilog
|
||||
directory. However, prepackaged Icarus Verilog binaries include these
|
||||
files.
|
||||
|
||||
* Running Icarus Verilog
|
||||
|
||||
Finally, put the C:\iverilog\bin directory in your Windows path, and
|
||||
you should be able to run the iverilog and vvp commands to your
|
||||
heart's content.
|
||||
|
||||
Currently, the iverilog.exe uses the path to itself to locate the
|
||||
libraries and modules associated with itself. In other words, if you
|
||||
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the C:\iverilog directory and subdirectories below
|
||||
that. This means you can move the Icarus Verilog installation by
|
||||
simply moving the root directory and all its contents.
|
||||
|
||||
The vvp.pdf and iverilog.pdf files document the main commands. View
|
||||
these with Acrobat reader, or any other viewer capable of displaying
|
||||
PDF format files.
|
||||
http://iverilog.wikia.com/wiki/Installation_Guide#Compiling_on_MS_Windows_.28MinGW.29
|
||||
|
||||
+3
-2
@@ -101,11 +101,12 @@ uint64_t Design::scale_to_precision(uint64_t val,
|
||||
return val;
|
||||
}
|
||||
|
||||
NetScope* Design::make_root_scope(perm_string root, bool program_block)
|
||||
NetScope* Design::make_root_scope(perm_string root, bool program_block,
|
||||
bool is_interface)
|
||||
{
|
||||
NetScope *root_scope_;
|
||||
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
|
||||
false, program_block);
|
||||
false, program_block, is_interface);
|
||||
/* This relies on the fact that the basename return value is
|
||||
permallocated. */
|
||||
root_scope_->set_module_name(root_scope_->basename());
|
||||
|
||||
+6
-2
@@ -110,8 +110,10 @@ void Definitions::add_class(netclass_t*net_class)
|
||||
* in question.
|
||||
*/
|
||||
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bool prog)
|
||||
: type_(t), name_(n), nested_module_(nest), program_block_(prog), up_(up)
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
|
||||
bool program, bool interface)
|
||||
: type_(t), name_(n), nested_module_(nest), program_block_(program),
|
||||
is_interface_(interface), up_(up)
|
||||
{
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
@@ -372,6 +374,8 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
|
||||
// To get here the parameter must already exist, so we should
|
||||
// never get here.
|
||||
assert(0);
|
||||
// But return something to avoid a compiler warning.
|
||||
return idx;
|
||||
}
|
||||
|
||||
NetScope::TYPE NetScope::type() const
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_netdarray_H
|
||||
#define IVL_netdarray_H
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2015 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
|
||||
@@ -33,6 +33,9 @@ class netdarray_t : public netarray_t {
|
||||
// IVL_VT_DARRAY for dynamic arrays?
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
||||
// A dynamic array may have a type that is signed.
|
||||
inline bool get_signed() const { return element_type()->get_signed(); }
|
||||
|
||||
// This is the base_type() of the element of the array. We
|
||||
// need this in some cases in order to get the base type of
|
||||
// the element, and not the IVL_VT_DARRAY of the array itself.
|
||||
|
||||
@@ -918,7 +918,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
/* Create a new scope, and attach it to the given parent. The
|
||||
name is expected to have been permallocated. */
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, bool prog=false);
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false,
|
||||
bool program=false, bool interface=false);
|
||||
~NetScope();
|
||||
|
||||
/* Rename the scope using the name generated by inserting as
|
||||
@@ -1008,8 +1009,9 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
// Nested modules have slightly different scope search rules.
|
||||
inline bool nested_module() const { return nested_module_; }
|
||||
// Program blocks have elaboration constraints.
|
||||
// Program blocks and interfaces have elaboration constraints.
|
||||
inline bool program_block() const { return program_block_; }
|
||||
inline bool is_interface() const { return is_interface_; }
|
||||
TYPE type() const;
|
||||
void print_type(ostream&) const;
|
||||
|
||||
@@ -1221,6 +1223,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
bool nested_module_;
|
||||
// True if the scope is a program block
|
||||
bool program_block_;
|
||||
// True if the scope is an interface
|
||||
bool is_interface_;
|
||||
|
||||
perm_string file_;
|
||||
perm_string def_file_;
|
||||
@@ -4747,7 +4751,8 @@ class Design : public Definitions {
|
||||
|
||||
const char* get_flag(const string&key) const;
|
||||
|
||||
NetScope* make_root_scope(perm_string name, bool program_block);
|
||||
NetScope* make_root_scope(perm_string name, bool program_block,
|
||||
bool is_interface);
|
||||
NetScope* find_root_scope();
|
||||
std::list<NetScope*> find_root_scopes() const;
|
||||
|
||||
|
||||
@@ -34,6 +34,12 @@ netparray_t::~netparray_t()
|
||||
* The packed width of a packed array is the packed width of the
|
||||
* element times the dimension width of the array itself.
|
||||
*/
|
||||
|
||||
bool netparray_t::packed(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long netparray_t::packed_width(void) const
|
||||
{
|
||||
long cur_width = element_type()->packed_width();
|
||||
|
||||
@@ -64,6 +64,7 @@ class netparray_t : public netsarray_t {
|
||||
|
||||
public:
|
||||
// Virtual methods from the ivl_type_s type...
|
||||
bool packed(void) const;
|
||||
long packed_width(void) const;
|
||||
std::vector<netrange_t> slice_dimensions() const;
|
||||
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL__netqueue_H
|
||||
#define IVL__netqueue_H
|
||||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014-2015 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
|
||||
@@ -38,6 +38,9 @@ class netqueue_t : public netdarray_t {
|
||||
// IVL_VT_QUEUE for queues.
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
||||
// A queue may have a type that is signed.
|
||||
inline bool get_signed() const { return element_type()->get_signed(); }
|
||||
|
||||
std::ostream& debug_dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ class netrange_t {
|
||||
inline netrange_t() : msb_(LONG_MAX), lsb_(LONG_MAX) { }
|
||||
// Create a properly defined netrange
|
||||
inline netrange_t(long m, long l) : msb_(m), lsb_(l) { }
|
||||
// Copy constructure.
|
||||
// Copy constructor.
|
||||
inline netrange_t(const netrange_t&that)
|
||||
: msb_(that.msb_), lsb_(that.lsb_) { }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
|
||||
* Copyright CERN 2012-2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -49,6 +49,16 @@ static struct {
|
||||
data_type_t* data_type;
|
||||
} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT, 0};
|
||||
|
||||
/* Modport port declaration lists use this structure for context. */
|
||||
enum modport_port_type_t { MP_NONE, MP_SIMPLE, MP_TF, MP_CLOCKING };
|
||||
static struct {
|
||||
modport_port_type_t type;
|
||||
union {
|
||||
NetNet::PortType direction;
|
||||
bool is_import;
|
||||
};
|
||||
} last_modport_port = { MP_NONE, {NetNet::NOT_A_PORT}};
|
||||
|
||||
/* The task and function rules need to briefly hold the pointer to the
|
||||
task/function that is currently in progress. */
|
||||
static PTask* current_task = 0;
|
||||
@@ -549,6 +559,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||
%type <flag> from_exclude block_item_decls_opt
|
||||
%type <number> number pos_neg_number
|
||||
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||
%type <flag> import_export
|
||||
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
||||
%type <flag> udp_reg_opt edge_operator
|
||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
@@ -562,8 +573,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||
%type <statement> udp_initial udp_init_opt
|
||||
%type <expr> udp_initial_expr_opt
|
||||
|
||||
%type <text> register_variable net_variable endlabel_opt class_declaration_endlabel_opt
|
||||
%type <perm_strings> register_variable_list net_variable_list
|
||||
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
|
||||
%type <perm_strings> register_variable_list net_variable_list event_variable_list
|
||||
%type <perm_strings> list_of_identifiers loop_variables
|
||||
%type <port_list> list_of_port_identifiers
|
||||
|
||||
@@ -583,7 +594,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||
%type <tf_ports> task_item task_item_list task_item_list_opt
|
||||
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
|
||||
|
||||
%type <named_pexpr> port_name parameter_value_byname
|
||||
%type <named_pexpr> modport_simple_port port_name parameter_value_byname
|
||||
%type <named_pexprs> port_name_list parameter_value_byname_list
|
||||
|
||||
%type <named_pexpr> attribute
|
||||
@@ -739,7 +750,7 @@ class_identifier
|
||||
perm_string name = lex_strings.make($1);
|
||||
class_type_t*tmp = new class_type_t(name);
|
||||
FILE_NAME(tmp, @1);
|
||||
pform_set_typedef(name, tmp);
|
||||
pform_set_typedef(name, tmp, NULL);
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
@@ -1117,8 +1128,8 @@ data_type_or_implicit_or_void
|
||||
statements may go. This may be a bad idea, but it is legacy now. */
|
||||
|
||||
/* NOTE 2: The "module" rule of the description combines the
|
||||
module_declaration and program_declaration rules from the
|
||||
standard description. */
|
||||
module_declaration, program_declaration, and interface_declaration
|
||||
rules from the standard description. */
|
||||
|
||||
description /* IEEE1800-2005: A.1.2 */
|
||||
: module
|
||||
@@ -1142,7 +1153,7 @@ description_list
|
||||
;
|
||||
|
||||
|
||||
/* This implements the [ : INDENTIFIER ] part of the constructure
|
||||
/* This implements the [ : IDENTIFIER ] part of the constructor
|
||||
rule documented in IEEE1800-2005: A.1.8 */
|
||||
endnew_opt : ':' K_new | ;
|
||||
|
||||
@@ -1270,6 +1281,11 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||
|
||||
;
|
||||
|
||||
import_export /* IEEE1800-2012: A.2.9 */
|
||||
: K_import { $$ = true; }
|
||||
| K_export { $$ = false; }
|
||||
;
|
||||
|
||||
implicit_class_handle /* IEEE1800-2005: A.8.4 */
|
||||
: K_this { $$ = pform_create_this(); }
|
||||
| K_super { $$ = pform_create_super(); }
|
||||
@@ -1546,6 +1562,115 @@ method_qualifier_opt
|
||||
|
|
||||
;
|
||||
|
||||
modport_declaration /* IEEE1800-2012: A.2.9 */
|
||||
: K_modport
|
||||
{ if (!pform_in_interface())
|
||||
yyerror(@1, "error: modport declarations are only allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
modport_item_list ';'
|
||||
|
||||
modport_item_list
|
||||
: modport_item
|
||||
| modport_item_list ',' modport_item
|
||||
;
|
||||
|
||||
modport_item
|
||||
: IDENTIFIER
|
||||
{ pform_start_modport_item(@1, $1); }
|
||||
'(' modport_ports_list ')'
|
||||
{ pform_end_modport_item(@1); }
|
||||
;
|
||||
|
||||
/* The modport_ports_list is a LALR(2) grammar. When the parser sees a
|
||||
',' it needs to look ahead to the next token to decide whether it is
|
||||
a continuation of the preceding modport_ports_declaration, or the
|
||||
start of a new modport_ports_declaration. bison only supports LALR(1),
|
||||
so we have to handcraft a mini parser for this part of the syntax.
|
||||
last_modport_port holds the state for this mini parser.*/
|
||||
|
||||
modport_ports_list
|
||||
: modport_ports_declaration
|
||||
| modport_ports_list ',' modport_ports_declaration
|
||||
| modport_ports_list ',' modport_simple_port
|
||||
{ if (last_modport_port.type == MP_SIMPLE) {
|
||||
pform_add_modport_port(@3, last_modport_port.direction,
|
||||
$3->name, $3->parm);
|
||||
} else {
|
||||
yyerror(@3, "error: modport expression not allowed here.");
|
||||
}
|
||||
delete $3;
|
||||
}
|
||||
| modport_ports_list ',' modport_tf_port
|
||||
{ if (last_modport_port.type != MP_TF)
|
||||
yyerror(@3, "error: task/function declaration not allowed here.");
|
||||
}
|
||||
| modport_ports_list ',' IDENTIFIER
|
||||
{ if (last_modport_port.type == MP_SIMPLE) {
|
||||
pform_add_modport_port(@3, last_modport_port.direction,
|
||||
lex_strings.make($3), 0);
|
||||
} else if (last_modport_port.type != MP_TF) {
|
||||
yyerror(@3, "error: list of identifiers not allowed here.");
|
||||
}
|
||||
delete[] $3;
|
||||
}
|
||||
| modport_ports_list ','
|
||||
{ yyerror(@2, "error: NULL port declarations are not allowed"); }
|
||||
;
|
||||
|
||||
modport_ports_declaration
|
||||
: attribute_list_opt port_direction IDENTIFIER
|
||||
{ last_modport_port.type = MP_SIMPLE;
|
||||
last_modport_port.direction = $2;
|
||||
pform_add_modport_port(@3, $2, lex_strings.make($3), 0);
|
||||
delete[] $3;
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt port_direction modport_simple_port
|
||||
{ last_modport_port.type = MP_SIMPLE;
|
||||
last_modport_port.direction = $2;
|
||||
pform_add_modport_port(@3, $2, $3->name, $3->parm);
|
||||
delete $3;
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt import_export IDENTIFIER
|
||||
{ last_modport_port.type = MP_TF;
|
||||
last_modport_port.is_import = $2;
|
||||
yyerror(@3, "sorry: modport task/function ports are not yet supported.");
|
||||
delete[] $3;
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt import_export modport_tf_port
|
||||
{ last_modport_port.type = MP_TF;
|
||||
last_modport_port.is_import = $2;
|
||||
yyerror(@3, "sorry: modport task/function ports are not yet supported.");
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt K_clocking IDENTIFIER
|
||||
{ last_modport_port.type = MP_CLOCKING;
|
||||
last_modport_port.direction = NetNet::NOT_A_PORT;
|
||||
yyerror(@3, "sorry: modport clocking declaration is not yet supported.");
|
||||
delete[] $3;
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
|
||||
modport_simple_port
|
||||
: '.' IDENTIFIER '(' expression ')'
|
||||
{ named_pexpr_t*tmp = new named_pexpr_t;
|
||||
tmp->name = lex_strings.make($2);
|
||||
tmp->parm = $4;
|
||||
delete[]$2;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
modport_tf_port
|
||||
: K_task IDENTIFIER
|
||||
| K_task IDENTIFIER '(' tf_port_list_opt ')'
|
||||
| K_function data_type_or_implicit_or_void IDENTIFIER
|
||||
| K_function data_type_or_implicit_or_void IDENTIFIER '(' tf_port_list_opt ')'
|
||||
;
|
||||
|
||||
non_integer_type /* IEEE1800-2005: A.2.2.1 */
|
||||
: K_real { $$ = real_type_t::REAL; }
|
||||
@@ -2186,8 +2311,8 @@ block_item_decl
|
||||
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||
}
|
||||
|
||||
| K_event list_of_identifiers ';'
|
||||
{ pform_make_events($2, @1.text, @1.first_line);
|
||||
| K_event event_variable_list ';'
|
||||
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
||||
}
|
||||
|
||||
| K_parameter param_type parameter_assign_list ';'
|
||||
@@ -2233,9 +2358,9 @@ block_item_decls_opt
|
||||
/* Type declarations are parsed here. The rule actions call pform
|
||||
functions that add the declaration to the current lexical scope. */
|
||||
type_declaration
|
||||
: K_typedef data_type IDENTIFIER ';'
|
||||
: K_typedef data_type IDENTIFIER dimensions_opt ';'
|
||||
{ perm_string name = lex_strings.make($3);
|
||||
pform_set_typedef(name, $2);
|
||||
pform_set_typedef(name, $2, $4);
|
||||
delete[]$3;
|
||||
}
|
||||
|
||||
@@ -2248,7 +2373,7 @@ type_declaration
|
||||
yyerror(@3, "error: Typedef identifier \"%s\" is already a type name.", $3.text);
|
||||
|
||||
} else {
|
||||
pform_set_typedef(name, $2);
|
||||
pform_set_typedef(name, $2, NULL);
|
||||
}
|
||||
delete[]$3.text;
|
||||
}
|
||||
@@ -2261,7 +2386,7 @@ type_declaration
|
||||
perm_string name = lex_strings.make($3);
|
||||
class_type_t*tmp = new class_type_t(name);
|
||||
FILE_NAME(tmp, @3);
|
||||
pform_set_typedef(name, tmp);
|
||||
pform_set_typedef(name, tmp, NULL);
|
||||
delete[]$3;
|
||||
}
|
||||
| K_typedef K_enum IDENTIFIER ';'
|
||||
@@ -2276,7 +2401,7 @@ type_declaration
|
||||
perm_string name = lex_strings.make($2);
|
||||
class_type_t*tmp = new class_type_t(name);
|
||||
FILE_NAME(tmp, @2);
|
||||
pform_set_typedef(name, tmp);
|
||||
pform_set_typedef(name, tmp, NULL);
|
||||
delete[]$2;
|
||||
}
|
||||
|
||||
@@ -2323,34 +2448,34 @@ enum_data_type
|
||||
enum_type->range.reset(make_range_from_width(integer_width));
|
||||
$$ = enum_type;
|
||||
}
|
||||
| K_enum K_logic unsigned_signed_opt dimensions '{' enum_name_list '}'
|
||||
| K_enum K_logic unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
|
||||
{ enum_type_t*enum_type = new enum_type_t;
|
||||
FILE_NAME(enum_type, @1);
|
||||
enum_type->names .reset($6);
|
||||
enum_type->base_type = IVL_VT_LOGIC;
|
||||
enum_type->signed_flag = $3;
|
||||
enum_type->integer_flag = false;
|
||||
enum_type->range.reset($4);
|
||||
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
|
||||
$$ = enum_type;
|
||||
}
|
||||
| K_enum K_reg unsigned_signed_opt dimensions '{' enum_name_list '}'
|
||||
| K_enum K_reg unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
|
||||
{ enum_type_t*enum_type = new enum_type_t;
|
||||
FILE_NAME(enum_type, @1);
|
||||
enum_type->names .reset($6);
|
||||
enum_type->base_type = IVL_VT_LOGIC;
|
||||
enum_type->signed_flag = $3;
|
||||
enum_type->integer_flag = false;
|
||||
enum_type->range.reset($4);
|
||||
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
|
||||
$$ = enum_type;
|
||||
}
|
||||
| K_enum K_bit unsigned_signed_opt dimensions '{' enum_name_list '}'
|
||||
| K_enum K_bit unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
|
||||
{ enum_type_t*enum_type = new enum_type_t;
|
||||
FILE_NAME(enum_type, @1);
|
||||
enum_type->names .reset($6);
|
||||
enum_type->base_type = IVL_VT_BOOL;
|
||||
enum_type->signed_flag = $3;
|
||||
enum_type->integer_flag = false;
|
||||
enum_type->range.reset($4);
|
||||
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
|
||||
$$ = enum_type;
|
||||
}
|
||||
;
|
||||
@@ -4213,13 +4338,13 @@ local_timeunit_prec_decl2
|
||||
}
|
||||
;
|
||||
|
||||
/* This is the global structure of a module. A module in a start
|
||||
/* This is the global structure of a module. A module is a start
|
||||
section, with optional ports, then an optional list of module
|
||||
items, and finally an end marker. */
|
||||
|
||||
module
|
||||
: attribute_list_opt module_start IDENTIFIER
|
||||
{ pform_startmodule(@2, $3, $2==K_program, $1); }
|
||||
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
|
||||
module_package_import_list_opt
|
||||
module_parameter_port_list_opt
|
||||
module_port_list_opt
|
||||
@@ -4258,6 +4383,9 @@ module
|
||||
case K_program:
|
||||
yyerror(@14, "error: program not closed by endprogram.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@14, "error: interface not closed by endinterface.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -4283,6 +4411,10 @@ module
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
"program name.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
"interface name.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -4297,19 +4429,21 @@ module
|
||||
}
|
||||
;
|
||||
|
||||
/* Modules start with module/macromodule or program keyword, and end
|
||||
with the endmodule or endprogram keyword. The syntax for modules
|
||||
and programs is almost identical, so let semantics sort out the
|
||||
differences. */
|
||||
/* Modules start with a module/macromodule, program, or interface
|
||||
keyword, and end with a endmodule, endprogram, or endinterface
|
||||
keyword. The syntax for modules programs, and interfaces is
|
||||
almost identical, so let semantics sort out the differences. */
|
||||
module_start
|
||||
: K_module { $$ = K_module; }
|
||||
| K_macromodule { $$ = K_module; }
|
||||
| K_program { $$ = K_program; }
|
||||
| K_interface { $$ = K_interface; }
|
||||
;
|
||||
|
||||
module_end
|
||||
: K_endmodule { $$ = K_module; }
|
||||
| K_endprogram { $$ = K_program; }
|
||||
: K_endmodule { $$ = K_module; }
|
||||
| K_endprogram { $$ = K_program; }
|
||||
| K_endinterface { $$ = K_interface; }
|
||||
;
|
||||
|
||||
endlabel_opt
|
||||
@@ -4505,7 +4639,12 @@ module_item
|
||||
|
||||
/* */
|
||||
|
||||
| K_defparam defparam_assign_list ';'
|
||||
| K_defparam
|
||||
{ if (pform_in_interface())
|
||||
yyerror(@1, "error: Parameter overrides are not allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
defparam_assign_list ';'
|
||||
|
||||
/* Most gate types have an optional drive strength and optional
|
||||
two/three-value delay. These rules handle the different cases.
|
||||
@@ -4670,25 +4809,32 @@ module_item
|
||||
pform_endgenerate();
|
||||
}
|
||||
|
||||
| modport_declaration
|
||||
|
||||
| package_import_declaration
|
||||
|
||||
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
|
||||
|
||||
| attribute_list_opt K_specparam specparam_decl ';'
|
||||
| attribute_list_opt K_specparam
|
||||
{ if (pform_in_interface())
|
||||
yyerror(@1, "error: specparam declarations are not allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
specparam_decl ';'
|
||||
|
||||
/* specify blocks are parsed but ignored. */
|
||||
|
||||
| K_specify K_endspecify
|
||||
{ /* empty lists are legal syntax. */ }
|
||||
| K_specify
|
||||
{ if (pform_in_interface())
|
||||
yyerror(@1, "error: specify blocks are not allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
specify_item_list_opt K_endspecify
|
||||
|
||||
| K_specify specify_item_list K_endspecify
|
||||
{
|
||||
}
|
||||
|
||||
| K_specify error K_endspecify
|
||||
{ yyerror(@1, "error: syntax error in specify block");
|
||||
yyerrok;
|
||||
}
|
||||
| K_specify error K_endspecify
|
||||
{ yyerror(@1, "error: syntax error in specify block");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
/* These rules match various errors that the user can type into
|
||||
module items. These rules try to catch them at a point where a
|
||||
@@ -5338,6 +5484,23 @@ net_variable_list
|
||||
}
|
||||
;
|
||||
|
||||
event_variable
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ if ($2) {
|
||||
yyerror(@2, "sorry: event arrays are not supported.");
|
||||
delete $2;
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
event_variable_list
|
||||
: event_variable
|
||||
{ $$ = list_from_identifier($1); }
|
||||
| event_variable_list ',' event_variable
|
||||
{ $$ = list_from_identifier($1, $3); }
|
||||
;
|
||||
|
||||
specify_item
|
||||
: K_specparam specparam_decl ';'
|
||||
| specify_simple_path_decl ';'
|
||||
@@ -5450,6 +5613,12 @@ specify_item_list
|
||||
| specify_item_list specify_item
|
||||
;
|
||||
|
||||
specify_item_list_opt
|
||||
: /* empty */
|
||||
{ }
|
||||
| specify_item_list
|
||||
{ }
|
||||
|
||||
specify_edge_path_decl
|
||||
: specify_edge_path '=' '(' delay_value_list ')'
|
||||
{ $$ = pform_assign_path_delay($1, $4); }
|
||||
@@ -6566,7 +6735,7 @@ udp_primitive
|
||||
presence is significant. This is a fairly common pattern so
|
||||
collect those rules here. */
|
||||
|
||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false;} ;
|
||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
|
||||
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -29,6 +29,7 @@
|
||||
# include "PPackage.h"
|
||||
# include "PUdp.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PModport.h"
|
||||
# include "PSpec.h"
|
||||
# include "discipline.h"
|
||||
# include <list>
|
||||
@@ -265,6 +266,10 @@ static unsigned scope_generate_counter = 1;
|
||||
always within a module. */
|
||||
static PGenerate*pform_cur_generate = 0;
|
||||
|
||||
/* This tracks the current modport list being processed. This is
|
||||
always within an interface. */
|
||||
static PModport*pform_cur_modport = 0;
|
||||
|
||||
static NetNet::Type pform_default_nettype = NetNet::WIRE;
|
||||
|
||||
/*
|
||||
@@ -534,6 +539,15 @@ bool pform_in_program_block()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pform_in_interface()
|
||||
{
|
||||
if (pform_cur_module.empty())
|
||||
return false;
|
||||
if (pform_cur_module.front()->is_interface)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pform_at_module_level()
|
||||
{
|
||||
return (lexical_scope == pform_cur_module.front())
|
||||
@@ -579,8 +593,11 @@ PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetN
|
||||
return cur;
|
||||
}
|
||||
|
||||
void pform_set_typedef(perm_string name, data_type_t*data_type)
|
||||
void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_range_t>*unp_ranges)
|
||||
{
|
||||
if(unp_ranges)
|
||||
data_type = new uarray_type_t(data_type, unp_ranges);
|
||||
|
||||
// If we are in a lexical scope (i.e. a package or module)
|
||||
// then put the typedef into that scope. Otherwise, put it
|
||||
// into the $root scope.
|
||||
@@ -1062,6 +1079,12 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||
assert(siz->is_defined());
|
||||
unsigned long size = siz->as_ulong();
|
||||
|
||||
if (size == 0) {
|
||||
cerr << file << ":" << lineno << ": error: Sized numeric constant "
|
||||
"must have a size greater than zero." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
verinum::V pad;
|
||||
|
||||
switch (val->get(val->len()-1)) {
|
||||
@@ -1107,7 +1130,8 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||
}
|
||||
|
||||
void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
bool program_block, list<named_pexpr_t>*attr)
|
||||
bool program_block, bool is_interface,
|
||||
list<named_pexpr_t>*attr)
|
||||
{
|
||||
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
||||
cerr << loc << ": error: Module definition " << name
|
||||
@@ -1115,15 +1139,25 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
if (gn_system_verilog() && ! pform_cur_module.empty() &&
|
||||
pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: Program blocks cannot contain nested modules/program blocks." << endl;
|
||||
error_count += 1;
|
||||
if (gn_system_verilog() && ! pform_cur_module.empty()) {
|
||||
if (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: module, program, or interface "
|
||||
"declarations are not allowed in program "
|
||||
"blocks." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (pform_cur_module.front()->is_interface
|
||||
&& !(program_block || is_interface)) {
|
||||
cerr << loc << ": error: module declarations are not "
|
||||
"allowed in interfaces." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string lex_name = lex_strings.make(name);
|
||||
Module*cur_module = new Module(lexical_scope, lex_name);
|
||||
cur_module->program_block = program_block;
|
||||
cur_module->is_interface = is_interface;
|
||||
/* Set the local time unit/precision to the global value. */
|
||||
cur_module->time_unit = pform_time_unit;
|
||||
cur_module->time_precision = pform_time_prec;
|
||||
@@ -1914,7 +1948,6 @@ static void pform_set_net_range(list<perm_string>*names,
|
||||
pform_set_net_range(txt, net_type, range, signed_flag, dt, SR_NET, attr);
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2001,8 +2034,13 @@ void pform_makegates(const struct vlltype&loc,
|
||||
{
|
||||
assert(! pform_cur_module.empty());
|
||||
if (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: Gates and switches may not be instantiated"
|
||||
<< " in program blocks." << endl;
|
||||
cerr << loc << ": error: Gates and switches may not be instantiated in "
|
||||
<< "program blocks." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (pform_cur_module.front()->is_interface) {
|
||||
cerr << loc << ": error: Gates and switches may not be instantiated in "
|
||||
<< "interfaces." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
@@ -2117,8 +2155,13 @@ void pform_make_modgates(const struct vlltype&loc,
|
||||
{
|
||||
assert(! pform_cur_module.empty());
|
||||
if (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: Module instantiations are not allowed"
|
||||
<< " in program blocks." << endl;
|
||||
cerr << loc << ": error: Module instantiations are not allowed in "
|
||||
<< "program blocks." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (pform_cur_module.front()->is_interface) {
|
||||
cerr << loc << ": error: Module instantiations are not allowed in "
|
||||
<< "interfaces." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
@@ -2317,6 +2360,11 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
signed_flag = false;
|
||||
prange = 0;
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(vtype)) {
|
||||
data_type = enum_type->base_type;
|
||||
signed_flag = enum_type->signed_flag;
|
||||
prange = enum_type->range.get();
|
||||
|
||||
} else if (vtype) {
|
||||
VLerror(li, "sorry: Given type %s not supported here (%s:%d).",
|
||||
typeid(*vtype).name(), __FILE__, __LINE__);
|
||||
@@ -2624,7 +2672,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
}
|
||||
|
||||
delete range;
|
||||
delete names;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2653,7 +2700,6 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
||||
|
||||
res->push_back(pform_tf_port_t(curw));
|
||||
}
|
||||
delete names;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2662,35 +2708,54 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
data_type_t*vtype,
|
||||
list<perm_string>*names)
|
||||
{
|
||||
vector<pform_tf_port_t>*ret = NULL;
|
||||
std::list<pform_range_t>*unpacked_dims = NULL;
|
||||
|
||||
if (uarray_type_t*uarray = dynamic_cast<uarray_type_t*> (vtype)) {
|
||||
unpacked_dims = uarray->dims.get();
|
||||
vtype = uarray->base_type;
|
||||
}
|
||||
|
||||
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
|
||||
list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code);
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL,
|
||||
atype->signed_flag,
|
||||
range_tmp, names);
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, vec_type->base_type,
|
||||
ret = pform_make_task_ports(loc, pt, vec_type->base_type,
|
||||
vec_type->signed_flag,
|
||||
copy_range(vec_type->pdims.get()),
|
||||
names, vec_type->integer_flag);
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_REAL,
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_REAL,
|
||||
true, 0, names);
|
||||
}
|
||||
|
||||
if (dynamic_cast<string_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_STRING,
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_STRING,
|
||||
false, 0, names);
|
||||
}
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
|
||||
return do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
|
||||
}
|
||||
|
||||
return do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
|
||||
|
||||
if (unpacked_dims) {
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(*cur);
|
||||
wire->set_unpacked_idx(*unpacked_dims);
|
||||
}
|
||||
}
|
||||
|
||||
delete names;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3136,7 +3201,6 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_
|
||||
perm_string txt = *cur;
|
||||
pform_set_integer_2atom(width, signed_flag, txt, net_type, attr);
|
||||
}
|
||||
delete names;
|
||||
}
|
||||
|
||||
template <class T> static void pform_set2_data_type(const struct vlltype&li, T*data_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
|
||||
@@ -3212,7 +3276,6 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
pform_set_enum(li, enum_type, txt, net_type, attr);
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3221,58 +3284,68 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
*/
|
||||
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
|
||||
{
|
||||
const std::list<pform_range_t>*unpacked_dims = NULL;
|
||||
|
||||
if (data_type == 0) {
|
||||
VLerror(li, "internal error: data_type==0.");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if(uarray_type_t*uarray_type = dynamic_cast<uarray_type_t*> (data_type)) {
|
||||
unpacked_dims = uarray_type->dims.get();
|
||||
data_type = uarray_type->base_type;
|
||||
}
|
||||
|
||||
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
|
||||
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
|
||||
else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
|
||||
pform_set_struct_type(struct_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
|
||||
else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
|
||||
pform_set_enum(li, enum_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
|
||||
else if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
|
||||
if (net_type==NetNet::REG && vec_type->integer_flag)
|
||||
net_type=NetNet::INTEGER;
|
||||
|
||||
pform_set_net_range(names, vec_type->pdims.get(),
|
||||
vec_type->signed_flag,
|
||||
vec_type->base_type, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
|
||||
else if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
|
||||
pform_set_net_range(names, 0, true, IVL_VT_REAL, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
|
||||
else if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
|
||||
pform_set_class_type(class_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
|
||||
else if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
|
||||
pform_set2_data_type(li, array_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
|
||||
else if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
|
||||
pform_set_string_type(string_type, names, net_type, attr);
|
||||
return;
|
||||
|
||||
} else {
|
||||
VLerror(li, "internal error: Unexpected data_type.");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
VLerror(li, "internal error: Unexpected data_type.");
|
||||
assert(0);
|
||||
if(unpacked_dims) {
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(*cur);
|
||||
wire->set_unpacked_idx(*unpacked_dims);
|
||||
}
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
vector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
@@ -3326,6 +3399,46 @@ PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
|
||||
return pp;
|
||||
}
|
||||
|
||||
void pform_start_modport_item(const struct vlltype&loc, const char*name)
|
||||
{
|
||||
Module*scope = pform_cur_module.front();
|
||||
ivl_assert(loc, scope && scope->is_interface);
|
||||
ivl_assert(loc, pform_cur_modport == 0);
|
||||
|
||||
perm_string use_name = lex_strings.make(name);
|
||||
pform_cur_modport = new PModport(use_name);
|
||||
FILE_NAME(pform_cur_modport, loc);
|
||||
if (scope->modports.find(use_name) != scope->modports.end()) {
|
||||
cerr << loc << ": error: duplicate declaration for modport '"
|
||||
<< name << "' in '" << scope->mod_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
scope->modports[use_name] = pform_cur_modport;
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
void pform_end_modport_item(const struct vlltype&loc)
|
||||
{
|
||||
ivl_assert(loc, pform_cur_modport);
|
||||
pform_cur_modport = 0;
|
||||
}
|
||||
|
||||
void pform_add_modport_port(const struct vlltype&loc,
|
||||
NetNet::PortType port_type,
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
ivl_assert(loc, pform_cur_modport);
|
||||
|
||||
if (pform_cur_modport->simple_ports.find(name)
|
||||
!= pform_cur_modport->simple_ports.end()) {
|
||||
cerr << loc << ": error: duplicate declaration of port '"
|
||||
<< name << "' in modport list '"
|
||||
<< pform_cur_modport->name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
pform_cur_modport->simple_ports[name] = make_pair(port_type, expr);
|
||||
}
|
||||
|
||||
|
||||
FILE*vl_input = 0;
|
||||
extern void reset_lexor();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_pform_H
|
||||
#define IVL_pform_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 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
|
||||
@@ -136,6 +136,10 @@ extern void pform_set_default_nettype(NetNet::Type net,
|
||||
used to reject statements that cannot exist in program blocks. */
|
||||
extern bool pform_in_program_block(void);
|
||||
|
||||
/* Return true if currently processing an interface. This can be
|
||||
used to reject statements that cannot exist in interfaces. */
|
||||
extern bool pform_in_interface(void);
|
||||
|
||||
/*
|
||||
* Look for the given wire in the current lexical scope. If the wire
|
||||
* (including variables of any type) cannot be found in the current
|
||||
@@ -152,12 +156,14 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
|
||||
* are to apply to the scope of that module. The endmodule causes the
|
||||
* pform to close up and finish the named module.
|
||||
*
|
||||
* The program_flag indicates that the module is actually a program
|
||||
* block. This has implications during parse and during
|
||||
* The program_block flag indicates that the module is actually a program
|
||||
* block. The is_interface flag indicates that the module is actually
|
||||
* an interface. These flags have implications during parse and during
|
||||
* elaboration/code generation.
|
||||
*/
|
||||
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
bool program_block, list<named_pexpr_t>*attr);
|
||||
bool program_block, bool is_interface,
|
||||
list<named_pexpr_t>*attr);
|
||||
extern void pform_check_timeunit_prec();
|
||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||
|
||||
@@ -213,6 +219,15 @@ extern void pform_package_import(const struct vlltype&loc,
|
||||
extern PExpr* pform_package_ident(const struct vlltype&loc,
|
||||
PPackage*pkg, pform_name_t*ident);
|
||||
|
||||
/*
|
||||
* Interface related functions.
|
||||
*/
|
||||
extern void pform_start_modport_item(const struct vlltype&loc, const char*name);
|
||||
extern void pform_end_modport_item(const struct vlltype&loc);
|
||||
extern void pform_add_modport_port(const struct vlltype&loc,
|
||||
NetNet::PortType port_type,
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/*
|
||||
* This creates an identifier aware of names that may have been
|
||||
* imported from other packages.
|
||||
@@ -272,7 +287,8 @@ extern void pform_endgenerate();
|
||||
*/
|
||||
extern PGenerate* pform_parent_generate(void);
|
||||
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type);
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
|
||||
std::list<pform_range_t>*unp_ranges);
|
||||
|
||||
/*
|
||||
* This function makes a PECallFunction of the named function. Decide
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
return false;
|
||||
|
||||
// The prefix is found to be a scope, so switch to that
|
||||
// scope, set the hier_path to turn of upwards searches,
|
||||
// scope, set the hier_path to turn off upwards searches,
|
||||
// and continue our search for the tail.
|
||||
if (recurse.is_scope()) {
|
||||
scope = recurse.scope;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2015 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
|
||||
@@ -82,15 +82,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (lval_->more) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "NetAssignBase::synth_async does not support an "
|
||||
<< "L-value concatenation ";
|
||||
dump_lval(cerr);
|
||||
cerr << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetAssignBase::synth_async: "
|
||||
@@ -109,6 +100,34 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
<< ", nex_out.pin_count()==" << nex_out.pin_count() << endl;
|
||||
}
|
||||
|
||||
if (lval_->more ) {
|
||||
unsigned base = 0, width = 1;
|
||||
unsigned i = 0;
|
||||
NetAssign_ *lval = lval_;
|
||||
while (lval) {
|
||||
NetNet *llsig = lval->sig();
|
||||
width = lval->lwidth();
|
||||
ivl_variable_type_t tmp_data_type = llsig->data_type();
|
||||
netvector_t *tmp_type = new netvector_t(tmp_data_type, llsig->vector_width()-1, 0);
|
||||
|
||||
NetNet *tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
NetPartSelect *ps = new NetPartSelect(rsig, base, width, NetPartSelect::VP);
|
||||
ps->set_line(*this);
|
||||
des->add_node(ps);
|
||||
|
||||
connect(tmp->pin(0), ps->pin(0));
|
||||
connect(nex_out.pin(i), tmp->pin(0));
|
||||
|
||||
base += width;
|
||||
i++;
|
||||
lval->turn_sig_to_wire_on_release();
|
||||
lval = lval->more;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Here we note if the l-value is actually a bit/part
|
||||
// select. If so, generate a NetPartSelect to perform the select.
|
||||
if ((lval_->lwidth()!=lsig->vector_width()) && !scope->loop_index_tmp.empty()) {
|
||||
@@ -136,6 +155,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(tmp, base_off, lval_->lwidth(), NetPartSelect::PV);
|
||||
ps->set_line(*this);
|
||||
@@ -166,7 +186,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
//tmp->local_flag(true);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
ivl_assert(*this, accumulated_nex_out.pin_count()==1);
|
||||
NetNet*use_lsig = lsig;
|
||||
@@ -185,7 +206,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
<< " Found no use_sig, resorting to lsig." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
NetSubstitute*ps = new NetSubstitute(use_lsig, rsig,
|
||||
tmp->vector_width(),
|
||||
base_off);
|
||||
@@ -531,18 +551,24 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
statement_map[sel_idx] = items_[item].statement;
|
||||
}
|
||||
|
||||
// The mux_size is the number of inputs that are selected.
|
||||
unsigned mux_size = max_guard_value + 1;
|
||||
unsigned sel_need = ceil(log2(mux_size));
|
||||
// The minimum selector width is the number of inputs that
|
||||
// are selected, rounded up to the nearest power of 2.
|
||||
unsigned sel_need = ceil(log2(max_guard_value + 1));
|
||||
|
||||
// If the sel_width can select more than just the explicit
|
||||
// guard values, and there is a default statement, then adjust
|
||||
// the mux size to allow for the implicit selections.
|
||||
if (statement_default && (sel_width > sel_need)) {
|
||||
// the sel_need to allow for the implicit selections.
|
||||
if (statement_default && (sel_width > sel_need))
|
||||
sel_need += 1;
|
||||
ivl_assert(*this, sel_need < sizeof mux_size);
|
||||
mux_size = 1<<sel_need;
|
||||
|
||||
// The mux size is always an exact power of 2.
|
||||
if (sel_need >= 8*sizeof(unsigned)) {
|
||||
cerr << get_fileline() << ": sorry: mux select width of "
|
||||
<< sel_need << " bits is too large for synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
unsigned mux_size = 1U << sel_need;
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
@@ -746,7 +772,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
|
||||
netvector_t*condit_type = new netvector_t(IVL_VT_LOGIC, 0, 0);
|
||||
|
||||
NetCaseCmp::kind_t case_kind;
|
||||
NetCaseCmp::kind_t case_kind = NetCaseCmp::EEQ;
|
||||
switch (type()) {
|
||||
case NetCase::EQ:
|
||||
case_kind = NetCaseCmp::EEQ;
|
||||
@@ -829,6 +855,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, tmp_vec);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
ivl_assert(*this, tmp->vector_width() != 0);
|
||||
connect(mux_cur->pin_Result(), tmp->pin(0));
|
||||
|
||||
@@ -1105,6 +1132,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*otmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
otmp->local_flag(true);
|
||||
otmp->set_line(*this);
|
||||
connect(mux->pin_Result(),otmp->pin(0));
|
||||
|
||||
connect(mux->pin_Sel(), ssig->pin(0));
|
||||
@@ -1115,6 +1143,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(mux->pin_Data(1), tmp->pin(0));
|
||||
}
|
||||
|
||||
@@ -1122,6 +1152,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(mux->pin_Data(0), tmp->pin(0));
|
||||
}
|
||||
|
||||
@@ -1132,6 +1164,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_lwidth-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
NetPartSelect*ps = new NetPartSelect(tmp, mux_off, mux_width, NetPartSelect::PV);
|
||||
des->add_node(ps);
|
||||
connect(ps->pin(0), otmp->pin(0));
|
||||
@@ -1159,8 +1193,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
}
|
||||
vector<bool>mask = statement_input.pin(idx).nexus()->driven_mask();
|
||||
for (size_t bit = mux_off ; bit < mux_off+mux_width ; bit += 1) {
|
||||
ivl_assert(*this, mask[bit]==false);
|
||||
// If the mask is empty then there are no bits in the
|
||||
// nexus to check yet.
|
||||
if (! mask.empty()) {
|
||||
for (size_t bit = mux_off;
|
||||
bit < mux_off+mux_width;
|
||||
bit += 1) {
|
||||
ivl_assert(*this, mask[bit]==false);
|
||||
}
|
||||
}
|
||||
connect(nex_out.pin(idx), statement_input.pin(idx));
|
||||
}
|
||||
@@ -1308,6 +1348,7 @@ bool NetProcTop::synth_async(Design*des)
|
||||
NetNet*tmp_sig = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp_sig->local_flag(true);
|
||||
tmp_sig->set_line(*this);
|
||||
|
||||
NetPartSelect*tmp = new NetPartSelect(tmp_sig, item.base,
|
||||
item.wid, NetPartSelect::PV);
|
||||
@@ -1508,9 +1549,49 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
connect(ff_aset.pin(pin), rst->pin(0));
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Forgot how to implement asynchronous scramble (set to x/z)." << endl;
|
||||
return false;
|
||||
NetConcat *set_cc = new NetConcat(scope,
|
||||
scope->local_symbol(),
|
||||
rst_nex->vector_width(),
|
||||
rst_drv.len(), true);
|
||||
NetConcat *rst_cc = new NetConcat(scope,
|
||||
scope->local_symbol(),
|
||||
rst_nex->vector_width(),
|
||||
rst_drv.len(), true);
|
||||
ivl_variable_type_t oosig_data_type = IVL_VT_LOGIC;
|
||||
netvector_t *oosig_vec = new netvector_t(oosig_data_type, 0, 0);
|
||||
NetNet *oosig[2] = {new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, oosig_vec),
|
||||
new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, oosig_vec)};
|
||||
set_cc->set_line(*this);
|
||||
des->add_node(set_cc);
|
||||
connect(set_cc->pin(0), oosig[0]->pin(0));
|
||||
rst_cc->set_line(*this);
|
||||
des->add_node(rst_cc);
|
||||
connect(rst_cc->pin(0), oosig[1]->pin(0));
|
||||
for (int i = 0; i < (int)rst_drv.len(); i += 1) {
|
||||
// This is the output signal f const, osig.
|
||||
ivl_variable_type_t osig_data_type = IVL_VT_LOGIC;
|
||||
netvector_t*osig_vec = new netvector_t(osig_data_type, 0, 0);
|
||||
NetNet *osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, osig_vec);
|
||||
NetConst *nc = new NetConst(scope, scope->local_symbol(),
|
||||
verinum(verinum::V0, 1));
|
||||
connect(nc->pin(0), osig->pin(0));
|
||||
nc->set_line(*this);
|
||||
des->add_node(nc);
|
||||
if (rst_drv[i] == verinum::V1) {
|
||||
connect(set_cc->pin(i+1), rst->pin(0));
|
||||
connect(rst_cc->pin(i+1), nc->pin(0));
|
||||
} else {
|
||||
connect(set_cc->pin(i+1), nc->pin(0));
|
||||
connect(rst_cc->pin(i+1), rst->pin(0));
|
||||
}
|
||||
}
|
||||
connect(ff_aset.pin(pin), set_cc->pin(0));
|
||||
connect(ff_aclr.pin(pin), rst_cc->pin(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1789,6 +1870,7 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
NetNet*clock = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::TRI, &netvector_t::scalar_logic);
|
||||
clock->local_flag(true);
|
||||
clock->set_line(*this);
|
||||
|
||||
#if 0
|
||||
NetNet*ce = new NetNet(scope(), scope()->local_symbol(),
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -364,6 +364,7 @@ void dll_target::expr_last(const NetELast*net)
|
||||
esig->value_ = IVL_VT_DARRAY;
|
||||
esig->net_type= sig->net_type;
|
||||
esig->width_ = 1;
|
||||
esig->signed_ = sig->net_type->get_signed()? 1 : 0;
|
||||
FILE_NAME(esig, net);
|
||||
esig->u_.signal_.word = 0;
|
||||
esig->u_.signal_.sig = sig;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -1057,20 +1057,17 @@ void dll_target::logic(const NetLogic*net)
|
||||
obj->npins_ = net->pin_count();
|
||||
obj->pins_ = new ivl_nexus_t[obj->npins_];
|
||||
|
||||
ivl_nexus_ptr_t out_ptr = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins_[idx] = nex->t_cookie();
|
||||
ivl_nexus_ptr_t tmp = nexus_log_add(obj->pins_[idx], obj, idx);
|
||||
if (idx == 0)
|
||||
out_ptr = tmp;
|
||||
if (idx == 0) {
|
||||
tmp->drive0 = net->pin(0).drive0();
|
||||
tmp->drive1 = net->pin(0).drive1();
|
||||
}
|
||||
}
|
||||
|
||||
out_ptr->drive0 = net->pin(0).drive0();
|
||||
out_ptr->drive1 = net->pin(0).drive1();
|
||||
|
||||
assert(net->scope());
|
||||
ivl_scope_t scop = find_scope(des_, net->scope());
|
||||
assert(scop);
|
||||
|
||||
+6
-3
@@ -82,12 +82,15 @@ pcb_config.h: stamp-pcb_config-h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
fp_lex.o: fp_lex.cc fp.h
|
||||
|
||||
fp_lex.cc: $(srcdir)/fp.lex
|
||||
$(LEX) -s -ofp_lex.cc $(srcdir)/fp.lex
|
||||
|
||||
fp.cc fp.h: $(srcdir)/fp.y
|
||||
$(YACC) --verbose -t -d -o fp.cc $(srcdir)/fp.y
|
||||
mv fp.cc.h fp.h 2>/dev/null || mv fp.hh fp.h
|
||||
fp.cc: $(srcdir)/fp.y
|
||||
$(YACC) --verbose -t -p fp -d -o $@ $<
|
||||
fp.h: fp.cc
|
||||
mv fp.cc.h $@ 2>/dev/null || mv fp.hh $@
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
%name-prefix="fp"
|
||||
%pure-parser
|
||||
%parse-param {const char*file_path}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// are not used here.
|
||||
|
||||
// target_design()
|
||||
unusedFunction:stub.c:1770
|
||||
unusedFunction:stub.c:1773
|
||||
|
||||
// target_query()
|
||||
unusedFunction:stub.c:1834
|
||||
unusedFunction:stub.c:1843
|
||||
|
||||
+1
-1
@@ -380,7 +380,7 @@ static void show_lpm_divide(ivl_lpm_t net)
|
||||
*/
|
||||
static void show_lpm_cmp_eeq(ivl_lpm_t net)
|
||||
{
|
||||
const char*str;
|
||||
const char*str = 0;
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
str = "EEQ";
|
||||
|
||||
@@ -1900,7 +1900,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
|
||||
{
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig, 0);
|
||||
unsigned idx, count = ivl_nexus_ptrs(nex);
|
||||
unsigned long emitted = (unsigned long) ivl_nexus_get_private(nex);
|
||||
unsigned long emitted = (uintptr_t) ivl_nexus_get_private(nex);
|
||||
for (idx = 0; idx < count; idx += 1) {
|
||||
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
||||
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
|
||||
@@ -1930,7 +1930,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
|
||||
fprintf(vlog_out, "\n");
|
||||
/* Increment the emitted constant count by one. */
|
||||
ivl_nexus_set_private(nex,
|
||||
(void *) ((unsigned long) ivl_nexus_get_private(nex) + 1U));
|
||||
(void *) ((uintptr_t) ivl_nexus_get_private(nex) + 1U));
|
||||
return;
|
||||
}
|
||||
/* We must find the constant in the nexus. */
|
||||
|
||||
+13
-3
@@ -78,6 +78,7 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
|
||||
{
|
||||
unsigned has_undef = 0;
|
||||
|
||||
assert(nbits > 0);
|
||||
/* Check for an undefined bit. */
|
||||
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
|
||||
if ((bits[idx] != '0') && (bits[idx] != '1')) {
|
||||
@@ -91,8 +92,14 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
|
||||
|
||||
/* Emit as a binary constant. */
|
||||
if (has_undef || (nbits < 2)) {
|
||||
int start = nbits - 1;
|
||||
char sbit = bits[start];
|
||||
/* Trim extra leading bits. */
|
||||
if (! is_signed && (sbit == '1')) sbit = ' ';
|
||||
while (start && (sbit == bits[start-1])) start -= 1;
|
||||
/* Print the trimmed value. */
|
||||
fprintf(vlog_out, "b");
|
||||
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
|
||||
for (int idx = start; idx >= 0; idx -= 1) {
|
||||
fprintf(vlog_out, "%c", bits[idx]);
|
||||
}
|
||||
/* Emit as a hex constant. */
|
||||
@@ -152,9 +159,12 @@ void emit_number(const char *bits, unsigned nbits, unsigned is_signed,
|
||||
vlog_errors += 1;
|
||||
return;
|
||||
} else if (rtype == -2) {
|
||||
fprintf(vlog_out, "'bz");
|
||||
fprintf(vlog_out, "%u'bz", nbits);
|
||||
} else if (rtype == -3) {
|
||||
fprintf(vlog_out, "'bx");
|
||||
/* If this is a 32-bit wide constant then generate the
|
||||
* undefined with integers to get a signed value. */
|
||||
if (nbits == 32) fprintf(vlog_out, "1/0");
|
||||
else fprintf(vlog_out, "%u'bx", nbits);
|
||||
} else {
|
||||
fprintf(vlog_out, "%"PRId32, value);
|
||||
}
|
||||
|
||||
+1
-1
@@ -942,7 +942,7 @@ static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
|
||||
static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
{
|
||||
const char *case_type;
|
||||
const char *case_type = 0;
|
||||
unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
|
||||
switch (ivl_statement_type(stmt)) {
|
||||
case IVL_ST_CASE:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// are not used here.
|
||||
|
||||
// target_design()
|
||||
unusedFunction:vvp.c:89
|
||||
unusedFunction:vvp.c:149
|
||||
|
||||
// target_query()
|
||||
unusedFunction:vvp.c:184
|
||||
unusedFunction:vvp.c:246
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
+46
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2005-2015 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,6 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
|
||||
if (ewidth < pwidth)
|
||||
fprintf(vvp_out, " %%pad/u %u;\n", pwidth);
|
||||
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", port, pwidth);
|
||||
}
|
||||
|
||||
static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
||||
@@ -45,54 +44,57 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
||||
assert(ivl_signal_dimensions(port) == 0);
|
||||
|
||||
draw_eval_real(expr);
|
||||
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
function_argument_logic(port, expr);
|
||||
}
|
||||
|
||||
static void function_argument_class(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
draw_eval_object(expr);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void function_argument_darray(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
draw_eval_object(expr);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void function_argument_string(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
draw_eval_string(expr);
|
||||
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||
static void draw_eval_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
switch (dtype) {
|
||||
case IVL_VT_BOOL:
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
case IVL_VT_LOGIC:
|
||||
function_argument_logic(port, expr);
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
function_argument_real(port, expr);
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
function_argument_bool(port, expr);
|
||||
break;
|
||||
case IVL_VT_CLASS:
|
||||
function_argument_class(port, expr);
|
||||
vvp_errors += draw_eval_object(expr);
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
function_argument_string(port, expr);
|
||||
draw_eval_string(expr);
|
||||
break;
|
||||
case IVL_VT_DARRAY:
|
||||
function_argument_darray(port, expr);
|
||||
vvp_errors += draw_eval_object(expr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
ivl_signal_basename(port), dtype);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_send_function_argument(ivl_signal_t port)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
switch (dtype) {
|
||||
case IVL_VT_BOOL:
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
case IVL_VT_LOGIC:
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n",
|
||||
port, ivl_signal_width(port));
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
|
||||
break;
|
||||
case IVL_VT_CLASS:
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
|
||||
break;
|
||||
case IVL_VT_DARRAY:
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
@@ -111,13 +113,20 @@ static void draw_ufunc_preamble(ivl_expr_t expr)
|
||||
fprintf(vvp_out, " %%alloc S_%p;\n", def);
|
||||
}
|
||||
|
||||
/* evaluate the expressions and send the results to the
|
||||
function ports. */
|
||||
/* Evaluate the expressions and send the results to the
|
||||
function ports. Do this in two passes - evaluate,
|
||||
then send - this avoids the function input variables
|
||||
being overwritten if the same (non-automatic) function
|
||||
is called in one of the expressions. */
|
||||
|
||||
assert(ivl_expr_parms(expr) == (ivl_scope_ports(def)-1));
|
||||
for (idx = 0 ; idx < ivl_expr_parms(expr) ; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx+1);
|
||||
draw_function_argument(port, ivl_expr_parm(expr, idx));
|
||||
draw_eval_function_argument(port, ivl_expr_parm(expr, idx));
|
||||
}
|
||||
for (idx = ivl_expr_parms(expr) ; idx > 0 ; idx -= 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx);
|
||||
draw_send_function_argument(port);
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
struct args_info {
|
||||
char*text;
|
||||
/* True ('s' or 'u' if this argument is a calculated vec4. */
|
||||
|
||||
+27
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2015 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
|
||||
@@ -28,7 +28,6 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
ivl_expr_t size_expr = ivl_expr_oper1(ex);
|
||||
ivl_expr_t init_expr = ivl_expr_oper2(ex);
|
||||
draw_eval_expr_into_integer(size_expr, size_reg);
|
||||
clr_word(size_reg);
|
||||
|
||||
// The new function has a net_type that contains the details
|
||||
// of the type.
|
||||
@@ -39,6 +38,7 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
assert(element_type);
|
||||
|
||||
switch (ivl_type_base(element_type)) {
|
||||
int msb, lsb, wid;
|
||||
case IVL_VT_REAL:
|
||||
// REAL objects are not packable.
|
||||
assert(ivl_type_packed_dimensions(element_type) == 0);
|
||||
@@ -53,19 +53,30 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
// bool objects are vectorable, but for now only support
|
||||
// a single dimensions.
|
||||
assert(ivl_type_packed_dimensions(element_type) == 1);
|
||||
int msb = ivl_type_packed_msb(element_type, 0);
|
||||
int lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
int wid = msb>=lsb? msb - lsb : lsb - msb;
|
||||
msb = ivl_type_packed_msb(element_type, 0);
|
||||
lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
wid = msb>=lsb? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
||||
fprintf(vvp_out, " %%new/darray %u, \"%sb%d\";\n", size_reg,
|
||||
ivl_type_signed(element_type) ? "s" : "", wid);
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
// logic objects are vectorable, but for now only support
|
||||
// a single dimensions.
|
||||
assert(ivl_type_packed_dimensions(element_type) == 1);
|
||||
msb = ivl_type_packed_msb(element_type, 0);
|
||||
lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
wid = msb>=lsb? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
fprintf(vvp_out, " %%new/darray %u, \"%sv%d\";\n", size_reg,
|
||||
ivl_type_signed(element_type) ? "s" : "", wid);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
clr_word(size_reg);
|
||||
|
||||
if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) {
|
||||
unsigned idx;
|
||||
@@ -109,12 +120,15 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
unsigned wid;
|
||||
switch (ivl_type_base(element_type)) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
wid = width_of_packed_type(element_type);
|
||||
draw_eval_vec4(init_expr);
|
||||
resize_vec4_wid(init_expr, wid);
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
|
||||
draw_eval_vec4(init_expr);
|
||||
fprintf(vvp_out, " %%parti/%c %u, %ld, 6;\n",
|
||||
ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid);
|
||||
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1);
|
||||
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
|
||||
fprintf(vvp_out, " %%pop/vec4 1;\n");
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
@@ -187,11 +201,12 @@ static int eval_object_property(ivl_expr_t expr)
|
||||
|
||||
static int eval_object_shallowcopy(ivl_expr_t ex)
|
||||
{
|
||||
int errors = 0;
|
||||
ivl_expr_t dest = ivl_expr_oper1(ex);
|
||||
ivl_expr_t src = ivl_expr_oper2(ex);
|
||||
|
||||
draw_eval_object(dest);
|
||||
draw_eval_object(src);
|
||||
errors += draw_eval_object(dest);
|
||||
errors += draw_eval_object(src);
|
||||
|
||||
/* The %scopy opcode pops the top of the object stack as the
|
||||
source object, and shallow-copies it to the new top, the
|
||||
@@ -199,7 +214,7 @@ static int eval_object_shallowcopy(ivl_expr_t ex)
|
||||
the stack. */
|
||||
fprintf(vvp_out, " %%scopy;\n");
|
||||
|
||||
return 0;
|
||||
return errors;
|
||||
}
|
||||
|
||||
static int eval_object_signal(ivl_expr_t expr)
|
||||
|
||||
+29
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2013-2015 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
|
||||
@@ -643,16 +643,16 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr)
|
||||
// the stack and replace it with the result of the shift.
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
case 'l': /* << */
|
||||
fprintf(vvp_out, " %%shiftl %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftl %d;\n", use_index_reg);
|
||||
break;
|
||||
case 'r': /* >> */
|
||||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
|
||||
break;
|
||||
case 'R': /* >>> */
|
||||
if (ivl_expr_signed(le))
|
||||
fprintf(vvp_out, " %%shiftr/s %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftr/s %d;\n", use_index_reg);
|
||||
else
|
||||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -790,10 +790,10 @@ static void draw_concat_number_vec4(ivl_expr_t expr, int as_concati)
|
||||
|
||||
if (accum) {
|
||||
if (count_pushi) {
|
||||
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %u;\n",
|
||||
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %d;\n",
|
||||
val0, valx, accum);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %u;\n",
|
||||
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %d;\n",
|
||||
val0, valx, accum);
|
||||
}
|
||||
}
|
||||
@@ -807,16 +807,27 @@ static void draw_concat_vec4(ivl_expr_t expr)
|
||||
/* This is the number of expressions that go into the
|
||||
concatenation. */
|
||||
unsigned num_sube = ivl_expr_parms(expr);
|
||||
unsigned sub_idx;
|
||||
unsigned sub_idx = 0;
|
||||
ivl_expr_t sube;
|
||||
|
||||
assert(num_sube > 0);
|
||||
|
||||
/* Start with the most-significant bits. */
|
||||
draw_eval_vec4(ivl_expr_parm(expr, 0));
|
||||
sube = ivl_expr_parm(expr, sub_idx);
|
||||
draw_eval_vec4(sube);
|
||||
/* Evaluate, but skip any zero replication expressions at the
|
||||
* head of this concatenation. */
|
||||
while ((ivl_expr_type(sube) == IVL_EX_CONCAT) &&
|
||||
(ivl_expr_repeat(sube) == 0)) {
|
||||
fprintf(vvp_out, " %%pop/vec4 1; skip zero replication\n");
|
||||
sub_idx += 1;
|
||||
sube = ivl_expr_parm(expr, sub_idx);
|
||||
draw_eval_vec4(sube);
|
||||
}
|
||||
|
||||
for (sub_idx = 1 ; sub_idx < num_sube ; sub_idx += 1) {
|
||||
for ( sub_idx += 1 ; sub_idx < num_sube ; sub_idx += 1) {
|
||||
/* Concatenate progressively lower parts. */
|
||||
ivl_expr_t sube = ivl_expr_parm(expr, sub_idx);
|
||||
sube = ivl_expr_parm(expr, sub_idx);
|
||||
|
||||
/* Special case: The next expression is a NUMBER that
|
||||
can be concatenated using %concati/vec4
|
||||
@@ -827,6 +838,13 @@ static void draw_concat_vec4(ivl_expr_t expr)
|
||||
}
|
||||
|
||||
draw_eval_vec4(sube);
|
||||
/* Evaluate, but skip any zero replication expressions in the
|
||||
* rest of this concatenation. */
|
||||
if ((ivl_expr_type(sube) == IVL_EX_CONCAT) &&
|
||||
(ivl_expr_repeat(sube) == 0)) {
|
||||
fprintf(vvp_out, " %%pop/vec4 1; skip zero replication\n");
|
||||
continue;
|
||||
}
|
||||
fprintf(vvp_out, " %%concat/vec4; draw_concat_vec4\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
static ivl_signal_t find_path_source_port(ivl_delaypath_t path)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
+33
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2011-2015 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
|
||||
@@ -22,11 +22,6 @@
|
||||
# include <assert.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These functions handle the blocking assignment. Use the %set
|
||||
* instruction to perform the actual assignment, and calculate any
|
||||
@@ -143,7 +138,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
|
||||
draw_eval_vec4(part_off_ex);
|
||||
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.part_select_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%dup/vec4;\n");
|
||||
fprintf(vvp_out, " %%ix/vec4 %u;\n", slice->u_.part_select_dynamic.word_idx_reg);
|
||||
fprintf(vvp_out, " %%ix/vec4 %d;\n", slice->u_.part_select_dynamic.word_idx_reg);
|
||||
fprintf(vvp_out, " %%part/u %u;\n", wid);
|
||||
|
||||
} else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {
|
||||
@@ -167,7 +162,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
|
||||
slice->u_.memory_word_dynamic.x_flag = allocate_flag();
|
||||
|
||||
draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%load/vec4a v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
|
||||
} else {
|
||||
@@ -263,7 +258,7 @@ static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
|
||||
break;
|
||||
|
||||
case SLICE_MEMORY_WORD_DYNAMIC:
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%flag_mov 4, %u;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%store/vec4a v%p, %d, 0;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
clr_flag(slice->u_.memory_word_dynamic.x_flag);
|
||||
@@ -381,7 +376,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
|
||||
/* Note that flag4 is set by the eval above. */
|
||||
assert(lsig);
|
||||
if (ivl_signal_type(lsig)==IVL_SIT_UWIRE) {
|
||||
fprintf(vvp_out, " %%force/vec4/off v%p_0, %u;\n",
|
||||
fprintf(vvp_out, " %%force/vec4/off v%p_0, %d;\n",
|
||||
lsig, offset_index);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n",
|
||||
@@ -397,7 +392,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
|
||||
assert(!lsig);
|
||||
ivl_type_t sub_type = draw_lval_expr(nest);
|
||||
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
||||
fprintf(vvp_out, " %%store/prop/v %u, %u;\n",
|
||||
fprintf(vvp_out, " %%store/prop/v %d, %u;\n",
|
||||
ivl_lval_property_idx(lval), lwid);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
@@ -444,11 +439,34 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||
fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
|
||||
|
||||
} else if (ivl_expr_value(rval) == IVL_VT_STRING) {
|
||||
/* Special case: vector to string casting */
|
||||
/* Special case: string to vector casting */
|
||||
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
||||
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
|
||||
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
|
||||
ivl_expr_signal(rval), ivl_lval_sig(lval));
|
||||
if (slices) free(slices);
|
||||
return 0;
|
||||
|
||||
} else if (ivl_expr_value(rval) == IVL_VT_DARRAY) {
|
||||
/* Special case: dynamic array to vector casting */
|
||||
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
||||
void*rval_addr = NULL;
|
||||
|
||||
/* Even more special case: function call returning dynamic array */
|
||||
if(ivl_expr_type(rval) == IVL_EX_UFUNC) {
|
||||
rval_addr = ivl_scope_port(ivl_expr_def(rval), 0);
|
||||
draw_ufunc_object(rval);
|
||||
/* We do not need to store the result, it is going to be
|
||||
converted to vector quite soon. */
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0; drop the result\n");
|
||||
} else {
|
||||
rval_addr = ivl_expr_signal(rval);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
|
||||
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
|
||||
rval_addr, ivl_lval_sig(lval));
|
||||
if (slices) free(slices);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
@@ -532,8 +550,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||
break;
|
||||
}
|
||||
|
||||
if (slices)
|
||||
free(slices);
|
||||
if (slices) free(slices);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -868,7 +885,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||
expression to the assignment is of an entire
|
||||
array object. */
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
@@ -882,7 +899,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||
|
||||
/* The property is a class object. */
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
errors += draw_eval_object(rval);
|
||||
if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 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
|
||||
@@ -59,7 +59,10 @@ __inline__ static void draw_execute_header(ivl_design_t des)
|
||||
{
|
||||
const char*cp = ivl_design_flag(des, "VVP_EXECUTABLE");
|
||||
if (cp) {
|
||||
fprintf(vvp_out, "#! %s\n", cp);
|
||||
const char *extra_args = ivl_design_flag(des, "VVP_EXTRA_ARGS");
|
||||
if (!extra_args)
|
||||
extra_args = "";
|
||||
fprintf(vvp_out, "#! %s%s\n", cp, extra_args);
|
||||
#if !defined(__MINGW32__)
|
||||
fchmod(fileno(vvp_out), 0755);
|
||||
#endif
|
||||
|
||||
@@ -23,11 +23,6 @@
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
extern int debug_draw;
|
||||
|
||||
/*
|
||||
|
||||
+44
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2015 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
|
||||
@@ -21,10 +21,7 @@
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
# include <stdbool.h>
|
||||
|
||||
static int show_statement(ivl_statement_t net, ivl_scope_t sscope);
|
||||
|
||||
@@ -114,14 +111,12 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
ivl_expr_t part_off_ex,
|
||||
unsigned nevents)
|
||||
{
|
||||
unsigned skip_assign = transient_id++;
|
||||
int word_ix_reg = 3;
|
||||
int part_off_reg = 0;
|
||||
int delay_index;
|
||||
unsigned long part_off = 0;
|
||||
|
||||
int error_flag = allocate_flag();
|
||||
fprintf(vvp_out, " %%flag_set/imm %d, 0;\n", error_flag);
|
||||
|
||||
/* Figure the constant part offset, if possible. If we can do
|
||||
so, then forget about the expression and use the calculated
|
||||
@@ -143,11 +138,13 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
|
||||
/* Calculate array word index into word index register */
|
||||
draw_eval_expr_into_integer(word_ix, word_ix_reg);
|
||||
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
|
||||
|
||||
if (part_off_ex) {
|
||||
part_off_reg = allocate_word();
|
||||
/* Save the index calculation error flag to a global. */
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
|
||||
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
|
||||
/* Add the error state of the part select to the global. */
|
||||
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
|
||||
|
||||
} else if (part_off != 0) {
|
||||
@@ -158,26 +155,35 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
part_off_reg, part_off);
|
||||
}
|
||||
|
||||
/* Calculated delay... */
|
||||
if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
delay_index = allocate_word();
|
||||
/* If needed save the index calculation error flag. */
|
||||
if (! part_off_ex) {
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
|
||||
}
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
if (word_ix_reg != 3) {
|
||||
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
||||
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
|
||||
clr_word(word_ix_reg);
|
||||
}
|
||||
/* Restore the error state since an undefined delay is okay. */
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
|
||||
lsig, part_off_reg, delay_index);
|
||||
|
||||
clr_word(delay_index);
|
||||
|
||||
/* Event control delay... */
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
/* If needed use the global error state. */
|
||||
if (part_off_ex) {
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
}
|
||||
fprintf(vvp_out, " %%assign/vec4/a/e v%p, %d;\n", lsig, part_off_reg);
|
||||
|
||||
/* Constant delay... */
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||
|
||||
@@ -185,15 +191,18 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu; Constant delay\n",
|
||||
delay_index, low_d, hig_d);
|
||||
if (word_ix_reg != 3) {
|
||||
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
||||
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
|
||||
clr_word(word_ix_reg);
|
||||
}
|
||||
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %u;\n",
|
||||
/* If needed use the global error state. */
|
||||
if (part_off_ex) {
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
}
|
||||
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
|
||||
lsig, part_off_reg, delay_index);
|
||||
clr_word(delay_index);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
|
||||
|
||||
clr_flag(error_flag);
|
||||
@@ -1043,7 +1052,14 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
||||
|
||||
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
||||
assert(ivl_signal_dimensions(rsig) != 0);
|
||||
assert(number_is_immediate(rword_idx, IMM_WID, 0));
|
||||
if (!number_is_immediate(rword_idx, IMM_WID, 0)) {
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: procedural continuous "
|
||||
"assignments are not yet fully supported. The RHS of "
|
||||
"this assignment will only be evaluated once, at the "
|
||||
"time the assignment statement is executed.\n",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net));
|
||||
return;
|
||||
}
|
||||
/* An out-of-range or undefined index will have been
|
||||
converted to a canonical offset of 1'bx. Skip the
|
||||
assignment in this case. */
|
||||
@@ -1321,7 +1337,7 @@ static int show_stmt_do_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
the result. If the expression evaluates to true, then
|
||||
branch to the top label. */
|
||||
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
|
||||
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u;\n",
|
||||
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %d;\n",
|
||||
thread_count, top_label, use_flag);
|
||||
clr_flag(use_flag);
|
||||
|
||||
@@ -1665,7 +1681,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
the result. If the expression evaluates to false, then
|
||||
branch to the out label. */
|
||||
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %u;\n",
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %d;\n",
|
||||
thread_count, out_label, use_flag);
|
||||
clr_flag(use_flag);
|
||||
|
||||
@@ -1696,19 +1712,16 @@ static int show_delete_method(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_push_frontback_method(ivl_statement_t net)
|
||||
static int show_push_frontback_method(ivl_statement_t net, bool is_front)
|
||||
{
|
||||
const char*stmt_name = ivl_stmt_name(net);
|
||||
|
||||
show_stmt_file_line(net, "queue: push_back");
|
||||
|
||||
const char*type_code = "?";
|
||||
if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0)
|
||||
const char*type_code;
|
||||
if (is_front) {
|
||||
show_stmt_file_line(net, "queue: push_front");
|
||||
type_code = "qf";
|
||||
else if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0)
|
||||
} else {
|
||||
show_stmt_file_line(net, "queue: push_back");
|
||||
type_code = "qb";
|
||||
else
|
||||
type_code = "??";
|
||||
}
|
||||
|
||||
unsigned parm_count = ivl_stmt_parm_count(net);
|
||||
if (parm_count != 2)
|
||||
@@ -1750,10 +1763,10 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
return show_delete_method(net);
|
||||
|
||||
if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0)
|
||||
return show_push_frontback_method(net);
|
||||
return show_push_frontback_method(net, true);
|
||||
|
||||
if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0)
|
||||
return show_push_frontback_method(net);
|
||||
return show_push_frontback_method(net, false);
|
||||
|
||||
show_stmt_file_line(net, "System task call.");
|
||||
|
||||
|
||||
+8
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2015 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
|
||||
@@ -1737,10 +1737,14 @@ static void draw_lpm_ff(ivl_lpm_t net)
|
||||
assert(ivl_lpm_sync_set(net) == 0);
|
||||
|
||||
if (ivl_lpm_async_clr(net)) {
|
||||
assert(! ivl_lpm_async_set(net));
|
||||
if (ivl_lpm_async_set(net)) {
|
||||
fprintf(stderr, "%s:%u:vvp.tgt: sorry: No support for a D-ff "
|
||||
"with both an async. set and clear.\n",
|
||||
ivl_lpm_file(net), ivl_lpm_lineno(net));
|
||||
vvp_errors += 1;
|
||||
}
|
||||
fprintf(vvp_out, "L_%p .dff/aclr ", net);
|
||||
} else if (ivl_lpm_async_set(net)) {
|
||||
assert(! ivl_lpm_async_clr(net));
|
||||
fprintf(vvp_out, "L_%p .dff/aset ", net);
|
||||
} else {
|
||||
fprintf(vvp_out, "L_%p .dff ", net);
|
||||
@@ -2328,7 +2332,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
draw_task_definition(net);
|
||||
|
||||
if (ivl_scope_type(net) == IVL_SCT_FUNCTION)
|
||||
draw_func_definition(net);
|
||||
vvp_errors += draw_func_definition(net);
|
||||
|
||||
ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#norootforbuild
|
||||
#
|
||||
%define rev_date 20141205
|
||||
%define rev_date 20150513
|
||||
# Normally, the suff-ix is %nil, meaning the suffix is to not be used.
|
||||
# But if the builder wants to make a suffixed package, he may set this
|
||||
# to a value (i.e. -test) to cause suffixes to be put in all the right
|
||||
|
||||
+3
-1
@@ -780,7 +780,9 @@ ostream& operator<< (ostream&o, const verinum&v)
|
||||
|
||||
/* If the number is fully defined (no x or z) then print it
|
||||
out as a decimal number. */
|
||||
if (v.is_defined() && v.len() <= 8*sizeof(long)) {
|
||||
unsigned dec_len = 8*sizeof(int); /* avoid 32/64 bit differences. */
|
||||
if (! v.has_sign()) dec_len -= 1; /* an unsigned number. */
|
||||
if (v.is_defined() && v.len() <= dec_len) {
|
||||
if (v.has_sign())
|
||||
o << "'sd" << v.as_long();
|
||||
else
|
||||
|
||||
+40
-1
@@ -28,7 +28,7 @@ using namespace std;
|
||||
|
||||
Architecture::Architecture(perm_string name, const ActiveScope&ref,
|
||||
list<Architecture::Statement*>&s)
|
||||
: Scope(ref), name_(name)
|
||||
: Scope(ref), name_(name), cur_component_(NULL)
|
||||
{
|
||||
statements_.splice(statements_.end(), s);
|
||||
}
|
||||
@@ -39,6 +39,34 @@ Architecture::~Architecture()
|
||||
ScopeBase::cleanup();
|
||||
}
|
||||
|
||||
bool Architecture::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const
|
||||
{
|
||||
if(Scope::find_constant(by_name, typ, exp))
|
||||
return true;
|
||||
|
||||
// Check generics in components
|
||||
if(cur_component_) {
|
||||
std::map<perm_string,ComponentBase*>::const_iterator c = new_components_.find(cur_component_->component_name());
|
||||
if(c == new_components_.end())
|
||||
c = old_components_.find(cur_component_->component_name());
|
||||
|
||||
assert(c != old_components_.end());
|
||||
ComponentBase*base = c->second;
|
||||
|
||||
const InterfacePort*generic = base->find_generic(by_name);
|
||||
if(!generic)
|
||||
return false; // apparently there is no such generic in the component
|
||||
|
||||
Expression*e = cur_component_->find_generic_map(by_name);
|
||||
|
||||
typ = generic->type;
|
||||
exp = e ? e : generic->expr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Architecture::push_genvar_type(perm_string gname, const VType*gtype)
|
||||
{
|
||||
genvar_type_t tmp;
|
||||
@@ -191,6 +219,17 @@ ComponentInstantiation::~ComponentInstantiation()
|
||||
}
|
||||
}
|
||||
|
||||
Expression*ComponentInstantiation::find_generic_map(perm_string by_name) const
|
||||
{
|
||||
map<perm_string,Expression*>::const_iterator p = generic_map_.find(by_name);
|
||||
|
||||
if(p == generic_map_.end())
|
||||
return NULL;
|
||||
|
||||
return p->second;
|
||||
}
|
||||
|
||||
|
||||
ProcessStatement::ProcessStatement(perm_string iname,
|
||||
std::list<Expression*>*sensitivity_list,
|
||||
std::list<SequentialStmt*>*statements_list)
|
||||
|
||||
+14
-5
@@ -25,7 +25,7 @@
|
||||
# include <list>
|
||||
# include <map>
|
||||
|
||||
class ComponentBase;
|
||||
class ComponentInstantiation;
|
||||
class Entity;
|
||||
class Expression;
|
||||
class ExpName;
|
||||
@@ -54,10 +54,6 @@ class Architecture : public Scope, public LineInfo {
|
||||
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||
virtual int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
virtual void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
|
||||
private: // Not implemented
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -69,6 +65,10 @@ class Architecture : public Scope, public LineInfo {
|
||||
|
||||
perm_string get_name() const { return name_; }
|
||||
|
||||
// Sets the currently processed component (to be able to reach its parameters).
|
||||
void set_cur_component(ComponentInstantiation*component) { cur_component_ = component; }
|
||||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const;
|
||||
|
||||
// Elaborate this architecture in the context of the given entity.
|
||||
int elaborate(Entity*entity);
|
||||
|
||||
@@ -110,6 +110,9 @@ class Architecture : public Scope, public LineInfo {
|
||||
};
|
||||
std::list<genvar_emit_t> genvar_emit_stack_;
|
||||
|
||||
// Currently processed component (or NULL if none).
|
||||
ComponentInstantiation*cur_component_;
|
||||
|
||||
private: // Not implemented
|
||||
};
|
||||
|
||||
@@ -198,6 +201,12 @@ class ComponentInstantiation : public Architecture::Statement {
|
||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
virtual void dump(ostream&out, int indent =0) const;
|
||||
|
||||
// Returns the expression that initializes a generic (or NULL if not found).
|
||||
Expression*find_generic_map(perm_string by_name) const;
|
||||
|
||||
inline perm_string instance_name() const { return iname_; }
|
||||
inline perm_string component_name() const { return cname_; }
|
||||
|
||||
private:
|
||||
perm_string iname_;
|
||||
perm_string cname_;
|
||||
|
||||
@@ -92,15 +92,16 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
||||
return 1;
|
||||
}
|
||||
|
||||
arc->set_cur_component(this);
|
||||
|
||||
for (map<perm_string,Expression*>::const_iterator cur = generic_map_.begin()
|
||||
; cur != generic_map_.end() ; ++cur) {
|
||||
// check if generic from component instantiation
|
||||
// exists in the component declaration
|
||||
const InterfacePort*iparm = base->find_generic(cur->first);
|
||||
if (iparm == 0) {
|
||||
cerr << get_fileline() << ": error: No generic " << cur->first
|
||||
cerr << get_fileline() << ": warning: No generic " << cur->first
|
||||
<< " in component " << cname_ << "." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -134,6 +135,8 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
||||
cur->second->elaborate_expr(ent, arc, iport->type);
|
||||
}
|
||||
|
||||
arc->set_cur_component(NULL);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -368,9 +371,9 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
for (list<Expression*>::const_iterator cur = rval_.begin()
|
||||
for (list<Expression*>::iterator cur = rval_.begin()
|
||||
; cur != rval_.end() ; ++cur) {
|
||||
(*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
||||
+12
-6
@@ -70,12 +70,12 @@ int Architecture::emit(ostream&out, Entity*entity)
|
||||
// of the full definition.
|
||||
|
||||
typedef_context_t typedef_ctx;
|
||||
for (map<perm_string,const VType*>::iterator cur = use_types_.begin()
|
||||
; cur != use_types_.end() ; ++cur) {
|
||||
//for (map<perm_string,const VType*>::iterator cur = use_types_.begin()
|
||||
//; cur != use_types_.end() ; ++cur) {
|
||||
|
||||
if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
|
||||
errors += def->emit_typedef(out, typedef_ctx);
|
||||
}
|
||||
//if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
|
||||
//errors += def->emit_typedef(out, typedef_ctx);
|
||||
//}
|
||||
for (map<perm_string,const VType*>::iterator cur = cur_types_.begin()
|
||||
; cur != cur_types_.end() ; ++cur) {
|
||||
|
||||
@@ -103,7 +103,9 @@ int Architecture::emit(ostream&out, Entity*entity)
|
||||
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||
errors += cur->second->emit_package(out);
|
||||
// Do not emit unbounded functions, we will just need fixed instances later
|
||||
if(!cur->second->unbounded())
|
||||
errors += cur->second->emit_package(out);
|
||||
}
|
||||
|
||||
for (list<Architecture::Statement*>::iterator cur = statements_.begin()
|
||||
@@ -146,6 +148,8 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
const char*comma = "";
|
||||
int errors = 0;
|
||||
|
||||
arc->set_cur_component(this);
|
||||
|
||||
out << cname_;
|
||||
if (! generic_map_.empty()) {
|
||||
out << " #(";
|
||||
@@ -175,6 +179,8 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
}
|
||||
out << ");" << endl;
|
||||
|
||||
arc->set_cur_component(NULL);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014 CERN / Maciej Suminski (maciej.suminski@cern.ch)
|
||||
* Copyright (c) 2014 CERN
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
||||
@@ -92,7 +92,8 @@ int Entity::elaborate_generic_exprs_()
|
||||
for (vector<InterfacePort*>::const_iterator cur = parms_.begin()
|
||||
; cur != parms_.end() ; ++cur) {
|
||||
InterfacePort*curp = *cur;
|
||||
curp->expr->elaborate_expr(this, 0, curp->type);
|
||||
if(curp->expr)
|
||||
curp->expr->elaborate_expr(this, 0, curp->type);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -50,9 +50,11 @@ int Entity::emit(ostream&out)
|
||||
const InterfacePort*curp = *cur;
|
||||
if (cur != parms_.begin())
|
||||
out << ", ";
|
||||
out << "parameter \\" << curp->name << " = ";
|
||||
ivl_assert(*this, curp->expr);
|
||||
errors += curp->expr->emit(out, this, 0);
|
||||
out << "parameter \\" << curp->name << " ";
|
||||
if(curp->expr) {
|
||||
out << "= ";
|
||||
errors += curp->expr->emit(out, this, 0);
|
||||
}
|
||||
}
|
||||
out << ") ";
|
||||
}
|
||||
|
||||
+51
-23
@@ -18,40 +18,68 @@
|
||||
*/
|
||||
|
||||
# include "entity.h"
|
||||
# include "expression.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ComponentBase::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << " component " << name_ << " is" << endl;
|
||||
fd << " port(" << endl;
|
||||
|
||||
vector<InterfacePort*>::const_iterator cur = ports_.begin();
|
||||
while (cur != ports_.end()) {
|
||||
InterfacePort*item = *cur;
|
||||
++cur;
|
||||
if(!parms_.empty()) {
|
||||
fd << " generic(" << endl;
|
||||
|
||||
fd << " " << item->name << " : ";
|
||||
switch (item->mode) {
|
||||
case PORT_NONE:
|
||||
fd << "???? ";
|
||||
break;
|
||||
case PORT_IN:
|
||||
fd << "in ";
|
||||
break;
|
||||
case PORT_OUT:
|
||||
fd << "out ";
|
||||
break;
|
||||
}
|
||||
for(vector<InterfacePort*>::const_iterator it = parms_.begin();
|
||||
it != parms_.end(); ++it) {
|
||||
const InterfacePort*parm = *it;
|
||||
|
||||
item->type->write_to_stream(fd);
|
||||
if(it != parms_.begin())
|
||||
fd << ";";
|
||||
|
||||
if (cur != ports_.end())
|
||||
fd << ";" << endl;
|
||||
else
|
||||
fd << endl;
|
||||
fd << " " << parm->name << " : ";
|
||||
parm->type->write_to_stream(fd);
|
||||
|
||||
if(parm->expr) {
|
||||
fd << " := ";
|
||||
parm->expr->write_to_stream(fd);
|
||||
}
|
||||
|
||||
fd << endl;
|
||||
}
|
||||
|
||||
fd << " );" << endl;
|
||||
}
|
||||
|
||||
fd << " );" << endl;
|
||||
if(!ports_.empty()) {
|
||||
fd << " port(" << endl;
|
||||
|
||||
vector<InterfacePort*>::const_iterator cur = ports_.begin();
|
||||
while (cur != ports_.end()) {
|
||||
InterfacePort*item = *cur;
|
||||
++cur;
|
||||
|
||||
fd << " " << item->name << " : ";
|
||||
switch (item->mode) {
|
||||
case PORT_NONE:
|
||||
fd << "???? ";
|
||||
break;
|
||||
case PORT_IN:
|
||||
fd << "in ";
|
||||
break;
|
||||
case PORT_OUT:
|
||||
fd << "out ";
|
||||
break;
|
||||
}
|
||||
|
||||
item->type->write_to_stream(fd);
|
||||
|
||||
if (cur != ports_.end())
|
||||
fd << ";" << endl;
|
||||
else
|
||||
fd << endl;
|
||||
}
|
||||
|
||||
fd << " );" << endl;
|
||||
}
|
||||
fd << " end component;" << endl;
|
||||
}
|
||||
|
||||
+147
-7
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2014 / Stephen Williams (steve@icarus.com),
|
||||
* Maciej Suminski (maciej.suminski@cern.ch)
|
||||
* Copyright CERN 2012-2015 / Stephen Williams (steve@icarus.com),
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
# include "expression.h"
|
||||
# include "subprogram.h"
|
||||
# include "parse_types.h"
|
||||
# include "scope.h"
|
||||
# include <iostream>
|
||||
@@ -63,6 +64,11 @@ ExpAttribute::~ExpAttribute()
|
||||
delete base_;
|
||||
}
|
||||
|
||||
Expression*ExpAttribute::clone() const
|
||||
{
|
||||
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
|
||||
}
|
||||
|
||||
ExpBinary::ExpBinary(Expression*op1, Expression*op2)
|
||||
: operand1_(op1), operand2_(op2)
|
||||
{
|
||||
@@ -112,6 +118,23 @@ ExpAggregate::~ExpAggregate()
|
||||
delete elements_[idx];
|
||||
}
|
||||
|
||||
Expression* ExpAggregate::clone() const
|
||||
{
|
||||
std::list<element_t*>*new_elements = NULL;
|
||||
|
||||
if(!elements_.empty()) {
|
||||
new_elements = new std::list<element_t*>();
|
||||
for(std::vector<element_t*>::const_iterator it = elements_.begin();
|
||||
it != elements_.end(); ++it) {
|
||||
new_elements->push_back(new element_t(**it));
|
||||
}
|
||||
}
|
||||
|
||||
assert(aggregate_.empty()); // cloning should not happen after elab
|
||||
|
||||
return new ExpAggregate(new_elements);
|
||||
}
|
||||
|
||||
ExpAggregate::choice_t::choice_t(Expression*exp)
|
||||
: expr_(exp)
|
||||
{
|
||||
@@ -126,6 +149,15 @@ ExpAggregate::choice_t::choice_t(prange_t*rang)
|
||||
{
|
||||
}
|
||||
|
||||
ExpAggregate::choice_t::choice_t(const choice_t&other)
|
||||
{
|
||||
if(Expression*e = other.expr_.get())
|
||||
expr_.reset(e->clone());
|
||||
|
||||
if(other.range_.get())
|
||||
range_.reset(new prange_t(*other.range_.get()));
|
||||
}
|
||||
|
||||
ExpAggregate::choice_t::~choice_t()
|
||||
{
|
||||
}
|
||||
@@ -159,6 +191,18 @@ ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
|
||||
}
|
||||
}
|
||||
|
||||
ExpAggregate::element_t::element_t(const ExpAggregate::element_t&other)
|
||||
{
|
||||
fields_.reserve(other.fields_.size());
|
||||
|
||||
for(std::vector<choice_t*>::const_iterator it = other.fields_.begin();
|
||||
it != other.fields_.end(); ++it) {
|
||||
fields_.push_back(*it);
|
||||
}
|
||||
|
||||
val_ = other.val_->clone();
|
||||
}
|
||||
|
||||
ExpAggregate::element_t::~element_t()
|
||||
{
|
||||
for (size_t idx = 0 ; idx < fields_.size() ; idx += 1)
|
||||
@@ -235,12 +279,46 @@ ExpConditional::~ExpConditional()
|
||||
}
|
||||
}
|
||||
|
||||
Expression*ExpConditional::clone() const
|
||||
{
|
||||
std::list<Expression*>*new_true_clause = NULL;
|
||||
if(!true_clause_.empty()) {
|
||||
new_true_clause = new std::list<Expression*>();
|
||||
|
||||
for(std::list<Expression*>::const_iterator it = true_clause_.begin();
|
||||
it != true_clause_.end(); ++it) {
|
||||
new_true_clause->push_back((*it)->clone());
|
||||
}
|
||||
}
|
||||
|
||||
std::list<else_t*>*new_else_clause = NULL;
|
||||
if(!else_clause_.empty()) {
|
||||
new_else_clause = new std::list<else_t*>();
|
||||
|
||||
for(std::list<else_t*>::const_iterator it = else_clause_.begin();
|
||||
it != else_clause_.end(); ++it) {
|
||||
new_else_clause->push_back(new else_t(**it));
|
||||
}
|
||||
}
|
||||
|
||||
return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause);
|
||||
}
|
||||
|
||||
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
|
||||
: cond_(cond)
|
||||
{
|
||||
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
||||
}
|
||||
|
||||
ExpConditional::else_t::else_t(const else_t&other)
|
||||
{
|
||||
cond_ = other.cond_->clone();
|
||||
for(std::list<Expression*>::const_iterator it = other.true_clause_.begin();
|
||||
it != other.true_clause_.end(); ++it) {
|
||||
true_clause_.push_back((*it)->clone());
|
||||
}
|
||||
}
|
||||
|
||||
ExpConditional::else_t::~else_t()
|
||||
{
|
||||
delete cond_;
|
||||
@@ -283,6 +361,27 @@ ExpFunc::~ExpFunc()
|
||||
delete argv_[idx];
|
||||
}
|
||||
|
||||
Expression*ExpFunc::clone() const {
|
||||
std::list<Expression*>*new_args = NULL;
|
||||
|
||||
if(!argv_.empty()) {
|
||||
new_args = new std::list<Expression*>();
|
||||
for(std::vector<Expression*>::const_iterator it = argv_.begin();
|
||||
it != argv_.end(); ++it)
|
||||
new_args->push_back((*it)->clone());
|
||||
}
|
||||
|
||||
ExpFunc*f = new ExpFunc(name_, new_args);
|
||||
f->def_ = def_;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
const VType* ExpFunc::func_ret_type() const
|
||||
{
|
||||
return def_ ? def_->peek_return_type() : NULL;
|
||||
}
|
||||
|
||||
ExpInteger::ExpInteger(int64_t val)
|
||||
: value_(val)
|
||||
{
|
||||
@@ -351,11 +450,6 @@ ExpName::~ExpName()
|
||||
delete index_;
|
||||
}
|
||||
|
||||
const char* ExpName::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
bool ExpName::symbolic_compare(const Expression*that) const
|
||||
{
|
||||
const ExpName*that_name = dynamic_cast<const ExpName*> (that);
|
||||
@@ -386,6 +480,28 @@ void ExpName::set_range(Expression*msb, Expression*lsb)
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
int ExpName::index_t::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << "(";
|
||||
|
||||
if(idx_ && size_) {
|
||||
errors += idx_->emit(out, ent, scope);
|
||||
out << "*";
|
||||
errors += size_->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
if(offset_) {
|
||||
if(idx_ && size_)
|
||||
out << "+";
|
||||
errors += offset_->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
ExpRelation::ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2)
|
||||
: ExpBinary(op1, op2), fun_(ty)
|
||||
{
|
||||
@@ -395,6 +511,11 @@ ExpRelation::~ExpRelation()
|
||||
{
|
||||
}
|
||||
|
||||
ExpShift::ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2)
|
||||
: ExpBinary(op1, op2), shift_(op)
|
||||
{
|
||||
}
|
||||
|
||||
ExpString::ExpString(const char* value)
|
||||
: value_(strlen(value))
|
||||
{
|
||||
@@ -423,3 +544,22 @@ ExpUNot::ExpUNot(Expression*op1)
|
||||
ExpUNot::~ExpUNot()
|
||||
{
|
||||
}
|
||||
|
||||
ExpCast::ExpCast(Expression*base, const VType*type) :
|
||||
base_(base), type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
ExpCast::~ExpCast()
|
||||
{
|
||||
}
|
||||
|
||||
ExpNew::ExpNew(Expression*size) :
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
ExpNew::~ExpNew()
|
||||
{
|
||||
delete size_;
|
||||
}
|
||||
|
||||
+276
-112
@@ -2,8 +2,8 @@
|
||||
#define IVL_expression_H
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2014 / Stephen Williams (steve@icarus.com),
|
||||
* Maciej Suminski (maciej.suminski@cern.ch)
|
||||
* Copyright CERN 2015 / Stephen Williams (steve@icarus.com),
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -31,13 +31,11 @@
|
||||
|
||||
class prange_t;
|
||||
class Entity;
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class Subprogram;
|
||||
class VType;
|
||||
class VTypeArray;
|
||||
class VTypePrimitive;
|
||||
|
||||
class ExpName;
|
||||
|
||||
/*
|
||||
@@ -51,18 +49,21 @@ class Expression : public LineInfo {
|
||||
Expression();
|
||||
virtual ~Expression() =0;
|
||||
|
||||
// Returns a deep copy of the expression.
|
||||
virtual Expression*clone() const =0;
|
||||
|
||||
// This virtual method handles the special case of elaborating
|
||||
// an expression that is the l-value of a sequential variable
|
||||
// assignment. This generates an error for most cases, but
|
||||
// expressions that are valid l-values return 0 and set any
|
||||
// flags needed to indicate their status as writable variables.
|
||||
virtual int elaborate_lval(Entity*ent, Architecture*arc,
|
||||
virtual int elaborate_lval(Entity*ent, ScopeBase*scope,
|
||||
bool is_sequ);
|
||||
|
||||
// This virtual method probes the expression to get the most
|
||||
// constrained type for the expression. For a given instance,
|
||||
// this may be called before the elaborate_expr method.
|
||||
virtual const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
virtual const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
|
||||
// The fit_type virtual method is used by the ExpConcat class
|
||||
// to probe the type of operands. The atype argument is the
|
||||
@@ -70,13 +71,13 @@ class Expression : public LineInfo {
|
||||
// returns its type as interpreted in this context. Really,
|
||||
// this is mostly about helping aggregate expressions within
|
||||
// concatenations to figure out their type.
|
||||
virtual const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
virtual const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
|
||||
// This virtual method elaborates an expression. The ltype is
|
||||
// the type of the lvalue expression, if known, and can be
|
||||
// used to calculate the type for the expression being
|
||||
// elaborated.
|
||||
virtual int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
virtual int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
|
||||
// Return the type that this expression would be if it were an
|
||||
// l-value. This should only be called after elaborate_lval is
|
||||
@@ -86,12 +87,12 @@ class Expression : public LineInfo {
|
||||
// This virtual method writes a VHDL-accurate representation
|
||||
// of this expression to the designated stream. This is used
|
||||
// for writing parsed types to library files.
|
||||
virtual void write_to_stream(std::ostream&fd) =0;
|
||||
virtual void write_to_stream(std::ostream&fd) const =0;
|
||||
|
||||
// The emit virtual method is called by architecture emit to
|
||||
// output the generated code for the expression. The derived
|
||||
// class fills in the details of what exactly happened.
|
||||
virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0;
|
||||
virtual int emit(ostream&out, Entity*ent, ScopeBase*scope) =0;
|
||||
|
||||
// The emit_package virtual message is similar, but is called
|
||||
// in a package context and to emit SV packages.
|
||||
@@ -102,8 +103,7 @@ class Expression : public LineInfo {
|
||||
// argument if the evaluation works, or return false if it
|
||||
// cannot be done.
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
virtual bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const;
|
||||
|
||||
virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
|
||||
|
||||
// The symbolic compare returns true if the two expressions
|
||||
// are equal without actually calculating the value.
|
||||
@@ -134,6 +134,13 @@ class Expression : public LineInfo {
|
||||
Expression& operator = (const Expression&);
|
||||
};
|
||||
|
||||
/*
|
||||
* Checks before cloning if the other expression actually exists (!=NULL).
|
||||
*/
|
||||
static inline Expression*safe_clone(const Expression*other) {
|
||||
return (other ? other->clone() : NULL);
|
||||
}
|
||||
|
||||
static inline void FILE_NAME(Expression*tgt, const LineInfo*src)
|
||||
{
|
||||
tgt->set_line(*src);
|
||||
@@ -150,13 +157,15 @@ class ExpUnary : public Expression {
|
||||
ExpUnary(Expression*op1);
|
||||
virtual ~ExpUnary() =0;
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
inline const Expression*peek_operand() const { return operand1_; }
|
||||
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
|
||||
protected:
|
||||
inline void write_to_stream_operand1(std::ostream&fd)
|
||||
inline void write_to_stream_operand1(std::ostream&fd) const
|
||||
{ operand1_->write_to_stream(fd); }
|
||||
|
||||
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump_operand1(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -173,23 +182,23 @@ class ExpBinary : public Expression {
|
||||
ExpBinary(Expression*op1, Expression*op2);
|
||||
virtual ~ExpBinary() =0;
|
||||
|
||||
const Expression* peek_operand1(void) const { return operand1_; }
|
||||
const Expression* peek_operand2(void) const { return operand2_; }
|
||||
inline const Expression* peek_operand1(void) const { return operand1_; }
|
||||
inline const Expression* peek_operand2(void) const { return operand2_; }
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
|
||||
protected:
|
||||
|
||||
int elaborate_exprs(Entity*, Architecture*, const VType*);
|
||||
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_exprs(Entity*, ScopeBase*, const VType*);
|
||||
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
bool eval_operand1(ScopeBase*scope, int64_t&val) const;
|
||||
bool eval_operand2(ScopeBase*scope, int64_t&val) const;
|
||||
|
||||
inline void write_to_stream_operand1(std::ostream&out)
|
||||
inline void write_to_stream_operand1(std::ostream&out) const
|
||||
{ operand1_->write_to_stream(out); }
|
||||
inline void write_to_stream_operand2(std::ostream&out)
|
||||
inline void write_to_stream_operand2(std::ostream&out) const
|
||||
{ operand2_->write_to_stream(out); }
|
||||
|
||||
void dump_operands(ostream&out, int indent = 0) const;
|
||||
@@ -219,6 +228,9 @@ class ExpAggregate : public Expression {
|
||||
explicit choice_t(perm_string name);
|
||||
// discreate_range choice
|
||||
explicit choice_t(prange_t*ran);
|
||||
|
||||
choice_t(const choice_t&other);
|
||||
|
||||
~choice_t();
|
||||
|
||||
// true if this represents an "others" choice
|
||||
@@ -235,11 +247,17 @@ class ExpAggregate : public Expression {
|
||||
std::auto_ptr<Expression>expr_;
|
||||
std::auto_ptr<prange_t> range_;
|
||||
private: // not implemented
|
||||
choice_t(const choice_t&);
|
||||
choice_t& operator= (const choice_t&);
|
||||
};
|
||||
|
||||
struct choice_element {
|
||||
choice_element() : choice(), expr() {}
|
||||
|
||||
choice_element(const choice_element&other) {
|
||||
choice = other.choice ? new choice_t(*other.choice) : NULL;
|
||||
expr = safe_clone(other.expr);
|
||||
}
|
||||
|
||||
choice_t*choice;
|
||||
Expression*expr;
|
||||
bool alias_flag;
|
||||
@@ -251,6 +269,7 @@ class ExpAggregate : public Expression {
|
||||
class element_t {
|
||||
public:
|
||||
explicit element_t(std::list<choice_t*>*fields, Expression*val);
|
||||
element_t(const element_t&other);
|
||||
~element_t();
|
||||
|
||||
size_t count_choices() const { return fields_.size(); }
|
||||
@@ -265,7 +284,6 @@ class ExpAggregate : public Expression {
|
||||
std::vector<choice_t*>fields_;
|
||||
Expression*val_;
|
||||
private: // not implemented
|
||||
element_t(const element_t&);
|
||||
element_t& operator = (const element_t&);
|
||||
};
|
||||
|
||||
@@ -273,19 +291,20 @@ class ExpAggregate : public Expression {
|
||||
ExpAggregate(std::list<element_t*>*el);
|
||||
~ExpAggregate();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
|
||||
int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype);
|
||||
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype);
|
||||
int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype);
|
||||
int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
|
||||
int elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
|
||||
int emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
|
||||
int emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
|
||||
|
||||
private:
|
||||
// This is the elements as directly parsed.
|
||||
@@ -305,9 +324,13 @@ class ExpArithmetic : public ExpBinary {
|
||||
ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2);
|
||||
~ExpArithmetic();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const {
|
||||
return new ExpArithmetic(fun_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
@@ -324,16 +347,18 @@ class ExpAttribute : public Expression {
|
||||
ExpAttribute(ExpName*base, perm_string name);
|
||||
~ExpAttribute();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
inline perm_string peek_attribute() const { return name_; }
|
||||
inline const ExpName* peek_base() const { return base_; }
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
// Some attributes can be evaluated at compile time
|
||||
bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const;
|
||||
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -345,12 +370,15 @@ class ExpBitstring : public Expression {
|
||||
|
||||
public:
|
||||
explicit ExpBitstring(const char*);
|
||||
ExpBitstring(const ExpBitstring&other) : Expression() { value_ = other.value_; }
|
||||
~ExpBitstring();
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpBitstring(*this); }
|
||||
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -362,19 +390,22 @@ class ExpCharacter : public Expression {
|
||||
|
||||
public:
|
||||
ExpCharacter(char val);
|
||||
ExpCharacter(const ExpCharacter&other) : Expression() { value_ = other.value_; }
|
||||
~ExpCharacter();
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpCharacter(*this); }
|
||||
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
char value() const { return value_; }
|
||||
|
||||
private:
|
||||
int emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc,
|
||||
int emit_primitive_bit_(ostream&out, Entity*ent, ScopeBase*scope,
|
||||
const VTypePrimitive*etype);
|
||||
|
||||
private:
|
||||
@@ -387,17 +418,21 @@ class ExpConcat : public Expression {
|
||||
ExpConcat(Expression*op1, Expression*op2);
|
||||
~ExpConcat();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const {
|
||||
return new ExpConcat(operand1_->clone(), operand2_->clone());
|
||||
}
|
||||
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
|
||||
int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
|
||||
|
||||
private:
|
||||
Expression*operand1_;
|
||||
@@ -415,11 +450,12 @@ class ExpConditional : public Expression {
|
||||
class else_t : public LineInfo {
|
||||
public:
|
||||
else_t(Expression*cond, std::list<Expression*>*tru);
|
||||
else_t(const else_t&other);
|
||||
~else_t();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*lt);
|
||||
int emit_when_else(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_else(ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
|
||||
int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_else(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -432,10 +468,12 @@ class ExpConditional : public Expression {
|
||||
std::list<else_t*>*fal);
|
||||
~ExpConditional();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const;
|
||||
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -457,10 +495,12 @@ class ExpEdge : public ExpUnary {
|
||||
explicit ExpEdge(ExpEdge::fun_t ty, Expression*op);
|
||||
~ExpEdge();
|
||||
|
||||
Expression*clone() const { return new ExpEdge(fun_, peek_operand()->clone()); }
|
||||
|
||||
inline fun_t edge_fun() const { return fun_; }
|
||||
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -474,14 +514,19 @@ class ExpFunc : public Expression {
|
||||
ExpFunc(perm_string nn, std::list<Expression*>*args);
|
||||
~ExpFunc();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
inline perm_string func_name() const { return name_; }
|
||||
inline size_t func_args() const { return argv_.size(); }
|
||||
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
|
||||
const VType*func_ret_type() const;
|
||||
|
||||
public: // Base methods
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -494,14 +539,17 @@ class ExpInteger : public Expression {
|
||||
|
||||
public:
|
||||
ExpInteger(int64_t val);
|
||||
ExpInteger(const ExpInteger&other) : Expression(), value_(other.value_) {}
|
||||
~ExpInteger();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpInteger(*this); }
|
||||
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_package(std::ostream&out);
|
||||
bool is_primary(void) const;
|
||||
bool is_primary(void) const { return true; }
|
||||
bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
virtual ostream& dump_inline(ostream&out) const;
|
||||
@@ -514,12 +562,15 @@ class ExpReal : public Expression {
|
||||
|
||||
public:
|
||||
ExpReal(double val);
|
||||
ExpReal(const ExpReal&other) : Expression(), value_(other.value_) {}
|
||||
~ExpReal();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpReal(*this); }
|
||||
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_package(std::ostream&out);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
@@ -538,11 +589,15 @@ class ExpLogical : public ExpBinary {
|
||||
ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2);
|
||||
~ExpLogical();
|
||||
|
||||
Expression*clone() const {
|
||||
return new ExpLogical(fun_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
inline fun_t logic_fun() const { return fun_; }
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
@@ -565,31 +620,64 @@ class ExpName : public Expression {
|
||||
~ExpName();
|
||||
|
||||
public: // Base methods
|
||||
int elaborate_lval(Entity*ent, Architecture*arc, bool);
|
||||
int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*);
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType* fit_type(Entity*ent, Architecture*arc, const VTypeArray*host) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const {
|
||||
return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
|
||||
name_, safe_clone(index_), safe_clone(lsb_));
|
||||
}
|
||||
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
|
||||
int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*);
|
||||
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
const VType* fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*host) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
bool is_primary(void) const;
|
||||
bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const;
|
||||
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
|
||||
bool symbolic_compare(const Expression*that) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
const char* name() const;
|
||||
inline perm_string peek_name() const { return name_; }
|
||||
inline const char* name() const { return name_; }
|
||||
inline const perm_string& peek_name() const { return name_; }
|
||||
|
||||
void set_range(Expression*msb, Expression*lsb);
|
||||
|
||||
private:
|
||||
const VType* elaborate_adjust_type_with_range_(Entity*ent, Architecture*arc, const VType*type);
|
||||
class index_t {
|
||||
public:
|
||||
index_t(Expression*idx, Expression*size, Expression*offset = NULL) :
|
||||
idx_(idx), size_(size), offset_(offset) {}
|
||||
|
||||
int elaborate_lval_(Entity*ent, Architecture*arc, bool, ExpName*suffix);
|
||||
const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const;
|
||||
const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
int emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc);
|
||||
private:
|
||||
Expression*idx_;
|
||||
Expression*size_;
|
||||
Expression*offset_;
|
||||
};
|
||||
|
||||
const VType* elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*scope, const VType*type);
|
||||
|
||||
int elaborate_lval_(Entity*ent, ScopeBase*scope, bool, ExpName*suffix);
|
||||
const VType* probe_prefix_type_(Entity*ent, ScopeBase*scope) const;
|
||||
const VType* probe_prefixed_type_(Entity*ent, ScopeBase*scope) const;
|
||||
|
||||
int emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
// There are some workarounds required for constant arrays/records, as
|
||||
// they are currently emitted as flat localparams (without any type
|
||||
// information). The following workarounds adjust the access indices
|
||||
// to select appropriate parts of the localparam.
|
||||
bool try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
|
||||
list<index_t*>&indices, int&data_size);
|
||||
|
||||
bool check_const_array_workaround_(const VTypeArray*arr, ScopeBase*scope,
|
||||
list<index_t*>&indices, int&data_size) const;
|
||||
|
||||
bool check_const_record_workaround_(const VTypeRecord*rec, ScopeBase*scope,
|
||||
list<index_t*>&indices, int&data_size) const;
|
||||
|
||||
int emit_workaround_(ostream&out, Entity*ent, ScopeBase*scope,
|
||||
const list<index_t*>&indices, int field_size);
|
||||
|
||||
private:
|
||||
std::auto_ptr<ExpName> prefix_;
|
||||
@@ -604,8 +692,8 @@ class ExpNameALL : public ExpName {
|
||||
ExpNameALL() : ExpName(perm_string()) { }
|
||||
|
||||
public:
|
||||
int elaborate_lval(Entity*ent, Architecture*arc, bool);
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
|
||||
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
void dump(ostream&out, int indent =0) const;
|
||||
};
|
||||
|
||||
@@ -620,32 +708,60 @@ class ExpRelation : public ExpBinary {
|
||||
ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2);
|
||||
~ExpRelation();
|
||||
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const {
|
||||
return new ExpRelation(fun_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
fun_t fun_;
|
||||
};
|
||||
|
||||
class ExpShift : public ExpBinary {
|
||||
public:
|
||||
enum shift_t { SRL, SLL, SRA, SLA, ROL, ROR };
|
||||
|
||||
public:
|
||||
ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2);
|
||||
|
||||
Expression*clone() const {
|
||||
return new ExpShift(shift_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
shift_t shift_;
|
||||
};
|
||||
|
||||
class ExpString : public Expression {
|
||||
|
||||
public:
|
||||
explicit ExpString(const char*);
|
||||
ExpString(const ExpString&other) : Expression(), value_(other.value_) {}
|
||||
~ExpString();
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpString(*this); }
|
||||
|
||||
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
const std::vector<char>& get_value() const { return value_; }
|
||||
|
||||
private:
|
||||
int emit_as_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*arr);
|
||||
int emit_as_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*arr);
|
||||
|
||||
private:
|
||||
std::vector<char> value_;
|
||||
@@ -657,8 +773,10 @@ class ExpUAbs : public ExpUnary {
|
||||
ExpUAbs(Expression*op1);
|
||||
~ExpUAbs();
|
||||
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); }
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
};
|
||||
|
||||
@@ -668,10 +786,56 @@ class ExpUNot : public ExpUnary {
|
||||
ExpUNot(Expression*op1);
|
||||
~ExpUNot();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpUNot(peek_operand()->clone()); }
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class that wraps other expressions to cast them to other types.
|
||||
*/
|
||||
class ExpCast : public Expression {
|
||||
|
||||
public:
|
||||
ExpCast(Expression*base, const VType*type);
|
||||
~ExpCast();
|
||||
|
||||
Expression*clone() const { return new ExpCast(base_->clone(), type_->clone()); }
|
||||
|
||||
inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) {
|
||||
return base_->elaborate_expr(ent, scope, type_);
|
||||
}
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
Expression*base_;
|
||||
const VType*type_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class that handles 'new' statement. VHDL is not capable of dynamic memory
|
||||
* allocation, but it is useful for emitting some cases.
|
||||
*/
|
||||
class ExpNew : public Expression {
|
||||
|
||||
public:
|
||||
ExpNew(Expression*size);
|
||||
~ExpNew();
|
||||
|
||||
Expression*clone() const { return new ExpNew(size_->clone()); }
|
||||
|
||||
// There is no 'new' in VHDL - do not emit anything
|
||||
void write_to_stream(std::ostream&) const {};
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
Expression*size_;
|
||||
};
|
||||
|
||||
#endif /* IVL_expression_H */
|
||||
|
||||
@@ -68,3 +68,47 @@ void ExpConcat::dump(ostream&out, int indent) const
|
||||
operand1_->dump(out, indent);
|
||||
operand2_->dump(out, indent);
|
||||
}
|
||||
|
||||
void ExpCast::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << "Casting ";
|
||||
base_->dump(out, indent+4);
|
||||
out << " to ";
|
||||
type_->emit_def(out, empty_perm_string);
|
||||
}
|
||||
|
||||
void ExpNew::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << "New dynamic array size: ";
|
||||
size_->dump(out, indent);
|
||||
}
|
||||
|
||||
void ExpShift::dump(ostream&out, int indent) const
|
||||
{
|
||||
const char*fun_name = "?";
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
fun_name = "srl";
|
||||
break;
|
||||
case SLL:
|
||||
fun_name = "sll";
|
||||
break;
|
||||
case SLA:
|
||||
fun_name = "sla";
|
||||
break;
|
||||
case SRA:
|
||||
fun_name = "sra";
|
||||
break;
|
||||
case ROR:
|
||||
fun_name = "ror";
|
||||
break;
|
||||
case ROL:
|
||||
fun_name = "rol";
|
||||
break;
|
||||
}
|
||||
|
||||
out << setw(indent) << "" << "Shift " << fun_name
|
||||
<< " at " << get_fileline() << endl;
|
||||
dump_operands(out, indent+4);
|
||||
}
|
||||
|
||||
|
||||
+300
-137
@@ -33,20 +33,20 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
int Expression::elaborate_lval(Entity*, Architecture*, bool)
|
||||
int Expression::elaborate_lval(Entity*, ScopeBase*, bool)
|
||||
{
|
||||
cerr << get_fileline() << ": error: Expression is not a valid l-value." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const VType* Expression::probe_type(Entity*, Architecture*) const
|
||||
const VType* Expression::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray*) const
|
||||
const VType* Expression::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
|
||||
{
|
||||
const VType*res = probe_type(ent,arc);
|
||||
const VType*res = probe_type(ent,scope);
|
||||
if (res == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "fit_type for " << typeid(*this).name()
|
||||
@@ -56,7 +56,7 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray
|
||||
return res;
|
||||
}
|
||||
|
||||
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type)
|
||||
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope, const VType*type)
|
||||
{
|
||||
// Unfold typedefs
|
||||
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) {
|
||||
@@ -75,23 +75,19 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc
|
||||
int64_t use_msb, use_lsb;
|
||||
bool flag;
|
||||
|
||||
flag = index_->evaluate(arc, use_msb);
|
||||
flag = index_->evaluate(scope, use_msb);
|
||||
ivl_assert(*this, flag);
|
||||
flag = lsb_->evaluate(arc, use_lsb);
|
||||
flag = lsb_->evaluate(scope, use_lsb);
|
||||
ivl_assert(*this, flag);
|
||||
|
||||
Expression*exp_msb = new ExpInteger(use_msb);
|
||||
Expression*exp_lsb = new ExpInteger(use_lsb);
|
||||
vector<VTypeArray::range_t> use_dims (1);
|
||||
use_dims[0] = VTypeArray::range_t(exp_msb, exp_lsb);
|
||||
type = new VTypeArray(array->element_type(), use_dims);
|
||||
type = new VTypeArray(array->element_type(), use_msb, use_lsb);
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName*suffix)
|
||||
int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName*suffix)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -134,13 +130,13 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
|
||||
<< ent->get_name() << "." << endl;
|
||||
return errors + 1;
|
||||
|
||||
} else if (Signal*sig = arc->find_signal(name_)) {
|
||||
} else if (Signal*sig = scope->find_signal(name_)) {
|
||||
// Tell the target signal that this may be a sequential l-value.
|
||||
if (is_sequ) sig->count_ref_sequ();
|
||||
|
||||
found_type = sig->peek_type();
|
||||
|
||||
} else if (Variable*var = arc->find_variable(name_)) {
|
||||
} else if (Variable*var = scope->find_variable(name_)) {
|
||||
// Tell the target signal that this may be a sequential l-value.
|
||||
if (is_sequ) var->count_ref_sequ();
|
||||
|
||||
@@ -201,7 +197,7 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
|
||||
return errors;
|
||||
}
|
||||
|
||||
suffix_type = suffix->elaborate_adjust_type_with_range_(ent, arc, suffix_type);
|
||||
suffix_type = suffix->elaborate_adjust_type_with_range_(ent, scope, suffix_type);
|
||||
|
||||
ivl_assert(*this, suffix_type);
|
||||
suffix->set_type(suffix_type);
|
||||
@@ -209,12 +205,12 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
|
||||
int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (prefix_.get()) {
|
||||
return prefix_->elaborate_lval_(ent, arc, is_sequ, this);
|
||||
return prefix_->elaborate_lval_(ent, scope, is_sequ, this);
|
||||
}
|
||||
|
||||
const VType*found_type = 0;
|
||||
@@ -238,13 +234,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
|
||||
<< ent->get_name() << "." << endl;
|
||||
return 1;
|
||||
|
||||
} else if (Signal*sig = arc->find_signal(name_)) {
|
||||
} else if (Signal*sig = scope->find_signal(name_)) {
|
||||
// Tell the target signal that this may be a sequential l-value.
|
||||
if (is_sequ) sig->count_ref_sequ();
|
||||
|
||||
found_type = sig->peek_type();
|
||||
|
||||
} else if (Variable*var = arc->find_variable(name_)) {
|
||||
} else if (Variable*var = scope->find_variable(name_)) {
|
||||
// Tell the target signal that this may be a sequential l-value.
|
||||
if (is_sequ) var->count_ref_sequ();
|
||||
|
||||
@@ -257,13 +253,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
|
||||
return errors + 1;
|
||||
}
|
||||
|
||||
found_type = elaborate_adjust_type_with_range_(ent, arc, found_type);
|
||||
found_type = elaborate_adjust_type_with_range_(ent, scope, found_type);
|
||||
|
||||
set_type(found_type);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval)
|
||||
int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lval)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -273,6 +269,9 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
const VType*dummy_type;
|
||||
Expression*dummy_expr;
|
||||
|
||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||
/* IEEE 1076-2008, p.80:
|
||||
* For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER
|
||||
@@ -295,14 +294,17 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (arc->find_signal(name_)) {
|
||||
} else if (scope->find_signal(name_)) {
|
||||
/* OK */
|
||||
|
||||
} else if (ent->find_generic(name_)) {
|
||||
/* OK */
|
||||
|
||||
} else if (scope->find_constant(name_, dummy_type, dummy_expr)) {
|
||||
/* OK */
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: No port or signal " << name_
|
||||
cerr << get_fileline() << ": error: No port, signal or constant " << name_
|
||||
<< " to be used as r-value." << endl;
|
||||
errors += 1;
|
||||
}
|
||||
@@ -310,21 +312,21 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
|
||||
int ExpNameALL::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
|
||||
{
|
||||
return Expression::elaborate_lval(ent, arc, is_sequ);
|
||||
return Expression::elaborate_lval(ent, scope, is_sequ);
|
||||
}
|
||||
|
||||
int Expression::elaborate_expr(Entity*, Architecture*, const VType*)
|
||||
int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const
|
||||
const VType* ExpBinary::probe_type(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
const VType*t1 = operand1_->probe_type(ent, arc);
|
||||
const VType*t2 = operand2_->probe_type(ent, arc);
|
||||
const VType*t1 = operand1_->probe_type(ent, scope);
|
||||
const VType*t2 = operand2_->probe_type(ent, scope);
|
||||
|
||||
if (t1 == 0)
|
||||
return t2;
|
||||
@@ -351,12 +353,12 @@ const VType*ExpBinary::resolve_operand_types_(const VType*, const VType*) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpBinary::elaborate_exprs(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += operand1_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand1_->elaborate_expr(ent, scope, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, scope, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -365,17 +367,17 @@ int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
* return the fit_type for the operand. The assumption is that the
|
||||
* operator doesn't change the type.
|
||||
*/
|
||||
const VType*ExpUnary::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const
|
||||
const VType*ExpUnary::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const
|
||||
{
|
||||
return operand1_->fit_type(ent, arc, atype);
|
||||
return operand1_->fit_type(ent, scope, atype);
|
||||
}
|
||||
|
||||
const VType*ExpAggregate::probe_type(Entity*ent, Architecture*arc) const
|
||||
const VType*ExpAggregate::probe_type(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
return Expression::probe_type(ent, arc);
|
||||
return Expression::probe_type(ent, scope);
|
||||
}
|
||||
|
||||
const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host) const
|
||||
const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) const
|
||||
{
|
||||
ivl_assert(*this, elements_.size() == 1);
|
||||
size_t choice_count = elements_[0]->count_choices();
|
||||
@@ -401,7 +403,7 @@ const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host
|
||||
return res;
|
||||
}
|
||||
|
||||
int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpAggregate::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
if (ltype == 0) {
|
||||
cerr << get_fileline() << ": error: Elaboration of aggregate types needs well known type context?" << endl;
|
||||
@@ -415,10 +417,10 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
|
||||
}
|
||||
|
||||
if (const VTypeArray*larray = dynamic_cast<const VTypeArray*>(ltype)) {
|
||||
return elaborate_expr_array_(ent, arc, larray);
|
||||
return elaborate_expr_array_(ent, scope, larray);
|
||||
}
|
||||
else if(const VTypeRecord*lrecord = dynamic_cast<const VTypeRecord*>(ltype)) {
|
||||
return elaborate_expr_record_(ent, arc, lrecord);
|
||||
return elaborate_expr_record_(ent, scope, lrecord);
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl;
|
||||
@@ -430,7 +432,7 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
|
||||
* expressions (the elements_ member) using the element type as the
|
||||
* ltype for the subexpression.
|
||||
*/
|
||||
int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype)
|
||||
int ExpAggregate::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype)
|
||||
{
|
||||
const VType*element_type = ltype->element_type();
|
||||
int errors = 0;
|
||||
@@ -476,7 +478,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
|
||||
if (aggregate_[idx].alias_flag)
|
||||
continue;
|
||||
|
||||
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, element_type);
|
||||
errors += aggregate_[idx].expr->elaborate_expr(ent, scope, element_type);
|
||||
}
|
||||
|
||||
// done with the obsolete elements_ vector.
|
||||
@@ -485,7 +487,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype)
|
||||
int ExpAggregate::elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -513,10 +515,12 @@ int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTy
|
||||
ivl_assert(*this, field);
|
||||
|
||||
perm_string field_name = field->peek_name();
|
||||
idx = -1;
|
||||
const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx);
|
||||
ivl_assert(*this, idx >= 0);
|
||||
|
||||
aggregate_[idx] = tmp;
|
||||
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type());
|
||||
errors += aggregate_[idx].expr->elaborate_expr(ent, scope, el->peek_type());
|
||||
}
|
||||
|
||||
// done with the obsolete elements_ vector.
|
||||
@@ -535,16 +539,16 @@ void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst)
|
||||
}
|
||||
}
|
||||
|
||||
int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpArithmetic::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
errors += elaborate_exprs(ent, arc, ltype);
|
||||
errors += elaborate_exprs(ent, scope, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -563,53 +567,55 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const
|
||||
const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
base_->probe_type(ent, arc);
|
||||
base_->probe_type(ent, scope);
|
||||
|
||||
if (name_ == "length" || name_ == "left" || name_ == "right") {
|
||||
return &primitive_INTEGER;
|
||||
return &primitive_NATURAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
||||
int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
||||
{
|
||||
int errors = 0;
|
||||
const VType*sub_type = base_->probe_type(ent, arc);
|
||||
errors += base_->elaborate_expr(ent, arc, sub_type);
|
||||
const VType*sub_type = base_->probe_type(ent, scope);
|
||||
errors += base_->elaborate_expr(ent, scope, sub_type);
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType*ExpBitstring::fit_type(Entity*, Architecture*, const VTypeArray*atype) const
|
||||
const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
|
||||
{
|
||||
// Really should check that this string can work with the
|
||||
// array element type?
|
||||
return atype->element_type();
|
||||
}
|
||||
|
||||
int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*)
|
||||
int ExpBitstring::elaborate_expr(Entity*, ScopeBase*, const VType*)
|
||||
{
|
||||
int errors = 0;
|
||||
const VTypeArray*type = new VTypeArray(&primitive_STDLOGIC, value_.size() - 1, 0);
|
||||
set_type(type);
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType*ExpCharacter::fit_type(Entity*, Architecture*, const VTypeArray*atype) const
|
||||
const VType*ExpCharacter::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
|
||||
{
|
||||
// Really should check that this character can work with the
|
||||
// array element type?
|
||||
return atype->element_type();
|
||||
}
|
||||
|
||||
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
int ExpCharacter::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
{
|
||||
ivl_assert(*this, ltype != 0);
|
||||
set_type(ltype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const
|
||||
const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const
|
||||
{
|
||||
Expression*operands[2] = {operand1_, operand2_};
|
||||
const VType*types[2] = {NULL, NULL};
|
||||
@@ -617,7 +623,7 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a
|
||||
|
||||
// determine the type and size of concatenated expressions
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
types[i] = operands[i]->fit_type(ent, arc, atype);
|
||||
types[i] = operands[i]->fit_type(ent, scope, atype);
|
||||
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(types[i])) {
|
||||
types[i] = arr->element_type();
|
||||
@@ -645,62 +651,62 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a
|
||||
/*
|
||||
* I don't know how to probe the type of a concatenation, quite yet.
|
||||
*/
|
||||
const VType*ExpConcat::probe_type(Entity*, Architecture*) const
|
||||
const VType*ExpConcat::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
ivl_assert(*this, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpConcat::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpConcat::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
|
||||
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*>(ltype)) {
|
||||
errors += elaborate_expr_array_(ent, arc, atype);
|
||||
errors += elaborate_expr_array_(ent, scope, atype);
|
||||
} else {
|
||||
errors += operand1_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand1_->elaborate_expr(ent, scope, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConcat::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*atype)
|
||||
int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*atype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// For now, only support single-dimension arrays here.
|
||||
ivl_assert(*this, atype->dimensions() == 1);
|
||||
|
||||
const VType*type1 = operand1_->fit_type(ent, arc, atype);
|
||||
const VType*type1 = operand1_->fit_type(ent, scope, atype);
|
||||
ivl_assert(*this, type1);
|
||||
|
||||
const VType*type2 = operand2_->fit_type(ent, arc, atype);
|
||||
const VType*type2 = operand2_->fit_type(ent, scope, atype);
|
||||
ivl_assert(*this, type2);
|
||||
|
||||
errors += operand1_->elaborate_expr(ent, arc, type1);
|
||||
errors += operand2_->elaborate_expr(ent, arc, type2);
|
||||
errors += operand1_->elaborate_expr(ent, scope, type1);
|
||||
errors += operand2_->elaborate_expr(ent, scope, type2);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpConditional::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpConditional::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0)
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
|
||||
ivl_assert(*this, ltype);
|
||||
|
||||
@@ -708,42 +714,92 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
|
||||
|
||||
/* Note that the type for the condition expression need not
|
||||
have anything to do with the type of this expression. */
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
for (list<else_t*>::const_iterator cur = else_clause_.begin()
|
||||
; cur != else_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::else_t::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (cond_)
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
||||
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
if(name_ == "integer")
|
||||
return &primitive_INTEGER;
|
||||
|
||||
if(name_ == "unsigned" || name_ == "resize") {
|
||||
if(argv_.empty())
|
||||
return NULL;
|
||||
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
if(!type)
|
||||
return NULL;
|
||||
|
||||
int msb = type->get_width(scope) - 1;
|
||||
ivl_assert(*this, msb >= 0);
|
||||
|
||||
// Determine the sign
|
||||
bool sign = false;
|
||||
if(name_ == "resize") {
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
|
||||
sign = arr->signed_vector();
|
||||
}
|
||||
|
||||
return new VTypeArray(&primitive_BIT, msb, 0, sign);
|
||||
}
|
||||
|
||||
if(name_ == "std_logic_vector" || name_ == "conv_std_logic_vector") {
|
||||
if(argv_.empty())
|
||||
return NULL;
|
||||
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
if(!type)
|
||||
return NULL;
|
||||
|
||||
int msb = type->get_width(scope) - 1;
|
||||
|
||||
return new VTypeArray(&primitive_STDLOGIC, msb, 0);
|
||||
}
|
||||
|
||||
Subprogram*prog = scope->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
return NULL;
|
||||
|
||||
return prog->peek_return_type();
|
||||
}
|
||||
|
||||
int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
ivl_assert(*this, arc);
|
||||
Subprogram*prog = arc->find_subprogram(name_);
|
||||
ivl_assert(*this, scope);
|
||||
Subprogram*prog = scope->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
@@ -751,27 +807,110 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
||||
ivl_assert(*this, def_==0);
|
||||
def_ = prog;
|
||||
|
||||
// Elaborate arguments
|
||||
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
|
||||
const VType*tmp = argv_[idx]->probe_type(ent, arc);
|
||||
if(!tmp && prog)
|
||||
tmp = prog->peek_param_type(idx);
|
||||
errors += argv_[idx]->elaborate_expr(ent, arc, tmp);
|
||||
const VType*tmp = argv_[idx]->probe_type(ent, scope);
|
||||
const VType*param_type = prog ? prog->peek_param_type(idx) : NULL;
|
||||
|
||||
if(!tmp && param_type)
|
||||
tmp = param_type;
|
||||
|
||||
errors += argv_[idx]->elaborate_expr(ent, scope, tmp);
|
||||
}
|
||||
|
||||
if(def_ && def_->unbounded()) {
|
||||
def_ = prog->make_instance(argv_, scope);
|
||||
name_ = def_->name();
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpInteger::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
|
||||
{
|
||||
// Built-in functions
|
||||
if(name_ == "to_integer" || name_ == "unsigned" || name_ == "integer") {
|
||||
ivl_assert(*this, argv_.size() == 1);
|
||||
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
ivl_assert(*this, type);
|
||||
|
||||
// Determine the sign
|
||||
bool sign = false;
|
||||
|
||||
if(name_ == "integer") {
|
||||
sign = true;
|
||||
} else if(name_ == "to_integer") {
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
|
||||
sign = arr->signed_vector();
|
||||
}
|
||||
|
||||
return new VTypeArray(&primitive_BIT, type->get_width(scope), 0, sign);
|
||||
}
|
||||
|
||||
if(name_ == "to_unsigned" || name_ == "std_logic_vector" ||
|
||||
name_ == "conv_std_logic_vector" || name_ == "resize")
|
||||
{
|
||||
ivl_assert(*this, argv_.size() == 2);
|
||||
|
||||
// Determine the sign
|
||||
bool sign = false;
|
||||
const VType*element = &primitive_STDLOGIC;
|
||||
|
||||
if(name_ == "resize") {
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
ivl_assert(*this, type);
|
||||
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
|
||||
{
|
||||
sign = arr->signed_vector();
|
||||
element = arr->element_type();
|
||||
}
|
||||
} else if(name_ == "to_unsigned") {
|
||||
element = &primitive_BIT;
|
||||
}
|
||||
|
||||
int64_t width = 0;
|
||||
bool evaluated = argv_[1]->evaluate(scope, width);
|
||||
ivl_assert(*this, evaluated);
|
||||
|
||||
return new VTypeArray(element, width, 0, sign);
|
||||
}
|
||||
|
||||
if(name_ == "and_reduce" || name_ == "or_reduce") {
|
||||
ivl_assert(*this, argv_.size() == 1);
|
||||
const VType*element = &primitive_STDLOGIC;
|
||||
return new VTypeArray(element, 0, 0, false);
|
||||
}
|
||||
|
||||
// Other cases
|
||||
Subprogram*prog = def_;
|
||||
|
||||
if(!prog) {
|
||||
ivl_assert(*this, scope);
|
||||
prog = scope->find_subprogram(name_);
|
||||
}
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
||||
cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl;
|
||||
ivl_assert(*this, prog);
|
||||
|
||||
return def_->peek_return_type();
|
||||
}
|
||||
|
||||
const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return &primitive_INTEGER;
|
||||
}
|
||||
|
||||
int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpInteger::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
@@ -779,17 +918,17 @@ int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpReal::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpReal::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return &primitive_REAL;
|
||||
}
|
||||
|
||||
int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpReal::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
@@ -797,27 +936,27 @@ int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpLogical::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
errors += elaborate_exprs(ent, arc, ltype);
|
||||
errors += elaborate_exprs(ent, scope, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const
|
||||
const VType* ExpName::probe_prefix_type_(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
if (prefix_.get()) {
|
||||
cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType*type = probe_type(ent, arc);
|
||||
const VType*type = probe_type(ent, scope);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -826,10 +965,10 @@ const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const
|
||||
* that have prefix parts. In this case we try to get the type of the
|
||||
* prefix and interpret the name in that context.
|
||||
*/
|
||||
const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
|
||||
const VType* ExpName::probe_prefixed_type_(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
// First, get the type of the prefix.
|
||||
const VType*prefix_type = prefix_->probe_prefix_type_(ent, arc);
|
||||
const VType*prefix_type = prefix_->probe_prefix_type_(ent, scope);
|
||||
if (prefix_type == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -850,6 +989,13 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
|
||||
return element_type;
|
||||
}
|
||||
|
||||
if (const VTypeArray*pref_array = dynamic_cast<const VTypeArray*> (prefix_type)) {
|
||||
const VType*element_type = pref_array->element_type();
|
||||
ivl_assert(*this, element_type);
|
||||
|
||||
return element_type;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": sorry: I don't know how to probe "
|
||||
<< "prefix type " << typeid(*prefix_type).name()
|
||||
<< " of " << name_ << "." << endl;
|
||||
@@ -857,34 +1003,43 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
|
||||
const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
if (prefix_.get())
|
||||
return probe_prefixed_type_(ent, arc);
|
||||
return probe_prefixed_type_(ent, scope);
|
||||
|
||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||
ivl_assert(*this, cur->type);
|
||||
return cur->type;
|
||||
if(ent) {
|
||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||
ivl_assert(*this, cur->type);
|
||||
return cur->type;
|
||||
}
|
||||
|
||||
if (const InterfacePort*cur = ent->find_generic(name_)) {
|
||||
ivl_assert(*this, cur->type);
|
||||
return cur->type;
|
||||
}
|
||||
}
|
||||
|
||||
if (const InterfacePort*cur = ent->find_generic(name_)) {
|
||||
ivl_assert(*this, cur->type);
|
||||
return cur->type;
|
||||
}
|
||||
if(scope) {
|
||||
if (Signal*sig = scope->find_signal(name_))
|
||||
return sig->peek_type();
|
||||
|
||||
if (Signal*sig = arc->find_signal(name_))
|
||||
return sig->peek_type();
|
||||
if (Variable*var = scope->find_variable(name_))
|
||||
return var->peek_type();
|
||||
|
||||
if (Variable*var = arc->find_variable(name_))
|
||||
return var->peek_type();
|
||||
const VType*type = 0;
|
||||
Expression*cval = 0;
|
||||
if (scope->find_constant(name_, type, cval))
|
||||
return type;
|
||||
|
||||
const VType*ctype = 0;
|
||||
Expression*cval = 0;
|
||||
if (arc->find_constant(name_, ctype, cval))
|
||||
return ctype;
|
||||
Architecture*arc = dynamic_cast<Architecture*>(scope);
|
||||
if (arc && (type = arc->probe_genvar_type(name_))) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (const VType*gtype = arc->probe_genvar_type(name_)) {
|
||||
return gtype;
|
||||
if ((type = scope->is_enum_name(name_))) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Signal/variable " << name_
|
||||
@@ -892,12 +1047,12 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpName::fit_type(Entity*ent, Architecture*arc, const VTypeArray*)const
|
||||
const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)const
|
||||
{
|
||||
return probe_type(ent, arc);
|
||||
return probe_type(ent, scope);
|
||||
}
|
||||
|
||||
int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
{
|
||||
if (ltype) {
|
||||
ivl_assert(*this, ltype != 0);
|
||||
@@ -907,22 +1062,22 @@ int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpNameALL::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpRelation::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return &primitive_BOOLEAN;
|
||||
}
|
||||
|
||||
int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
@@ -930,41 +1085,49 @@ int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
// The type of the operands must match, but need not match the
|
||||
// type for the ExpRelation itself. So get the operand type
|
||||
// separately.
|
||||
const VType*otype = ExpBinary::probe_type(ent, arc);
|
||||
errors += elaborate_exprs(ent, arc, otype);
|
||||
const VType*otype = ExpBinary::probe_type(ent, scope);
|
||||
errors += elaborate_exprs(ent, scope, otype);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpShift::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
errors += elaborate_exprs(ent, scope, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
/*
|
||||
* When a string appears in a concatenation, then the type of the
|
||||
* string is an array with the same element type of the concatenation,
|
||||
* but with elements for each character of the string.
|
||||
*/
|
||||
const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype) const
|
||||
const VType*ExpString::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
|
||||
{
|
||||
vector<VTypeArray::range_t> range (atype->dimensions());
|
||||
|
||||
// Generate an array range for this string
|
||||
ivl_assert(*this, range.size() == 1);
|
||||
ExpInteger*use_msb = new ExpInteger(value_.size());
|
||||
ExpInteger*use_lsb = new ExpInteger(0);
|
||||
FILE_NAME(use_msb, this);
|
||||
FILE_NAME(use_lsb, this);
|
||||
range[0] = VTypeArray::range_t(use_msb, use_lsb);
|
||||
|
||||
VTypeArray*type = new VTypeArray(atype->element_type(), range);
|
||||
VTypeArray*type = new VTypeArray(atype->element_type(), value_.size(), 0);
|
||||
return type;
|
||||
}
|
||||
|
||||
int ExpString::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
int ExpString::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
{
|
||||
ivl_assert(*this, ltype != 0);
|
||||
set_type(ltype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpUNot::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
int ExpUNot::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
{
|
||||
ivl_assert(*this, ltype != 0);
|
||||
set_type(ltype);
|
||||
|
||||
+348
-140
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2015 / Stephen Williams (steve@icarus.com)
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -33,7 +34,34 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
int Expression::emit(ostream&out, Entity*, Architecture*)
|
||||
inline static int emit_logic(char val, ostream& out, const VTypePrimitive::type_t type)
|
||||
{
|
||||
// TODO case 'W': case 'L': case 'H':
|
||||
|
||||
switch (val) {
|
||||
case '-': case 'U':
|
||||
val = 'x';
|
||||
/* fall through */
|
||||
|
||||
case 'X': case 'Z':
|
||||
assert(type == VTypePrimitive::STDLOGIC);
|
||||
/* fall through */
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
out << (char) tolower(val);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
out << "x";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Expression::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << " /* " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this expression! "
|
||||
@@ -54,34 +82,34 @@ bool Expression::is_primary(void) const
|
||||
return false;
|
||||
}
|
||||
|
||||
int ExpBinary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpBinary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
bool oper_primary = operand1_->is_primary();
|
||||
if (! oper_primary) out << "(";
|
||||
errors += operand1_->emit(out, ent, arc);
|
||||
errors += operand1_->emit(out, ent, scope);
|
||||
if (! oper_primary) out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpBinary::emit_operand2(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpBinary::emit_operand2(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
bool oper_primary = operand2_->is_primary();
|
||||
if (! oper_primary) out << "(";
|
||||
errors += operand2_->emit(out, ent, arc);
|
||||
errors += operand2_->emit(out, ent, scope);
|
||||
if (! oper_primary) out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpUnary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += operand1_->emit(out, ent, arc);
|
||||
errors += operand1_->emit(out, ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpAggregate::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
if (peek_type() == 0) {
|
||||
out << "/* " << get_fileline() << ": internal error: "
|
||||
@@ -95,9 +123,9 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
}
|
||||
|
||||
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (use_type))
|
||||
return emit_array_(out, ent, arc, atype);
|
||||
return emit_array_(out, ent, scope, atype);
|
||||
else if (const VTypeRecord*arecord = dynamic_cast<const VTypeRecord*> (use_type))
|
||||
return emit_record_(out, ent, arc, arecord);
|
||||
return emit_record_(out, ent, scope, arecord);
|
||||
|
||||
out << "/* " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to elab/emit aggregate in " << typeid(use_type).name()
|
||||
@@ -105,7 +133,7 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype)
|
||||
int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*atype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -119,14 +147,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
int64_t use_msb;
|
||||
int64_t use_lsb;
|
||||
bool rc_msb, rc_lsb;
|
||||
rc_msb = rang.msb()->evaluate(ent, arc, use_msb);
|
||||
rc_lsb = rang.lsb()->evaluate(ent, arc, use_lsb);
|
||||
rc_msb = rang.msb()->evaluate(ent, scope, use_msb);
|
||||
rc_lsb = rang.lsb()->evaluate(ent, scope, use_lsb);
|
||||
|
||||
if (rc_msb && rc_lsb) {
|
||||
int asize = (use_msb >= use_lsb) ? (use_msb - use_lsb) + 1 :
|
||||
(use_lsb - use_msb) + 1;
|
||||
out << "{" << asize << "{";
|
||||
errors += aggregate_[0].expr->emit(out, ent, arc);
|
||||
errors += aggregate_[0].expr->emit(out, ent, scope);
|
||||
out << "}}";
|
||||
} else {
|
||||
out << "{(";
|
||||
@@ -134,7 +162,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
out << use_msb;
|
||||
} else {
|
||||
out << "(";
|
||||
errors += rang.msb()->emit(out, ent, arc);
|
||||
errors += rang.msb()->emit(out, ent, scope);
|
||||
out << ")";
|
||||
}
|
||||
if (rc_lsb && use_lsb==0) {
|
||||
@@ -142,11 +170,11 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
out << "-" << use_lsb;
|
||||
} else {
|
||||
out << "-(";
|
||||
errors += rang.lsb()->emit(out, ent, arc);
|
||||
errors += rang.lsb()->emit(out, ent, scope);
|
||||
out << ")";
|
||||
}
|
||||
out << "+1){";
|
||||
errors += aggregate_[0].expr->emit(out, ent, arc);
|
||||
errors += aggregate_[0].expr->emit(out, ent, scope);
|
||||
out << "}}";
|
||||
}
|
||||
return errors;
|
||||
@@ -158,9 +186,9 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
// Fully calculate the range numbers.
|
||||
int64_t use_msb, use_lsb;
|
||||
bool rc;
|
||||
rc = rang.msb()->evaluate(ent, arc, use_msb);
|
||||
rc = rang.msb()->evaluate(ent, scope, use_msb);
|
||||
ivl_assert(*this, rc);
|
||||
rc = rang.lsb()->evaluate(ent, arc, use_lsb);
|
||||
rc = rang.lsb()->evaluate(ent, scope, use_lsb);
|
||||
ivl_assert(*this, rc);
|
||||
if(use_msb < use_lsb)
|
||||
swap(use_msb, use_lsb);
|
||||
@@ -198,14 +226,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
if (prange_t*range = aggregate_[idx].choice->range_expressions()) {
|
||||
int64_t begin_val, end_val;
|
||||
|
||||
if (! range->msb()->evaluate(ent, arc, begin_val)) {
|
||||
if (! range->msb()->evaluate(ent, scope, begin_val)) {
|
||||
cerr << range->msb()->get_fileline() << ": error: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! range->lsb()->evaluate(ent, arc, end_val)) {
|
||||
if (! range->lsb()->evaluate(ent, scope, end_val)) {
|
||||
cerr << range->msb()->get_fileline() << ": error: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
@@ -235,7 +263,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
// elements so disable further positional
|
||||
// processing.
|
||||
positional_section = false;
|
||||
if (! tmp->evaluate(ent, arc, tmp_val)) {
|
||||
if (! tmp->evaluate(ent, scope, tmp_val)) {
|
||||
cerr << tmp->get_fileline() << ": error: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
@@ -266,7 +294,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
<< "Missing element " << idx << "." << endl;
|
||||
errors += 1;
|
||||
} else {
|
||||
errors += cur->expr->emit(out, ent, arc);
|
||||
errors += cur->expr->emit(out, ent, scope);
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
@@ -274,7 +302,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*)
|
||||
int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -292,9 +320,9 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
|
||||
if(idx != 0)
|
||||
out << ",";
|
||||
|
||||
//errors += name->emit(out, ent, arc);
|
||||
//errors += name->emit(out, ent, scope);
|
||||
//out << ": ";
|
||||
errors += val->emit(out, ent, arc);
|
||||
errors += val->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
out << "}";
|
||||
@@ -302,13 +330,20 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// Try to evaluate first
|
||||
int64_t val;
|
||||
if(evaluate(scope, val)) {
|
||||
out << val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (name_ == "event") {
|
||||
out << "$ivlh_attribute_event(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
@@ -319,27 +354,27 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
expression doesn't even need to be evaluated.) */
|
||||
if (name_=="length") {
|
||||
out << "$bits(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
} else if (name_=="left" || name_=="right") {
|
||||
out << "$" << name_ << "(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
out << "$ivl_attribute(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ", \"" << name_ << "\")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (fun_) {
|
||||
case PLUS:
|
||||
@@ -369,12 +404,12 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpBitstring::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -385,39 +420,31 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
|
||||
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*,
|
||||
const VTypePrimitive*etype)
|
||||
{
|
||||
switch (etype->type()) {
|
||||
case VTypePrimitive::BOOLEAN:
|
||||
case VTypePrimitive::BIT:
|
||||
case VTypePrimitive::STDLOGIC:
|
||||
switch (value_) {
|
||||
case '0':
|
||||
case '1':
|
||||
out << "1'b" << value_;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out << "1'b";
|
||||
int res = emit_logic(value_, out, etype->type());
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
if(res)
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Don't know how to handle bit " << value_
|
||||
<< " with etype==" << etype->type() << endl;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ExpCharacter::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
const VType*etype = peek_type();
|
||||
|
||||
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) {
|
||||
return emit_primitive_bit_(out, ent, arc, use_type);
|
||||
return emit_primitive_bit_(out, ent, scope, use_type);
|
||||
}
|
||||
|
||||
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(etype)) {
|
||||
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(array->element_type())) {
|
||||
return emit_primitive_bit_(out, ent, arc, use_type);
|
||||
return emit_primitive_bit_(out, ent, scope, use_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,22 +466,22 @@ bool ExpConcat::is_primary(void) const
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpConcat::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpConcat::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "{";
|
||||
errors += operand1_->emit(out, ent, arc);
|
||||
errors += operand1_->emit(out, ent, scope);
|
||||
out << ", ";
|
||||
errors += operand2_->emit(out, ent, arc);
|
||||
errors += operand2_->emit(out, ent, scope);
|
||||
out << "}";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "(";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")? (";
|
||||
|
||||
if (true_clause_.size() > 1) {
|
||||
@@ -463,7 +490,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
}
|
||||
|
||||
Expression*tmp = true_clause_.front();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
out << ") : (";
|
||||
|
||||
@@ -475,11 +502,11 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
|
||||
for (list<else_t*>::iterator cur = else_clause_.begin()
|
||||
; cur != last ; ++cur) {
|
||||
errors += (*cur) ->emit_when_else(out, ent, arc);
|
||||
errors += (*cur) ->emit_when_else(out, ent, scope);
|
||||
}
|
||||
}
|
||||
|
||||
errors += else_clause_.back()->emit_else(out, ent, arc);
|
||||
errors += else_clause_.back()->emit_else(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
// The emit_when_else() functions do not close the last
|
||||
@@ -492,13 +519,13 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
assert(cond_ != 0);
|
||||
|
||||
out << "(";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")? (";
|
||||
|
||||
if (true_clause_.size() > 1) {
|
||||
@@ -507,14 +534,14 @@ int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture
|
||||
}
|
||||
|
||||
Expression*tmp = true_clause_.front();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
out << ") : (";
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
// Trailing else must have no condition.
|
||||
@@ -526,12 +553,12 @@ int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc)
|
||||
}
|
||||
|
||||
Expression*tmp = true_clause_.front();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpEdge::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
switch (fun_) {
|
||||
@@ -544,60 +571,90 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
case ANYEDGE:
|
||||
break;
|
||||
}
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (name_ == "unsigned" && argv_.size()==1) {
|
||||
if (name_ == "unsigned" && argv_.size() == 1) {
|
||||
// Handle the special case that this is a cast to
|
||||
// unsigned. This function is brought in as part of the
|
||||
// std numeric library, but we interpret it as the same
|
||||
// as the $unsigned function.
|
||||
out << "$unsigned(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "integer" && argv_.size() == 1) {
|
||||
// Simply skip the function name, SystemVerilog takes care of
|
||||
// rounding real numbers
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
out << "$signed(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "to_integer" && argv_.size() == 1) {
|
||||
bool signed_flag = false;
|
||||
|
||||
// to_integer converts unsigned to natural
|
||||
// signed to integer
|
||||
// try to determine the converted type
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
const VTypeArray*array = dynamic_cast<const VTypeArray*>(type);
|
||||
|
||||
if(array)
|
||||
signed_flag = array->signed_vector();
|
||||
else
|
||||
cerr << get_fileline() << ": sorry: Could not determine the "
|
||||
<< "expression sign. Output may be erroneous." << endl;
|
||||
|
||||
out << (signed_flag ? "$signed(" : "$unsigned(");
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "std_logic_vector" && argv_.size() == 1) {
|
||||
// Special case: The std_logic_vector function casts its
|
||||
// argument to std_logic_vector. Internally, we don't
|
||||
// have to do anything for that to work.
|
||||
out << "(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "to_unsigned" && argv_.size() == 2) {
|
||||
|
||||
out << "$ivlh_to_unsigned(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ", ";
|
||||
errors += argv_[1]->emit(out, ent, arc);
|
||||
errors += argv_[1]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) {
|
||||
} else if ((name_ == "conv_std_logic_vector" || name_ == "resize") &&
|
||||
argv_.size() == 2) {
|
||||
int64_t use_size;
|
||||
bool rc = argv_[1]->evaluate(ent, arc, use_size);
|
||||
bool rc = argv_[1]->evaluate(ent, scope, use_size);
|
||||
ivl_assert(*this, rc);
|
||||
out << use_size << "'(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "rising_edge" && argv_.size()==1) {
|
||||
} else if (name_ == "rising_edge" && argv_.size() == 1) {
|
||||
out << "$ivlh_rising_edge(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "falling_edge" && argv_.size()==1) {
|
||||
} else if (name_ == "falling_edge" && argv_.size() == 1) {
|
||||
out << "$ivlh_falling_edge(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "and_reduce" && argv_.size() == 1) {
|
||||
out << "&(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "or_reduce" && argv_.size() == 1) {
|
||||
out << "|(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else {
|
||||
@@ -615,7 +672,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
out << "\\" << name_ << " (";
|
||||
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
errors += argv_[idx]->emit(out, ent, arc);
|
||||
errors += argv_[idx]->emit(out, ent, scope);
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
@@ -623,9 +680,9 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpInteger::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << value_;
|
||||
out << "32'd" << value_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -635,12 +692,7 @@ int ExpInteger::emit_package(ostream&out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ExpInteger::is_primary(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpReal::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpReal::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << value_;
|
||||
return 0;
|
||||
@@ -657,11 +709,11 @@ bool ExpReal::is_primary(void) const
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpLogical::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (fun_) {
|
||||
case AND:
|
||||
@@ -684,22 +736,22 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
if (prefix_.get()) {
|
||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||
errors += prefix_->emit_as_prefix_(out, ent, scope);
|
||||
}
|
||||
|
||||
out << "\\" << name_ << " ";
|
||||
if (index_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, arc);
|
||||
errors += index_->emit(out, ent, scope);
|
||||
out << "]";
|
||||
ivl_assert(*this, lsb_ == 0);
|
||||
}
|
||||
@@ -707,27 +759,35 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
int field_size = 0;
|
||||
list<index_t*> indices;
|
||||
|
||||
if(try_workarounds_(out, ent, scope, indices, field_size)) {
|
||||
emit_workaround_(out, ent, scope, indices, field_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prefix_.get()) {
|
||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||
errors += prefix_->emit_as_prefix_(out, ent, scope);
|
||||
}
|
||||
|
||||
const GenerateStatement*gs = 0;
|
||||
Architecture*arc = dynamic_cast<Architecture*>(scope);
|
||||
if (arc && (gs = arc->probe_genvar_emit(name_)))
|
||||
out << "\\" << gs->get_name() << ":" << name_ << " ";
|
||||
out << "\\" << gs->get_name() << ":" << name_ << " ";
|
||||
else
|
||||
out << "\\" << name_ << " ";
|
||||
|
||||
if (index_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, arc);
|
||||
errors += index_->emit(out, ent, scope);
|
||||
|
||||
if (lsb_) {
|
||||
out << ":";
|
||||
errors += lsb_->emit(out, ent, arc);
|
||||
errors += lsb_->emit(out, ent, scope);
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
@@ -735,15 +795,130 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
bool ExpName::try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
|
||||
list<index_t*>& indices, int& data_size)
|
||||
{
|
||||
Expression*exp = NULL;
|
||||
bool wrkand_required = false;
|
||||
const VType*type = NULL;
|
||||
|
||||
if(!scope)
|
||||
return false;
|
||||
|
||||
if(prefix_.get())
|
||||
prefix_->try_workarounds_(out, ent, scope, indices, data_size);
|
||||
|
||||
if(index_ && !lsb_ && scope->find_constant(name_, type, exp)) {
|
||||
while(const VTypeDef*type_def = dynamic_cast<const VTypeDef*>(type)) {
|
||||
type = type_def->peek_definition();
|
||||
}
|
||||
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
|
||||
assert(arr);
|
||||
wrkand_required |= check_const_array_workaround_(arr, scope, indices, data_size);
|
||||
}
|
||||
|
||||
if(prefix_.get() && scope->find_constant(prefix_->name_, type, exp)) {
|
||||
// Handle the case of array of records
|
||||
if(prefix_->index_) {
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
|
||||
assert(arr);
|
||||
type = arr->element_type();
|
||||
data_size = type->get_width(scope);
|
||||
}
|
||||
|
||||
while(const VTypeDef*type_def = dynamic_cast<const VTypeDef*>(type)) {
|
||||
type = type_def->peek_definition();
|
||||
}
|
||||
|
||||
const VTypeRecord*rec = dynamic_cast<const VTypeRecord*>(type);
|
||||
assert(rec);
|
||||
|
||||
wrkand_required |= check_const_record_workaround_(rec, scope, indices, data_size);
|
||||
}
|
||||
|
||||
return wrkand_required;
|
||||
}
|
||||
|
||||
bool ExpName::check_const_array_workaround_(const VTypeArray*arr,
|
||||
ScopeBase*scope, list<index_t*>&indices, int&data_size) const
|
||||
{
|
||||
const VType*element = arr->element_type();
|
||||
data_size = element->get_width(scope);
|
||||
if(data_size < 0)
|
||||
return false;
|
||||
indices.push_back(new index_t(index_, new ExpInteger(data_size)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpName::check_const_record_workaround_(const VTypeRecord*rec,
|
||||
ScopeBase*scope, list<index_t*>&indices, int&data_size) const
|
||||
{
|
||||
int tmp_offset = 0;
|
||||
const vector<VTypeRecord::element_t*>& elements = rec->get_elements();
|
||||
|
||||
for(vector<VTypeRecord::element_t*>::const_reverse_iterator it = elements.rbegin();
|
||||
it != elements.rend(); ++it) {
|
||||
VTypeRecord::element_t* el = (*it);
|
||||
|
||||
if(el->peek_name() == name_) {
|
||||
const VType*type = el->peek_type();
|
||||
|
||||
int tmp_field = type->get_width(scope);
|
||||
if(tmp_field < 0)
|
||||
return false;
|
||||
|
||||
data_size = tmp_field;
|
||||
indices.push_back(new index_t(NULL, NULL, new ExpInteger(tmp_offset)));
|
||||
|
||||
if(index_) {
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
|
||||
assert(arr);
|
||||
return check_const_array_workaround_(arr, scope, indices, data_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int w = el->peek_type()->get_width(scope);
|
||||
|
||||
if(w < 0)
|
||||
return false;
|
||||
|
||||
tmp_offset += w;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ExpName::emit_workaround_(ostream&out, Entity*ent, ScopeBase*scope,
|
||||
const list<index_t*>& indices, int field_size)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << "\\" << (prefix_.get() ? prefix_->name_ : name_) << " [";
|
||||
|
||||
for(list<index_t*>::const_iterator it = indices.begin();
|
||||
it != indices.end(); ++it) {
|
||||
errors += (*it)->emit(out, ent, scope);
|
||||
out << "+";
|
||||
}
|
||||
|
||||
out << ":" << field_size << "]";
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
bool ExpName::is_primary(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (fun_) {
|
||||
case EQ:
|
||||
@@ -766,7 +941,37 @@ int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpShift::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
out << " >> ";
|
||||
break;
|
||||
case SLL:
|
||||
out << " << ";
|
||||
break;
|
||||
case SRA:
|
||||
out << " >>> ";
|
||||
break;
|
||||
case SLA:
|
||||
out << " <<< ";
|
||||
break;
|
||||
case ROR:
|
||||
case ROL:
|
||||
out << " /* ?ror/rol? */ ";
|
||||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -775,13 +980,13 @@ bool ExpString::is_primary(void) const
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpString::emit(ostream& out, Entity*ent, Architecture*arc)
|
||||
int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
const VType*type = peek_type();
|
||||
assert(type != 0);
|
||||
|
||||
if (const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type)) {
|
||||
return emit_as_array_(out, ent, arc, arr);
|
||||
return emit_as_array_(out, ent, scope, arr);
|
||||
}
|
||||
|
||||
out << "\"";
|
||||
@@ -792,7 +997,7 @@ int ExpString::emit(ostream& out, Entity*ent, Architecture*arc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeArray*arr)
|
||||
int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr)
|
||||
{
|
||||
int errors = 0;
|
||||
assert(arr->dimensions() == 1);
|
||||
@@ -815,48 +1020,51 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA
|
||||
assert(etype->type() != VTypePrimitive::INTEGER);
|
||||
out << value_.size() << "'b";
|
||||
for (size_t idx = 0 ; idx < value_.size() ; idx += 1) {
|
||||
switch (value_[idx]) {
|
||||
case '0':
|
||||
out << "0";
|
||||
break;
|
||||
case '1':
|
||||
out << "1";
|
||||
break;
|
||||
case 'z': case 'Z':
|
||||
assert(etype->type() == VTypePrimitive::STDLOGIC);
|
||||
out << "z";
|
||||
break;
|
||||
case '-':
|
||||
assert(etype->type() == VTypePrimitive::STDLOGIC);
|
||||
out << "x";
|
||||
break;
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Don't know how to handle bit " << value_[idx]
|
||||
<< " with etype==" << etype->type() << endl;
|
||||
assert(etype->type() == VTypePrimitive::STDLOGIC);
|
||||
out << "x";
|
||||
break;
|
||||
}
|
||||
int res = emit_logic(value_[idx], out, etype->type());
|
||||
errors += res;
|
||||
|
||||
if(res)
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Don't know how to handle bit " << value_[idx]
|
||||
<< " with etype==" << etype->type() << endl;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "abs(";
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "~(";
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += type_->emit_def(out, empty_perm_string);
|
||||
out << "'(";
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpNew::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "new[";
|
||||
errors += size_->emit(out, ent, scope);
|
||||
out << "]";
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -26,12 +28,11 @@ bool Expression::evaluate(ScopeBase*, int64_t&) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Expression::evaluate(Entity*, Architecture*arc, int64_t&val) const
|
||||
bool Expression::evaluate(Entity*, ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
return evaluate(arc, val);
|
||||
return evaluate(scope, val);
|
||||
}
|
||||
|
||||
|
||||
bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
int64_t val1, val2;
|
||||
@@ -76,67 +77,92 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
|
||||
bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
/* Special Case: The length attribute can be calculated all
|
||||
/* Special Case: The array attributes can sometimes be calculated all
|
||||
the down to a literal integer at compile time, and all it
|
||||
needs is the type of the base expression. (The base
|
||||
expression doesn't even need to be evaluated.) */
|
||||
if (name_ == "length") {
|
||||
if (name_ == "length" || name_ == "right" || name_ == "left") {
|
||||
const VType*base_type = base_->peek_type();
|
||||
//if (base_type == 0)
|
||||
// base_type = base_->probe_type(ent,arc);
|
||||
|
||||
ivl_assert(*this, base_type);
|
||||
if(!base_type) {
|
||||
const ExpName*name = NULL;
|
||||
|
||||
if(scope && (name = dynamic_cast<const ExpName*>(base_))) {
|
||||
const perm_string& n = name->peek_name();
|
||||
if(const Variable*var = scope->find_variable(n))
|
||||
base_type = var->peek_type();
|
||||
else if(const Signal*sig = scope->find_signal(n))
|
||||
base_type = sig->peek_type();
|
||||
else if(const InterfacePort*port = scope->find_param(n))
|
||||
base_type = port->type;
|
||||
}
|
||||
}
|
||||
|
||||
if(!base_type)
|
||||
return false; // I tried really hard, sorry
|
||||
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
|
||||
if (arr == 0) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
cerr << endl << get_fileline() << ": error: "
|
||||
<< "Cannot apply the 'length attribute to non-array objects"
|
||||
<< endl;
|
||||
ivl_assert(*this, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t size = 1;
|
||||
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
|
||||
const VTypeArray::range_t&dim = arr->dimension(idx);
|
||||
ivl_assert(*this, ! dim.is_box());
|
||||
size *= 1 + labs(dim.msb() - dim.lsb());
|
||||
}
|
||||
val = size;
|
||||
if(name_ == "length") {
|
||||
int64_t size = arr->get_width(scope);
|
||||
|
||||
if(size > 0)
|
||||
val = size;
|
||||
else
|
||||
return false;
|
||||
} else if(name_ == "left") {
|
||||
arr->dimension(0).msb()->evaluate(scope, val);
|
||||
} else if(name_ == "right") {
|
||||
arr->dimension(0).lsb()->evaluate(scope, val);
|
||||
} else ivl_assert(*this, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
|
||||
bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
if (!ent || !scope) { // it's impossible to evaluate, probably it is inside a subprogram
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name_ == "left" || name_ == "right") {
|
||||
const VType*base_type = base_->peek_type();
|
||||
if (base_type == 0)
|
||||
base_type = base_->probe_type(ent,arc);
|
||||
base_type = base_->probe_type(ent, scope);
|
||||
|
||||
ivl_assert(*this, base_type);
|
||||
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
|
||||
if (arr == 0) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
cerr << endl << get_fileline() << ": error: "
|
||||
<< "Cannot apply the '" << name_
|
||||
<< " attribute to non-array objects" << endl;
|
||||
ivl_assert(*this, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
ivl_assert(*this, arr->dimensions() == 1);
|
||||
if(name_ == "left")
|
||||
arr->dimension(0).msb()->evaluate(ent, arc, val);
|
||||
else
|
||||
arr->dimension(0).lsb()->evaluate(ent, arc, val);
|
||||
arr->dimension(0).msb()->evaluate(ent, scope, val);
|
||||
else // "right"
|
||||
arr->dimension(0).lsb()->evaluate(ent, scope, val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return evaluate(arc, val);
|
||||
return evaluate(scope, val);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,14 +184,16 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rc = scope->find_constant(name_, type, exp);
|
||||
if (rc == false)
|
||||
if (!scope)
|
||||
return false;
|
||||
|
||||
if (!scope->find_constant(name_, type, exp))
|
||||
return false;
|
||||
|
||||
return exp->evaluate(scope, val);
|
||||
}
|
||||
|
||||
bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
|
||||
bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
if (prefix_.get()) {
|
||||
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
|
||||
@@ -178,8 +206,42 @@ bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
|
||||
|
||||
// Evaluate the default expression and use that.
|
||||
if (gen->expr)
|
||||
return gen->expr->evaluate(ent, arc, val);
|
||||
return gen->expr->evaluate(ent, scope, val);
|
||||
}
|
||||
|
||||
return evaluate(arc, val);
|
||||
return evaluate(scope, val);
|
||||
}
|
||||
|
||||
bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
int64_t val1, val2;
|
||||
bool rc;
|
||||
|
||||
rc = eval_operand1(scope, val1);
|
||||
if (rc == false)
|
||||
return false;
|
||||
|
||||
rc = eval_operand2(scope, val2);
|
||||
if (rc == false)
|
||||
return false;
|
||||
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
val = (uint64_t)val1 >> (uint64_t)val2;
|
||||
break;
|
||||
case SLL:
|
||||
val = (uint64_t)val1 << (uint64_t)val2;
|
||||
break;
|
||||
case SRA:
|
||||
val = (int64_t)val1 >> (int64_t)val2;
|
||||
break;
|
||||
case SLA:
|
||||
val = (int64_t)val1 << (int64_t)val2;
|
||||
break;
|
||||
case ROR:
|
||||
case ROL:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+89
-22
@@ -24,7 +24,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ExpAggregate::write_to_stream(ostream&fd)
|
||||
void ExpAggregate::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "(";
|
||||
for (vector<element_t*>::const_iterator cur = elements_.begin()
|
||||
@@ -73,7 +73,7 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd)
|
||||
fd << "/* ERROR */";
|
||||
}
|
||||
|
||||
void ExpArithmetic::write_to_stream(ostream&out)
|
||||
void ExpArithmetic::write_to_stream(ostream&out) const
|
||||
{
|
||||
out << "(";
|
||||
write_to_stream_operand1(out);
|
||||
@@ -111,23 +111,23 @@ void ExpArithmetic::write_to_stream(ostream&out)
|
||||
out << ")";
|
||||
}
|
||||
|
||||
void ExpAttribute::write_to_stream(ostream&fd)
|
||||
void ExpAttribute::write_to_stream(ostream&fd) const
|
||||
{
|
||||
base_->write_to_stream(fd);
|
||||
fd << "'" << name_;
|
||||
}
|
||||
|
||||
void ExpBitstring::write_to_stream(ostream&fd)
|
||||
void ExpBitstring::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "\"";
|
||||
for(vector<char>::const_iterator it = value_.begin();
|
||||
it != value_.end(); ++it) {
|
||||
fd << "B\"";
|
||||
for(vector<char>::const_reverse_iterator it = value_.rbegin();
|
||||
it != value_.rend(); ++it) {
|
||||
fd << *it;
|
||||
}
|
||||
fd << "\"";
|
||||
}
|
||||
|
||||
void ExpCharacter::write_to_stream(ostream&fd)
|
||||
void ExpCharacter::write_to_stream(ostream&fd) const
|
||||
{
|
||||
char buf[4];
|
||||
buf[0] = '\'';
|
||||
@@ -137,7 +137,7 @@ void ExpCharacter::write_to_stream(ostream&fd)
|
||||
fd << buf;
|
||||
}
|
||||
|
||||
void ExpConcat::write_to_stream(ostream&fd)
|
||||
void ExpConcat::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "(";
|
||||
operand1_->write_to_stream(fd);
|
||||
@@ -146,21 +146,21 @@ void ExpConcat::write_to_stream(ostream&fd)
|
||||
fd << ")";
|
||||
}
|
||||
|
||||
void ExpConditional::write_to_stream(ostream&)
|
||||
void ExpConditional::write_to_stream(ostream&) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
}
|
||||
|
||||
void ExpEdge::write_to_stream(ostream&)
|
||||
void ExpEdge::write_to_stream(ostream&) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
}
|
||||
|
||||
void ExpFunc::write_to_stream(ostream&fd)
|
||||
void ExpFunc::write_to_stream(ostream&fd) const
|
||||
{
|
||||
const char*comma = "";
|
||||
fd << name_ << "(";
|
||||
for (vector<Expression*>::iterator cur = argv_.begin()
|
||||
for (vector<Expression*>::const_iterator cur = argv_.begin()
|
||||
; cur != argv_.end() ; ++cur) {
|
||||
fd << comma;
|
||||
(*cur)->write_to_stream(fd);
|
||||
@@ -169,22 +169,22 @@ void ExpFunc::write_to_stream(ostream&fd)
|
||||
fd << ")";
|
||||
}
|
||||
|
||||
void ExpInteger::write_to_stream(ostream&fd)
|
||||
void ExpInteger::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << value_;
|
||||
}
|
||||
|
||||
void ExpReal::write_to_stream(ostream&fd)
|
||||
void ExpReal::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << value_;
|
||||
}
|
||||
|
||||
void ExpLogical::write_to_stream(ostream&)
|
||||
void ExpLogical::write_to_stream(ostream&) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
}
|
||||
|
||||
void ExpName::write_to_stream(ostream&fd)
|
||||
void ExpName::write_to_stream(ostream&fd) const
|
||||
{
|
||||
if (prefix_.get()) {
|
||||
prefix_->write_to_stream(fd);
|
||||
@@ -203,12 +203,73 @@ void ExpName::write_to_stream(ostream&fd)
|
||||
}
|
||||
}
|
||||
|
||||
void ExpRelation::write_to_stream(ostream&)
|
||||
void ExpRelation::write_to_stream(ostream&fd) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
peek_operand1()->write_to_stream(fd);
|
||||
|
||||
switch(fun_) {
|
||||
case EQ:
|
||||
fd << " = ";
|
||||
break;
|
||||
|
||||
case LT:
|
||||
fd << " < ";
|
||||
break;
|
||||
|
||||
case GT:
|
||||
fd << " > ";
|
||||
break;
|
||||
|
||||
case NEQ:
|
||||
fd << " != ";
|
||||
break;
|
||||
|
||||
case LE:
|
||||
fd << " <= ";
|
||||
break;
|
||||
|
||||
case GE:
|
||||
fd << " >= ";
|
||||
break;
|
||||
}
|
||||
|
||||
peek_operand2()->write_to_stream(fd);
|
||||
}
|
||||
|
||||
void ExpString::write_to_stream(ostream&fd)
|
||||
void ExpShift::write_to_stream(ostream&out) const
|
||||
{
|
||||
out << "(";
|
||||
write_to_stream_operand1(out);
|
||||
out << ")";
|
||||
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
out << "srl";
|
||||
break;
|
||||
case SLL:
|
||||
out << "sll";
|
||||
break;
|
||||
case SLA:
|
||||
out << "sla";
|
||||
break;
|
||||
case SRA:
|
||||
out << "sra";
|
||||
break;
|
||||
case ROR:
|
||||
out << "ror";
|
||||
break;
|
||||
case ROL:
|
||||
out << "rol";
|
||||
break;
|
||||
}
|
||||
|
||||
out << "(";
|
||||
write_to_stream_operand2(out);
|
||||
out << ")";
|
||||
}
|
||||
|
||||
|
||||
void ExpString::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "\"";
|
||||
for(vector<char>::const_iterator it = value_.begin();
|
||||
@@ -218,15 +279,21 @@ void ExpString::write_to_stream(ostream&fd)
|
||||
fd << "\"";
|
||||
}
|
||||
|
||||
void ExpUAbs::write_to_stream(ostream&fd)
|
||||
void ExpUAbs::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "abs ";
|
||||
write_to_stream_operand1(fd);
|
||||
}
|
||||
|
||||
void ExpUNot::write_to_stream(ostream&fd)
|
||||
void ExpUNot::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "not ";
|
||||
write_to_stream_operand1(fd);
|
||||
}
|
||||
|
||||
void ExpCast::write_to_stream(ostream&fd) const
|
||||
{
|
||||
// Type casting is introduced only for a few specific cases in
|
||||
// SystemVerilog, so no need to use it here
|
||||
base_->write_to_stream(fd);
|
||||
}
|
||||
|
||||
+45
-8
@@ -108,6 +108,7 @@ static string make_library_package_path(perm_string lib_name, perm_string name)
|
||||
|
||||
static void import_ieee(void);
|
||||
static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name);
|
||||
static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name);
|
||||
|
||||
static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack)
|
||||
{
|
||||
@@ -211,6 +212,9 @@ void library_import(const YYLTYPE&loc, const std::list<perm_string>*names)
|
||||
// The ieee library is special and handled by an
|
||||
// internal function.
|
||||
import_ieee();
|
||||
} else if (*cur == "std") {
|
||||
// The std library is always implicitly imported.
|
||||
|
||||
} else if (*cur == "work") {
|
||||
// The work library is always implicitly imported.
|
||||
|
||||
@@ -238,6 +242,11 @@ void library_use(const YYLTYPE&loc, ActiveScope*res,
|
||||
import_ieee_use(res, use_package, use_name);
|
||||
return;
|
||||
}
|
||||
// Special case handling for the STD library.
|
||||
if (use_library == "std") {
|
||||
import_std_use(loc, res, use_package, use_name);
|
||||
return;
|
||||
}
|
||||
|
||||
struct library_contents&lib = libraries[use_library];
|
||||
Package*pack = lib.packages[use_package];
|
||||
@@ -361,15 +370,28 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
|
||||
}
|
||||
}
|
||||
|
||||
static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string package, perm_string name)
|
||||
{
|
||||
if (package == "standard") {
|
||||
// do nothing
|
||||
return;
|
||||
} else if (package == "textio") {
|
||||
cerr << "warning: textio package not really supported" << endl;
|
||||
return;
|
||||
} else {
|
||||
sorrymsg(loc, "package %s of library %s not yet supported", package.str(), name.str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true);
|
||||
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
|
||||
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
|
||||
const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL);
|
||||
const VTypePrimitive primitive_REAL(VTypePrimitive::REAL);
|
||||
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true);
|
||||
const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER);
|
||||
|
||||
const VTypeRange primitive_NATURAL(&primitive_INTEGER, INT64_MAX, 0);
|
||||
|
||||
static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_STRING(&primitive_CHARACTER, vector<VTypeArray::range_t> (1));
|
||||
@@ -382,11 +404,19 @@ void generate_global_types(ActiveScope*res)
|
||||
res->use_name(perm_string::literal("real"), &primitive_REAL);
|
||||
res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC);
|
||||
res->use_name(perm_string::literal("character"), &primitive_CHARACTER);
|
||||
res->use_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR);
|
||||
res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR);
|
||||
res->use_name(perm_string::literal("string"), &primitive_STRING);
|
||||
res->use_name(perm_string::literal("natural"), &primitive_NATURAL);
|
||||
}
|
||||
|
||||
void emit_std_types(ostream&out)
|
||||
{
|
||||
out << "`ifndef __VHDL_STD_TYPES" << endl;
|
||||
out << "`define __VHDL_STD_TYPES" << endl;
|
||||
out << "typedef enum bit { \\false , \\true } boolean ;" << endl;
|
||||
out << "`endif" << endl;
|
||||
}
|
||||
|
||||
bool is_global_type(perm_string name)
|
||||
{
|
||||
if (name == "boolean") return true;
|
||||
@@ -394,10 +424,13 @@ bool is_global_type(perm_string name)
|
||||
if (name == "integer") return true;
|
||||
if (name == "real") return true;
|
||||
if (name == "std_logic") return true;
|
||||
if (name == "std_logic_vector") return true;
|
||||
if (name == "character") return true;
|
||||
if (name == "bit_vector") return true;
|
||||
if (name == "string") return true;
|
||||
if (name == "natural") return true;
|
||||
if (name == "signed") return true;
|
||||
if (name == "unsigned") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -407,13 +440,10 @@ void library_set_work_path(const char*path)
|
||||
library_work_path = path;
|
||||
}
|
||||
|
||||
list<const Package*> work_packages;
|
||||
static void store_package_in_work(const Package*pack)
|
||||
{
|
||||
string path = make_work_package_path(pack->name());
|
||||
|
||||
ofstream file (path.c_str(), ios_base::out);
|
||||
|
||||
pack->write_to_stream(file);
|
||||
work_packages.push_back(pack);
|
||||
}
|
||||
|
||||
static int emit_packages(perm_string, const map<perm_string,Package*>&packages)
|
||||
@@ -424,6 +454,13 @@ static int emit_packages(perm_string, const map<perm_string,Package*>&packages)
|
||||
errors += cur->second->emit_package(cout);
|
||||
}
|
||||
|
||||
for (list<const Package*>::const_iterator cur = work_packages.begin()
|
||||
; cur != work_packages.end(); ++cur) {
|
||||
string path = make_work_package_path((*cur)->name());
|
||||
ofstream file (path.c_str(), ios_base::out);
|
||||
(*cur)->write_to_stream(file);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ extern void library_add_directory(const char*directory);
|
||||
|
||||
extern Subprogram*library_find_subprogram(perm_string name);
|
||||
|
||||
extern void emit_std_types(ostream&out);
|
||||
extern int emit_packages(void);
|
||||
|
||||
#endif /* IVL_library_H */
|
||||
|
||||
@@ -232,6 +232,8 @@ int main(int argc, char*argv[])
|
||||
return 3;
|
||||
}
|
||||
|
||||
emit_std_types(cout);
|
||||
|
||||
errors = emit_packages();
|
||||
if (errors > 0) {
|
||||
fprintf(stderr, "%d errors emitting packages.\n", errors);
|
||||
|
||||
+7
-8
@@ -73,12 +73,6 @@ void Package::write_to_stream(ostream&fd) const
|
||||
// Do not include global types in types dump
|
||||
if (is_global_type(cur->first))
|
||||
continue;
|
||||
if (cur->first == "std_logic_vector")
|
||||
continue;
|
||||
if (cur->first == "signed")
|
||||
continue;
|
||||
if (cur->first == "unsigned")
|
||||
continue;
|
||||
|
||||
fd << "type " << cur->first << " is ";
|
||||
cur->second->write_type_to_stream(fd);
|
||||
@@ -90,8 +84,6 @@ void Package::write_to_stream(ostream&fd) const
|
||||
// Do not include global types in types dump
|
||||
if (is_global_type(cur->first))
|
||||
continue;
|
||||
if (cur->first == "std_logic_vector")
|
||||
continue;
|
||||
|
||||
fd << "type " << cur->first << " is ";
|
||||
cur->second->write_type_to_stream(fd);
|
||||
@@ -130,4 +122,11 @@ void Package::write_to_stream(ostream&fd) const
|
||||
}
|
||||
|
||||
fd << "end package " << name_ << ";" << endl;
|
||||
|
||||
fd << "package body " << name_ << " is" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++cur) {
|
||||
cur->second->write_to_stream_body(fd);
|
||||
}
|
||||
fd << "end " << name_ << ";" << endl;
|
||||
}
|
||||
|
||||
+18
-14
@@ -32,25 +32,22 @@ int Package::emit_package(ostream&fd) const
|
||||
if (cur_types_.empty() && cur_constants_.empty() && cur_subprograms_.empty())
|
||||
return 0;
|
||||
|
||||
// If this package was imported from a library, then do not
|
||||
// emit it again.
|
||||
if (from_library_.str() != 0) {
|
||||
fd << "/* Suppress package " << name()
|
||||
<< " from library " << from_library_ << " */" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int errors = 0;
|
||||
|
||||
fd << "package \\" << name() << " ;" << endl;
|
||||
fd << "`ifndef package_" << name() << endl;
|
||||
fd << "`define package_" << name() << endl;
|
||||
|
||||
// Only emit types that were defined within this package. Skip
|
||||
// the types that were imported from elsewhere.
|
||||
typedef_context_t typedef_ctx;
|
||||
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
|
||||
; cur != cur_types_.end() ; ++ cur) {
|
||||
fd << "typedef ";
|
||||
errors += cur->second->emit_def(fd, cur->first);
|
||||
fd << " ;" << endl;
|
||||
if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
|
||||
errors += def->emit_typedef(fd, typedef_ctx);
|
||||
//fd << "typedef ";
|
||||
//errors += cur->second->emit_def(fd,
|
||||
//dynamic_cast<const VTypeDef*>(cur->second) ? empty_perm_string : cur->first);
|
||||
//fd << " ;" << endl;
|
||||
}
|
||||
|
||||
//for (map<perm_string,struct const_t*>::const_iterator cur = use_constants_.begin()
|
||||
@@ -66,12 +63,19 @@ int Package::emit_package(ostream&fd) const
|
||||
//fd << ";" << endl;
|
||||
//}
|
||||
|
||||
fd << "package \\" << name() << " ;" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||
errors += cur->second->emit_package(fd);
|
||||
// Do not emit unbounded functions, we will just need fixed instances later
|
||||
if(!cur->second->unbounded())
|
||||
errors += cur->second->emit_package(fd);
|
||||
else
|
||||
fd << "/* function " << cur->second->name() <<
|
||||
" has to be instantiated, skipping */" << endl;
|
||||
}
|
||||
|
||||
fd << "endpackage" << endl;
|
||||
fd << "endpackage /* " << name() << " */" << endl;
|
||||
fd << "`endif" << endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
+184
-46
@@ -8,7 +8,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2013 Stephen Williams ([email protected])
|
||||
* Copyright CERN 2012-2014 / Stephen Williams ([email protected]),
|
||||
* Maciej Suminski ([email protected])
|
||||
* @author Maciej Suminski ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -260,6 +260,8 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
||||
Architecture::Statement* arch_statement;
|
||||
std::list<Architecture::Statement*>* arch_statement_list;
|
||||
|
||||
ReportStmt::severity_t severity;
|
||||
|
||||
Subprogram*subprogram;
|
||||
};
|
||||
|
||||
@@ -314,7 +316,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
||||
|
||||
%type <arch_statement> concurrent_statement component_instantiation_statement
|
||||
%type <arch_statement> concurrent_conditional_signal_assignment
|
||||
%type <arch_statement> concurrent_signal_assignment_statement
|
||||
%type <arch_statement> concurrent_signal_assignment_statement concurrent_simple_signal_assignment
|
||||
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
|
||||
%type <arch_statement> process_statement
|
||||
%type <arch_statement_list> architecture_statement_part generate_statement_body
|
||||
@@ -348,15 +350,16 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
||||
|
||||
%type <text> architecture_body_start package_declaration_start
|
||||
%type <text> package_body_start
|
||||
%type <text> identifier_opt identifier_colon_opt logical_name suffix
|
||||
%type <text> identifier_opt identifier_colon_opt logical_name suffix instantiated_unit
|
||||
|
||||
%type <name_list> logical_name_list identifier_list
|
||||
%type <name_list> enumeration_literal_list enumeration_literal
|
||||
|
||||
%type <sequ_list> if_statement_else sequence_of_statements subprogram_statement_part
|
||||
%type <sequ> sequential_statement if_statement signal_assignment_statement
|
||||
%type <sequ> sequential_statement if_statement signal_assignment signal_assignment_statement
|
||||
%type <sequ> case_statement procedure_call procedure_call_statement
|
||||
%type <sequ> loop_statement variable_assignment_statement
|
||||
%type <sequ> return_statement
|
||||
%type <sequ> loop_statement variable_assignment variable_assignment_statement
|
||||
%type <sequ> assertion_statement report_statement return_statement
|
||||
|
||||
%type <range> range
|
||||
%type <range_list> range_list index_constraint
|
||||
@@ -371,6 +374,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
||||
%type <exp_else_list> else_when_waveforms
|
||||
|
||||
%type <subprogram> function_specification subprogram_specification subprogram_body_start
|
||||
%type <severity> severity severity_opt
|
||||
|
||||
%%
|
||||
|
||||
@@ -433,6 +437,22 @@ architecture_statement_part
|
||||
}
|
||||
;
|
||||
|
||||
assertion_statement
|
||||
: K_assert expression report_statement
|
||||
{ ReportStmt*report = dynamic_cast<ReportStmt*>($3);
|
||||
assert(report);
|
||||
AssertStmt*tmp = new AssertStmt($2, report->message().c_str(), report->severity());
|
||||
delete report;
|
||||
FILE_NAME(tmp,@2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_assert expression severity_opt ';'
|
||||
{ AssertStmt*tmp = new AssertStmt($2, NULL, $3);
|
||||
FILE_NAME(tmp,@2);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
association_element
|
||||
: IDENTIFIER ARROW expression
|
||||
{ named_expr_t*tmp = new named_expr_t(lex_strings.make($1), $3);
|
||||
@@ -573,20 +593,40 @@ case_statement_alternative_list
|
||||
* statement alternative and pass that up instead.
|
||||
*/
|
||||
case_statement_alternative
|
||||
: K_when choice ARROW sequence_of_statements
|
||||
: K_when choices ARROW sequence_of_statements
|
||||
{ CaseSeqStmt::CaseStmtAlternative* tmp;
|
||||
if ($2->others()) {
|
||||
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
|
||||
} else if (Expression*ex = $2->simple_expression()) {
|
||||
tmp = new CaseSeqStmt::CaseStmtAlternative(ex, $4);
|
||||
} else {
|
||||
errormsg(@2, "I don't know what to make of the case choice\n");
|
||||
tmp = 0;
|
||||
}
|
||||
if (tmp) FILE_NAME(tmp, @1);
|
||||
delete $2;
|
||||
delete $4;
|
||||
$$ = tmp;
|
||||
std::list<ExpAggregate::choice_t*>*choices = $2;
|
||||
std::list<Expression*>*exp_list = new std::list<Expression*>;
|
||||
bool others = false;
|
||||
|
||||
for(std::list<ExpAggregate::choice_t*>::iterator it = choices->begin();
|
||||
it != choices->end(); ++it) {
|
||||
if((*it)->others() || others)
|
||||
// If there is one "others", then it also covers all other alternatives
|
||||
// Continue the loop to delete every choice_t, but do not
|
||||
// bother to add the expressions to the exp_list (we are going to
|
||||
// delete them very soon)
|
||||
others = true;
|
||||
else
|
||||
exp_list->push_back((*it)->simple_expression());
|
||||
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
if(others) {
|
||||
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
|
||||
for(std::list<Expression*>::iterator it = exp_list->begin();
|
||||
it != exp_list->end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
} else {
|
||||
tmp = new CaseSeqStmt::CaseStmtAlternative(exp_list, $4);
|
||||
}
|
||||
if (tmp) FILE_NAME(tmp, @1);
|
||||
|
||||
delete choices;
|
||||
delete $4;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -657,22 +697,27 @@ component_declaration
|
||||
}
|
||||
;
|
||||
|
||||
instantiated_unit
|
||||
: IDENTIFIER
|
||||
| K_component IDENTIFIER { $$ = $2; }
|
||||
;
|
||||
|
||||
component_instantiation_statement
|
||||
: IDENTIFIER ':' K_component_opt IDENTIFIER generic_map_aspect_opt port_map_aspect_opt ';'
|
||||
: IDENTIFIER ':' instantiated_unit generic_map_aspect_opt port_map_aspect_opt ';'
|
||||
{ perm_string iname = lex_strings.make($1);
|
||||
perm_string cname = lex_strings.make($4);
|
||||
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5, $6);
|
||||
perm_string cname = lex_strings.make($3);
|
||||
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $4, $5);
|
||||
delete $4;
|
||||
delete $5;
|
||||
delete $6;
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
delete[]$4;
|
||||
delete[]$3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER ':' K_component_opt IDENTIFIER error ';'
|
||||
| IDENTIFIER ':' instantiated_unit error ';'
|
||||
{ errormsg(@4, "Errors in component instantiation.\n");
|
||||
delete[]$1;
|
||||
delete[]$4;
|
||||
delete[]$3;
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
@@ -706,7 +751,6 @@ composite_type_definition
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
/* The when...else..when...else syntax is not a general expression
|
||||
in VHDL but a specific sort of assignment statement model. We
|
||||
create Exppression objects for it, but the parser will only
|
||||
@@ -743,6 +787,17 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
|
||||
}
|
||||
;
|
||||
|
||||
concurrent_simple_signal_assignment
|
||||
: name LEQ waveform ';'
|
||||
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
||||
$$ = tmp;
|
||||
delete $3;
|
||||
}
|
||||
|
||||
else_when_waveforms
|
||||
: else_when_waveforms else_when_waveform
|
||||
{ list<ExpConditional::else_t*>*tmp = $1;
|
||||
@@ -770,18 +825,14 @@ else_when_waveform
|
||||
;
|
||||
|
||||
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
|
||||
: name LEQ waveform ';'
|
||||
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
: concurrent_simple_signal_assignment
|
||||
|
||||
$$ = tmp;
|
||||
delete $3;
|
||||
}
|
||||
| IDENTIFIER ':' concurrent_simple_signal_assignment { $$ = $3; }
|
||||
|
||||
| concurrent_conditional_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; }
|
||||
|
||||
| name LEQ error ';'
|
||||
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
||||
delete $1;
|
||||
@@ -1539,10 +1590,17 @@ mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
|
||||
|
||||
name /* IEEE 1076-2008 P8.1 */
|
||||
: IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */
|
||||
{ ExpName*tmp = new ExpName(lex_strings.make($1));
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
{ Expression*tmp;
|
||||
if(!strcasecmp($1, "true"))
|
||||
tmp = new ExpBitstring("1");
|
||||
else if(!strcasecmp($1, "false"))
|
||||
tmp = new ExpBitstring("0");
|
||||
else
|
||||
tmp = new ExpName(lex_strings.make($1));
|
||||
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| selected_name
|
||||
@@ -1570,11 +1628,16 @@ name /* IEEE 1076-2008 P8.1 */
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| selected_name '(' range ')'
|
||||
| selected_name '(' range ')'
|
||||
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
|
||||
tmp->set_range($3->msb(), $3->lsb());
|
||||
$$ = tmp;
|
||||
}
|
||||
| selected_name '(' expression ')'
|
||||
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
|
||||
tmp->set_range($3, NULL);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* Handle name lists as lists of expressions. */
|
||||
@@ -1771,6 +1834,7 @@ primary
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/*XXXX Caught up in element_association_list?
|
||||
| '(' expression ')'
|
||||
{ $$ = $2; }
|
||||
@@ -1993,6 +2057,14 @@ relation
|
||||
}
|
||||
;
|
||||
|
||||
report_statement
|
||||
: K_report STRING_LITERAL severity_opt ';'
|
||||
{ ReportStmt*tmp = new ReportStmt($2, $3);
|
||||
FILE_NAME(tmp,@2);
|
||||
delete[]$2;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
return_statement
|
||||
: K_return expression ';'
|
||||
{ ReturnStmt*tmp = new ReturnStmt($2);
|
||||
@@ -2100,6 +2172,8 @@ sequential_statement
|
||||
| procedure_call_statement { $$ = $1; }
|
||||
| loop_statement { $$ = $1; }
|
||||
| return_statement { $$ = $1; }
|
||||
| report_statement { $$ = $1; }
|
||||
| assertion_statement { $$ = $1; }
|
||||
| K_null ';' { $$ = 0; }
|
||||
| error ';'
|
||||
{ errormsg(@1, "Syntax error in sequential statement.\n");
|
||||
@@ -2108,7 +2182,61 @@ sequential_statement
|
||||
}
|
||||
;
|
||||
|
||||
shift_expression : simple_expression { $$ = $1; } ;
|
||||
severity
|
||||
: K_severity IDENTIFIER
|
||||
{ if(!strcasecmp($2, "NOTE"))
|
||||
$$ = ReportStmt::NOTE;
|
||||
else if(!strcasecmp($2, "WARNING"))
|
||||
$$ = ReportStmt::WARNING;
|
||||
else if(!strcasecmp($2, "ERROR"))
|
||||
$$ = ReportStmt::ERROR;
|
||||
else if(!strcasecmp($2, "FAILURE"))
|
||||
$$ = ReportStmt::FAILURE;
|
||||
else {
|
||||
errormsg(@1, "Invalid severity level (possible values: NOTE, WARNING, ERROR, FAILURE).\n");
|
||||
$$ = ReportStmt::UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
severity_opt
|
||||
: severity { $$ = $1; }
|
||||
| { $$ = ReportStmt::UNSPECIFIED; }
|
||||
|
||||
shift_expression
|
||||
: simple_expression
|
||||
| simple_expression K_srl simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SRL, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_sll simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SLL, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_sra simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SRA, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_sla simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SLA, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_ror simple_expression
|
||||
{ sorrymsg(@2, "ROR is not supported.\n");
|
||||
ExpShift*tmp = new ExpShift(ExpShift::ROR, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_rol simple_expression
|
||||
{ sorrymsg(@2, "ROL is not supported.\n");
|
||||
ExpShift*tmp = new ExpShift(ExpShift::ROL, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
sign
|
||||
: '+'
|
||||
@@ -2186,7 +2314,7 @@ simple_expression_terms
|
||||
}
|
||||
;
|
||||
|
||||
signal_assignment_statement
|
||||
signal_assignment
|
||||
: name LEQ waveform ';'
|
||||
{ SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
|
||||
FILE_NAME(tmp, @1);
|
||||
@@ -2201,6 +2329,10 @@ signal_assignment_statement
|
||||
}
|
||||
;
|
||||
|
||||
signal_assignment_statement
|
||||
: signal_assignment
|
||||
| IDENTIFIER ':' signal_assignment { $$ = $3; }
|
||||
|
||||
subprogram_body_start
|
||||
: subprogram_specification K_is
|
||||
{ assert(!active_sub);
|
||||
@@ -2223,7 +2355,7 @@ subprogram_body /* IEEE 1076-2008 P4.3 */
|
||||
} else if (tmp) {
|
||||
errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str());
|
||||
}
|
||||
prog->transfer_from(*active_scope);
|
||||
prog->transfer_from(*active_scope, ScopeBase::VARIABLES);
|
||||
prog->set_program_body($4);
|
||||
active_scope->bind_name(prog->name(), prog);
|
||||
active_sub = NULL;
|
||||
@@ -2373,6 +2505,9 @@ type_declaration
|
||||
tmp->set_definition($4);
|
||||
active_scope->incomplete_types.erase(cur);
|
||||
}
|
||||
if(const VTypeEnum*enum_type = dynamic_cast<const VTypeEnum*>($4)) {
|
||||
active_scope->use_enum(enum_type);
|
||||
}
|
||||
}
|
||||
delete[]$2;
|
||||
}
|
||||
@@ -2429,6 +2564,10 @@ use_clauses_opt
|
||||
;
|
||||
|
||||
variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
|
||||
: variable_assignment
|
||||
| IDENTIFIER ':' variable_assignment { $$ = $3; }
|
||||
|
||||
variable_assignment
|
||||
: name VASSIGN expression ';'
|
||||
{ VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3);
|
||||
FILE_NAME(tmp, @1);
|
||||
@@ -2495,7 +2634,6 @@ waveform_element
|
||||
/* Some keywords are optional in some contexts. In all such cases, a
|
||||
similar rule is used, as described here. */
|
||||
K_architecture_opt : K_architecture | ;
|
||||
K_component_opt : K_component | ;
|
||||
K_configuration_opt: K_configuration| ;
|
||||
K_entity_opt : K_entity | ;
|
||||
K_is_opt : K_is | ;
|
||||
@@ -2504,9 +2642,9 @@ K_postponed_opt : K_postponed | ;
|
||||
K_shared_opt : K_shared | ;
|
||||
%%
|
||||
|
||||
static void yyerror(YYLTYPE*, yyscan_t, const char*, bool, const char* /*msg*/)
|
||||
static void yyerror(YYLTYPE*loc, yyscan_t, const char*, bool, const char*msg)
|
||||
{
|
||||
//fprintf(stderr, "%s\n", msg);
|
||||
fprintf(stderr, "%s:%u: %s\n", loc->text, loc->first_line, msg);
|
||||
parse_errors += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
|
||||
|
||||
VTypeArray*subtype = new VTypeArray(element, range,
|
||||
base_array->signed_vector());
|
||||
subtype->set_parent_type(base_array);
|
||||
return subtype;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ class prange_t {
|
||||
public:
|
||||
prange_t(Expression* left, Expression* right, bool dir)
|
||||
: left_(left), right_(right), direction_(dir), auto_dir_(false) {}
|
||||
prange_t(const prange_t&other) :
|
||||
left_(other.left_->clone()), right_(other.right_->clone()),
|
||||
direction_(other.direction_), auto_dir_(other.auto_dir_) {}
|
||||
~prange_t() { delete left_; delete right_; }
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
@@ -91,7 +94,6 @@ class prange_t {
|
||||
bool auto_dir_;
|
||||
|
||||
private: //not implemented
|
||||
prange_t(const prange_t&);
|
||||
prange_t operator=(const prange_t&);
|
||||
};
|
||||
|
||||
|
||||
+66
-17
@@ -21,6 +21,7 @@
|
||||
# include "scope.h"
|
||||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include "entity.h"
|
||||
# include <algorithm>
|
||||
# include <iostream>
|
||||
# include <iterator>
|
||||
@@ -58,6 +59,8 @@ ScopeBase::ScopeBase(const ActiveScope&ref)
|
||||
use_subprograms_ = ref.use_subprograms_;
|
||||
cur_subprograms_ = ref.cur_subprograms_;
|
||||
|
||||
use_enums_ = ref.use_enums_;
|
||||
|
||||
// This constructor is invoked when the parser is finished with
|
||||
// an active scope and is making the actual scope. At this point
|
||||
// we know that "this" is the parent scope for the subprograms,
|
||||
@@ -101,8 +104,11 @@ const VType*ScopeBase::find_type(perm_string by_name)
|
||||
return cur->second;
|
||||
}
|
||||
|
||||
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp)
|
||||
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const
|
||||
{
|
||||
typ = NULL;
|
||||
exp = NULL;
|
||||
|
||||
map<perm_string,struct const_t*>::const_iterator cur = cur_constants_.find(by_name);
|
||||
if (cur == cur_constants_.end()) {
|
||||
cur = use_constants_.find(by_name);
|
||||
@@ -118,6 +124,8 @@ bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*
|
||||
exp = cur->second->val;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Signal* ScopeBase::find_signal(perm_string by_name) const
|
||||
@@ -148,6 +156,23 @@ Variable* ScopeBase::find_variable(perm_string by_name) const
|
||||
}
|
||||
}
|
||||
|
||||
const InterfacePort* ScopeBase::find_param(perm_string by_name) const
|
||||
{
|
||||
for(map<perm_string,Subprogram*>::const_iterator it = use_subprograms_.begin();
|
||||
it != use_subprograms_.end(); ++it) {
|
||||
if(const InterfacePort*port = it->second->find_param(by_name))
|
||||
return port;
|
||||
}
|
||||
|
||||
for(map<perm_string,Subprogram*>::const_iterator it = cur_subprograms_.begin();
|
||||
it != cur_subprograms_.end(); ++it) {
|
||||
if(const InterfacePort*port = it->second->find_param(by_name))
|
||||
return port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Subprogram* ScopeBase::find_subprogram(perm_string name) const
|
||||
{
|
||||
map<perm_string,Subprogram*>::const_iterator cur;
|
||||
@@ -163,6 +188,17 @@ Subprogram* ScopeBase::find_subprogram(perm_string name) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const
|
||||
{
|
||||
for(list<const VTypeEnum*>::const_iterator it = use_enums_.begin();
|
||||
it != use_enums_.end(); ++it) {
|
||||
if((*it)->has_name(name))
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is only used by the ActiveScope derived class to import
|
||||
* definition from another scope.
|
||||
@@ -201,27 +237,35 @@ void ScopeBase::do_use_from(const ScopeBase*that)
|
||||
; cur != that->cur_constants_.end() ; ++ cur) {
|
||||
use_constants_[cur->first] = cur->second;
|
||||
}
|
||||
|
||||
use_enums_ = that->use_enums_;
|
||||
}
|
||||
|
||||
void ScopeBase::transfer_from(ScopeBase&ref)
|
||||
void ScopeBase::transfer_from(ScopeBase&ref, transfer_type_t what)
|
||||
{
|
||||
std::copy(ref.new_signals_.begin(), ref.new_signals_.end(),
|
||||
insert_iterator<map<perm_string, Signal*> >(
|
||||
new_signals_, new_signals_.end())
|
||||
);
|
||||
ref.new_signals_.clear();
|
||||
if(what & SIGNALS) {
|
||||
std::copy(ref.new_signals_.begin(), ref.new_signals_.end(),
|
||||
insert_iterator<map<perm_string, Signal*> >(
|
||||
new_signals_, new_signals_.end())
|
||||
);
|
||||
ref.new_signals_.clear();
|
||||
}
|
||||
|
||||
std::copy(ref.new_variables_.begin(), ref.new_variables_.end(),
|
||||
insert_iterator<map<perm_string, Variable*> >(
|
||||
new_variables_, new_variables_.end())
|
||||
);
|
||||
ref.new_variables_.clear();
|
||||
if(what & VARIABLES) {
|
||||
std::copy(ref.new_variables_.begin(), ref.new_variables_.end(),
|
||||
insert_iterator<map<perm_string, Variable*> >(
|
||||
new_variables_, new_variables_.end())
|
||||
);
|
||||
ref.new_variables_.clear();
|
||||
}
|
||||
|
||||
std::copy(ref.new_components_.begin(), ref.new_components_.end(),
|
||||
insert_iterator<map<perm_string, ComponentBase*> >(
|
||||
new_components_, new_components_.end())
|
||||
);
|
||||
ref.new_components_.clear();
|
||||
if(what & COMPONENTS) {
|
||||
std::copy(ref.new_components_.begin(), ref.new_components_.end(),
|
||||
insert_iterator<map<perm_string, ComponentBase*> >(
|
||||
new_components_, new_components_.end())
|
||||
);
|
||||
ref.new_components_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveScope::set_package_header(Package*pkg)
|
||||
@@ -248,6 +292,11 @@ bool ActiveScope::is_vector_name(perm_string name) const
|
||||
if (find_variable(name))
|
||||
return true;
|
||||
|
||||
const VType*dummy_type;
|
||||
Expression*dummy_exp;
|
||||
if (find_constant(name, dummy_type, dummy_exp))
|
||||
return true;
|
||||
|
||||
if (context_entity_ && context_entity_->find_port(name))
|
||||
return true;
|
||||
|
||||
|
||||
+22
-4
@@ -53,13 +53,26 @@ class ScopeBase {
|
||||
virtual ~ScopeBase() =0;
|
||||
|
||||
const VType* find_type(perm_string by_name);
|
||||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
||||
virtual bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const;
|
||||
Signal* find_signal(perm_string by_name) const;
|
||||
Variable* find_variable(perm_string by_name) const;
|
||||
virtual const InterfacePort* find_param(perm_string by_name) const;
|
||||
Subprogram* find_subprogram(perm_string by_name) const;
|
||||
// Moves all signals, variables and components from another scope to
|
||||
// this one. After the transfer new_* maps are emptied in the another scope.
|
||||
void transfer_from(ScopeBase&ref);
|
||||
// Checks if a string is one of possible enum values. If so, the enum
|
||||
// type is returned, otherwise NULL.
|
||||
const VTypeEnum* is_enum_name(perm_string name) const;
|
||||
|
||||
// Moves signals, variables and components from another scope to
|
||||
// this one. After the transfer new_* maps are cleared in the source scope.
|
||||
enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff };
|
||||
void transfer_from(ScopeBase&ref, transfer_type_t what = ALL);
|
||||
|
||||
inline void bind_subprogram(perm_string name, Subprogram*obj)
|
||||
{ map<perm_string, Subprogram*>::iterator it;
|
||||
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
|
||||
use_subprograms_.erase(it);
|
||||
cur_subprograms_[name] = obj;
|
||||
}
|
||||
|
||||
protected:
|
||||
void cleanup();
|
||||
@@ -106,6 +119,8 @@ class ScopeBase {
|
||||
std::map<perm_string, Subprogram*> use_subprograms_; //imported
|
||||
std::map<perm_string, Subprogram*> cur_subprograms_; //current
|
||||
|
||||
std::list<const VTypeEnum*> use_enums_;
|
||||
|
||||
void do_use_from(const ScopeBase*that);
|
||||
};
|
||||
|
||||
@@ -191,6 +206,9 @@ class ActiveScope : public ScopeBase {
|
||||
cur_types_[name] = t;
|
||||
}
|
||||
|
||||
inline void use_enum(const VTypeEnum* t)
|
||||
{ use_enums_.push_back(t); }
|
||||
|
||||
inline void use_name(perm_string name, const VType* t)
|
||||
{ use_types_[name] = t; }
|
||||
|
||||
|
||||
+68
-1
@@ -19,6 +19,15 @@
|
||||
|
||||
# include "sequential.h"
|
||||
# include "expression.h"
|
||||
# include <cassert>
|
||||
|
||||
template<typename T>
|
||||
inline static void visit_stmt_list(std::list<T*>& stmts, SeqStmtVisitor& func)
|
||||
{
|
||||
for(typename std::list<T*>::iterator it = stmts.begin(); it != stmts.end(); ++it) {
|
||||
(*it)->visit(func);
|
||||
}
|
||||
}
|
||||
|
||||
SequentialStmt::SequentialStmt()
|
||||
{
|
||||
@@ -75,6 +84,14 @@ void IfSequential::extract_false(std::list<SequentialStmt*>&that)
|
||||
}
|
||||
}
|
||||
|
||||
void IfSequential::visit(SeqStmtVisitor& func)
|
||||
{
|
||||
visit_stmt_list(if_, func);
|
||||
visit_stmt_list(elsif_, func);
|
||||
visit_stmt_list(else_, func);
|
||||
func(this);
|
||||
}
|
||||
|
||||
IfSequential::Elsif::Elsif(Expression*cond, std::list<SequentialStmt*>*tr)
|
||||
: cond_(cond)
|
||||
{
|
||||
@@ -91,6 +108,11 @@ IfSequential::Elsif::~Elsif()
|
||||
}
|
||||
}
|
||||
|
||||
void IfSequential::Elsif::visit(SeqStmtVisitor& func)
|
||||
{
|
||||
visit_stmt_list(if_, func);
|
||||
}
|
||||
|
||||
SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav)
|
||||
{
|
||||
lval_ = sig;
|
||||
@@ -118,7 +140,14 @@ CaseSeqStmt::~CaseSeqStmt()
|
||||
}
|
||||
}
|
||||
|
||||
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list<SequentialStmt*>* stmts)
|
||||
void CaseSeqStmt::visit(SeqStmtVisitor& func)
|
||||
{
|
||||
visit_stmt_list(alt_, func);
|
||||
func(this);
|
||||
}
|
||||
|
||||
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(std::list<Expression*>*exp,
|
||||
list<SequentialStmt*>*stmts)
|
||||
: exp_(exp)
|
||||
{
|
||||
if (stmts) stmts_.splice(stmts_.end(), *stmts);
|
||||
@@ -134,6 +163,11 @@ CaseSeqStmt::CaseStmtAlternative::~CaseStmtAlternative()
|
||||
}
|
||||
}
|
||||
|
||||
void CaseSeqStmt::CaseStmtAlternative::visit(SeqStmtVisitor& func)
|
||||
{
|
||||
visit_stmt_list(stmts_, func);
|
||||
}
|
||||
|
||||
ProcedureCall::ProcedureCall(perm_string name)
|
||||
: name_(name), param_list_(0)
|
||||
{
|
||||
@@ -163,6 +197,12 @@ ReturnStmt::~ReturnStmt()
|
||||
delete val_;
|
||||
}
|
||||
|
||||
void ReturnStmt::cast_to(const VType*type)
|
||||
{
|
||||
assert(val_);
|
||||
val_ = new ExpCast(val_, type);
|
||||
}
|
||||
|
||||
LoopStatement::LoopStatement(perm_string name, list<SequentialStmt*>* stmts)
|
||||
: name_(name)
|
||||
{
|
||||
@@ -178,6 +218,12 @@ LoopStatement::~LoopStatement()
|
||||
}
|
||||
}
|
||||
|
||||
void LoopStatement::visit(SeqStmtVisitor& func)
|
||||
{
|
||||
visit_stmt_list(stmts_, func);
|
||||
func(this);
|
||||
}
|
||||
|
||||
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list<SequentialStmt*>* stmts)
|
||||
: LoopStatement(scope_name, stmts), it_(it), range_(range)
|
||||
{
|
||||
@@ -217,3 +263,24 @@ BasicLoopStatement::BasicLoopStatement(perm_string lname, list<SequentialStmt*>*
|
||||
BasicLoopStatement::~BasicLoopStatement()
|
||||
{
|
||||
}
|
||||
|
||||
ReportStmt::ReportStmt(const char*msg, severity_t sev)
|
||||
: msg_(msg), severity_(sev)
|
||||
{
|
||||
if(sev == ReportStmt::UNSPECIFIED)
|
||||
severity_ = ReportStmt::NOTE;
|
||||
}
|
||||
|
||||
AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severity_t sev)
|
||||
: ReportStmt("", sev), cond_(condition)
|
||||
{
|
||||
if(msg == NULL)
|
||||
msg_ = default_msg_;
|
||||
else
|
||||
msg_ = std::string(msg);
|
||||
|
||||
if(sev == ReportStmt::UNSPECIFIED)
|
||||
severity_ = ReportStmt::ERROR;
|
||||
}
|
||||
|
||||
const std::string AssertStmt::default_msg_ = std::string("Assertion violation.");
|
||||
|
||||
+95
-30
@@ -23,10 +23,17 @@
|
||||
# include "LineInfo.h"
|
||||
# include "parse_types.h"
|
||||
# include <list>
|
||||
# include <functional>
|
||||
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class Entity;
|
||||
class Expression;
|
||||
class SequentialStmt;
|
||||
|
||||
struct SeqStmtVisitor {
|
||||
virtual ~SeqStmtVisitor() {};
|
||||
virtual void operator() (SequentialStmt*s) = 0;
|
||||
};
|
||||
|
||||
class SequentialStmt : public LineInfo {
|
||||
|
||||
@@ -35,9 +42,13 @@ class SequentialStmt : public LineInfo {
|
||||
virtual ~SequentialStmt() =0;
|
||||
|
||||
public:
|
||||
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
virtual int elaborate(Entity*ent, ScopeBase*scope);
|
||||
virtual int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
virtual void dump(ostream&out, int indent) const;
|
||||
virtual void write_to_stream(std::ostream&fd);
|
||||
|
||||
// Recursively visits a tree of sequential statements.
|
||||
virtual void visit(SeqStmtVisitor& func) { func(this); }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -52,10 +63,12 @@ class LoopStatement : public SequentialStmt {
|
||||
inline perm_string loop_name() const { return name_; }
|
||||
|
||||
void dump(ostream&out, int indent) const;
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
protected:
|
||||
int elaborate_substatements(Entity*ent, Architecture*arc);
|
||||
int emit_substatements(std::ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_substatements(Entity*ent, ScopeBase*scope);
|
||||
int emit_substatements(std::ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void write_to_stream_substatements(ostream&fd);
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
@@ -70,11 +83,15 @@ class IfSequential : public SequentialStmt {
|
||||
Elsif(Expression*cond, std::list<SequentialStmt*>*tr);
|
||||
~Elsif();
|
||||
|
||||
int elaborate(Entity*entity, Architecture*arc);
|
||||
int condition_emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int statement_emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*entity, ScopeBase*scope);
|
||||
int condition_emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
int statement_emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
|
||||
void condition_write_to_stream(ostream&fd);
|
||||
void statement_write_to_stream(ostream&fd);
|
||||
|
||||
void dump(ostream&out, int indent) const;
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
@@ -91,9 +108,11 @@ class IfSequential : public SequentialStmt {
|
||||
~IfSequential();
|
||||
|
||||
public:
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
const Expression*peek_condition() const { return cond_; }
|
||||
|
||||
@@ -117,10 +136,12 @@ class ReturnStmt : public SequentialStmt {
|
||||
~ReturnStmt();
|
||||
|
||||
public:
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
const Expression*peek_expr() const { return val_; };
|
||||
void cast_to(const VType*type);
|
||||
|
||||
private:
|
||||
Expression*val_;
|
||||
@@ -132,8 +153,9 @@ class SignalSeqAssignment : public SequentialStmt {
|
||||
~SignalSeqAssignment();
|
||||
|
||||
public:
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
@@ -145,15 +167,17 @@ class CaseSeqStmt : public SequentialStmt {
|
||||
public:
|
||||
class CaseStmtAlternative : public LineInfo {
|
||||
public:
|
||||
CaseStmtAlternative(Expression* exp, std::list<SequentialStmt*>* stmts);
|
||||
CaseStmtAlternative(std::list<Expression*>*exp, std::list<SequentialStmt*>*stmts);
|
||||
~CaseStmtAlternative();
|
||||
void dump(std::ostream& out, int indent) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
private:
|
||||
Expression* exp_;
|
||||
std::list<Expression*>*exp_;
|
||||
std::list<SequentialStmt*> stmts_;
|
||||
private: // not implemented
|
||||
CaseStmtAlternative(const CaseStmtAlternative&);
|
||||
@@ -166,8 +190,10 @@ class CaseSeqStmt : public SequentialStmt {
|
||||
|
||||
public:
|
||||
void dump(ostream&out, int indent) const;
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
private:
|
||||
Expression* cond_;
|
||||
@@ -180,8 +206,8 @@ class ProcedureCall : public SequentialStmt {
|
||||
ProcedureCall(perm_string name, std::list<named_expr_t*>* param_list);
|
||||
~ProcedureCall();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
@@ -195,8 +221,9 @@ class VariableSeqAssignment : public SequentialStmt {
|
||||
~VariableSeqAssignment();
|
||||
|
||||
public:
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
@@ -210,8 +237,7 @@ class WhileLoopStatement : public LoopStatement {
|
||||
ExpLogical*, list<SequentialStmt*>*);
|
||||
~WhileLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
@@ -224,11 +250,16 @@ class ForLoopStatement : public LoopStatement {
|
||||
perm_string index, prange_t*, list<SequentialStmt*>*);
|
||||
~ForLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
// Emits for-loop which direction is determined at run-time.
|
||||
// It is used for 'range & 'reverse_range attributes.
|
||||
int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
perm_string it_;
|
||||
prange_t* range_;
|
||||
};
|
||||
@@ -238,9 +269,43 @@ class BasicLoopStatement : public LoopStatement {
|
||||
BasicLoopStatement(perm_string lname, list<SequentialStmt*>*);
|
||||
~BasicLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent) const;
|
||||
};
|
||||
|
||||
class ReportStmt : public SequentialStmt {
|
||||
public:
|
||||
typedef enum { UNSPECIFIED, NOTE, WARNING, ERROR, FAILURE } severity_t;
|
||||
|
||||
ReportStmt(const char*message, severity_t severity = NOTE);
|
||||
virtual ~ReportStmt() {}
|
||||
|
||||
void dump(ostream&out, int indent) const;
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
|
||||
inline const std::string& message() const { return msg_; }
|
||||
inline severity_t severity() const { return severity_; }
|
||||
|
||||
protected:
|
||||
std::string msg_;
|
||||
severity_t severity_;
|
||||
};
|
||||
|
||||
class AssertStmt : public ReportStmt {
|
||||
public:
|
||||
AssertStmt(Expression*condition, const char*message, ReportStmt::severity_t severity = ReportStmt::ERROR);
|
||||
|
||||
void dump(ostream&out, int indent) const;
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
|
||||
// Message displayed when there is no report assigned.
|
||||
static const std::string default_msg_;
|
||||
};
|
||||
|
||||
#endif /* IVL_sequential_H */
|
||||
|
||||
@@ -105,7 +105,9 @@ void CaseSeqStmt::CaseStmtAlternative::dump(ostream& out, int indent) const
|
||||
|
||||
out << setw(indent) << "" << "when ";
|
||||
if (exp_)
|
||||
exp_->dump(out, 0);
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
|
||||
(*it)->dump(out, 0);
|
||||
}
|
||||
else
|
||||
out << "others" << endl;
|
||||
|
||||
@@ -163,3 +165,18 @@ void BasicLoopStatement::dump(ostream&out, int indent) const
|
||||
out << setw(indent) << "" << "BasicLoopStatement at file=" << get_fileline() << endl;
|
||||
LoopStatement::dump(out, indent+2);
|
||||
}
|
||||
|
||||
void ReportStmt::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "ReportStmt at file=" << get_fileline() << endl;
|
||||
out << setw(indent+3) << "" << "severity: " << severity_ << endl;
|
||||
out << setw(indent+3) << "" << "message: " << msg_ << endl;
|
||||
}
|
||||
|
||||
void AssertStmt::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "AssertStmt at file=" << get_fileline() << endl;
|
||||
out << setw(indent+3) << "" << "condition: ";
|
||||
cond_->dump(out, indent+3);
|
||||
ReportStmt::dump(out, indent+3);
|
||||
}
|
||||
|
||||
@@ -20,35 +20,35 @@
|
||||
# include "sequential.h"
|
||||
# include "expression.h"
|
||||
|
||||
int SequentialStmt::elaborate(Entity*, Architecture*)
|
||||
int SequentialStmt::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc)
|
||||
int LoopStatement::elaborate_substatements(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
|
||||
int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
const VType*ctype = cond_->probe_type(ent, arc);
|
||||
errors += cond_->elaborate_expr(ent, arc, ctype);
|
||||
const VType*ctype = cond_->probe_type(ent, scope);
|
||||
errors += cond_->elaborate_expr(ent, scope, ctype);
|
||||
|
||||
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
|
||||
; cur != alt_.end() ; ++cur) {
|
||||
CaseStmtAlternative*curp = *cur;
|
||||
errors += curp->elaborate_expr(ent, arc, ctype);
|
||||
errors += curp->elaborate(ent, arc);
|
||||
errors += curp->elaborate_expr(ent, scope, ctype);
|
||||
errors += curp->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
@@ -59,79 +59,82 @@ int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
|
||||
* ltype is the probed type for the main case condition. The
|
||||
* expression needs to elaborate itself in that context.
|
||||
*/
|
||||
int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
if (exp_)
|
||||
errors += exp_->elaborate_expr(ent, arc, ltype);
|
||||
if (exp_) {
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end();
|
||||
++it) {
|
||||
errors += (*it)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc)
|
||||
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
SequentialStmt*curp = *cur;
|
||||
errors += curp->elaborate(ent, arc);
|
||||
errors += curp->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
int ForLoopStatement::elaborate(Entity*ent, Architecture*arc)
|
||||
int ForLoopStatement::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += elaborate_substatements(ent, arc);
|
||||
errors += elaborate_substatements(ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int IfSequential::elaborate(Entity*ent, Architecture*arc)
|
||||
int IfSequential::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
|
||||
; cur != elsif_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = else_.begin()
|
||||
; cur != else_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int IfSequential::Elsif::elaborate(Entity*ent, Architecture*arc)
|
||||
int IfSequential::Elsif::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// Elaborate the l-value expression.
|
||||
errors += lval_->elaborate_lval(ent, arc, true);
|
||||
errors += lval_->elaborate_lval(ent, scope, true);
|
||||
|
||||
// The elaborate_lval should have resolved the type of the
|
||||
// l-value expression. We'll use that type to elaborate the
|
||||
@@ -146,23 +149,23 @@ int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
for (list<Expression*>::iterator cur = waveform_.begin()
|
||||
; cur != waveform_.end() ; ++cur) {
|
||||
|
||||
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, lval_type);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ProcedureCall::elaborate(Entity*, Architecture*)
|
||||
int ProcedureCall::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// Elaborate the l-value expression.
|
||||
errors += lval_->elaborate_lval(ent, arc, true);
|
||||
errors += lval_->elaborate_lval(ent, scope, true);
|
||||
|
||||
// The elaborate_lval should have resolved the type of the
|
||||
// l-value expression. We'll use that type to elaborate the
|
||||
@@ -174,18 +177,23 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
}
|
||||
|
||||
// Elaborate the r-value expression.
|
||||
errors += rval_->elaborate_expr(ent, arc, lval_type);
|
||||
errors += rval_->elaborate_expr(ent, scope, lval_type);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int WhileLoopStatement::elaborate(Entity*, Architecture*)
|
||||
int WhileLoopStatement::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
//TODO:check whether there is any wait statement in the statements (there should be)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BasicLoopStatement::elaborate(Entity*, Architecture*)
|
||||
int BasicLoopStatement::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AssertStmt::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
return cond_->elaborate_expr(ent, scope, 0);
|
||||
}
|
||||
|
||||
+333
-108
@@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -27,7 +29,7 @@
|
||||
# include <typeinfo>
|
||||
# include <ivl_assert.h>
|
||||
|
||||
int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
|
||||
int SequentialStmt::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << " // " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
@@ -35,23 +37,30 @@ int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void SequentialStmt::write_to_stream(std::ostream&fd)
|
||||
{
|
||||
fd << " // " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to write_to_stream this sequential statement! "
|
||||
<< "type=" << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
int IfSequential::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "if (";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ") begin" << endl;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
errors += (*cur)->emit(out, ent, arc);
|
||||
errors += (*cur)->emit(out, ent, scope);
|
||||
|
||||
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
|
||||
; cur != elsif_.end() ; ++cur) {
|
||||
out << "end else if (";
|
||||
errors += (*cur)->condition_emit(out, ent, arc);
|
||||
errors += (*cur)->condition_emit(out, ent, scope);
|
||||
out << ") begin" << endl;
|
||||
errors += (*cur)->statement_emit(out, ent, arc);
|
||||
errors += (*cur)->statement_emit(out, ent, scope);
|
||||
}
|
||||
|
||||
if (! else_.empty()) {
|
||||
@@ -59,7 +68,7 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = else_.begin()
|
||||
; cur != else_.end() ; ++cur)
|
||||
errors += (*cur)->emit(out, ent, arc);
|
||||
errors += (*cur)->emit(out, ent, scope);
|
||||
|
||||
}
|
||||
|
||||
@@ -67,36 +76,84 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void IfSequential::write_to_stream(std::ostream&fd)
|
||||
{
|
||||
return cond_->emit(out, ent, arc);
|
||||
fd << "if ";
|
||||
cond_->write_to_stream(fd);
|
||||
fd << " then " << endl;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
(*cur)->write_to_stream(fd);
|
||||
|
||||
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
|
||||
; cur != elsif_.end() ; ++cur) {
|
||||
fd << "elsif ";
|
||||
(*cur)->condition_write_to_stream(fd);
|
||||
fd << " " << endl;
|
||||
(*cur)->statement_write_to_stream(fd);
|
||||
}
|
||||
|
||||
if (! else_.empty()) {
|
||||
fd << " else " << endl;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = else_.begin()
|
||||
; cur != else_.end() ; ++cur)
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
|
||||
fd << "end if;" << endl;
|
||||
}
|
||||
|
||||
int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
return cond_->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
errors += (*cur)->emit(out, ent, arc);
|
||||
errors += (*cur)->emit(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ReturnStmt::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void IfSequential::Elsif::condition_write_to_stream(ostream&fd)
|
||||
{
|
||||
cond_->write_to_stream(fd);
|
||||
}
|
||||
|
||||
void IfSequential::Elsif::statement_write_to_stream(ostream&fd)
|
||||
{
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
|
||||
int ReturnStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "return ";
|
||||
errors += val_->emit(out, ent, arc);
|
||||
errors += val_->emit(out, ent, scope);
|
||||
out << ";" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void ReturnStmt::write_to_stream(ostream&fd)
|
||||
{
|
||||
fd << "return ";
|
||||
val_->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
int SignalSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += lval_->emit(out, ent, arc);
|
||||
errors += lval_->emit(out, ent, scope);
|
||||
|
||||
if (waveform_.size() != 1) {
|
||||
out << "/* Confusing waveform? */;" << endl;
|
||||
@@ -105,27 +162,50 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
} else {
|
||||
Expression*tmp = waveform_.front();
|
||||
out << " <= ";
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
out << ";" << endl;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int VariableSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void SignalSeqAssignment::write_to_stream(ostream&fd)
|
||||
{
|
||||
lval_->write_to_stream(fd);
|
||||
|
||||
if (waveform_.size() != 1) {
|
||||
fd << "-- Confusing waveform?" << endl;
|
||||
|
||||
} else {
|
||||
Expression*tmp = waveform_.front();
|
||||
fd << " <= ";
|
||||
tmp->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int VariableSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += lval_->emit(out, ent, arc);
|
||||
errors += lval_->emit(out, ent, scope);
|
||||
|
||||
out << " = ";
|
||||
errors += rval_->emit(out, ent, arc);
|
||||
errors += rval_->emit(out, ent, scope);
|
||||
out << ";" << endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
|
||||
void VariableSeqAssignment::write_to_stream(ostream&fd)
|
||||
{
|
||||
lval_->write_to_stream(fd);
|
||||
fd << " := ";
|
||||
rval_->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << " // " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
@@ -133,29 +213,38 @@ int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LoopStatement::emit_substatements(ostream&out, Entity*ent, Architecture*arc)
|
||||
int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
SequentialStmt*tmp = *cur;
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void LoopStatement::write_to_stream_substatements(ostream&fd)
|
||||
{
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
SequentialStmt*tmp = *cur;
|
||||
tmp->write_to_stream(fd);
|
||||
}
|
||||
}
|
||||
|
||||
int CaseSeqStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << "case (";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")" << endl;
|
||||
|
||||
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
|
||||
; cur != alt_.end() ; ++cur) {
|
||||
CaseStmtAlternative*curp = *cur;
|
||||
errors += curp ->emit(out, ent, arc);
|
||||
errors += curp ->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
out << "endcase" << endl;
|
||||
@@ -163,16 +252,38 @@ int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void CaseSeqStmt::write_to_stream(ostream&fd)
|
||||
{
|
||||
fd << "case ";
|
||||
cond_->write_to_stream(fd);
|
||||
fd << " is" << endl;
|
||||
|
||||
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
|
||||
; cur != alt_.end() ; ++cur) {
|
||||
CaseStmtAlternative*curp = *cur;
|
||||
curp ->write_to_stream(fd);
|
||||
}
|
||||
|
||||
fd << "end case;" << endl;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
bool first = true;
|
||||
if (exp_) {
|
||||
errors += exp_->emit(out, ent, arc);
|
||||
out << ":" << endl;
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
out << ",";
|
||||
errors += (*it)->emit(out, ent, scope);
|
||||
}
|
||||
} else {
|
||||
out << "default:" << endl;
|
||||
out << "default";
|
||||
}
|
||||
out << ":" << endl;
|
||||
|
||||
SequentialStmt*curp;
|
||||
|
||||
@@ -182,14 +293,14 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
|
||||
break;
|
||||
case 1:
|
||||
curp = stmts_.front();
|
||||
errors += curp->emit(out, ent, arc);
|
||||
errors += curp->emit(out, ent, scope);
|
||||
break;
|
||||
default:
|
||||
out << "begin" << endl;
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
curp = *cur;
|
||||
errors += curp->emit(out, ent, arc);
|
||||
errors += curp->emit(out, ent, scope);
|
||||
}
|
||||
out << "end" << endl;
|
||||
break;
|
||||
@@ -198,92 +309,206 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd)
|
||||
{
|
||||
int errors = 0;
|
||||
ivl_assert(*this, range_);
|
||||
fd << "when ";
|
||||
if (exp_) {
|
||||
bool first = true;
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
fd << "|";
|
||||
|
||||
int64_t start_val;
|
||||
bool start_rc = range_->msb()->evaluate(ent, arc, start_val);
|
||||
|
||||
int64_t finish_val;
|
||||
bool finish_rc = range_->lsb()->evaluate(ent, arc, finish_val);
|
||||
|
||||
ivl_assert(*this, start_rc);
|
||||
ivl_assert(*this, finish_rc);
|
||||
|
||||
bool dir = range_->is_downto();
|
||||
|
||||
if (!dir) {
|
||||
int64_t tmp = start_val;
|
||||
start_val = finish_val;
|
||||
finish_val = tmp;
|
||||
(*it)->write_to_stream(fd);
|
||||
}
|
||||
} else {
|
||||
fd << "others" << endl;
|
||||
}
|
||||
fd << "=>" << endl;
|
||||
|
||||
if (dir && (start_val < finish_val)) {
|
||||
if(range_->is_auto_dir()) {
|
||||
dir = false;
|
||||
} else {
|
||||
out << "begin /* Degenerate loop at " << get_fileline()
|
||||
<< ": " << start_val
|
||||
<< " downto " << finish_val << " */ end" << endl;
|
||||
return errors;
|
||||
}
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
|
||||
else if (!dir && start_val > finish_val) {
|
||||
if(range_->is_auto_dir()) {
|
||||
dir = true;
|
||||
} else {
|
||||
out << "begin /* Degenerate loop at " << get_fileline()
|
||||
<< ": " << start_val
|
||||
<< " to " << finish_val << " */ end" << endl;
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string scope_name = loop_name();
|
||||
if (scope_name.nil()) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof buf, "__%p", this);
|
||||
scope_name = lex_strings.make(buf);
|
||||
}
|
||||
|
||||
out << "begin : " << scope_name << endl;
|
||||
out << "longint \\" << it_ << " ;" << endl;
|
||||
out << "for (\\" << it_ << " = " << start_val << " ; ";
|
||||
if (dir)
|
||||
out << "\\" << it_ << " >= " << finish_val;
|
||||
else
|
||||
out << "\\" << it_ << " <= " << finish_val;
|
||||
out << "; \\" << it_ << " = \\" << it_;
|
||||
if (dir)
|
||||
out << " - 1";
|
||||
else
|
||||
out << " + 1";
|
||||
|
||||
out << ") begin" << endl;
|
||||
|
||||
errors += emit_substatements(out, ent, arc);
|
||||
|
||||
out << "end" << endl;
|
||||
out << "end /* " << scope_name << " */" << endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*)
|
||||
int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
out << " // " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
<< "type=" << typeid(*this).name() << endl;
|
||||
return 1;
|
||||
int errors = 0;
|
||||
ivl_assert(*this, range_);
|
||||
|
||||
int64_t start_val;
|
||||
bool start_rc = range_->msb()->evaluate(ent, scope, start_val);
|
||||
|
||||
int64_t finish_val;
|
||||
bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val);
|
||||
|
||||
perm_string scope_name = loop_name();
|
||||
if (scope_name.nil()) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof buf, "__%p", this);
|
||||
scope_name = lex_strings.make(buf);
|
||||
}
|
||||
|
||||
out << "begin : " << scope_name << endl;
|
||||
out << "longint \\" << it_ << " ;" << endl;
|
||||
|
||||
if(!start_rc || !finish_rc) {
|
||||
// Could not evaluate one of the loop boundaries, it has to be
|
||||
// determined during the run-time
|
||||
errors += emit_runtime_(out, ent, scope);
|
||||
} else {
|
||||
bool dir = range_->is_downto();
|
||||
|
||||
if (!dir) {
|
||||
int64_t tmp = start_val;
|
||||
start_val = finish_val;
|
||||
finish_val = tmp;
|
||||
}
|
||||
|
||||
if (dir && (start_val < finish_val)) {
|
||||
if(range_->is_auto_dir()) {
|
||||
dir = false;
|
||||
} else {
|
||||
out << "begin /* Degenerate loop at " << get_fileline()
|
||||
<< ": " << start_val
|
||||
<< " downto " << finish_val << " */ end" << endl
|
||||
<< "end" << endl;
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
else if (!dir && start_val > finish_val) {
|
||||
if(range_->is_auto_dir()) {
|
||||
dir = true;
|
||||
} else {
|
||||
out << "begin /* Degenerate loop at " << get_fileline()
|
||||
<< ": " << start_val
|
||||
<< " to " << finish_val << " */ end" << endl
|
||||
<< "end" << endl;
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
out << "for (\\" << it_ << " = " << start_val << " ; ";
|
||||
|
||||
if (dir)
|
||||
out << "\\" << it_ << " >= " << finish_val;
|
||||
else
|
||||
out << "\\" << it_ << " <= " << finish_val;
|
||||
|
||||
out << "; \\" << it_ << " = \\" << it_;
|
||||
|
||||
if (dir)
|
||||
out << " - 1)";
|
||||
else
|
||||
out << " + 1)";
|
||||
}
|
||||
|
||||
out << " begin" << endl;
|
||||
|
||||
errors += emit_substatements(out, ent, scope);
|
||||
|
||||
out << "end" << endl;
|
||||
out << "end /* " << scope_name << " */" << endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int BasicLoopStatement::emit(ostream&out, Entity*, Architecture*)
|
||||
void ForLoopStatement::write_to_stream(ostream&fd)
|
||||
{
|
||||
out << " // " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
<< "type=" << typeid(*this).name() << endl;
|
||||
return 1;
|
||||
fd << "for " << it_ << " in ";
|
||||
range_->expr_left()->write_to_stream(fd);
|
||||
fd << " to ";
|
||||
range_->expr_right()->write_to_stream(fd);
|
||||
fd << " loop" << endl;
|
||||
write_to_stream_substatements(fd);
|
||||
fd << "end loop;" << endl;
|
||||
}
|
||||
|
||||
int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << "for (\\" << it_ << " = ";
|
||||
errors += range_->expr_left()->emit(out, ent, scope);
|
||||
|
||||
// Twisted way of determining the loop direction at runtime
|
||||
out << " ;\n(";
|
||||
errors += range_->expr_left()->emit(out, ent, scope);
|
||||
out << " < ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
out << " ? \\" << it_ << " <= ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
out << " : \\" << it_ << " >= ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
out << ");\n\\" << it_ << " = \\" << it_ << " + (";
|
||||
errors += range_->expr_left()->emit(out, ent, scope);
|
||||
out << " < ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
out << " ? 1 : -1))";
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ReportStmt::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << "$display(\"";
|
||||
|
||||
switch(severity_)
|
||||
{
|
||||
case NOTE: out << "** Note: "; break;
|
||||
case WARNING: out << "** Warning: "; break;
|
||||
case ERROR: out << "** Error: "; break;
|
||||
case FAILURE: out << "** Failure: "; break;
|
||||
case UNSPECIFIED: ivl_assert(*this, false); break;
|
||||
}
|
||||
|
||||
out << msg_;
|
||||
out << " (" << get_fileline() << ")\");";
|
||||
|
||||
if(severity_ == FAILURE)
|
||||
out << "$finish();";
|
||||
|
||||
out << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ReportStmt::write_to_stream(std::ostream&fd)
|
||||
{
|
||||
fd << "report \"" << msg_ << "\"" << std::endl;
|
||||
|
||||
fd << "severity ";
|
||||
switch(severity_)
|
||||
{
|
||||
case NOTE: fd << "NOTE"; break;
|
||||
case WARNING: fd << "WARNING"; break;
|
||||
case ERROR: fd << "ERROR"; break;
|
||||
case FAILURE: fd << "FAILURE"; break;
|
||||
case UNSPECIFIED: break;
|
||||
}
|
||||
fd << ";" << std::endl;
|
||||
}
|
||||
|
||||
int AssertStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << "if(!(";
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")) begin" << std::endl;
|
||||
errors += ReportStmt::emit(out, ent, scope);
|
||||
out << "end" << std::endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void AssertStmt::write_to_stream(std::ostream&fd)
|
||||
{
|
||||
fd << "assert ";
|
||||
cond_->write_to_stream(fd);
|
||||
fd << std::endl;
|
||||
ReportStmt::write_to_stream(fd);
|
||||
}
|
||||
|
||||
+141
-13
@@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -23,6 +25,8 @@
|
||||
# include "vtype.h"
|
||||
# include "sequential.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "compiler.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -46,7 +50,21 @@ void Subprogram::set_program_body(list<SequentialStmt*>*stmt)
|
||||
{
|
||||
ivl_assert(*this, statements_==0);
|
||||
statements_ = stmt;
|
||||
fix_return_type();
|
||||
}
|
||||
|
||||
bool Subprogram::unbounded() const {
|
||||
if(return_type_->is_unbounded())
|
||||
return true;
|
||||
|
||||
if(ports_) {
|
||||
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
|
||||
it != ports_->end(); ++it) {
|
||||
if((*it)->type->is_unbounded())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Subprogram::compare_specification(Subprogram*that) const
|
||||
@@ -105,30 +123,104 @@ const VType*Subprogram::peek_param_type(int idx) const
|
||||
return (*p)->type;
|
||||
}
|
||||
|
||||
void Subprogram::fix_return_type(void)
|
||||
{
|
||||
if(!statements_)
|
||||
return;
|
||||
Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBase*scope) {
|
||||
assert(arguments.size() == ports_->size());
|
||||
|
||||
const ReturnStmt*ret = NULL;
|
||||
const VType*t = NULL;
|
||||
std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
|
||||
int i = 0;
|
||||
|
||||
for (std::list<SequentialStmt*>::const_iterator s = statements_->begin()
|
||||
; s != statements_->end(); ++s) {
|
||||
if((ret = dynamic_cast<const ReturnStmt*>(*s))) {
|
||||
// Change the argument types to match the ones that were used during
|
||||
// the function call
|
||||
for(std::list<InterfacePort*>::iterator it = ports_->begin();
|
||||
it != ports_->end(); ++it) {
|
||||
InterfacePort*p = new InterfacePort(**it);
|
||||
p->type = arguments[i++]->peek_type()->clone();
|
||||
assert(p->type);
|
||||
ports->push_back(p);
|
||||
}
|
||||
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports);
|
||||
perm_string new_name = lex_strings.make(buf);
|
||||
Subprogram*instance = new Subprogram(new_name, ports, return_type_);
|
||||
|
||||
// Copy variables
|
||||
for(std::map<perm_string,Variable*>::iterator it = new_variables_.begin();
|
||||
it != new_variables_.end(); ++it) {
|
||||
Variable*v = new Variable(it->first, it->second->peek_type()->clone());
|
||||
instance->new_variables_[it->first] = v;
|
||||
}
|
||||
|
||||
instance->set_parent(scope);
|
||||
instance->set_program_body(statements_);
|
||||
instance->fix_return_type();
|
||||
scope->bind_subprogram(new_name, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
struct check_return_type : public SeqStmtVisitor {
|
||||
check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {}
|
||||
|
||||
void operator() (SequentialStmt*s)
|
||||
{
|
||||
ReturnStmt*ret;
|
||||
if((ret = dynamic_cast<ReturnStmt*>(s))) {
|
||||
const Expression*expr = ret->peek_expr();
|
||||
const VType*t = NULL;
|
||||
|
||||
if(const ExpName*n = dynamic_cast<const ExpName*>(expr)) {
|
||||
if(Variable*v = find_variable(n->peek_name()))
|
||||
if(Variable*v = subp_->find_variable(n->peek_name()))
|
||||
t = v->peek_type();
|
||||
} else {
|
||||
t = expr->peek_type();
|
||||
}
|
||||
|
||||
if(t)
|
||||
return_type_ = t;
|
||||
if(!t) { // cannot determine the type at least in one case
|
||||
ret_type_ = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ret_type_) { // this is first processed return statement
|
||||
ret_type_ = t;
|
||||
} else if(!t->type_match(ret_type_)) {
|
||||
// the function can return different types,
|
||||
// we cannot have fixed width
|
||||
ret_type_ = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const VType*get_type() const { return ret_type_; }
|
||||
|
||||
private:
|
||||
const Subprogram*subp_;
|
||||
const VType*ret_type_;
|
||||
};
|
||||
|
||||
void Subprogram::fix_return_type()
|
||||
{
|
||||
if(!statements_)
|
||||
return;
|
||||
|
||||
check_return_type r(this);
|
||||
|
||||
for (std::list<SequentialStmt*>::iterator s = statements_->begin()
|
||||
; s != statements_->end(); ++s) {
|
||||
(*s)->visit(r);
|
||||
}
|
||||
|
||||
VType*return_type = const_cast<VType*>(r.get_type());
|
||||
if(return_type && !return_type->is_unbounded()) {
|
||||
// Let's check if the variable length can be evaluated without any scope.
|
||||
// If not, then it is depends on information about e.g. function params
|
||||
if(return_type->is_variable_length(NULL)) {
|
||||
if(VTypeArray*arr = dynamic_cast<VTypeArray*>(return_type))
|
||||
arr->evaluate_ranges(this);
|
||||
}
|
||||
return_type_ = return_type;
|
||||
}
|
||||
}
|
||||
|
||||
void Subprogram::write_to_stream(ostream&fd) const
|
||||
@@ -149,3 +241,39 @@ void Subprogram::write_to_stream(ostream&fd) const
|
||||
return_type_->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
void Subprogram::write_to_stream_body(ostream&fd) const
|
||||
{
|
||||
fd << "function " << name_ << "(";
|
||||
if (ports_ && ! ports_->empty()) {
|
||||
list<InterfacePort*>::const_iterator cur = ports_->begin();
|
||||
InterfacePort*curp = *cur;
|
||||
fd << curp->name << " : ";
|
||||
curp->type->write_to_stream(fd);
|
||||
for (++cur ; cur != ports_->end() ; ++cur) {
|
||||
curp = *cur;
|
||||
fd << "; " << curp->name << " : ";
|
||||
curp->type->write_to_stream(fd);
|
||||
}
|
||||
}
|
||||
fd << ") return ";
|
||||
return_type_->write_to_stream(fd);
|
||||
fd << " is" << endl;
|
||||
|
||||
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
|
||||
; cur != new_variables_.end() ; ++cur) {
|
||||
cur->second->write_to_stream(fd);
|
||||
}
|
||||
|
||||
fd << "begin" << endl;
|
||||
|
||||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
} else {
|
||||
fd << "--empty body" << endl;
|
||||
}
|
||||
fd << "end function;" << endl;
|
||||
}
|
||||
|
||||
+19
-4
@@ -3,6 +3,8 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -43,6 +45,7 @@ class Subprogram : public LineInfo, public ScopeBase {
|
||||
inline const perm_string&name() const { return name_; }
|
||||
|
||||
void set_program_body(std::list<SequentialStmt*>*statements);
|
||||
inline bool empty_program_body() const { return !statements_ || statements_->empty(); }
|
||||
|
||||
// Return true if the specification (name, types, ports)
|
||||
// matches this subprogram and that subprogram.
|
||||
@@ -50,19 +53,31 @@ class Subprogram : public LineInfo, public ScopeBase {
|
||||
|
||||
const InterfacePort*find_param(perm_string nam) const;
|
||||
const VType*peek_param_type(int idx) const;
|
||||
const VType*peek_return_type() const { return return_type_; }
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
// Emit a definition as it would show up in a package.
|
||||
int emit_package(std::ostream&fd) const;
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void write_to_stream_body(std::ostream&fd) const;
|
||||
void dump(std::ostream&fd) const;
|
||||
|
||||
// Creates a new instance of the function that takes arguments of
|
||||
// a different type. It is used to allow VHDL functions that work with
|
||||
// unbounded std_logic_vectors, so there can be a separate instance
|
||||
// for limited length logic vector.
|
||||
Subprogram*make_instance(std::vector<Expression*> arguments, ScopeBase*scope);
|
||||
|
||||
// Checks if either return type or parameters are unbounded vectors.
|
||||
bool unbounded() const;
|
||||
|
||||
private:
|
||||
// Determines appropriate return type. Un case of std_logic_vector
|
||||
// VHDL requires skipping its size in contrary to Verilog
|
||||
void fix_return_type(void);
|
||||
// Tries to set the return type to a fixed type. VHDL functions that
|
||||
// return std_logic_vectors do not specify its length, as SystemVerilog
|
||||
// demands.
|
||||
void fix_return_type();
|
||||
|
||||
perm_string name_;
|
||||
const ScopeBase*parent_;
|
||||
|
||||
@@ -70,7 +70,7 @@ int Subprogram::emit_package(ostream&fd) const
|
||||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
errors += (*cur)->emit(fd, NULL, NULL);
|
||||
errors += (*cur)->emit(fd, NULL, const_cast<Subprogram*>(this));
|
||||
}
|
||||
} else {
|
||||
fd << " begin /* empty body */ end" << endl;
|
||||
|
||||
+16
-8
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2014 / Maciej Suminski (maciej.suminski@cern.ch)
|
||||
* Copyright CERN 2014
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -34,10 +35,10 @@ SigVarBase::~SigVarBase()
|
||||
{
|
||||
}
|
||||
|
||||
void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc)
|
||||
void SigVarBase::elaborate_init_expr(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
if(init_expr_) {
|
||||
init_expr_->elaborate_expr(ent, arc, peek_type());
|
||||
init_expr_->elaborate_expr(ent, scope, peek_type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +47,7 @@ void SigVarBase::type_elaborate_(VType::decl_t&decl)
|
||||
decl.type = type_;
|
||||
}
|
||||
|
||||
int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -54,18 +55,18 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
type_elaborate_(decl);
|
||||
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
|
||||
decl.reg_flag = true;
|
||||
errors += decl.emit(out, peek_name_());
|
||||
errors += decl.emit(out, peek_name());
|
||||
|
||||
Expression*init_expr = peek_init_expr();
|
||||
if (init_expr) {
|
||||
out << " = ";
|
||||
init_expr->emit(out, ent, arc);
|
||||
init_expr->emit(out, ent, scope);
|
||||
}
|
||||
out << ";" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
||||
int Variable::emit(ostream&out, Entity*, Architecture*)
|
||||
int Variable::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
@@ -73,7 +74,14 @@ int Variable::emit(ostream&out, Entity*, Architecture*)
|
||||
type_elaborate_(decl);
|
||||
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
|
||||
decl.reg_flag = true;
|
||||
errors += decl.emit(out, peek_name_());
|
||||
errors += decl.emit(out, peek_name());
|
||||
out << ";" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
||||
void Variable::write_to_stream(std::ostream&fd)
|
||||
{
|
||||
fd << "variable " << peek_name() << " : ";
|
||||
peek_type()->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user