mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-22 22:06:47 +02:00
Compare commits
134
Commits
master
...
v11-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2f2414f48 | ||
|
|
689a1c27a8 | ||
|
|
af2b952769 | ||
|
|
0ad16a6c0b | ||
|
|
f8e29ee5e1 | ||
|
|
14d458dd78 | ||
|
|
05e3e13fbd | ||
|
|
38ab5f9b2c | ||
|
|
1f4e65ee08 | ||
|
|
5aef565b94 | ||
|
|
20b5377989 | ||
|
|
f247fe532f | ||
|
|
598363de84 | ||
|
|
7b9407f66d | ||
|
|
fcb64232de | ||
|
|
ff21f02c6c | ||
|
|
92e4597607 | ||
|
|
37a8b9a6c7 | ||
|
|
899a240311 | ||
|
|
631fa17002 | ||
|
|
a48769f5d4 | ||
|
|
5b82d69636 | ||
|
|
c4d07b6a62 | ||
|
|
9bf45e89f0 | ||
|
|
b17a967ced | ||
|
|
6f114cce17 | ||
|
|
fd30e57337 | ||
|
|
74f7dacc86 | ||
|
|
3e84e6e93a | ||
|
|
7d3c25f39a | ||
|
|
48e26a44d7 | ||
|
|
f436565dfe | ||
|
|
6b494eaa11 | ||
|
|
687dc0c751 | ||
|
|
f7ca845a47 | ||
|
|
48ab896fa6 | ||
|
|
cdbc2c466f | ||
|
|
038fbe609d | ||
|
|
a317a066af | ||
|
|
c7ee6157fc | ||
|
|
c00104bc50 | ||
|
|
56d69f498b | ||
|
|
12d67bb9ae | ||
|
|
c288487810 | ||
|
|
7ba381a0d0 | ||
|
|
97b5ac91cb | ||
|
|
5533ff848b | ||
|
|
52b099feae | ||
|
|
9ac6154068 | ||
|
|
2b7ee675ee | ||
|
|
5ea6ee130e | ||
|
|
066eb0aca7 | ||
|
|
4c428a536e | ||
|
|
1ff4bfa63d | ||
|
|
79a5e90e4d | ||
|
|
2f75fe4053 | ||
|
|
19dc81a242 | ||
|
|
987ac819a9 | ||
|
|
c564184bd1 | ||
|
|
b48cdff89e | ||
|
|
d3b0992a22 | ||
|
|
5a9ff97df5 | ||
|
|
87d7881365 | ||
|
|
afe008ca75 | ||
|
|
b45a52a164 | ||
|
|
a676db798a | ||
|
|
a14118cd6c | ||
|
|
0bd51dbfb8 | ||
|
|
ada3067899 | ||
|
|
69cf8d8901 | ||
|
|
a83a205b06 | ||
|
|
c0c46dc173 | ||
|
|
cccf36d76f | ||
|
|
f64c831688 | ||
|
|
adb4be5c75 | ||
|
|
eaea698027 | ||
|
|
338b9a69ee | ||
|
|
b613cf4bf5 | ||
|
|
a89eab47f5 | ||
|
|
0d9268cdbc | ||
|
|
f806ed5084 | ||
|
|
e396369410 | ||
|
|
9771be8ba1 | ||
|
|
3d7d2e5502 | ||
|
|
8c4dd80944 | ||
|
|
b58ca95909 | ||
|
|
7866168cf7 | ||
|
|
d56efebbfe | ||
|
|
48615fb8ac | ||
|
|
25154b6482 | ||
|
|
d9484b4f75 | ||
|
|
859e3e39be | ||
|
|
c690558cd6 | ||
|
|
838349590e | ||
|
|
5aac481d9a | ||
|
|
363f45cd7d | ||
|
|
b4d8108409 | ||
|
|
c8aa7bf873 | ||
|
|
864c09d034 | ||
|
|
b62c37ea58 | ||
|
|
ebad47937e | ||
|
|
45c52d5291 | ||
|
|
8d8cb16b72 | ||
|
|
04b0a1f80d | ||
|
|
1fda3ff23e | ||
|
|
bfac44a630 | ||
|
|
27986477fb | ||
|
|
0b991f5a28 | ||
|
|
e3ed4b28e7 | ||
|
|
9de8577e04 | ||
|
|
b415678d5c | ||
|
|
eec64de190 | ||
|
|
1baeb0d671 | ||
|
|
26aaa42831 | ||
|
|
7befefc65f | ||
|
|
5667c63907 | ||
|
|
580170d974 | ||
|
|
d0e2ed1509 | ||
|
|
4598341e85 | ||
|
|
55e2c5abef | ||
|
|
20c6d83ae9 | ||
|
|
f0b3056bfc | ||
|
|
412195e660 | ||
|
|
103f1fa4bb | ||
|
|
d521585901 | ||
|
|
84fa910820 | ||
|
|
ae0ee87363 | ||
|
|
c09ae8869c | ||
|
|
5b1d97fac7 | ||
|
|
794e15ac56 | ||
|
|
50cd3b107c | ||
|
|
59b67b69f6 | ||
|
|
84b4ebee0c | ||
|
|
e66fbc9bf9 |
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
echo "Using the bundled ivtest to run regression tests."
|
||||
echo " pwd = $(pwd)"
|
||||
|
||||
cd ivtest
|
||||
|
||||
status=0
|
||||
|
||||
perl vvp_reg.pl || status=1
|
||||
|
||||
perl vpi_reg.pl || status=1
|
||||
|
||||
exit $status
|
||||
@@ -0,0 +1,85 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
lin:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [
|
||||
'18.04',
|
||||
'20.04'
|
||||
]
|
||||
runs-on: ubuntu-${{ matrix.os }}
|
||||
name: '🐧 Ubuntu ${{ matrix.os }}'
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install -y make g++ git bison flex gperf libreadline-dev autoconf
|
||||
|
||||
- name: Build, check and install
|
||||
run: |
|
||||
autoconf
|
||||
./configure
|
||||
make check
|
||||
sudo make install
|
||||
|
||||
- name: Test
|
||||
run: ./.github/test.sh
|
||||
|
||||
|
||||
win:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64 },
|
||||
{ msystem: MINGW32, arch: i686 }
|
||||
]
|
||||
name: 🟪 ${{ matrix.msystem}} · ${{ matrix.arch }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
env:
|
||||
MINGW_INSTALLS: ${{ matrix.msystem }}
|
||||
steps:
|
||||
|
||||
- run: git config --global core.autocrlf input
|
||||
shell: bash
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >
|
||||
git
|
||||
base-devel
|
||||
mingw-w64-${{ matrix.arch }}-toolchain
|
||||
|
||||
- name: Build and check
|
||||
run: |
|
||||
cd msys2
|
||||
makepkg-mingw --noconfirm --noprogressbar -sCLf
|
||||
|
||||
- name: Install
|
||||
run: pacman -U --noconfirm msys2/*.zst
|
||||
|
||||
- name: Test
|
||||
run: ./.github/test.sh
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.msystem }}-${{ matrix.arch }}
|
||||
path: msys2/*.zst
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: xenial
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gperf
|
||||
|
||||
sudo: false
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
- stage: Test
|
||||
os: linux
|
||||
dist: xenial
|
||||
before_install:
|
||||
- git clone https://github.com/steveicarus/ivtest.git
|
||||
- export PATH=$HOME/bin:$PATH
|
||||
script:
|
||||
- autoconf
|
||||
- ./configure --prefix=$HOME
|
||||
- make install
|
||||
- make check
|
||||
- cd ivtest
|
||||
- perl vvp_reg.pl
|
||||
- diff regression_report-devel.txt regression_report.txt
|
||||
- perl vpi_reg.pl
|
||||
|
||||
- stage: Test
|
||||
os: linux
|
||||
dist: bionic
|
||||
before_install:
|
||||
- git clone https://github.com/steveicarus/ivtest.git
|
||||
- export PATH=$HOME/bin:$PATH
|
||||
script:
|
||||
- autoconf
|
||||
- ./configure --prefix=$HOME
|
||||
- make install
|
||||
- make check
|
||||
- cd ivtest
|
||||
- perl vvp_reg.pl
|
||||
- diff regression_report-devel.txt regression_report.txt
|
||||
- perl vpi_reg.pl
|
||||
|
||||
- stage: Test
|
||||
os: windows
|
||||
before_install:
|
||||
- git clone https://github.com/steveicarus/ivtest.git
|
||||
- choco uninstall -y mingw
|
||||
- choco upgrade --no-progress -y msys2
|
||||
- export msys2='cmd //C RefreshEnv.cmd '
|
||||
- export msys2+='& set MSYS=winsymlinks:nativestrict '
|
||||
- export msys2+='& C:\\tools\\msys64\\msys2_shell.cmd -defterm -no-start'
|
||||
- export mingw64="$msys2 -mingw64 -full-path -here -c "\"\$@"\" --"
|
||||
- export msys2+=" -msys2 -c "\"\$@"\" --"
|
||||
- $msys2 pacman --sync --noconfirm --needed base-devel mingw-w64-x86_64-toolchain
|
||||
script:
|
||||
- $mingw64 ./autoconf.sh
|
||||
- $mingw64 ./configure
|
||||
- $mingw64 make install
|
||||
- $mingw64 make check
|
||||
- cd ivtest
|
||||
- $mingw64 perl update_msys2_report.pl
|
||||
- $mingw64 perl vvp_reg.pl
|
||||
- diff --strip-trailing-cr regression_report-msys2.txt regression_report.txt
|
||||
- $mingw64 perl vpi_reg.pl
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_AStatement_H
|
||||
#define IVL_AStatement_H
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2021 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
|
||||
@@ -42,7 +42,7 @@ class AContrib : public Statement {
|
||||
AContrib(PExpr*lval, PExpr*rval);
|
||||
~AContrib();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -68,10 +68,10 @@ class AProcess : public LineInfo {
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Dump the analog process
|
||||
void dump(ostream&out, unsigned ind) const;
|
||||
void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_process_type_t type_;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_HName_H
|
||||
#define IVL_HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2021 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
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
class hname_t {
|
||||
|
||||
friend ostream& operator<< (ostream&out, const hname_t&that);
|
||||
friend std::ostream& operator<< (std::ostream&out, const hname_t&that);
|
||||
|
||||
public:
|
||||
hname_t ();
|
||||
@@ -92,14 +92,14 @@ inline size_t hname_t::has_numbers() const
|
||||
return number_.size();
|
||||
}
|
||||
|
||||
extern ostream& operator<< (ostream&, const hname_t&);
|
||||
extern std::ostream& operator<< (std::ostream&, const hname_t&);
|
||||
|
||||
inline bool operator != (const hname_t&l, const hname_t&r)
|
||||
{ return ! (l == r); }
|
||||
|
||||
inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
|
||||
inline std::ostream& operator<< (std::ostream&out, const std::list<hname_t>&ll)
|
||||
{
|
||||
list<hname_t>::const_iterator cur = ll.begin();
|
||||
std::list<hname_t>::const_iterator cur = ll.begin();
|
||||
out << *cur;
|
||||
++ cur;
|
||||
while (cur != ll.end()) {
|
||||
|
||||
@@ -19,8 +19,8 @@ diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
The file `configure.ac' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.ac' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
@@ -178,4 +178,3 @@ operates.
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
|
||||
|
||||
+1
-1
@@ -202,7 +202,7 @@ stamp-_pli_types-h: $(srcdir)/_pli_types.h.in config.status
|
||||
./config.status _pli_types.h
|
||||
_pli_types.h: stamp-_pli_types-h
|
||||
|
||||
$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4
|
||||
$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4
|
||||
cd $(srcdir) && autoconf
|
||||
|
||||
config.status: $(srcdir)/configure
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
# include "PWire.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
list<Module::named_expr_t> Module::user_defparms;
|
||||
|
||||
/* n is a permallocated string. */
|
||||
|
||||
@@ -64,7 +64,7 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
public:
|
||||
struct port_t {
|
||||
perm_string name;
|
||||
vector<PEIdent*> expr;
|
||||
std::vector<PEIdent*> expr;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -97,15 +97,15 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
/* specparams are simpler than other parameters, in that they
|
||||
can have a range, but not an explicit type. The restrictions
|
||||
are enforced by the parser. */
|
||||
map<perm_string,param_expr_t*>specparams;
|
||||
std::map<perm_string,param_expr_t*>specparams;
|
||||
|
||||
/* The module also has defparam assignments which don't create
|
||||
new parameters within the module, but may be used to set
|
||||
values within this module (when instantiated) or in other
|
||||
instantiated modules. */
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
static list<named_expr_t>user_defparms;
|
||||
typedef std::pair<pform_name_t,PExpr*> named_expr_t;
|
||||
std::list<named_expr_t>defparms;
|
||||
static std::list<named_expr_t>user_defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -113,17 +113,17 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
appear in the instantiated module. Therefore a
|
||||
list of names in module-order is needed to pass from
|
||||
a parameter-index to its name. */
|
||||
list<perm_string> param_names;
|
||||
std::list<perm_string> param_names;
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
vector<port_t*> ports;
|
||||
std::vector<port_t*> ports;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* The module has a list of generate schemes that appear in
|
||||
the module definition. These are used at elaboration time. */
|
||||
list<PGenerate*> generate_schemes;
|
||||
std::list<PGenerate*> generate_schemes;
|
||||
|
||||
/* Nested modules are placed here, and are not elaborated
|
||||
unless they are instantiated, implicitly or explicitly. */
|
||||
@@ -132,9 +132,9 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
/* 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;
|
||||
std::map<perm_string,PModport*> modports;
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
std::list<PSpecPath*> specify_paths;
|
||||
|
||||
// The mod_name() is the name of the module type.
|
||||
perm_string mod_name() const { return pscope_name(); }
|
||||
@@ -142,7 +142,7 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
void add_gate(PGate*gate);
|
||||
|
||||
unsigned port_count() const;
|
||||
const vector<PEIdent*>& get_port(unsigned idx) const;
|
||||
const std::vector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const char*name) const;
|
||||
|
||||
// Return port name ("" for undeclared port)
|
||||
@@ -150,12 +150,12 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
|
||||
PGate* get_gate(perm_string name);
|
||||
|
||||
const list<PGate*>& get_gates() const;
|
||||
const std::list<PGate*>& get_gates() const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
typedef map<perm_string,PExpr*> replace_t;
|
||||
typedef std::map<perm_string,PExpr*> replace_t;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
@@ -163,8 +163,8 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
private:
|
||||
void dump_specparams_(ostream&out, unsigned indent) const;
|
||||
list<PGate*> gates_;
|
||||
void dump_specparams_(std::ostream&out, unsigned indent) const;
|
||||
std::list<PGate*> gates_;
|
||||
|
||||
private: // Not implemented
|
||||
Module(const Module&);
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2017 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -26,6 +26,8 @@
|
||||
# include "verinum.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
PDelays::PDelays()
|
||||
{
|
||||
delete_flag_ = true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PDelays_H
|
||||
#define IVL_PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -24,12 +24,6 @@
|
||||
# include <list>
|
||||
# include <iostream>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class NetExpr;
|
||||
@@ -49,7 +43,7 @@ class PDelays {
|
||||
this object takes ownership of the expressions, and will
|
||||
delete it in the destructor. */
|
||||
void set_delay(PExpr*);
|
||||
void set_delays(const list<PExpr*>*del, bool delete_flag=true);
|
||||
void set_delays(const std::list<PExpr*>*del, bool delete_flag=true);
|
||||
|
||||
unsigned delay_count() const;
|
||||
|
||||
@@ -59,7 +53,7 @@ class PDelays {
|
||||
NetExpr*&decay_time,
|
||||
bool as_nets_flag =false) const;
|
||||
|
||||
void dump_delays(ostream&out) const;
|
||||
void dump_delays(std::ostream&out) const;
|
||||
|
||||
private:
|
||||
PExpr* delay_[3];
|
||||
@@ -70,6 +64,6 @@ class PDelays {
|
||||
PDelays& operator= (const PDelays&);
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PDelays&);
|
||||
std::ostream& operator << (std::ostream&o, const PDelays&);
|
||||
|
||||
#endif /* IVL_PDelays_H */
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PExpr::PExpr()
|
||||
{
|
||||
expr_type_ = IVL_VT_NO_TYPE;
|
||||
|
||||
@@ -60,7 +60,7 @@ class PExpr : public LineInfo {
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
// This method tests whether the expression contains any identifiers
|
||||
// that have not been previously declared in the specified scope or
|
||||
@@ -202,7 +202,7 @@ class PExpr : public LineInfo {
|
||||
PExpr& operator= (const PExpr&);
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&, const PExpr&);
|
||||
std::ostream& operator << (std::ostream&, const PExpr&);
|
||||
|
||||
class PEAssignPattern : public PExpr {
|
||||
public:
|
||||
@@ -230,11 +230,11 @@ class PEAssignPattern : public PExpr {
|
||||
class PEConcat : public PExpr {
|
||||
|
||||
public:
|
||||
PEConcat(const list<PExpr*>&p, PExpr*r =0);
|
||||
explicit PEConcat(const std::list<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -261,7 +261,7 @@ class PEConcat : public PExpr {
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
private:
|
||||
vector<PExpr*>parms_;
|
||||
std::vector<PExpr*>parms_;
|
||||
std::valarray<width_mode_t>width_modes_;
|
||||
|
||||
PExpr*repeat_;
|
||||
@@ -289,7 +289,7 @@ class PEEvent : public PExpr {
|
||||
edge_t type() const;
|
||||
PExpr* expr() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -322,7 +322,7 @@ class PEFNumber : public PExpr {
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
verireal*value_;
|
||||
@@ -340,7 +340,7 @@ class PEIdent : public PExpr {
|
||||
// current identifier.
|
||||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -540,7 +540,7 @@ class PENewArray : public PExpr {
|
||||
explicit PENewArray (PExpr*s, PExpr*i);
|
||||
~PENewArray();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -564,7 +564,7 @@ class PENewClass : public PExpr {
|
||||
|
||||
~PENewClass();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
// Class objects don't have a useful width, but the expression
|
||||
// is IVL_VT_CLASS.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
@@ -589,7 +589,7 @@ class PENewCopy : public PExpr {
|
||||
explicit PENewCopy(PExpr*src);
|
||||
~PENewCopy();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
// Class objects don't have a useful width, but the expression
|
||||
// is IVL_VT_CLASS.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
@@ -609,7 +609,7 @@ class PENull : public PExpr {
|
||||
explicit PENull();
|
||||
~PENull();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -627,7 +627,7 @@ class PENumber : public PExpr {
|
||||
|
||||
const verinum& value() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
@@ -661,8 +661,8 @@ class PEString : public PExpr {
|
||||
explicit PEString(char*s);
|
||||
~PEString();
|
||||
|
||||
string value() const;
|
||||
virtual void dump(ostream&) const;
|
||||
std::string value() const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
@@ -683,7 +683,7 @@ class PETypename : public PExpr {
|
||||
explicit PETypename(data_type_t*data_type);
|
||||
~PETypename();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -701,7 +701,7 @@ class PEUnary : public PExpr {
|
||||
explicit PEUnary(char op, PExpr*ex);
|
||||
~PEUnary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(std::ostream&out) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -733,7 +733,7 @@ class PEBinary : public PExpr {
|
||||
explicit PEBinary(char op, PExpr*l, PExpr*r);
|
||||
~PEBinary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(std::ostream&out) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -858,7 +858,7 @@ class PETernary : public PExpr {
|
||||
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
|
||||
~PETernary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(std::ostream&out) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -890,7 +890,7 @@ class PETernary : public PExpr {
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(const pform_name_t&n, const std::vector<PExpr *> &parms);
|
||||
// Call function defined in package.
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::vector<PExpr *> &parms);
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::list<PExpr *> &parms);
|
||||
@@ -899,16 +899,16 @@ class PECallFunction : public PExpr {
|
||||
explicit PECallFunction(PPackage*pkg, const pform_name_t&n, const std::vector<PExpr *> &parms);
|
||||
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const std::vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
|
||||
// std::list versions. Should be removed!
|
||||
explicit PECallFunction(const pform_name_t&n, const list<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const list<PExpr *> &parms);
|
||||
explicit PECallFunction(const pform_name_t&n, const std::list<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const std::list<PExpr *> &parms);
|
||||
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
virtual void dump(std::ostream &) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -975,7 +975,7 @@ class PECastSize : public PExpr {
|
||||
explicit PECastSize(PExpr*size, PExpr*base);
|
||||
~PECastSize();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
void dump(std::ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
@@ -998,7 +998,7 @@ class PECastType : public PExpr {
|
||||
explicit PECastType(data_type_t*target, PExpr*base);
|
||||
~PECastType();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
void dump(std::ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||
: PTaskFunc(name, parent), statement_(0)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -24,6 +24,8 @@
|
||||
# include "verinum.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void PGate::set_pins_(list<PExpr*>*pins)
|
||||
{
|
||||
assert(pins);
|
||||
@@ -39,7 +41,7 @@ void PGate::set_pins_(list<PExpr*>*pins)
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
|
||||
: name_(name), pins_(pins? pins->size() : 0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
if (del) delay_.set_delays(del);
|
||||
@@ -48,7 +50,7 @@ PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
|
||||
: name_(name), pins_(pins? pins->size() : 0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
if (del) delay_.set_delay(del);
|
||||
@@ -57,7 +59,7 @@ PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins)
|
||||
: name_(name), pins_(pins? pins->size() : 0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
str0_ = IVL_DR_STRONG;
|
||||
@@ -68,6 +70,12 @@ PGate::~PGate()
|
||||
{
|
||||
}
|
||||
|
||||
void PGate::set_ranges(list<pform_range_t>*ranges)
|
||||
{
|
||||
assert(ranges_ == 0);
|
||||
ranges_ = ranges;
|
||||
}
|
||||
|
||||
ivl_drive_t PGate::strength0() const
|
||||
{
|
||||
return str0_;
|
||||
@@ -141,14 +149,14 @@ PGAssign::~PGAssign()
|
||||
PGBuiltin::PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
list<PExpr*>*del)
|
||||
: PGate(name, pins, del), type_(t), msb_(0), lsb_(0)
|
||||
: PGate(name, pins, del), type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
PGBuiltin::PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
PExpr*del)
|
||||
: PGate(name, pins, del), type_(t), msb_(0), lsb_(0)
|
||||
: PGate(name, pins, del), type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -157,15 +165,6 @@ PGBuiltin::~PGBuiltin()
|
||||
{
|
||||
}
|
||||
|
||||
void PGBuiltin::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
const char* PGBuiltin::gate_name() const
|
||||
{
|
||||
switch(type_) {
|
||||
@@ -266,20 +265,20 @@ const char* PGBuiltin::gate_name() const
|
||||
|
||||
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
|
||||
: PGate(name, pins), bound_type_(0), type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
npins_(0), parms_(0), nparms_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(perm_string type, perm_string name,
|
||||
named<PExpr*>*pins, unsigned npins)
|
||||
: PGate(name, 0), bound_type_(0), type_(type), overrides_(0), pins_(pins),
|
||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
npins_(npins), parms_(0), nparms_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(Module*type, perm_string name)
|
||||
: PGate(name, 0), bound_type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
npins_(0), parms_(0), nparms_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -301,15 +300,6 @@ void PGModule::set_parameters(named<PExpr*>*pa, unsigned npa)
|
||||
nparms_ = npa;
|
||||
}
|
||||
|
||||
void PGModule::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
perm_string PGModule::get_type() const
|
||||
{
|
||||
return type_;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PGate_H
|
||||
#define IVL_PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 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
|
||||
@@ -50,16 +50,19 @@ class Module;
|
||||
class PGate : public PNamedItem {
|
||||
|
||||
public:
|
||||
explicit PGate(perm_string name, list<PExpr*>*pins,
|
||||
const list<PExpr*>*del);
|
||||
explicit PGate(perm_string name, std::list<PExpr*>*pins,
|
||||
const std::list<PExpr*>*del);
|
||||
|
||||
explicit PGate(perm_string name, list<PExpr*>*pins,
|
||||
explicit PGate(perm_string name, std::list<PExpr*>*pins,
|
||||
PExpr*del);
|
||||
|
||||
explicit PGate(perm_string name, list<PExpr*>*pins);
|
||||
explicit PGate(perm_string name, std::list<PExpr*>*pins);
|
||||
|
||||
virtual ~PGate();
|
||||
|
||||
void set_ranges(std::list<pform_range_t>*ranges);
|
||||
bool is_array() const { return ranges_ != 0; }
|
||||
|
||||
perm_string get_name() const { return name_; }
|
||||
|
||||
// This evaluates the delays as far as possible, but returns
|
||||
@@ -81,9 +84,9 @@ class PGate : public PNamedItem {
|
||||
void strength0(ivl_drive_t);
|
||||
void strength1(ivl_drive_t);
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -91,19 +94,25 @@ class PGate : public PNamedItem {
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
protected:
|
||||
const vector<PExpr*>& get_pins() const { return pins_; }
|
||||
const std::vector<PExpr*>& get_pins() const { return pins_; }
|
||||
|
||||
void dump_pins(ostream&out) const;
|
||||
void dump_delays(ostream&out) const;
|
||||
unsigned calculate_array_size_(Design*, NetScope*,
|
||||
long&high, long&low) const;
|
||||
|
||||
void dump_pins(std::ostream&out) const;
|
||||
void dump_delays(std::ostream&out) const;
|
||||
void dump_ranges(std::ostream&out) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
PDelays delay_;
|
||||
vector<PExpr*>pins_;
|
||||
std::vector<PExpr*>pins_;
|
||||
|
||||
std::list<pform_range_t>*ranges_;
|
||||
|
||||
ivl_drive_t str0_, str1_;
|
||||
|
||||
void set_pins_(list<PExpr*>*pins);
|
||||
void set_pins_(std::list<PExpr*>*pins);
|
||||
|
||||
private: // not implemented
|
||||
PGate(const PGate&);
|
||||
@@ -117,11 +126,11 @@ class PGate : public PNamedItem {
|
||||
class PGAssign : public PGate {
|
||||
|
||||
public:
|
||||
explicit PGAssign(list<PExpr*>*pins);
|
||||
explicit PGAssign(list<PExpr*>*pins, list<PExpr*>*dels);
|
||||
explicit PGAssign(std::list<PExpr*>*pins);
|
||||
explicit PGAssign(std::list<PExpr*>*pins, std::list<PExpr*>*dels);
|
||||
~PGAssign();
|
||||
|
||||
void dump(ostream&out, unsigned ind =4) const;
|
||||
void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -150,25 +159,21 @@ class PGBuiltin : public PGate {
|
||||
|
||||
public:
|
||||
explicit PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
list<PExpr*>*del);
|
||||
std::list<PExpr*>*pins,
|
||||
std::list<PExpr*>*del);
|
||||
explicit PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
std::list<PExpr*>*pins,
|
||||
PExpr*del);
|
||||
~PGBuiltin();
|
||||
|
||||
Type type() const { return type_; }
|
||||
const char * gate_name() const;
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
unsigned calculate_array_count_(Design*, NetScope*,
|
||||
long&high, long&low) const;
|
||||
|
||||
void calculate_gate_and_lval_count_(unsigned&gate_count,
|
||||
unsigned&lval_count) const;
|
||||
|
||||
@@ -179,8 +184,6 @@ class PGBuiltin : public PGate {
|
||||
bool check_delay_count(Design*des) const;
|
||||
|
||||
Type type_;
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -197,7 +200,7 @@ class PGModule : public PGate {
|
||||
// If the binding of ports is by position, this constructor
|
||||
// builds everything all at once.
|
||||
explicit PGModule(perm_string type, perm_string name,
|
||||
list<PExpr*>*pins);
|
||||
std::list<PExpr*>*pins);
|
||||
|
||||
// If the binding of ports is by name, this constructor takes
|
||||
// the bindings and stores them for later elaboration.
|
||||
@@ -212,16 +215,12 @@ class PGModule : public PGate {
|
||||
|
||||
// Parameter overrides can come as an ordered list, or a set
|
||||
// of named expressions.
|
||||
void set_parameters(list<PExpr*>*o);
|
||||
void set_parameters(std::list<PExpr*>*o);
|
||||
void set_parameters(named<PExpr*>*pa, unsigned npa);
|
||||
|
||||
// Modules can be instantiated in ranges. The parser uses this
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -233,7 +232,7 @@ class PGModule : public PGate {
|
||||
private:
|
||||
Module*bound_type_;
|
||||
perm_string type_;
|
||||
list<PExpr*>*overrides_;
|
||||
std::list<PExpr*>*overrides_;
|
||||
named<PExpr*>*pins_;
|
||||
unsigned npins_;
|
||||
|
||||
@@ -241,16 +240,9 @@ class PGModule : public PGate {
|
||||
named<PExpr*>*parms_;
|
||||
unsigned nparms_;
|
||||
|
||||
// Arrays of modules are give if these are set.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
friend class delayed_elaborate_scope_mod_instances;
|
||||
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
|
||||
unsigned calculate_instance_count_(Design*, NetScope*,
|
||||
long&high, long&low,
|
||||
perm_string name) const;
|
||||
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
|
||||
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
|
||||
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
|
||||
|
||||
+3
-46
@@ -21,11 +21,13 @@
|
||||
# include "PWire.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
PGenerate::PGenerate(LexicalScope*parent, unsigned id)
|
||||
: LexicalScope(parent), id_number(id)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
scheme_type = GS_NONE;
|
||||
directly_nested = false;
|
||||
local_index = false;
|
||||
loop_init = 0;
|
||||
loop_test = 0;
|
||||
@@ -41,51 +43,6 @@ void PGenerate::add_gate(PGate*gate)
|
||||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::probe_for_direct_nesting_(void)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
|
||||
ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE);
|
||||
|
||||
// If this scheme has received an explicit name, then it
|
||||
// cannot be direct nested.
|
||||
if (scope_name[0] != '$') return;
|
||||
|
||||
if (! tasks.empty()) return;
|
||||
if (! funcs.empty()) return;
|
||||
if (! gates.empty()) return;
|
||||
if (! parameters.empty()) return;
|
||||
if (! localparams.empty()) return;
|
||||
if (! events.empty()) return;
|
||||
if (! wires.empty()) return;
|
||||
if (! genvars.empty()) return;
|
||||
if (! behaviors.empty()) return;
|
||||
if (! analog_behaviors.empty()) return;
|
||||
|
||||
if (generate_schemes.empty()) return;
|
||||
|
||||
switch (generate_schemes.size()) {
|
||||
case 1: {
|
||||
PGenerate*child = generate_schemes.front();
|
||||
if (child->scheme_type == GS_CONDIT)
|
||||
direct_nested_ = true;
|
||||
if (child->scheme_type == GS_CASE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
PGenerate*child1 = generate_schemes.front();
|
||||
PGenerate*child2 = generate_schemes.back();
|
||||
if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&out, PGenerate::scheme_t type)
|
||||
{
|
||||
switch (type) {
|
||||
|
||||
+12
-16
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PGenerate_H
|
||||
#define IVL_PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2006-2021 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
|
||||
@@ -69,6 +69,8 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
||||
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||
scheme_t scheme_type;
|
||||
|
||||
bool directly_nested;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
// expressions: for (index = <init>; <test>; index=<step>)
|
||||
// the index is local if it was declared in the init expression,
|
||||
@@ -84,18 +86,18 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
||||
std::valarray<PExpr*> item_test;
|
||||
|
||||
// defparam assignments found in this scope.
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
typedef std::pair<pform_name_t,PExpr*> named_expr_t;
|
||||
std::list<named_expr_t>defparms;
|
||||
|
||||
list<PGate*> gates;
|
||||
std::list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
// Tasks instantiated within this scheme.
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*>funcs;
|
||||
std::map<perm_string,PTask*> tasks;
|
||||
std::map<perm_string,PFunction*>funcs;
|
||||
|
||||
// Generate schemes can contain further generate schemes.
|
||||
list<PGenerate*> generate_schemes;
|
||||
std::list<PGenerate*> generate_schemes;
|
||||
// PGenerate*parent;
|
||||
|
||||
// This method is called by the elaboration of a module to
|
||||
@@ -108,29 +110,23 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
||||
bool elaborate_sig(Design*des, NetScope*container) const;
|
||||
bool elaborate(Design*des, NetScope*container) const;
|
||||
|
||||
void dump(ostream&out, unsigned indent) const;
|
||||
void dump(std::ostream&out, unsigned indent) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
private:
|
||||
void check_for_valid_genvar_value_(long value);
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
|
||||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||
|
||||
// Call probe during elaborate_scope to calculate the
|
||||
// direct_nested_ flag. It is OK to store the direct_nested_
|
||||
// information here because "direct nested" is a property of
|
||||
// the lexical generate code.
|
||||
void probe_for_direct_nesting_(void);
|
||||
bool direct_nested_;
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
void elaborate_subscope_direct_(Design*des, NetScope*scope);
|
||||
|
||||
// These are the scopes created by generate_scope.
|
||||
list<NetScope*>scope_list_;
|
||||
std::list<NetScope*>scope_list_;
|
||||
// internal function called on each scope generated by this scheme.
|
||||
bool elaborate_sig_(Design*des, NetScope*scope) const;
|
||||
bool elaborate_sig_direct_(Design*des, NetScope*scope) const;
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PModport_H
|
||||
#define IVL_PModport_H
|
||||
/*
|
||||
* Copyright (c) 2015-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2015-2021 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
|
||||
@@ -38,8 +38,8 @@ class PModport : public PNamedItem {
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
map<perm_string,simple_port_t> simple_ports;
|
||||
typedef std::pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
std::map<perm_string,simple_port_t> simple_ports;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2021 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
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -55,7 +55,8 @@ class LexicalScope {
|
||||
public:
|
||||
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||
|
||||
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
|
||||
explicit LexicalScope(LexicalScope*parent)
|
||||
: default_lifetime(INHERITED), generate_counter(0), parent_(parent) { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
@@ -71,7 +72,7 @@ class LexicalScope {
|
||||
// Packages that are wildcard imported. When identifiers from
|
||||
// these packages are referenced, they will be added to the
|
||||
// explicit imports (IEEE 1800-2012 26.3).
|
||||
std::set<PPackage*>potential_imports;
|
||||
std::list<PPackage*>potential_imports;
|
||||
|
||||
// A task or function call may reference a task or function defined
|
||||
// later in the scope. So here we stash the potential imports for
|
||||
@@ -111,52 +112,57 @@ class LexicalScope {
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
};
|
||||
map<perm_string,param_expr_t*>parameters;
|
||||
map<perm_string,param_expr_t*>localparams;
|
||||
std::map<perm_string,param_expr_t*>parameters;
|
||||
std::map<perm_string,param_expr_t*>localparams;
|
||||
|
||||
// Defined types in the scope.
|
||||
map<perm_string,data_type_t*>typedefs;
|
||||
std::map<perm_string,data_type_t*>typedefs;
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
std::map<perm_string,PEvent*>events;
|
||||
|
||||
// Nets and variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
std::map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Genvars in the scope. These will only be present in module
|
||||
// scopes, but are listed here to allow them to be found when
|
||||
// creating implicit nets.
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
std::map<perm_string,LineInfo*> genvars;
|
||||
|
||||
// Variable initializations in this scope
|
||||
vector<Statement*> var_inits;
|
||||
std::vector<Statement*> var_inits;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
list<AProcess*> analog_behaviors;
|
||||
std::list<PProcess*> behaviors;
|
||||
std::list<AProcess*> analog_behaviors;
|
||||
|
||||
// Enumeration sets.
|
||||
std::set<enum_type_t*> enum_sets;
|
||||
|
||||
// A count of the generate constructs in this scope. This is
|
||||
// used to automatically name unnamed generate blocks, as
|
||||
// specified in the LRM.
|
||||
unsigned generate_counter;
|
||||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
virtual bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
protected:
|
||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||
void dump_typedefs_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_parameters_(ostream&out, unsigned indent) const;
|
||||
void dump_parameters_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_localparams_(ostream&out, unsigned indent) const;
|
||||
void dump_localparams_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_enumerations_(ostream&out, unsigned indent) const;
|
||||
void dump_enumerations_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_events_(ostream&out, unsigned indent) const;
|
||||
void dump_events_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
void dump_wires_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_var_inits_(ostream&out, unsigned indent) const;
|
||||
void dump_var_inits_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_var_inits_(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -227,9 +233,9 @@ class PScopeExtra : public PScope {
|
||||
bool time_prec_is_local;
|
||||
|
||||
protected:
|
||||
void dump_classes_(ostream&out, unsigned indent) const;
|
||||
void dump_tasks_(ostream&out, unsigned indent) const;
|
||||
void dump_funcs_(ostream&out, unsigned indent) const;
|
||||
void dump_classes_(std::ostream&out, unsigned indent) const;
|
||||
void dump_tasks_(std::ostream&out, unsigned indent) const;
|
||||
void dump_funcs_(std::ostream&out, unsigned indent) const;
|
||||
};
|
||||
|
||||
#endif /* IVL_PScope_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -21,6 +21,8 @@
|
||||
# include "PTask.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PTaskFunc::PTaskFunc(perm_string n, LexicalScope*p)
|
||||
: PScope(n,p), this_type_(0), ports_(0)
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ class PTask : public PTaskFunc {
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
@@ -148,7 +148,7 @@ class PFunction : public PTaskFunc {
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PUdp_H
|
||||
#define IVL_PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 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
|
||||
@@ -53,20 +53,20 @@ class PUdp : public LineInfo {
|
||||
public:
|
||||
explicit PUdp(perm_string n, unsigned nports);
|
||||
|
||||
svector<string>ports;
|
||||
svector<std::string>ports;
|
||||
unsigned find_port(const char*name);
|
||||
|
||||
bool sequential;
|
||||
|
||||
svector<string>tinput;
|
||||
svector<std::string>tinput;
|
||||
svector<char> tcurrent;
|
||||
svector<char> toutput;
|
||||
|
||||
verinum::V initial;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
std::map<std::string,PExpr*> attributes;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
|
||||
perm_string name_;
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -22,6 +22,8 @@
|
||||
# include "PExpr.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PWire::PWire(perm_string n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
@@ -132,7 +134,13 @@ ivl_variable_type_t PWire::get_data_type() const
|
||||
|
||||
void PWire::set_signed(bool flag)
|
||||
{
|
||||
signed_ = flag;
|
||||
// For a non-ANSI style port declaration where the data type is
|
||||
// specified in a corresponding variable declaration, the signed
|
||||
// attribute may be attached to either the port declaration or to
|
||||
// the variable declaration (IEEE 1364-2005 section 12.3.3). The
|
||||
// signal is signed if either the port or the variable is signed.
|
||||
// Handle that here.
|
||||
signed_ = signed_ || flag;
|
||||
}
|
||||
|
||||
bool PWire::get_signed() const
|
||||
@@ -264,7 +272,7 @@ void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
|
||||
|
||||
void PWire::set_data_type(data_type_t*type)
|
||||
{
|
||||
assert(set_data_type_ == 0);
|
||||
assert(set_data_type_ == 0 || set_data_type_ == type);
|
||||
set_data_type_ = type;
|
||||
|
||||
if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(type)) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PWire_H
|
||||
#define IVL_PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 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
|
||||
@@ -28,7 +28,7 @@
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
class PExpr;
|
||||
@@ -87,10 +87,10 @@ class PWire : public PNamedItem {
|
||||
void set_discipline(ivl_discipline_t);
|
||||
ivl_discipline_t get_discipline(void) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out, unsigned ind=4) const;
|
||||
void dump(std::ostream&out, unsigned ind=4) const;
|
||||
|
||||
NetNet* elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ If you are building from git, you will also need software to generate
|
||||
the configure scripts.
|
||||
|
||||
- autoconf 2.53 or later
|
||||
This generates configure scripts from configure.in. The 2.53
|
||||
This generates configure scripts from configure.ac. The 2.53
|
||||
or later versions are known to work, autoconf 2.13 is
|
||||
reported to *not* work.
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
# include "PExpr.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Statement::~Statement()
|
||||
{
|
||||
}
|
||||
|
||||
+40
-33
@@ -61,9 +61,9 @@ class PProcess : public LineInfo {
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_process_type_t type_;
|
||||
@@ -81,12 +81,12 @@ class Statement : virtual public LineInfo {
|
||||
Statement() { }
|
||||
virtual ~Statement() =0;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -139,7 +139,7 @@ class PAssign : public PAssign_ {
|
||||
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
|
||||
~PAssign();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -155,7 +155,7 @@ class PAssignNB : public PAssign_ {
|
||||
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
~PAssignNB();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -200,7 +200,7 @@ class PBlock : public PScope, public Statement, public PNamedItem {
|
||||
// block.
|
||||
void push_statement_front(Statement*that);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -215,14 +215,14 @@ class PBlock : public PScope, public Statement, public PNamedItem {
|
||||
class PCallTask : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const std::list<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const std::list<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const std::list<PExpr*>&parms);
|
||||
~PCallTask();
|
||||
|
||||
const pform_name_t& path() const;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -245,18 +245,25 @@ class PCallTask : public Statement {
|
||||
NetNet*net,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const;
|
||||
NetProc*elaborate_method_func_(NetScope*scope,
|
||||
NetNet*net,
|
||||
ivl_variable_type_t type,
|
||||
unsigned width,
|
||||
bool signed_flag,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const;
|
||||
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
||||
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
vector<PExpr*> parms_;
|
||||
std::vector<PExpr*> parms_;
|
||||
};
|
||||
|
||||
class PCase : public Statement {
|
||||
|
||||
public:
|
||||
struct Item {
|
||||
list<PExpr*>expr;
|
||||
std::list<PExpr*>expr;
|
||||
Statement*stat;
|
||||
};
|
||||
|
||||
@@ -266,7 +273,7 @@ class PCase : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_case_quality_t quality_;
|
||||
@@ -287,7 +294,7 @@ class PCAssign : public Statement {
|
||||
~PCAssign();
|
||||
|
||||
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -301,11 +308,11 @@ class PCAssign : public Statement {
|
||||
*/
|
||||
class PChainConstructor : public Statement {
|
||||
public:
|
||||
explicit PChainConstructor(const list<PExpr*>&parms);
|
||||
explicit PChainConstructor(const std::list<PExpr*>&parms);
|
||||
~PChainConstructor();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
inline const std::vector<PExpr*>& chain_args(void) const
|
||||
{ return parms_; }
|
||||
@@ -323,7 +330,7 @@ class PCondit : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -342,7 +349,7 @@ class PDeassign : public Statement {
|
||||
~PDeassign();
|
||||
|
||||
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -354,7 +361,7 @@ class PDelayStatement : public Statement {
|
||||
PDelayStatement(PExpr*d, Statement*st);
|
||||
~PDelayStatement();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -374,7 +381,7 @@ class PDisable : public Statement {
|
||||
explicit PDisable(const pform_name_t&sc);
|
||||
~PDisable();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -390,7 +397,7 @@ class PDoWhile : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*cond_;
|
||||
@@ -419,10 +426,10 @@ class PEventStatement : public Statement {
|
||||
|
||||
void set_statement(Statement*st);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
// Call this with a NULL statement only. It is used to print
|
||||
// the event expression for inter-assignment event controls.
|
||||
virtual void dump_inline(ostream&out) const;
|
||||
virtual void dump_inline(std::ostream&out) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -442,7 +449,7 @@ class PEventStatement : public Statement {
|
||||
bool always_sens_;
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PEventStatement&obj);
|
||||
std::ostream& operator << (std::ostream&o, const PEventStatement&obj);
|
||||
|
||||
class PForce : public Statement {
|
||||
|
||||
@@ -451,7 +458,7 @@ class PForce : public Statement {
|
||||
~PForce();
|
||||
|
||||
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -466,7 +473,7 @@ class PForeach : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
||||
@@ -486,7 +493,7 @@ class PForever : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
Statement*statement_;
|
||||
@@ -502,7 +509,7 @@ class PForStatement : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr* name1_;
|
||||
@@ -530,7 +537,7 @@ class PRepeat : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -544,7 +551,7 @@ class PRelease : public Statement {
|
||||
~PRelease();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -574,7 +581,7 @@ class PTrigger : public Statement {
|
||||
~PTrigger();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PPackage*package_;
|
||||
@@ -590,7 +597,7 @@ class PWhile : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*cond_;
|
||||
|
||||
Vendored
+35
-22
@@ -6,7 +6,7 @@
|
||||
# different builds. Remember to change the default suffix string to some
|
||||
# value appropriate for the current version.
|
||||
AC_DEFUN([AX_ENABLE_SUFFIX],
|
||||
[AC_ARG_ENABLE([suffix],[AC_HELP_STRING([--enable-suffix],
|
||||
[AC_ARG_ENABLE([suffix],[AS_HELP_STRING([--enable-suffix],
|
||||
[Use/set the installation command suffix])],
|
||||
[true],[enable_suffix=no])
|
||||
if test X$enable_suffix = Xyes; then
|
||||
@@ -250,7 +250,7 @@ echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_sta
|
||||
]) #_AC_AM_CONFIG_HEADER_HOOK
|
||||
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -283,31 +283,35 @@ echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_sta
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 8
|
||||
#serial 18
|
||||
|
||||
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
|
||||
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_PROG_CPP])dnl
|
||||
AC_REQUIRE([AC_EXEEXT])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
|
||||
|
||||
dnl Use the standard macros, but make them use other variable names
|
||||
dnl
|
||||
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
|
||||
pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl
|
||||
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
|
||||
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
|
||||
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
|
||||
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
|
||||
pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl
|
||||
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
|
||||
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
|
||||
pushdef([ac_exeext], ac_build_exeext)dnl
|
||||
pushdef([ac_objext], ac_build_objext)dnl
|
||||
pushdef([CC], CC_FOR_BUILD)dnl
|
||||
pushdef([CPP], CPP_FOR_BUILD)dnl
|
||||
pushdef([GCC], GCC_FOR_BUILD)dnl
|
||||
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
|
||||
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
|
||||
pushdef([EXEEXT], BUILD_EXEEXT)dnl
|
||||
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
|
||||
pushdef([OBJEXT], BUILD_OBJEXT)dnl
|
||||
pushdef([host], build)dnl
|
||||
pushdef([host_alias], build_alias)dnl
|
||||
pushdef([host_cpu], build_cpu)dnl
|
||||
@@ -318,27 +322,29 @@ pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
|
||||
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
|
||||
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
|
||||
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
|
||||
pushdef([ac_cpp], ac_build_cpp)dnl
|
||||
pushdef([ac_compile], ac_build_compile)dnl
|
||||
pushdef([ac_link], ac_build_link)dnl
|
||||
pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl
|
||||
pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl
|
||||
pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl
|
||||
pushdef([cross_compiling], cross_compiling_build)dnl
|
||||
|
||||
save_cross_compiling=$cross_compiling
|
||||
save_ac_tool_prefix=$ac_tool_prefix
|
||||
cross_compiling=no
|
||||
ac_tool_prefix=
|
||||
cross_compiling_build=no
|
||||
|
||||
ac_build_tool_prefix=
|
||||
AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"],
|
||||
[test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"])
|
||||
|
||||
AC_LANG_PUSH([C])
|
||||
AC_PROG_CC
|
||||
_AC_COMPILER_EXEEXT
|
||||
_AC_COMPILER_OBJEXT
|
||||
AC_PROG_CPP
|
||||
AC_EXEEXT
|
||||
|
||||
ac_tool_prefix=$save_ac_tool_prefix
|
||||
cross_compiling=$save_cross_compiling
|
||||
|
||||
dnl Restore the old definitions
|
||||
dnl
|
||||
popdef([ac_link])dnl
|
||||
popdef([ac_compile])dnl
|
||||
popdef([ac_cpp])dnl
|
||||
popdef([cross_compiling])dnl
|
||||
popdef([am_cv_prog_cc_c_o])dnl
|
||||
popdef([am_cv_CC_dependencies_compiler_type])dnl
|
||||
popdef([ac_tool_prefix])dnl
|
||||
popdef([ac_cv_host_os])dnl
|
||||
popdef([ac_cv_host_vendor])dnl
|
||||
popdef([ac_cv_host_cpu])dnl
|
||||
@@ -349,29 +355,36 @@ popdef([host_vendor])dnl
|
||||
popdef([host_cpu])dnl
|
||||
popdef([host_alias])dnl
|
||||
popdef([host])dnl
|
||||
popdef([OBJEXT])dnl
|
||||
popdef([LDFLAGS])dnl
|
||||
popdef([EXEEXT])dnl
|
||||
popdef([CPPFLAGS])dnl
|
||||
popdef([CFLAGS])dnl
|
||||
popdef([GCC])dnl
|
||||
popdef([CPP])dnl
|
||||
popdef([CC])dnl
|
||||
popdef([ac_objext])dnl
|
||||
popdef([ac_exeext])dnl
|
||||
popdef([ac_cv_objext])dnl
|
||||
popdef([ac_cv_exeext])dnl
|
||||
popdef([ac_cv_c_compiler_gnu])dnl
|
||||
popdef([ac_cv_prog_cc_g])dnl
|
||||
popdef([ac_cv_prog_cc_cross])dnl
|
||||
popdef([ac_cv_prog_cc_works])dnl
|
||||
popdef([ac_cv_prog_cc_c89])dnl
|
||||
popdef([ac_cv_prog_gcc])dnl
|
||||
popdef([ac_cv_prog_CPP])dnl
|
||||
|
||||
dnl restore global variables ac_ext, ac_cpp, ac_compile,
|
||||
dnl ac_link, ac_compiler_gnu (dependant on the current
|
||||
dnl language after popping):
|
||||
AC_LANG_POP([C])
|
||||
|
||||
dnl Finally, set Makefile variables
|
||||
dnl
|
||||
BUILD_EXEEXT=$ac_build_exeext
|
||||
BUILD_OBJEXT=$ac_build_objext
|
||||
AC_SUBST(BUILD_EXEEXT)dnl
|
||||
AC_SUBST(BUILD_OBJEXT)dnl
|
||||
AC_SUBST([CFLAGS_FOR_BUILD])dnl
|
||||
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
|
||||
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
|
||||
])
|
||||
|
||||
|
||||
+3
-3
@@ -147,7 +147,7 @@ extern unsigned long array_size_limit;
|
||||
extern const char*basedir;
|
||||
|
||||
/* This is an ordered list of library suffixes to search. */
|
||||
extern list<const char*>library_suff;
|
||||
extern std::list<const char*>library_suff;
|
||||
extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
|
||||
/* This is the generation of Verilog that the compiler is asked to
|
||||
@@ -244,14 +244,14 @@ extern int lexor_keyword_mask;
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
|
||||
extern map<perm_string,unsigned> missing_modules;
|
||||
extern std::map<perm_string,unsigned> missing_modules;
|
||||
|
||||
/* Files that are library files are in this map. The lexor compares
|
||||
file names as it processes `line directives, and if the file name
|
||||
matches an entry in this table, it will turn on the
|
||||
library_active_flag so that modules know that they are in a
|
||||
library. */
|
||||
extern map<perm_string,bool> library_file_map;
|
||||
extern std::map<perm_string,bool> library_file_map;
|
||||
|
||||
/*
|
||||
* the lex_strings are perm_strings made up of tokens from the source
|
||||
|
||||
+1
-9
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2021 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
|
||||
@@ -19,14 +19,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if !defined(__GNUC__)
|
||||
using namespace std;
|
||||
# elif (__GNUC__ == 3)
|
||||
using namespace std;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# undef NEED_LU
|
||||
# undef NEED_TU
|
||||
# undef WLU
|
||||
|
||||
+25
-26
@@ -1,21 +1,22 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(netlist.h)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_CONFIG_HEADER(_pli_types.h)
|
||||
AC_CONFIG_HEADER(vhdlpp/vhdlpp_config.h)
|
||||
AC_CONFIG_HEADER(vvp/config.h)
|
||||
AC_CONFIG_HEADER(vpi/vpi_config.h)
|
||||
AC_CONFIG_HEADER(libveriuser/config.h)
|
||||
AC_CONFIG_HEADER(tgt-vvp/vvp_config.h)
|
||||
AC_CONFIG_HEADER(tgt-vhdl/vhdl_config.h)
|
||||
AC_CONFIG_HEADER(tgt-pcb/pcb_config.h)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([netlist.h])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_HEADERS([_pli_types.h])
|
||||
AC_CONFIG_HEADERS([vhdlpp/vhdlpp_config.h])
|
||||
AC_CONFIG_HEADERS([vvp/config.h])
|
||||
AC_CONFIG_HEADERS([vpi/vpi_config.h])
|
||||
AC_CONFIG_HEADERS([libveriuser/config.h])
|
||||
AC_CONFIG_HEADERS([tgt-vvp/vvp_config.h])
|
||||
AC_CONFIG_HEADERS([tgt-vhdl/vhdl_config.h])
|
||||
AC_CONFIG_HEADERS([tgt-pcb/pcb_config.h])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
# AC_PROG_CC_C99 is only available in autoconf version 2.60 and later.
|
||||
AC_PREREQ([2.60])
|
||||
AC_PROG_CC_C99
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
AC_PREREQ([2.62])
|
||||
m4_version_prereq([2.70], [], [AC_PROG_CC_C99])
|
||||
AC_PROG_CXX
|
||||
AC_PROG_RANLIB
|
||||
AC_CHECK_TOOL(LD, ld, false)
|
||||
@@ -92,7 +93,7 @@ fi
|
||||
|
||||
AC_LANG(C++)
|
||||
|
||||
AC_ARG_WITH([m32], [AC_HELP_STRING([--with-m32], [Compile 32-bit on x86_64])],
|
||||
AC_ARG_WITH([m32], [AS_HELP_STRING([--with-m32],[Compile 32-bit on x86_64])],
|
||||
[ with_m32=yes ],[ with_m32=no ])
|
||||
|
||||
AS_IF( [test "x$with_m32" = xyes],
|
||||
@@ -135,6 +136,7 @@ CXXFLAGS="$iverilog_temp_cxxflags"
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
AC_CHECK_SIZEOF(unsigned)
|
||||
AC_CHECK_SIZEOF(void *)
|
||||
|
||||
# vvp uses these...
|
||||
AC_CHECK_LIB(termcap, tputs)
|
||||
@@ -169,8 +171,7 @@ AC_FUNC_ALLOCA
|
||||
AC_FUNC_FSEEKO
|
||||
|
||||
# valgrind checks
|
||||
AC_ARG_WITH([valgrind], [AC_HELP_STRING([--with-valgrind],
|
||||
[Add valgrind hooks])],
|
||||
AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind],[Add valgrind hooks])],
|
||||
[], [check_valgrind=yes])
|
||||
|
||||
AS_IF([test "x$check_valgrind" = xyes],
|
||||
@@ -181,14 +182,11 @@ AS_IF([test "x$check_valgrind" = xyes],
|
||||
[AC_MSG_ERROR([Could not find <valgrind/memcheck.h>])])])
|
||||
|
||||
AC_MSG_CHECKING(for sys/times)
|
||||
AC_TRY_LINK(
|
||||
#include <unistd.h>
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
|
||||
#include <sys/times.h>
|
||||
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
|
||||
do_times=yes
|
||||
AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
|
||||
do_times=no
|
||||
)
|
||||
]], [[{clock_t a = times(0)/sysconf(_SC_CLK_TCK);}]])],[do_times=yes
|
||||
AC_DEFINE(HAVE_TIMES, 1, The times system call is available in the host operating system.)],[do_times=no
|
||||
])
|
||||
AC_MSG_RESULT($do_times)
|
||||
|
||||
# --
|
||||
@@ -261,7 +259,8 @@ AC_CHECK_FUNCS(fopen64)
|
||||
# The following math functions may be defined in the math library so look
|
||||
# in the default libraries first and then look in -lm for them. On some
|
||||
# systems we may need to use the compiler in C99 mode to get a definition.
|
||||
# We requested C99 mode earlier with AC_PROG_CC_C99.
|
||||
# autoconf >= 2.70 will enable C99 if it is available. For older autoconf
|
||||
# versions, we requested C99 mode earlier with AC_PROG_CC_C99.
|
||||
AC_SEARCH_LIBS([lround], [m], [AC_DEFINE([HAVE_LROUND], [1])])
|
||||
AC_SEARCH_LIBS([llround], [m], [AC_DEFINE([HAVE_LLROUND], [1])])
|
||||
AC_SEARCH_LIBS([nan], [m], [AC_DEFINE([HAVE_NAN], [1])])
|
||||
@@ -335,5 +334,5 @@ then
|
||||
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
||||
fi
|
||||
AC_MSG_RESULT(ok)
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile)
|
||||
AC_CONFIG_FILES([Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile])
|
||||
AC_OUTPUT
|
||||
@@ -28,6 +28,7 @@
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The cprop function below invokes constant propagation where
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
# include "ivl_assert.h"
|
||||
# include "PExpr.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
{
|
||||
switch (t) {
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_discipline_H
|
||||
#define IVL_discipline_H
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2021 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
|
||||
@@ -69,9 +69,9 @@ class ivl_discipline_s : public LineInfo {
|
||||
ivl_discipline_s& operator = (const ivl_discipline_s&);
|
||||
};
|
||||
|
||||
extern map<perm_string,ivl_nature_t> natures;
|
||||
extern map<perm_string,ivl_discipline_t> disciplines;
|
||||
extern std::map<perm_string,ivl_nature_t> natures;
|
||||
extern std::map<perm_string,ivl_discipline_t> disciplines;
|
||||
// Map access function name to the nature that it accesses.
|
||||
extern map<perm_string,ivl_nature_t> access_function_nature;
|
||||
extern std::map<perm_string,ivl_nature_t> access_function_nature;
|
||||
|
||||
#endif /* IVL_discipline_H */
|
||||
|
||||
@@ -99,7 +99,7 @@ install: all installdirs installfiles
|
||||
F = ./iverilog-vpi@EXEEXT@
|
||||
|
||||
installfiles: $(F) | installdirs
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
|
||||
ifeq (@WIN32@,yes)
|
||||
ifneq ($(HOSTCC),$(CC))
|
||||
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libwinpthread-1.dll) "$(DESTDIR)$(bindir)"
|
||||
@@ -109,7 +109,7 @@ endif
|
||||
endif
|
||||
|
||||
installdirs: $(srcdir)/../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs "$(bindir)"
|
||||
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)"
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
rm -f $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022 Martin Whitaker
|
||||
* Copyright (c) 2002 Gus Baldauf (gus@picturel.com)
|
||||
* 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
|
||||
@@ -564,10 +564,10 @@ static void compile(char *pSource, char *pFlags, char **pObject, int *compile_er
|
||||
assignn(&src, ptr1, len);
|
||||
|
||||
/* Build the object file name */
|
||||
ostart = strrchr(ptr1, '/');
|
||||
if (ostart == NULL) ostart = ptr1;
|
||||
ostart = strrchr(src, '/');
|
||||
if (ostart == NULL) ostart = src;
|
||||
else ostart += 1;
|
||||
olen = strrchr(ptr1, '.') - ostart;
|
||||
olen = strrchr(ostart, '.') - ostart;
|
||||
assignn(&obj, ostart, olen);
|
||||
append(&obj, ".o");
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH iverilog 1 "Aug 10th, 2020" "" "Version %M.%n%E"
|
||||
.TH iverilog 1 "Jan 14th, 2021" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
@@ -582,9 +582,13 @@ The following macros are predefined by the compiler:
|
||||
.B __ICARUS__ = 1
|
||||
This is always defined when compiling with Icarus Verilog.
|
||||
|
||||
.TP 8
|
||||
.B __ICARUS_SYNTH__ = 1
|
||||
This is defined when synthesis is enabled.
|
||||
|
||||
.TP 8
|
||||
.B __VAMS_ENABLE__ = 1
|
||||
This is defined if Verilog\-AMS is enabled.
|
||||
This is defined when Verilog\-AMS is enabled.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.PP
|
||||
@@ -633,7 +637,7 @@ Tips on using, debugging, and developing the compiler can be found at
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2020 Stephen Williams
|
||||
Copyright \(co 2002\-2021 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+16
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 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
|
||||
@@ -184,7 +184,7 @@ int verbose_flag = 0;
|
||||
FILE *fp;
|
||||
|
||||
char line[MAXSIZE];
|
||||
char tmp[MAXSIZE];
|
||||
char tmp[MAXSIZE+24];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
@@ -1046,7 +1046,7 @@ static void find_ivl_root(void)
|
||||
if the user has overridden $(bindir) or $(libdir), but there's
|
||||
not a lot we can do in that case.
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
#if defined(__MINGW32__)
|
||||
char tmppath[MAXSIZE];
|
||||
len = GetModuleFileName(NULL, tmppath, sizeof tmppath);
|
||||
if (len >= (ssize_t) sizeof ivl_root) {
|
||||
@@ -1054,6 +1054,9 @@ static void find_ivl_root(void)
|
||||
}
|
||||
/* Convert to a short name to remove any embedded spaces. */
|
||||
len = GetShortPathName(tmppath, ivl_root, sizeof ivl_root);
|
||||
#elif defined(__APPLE__)
|
||||
uint32_t size = sizeof ivl_root;
|
||||
len = _NSGetExecutablePath(ivl_root, &size) + 1;
|
||||
#else
|
||||
len = readlink("/proc/self/exe", ivl_root, sizeof ivl_root);
|
||||
#endif
|
||||
@@ -1061,7 +1064,11 @@ static void find_ivl_root(void)
|
||||
find_ivl_root_failed("command path exceeds size of string buffer.");
|
||||
}
|
||||
if (len <= 0) {
|
||||
find_ivl_root_failed("couldn't get command path from OS.");
|
||||
// We've failed, but we may yet find a -B option on the command line.
|
||||
// Use the built-in path so the user sees a sensible error message.
|
||||
assert(strlen(IVL_ROOT) < sizeof ivl_root);
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
return;
|
||||
}
|
||||
s = strrchr(ivl_root, sep);
|
||||
if (s == 0) {
|
||||
@@ -1116,8 +1123,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
fprintf(defines_file, "D:__ICARUS__=1\n");
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0)
|
||||
fprintf(defines_file, "D:__VAMS_ENABLE__=1\n");
|
||||
|
||||
/* Create another temporary file for passing configuration
|
||||
information to ivl. */
|
||||
@@ -1301,6 +1306,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0)
|
||||
fprintf(defines_file, "D:__VAMS_ENABLE__=1\n");
|
||||
if (synth_flag)
|
||||
fprintf(defines_file, "D:__ICARUS_SYNTH__=1\n");
|
||||
|
||||
if (vpi_dir == 0)
|
||||
vpi_dir = base;
|
||||
if (ivlpp_dir == 0)
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -24,6 +24,8 @@
|
||||
# include <cstdlib>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetEAccess* NetEAccess::dup_expr() const
|
||||
{
|
||||
NetEAccess*tmp = new NetEAccess(branch_, nature_);
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 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
|
||||
@@ -29,6 +29,8 @@
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetNet* PExpr::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_line() << ": error: Invalid expression on left side "
|
||||
@@ -163,4 +165,3 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
||||
+180
-43
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -41,6 +41,8 @@
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool type_is_vectorable(ivl_variable_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
@@ -110,6 +112,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||
switch (lv_type) {
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
case IVL_VT_CLASS:
|
||||
// For these types, use a different elab_and_eval that
|
||||
// uses the lv_net_type. We should eventually transition
|
||||
// all the types to this new form.
|
||||
@@ -127,12 +130,6 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||
case IVL_VT_NO_TYPE:
|
||||
ivl_assert(*expr, 0);
|
||||
break;
|
||||
case IVL_VT_CLASS:
|
||||
cerr << expr->get_fileline() << ": sorry: "
|
||||
<< "I do not know how to elaborate r-value as IVL_VT_CLASS." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return elab_and_eval(des, scope, expr, context_wid, need_const,
|
||||
@@ -282,6 +279,13 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
ivl_variable_type_t l_type = left_->expr_type();
|
||||
ivl_variable_type_t r_type = right_->expr_type();
|
||||
|
||||
if (l_type == IVL_VT_CLASS || r_type == IVL_VT_CLASS) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Class/null is not allowed with the '"
|
||||
<< human_readable_op(op_) << "' operator." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (l_type == IVL_VT_REAL || r_type == IVL_VT_REAL)
|
||||
expr_type_ = IVL_VT_REAL;
|
||||
else if (l_type == IVL_VT_LOGIC || r_type == IVL_VT_LOGIC)
|
||||
@@ -627,6 +631,34 @@ unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||
<< r_width_ << " bits." << endl;
|
||||
}
|
||||
|
||||
switch (op_) {
|
||||
case 'e': /* == */
|
||||
case 'n': /* != */
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
// FIXME: A class variable/array inside a class is not
|
||||
// reported correctly so this cannot be used.
|
||||
#if 0
|
||||
if ((l_type == IVL_VT_CLASS || r_type == IVL_VT_CLASS) &&
|
||||
l_type != r_type) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Both arguments ("<< l_type << ", " << r_type
|
||||
<< ") must be class/null for '"
|
||||
<< human_readable_op(op_) << "' operator." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
if (l_type == IVL_VT_CLASS || r_type == IVL_VT_CLASS) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Class/null is not allowed with the '"
|
||||
<< human_readable_op(op_) << "' operator." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
@@ -760,6 +792,13 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
expr_type_ = left_->expr_type();
|
||||
signed_flag_ = left_->has_sign();
|
||||
|
||||
if (expr_type_ == IVL_VT_CLASS || right_->expr_type() == IVL_VT_CLASS) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Class/null is not allowed with the '"
|
||||
<< human_readable_op(op_) << "' operator." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (mode==SIZED)
|
||||
mode = l_mode;
|
||||
|
||||
@@ -1958,6 +1997,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
unsigned long use_width = struct_type->packed_width();
|
||||
|
||||
pform_name_t completed_path;
|
||||
ivl_type_t member_type = 0;
|
||||
do {
|
||||
const name_component_t member_comp = member_path.front();
|
||||
const perm_string&member_name = member_comp.name;
|
||||
@@ -1985,28 +2025,29 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
member_type = member->net_type;
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": check_for_struct_members: "
|
||||
<< "Member type: " << *(member->net_type)
|
||||
<< " (" << typeid(*(member->net_type)).name() << ")"
|
||||
<< "Member type: " << *member_type
|
||||
<< " (" << typeid(*member_type).name() << ")"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
off += tmp_off;
|
||||
ivl_assert(*li, use_width >= (unsigned long)member->net_type->packed_width());
|
||||
use_width = member->net_type->packed_width();
|
||||
ivl_assert(*li, use_width >= (unsigned long)member_type->packed_width());
|
||||
use_width = member_type->packed_width();
|
||||
|
||||
// At this point, off and use_width are the part select
|
||||
// expressed by the member_comp, which is a member of the
|
||||
// struct. We can further refine the part select with any
|
||||
// indices that might be present.
|
||||
|
||||
if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*>(member->net_type)) {
|
||||
if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*>(member_type)) {
|
||||
// If the member is itself a struct, then get
|
||||
// ready to go on to the next iteration.
|
||||
struct_type = tmp_struct;
|
||||
|
||||
} else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member->net_type)) {
|
||||
} else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member_type)) {
|
||||
|
||||
// If the element is an enum, then we don't have
|
||||
// anything special to do.
|
||||
@@ -2017,7 +2058,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
}
|
||||
struct_type = 0;
|
||||
|
||||
} else if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type)) {
|
||||
} else if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member_type)) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": check_for_struct_members: "
|
||||
@@ -2104,7 +2145,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
// there is no next struct type.
|
||||
struct_type = 0;
|
||||
|
||||
} else if (const netparray_t*array = dynamic_cast<const netparray_t*>(member->net_type)) {
|
||||
} else if (const netparray_t*array = dynamic_cast<const netparray_t*>(member_type)) {
|
||||
|
||||
// If the member is a parray, then the elements
|
||||
// are themselves packed object, including
|
||||
@@ -2178,7 +2219,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
} else {
|
||||
// Unknown type?
|
||||
cerr << li->get_fileline() << ": internal error: "
|
||||
<< "Unexpected member type? " << *(member->net_type)
|
||||
<< "Unexpected member type? " << *member_type
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
struct_type = 0;
|
||||
@@ -2224,7 +2265,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
NetExpr *base = packed_base? packed_base : make_const_val(off);
|
||||
NetESelect*sel = new NetESelect(sig, base, use_width);
|
||||
NetESelect*sel = new NetESelect(sig, base, use_width, member_type);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": check_for_struct_member: "
|
||||
@@ -3556,6 +3597,15 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
}
|
||||
|
||||
if (use_width != UINT_MAX) {
|
||||
// We have a bit/part select. Account for any remaining dimensions
|
||||
// beyond the indexed dimension.
|
||||
size_t use_depth = name_tail.index.size();
|
||||
if (net) {
|
||||
if (use_depth >= net->unpacked_dimensions())
|
||||
use_depth -= net->unpacked_dimensions();
|
||||
use_width *= net->slice_width(use_depth);
|
||||
}
|
||||
|
||||
expr_type_ = IVL_VT_LOGIC; // Assume bit/parts selects are logic
|
||||
expr_width_ = use_width;
|
||||
min_width_ = use_width;
|
||||
@@ -5085,11 +5135,19 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
// range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc;
|
||||
bool lrc, mrc;
|
||||
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, loff, lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = net->sig()->sb_to_slice(prefix_indices, msv, moff, mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
mrc = net->sig()->sb_to_slice(prefix_indices, msv, moff, mwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << msv << ":" << lsv;
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << net->sig()->name();
|
||||
if (net->sig()->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
if (moff > loff) {
|
||||
@@ -5195,19 +5253,48 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetExpr*ex;
|
||||
if (base_c->value().is_defined()) {
|
||||
long lsv = base_c->value().as_long();
|
||||
long offset = 0;
|
||||
long rel_base = 0;
|
||||
// Get the signal range.
|
||||
const vector<netrange_t>&packed = net->sig()->packed_dims();
|
||||
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
|
||||
if (prefix_indices.size()+1 < net->sig()->packed_dims().size()) {
|
||||
// Here we are selecting one or more sub-arrays.
|
||||
// Make this work by finding the indexed sub-arrays and
|
||||
// creating a generated slice that spans the whole range.
|
||||
unsigned long swid = net->sig()->slice_width(prefix_indices.size()+1);
|
||||
ivl_assert(*this, swid > 0);
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc, mrc;
|
||||
mrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||
lrc = net->sig()->sb_to_slice(prefix_indices, lsv+(wid/swid)-1, loff, lwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << lsv << "+:" << (wid/swid);
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << net->sig()->name();
|
||||
if (net->sig()->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, mwid == swid);
|
||||
ivl_assert(*this, lwid == swid);
|
||||
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (rng.get_msb() < rng.get_lsb()) {
|
||||
offset = -wid + 1;
|
||||
if (moff > loff) {
|
||||
rel_base = loff;
|
||||
} else {
|
||||
rel_base = moff;
|
||||
}
|
||||
} else {
|
||||
long offset = 0;
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (rng.get_msb() < rng.get_lsb()) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
rel_base = net->sig()->sb_to_idx(prefix_indices, lsv) + offset;
|
||||
}
|
||||
|
||||
long rel_base = net->sig()->sb_to_idx(prefix_indices, lsv);
|
||||
|
||||
// If the part select covers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
@@ -5219,7 +5306,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
|
||||
// Otherwise, make a part select that covers the right
|
||||
// range.
|
||||
ex = new NetEConst(verinum(rel_base + offset));
|
||||
ex = new NetEConst(verinum(rel_base));
|
||||
if (warn_ob_select) {
|
||||
if (rel_base < 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
@@ -5298,31 +5385,66 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetExpr*ex;
|
||||
if (base_c->value().is_defined()) {
|
||||
long lsv = base_c->value().as_long();
|
||||
long rel_base = 0;
|
||||
// Get the signal range.
|
||||
const vector<netrange_t>&packed = net->sig()->packed_dims();
|
||||
if (prefix_indices.size()+1 < net->sig()->packed_dims().size()) {
|
||||
// Here we are selecting one or more sub-arrays.
|
||||
// Make this work by finding the indexed sub-arrays and
|
||||
// creating a generated slice that spans the whole range.
|
||||
unsigned long swid = net->sig()->slice_width(prefix_indices.size()+1);
|
||||
ivl_assert(*this, swid > 0);
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc, mrc;
|
||||
mrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||
lrc = net->sig()->sb_to_slice(prefix_indices, lsv-(wid/swid)+1, loff, lwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << lsv << "-:" << (wid/swid);
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << net->sig()->name();
|
||||
if (net->sig()->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, mwid == swid);
|
||||
ivl_assert(*this, lwid == swid);
|
||||
|
||||
if (moff > loff) {
|
||||
rel_base = loff;
|
||||
} else {
|
||||
rel_base = moff;
|
||||
}
|
||||
} else {
|
||||
long offset = 0;
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (rng.get_msb() > rng.get_lsb()) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
rel_base = net->sig()->sb_to_idx(prefix_indices, lsv) + offset;
|
||||
}
|
||||
|
||||
// If the part select covers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sig()->sb_to_idx(prefix_indices,lsv) == (signed) (wid-1) &&
|
||||
wid == net->vector_width()) {
|
||||
if (rel_base == (long)(wid-1) && wid == net->vector_width()) {
|
||||
delete base;
|
||||
net->cast_signed(false);
|
||||
return net;
|
||||
}
|
||||
|
||||
long offset = 0;
|
||||
if (net->msi() > net->lsi()) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
// Otherwise, make a part select that covers the right
|
||||
// range.
|
||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(prefix_indices,lsv) + offset));
|
||||
ex = new NetEConst(verinum(rel_base));
|
||||
if (warn_ob_select) {
|
||||
long rel_base = net->sig()->sb_to_idx(prefix_indices,lsv) + offset;
|
||||
if (rel_base < 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "[" << lsv << "+:" << wid
|
||||
cerr << "[" << lsv << "-:" << wid
|
||||
<< "] is selecting before vector." << endl;
|
||||
}
|
||||
if (rel_base + wid > net->vector_width()) {
|
||||
@@ -5353,7 +5475,11 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
return ss;
|
||||
}
|
||||
|
||||
base = normalize_variable_base(base, net->msi(), net->lsi(), wid, false);
|
||||
ivl_assert(*this, prefix_indices.size()+1 == net->sig()->packed_dims().size());
|
||||
|
||||
// Convert the non-constant part select index expression into
|
||||
// an expression that returns a canonical base.
|
||||
base = normalize_variable_part_base(prefix_indices, base, net->sig(), wid, false);
|
||||
|
||||
NetESelect*ss = new NetESelect(net, base, wid, IVL_SEL_IDX_DOWN);
|
||||
ss->set_line(*this);
|
||||
@@ -5395,7 +5521,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Bit select of a dynamic array becomes NetESelect." << endl;
|
||||
}
|
||||
NetESelect*res = new NetESelect(net, mux, darray->element_width());
|
||||
NetESelect*res = new NetESelect(net, mux, darray->element_width(), darray->element_type());
|
||||
res->set_line(*net);
|
||||
return res;
|
||||
}
|
||||
@@ -5597,13 +5723,15 @@ NetExpr* PEIdent::elaborate_expr_net_bit_last_(Design*, NetScope*,
|
||||
}
|
||||
|
||||
unsigned use_width = 1;
|
||||
ivl_type_t use_type = 0;
|
||||
if (const netdarray_t*darray = net->sig()->darray_type()) {
|
||||
use_width = darray->element_width();
|
||||
use_type = darray->element_type();
|
||||
}
|
||||
|
||||
NetELast*mux = new NetELast(net->sig());
|
||||
mux->set_line(*this);
|
||||
NetESelect*ss = new NetESelect(net, mux, use_width);
|
||||
NetESelect*ss = new NetESelect(net, mux, use_width, use_type);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
@@ -6262,6 +6390,16 @@ NetExpr*PETypename::elaborate_expr(Design*des, NetScope*,
|
||||
|
||||
unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
{
|
||||
// Evaluate the expression width to get the correct type information
|
||||
expr_width_ = expr_->test_width(des, scope, mode);
|
||||
|
||||
if (expr_->expr_type() == IVL_VT_CLASS) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Class/null is not allowed with the '"
|
||||
<< human_readable_op(op_) << "' operator." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
switch (op_) {
|
||||
case '&': // Reduction AND
|
||||
case '|': // Reduction OR
|
||||
@@ -6291,7 +6429,6 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
expr_width_ = expr_->test_width(des, scope, mode);
|
||||
expr_type_ = expr_->expr_type();
|
||||
min_width_ = expr_->min_width();
|
||||
signed_flag_ = expr_->has_sign();
|
||||
|
||||
+73
-20
@@ -36,6 +36,8 @@
|
||||
# include <climits>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* These methods generate a NetAssign_ object for the l-value of the
|
||||
* assignment. This is common code for the = and <= statements.
|
||||
@@ -247,12 +249,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
// Special case: The l-value is an entire memory, or array
|
||||
// slice. This is, in fact, an error in l-values. Detect the
|
||||
// situation by noting if the index count is less than the
|
||||
// array dimensions (unpacked).
|
||||
// slice. Detect the situation by noting if the index count
|
||||
// is less than the array dimensions (unpacked).
|
||||
if (reg->unpacked_dimensions() > name_tail.index.size()) {
|
||||
cerr << get_fileline() << ": error: Cannot assign to array "
|
||||
<< path_ << ". Did you forget a word index?" << endl;
|
||||
if (gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": sorry: Assignment to an entire"
|
||||
" array or to an array slice is not yet supported."
|
||||
<< endl;
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Assignment to an entire"
|
||||
" array or to an array slice requires SystemVerilog."
|
||||
<< endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -853,12 +861,20 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
// If there are fewer indices then there are packed
|
||||
// dimensions, then this is a range of slices. Calculate
|
||||
// it into a big slice.
|
||||
bool lrc;
|
||||
bool lrc, mrc;
|
||||
unsigned long tmp_lwid, tmp_mwid;
|
||||
lrc = reg->sb_to_slice(prefix_indices,lsb, loff, tmp_lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = reg->sb_to_slice(prefix_indices,msb, moff, tmp_mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = reg->sb_to_slice(prefix_indices, lsb, loff, tmp_lwid);
|
||||
mrc = reg->sb_to_slice(prefix_indices, msb, moff, tmp_mwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << msb << ":" << lsb;
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (loff < moff) {
|
||||
moff = moff + tmp_mwid - 1;
|
||||
@@ -938,21 +954,58 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
// we will handle it in the code generator.
|
||||
if (base_c->value().is_defined()) {
|
||||
long lsv = base_c->value().as_long();
|
||||
long offset = 0;
|
||||
long rel_base = 0;
|
||||
// Get the signal range.
|
||||
const vector<netrange_t>&packed = reg->packed_dims();
|
||||
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
|
||||
if (prefix_indices.size()+1 < reg->packed_dims().size()) {
|
||||
// Here we are selecting one or more sub-arrays.
|
||||
// Make this work by finding the indexed sub-arrays and
|
||||
// creating a generated slice that spans the whole range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc, mrc;
|
||||
mrc = reg->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
lrc = reg->sb_to_slice(prefix_indices, lsv+wid-1, loff, lwid);
|
||||
else
|
||||
lrc = reg->sb_to_slice(prefix_indices, lsv-wid+1, loff, lwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << lsv;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] exceeds the declared bounds for ";
|
||||
cerr << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (((rng.get_msb() < rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((rng.get_msb() > rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||
offset = -wid + 1;
|
||||
if (moff > loff) {
|
||||
rel_base = loff;
|
||||
wid = moff + mwid - loff;
|
||||
} else {
|
||||
rel_base = moff;
|
||||
wid = loff + lwid - moff;
|
||||
}
|
||||
} else {
|
||||
long offset = 0;
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (((rng.get_msb() < rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((rng.get_msb() > rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
|
||||
}
|
||||
delete base;
|
||||
long rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
|
||||
/* If we cover the entire lvalue just skip the select. */
|
||||
if (rel_base == 0 && wid == reg->vector_width()) return true;
|
||||
base = new NetEConst(verinum(rel_base));
|
||||
|
||||
+90
-42
@@ -32,6 +32,8 @@
|
||||
# include <iostream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value. The return values is the *input* net of
|
||||
@@ -262,49 +264,87 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
}
|
||||
|
||||
long midx_val = tmp->value().as_long();
|
||||
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
||||
delete tmp_ex;
|
||||
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
|
||||
// Here we are selecting one or more sub-arrays.
|
||||
// Make this work by finding the indexed sub-arrays and
|
||||
// creating a generated slice that spans the whole range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool mrc, lrc;
|
||||
mrc = sig->sb_to_slice(prefix_indices, midx_val, moff, mwid);
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lrc = sig->sb_to_slice(prefix_indices, midx_val+wid-1, loff, lwid);
|
||||
else
|
||||
lrc = sig->sb_to_slice(prefix_indices, midx_val-wid+1, loff, lwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] exceeds the declared bounds for ";
|
||||
cerr << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
||||
else
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
|
||||
|
||||
if (midx < lidx) {
|
||||
long tmpx = midx;
|
||||
midx = lidx;
|
||||
lidx = tmpx;
|
||||
}
|
||||
|
||||
/* Warn about an indexed part select that is out of range. */
|
||||
if (warn_ob_select && (lidx < 0)) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
if (moff > loff) {
|
||||
lidx = loff;
|
||||
midx = moff + mwid - 1;
|
||||
} else {
|
||||
cerr << "-:";
|
||||
lidx = moff;
|
||||
midx = loff + lwid - 1;
|
||||
}
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
} else {
|
||||
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
||||
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
||||
return false;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
||||
else
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
|
||||
|
||||
if (midx < lidx) {
|
||||
long tmpx = midx;
|
||||
midx = lidx;
|
||||
lidx = tmpx;
|
||||
}
|
||||
|
||||
/* Warn about an indexed part select that is out of range. */
|
||||
if (warn_ob_select && (lidx < 0)) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -338,11 +378,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
// range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc;
|
||||
bool lrc, mrc;
|
||||
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
mrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << msb << ":" << lsb;
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
if (moff > loff) {
|
||||
|
||||
+42
-41
@@ -54,6 +54,7 @@
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
|
||||
{
|
||||
@@ -468,7 +469,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
|
||||
netclass_t*use_base_class = 0;
|
||||
if (base_class) {
|
||||
use_base_class = scope->find_class(base_class->name);
|
||||
use_base_class = scope->find_class(des, base_class->name);
|
||||
if (use_base_class == 0) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
<< "Base class " << base_class->name
|
||||
@@ -894,6 +895,18 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
}
|
||||
}
|
||||
|
||||
void PGenerate::check_for_valid_genvar_value_(long value)
|
||||
{
|
||||
if (generation_flag < GN_VER2005 && value < 0) {
|
||||
cerr << get_fileline() << ": warning: A negative value (" << value
|
||||
<< ") has been assigned to genvar '" << loop_index << "'."
|
||||
<< endl;
|
||||
cerr << get_fileline() << ": : This is illegal in "
|
||||
"Verilog-2001. Use at least -g2005 to remove this warning."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the elaborate scope method for a generate loop.
|
||||
*/
|
||||
@@ -903,8 +916,16 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// Check that the loop_index variable was declared in a
|
||||
// genvar statement.
|
||||
NetScope*cscope = container;
|
||||
while (cscope && !cscope->find_genvar(loop_index))
|
||||
while (cscope && !cscope->find_genvar(loop_index)) {
|
||||
if (cscope->symbol_exists(loop_index)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "generate loop variable '" << loop_index
|
||||
<< "' is not a genvar in this scope." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
cscope = cscope->parent();
|
||||
}
|
||||
if (!cscope) {
|
||||
cerr << get_fileline() << ": error: genvar is missing for "
|
||||
"generate \"loop\" variable '" << loop_index << "'."
|
||||
@@ -915,7 +936,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
}
|
||||
|
||||
// We're going to need a genvar...
|
||||
int genvar;
|
||||
long genvar;
|
||||
|
||||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
@@ -930,6 +951,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
}
|
||||
|
||||
genvar = init->value().as_long();
|
||||
check_for_valid_genvar_value_(genvar);
|
||||
delete init_ex;
|
||||
|
||||
if (debug_scopes)
|
||||
@@ -966,7 +988,11 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// block. Code within this scope thus has access to the
|
||||
// genvar as a constant.
|
||||
{
|
||||
verinum genvar_verinum(genvar);
|
||||
verinum genvar_verinum;
|
||||
if (gn_strict_expr_width_flag)
|
||||
genvar_verinum = verinum(genvar, integer_width);
|
||||
else
|
||||
genvar_verinum = verinum(genvar);
|
||||
genvar_verinum.has_sign(true);
|
||||
NetEConstParam*gp = new NetEConstParam(scope,
|
||||
loop_index,
|
||||
@@ -996,6 +1022,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
|
||||
genvar = step->value().as_long();
|
||||
check_for_valid_genvar_value_(genvar);
|
||||
container->genvar_tmp_val = genvar;
|
||||
delete step;
|
||||
delete test_ex;
|
||||
@@ -1042,8 +1069,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
<< " value=" << test->value() << ": Generate scope="
|
||||
<< use_name << endl;
|
||||
|
||||
probe_for_direct_nesting_();
|
||||
if (direct_nested_) {
|
||||
if (directly_nested) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
@@ -1141,8 +1167,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (item->scope_name);
|
||||
|
||||
item->probe_for_direct_nesting_();
|
||||
if (item->direct_nested_) {
|
||||
if (item->directly_nested) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
||||
<< " detected direct nesting." << endl;
|
||||
@@ -1355,7 +1380,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
return;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
if (is_array()) {
|
||||
// If there are expressions to evaluate in order to know
|
||||
// the actual number of instances that will be
|
||||
// instantiated, then we have to delay further scope
|
||||
@@ -1385,41 +1410,17 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
*/
|
||||
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1, true) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
|
||||
assert( (msb == 0) || (lsb != 0) );
|
||||
|
||||
long instance_low = 0;
|
||||
long instance_high = 0;
|
||||
long instance_count = 1;
|
||||
bool instance_array = false;
|
||||
|
||||
if (msb) {
|
||||
instance_array = true;
|
||||
instance_high = msb->value().as_long();
|
||||
instance_low = lsb->value().as_long();
|
||||
if (instance_high > instance_low)
|
||||
instance_count = instance_high - instance_low + 1;
|
||||
else
|
||||
instance_count = instance_low - instance_high + 1;
|
||||
|
||||
delete mse;
|
||||
delete lse;
|
||||
}
|
||||
long instance_count = calculate_array_size_(des, sc, instance_high, instance_low);
|
||||
if (instance_count == 0)
|
||||
return;
|
||||
|
||||
NetScope::scope_vec_t instances (instance_count);
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Create " << instance_count
|
||||
<< " instances of " << get_name()
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
|
||||
|
||||
// Run through the module instances, and make scopes out of
|
||||
// them. Also do parameter overrides that are done on the
|
||||
@@ -1428,8 +1429,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
|
||||
hname_t use_name (get_name());
|
||||
|
||||
if (instance_array) {
|
||||
int instance_idx = idx;
|
||||
if (is_array()) {
|
||||
int instance_idx;
|
||||
if (instance_low < instance_high)
|
||||
instance_idx = instance_low + idx;
|
||||
else
|
||||
|
||||
+5
-5
@@ -198,7 +198,7 @@ static void elaborate_sig_classes(Design*des, NetScope*scope,
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
netclass_t*use_class = scope->find_class(cur->second->pscope_name());
|
||||
netclass_t*use_class = scope->find_class(des, cur->second->pscope_name());
|
||||
use_class->elaborate_sig(des, cur->second);
|
||||
}
|
||||
}
|
||||
@@ -429,7 +429,7 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
|
||||
|
||||
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
if (directly_nested)
|
||||
return elaborate_sig_direct_(des, container);
|
||||
|
||||
bool flag = true;
|
||||
@@ -448,7 +448,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
@@ -496,12 +496,12 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
|
||||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
|
||||
+189
-170
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -51,6 +51,7 @@
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Implemented in elab_scope.cc
|
||||
extern void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope);
|
||||
@@ -61,6 +62,44 @@ void PGate::elaborate(Design*, NetScope*) const
|
||||
typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
unsigned PGate::calculate_array_size_(Design*des, NetScope*scope,
|
||||
long&high, long&low) const
|
||||
{
|
||||
if (ranges_ && ranges_->size() > 1) {
|
||||
if (gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": sorry: Multi-dimensional"
|
||||
<< " arrays of instances are not yet supported." << endl;
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Multi-dimensional"
|
||||
<< " arrays of instances require SystemVerilog." << endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned size = 1;
|
||||
high = 0;
|
||||
low = 0;
|
||||
|
||||
if (ranges_) {
|
||||
if (!evaluate_range(des, scope, this, ranges_->front(), high, low))
|
||||
return 0;
|
||||
|
||||
if (high > low)
|
||||
size = high - low + 1;
|
||||
else
|
||||
size = low - high + 1;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGate: Make array "
|
||||
<< "[" << high << ":" << low << "]" << " of "
|
||||
<< size << " instances for " << get_name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the continuous assign. (This is *not* the procedural
|
||||
* assign.) Elaborate the lvalue and rvalue, and do the assignment.
|
||||
@@ -110,6 +149,18 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return;
|
||||
}
|
||||
|
||||
if (lval->enumeration()) {
|
||||
if (! rval_expr->enumeration()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (! lval->enumeration()->matches(rval_expr->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet*rval = rval_expr->synthesize(des, scope, rval_expr);
|
||||
|
||||
if (rval == 0) {
|
||||
@@ -220,61 +271,6 @@ void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval
|
||||
assign_unpacked_with_bufz(des, scope, this, lval, rval_net);
|
||||
}
|
||||
|
||||
unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
||||
long&high, long&low) const
|
||||
{
|
||||
unsigned count = 1;
|
||||
high = 0;
|
||||
low = 0;
|
||||
|
||||
/* If the Verilog source has a range specification for the
|
||||
gates, then I am expected to make more than one
|
||||
gate. Figure out how many are desired. */
|
||||
if (msb_) {
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
|
||||
|
||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||
|
||||
if (msb_con == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
"expression " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lsb_con == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
"expression " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum msb = msb_con->value();
|
||||
verinum lsb = lsb_con->value();
|
||||
|
||||
delete msb_exp;
|
||||
delete lsb_exp;
|
||||
|
||||
if (msb.as_long() > lsb.as_long())
|
||||
count = msb.as_long() - lsb.as_long() + 1;
|
||||
else
|
||||
count = lsb.as_long() - msb.as_long() + 1;
|
||||
|
||||
low = lsb.as_long();
|
||||
high = msb.as_long();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGBuiltin: Make array "
|
||||
<< "[" << high << ":" << low << "]" << " of "
|
||||
<< count << " gates for " << get_name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void PGBuiltin::calculate_gate_and_lval_count_(unsigned&gate_count,
|
||||
unsigned&lval_count) const
|
||||
{
|
||||
@@ -710,7 +706,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
the count is 1, and high==low==0. */
|
||||
|
||||
long low=0, high=0;
|
||||
unsigned array_count = calculate_array_count_(des, scope, high, low);
|
||||
unsigned array_count = calculate_array_size_(des, scope, high, low);
|
||||
if (array_count == 0) return;
|
||||
|
||||
unsigned gate_count = 0, lval_count = 0;
|
||||
@@ -841,10 +837,10 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
// to be the exact width required (this will be checked
|
||||
// later). But if this is a single instance, consensus
|
||||
// is that we just take the LSB of the port expression.
|
||||
NetExpr*tmp = elab_and_eval(des, scope, ex, msb_ ? -1 : 1);
|
||||
NetExpr*tmp = elab_and_eval(des, scope, ex, is_array() ? -1 : 1);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
if (msb_ == 0 && tmp->expr_width() != 1)
|
||||
if (!is_array() && tmp->expr_width() != 1)
|
||||
tmp = new NetESelect(tmp, make_const_0(1), 1,
|
||||
IVL_SEL_IDX_UP);
|
||||
sig = tmp->synthesize(des, scope, tmp);
|
||||
@@ -1188,7 +1184,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// Handle wildcard named port
|
||||
if (pins_[idx].name[0] == '*') {
|
||||
for (unsigned j = 0 ; j < nexp ; j += 1) {
|
||||
if ((!pins[j]) && (!pins_is_explicitly_not_connected[j])) {
|
||||
if (rmod->ports[j] && !pins[j] && !pins_is_explicitly_not_connected[j]) {
|
||||
pins_fromwc[j] = true;
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
@@ -1476,17 +1472,23 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Input to module. elaborate the expression to
|
||||
the desired width. If this in an instance
|
||||
array, then let the net determine its own
|
||||
width. We use that, then, to decide how to hook
|
||||
it up.
|
||||
/* Input to module. Here we elaborate the source expression
|
||||
using its self-determined width. This allows us to check
|
||||
for and warn about port width mismatches. But in the
|
||||
special case that the source expression is a SV unbased
|
||||
unsized literal, we need to force the expression width
|
||||
to match the destination.
|
||||
|
||||
NOTE that this also handles the case that the
|
||||
port is actually empty on the inside. We assume
|
||||
in that case that the port is input. */
|
||||
|
||||
NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], -1);
|
||||
int context_width = -1;
|
||||
if (PENumber*literal = dynamic_cast<PENumber*>(pins[idx])) {
|
||||
if (literal->value().is_single())
|
||||
context_width = prts_vector_width;
|
||||
}
|
||||
NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], context_width);
|
||||
if (tmp_expr == 0) {
|
||||
cerr << pins[idx]->get_fileline()
|
||||
<< ": error: Failed to elaborate port expression."
|
||||
@@ -1956,62 +1958,6 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
}
|
||||
|
||||
unsigned PGModule::calculate_instance_count_(Design*des, NetScope*scope,
|
||||
long&high, long&low,
|
||||
perm_string name) const
|
||||
{
|
||||
unsigned count = 1;
|
||||
high = 0;
|
||||
low = 0;
|
||||
|
||||
/* If the Verilog source has a range specification for the UDP, then
|
||||
* I am expected to make more than one gate. Figure out how many are
|
||||
* desired. */
|
||||
if (msb_) {
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
|
||||
|
||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||
|
||||
if (msb_con == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
"expression " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lsb_con == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
"expression " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum msb = msb_con->value();
|
||||
verinum lsb = lsb_con->value();
|
||||
|
||||
delete msb_exp;
|
||||
delete lsb_exp;
|
||||
|
||||
if (msb.as_long() > lsb.as_long())
|
||||
count = msb.as_long() - lsb.as_long() + 1;
|
||||
else
|
||||
count = lsb.as_long() - msb.as_long() + 1;
|
||||
|
||||
low = lsb.as_long();
|
||||
high = msb.as_long();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGModule: Make range "
|
||||
<< "[" << high << ":" << low << "]" << " of "
|
||||
<< count << " UDPs for " << name << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* From a UDP definition in the source, make a NetUDP
|
||||
* object. Elaborate the pin expressions as netlists, then connect
|
||||
@@ -2043,8 +1989,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||
}
|
||||
|
||||
long low = 0, high = 0;
|
||||
unsigned inst_count = calculate_instance_count_(des, scope, high, low,
|
||||
my_name);
|
||||
unsigned inst_count = calculate_array_size_(des, scope, high, low);
|
||||
if (inst_count == 0) return;
|
||||
|
||||
if (inst_count != 1) {
|
||||
@@ -3524,8 +3469,10 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
// For SystemVerilog this may be a few other things.
|
||||
if (gn_system_verilog()) {
|
||||
NetProc *tmp;
|
||||
// This could be a method attached to a signal?
|
||||
tmp = elaborate_method_(des, scope);
|
||||
// This could be a method attached to a signal
|
||||
// or defined in this object?
|
||||
bool try_implicit_this = scope->get_class_scope() && path_.size() == 1;
|
||||
tmp = elaborate_method_(des, scope, try_implicit_this);
|
||||
if (tmp) return tmp;
|
||||
// Or it could be a function call ignoring the return?
|
||||
tmp = elaborate_function_(des, scope);
|
||||
@@ -3567,6 +3514,9 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
/* Handle non-automatic tasks with no parameters specially. There is
|
||||
no need to make a sequential block to hold the generated code. */
|
||||
if ((parm_count == 0) && !task->is_auto()) {
|
||||
// Check if a task call is allowed in this context.
|
||||
test_task_calls_ok_(des, scope);
|
||||
|
||||
NetUTask*cur = new NetUTask(task);
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
@@ -3701,6 +3651,38 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
|
||||
return sys;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used for array/queue function methods called as tasks.
|
||||
*/
|
||||
NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
|
||||
NetNet*net,
|
||||
ivl_variable_type_t type,
|
||||
unsigned width,
|
||||
bool signed_flag,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const
|
||||
{
|
||||
cerr << get_fileline() << ": warning: method function '"
|
||||
<< method_name << "' is being called as a task." << endl;
|
||||
|
||||
// Generate the function.
|
||||
NetESFunc*sys_expr = new NetESFunc(sys_task_name, type, width, 1);
|
||||
sys_expr->set_line(*this);
|
||||
NetESignal*arg = new NetESignal(net);
|
||||
arg->set_line(*net);
|
||||
sys_expr->parm(0, arg);
|
||||
// Create a L-value that matches the function return type.
|
||||
NetNet*tmp;
|
||||
netvector_t*tmp_vec = new netvector_t(type, width-1, 0, signed_flag);
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, tmp_vec);
|
||||
tmp->set_line(*this);
|
||||
NetAssign_*lv = new NetAssign_(tmp);
|
||||
// Generate an assign to the fake L-value.
|
||||
NetAssign*cur = new NetAssign(lv, sys_expr);
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
}
|
||||
|
||||
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||
bool add_this_flag) const
|
||||
{
|
||||
@@ -3732,13 +3714,21 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
// Is this a delete method for dynamic arrays?
|
||||
if (net->darray_type() && method_name=="delete") {
|
||||
return elaborate_sys_task_method_(des, scope, net, method_name,
|
||||
"$ivl_darray_method$delete");
|
||||
// Is this a delete method for dynamic arrays or queues?
|
||||
if (net->darray_type()) {
|
||||
if (method_name=="delete")
|
||||
return elaborate_sys_task_method_(des, scope, net, method_name,
|
||||
"$ivl_darray_method$delete");
|
||||
else if (method_name=="size")
|
||||
// This returns an int. It could be removed, but keep for now.
|
||||
return elaborate_method_func_(scope, net,
|
||||
IVL_VT_BOOL, 32,
|
||||
true, method_name,
|
||||
"$size");
|
||||
}
|
||||
|
||||
if (net->queue_type()) {
|
||||
const netdarray_t*use_darray = net->darray_type();
|
||||
if (method_name == "push_back")
|
||||
return elaborate_queue_method_(des, scope, net, method_name,
|
||||
"$ivl_queue_method$push_back");
|
||||
@@ -3748,6 +3738,18 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||
else if (method_name == "insert")
|
||||
return elaborate_queue_method_(des, scope, net, method_name,
|
||||
"$ivl_queue_method$insert");
|
||||
else if (method_name == "pop_front")
|
||||
return elaborate_method_func_(scope, net,
|
||||
use_darray->element_base_type(),
|
||||
use_darray->element_width(),
|
||||
false, method_name,
|
||||
"$ivl_queue_method$pop_front");
|
||||
else if (method_name == "pop_back")
|
||||
return elaborate_method_func_(scope, net,
|
||||
use_darray->element_base_type(),
|
||||
use_darray->element_width(),
|
||||
false, method_name,
|
||||
"$ivl_queue_method$pop_back");
|
||||
}
|
||||
|
||||
if (const netclass_t*class_type = net->class_type()) {
|
||||
@@ -3779,7 +3781,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||
* If during elaboration we determine (for sure) that we are calling a
|
||||
* task (and not just a void function) then this method tests if that
|
||||
* task call is allowed in the current context. If so, return true. If
|
||||
* not, print and error message and return false;
|
||||
* not, print an error message and return false;
|
||||
*/
|
||||
bool PCallTask::test_task_calls_ok_(Design*des, NetScope*scope) const
|
||||
{
|
||||
@@ -3835,7 +3837,14 @@ NetProc* PCallTask::elaborate_void_function_(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, dscope->elab_stage() >= 3);
|
||||
// If we haven't already elaborated the function, do so now.
|
||||
// This allows elaborate_build_call_ to elide the function call
|
||||
// if the function body is empty.
|
||||
if (dscope->elab_stage() < 3) {
|
||||
const PFunction*pfunc = dscope->func_pform();
|
||||
ivl_assert(*this, pfunc);
|
||||
pfunc->elaborate(des, dscope);
|
||||
}
|
||||
return elaborate_build_call_(des, scope, dscope, 0);
|
||||
}
|
||||
|
||||
@@ -3884,8 +3893,13 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
task, all the assignments, etc. Just return a no-op. */
|
||||
|
||||
if (const NetBlock*tp = dynamic_cast<const NetBlock*>(def->proc())) {
|
||||
if (tp->proc_first() == 0)
|
||||
if (tp->proc_first() == 0) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PCallTask::elaborate_build_call_: "
|
||||
<< "Eliding call to empty task " << task->basename() << endl;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is an automatic task, generate a statement to
|
||||
@@ -5261,14 +5275,18 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
assert(def);
|
||||
|
||||
ivl_assert(*this, statement_);
|
||||
NetProc*st = statement_->elaborate(des, scope);
|
||||
if (st == 0) {
|
||||
cerr << statement_->get_fileline() << ": error: Unable to elaborate "
|
||||
"statement in function " << scope->basename() << "." << endl;
|
||||
scope->is_const_func(true); // error recovery
|
||||
des->errors += 1;
|
||||
return;
|
||||
NetProc*st;
|
||||
if (statement_ == 0) {
|
||||
st = new NetBlock(NetBlock::SEQU, 0);
|
||||
} else {
|
||||
st = statement_->elaborate(des, scope);
|
||||
if (st == 0) {
|
||||
cerr << statement_->get_fileline() << ": error: Unable to elaborate "
|
||||
"statement in function " << scope->basename() << "." << endl;
|
||||
scope->is_const_func(true); // error recovery
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle any variable initialization statements in this scope.
|
||||
@@ -5900,7 +5918,7 @@ static void elaborate_classes(Design*des, NetScope*scope,
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
netclass_t*use_class = scope->find_class(cur->second->pscope_name());
|
||||
netclass_t*use_class = scope->find_class(des, cur->second->pscope_name());
|
||||
use_class->elaborate(des, cur->second);
|
||||
|
||||
if (use_class->test_for_missing_initializers()) {
|
||||
@@ -6041,7 +6059,7 @@ void netclass_t::elaborate(Design*des, PClass*pclass)
|
||||
|
||||
bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
if (directly_nested)
|
||||
return elaborate_direct_(des, container);
|
||||
|
||||
bool flag = true;
|
||||
@@ -6066,7 +6084,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
flag &= item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
@@ -6128,7 +6146,7 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
||||
cerr << get_fileline() << ": PGenerate::elaborate_direct_: "
|
||||
<< "item->scope_name=" << item->scope_name
|
||||
<< ", item->scheme_type=" << item->scheme_type
|
||||
<< ", item->direct_nested_=" << item->direct_nested_
|
||||
<< ", item->directly_nested=" << item->directly_nested
|
||||
<< ", item->scope_list_.size()=" << item->scope_list_.size()
|
||||
<< "." << endl;
|
||||
}
|
||||
@@ -6141,12 +6159,12 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
||||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate(des, container);
|
||||
}
|
||||
@@ -6560,7 +6578,7 @@ static void check_event_probe_width(const LineInfo *info, const NetEvProbe *prb)
|
||||
assert(prb->pin(0).is_linked());
|
||||
if (prb->edge() == NetEvProbe::ANYEDGE) return;
|
||||
if (prb->pin(0).nexus()->vector_width() > 1) {
|
||||
cerr << info->get_fileline() << " Warning: Synthesis wants "
|
||||
cerr << info->get_fileline() << " warning: Synthesis wants "
|
||||
"the sensitivity list expressions for '";
|
||||
switch (prb->edge()) {
|
||||
case NetEvProbe::POSEDGE:
|
||||
@@ -6590,7 +6608,7 @@ static void check_ff_sensitivity(const NetProc* statement)
|
||||
const NetEvProbe *prb = evt->probe(cprb);
|
||||
check_event_probe_width(evwt, prb);
|
||||
if (prb->edge() == NetEvProbe::ANYEDGE) {
|
||||
cerr << evwt->get_fileline() << " Warning: Synthesis "
|
||||
cerr << evwt->get_fileline() << " warning: Synthesis "
|
||||
"requires the sensitivity list of an "
|
||||
"always_ff process to only be edge "
|
||||
"sensitive. ";
|
||||
@@ -6657,18 +6675,18 @@ static void check_timescales()
|
||||
if (some_explicit && some_implicit)
|
||||
break;
|
||||
}
|
||||
map<perm_string,PPackage*>::iterator pkg;
|
||||
vector<PPackage*>::iterator pkg;
|
||||
if (gn_system_verilog() && !(some_explicit && some_implicit)) {
|
||||
for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) {
|
||||
const PPackage*pp = (*pkg).second;
|
||||
const PPackage*pp = *pkg;
|
||||
check_timescales(some_explicit, some_implicit, pp);
|
||||
if (some_explicit && some_implicit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gn_system_verilog() && !(some_explicit && some_implicit)) {
|
||||
for (unsigned idx = 0; idx < pform_units.size(); idx += 1) {
|
||||
const PPackage*pp = pform_units[idx];
|
||||
for (pkg = pform_units.begin(); pkg != pform_units.end(); ++pkg) {
|
||||
const PPackage*pp = *pkg;
|
||||
// We don't need a timescale if the compilation unit
|
||||
// contains no items outside a design element.
|
||||
if (pp->parameters.empty() &&
|
||||
@@ -6719,15 +6737,15 @@ static void check_timescales()
|
||||
return;
|
||||
|
||||
for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) {
|
||||
PPackage*pp = (*pkg).second;
|
||||
PPackage*pp = *pkg;
|
||||
if (pp->has_explicit_timescale())
|
||||
continue;
|
||||
cerr << " : -- package " << (*pkg).first
|
||||
cerr << " : -- package " << pp->pscope_name()
|
||||
<< " declared here: " << pp->get_fileline() << endl;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0; idx < pform_units.size(); idx += 1) {
|
||||
PPackage*pp = pform_units[idx];
|
||||
for (pkg = pform_units.begin(); pkg != pform_units.end(); ++pkg) {
|
||||
PPackage*pp = *pkg;
|
||||
if (pp->has_explicit_timescale())
|
||||
continue;
|
||||
|
||||
@@ -6783,8 +6801,9 @@ Design* elaborate(list<perm_string>roots)
|
||||
// Elaborate the compilation unit scopes. From here on, these are
|
||||
// treated as an additional set of packages.
|
||||
if (gn_system_verilog()) {
|
||||
for (i = 0; i < pform_units.size(); i += 1) {
|
||||
PPackage*unit = pform_units[i];
|
||||
for (vector<PPackage*>::iterator pkg = pform_units.begin()
|
||||
; pkg != pform_units.end() ; ++pkg) {
|
||||
PPackage*unit = *pkg;
|
||||
NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true);
|
||||
scope->set_line(unit);
|
||||
scope->add_imports(&unit->explicit_imports);
|
||||
@@ -6795,6 +6814,7 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
pack_elems[i].pack = unit;
|
||||
pack_elems[i].scope = scope;
|
||||
i += 1;
|
||||
|
||||
unit_scopes[unit] = scope;
|
||||
}
|
||||
@@ -6805,20 +6825,19 @@ Design* elaborate(list<perm_string>roots)
|
||||
// in SystemVerilog, packages are not allowed to refer to
|
||||
// the compilation unit scope, but the VHDL preprocessor
|
||||
// assumes they can.
|
||||
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
|
||||
; pac != pform_packages.end() ; ++ pac) {
|
||||
for (vector<PPackage*>::iterator pkg = pform_packages.begin()
|
||||
; pkg != pform_packages.end() ; ++pkg) {
|
||||
PPackage*pack = *pkg;
|
||||
NetScope*unit_scope = unit_scopes[pack->parent_scope()];
|
||||
NetScope*scope = des->make_package_scope(pack->pscope_name(), unit_scope, false);
|
||||
scope->set_line(pack);
|
||||
scope->add_imports(&pack->explicit_imports);
|
||||
set_scope_timescale(des, scope, pack);
|
||||
|
||||
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
|
||||
NetScope*unit_scope = unit_scopes[pac->second->parent_scope()];
|
||||
NetScope*scope = des->make_package_scope(pac->first, unit_scope, false);
|
||||
scope->set_line(pac->second);
|
||||
scope->add_imports(&pac->second->explicit_imports);
|
||||
set_scope_timescale(des, scope, pac->second);
|
||||
|
||||
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
|
||||
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pack);
|
||||
des->elaboration_work_list.push_back(es);
|
||||
|
||||
pack_elems[i].pack = pac->second;
|
||||
pack_elems[i].pack = pack;
|
||||
pack_elems[i].scope = scope;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2021 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
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
# include <typeinfo>
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
# include <cassert>
|
||||
# include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool NetNode::emit_node(struct target_t*) const
|
||||
{
|
||||
cerr << "EMIT: Gate type? " << typeid(*this).name() << endl;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2021 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
|
||||
@@ -27,6 +27,8 @@
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
verinum* PExpr::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return 0;
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2021 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
|
||||
@@ -24,6 +24,8 @@
|
||||
# include <iostream>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The evaluate_attributes function evaluates the attribute
|
||||
* expressions from the map, and returns a table in a form suitable
|
||||
|
||||
+32
-7
@@ -29,6 +29,8 @@
|
||||
# include "ivl_assert.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
{
|
||||
return 0;
|
||||
@@ -404,7 +406,6 @@ NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(le, re, true);
|
||||
// assert(expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
|
||||
if (r == 0) return 0;
|
||||
@@ -416,12 +417,6 @@ NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
|
||||
return res;
|
||||
}
|
||||
|
||||
if (le->expr_width() == 0) {
|
||||
cerr << get_fileline() << ": internal error: Something wrong "
|
||||
<< "with the left side width of <= ?" << endl;
|
||||
cerr << get_fileline() << ": : " << *this << endl;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = must_be_leeq_(le, rv, true)) {
|
||||
return tmp;
|
||||
}
|
||||
@@ -816,6 +811,36 @@ NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
|
||||
// If the left side is constant and the right side is short circuited
|
||||
// replace the expression with a constant
|
||||
if (rc == 0 && lc != 0) {
|
||||
verinum v = lc->value();
|
||||
verinum::V res = verinum::Vx;
|
||||
switch (op_) {
|
||||
case 'a': // Logical AND (&&)
|
||||
if (v.is_zero())
|
||||
res = verinum::V0;
|
||||
break;
|
||||
case 'o': // Logical OR (||)
|
||||
if (! v.is_zero() && v.is_defined())
|
||||
res = verinum::V1;
|
||||
break;
|
||||
case 'q': // Logical implication (->)
|
||||
if (v.is_zero())
|
||||
res = verinum::V1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (res != verinum::Vx) {
|
||||
NetEConst*tmp = new NetEConst(verinum(res, 1));
|
||||
ivl_assert(*this, tmp);
|
||||
eval_debug(this, tmp, false);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (lc == 0 || rc == 0) return 0;
|
||||
|
||||
verinum::V lv = verinum::V0;
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Martin Whitaker (icarus@martin-whitaker.me.uk)
|
||||
* Copyright (c) 2016-2021 Martin Whitaker (icarus@martin-whitaker.me.uk)
|
||||
*
|
||||
* 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,6 +26,7 @@
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The exposenodes functor is primarily provided for use by the vlog95
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
|
||||
{
|
||||
verireal vrl(expr->value().as_double());
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_ivl_assert_H
|
||||
#define IVL_ivl_assert_H
|
||||
/*
|
||||
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2021 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
|
||||
@@ -24,9 +24,9 @@
|
||||
#define ivl_assert(tok, expression) \
|
||||
do { \
|
||||
if (! (expression)) { \
|
||||
cerr << (tok).get_fileline() << ": assert: " \
|
||||
<< __FILE__ << ":" << __LINE__ \
|
||||
<< ": failed assertion " << #expression << endl; \
|
||||
std::cerr << (tok).get_fileline() << ": assert: " \
|
||||
<< __FILE__ << ":" << __LINE__ \
|
||||
<< ": failed assertion " << #expression << std::endl; \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
+47
-16
@@ -1,7 +1,7 @@
|
||||
%option prefix="yy"
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1999-2020 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 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
|
||||
@@ -50,7 +50,7 @@ static void do_expand(int use_args);
|
||||
static const char* do_magic(const char*name);
|
||||
static const char* macro_name(void);
|
||||
|
||||
static void include_filename(void);
|
||||
static void include_filename(int macro_str);
|
||||
static void do_include(void);
|
||||
|
||||
static int load_next_input(void);
|
||||
@@ -154,9 +154,9 @@ static void ifdef_leave(void)
|
||||
result = (rc == 0) ? YY_NULL : rc; \
|
||||
} else { \
|
||||
/* We are expanding a macro. Handle the SV `` delimiter. \
|
||||
If the delimiter terminates a compiler directive, leave \
|
||||
If the delimiter terminates a defined macro usage, leave \
|
||||
it in place, otherwise remove it now. */ \
|
||||
if (yytext[0] != '`') { \
|
||||
if (!(yytext[0] == '`' && is_defined(yytext+1))) { \
|
||||
while ((istack->str[0] == '`') && \
|
||||
(istack->str[1] == '`')) { \
|
||||
istack->str += 2; \
|
||||
@@ -186,9 +186,11 @@ static int ma_parenthesis_level = 0;
|
||||
|
||||
%x PPINCLUDE
|
||||
%x DEF_NAME
|
||||
%x DEF_ESC
|
||||
%x DEF_ARG
|
||||
%x DEF_SEP
|
||||
%x DEF_TXT
|
||||
%x MN_ESC
|
||||
%x MA_START
|
||||
%x MA_ADD
|
||||
%x CCOMMENT
|
||||
@@ -286,7 +288,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
|
||||
}
|
||||
|
||||
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
|
||||
<PPINCLUDE>\"[^\"]*\" { include_filename(0); } /* A normal (") string */
|
||||
<PPINCLUDE>`\"[^\"]*`\" { include_filename(1); } /* A macro (`") string */
|
||||
|
||||
<PPINCLUDE>[ \t\b\f] { ; }
|
||||
|
||||
@@ -338,6 +341,11 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*{W}? { BEGIN(DEF_TXT); def_start(); }
|
||||
|
||||
<DEF_NAME>\\ { BEGIN(DEF_ESC); }
|
||||
|
||||
<DEF_ESC>[^ \t\b\f\n\r]+{W}"("{W}? { BEGIN(DEF_ARG); def_start(); }
|
||||
<DEF_ESC>[^ \t\b\f\n\r]+{W} { BEGIN(DEF_TXT); def_start(); }
|
||||
|
||||
/* define arg: <name> = <text> */
|
||||
<DEF_ARG>[a-zA-Z_][a-zA-Z0-9_$]*{W}*"="[^,\)]*{W}? { BEGIN(DEF_SEP); def_add_arg(); }
|
||||
/* define arg: <name> */
|
||||
@@ -352,7 +360,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
|
||||
<DEF_ARG,DEF_SEP>(\n|"\r\n"|"\n\r"|\r){W}? { istack->lineno += 1; fputc('\n', yyout); }
|
||||
|
||||
<DEF_NAME,DEF_ARG,DEF_SEP>. {
|
||||
<DEF_NAME,DEF_ESC,DEF_ARG,DEF_SEP>. {
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: malformed `define directive.\n");
|
||||
error_count += 1;
|
||||
@@ -535,6 +543,24 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
do_expand(0);
|
||||
}
|
||||
|
||||
`\\ { yy_push_state(MN_ESC); }
|
||||
|
||||
<MN_ESC>[^ \t\b\f\n\r]+ {
|
||||
yy_pop_state();
|
||||
if (macro_needs_args(yytext))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
}
|
||||
|
||||
<MN_ESC>. {
|
||||
yy_pop_state();
|
||||
unput(yytext[0]);
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: malformed macro name.\n");
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
/* Stringified version of macro expansion. This is an Icarus extension.
|
||||
When expanding macro text, the SV usage of `` takes precedence. */
|
||||
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
@@ -825,8 +851,13 @@ static void def_add_arg(void)
|
||||
|
||||
/* 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--;
|
||||
as name(, so chop off the ( here. If we have an escaped name,
|
||||
we also need to strip off the white space that terminates the
|
||||
name. */
|
||||
if (yytext[length - 1] == '(') {
|
||||
length--;
|
||||
while (isspace((int)yytext[length - 1])) length--;
|
||||
}
|
||||
|
||||
yytext[length] = 0;
|
||||
|
||||
@@ -1052,15 +1083,15 @@ static void do_define(void)
|
||||
|
||||
define_continue_flag = 0;
|
||||
|
||||
/* Look for comments in the definition, and remove them. The
|
||||
* "//" style comments go to the end of the line and terminate
|
||||
* the definition, but the multi-line comments are simply cut
|
||||
* out, and the define continues.
|
||||
*/
|
||||
/* Look for comments in the definition, and remove them. */
|
||||
cp = strchr(yytext, '/');
|
||||
|
||||
while (cp && *cp) {
|
||||
if (cp[1] == '/') {
|
||||
if (cp[strlen(cp) - 1] == '\\') {
|
||||
define_continue_flag = 1;
|
||||
*cp++ = '\\';
|
||||
}
|
||||
*cp = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1657,7 +1688,7 @@ static void output_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void include_filename(void)
|
||||
static void include_filename(int macro_str)
|
||||
{
|
||||
if(standby) {
|
||||
emit_pathline(istack);
|
||||
@@ -1667,8 +1698,8 @@ static void include_filename(void)
|
||||
}
|
||||
|
||||
standby = malloc(sizeof(struct include_stack_t));
|
||||
standby->path = strdup(yytext+1);
|
||||
standby->path[strlen(standby->path)-1] = 0;
|
||||
standby->path = strdup(yytext+1+macro_str);
|
||||
standby->path[strlen(standby->path)-1-macro_str] = 0;
|
||||
standby->lineno = 0;
|
||||
standby->comment = NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# This test is sensitive to the number of bytes in the text file.
|
||||
ivltests/pr1819452.txt text eol=lf
|
||||
|
||||
# MSY2 expected results require LF line endings.
|
||||
regression_report-msys2.txt text eol=lf
|
||||
@@ -0,0 +1,33 @@
|
||||
# Lines that start with '#' are comments.
|
||||
#
|
||||
# This file is for the development branch of Icarus Verilog.
|
||||
#
|
||||
# The following files will be ignored by git.
|
||||
|
||||
# The log and work directories
|
||||
ivl_vhdl_work/
|
||||
log/
|
||||
work/
|
||||
vpi_log/
|
||||
vhdl/
|
||||
|
||||
# The normal regression output files.
|
||||
|
||||
regression_report.txt
|
||||
vhdl_regression_report.txt
|
||||
|
||||
# These should be cleaned up, but ignore them as well.
|
||||
*~
|
||||
*.o
|
||||
*.vpi
|
||||
*.tmp
|
||||
src/vcddiff
|
||||
vsim
|
||||
vlog95.v
|
||||
tmp_blif.blif
|
||||
tmp_blif.v
|
||||
tmp_blif.vvp
|
||||
|
||||
# Some tests do not work out of the work directory, so
|
||||
# ignore these files that they leave in the home directory.
|
||||
dump.vcd
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
####################
|
||||
#
|
||||
# Main test script
|
||||
#
|
||||
####################
|
||||
|
||||
There are a group of tests that are meant to exercise the compiler
|
||||
and the run time. To run them just type:
|
||||
|
||||
./regress
|
||||
|
||||
or
|
||||
|
||||
perl vvp_reg.pl
|
||||
|
||||
or if perl is located in /usr/bin
|
||||
|
||||
./vvp_reg.pl
|
||||
|
||||
The output from these tests are displayed on the screen
|
||||
and are also placed in the regression_report.txt file.
|
||||
The expected output for the current development release
|
||||
is located in the regression_report-devel.txt file. The
|
||||
expected output for stable (released) versions can be
|
||||
found in files named regression_report-v<version>.txt.
|
||||
|
||||
The results from individual tests can be found in the
|
||||
log directory and gold files, when needed, are in the
|
||||
gold directory. The source files can be found in the
|
||||
ivltests and contrib directories. The list of tests
|
||||
and how they are run are in the regress-*.list files.
|
||||
|
||||
To check a specific suffixed version of Icarus Verilog
|
||||
use the --suffix=<suffix> flag to tell the script which
|
||||
version to run e.g.(--suffix=-10 will test iverilog-10,
|
||||
etc.). You can also run the test with valgrind (very very
|
||||
slow) by giving the script the --with-valgrind flag.
|
||||
|
||||
|
||||
####################
|
||||
#
|
||||
# VPI test script
|
||||
#
|
||||
####################
|
||||
|
||||
To test the VPI interface type:
|
||||
|
||||
perl vpi_reg.pl
|
||||
|
||||
or if perl is located in /usr/bin
|
||||
|
||||
./vpi_reg.pl
|
||||
|
||||
All these tests should pass for V11.devel. There are
|
||||
some expected failures for V10, which are flagged as
|
||||
Not Implemented
|
||||
|
||||
The individual test results are found in the vpi_log
|
||||
directory and the gold files are in the vpi_gold
|
||||
directory. The source files are in the vpi directory.
|
||||
The vpi_regress.list file has the tests to perform.
|
||||
|
||||
This script also takes the --suffix=<suffix> and the
|
||||
--with-valgrind flags described above.
|
||||
|
||||
|
||||
####################
|
||||
#
|
||||
# VHDL test script
|
||||
#
|
||||
####################
|
||||
|
||||
** Note this is no longer maintained **
|
||||
|
||||
This test script require that ghdl be installed in your
|
||||
path and is used to test the Verilog to VHDL translation.
|
||||
|
||||
perl vhdl_reg.pl
|
||||
|
||||
or if perl is located in /usr/bin
|
||||
|
||||
./vhdl_reg.pl
|
||||
|
||||
The expected output for V0.10.devel and V0.9 is located
|
||||
in the vhdl_regression_report-devel.txt file. V0.8 does
|
||||
not support converting Verilog to VHDL.
|
||||
|
||||
This script also takes the --suffix=<suffix> and the
|
||||
--with-valgrind flags described above.
|
||||
|
||||
|
||||
####################
|
||||
#
|
||||
# BLIF test script
|
||||
#
|
||||
####################
|
||||
|
||||
This test script require that abc be installed in your
|
||||
path and is used to test the Verilog to VHDL translation.
|
||||
|
||||
python blif_reg.py
|
||||
|
||||
There is no expected output as of yet so to check for
|
||||
regressions simply run with and without your patches.
|
||||
|
||||
|
||||
####################
|
||||
#
|
||||
# Windows (MinGW) test issues
|
||||
#
|
||||
####################
|
||||
|
||||
When running under Windows using a MinGW build in a MSYS2
|
||||
shell, the expected output from vvp_reg.pl can be found in
|
||||
regression_report-msys2.txt. The MinGW/MSYS2 specific test
|
||||
exceptions can be found in regress-msys2.list. Exceptions
|
||||
for the VPI tests can be found in the vpi_regress.list file.
|
||||
|
||||
With Windows 10 and MSYS2, there are now very few differences
|
||||
between the Windows and Linux builds.
|
||||
@@ -0,0 +1,21 @@
|
||||
blif01a
|
||||
blif01b
|
||||
blif01c
|
||||
blif01d
|
||||
blif01e
|
||||
blif01f
|
||||
blif01g
|
||||
blif01h
|
||||
blif01i
|
||||
blif02a
|
||||
blif02b
|
||||
blif02c
|
||||
blif02d
|
||||
blif02e
|
||||
blif02f
|
||||
blif02g
|
||||
blif02h
|
||||
blif02i
|
||||
blif02j
|
||||
blif02k
|
||||
blif_shift
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
/*
|
||||
* Generate a combinational adder of any width. The width parameter can
|
||||
* be any integer value >0. The A and B inputs have WID bits, and the Q
|
||||
* output has WID+1 bits to include the overflow.
|
||||
*/
|
||||
module addN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output wire [WID:0] Q
|
||||
/* */);
|
||||
|
||||
wire [WID-1:0] Cout;
|
||||
|
||||
/* The least significant slice has no Cin */
|
||||
add1 U0 (.A(A[0]), .B(B[0]), .Cin(1'b0), .Q(Q[0]), .Cout(Cout[0]));
|
||||
|
||||
/* Generate all the remaining slices */
|
||||
genvar i;
|
||||
for (i = 1 ; i < WID ; i = i+1) begin : U
|
||||
add1 Un (.A(A[i]), .B(B[i]), .Cin(Cout[i-1]), .Q(Q[i]), .Cout(Cout[i]));
|
||||
end
|
||||
|
||||
assign Q[WID] = Cout[WID-1];
|
||||
|
||||
endmodule // add
|
||||
|
||||
/*
|
||||
* This is a single-bit combinational adder used by the addH module
|
||||
* above.
|
||||
*/
|
||||
module add1(input A, input B, input Cin, output Q, output Cout);
|
||||
|
||||
assign Q = A ^ B ^ Cin;
|
||||
assign Cout = A&B | A&Cin | B&Cin;
|
||||
|
||||
endmodule // hadd
|
||||
|
||||
`ifdef TEST_BENCH
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
addN #(.WID(WID)) usum (.A(A), .B(B), .Q(Q));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx+bdx)) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
`endif
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* This is a post-wynthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
addN usum(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.\Q[4] (Q[4]), .\Q[3] (Q[3]), .\Q[2] (Q[2]), .\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx+bdx)) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
module test_logic(input A, B, output q_nand, q_nor, q_xnor, q_not);
|
||||
|
||||
assign q_nand = A ~& B;
|
||||
assign q_nor = A ~| B;
|
||||
assign q_xnor = A ~^ B;
|
||||
assign q_not = ~A;
|
||||
|
||||
endmodule // test_logic
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
module main;
|
||||
|
||||
reg [2:0] X;
|
||||
wire q_nand, q_nor, q_xnor, q_not;
|
||||
|
||||
test_logic DUT(.A(X[0]), .B(X[1]), .q_nand(q_nand), .q_nor(q_nor),
|
||||
.q_xnor(q_xnor), .q_not(q_not));
|
||||
|
||||
initial begin
|
||||
for (X = 0 ; X < 4 ; X = X+1) begin
|
||||
#1 /* Let gates settle. */;
|
||||
if (q_nand !== (X[0] ~& X[1])) begin
|
||||
$display("FAILED -- q_nand=%b, X=%b", q_nand, X[1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_nor !== (X[0] ~| X[1])) begin
|
||||
$display("FAILED -- q_nor=%b, X=%b", q_nor, X[1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_xnor !== (X[0] ~^ X[1])) begin
|
||||
$display("FAILED -- q_xnor=%b, X=%b", q_xnor, X[1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_not !== (~X[0])) begin
|
||||
$display("FAILED -- q_not=%b, X=%b", q_not, X[0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module addN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output wire [WID:0] Q
|
||||
/* */);
|
||||
|
||||
assign Q = A + B;
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* This is a post-wynthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
addN usum(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.\Q[4] (Q[4]), .\Q[3] (Q[3]), .\Q[2] (Q[2]), .\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx+bdx)) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module subN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output wire [WID:0] Q
|
||||
/* */);
|
||||
|
||||
assign Q = A - B;
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* This is a post-wynthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
subN usum(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.\Q[4] (Q[4]), .\Q[3] (Q[3]), .\Q[2] (Q[2]), .\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx[WID-1:0]-bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
module cmpN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output wire QE, QN, QGT, QGE
|
||||
/* */);
|
||||
|
||||
assign QE = A == B;
|
||||
assign QN = A != B;
|
||||
assign QGT = A > B;
|
||||
assign QGE = A >= B;
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
/*
|
||||
* This is a post-synthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire QE, QN, QGT, QGE;
|
||||
|
||||
cmpN ucmp(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.QE(QE), .QN(QN), .QGT(QGT), .QGE(QGE));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 ;
|
||||
if (QE !== (adx[WID-1:0]==bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QE=%b", A, B, QE);
|
||||
$finish;
|
||||
end
|
||||
if (QN !== (adx[WID-1:0]!=bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QN=%b", A, B, QN);
|
||||
$finish;
|
||||
end
|
||||
if (QGT !== (adx[WID-1:0] > bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QGT=%b", A, B, QGT);
|
||||
$finish;
|
||||
end
|
||||
if (QGE !== (adx[WID-1:0] >= bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QGE=%b", A, B, QGE);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module muxN
|
||||
#(parameter WID = 4, parameter SWID = 2)
|
||||
(input wire [WID-1:0] D,
|
||||
input wire [SWID-1:0] S,
|
||||
output wire Q
|
||||
/* */);
|
||||
|
||||
assign Q = D[S];
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
parameter SWID = 2;
|
||||
|
||||
reg [WID-1:0] D;
|
||||
reg [SWID-1:0] S;
|
||||
wire Q;
|
||||
|
||||
muxN dut(.\D[3] (D[3]), .\D[2] (D[2]), .\D[1] (D[1]), .\D[0] (D[0]),
|
||||
.\S[1] (S[1]), .\S[0] (S[0]),
|
||||
.Q(Q));
|
||||
|
||||
integer idx, sdx;
|
||||
initial begin
|
||||
for (idx = 0 ; idx < 50 ; idx += 1) begin
|
||||
D = $random;
|
||||
|
||||
for (sdx = 0 ; sdx < (1<<SWID) ; sdx = sdx+1) begin
|
||||
S = sdx[SWID-1:0];
|
||||
#1 ;
|
||||
if (Q !== D[S]) begin
|
||||
$display("FAILED = D=%b, S=%0d, Q=%b", D, S, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end // for (idx = 0 ; idx < 50 ; idx += 1)
|
||||
$display("PASSED");
|
||||
end // initial begin
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
module test_logic
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
output q_and, q_or, q_xor, q_nand, q_nor, q_xnor);
|
||||
|
||||
assign q_and = & A;
|
||||
assign q_or = | A;
|
||||
assign q_xor = ^ A;
|
||||
assign q_nand= ~& A;
|
||||
assign q_nor = ~| A;
|
||||
assign q_xnor= ~^ A;
|
||||
|
||||
endmodule // test_logic
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
module main;
|
||||
|
||||
localparam WID = 4;
|
||||
reg [WID:0] X;
|
||||
wire q_and, q_or, q_xor, q_nand, q_nor, q_xnor;
|
||||
|
||||
test_logic DUT(.\A[3] (X[3]), .\A[2] (X[2]), .\A[1] (X[1]), .\A[0] (X[0]),
|
||||
.q_and(q_and), .q_or(q_or), .q_xor(q_xor),
|
||||
.q_nand(q_nand), .q_nor(q_nor), .q_xnor(q_xnor));
|
||||
|
||||
initial begin
|
||||
for (X = 0 ; X < 16 ; X = X+1) begin
|
||||
#1 /* Let gates settle. */;
|
||||
if (q_and !== & X[WID-1:0]) begin
|
||||
$display("FAILED -- q_and=%b, X=%b", q_and, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_or !== | X[WID-1:0]) begin
|
||||
$display("FAILED -- q_or=%b, X=%b", q_or, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_xor !== ^ X[WID-1:0]) begin
|
||||
$display("FAILED -- q_xor=%b, X=%b", q_xor, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_nand !== ~& X[WID-1:0]) begin
|
||||
$display("FAILED -- q_nand=%b, X=%b", q_nand, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_nor !== ~| X[WID-1:0]) begin
|
||||
$display("FAILED -- q_nor=%b, X=%b", q_nor, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_xnor !== ~^ X[WID-1:0]) begin
|
||||
$display("FAILED -- q_xnor=%b, X=%b", q_xnor, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
module test_mux
|
||||
(input wire [1:0] D0, D1,
|
||||
input wire S,
|
||||
output wire [1:0] Q);
|
||||
|
||||
assign Q = S? D1 : D0;
|
||||
|
||||
endmodule // test_mux
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
module main;
|
||||
|
||||
reg [1:0] D0, D1;
|
||||
reg sel;
|
||||
wire [1:0] Q;
|
||||
|
||||
test_mux DUT(.S(sel),
|
||||
.\D0[1] (D0[1]), .\D0[0] (D0[0]),
|
||||
.\D1[1] (D1[1]), .\D1[0] (D1[0]),
|
||||
.\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
initial begin
|
||||
D0 = 'b01;
|
||||
D1 = 'b10;
|
||||
sel = 0;
|
||||
#1 ;
|
||||
if (Q !== D0) begin
|
||||
$display("FAILED -- D0=%b, D1=%b, S=%b, Q=%b", D0, D1, sel, Q);
|
||||
$finish;
|
||||
end
|
||||
|
||||
sel = 1;
|
||||
#1 ;
|
||||
if (Q !== D1) begin
|
||||
$display("FAILED -- D0=%b, D1=%b, S=%b, Q=%b", D0, D1, sel, Q);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
module ivtest
|
||||
(
|
||||
input [3:0] x,
|
||||
input [3:0] y,
|
||||
output [3:0] z
|
||||
);
|
||||
|
||||
assign z = x ^ y;
|
||||
|
||||
endmodule // ivtest
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
module main;
|
||||
|
||||
reg [3:0] x, y;
|
||||
wire [3:0] z;
|
||||
|
||||
ivtest dut (.\x[3] (x[3]), .\x[2] (x[2]), .\x[1] (x[1]), .\x[0] (x[0]),
|
||||
.\y[3] (y[3]), .\y[2] (y[2]), .\y[1] (y[1]), .\y[0] (y[0]),
|
||||
.\z[3] (z[3]), .\z[2] (z[2]), .\z[1] (z[1]), .\z[0] (z[0]));
|
||||
|
||||
integer idx;
|
||||
initial begin
|
||||
for (idx = 0 ; idx[8]==0 ; idx = idx+1) begin
|
||||
x = idx[3:0];
|
||||
y = idx[7:4];
|
||||
#1 /* let devices settle. */ ;
|
||||
if (z !== (x ^ y)) begin
|
||||
$display("FAILED -- x=%b, y=%b, x^y=%b", x, y, z);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end // initial begin
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* Generate a combinational adder of any width. The width parameter can
|
||||
* be any integer value >0. The A and B inputs have WID bits, and the Q
|
||||
* output has WID+1 bits to include the overflow.
|
||||
*/
|
||||
module addN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output wire [WID:0] Q
|
||||
/* */);
|
||||
|
||||
wire [WID-1:0] Cout;
|
||||
|
||||
/* The least significant slice has no Cin */
|
||||
add1 U0 (.A(A[0]), .B(B[0]), .Cin(1'b0), .Q(Q[0]), .Cout(Cout[0]));
|
||||
|
||||
/* Generate all the remaining slices */
|
||||
genvar i;
|
||||
for (i = 1 ; i < WID ; i = i+1) begin : U
|
||||
add1 Un (.A(A[i]), .B(B[i]), .Cin(Cout[i-1]), .Q(Q[i]), .Cout(Cout[i]));
|
||||
end
|
||||
|
||||
assign Q[WID] = Cout[WID-1];
|
||||
|
||||
endmodule // add
|
||||
|
||||
/*
|
||||
* This is a single-bit combinational adder used by the addH module
|
||||
* above.
|
||||
*/
|
||||
module add1(input A, input B, input Cin, output reg Q, output reg Cout);
|
||||
|
||||
always @* begin
|
||||
Q = A ^ B ^ Cin;
|
||||
Cout = A&B | A&Cin | B&Cin;
|
||||
end
|
||||
|
||||
endmodule // hadd
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* This is a post-wynthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
addN usum(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.\Q[4] (Q[4]), .\Q[3] (Q[3]), .\Q[2] (Q[2]), .\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx+bdx)) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module test_logic(input A, B, output reg q_nand, q_nor, q_xnor, q_not);
|
||||
|
||||
always @(A, B) begin
|
||||
q_nand = A ~& B;
|
||||
q_nor = A ~| B;
|
||||
q_xnor = A ~^ B;
|
||||
q_not = ~A;
|
||||
end
|
||||
|
||||
endmodule // test_logic
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
module main;
|
||||
|
||||
reg [2:0] X;
|
||||
wire q_nand, q_nor, q_xnor, q_not;
|
||||
|
||||
test_logic DUT(.A(X[0]), .B(X[1]), .q_nand(q_nand), .q_nor(q_nor),
|
||||
.q_xnor(q_xnor), .q_not(q_not));
|
||||
|
||||
initial begin
|
||||
for (X = 0 ; X < 4 ; X = X+1) begin
|
||||
#1 /* Let gates settle. */;
|
||||
if (q_nand !== (X[0] ~& X[1])) begin
|
||||
$display("FAILED -- q_nand=%b, X=%b", q_nand, X[1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_nor !== (X[0] ~| X[1])) begin
|
||||
$display("FAILED -- q_nor=%b, X=%b", q_nor, X[1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_xnor !== (X[0] ~^ X[1])) begin
|
||||
$display("FAILED -- q_xnor=%b, X=%b", q_xnor, X[1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_not !== (~X[0])) begin
|
||||
$display("FAILED -- q_not=%b, X=%b", q_not, X[0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module addN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output reg [WID:0] Q
|
||||
/* */);
|
||||
|
||||
always @* Q = A + B;
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* This is a post-wynthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
addN usum(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.\Q[4] (Q[4]), .\Q[3] (Q[3]), .\Q[2] (Q[2]), .\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx+bdx)) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module subN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output reg [WID:0] Q
|
||||
/* */);
|
||||
|
||||
always @(A or B) Q = A - B;
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* This is a post-wynthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire [WID:0] Q;
|
||||
|
||||
subN usum(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.\Q[4] (Q[4]), .\Q[3] (Q[3]), .\Q[2] (Q[2]), .\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 if (Q !== (adx[WID-1:0]-bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, Q=%b", A, B, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
module cmpN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output reg QE, QN, QGT, QGE
|
||||
/* */);
|
||||
|
||||
always @(A, B)
|
||||
if (A > B) begin
|
||||
QE = 0;
|
||||
QN = 1;
|
||||
QGT = 1;
|
||||
QGE = 1;
|
||||
end else if (A == B) begin
|
||||
QE = 1;
|
||||
QN = 0;
|
||||
QGT = 0;
|
||||
QGE = 1;
|
||||
end else begin
|
||||
QE = 0;
|
||||
QN = 1;
|
||||
QGT = 0;
|
||||
QGE = 0;
|
||||
end
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
/*
|
||||
* This is a post-synthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire QE, QN, QGT, QGE;
|
||||
|
||||
cmpN ucmp(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.QE(QE), .QN(QN), .QGT(QGT), .QGE(QGE));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 ;
|
||||
if (QE !== (adx[WID-1:0]==bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QE=%b", A, B, QE);
|
||||
$finish;
|
||||
end
|
||||
if (QN !== (adx[WID-1:0]!=bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QN=%b", A, B, QN);
|
||||
$finish;
|
||||
end
|
||||
if (QGT !== (adx[WID-1:0] > bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QGT=%b", A, B, QGT);
|
||||
$finish;
|
||||
end
|
||||
if (QGE !== (adx[WID-1:0] >= bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QGE=%b", A, B, QGE);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module muxN
|
||||
#(parameter WID = 4, parameter SWID = 2)
|
||||
(input wire [WID-1:0] D,
|
||||
input wire [SWID-1:0] S,
|
||||
output reg Q
|
||||
/* */);
|
||||
|
||||
always @* Q = D[S];
|
||||
|
||||
endmodule // add
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
parameter SWID = 2;
|
||||
|
||||
reg [WID-1:0] D;
|
||||
reg [SWID-1:0] S;
|
||||
wire Q;
|
||||
|
||||
muxN dut(.\D[3] (D[3]), .\D[2] (D[2]), .\D[1] (D[1]), .\D[0] (D[0]),
|
||||
.\S[1] (S[1]), .\S[0] (S[0]),
|
||||
.Q(Q));
|
||||
|
||||
integer idx, sdx;
|
||||
initial begin
|
||||
for (idx = 0 ; idx < 50 ; idx += 1) begin
|
||||
D = $random;
|
||||
|
||||
for (sdx = 0 ; sdx < (1<<SWID) ; sdx = sdx+1) begin
|
||||
S = sdx[SWID-1:0];
|
||||
#1 ;
|
||||
if (Q !== D[S]) begin
|
||||
$display("FAILED = D=%b, S=%0d, Q=%b", D, S, Q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end // for (idx = 0 ; idx < 50 ; idx += 1)
|
||||
$display("PASSED");
|
||||
end // initial begin
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
module test_logic
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
output reg q_and, q_or, q_xor, q_nand, q_nor, q_xnor);
|
||||
|
||||
always @(A) begin
|
||||
q_and = &A;
|
||||
q_or = |A;
|
||||
q_xor = ^A;
|
||||
q_nand = ~q_and;
|
||||
q_nor = ~q_or;
|
||||
q_xnor = ~q_xor;
|
||||
end
|
||||
|
||||
endmodule // test_logic
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
module main;
|
||||
|
||||
localparam WID = 4;
|
||||
reg [WID:0] X;
|
||||
wire q_and, q_or, q_xor, q_nand, q_nor, q_xnor;
|
||||
|
||||
test_logic DUT(.\A[3] (X[3]), .\A[2] (X[2]), .\A[1] (X[1]), .\A[0] (X[0]),
|
||||
.q_and(q_and), .q_or(q_or), .q_xor(q_xor),
|
||||
.q_nand(q_nand), .q_nor(q_nor), .q_xnor(q_xnor));
|
||||
|
||||
initial begin
|
||||
for (X = 0 ; X < 16 ; X = X+1) begin
|
||||
#1 /* Let gates settle. */;
|
||||
if (q_and !== & X[WID-1:0]) begin
|
||||
$display("FAILED -- q_and=%b, X=%b", q_and, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_or !== | X[WID-1:0]) begin
|
||||
$display("FAILED -- q_or=%b, X=%b", q_or, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_xor !== ^ X[WID-1:0]) begin
|
||||
$display("FAILED -- q_xor=%b, X=%b", q_xor, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_nand !== ~& X[WID-1:0]) begin
|
||||
$display("FAILED -- q_nand=%b, X=%b", q_nand, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_nor !== ~| X[WID-1:0]) begin
|
||||
$display("FAILED -- q_nor=%b, X=%b", q_nor, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
if (q_xnor !== ~^ X[WID-1:0]) begin
|
||||
$display("FAILED -- q_xnor=%b, X=%b", q_xnor, X[WID-1:0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
module test_mux
|
||||
(input wire [1:0] D0, D1,
|
||||
input wire [1:0] S,
|
||||
output reg [1:0] Q);
|
||||
|
||||
always @(*) begin
|
||||
case (S)
|
||||
2'b00: Q = D0;
|
||||
2'b01: Q = D1;
|
||||
default: Q = 0;
|
||||
endcase // case (S)
|
||||
end
|
||||
|
||||
endmodule // test_mux
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
module main;
|
||||
|
||||
reg [1:0] D0, D1;
|
||||
reg sel;
|
||||
wire [1:0] Q;
|
||||
|
||||
test_mux DUT(.\S[1] (1'b0), .\S[0] (sel),
|
||||
.\D0[1] (D0[1]), .\D0[0] (D0[0]),
|
||||
.\D1[1] (D1[1]), .\D1[0] (D1[0]),
|
||||
.\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
initial begin
|
||||
D0 = 'b01;
|
||||
D1 = 'b10;
|
||||
sel = 0;
|
||||
#1 ;
|
||||
if (Q !== D0) begin
|
||||
$display("FAILED -- D0=%b, D1=%b, S=%b, Q=%b", D0, D1, sel, Q);
|
||||
$finish;
|
||||
end
|
||||
|
||||
sel = 1;
|
||||
#1 ;
|
||||
if (Q !== D1) begin
|
||||
$display("FAILED -- D0=%b, D1=%b, S=%b, Q=%b", D0, D1, sel, Q);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
module cmpN
|
||||
#(parameter WID = 4)
|
||||
(input wire [WID-1:0] A,
|
||||
input wire [WID-1:0] B,
|
||||
output reg QE, QN, QGT, QGE
|
||||
/* */);
|
||||
|
||||
always @(A, B)
|
||||
if (A > B)
|
||||
QGT = 1;
|
||||
else
|
||||
QGT = 0;
|
||||
|
||||
always @(A, B)
|
||||
if (A >= B)
|
||||
QGE = 1;
|
||||
else
|
||||
QGE = 0;
|
||||
|
||||
always @(A, B)
|
||||
if (A == B)
|
||||
QE = 1;
|
||||
else
|
||||
QE = 0;
|
||||
|
||||
always @(A, B)
|
||||
if (A != B)
|
||||
QN = 1;
|
||||
else
|
||||
QN = 0;
|
||||
|
||||
|
||||
/*
|
||||
always @(A, B)
|
||||
if (A > B) begin
|
||||
QE = 0;
|
||||
QN = 1;
|
||||
QGT = 1;
|
||||
QGE = 1;
|
||||
end else if (A == B) begin
|
||||
QE = 1;
|
||||
QN = 0;
|
||||
QGT = 0;
|
||||
QGE = 1;
|
||||
end else begin
|
||||
QE = 0;
|
||||
QN = 1;
|
||||
QGT = 0;
|
||||
QGE = 0;
|
||||
end
|
||||
*/
|
||||
endmodule // add
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
/*
|
||||
* This is a post-synthesis test for the blif01a.v test. Run this
|
||||
* simulation in these steps:
|
||||
*
|
||||
* $ iverilog -tblif -o foo.blif blif01a.v
|
||||
* $ abc
|
||||
* abc 01> read_blif foo.blif
|
||||
* abc 02> write_verilog foo.v
|
||||
* abc 03> quit
|
||||
* $ iverilog -g2009 -o foo.vvp blif02a_tb.v foo.v
|
||||
* $ vvp foo.vvp
|
||||
*/
|
||||
module main;
|
||||
|
||||
parameter WID = 4;
|
||||
reg [WID-1:0] A, B;
|
||||
wire QE, QN, QGT, QGE;
|
||||
|
||||
cmpN ucmp(.\A[3] (A[3]), .\A[2] (A[2]), .\A[1] (A[1]), .\A[0] (A[0]),
|
||||
.\B[3] (B[3]), .\B[2] (B[2]), .\B[1] (B[1]), .\B[0] (B[0]),
|
||||
.QE(QE), .QN(QN), .QGT(QGT), .QGE(QGE));
|
||||
|
||||
int adx;
|
||||
int bdx;
|
||||
initial begin
|
||||
for (bdx = 0 ; bdx[WID]==0 ; bdx = bdx+1) begin
|
||||
for (adx = 0 ; adx[WID]==0 ; adx = adx+1) begin
|
||||
A <= adx[WID-1:0];
|
||||
B <= bdx[WID-1:0];
|
||||
#1 ;
|
||||
if (QE !== (adx[WID-1:0]==bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QE=%b", A, B, QE);
|
||||
$finish;
|
||||
end
|
||||
if (QN !== (adx[WID-1:0]!=bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QN=%b", A, B, QN);
|
||||
$finish;
|
||||
end
|
||||
if (QGT !== (adx[WID-1:0] > bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QGT=%b", A, B, QGT);
|
||||
$finish;
|
||||
end
|
||||
if (QGE !== (adx[WID-1:0] >= bdx[WID-1:0])) begin
|
||||
$display("FAILED -- A=%b, B=%b, QGE=%b", A, B, QGE);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
module test_mux
|
||||
(input wire [1:0] D0, D1,
|
||||
input wire [1:0] S,
|
||||
output reg [1:0] Q);
|
||||
|
||||
always @(*) begin
|
||||
if (S[1]==1'b0)
|
||||
case (S[0])
|
||||
1'b0: Q = D0;
|
||||
1'b1: Q = D1;
|
||||
endcase // case (S[0])
|
||||
else
|
||||
Q = 2'b0;
|
||||
end
|
||||
|
||||
endmodule // test_mux
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
module main;
|
||||
|
||||
reg [1:0] D0, D1;
|
||||
reg sel;
|
||||
wire [1:0] Q;
|
||||
|
||||
test_mux DUT(.\S[1] (1'b0), .\S[0] (sel),
|
||||
.\D0[1] (D0[1]), .\D0[0] (D0[0]),
|
||||
.\D1[1] (D1[1]), .\D1[0] (D1[0]),
|
||||
.\Q[1] (Q[1]), .\Q[0] (Q[0]));
|
||||
|
||||
initial begin
|
||||
D0 = 'b01;
|
||||
D1 = 'b10;
|
||||
sel = 0;
|
||||
#1 ;
|
||||
if (Q !== D0) begin
|
||||
$display("FAILED -- D0=%b, D1=%b, S=%b, Q=%b", D0, D1, sel, Q);
|
||||
$finish;
|
||||
end
|
||||
|
||||
sel = 1;
|
||||
#1 ;
|
||||
if (Q !== D1) begin
|
||||
$display("FAILED -- D0=%b, D1=%b, S=%b, Q=%b", D0, D1, sel, Q);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user