mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-25 07:16:52 +02:00
Compare commits
363
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc7516eab3 | ||
|
|
1a5ae96540 | ||
|
|
1ea8a13bf8 | ||
|
|
490884cf7b | ||
|
|
ca1d7ccffe | ||
|
|
faf9bfe158 | ||
|
|
086ce04cf5 | ||
|
|
7b7231c417 | ||
|
|
d7b919f6d0 | ||
|
|
9b34a96cb9 | ||
|
|
90cf0e5794 | ||
|
|
818379b9bc | ||
|
|
9fbb7f84e6 | ||
|
|
ed7d6c1002 | ||
|
|
a4306dbac1 | ||
|
|
a682e13d82 | ||
|
|
643e0a984e | ||
|
|
63d2059b85 | ||
|
|
d9e09ceb59 | ||
|
|
6d0ab9978f | ||
|
|
e25cdf86ac | ||
|
|
13bff8c50d | ||
|
|
b1b017251a | ||
|
|
e13a52637a | ||
|
|
4803f0d12b | ||
|
|
be44289fc0 | ||
|
|
e682166253 | ||
|
|
e2a1f21896 | ||
|
|
cb73accd84 | ||
|
|
a66361a4f2 | ||
|
|
1159de0482 | ||
|
|
ac5d4114ad | ||
|
|
85f796fda2 | ||
|
|
8612ec5452 | ||
|
|
870a351944 | ||
|
|
434bf0fe46 | ||
|
|
5147105042 | ||
|
|
fc2139f01c | ||
|
|
775904ab0f | ||
|
|
0ae3414ec5 | ||
|
|
f3321126ed | ||
|
|
428f059c58 | ||
|
|
e98bcb61bb | ||
|
|
5facf243cd | ||
|
|
853f119d83 | ||
|
|
3e2196651a | ||
|
|
64b72cf7e1 | ||
|
|
d766e82aa1 | ||
|
|
c35f2f8334 | ||
|
|
afd225a44d | ||
|
|
b36a0a2c54 | ||
|
|
a3728dcf20 | ||
|
|
4cf4cdabcd | ||
|
|
5f906369b5 | ||
|
|
12f4d29df3 | ||
|
|
5e931b7e89 | ||
|
|
11d7cbd3e2 | ||
|
|
7aff1adf99 | ||
|
|
093e7eb2c8 | ||
|
|
82d46a5e1a | ||
|
|
fc976bdb97 | ||
|
|
9f7995f648 | ||
|
|
9bcafe39c6 | ||
|
|
9635f031a1 | ||
|
|
e6be9dec08 | ||
|
|
97c6339241 | ||
|
|
8d2149f5aa | ||
|
|
e8225bd39e | ||
|
|
935ee6137d | ||
|
|
586e415d96 | ||
|
|
637fc40dd9 | ||
|
|
05a52e55e9 | ||
|
|
59c211d20c | ||
|
|
dad223316e | ||
|
|
df597e19cb | ||
|
|
7597270939 | ||
|
|
5509b3c7a5 | ||
|
|
49253c43ba | ||
|
|
311ffb27f2 | ||
|
|
f0fd73e146 | ||
|
|
5858e1bbac | ||
|
|
95044d9ac7 | ||
|
|
c6f934964f | ||
|
|
6f867d6f01 | ||
|
|
e6b57910a4 | ||
|
|
cc9b182eb6 | ||
|
|
d39f692cfd | ||
|
|
b666b9c0bf | ||
|
|
b3c1fa3e85 | ||
|
|
169228ad0f | ||
|
|
356a09d295 | ||
|
|
47c5ce0ab6 | ||
|
|
3c437874e2 | ||
|
|
c28000c55f | ||
|
|
5a0d967682 | ||
|
|
49efe6573c | ||
|
|
ea12c0fe23 | ||
|
|
44dfc41004 | ||
|
|
bdd0657140 | ||
|
|
1d279798d8 | ||
|
|
0e66e9781a | ||
|
|
b23faff27c | ||
|
|
b242663cae | ||
|
|
d39c284055 | ||
|
|
6a73de0c43 | ||
|
|
e0cdd71984 | ||
|
|
81e1735959 | ||
|
|
3fb65eb51a | ||
|
|
3080f5730d | ||
|
|
29ddd5208f | ||
|
|
4a31f36646 | ||
|
|
1f1d47887e | ||
|
|
80403d2ade | ||
|
|
cd3180d1c2 | ||
|
|
68f8007fc4 | ||
|
|
d6ff1946f9 | ||
|
|
4068c172f4 | ||
|
|
9ac9f1c9f2 | ||
|
|
2739f83702 | ||
|
|
7af3280215 | ||
|
|
05d591ccd6 | ||
|
|
fbedf4ae22 | ||
|
|
e6c6f6c81e | ||
|
|
33c651aa00 | ||
|
|
358bb4d5d9 | ||
|
|
d5b41853fd | ||
|
|
0fc10e3e70 | ||
|
|
ab688613cc | ||
|
|
79042e38ad | ||
|
|
ced9759c65 | ||
|
|
8f22998447 | ||
|
|
51d7237d52 | ||
|
|
7aab315ce5 | ||
|
|
bc83d2914a | ||
|
|
bb2e6782fa | ||
|
|
9231ad51a4 | ||
|
|
25458b8cc2 | ||
|
|
515ab40ffe | ||
|
|
ddc204391e | ||
|
|
a33bbecc98 | ||
|
|
61ace52f31 | ||
|
|
71b1546a7d | ||
|
|
578a2543f7 | ||
|
|
a479bd6b16 | ||
|
|
c75498b1d4 | ||
|
|
b6304129fa | ||
|
|
bb444b6178 | ||
|
|
7442c14689 | ||
|
|
0082795967 | ||
|
|
ac4f4cf1a0 | ||
|
|
676d23f973 | ||
|
|
6069cbfc3c | ||
|
|
cfbc90812b | ||
|
|
e530b4e642 | ||
|
|
6a3edc63d5 | ||
|
|
3069b8dd51 | ||
|
|
7db01d8ded | ||
|
|
e4694cb6cb | ||
|
|
08e5aa021a | ||
|
|
4304fd503e | ||
|
|
5438464d67 | ||
|
|
6df2979998 | ||
|
|
9de4ced133 | ||
|
|
45dc13e496 | ||
|
|
9e3f1ef1ff | ||
|
|
1b3e321d35 | ||
|
|
a27274aa04 | ||
|
|
f1be16be7c | ||
|
|
9ac374501c | ||
|
|
250b278d0e | ||
|
|
52275deb0e | ||
|
|
120ad59017 | ||
|
|
2ac8a555e1 | ||
|
|
8d845ae49f | ||
|
|
352175d921 | ||
|
|
e78205eacf | ||
|
|
c6e618350d | ||
|
|
301a7e587b | ||
|
|
3cee5d4567 | ||
|
|
e1ae5020c4 | ||
|
|
22d15f9ca9 | ||
|
|
19d966e235 | ||
|
|
c8fe897446 | ||
|
|
5101b3b64b | ||
|
|
bed5ee4529 | ||
|
|
7c0a191626 | ||
|
|
cfa43c7742 | ||
|
|
a5138e238f | ||
|
|
d352d8ead3 | ||
|
|
02ee3874e7 | ||
|
|
f9fef5d00b | ||
|
|
891399185f | ||
|
|
5dc1396eea | ||
|
|
ccf7c042c9 | ||
|
|
560b9530fd | ||
|
|
b89c059153 | ||
|
|
8326fe843b | ||
|
|
1cbc38100e | ||
|
|
ba31252226 | ||
|
|
008affe557 | ||
|
|
0ca856d4e8 | ||
|
|
2a210dfee1 | ||
|
|
83d721232d | ||
|
|
d5ffb55bfd | ||
|
|
ab9a8ccbf3 | ||
|
|
e6525ec35f | ||
|
|
afaedbd06d | ||
|
|
d4237774a5 | ||
|
|
2f2539e557 | ||
|
|
11a86794d9 | ||
|
|
3b14797075 | ||
|
|
e006f9e132 | ||
|
|
437dc10341 | ||
|
|
102d2d534f | ||
|
|
5e437145bf | ||
|
|
d1dc98b7f7 | ||
|
|
50b45dac7b | ||
|
|
295e4e7dfb | ||
|
|
807ad8002d | ||
|
|
d3229b9068 | ||
|
|
099bb427bc | ||
|
|
d406545331 | ||
|
|
1de3fb1625 | ||
|
|
e33b8b4dde | ||
|
|
9128eb67b9 | ||
|
|
afbda099fb | ||
|
|
4b0d220671 | ||
|
|
a42b056b24 | ||
|
|
1852c5ab9d | ||
|
|
24be13d825 | ||
|
|
bddfcac823 | ||
|
|
ea1c07e234 | ||
|
|
8e0ae733ca | ||
|
|
feb710a186 | ||
|
|
62abb199d7 | ||
|
|
7373bf2224 | ||
|
|
ae629f8c41 | ||
|
|
03e0e96832 | ||
|
|
3c38b2972d | ||
|
|
4f1fc6e302 | ||
|
|
f1436fbe62 | ||
|
|
a79533ddc9 | ||
|
|
d47afb588b | ||
|
|
386774ac19 | ||
|
|
9ca754b6db | ||
|
|
0f0bef32f2 | ||
|
|
cd55f30a27 | ||
|
|
5884879b02 | ||
|
|
a1a4f47894 | ||
|
|
e569e07d4e | ||
|
|
ee840391d6 | ||
|
|
0046e9eca0 | ||
|
|
f51c037432 | ||
|
|
763c6fe3c9 | ||
|
|
49b6ddf93c | ||
|
|
12b4914b63 | ||
|
|
fc0728ab6f | ||
|
|
46c41f9be2 | ||
|
|
cdf18de10e | ||
|
|
19ff6a434b | ||
|
|
5349ca9a55 | ||
|
|
5b7b980ead | ||
|
|
a1c2a8e605 | ||
|
|
8777cd8e7c | ||
|
|
11bb7ac348 | ||
|
|
9de69f2f24 | ||
|
|
dae3410dcd | ||
|
|
1a367c84b6 | ||
|
|
8a854affa6 | ||
|
|
60077f4f06 | ||
|
|
51ce9f1a60 | ||
|
|
48265ecd9b | ||
|
|
abbcea64d0 | ||
|
|
25c3798248 | ||
|
|
90293d8e0a | ||
|
|
621cf37339 | ||
|
|
6d75af86e6 | ||
|
|
5d26f0e28d | ||
|
|
774609fbbb | ||
|
|
9ba7694484 | ||
|
|
870a826225 | ||
|
|
2ecfed0baa | ||
|
|
56e410f386 | ||
|
|
d4dd635bf6 | ||
|
|
c287281bbe | ||
|
|
962330f20a | ||
|
|
777e7e0a3d | ||
|
|
839f9cd7ae | ||
|
|
b8b2f53027 | ||
|
|
9b3bd039bb | ||
|
|
51b9191021 | ||
|
|
756c9ceccf | ||
|
|
8b3667f76e | ||
|
|
a52242745a | ||
|
|
ff5b696569 | ||
|
|
b05a19dffc | ||
|
|
e6b22a2bea | ||
|
|
a02ebc3114 | ||
|
|
0592ba042e | ||
|
|
bcca3cf395 | ||
|
|
01ba41afd8 | ||
|
|
84c592b068 | ||
|
|
bb93a585b6 | ||
|
|
47688d234b | ||
|
|
b3425d6cf3 | ||
|
|
40ae1051d4 | ||
|
|
21c60b38e1 | ||
|
|
78c6b3cad2 | ||
|
|
a04104077f | ||
|
|
0e3a758894 | ||
|
|
d682029240 | ||
|
|
1ffcd40336 | ||
|
|
09439c55ab | ||
|
|
c858dea2d5 | ||
|
|
228a3f123a | ||
|
|
074f7a7a49 | ||
|
|
f642313e1b | ||
|
|
dd9d96eb07 | ||
|
|
35401f0e2c | ||
|
|
b6e16aea6b | ||
|
|
eeaf23041b | ||
|
|
e8096eda80 | ||
|
|
961d6a8f3b | ||
|
|
288ebf011c | ||
|
|
0ae304b6a8 | ||
|
|
5e61bb64b7 | ||
|
|
3f847fd927 | ||
|
|
4a41a53b42 | ||
|
|
a1630e1d30 | ||
|
|
bca84d9dbb | ||
|
|
e61ed48914 | ||
|
|
d29a6d134f | ||
|
|
6310b47538 | ||
|
|
9c75a4b96b | ||
|
|
c57e68292c | ||
|
|
0fecdcbeda | ||
|
|
23ad62f317 | ||
|
|
ac20008606 | ||
|
|
96d181efed | ||
|
|
18bfe7d497 | ||
|
|
86562e60ba | ||
|
|
b400532169 | ||
|
|
6fd10dedb6 | ||
|
|
c8255952a3 | ||
|
|
71c4ea36e8 | ||
|
|
5df179cd5f | ||
|
|
ce5c4ca8ba | ||
|
|
6aa8e49b09 | ||
|
|
f29f4ff4e3 | ||
|
|
3ccc59eaa3 | ||
|
|
0282b8450c | ||
|
|
43841af2f3 | ||
|
|
b2d8d41e3f | ||
|
|
0e38843ae9 | ||
|
|
96472e5537 | ||
|
|
48b0fed29e | ||
|
|
1efa220773 | ||
|
|
2d6622e543 | ||
|
|
edf112b900 | ||
|
|
f0a0ab100f | ||
|
|
c28188618b | ||
|
|
0d7daf5862 | ||
|
|
60ab1daa1f |
@@ -0,0 +1,2 @@
|
||||
# gperf in MSYS chokes on DOS line endings
|
||||
*.gperf text eol=lf
|
||||
@@ -40,7 +40,7 @@ hname_t::hname_t(perm_string text, int num)
|
||||
number_[0] = num;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, vector<int>&nums)
|
||||
hname_t::hname_t(perm_string text, const vector<int>&nums)
|
||||
: name_(text), number_(nums)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class hname_t {
|
||||
hname_t ();
|
||||
explicit hname_t (perm_string text);
|
||||
explicit hname_t (perm_string text, int num);
|
||||
explicit hname_t (perm_string text, std::vector<int>&nums);
|
||||
explicit hname_t (perm_string text, const std::vector<int>&nums);
|
||||
hname_t (const hname_t&that);
|
||||
~hname_t();
|
||||
|
||||
@@ -56,12 +56,12 @@ class hname_t {
|
||||
|
||||
size_t has_numbers() const;
|
||||
int peek_number(size_t idx) const;
|
||||
const std::vector<int>&peek_numbers() const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// If the number is anything other than INT_MIN, then this is
|
||||
// the numeric part of the name. Otherwise, it is not part of
|
||||
// the name at all.
|
||||
// If this vector has size, then the numbers all together make
|
||||
// up part of the hierarchical name.
|
||||
std::vector<int> number_;
|
||||
|
||||
private: // not implemented
|
||||
@@ -82,6 +82,11 @@ inline int hname_t::peek_number(size_t idx) const
|
||||
return number_[idx];
|
||||
}
|
||||
|
||||
inline const std::vector<int>& hname_t::peek_numbers(void) const
|
||||
{
|
||||
return number_;
|
||||
}
|
||||
|
||||
inline size_t hname_t::has_numbers() const
|
||||
{
|
||||
return number_.size();
|
||||
|
||||
+3
-3
@@ -118,8 +118,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
|
||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
|
||||
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
|
||||
PGenerate.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||
Statement.o AStatement.o $M $(FF) $(TT)
|
||||
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
|
||||
PFunction.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
|
||||
|
||||
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
|
||||
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
|
||||
@@ -292,7 +292,7 @@ endif
|
||||
version_tag.h version:
|
||||
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
|
||||
echo "Using git-describe for VERSION_TAG"; \
|
||||
tmp=`$(GIT) --git-dir $(srcdir)/.git describe --always --dirty \
|
||||
tmp=`(cd $(srcdir) && $(GIT) describe --always --dirty) \
|
||||
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
|
||||
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
|
||||
elif test -r $(srcdir)/version_tag.h; then \
|
||||
|
||||
@@ -94,13 +94,15 @@ perm_string Module::get_port_name(unsigned idx) const
|
||||
{
|
||||
|
||||
assert(idx < ports.size());
|
||||
if (ports[idx] == 0) {
|
||||
if (ports[idx] == 0 || ports[idx]->name.str() == 0) {
|
||||
/* It is possible to have undeclared ports. These
|
||||
are ports that are skipped in the declaration,
|
||||
for example like so: module foo(x ,, y); The
|
||||
port between x and y is unnamed and thus
|
||||
inaccessible to binding by name. */
|
||||
return perm_string::literal("");
|
||||
inaccessible to binding by name. Port references
|
||||
that aren't simple or escaped identifiers are
|
||||
also inaccessible to binding by name. */
|
||||
return perm_string::literal("unnamed");
|
||||
}
|
||||
return ports[idx]->name;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_Module_H
|
||||
#define IVL_Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -35,6 +35,7 @@ class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
class PGenerate;
|
||||
class PModport;
|
||||
class PSpecPath;
|
||||
class PTask;
|
||||
class PFunction;
|
||||
@@ -47,6 +48,10 @@ class NetScope;
|
||||
* A module is a named container and scope. A module holds a bunch of
|
||||
* semantic quantities such as wires and gates. The module is
|
||||
* therefore the handle for grasping the described circuit.
|
||||
*
|
||||
* SystemVerilog introduces program blocks and interfaces. These have
|
||||
* much in common with modules, so the Module class is used to represent
|
||||
* these containers as well.
|
||||
*/
|
||||
|
||||
class Module : public PScopeExtra, public LineInfo {
|
||||
@@ -64,7 +69,7 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
|
||||
public:
|
||||
/* The name passed here is the module name, not the instance
|
||||
name. This make must be a permallocated string. */
|
||||
name. This name must be a permallocated string. */
|
||||
explicit Module(LexicalScope*parent, perm_string name);
|
||||
~Module();
|
||||
|
||||
@@ -81,6 +86,11 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
restrictions and slightly modify scheduling semantics. */
|
||||
bool program_block;
|
||||
|
||||
/* This is true if the module represents a interface
|
||||
instead of a module/cell. Interfaces have different
|
||||
content restrictions and some extra allowed items. */
|
||||
bool is_interface;
|
||||
|
||||
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||
UCDriveType uc_drive;
|
||||
|
||||
@@ -125,6 +135,11 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
unless they are instantiated, implicitly or explicitly. */
|
||||
std::map<perm_string,Module*> nested_modules;
|
||||
|
||||
/* An interface can contain one or more named modport lists.
|
||||
The parser will ensure these don't appear in modules or
|
||||
program blocks. */
|
||||
map<perm_string,PModport*> modports;
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
|
||||
// The mod_name() is the name of the module type.
|
||||
|
||||
@@ -436,7 +436,7 @@ class PEIdent : public PExpr {
|
||||
const perm_string&) const;
|
||||
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
||||
NetAssign_*,
|
||||
const perm_string&) const;
|
||||
const name_component_t&) const;
|
||||
bool elaborate_lval_darray_bit_(Design*, NetScope*,
|
||||
NetAssign_*) const;
|
||||
|
||||
@@ -917,8 +917,10 @@ class PECallFunction : public PExpr {
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
@@ -997,6 +999,9 @@ class PECastType : public PExpr {
|
||||
|
||||
void dump(ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PModport.h"
|
||||
|
||||
PModport::PModport(perm_string n)
|
||||
: name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PModport::~PModport()
|
||||
{
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#ifndef IVL_PModport_H
|
||||
#define IVL_PModport_H
|
||||
/*
|
||||
* Copyright (c) 2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "PScope.h"
|
||||
# include "StringHeap.h"
|
||||
# include "netlist.h"
|
||||
# include <vector>
|
||||
|
||||
/*
|
||||
* The PModport class represents a parsed SystemVerilog modport list.
|
||||
*/
|
||||
class PModport : public LineInfo {
|
||||
|
||||
public:
|
||||
// The name is a perm-allocated string. It is the simple name
|
||||
// of the modport, without any scope.
|
||||
explicit PModport(perm_string name);
|
||||
~PModport();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
map<perm_string,simple_port_t> simple_ports;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
private: // not implemented
|
||||
PModport(const PModport&);
|
||||
PModport& operator= (const PModport&);
|
||||
};
|
||||
|
||||
#endif /* IVL_PModport_H */
|
||||
@@ -41,7 +41,7 @@ void PTaskFunc::set_this(class_type_t*type, PWire*this_wire)
|
||||
assert(this_type_ == 0);
|
||||
this_type_ = type;
|
||||
|
||||
// Push a synthethis argument that is the "this" value.
|
||||
// Push a synthesis argument that is the "this" value.
|
||||
if (ports_==0)
|
||||
ports_ = new vector<pform_tf_port_t>;
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -223,8 +223,9 @@ AC_SUBST(strip_dynamic)
|
||||
# -------------
|
||||
AC_DEFUN([AX_C99_STRTOD],
|
||||
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
|
||||
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
|
||||
case "${host}" in
|
||||
*-*-mingw*)
|
||||
*-*-mingw32)
|
||||
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -80,6 +80,10 @@ extern unsigned recursive_mod_limit;
|
||||
/* Implicit definitions of wires. */
|
||||
extern bool warn_implicit;
|
||||
|
||||
/* Warn if dimensions of port or var/net are implicitly taken from
|
||||
the input/output/inout declaration. */
|
||||
extern bool warn_implicit_dimensions;
|
||||
|
||||
/* inherit timescales across files. */
|
||||
extern bool warn_timescale;
|
||||
|
||||
|
||||
Vendored
+324
-447
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -55,6 +55,7 @@
|
||||
# undef HAVE_FSEEKO
|
||||
/* And this is needed by the fst files (copied from GTKWave). */
|
||||
# undef HAVE_LIBPTHREAD
|
||||
# undef HAVE_REALPATH
|
||||
|
||||
/*
|
||||
* Define this if you want to compile vvp with memory freeing and
|
||||
|
||||
Vendored
+225
-101
@@ -1,44 +1,40 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-04-17'
|
||||
timestamp='2015-03-08'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
# the same distribution terms that you use for the rest of that
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
|
||||
# Please send patches to <[email protected]>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
# Please send patches to <[email protected]>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
# that are meaningful with *any* GNU software.
|
||||
@@ -72,8 +68,7 @@ Report bugs and patches to <[email protected]>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -120,13 +115,18 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
android-linux)
|
||||
os=-linux-android
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
@@ -149,10 +149,13 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis | -knuth | -cray)
|
||||
-apple | -axis | -knuth | -cray | -microblaze*)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
@@ -167,10 +170,10 @@ case $os in
|
||||
os=-chorusos
|
||||
basic_machine=$1
|
||||
;;
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
basic_machine=$1
|
||||
;;
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
@@ -215,6 +218,12 @@ case $os in
|
||||
-isc*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-lynx*178)
|
||||
os=-lynxos178
|
||||
;;
|
||||
-lynx*5)
|
||||
os=-lynxos5
|
||||
;;
|
||||
-lynx*)
|
||||
os=-lynxos
|
||||
;;
|
||||
@@ -239,20 +248,28 @@ case $basic_machine in
|
||||
# Some are omitted here because they have special meanings below.
|
||||
1750a | 580 \
|
||||
| a29k \
|
||||
| aarch64 | aarch64_be \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@@ -266,36 +283,55 @@ case $basic_machine in
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa32r6 | mipsisa32r6el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64r6 | mipsisa64r6el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| or32 \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| spu \
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| we32k \
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
# Motorola 68HC11/12.
|
||||
c54x)
|
||||
basic_machine=tic54x-unknown
|
||||
;;
|
||||
c55x)
|
||||
basic_machine=tic55x-unknown
|
||||
;;
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
leon|leon[3-9])
|
||||
basic_machine=sparc-$basic_machine
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
@@ -305,6 +341,21 @@ case $basic_machine in
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
strongarm | thumb | xscale)
|
||||
basic_machine=arm-unknown
|
||||
;;
|
||||
xgate)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
xscaleeb)
|
||||
basic_machine=armeb-unknown
|
||||
;;
|
||||
|
||||
xscaleel)
|
||||
basic_machine=armel-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
@@ -319,25 +370,31 @@ case $basic_machine in
|
||||
# Recognize the basic CPU types with company name.
|
||||
580-* \
|
||||
| a29k-* \
|
||||
| aarch64-* | aarch64_be-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| microblaze-* | microblazeel-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
@@ -351,32 +408,42 @@ case $basic_machine in
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa32r6-* | mipsisa32r6el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64r6-* | mipsisa64r6el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nios-* | nios2-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| or1k*-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-* | z80-*)
|
||||
@@ -401,7 +468,7 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
@@ -451,6 +518,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -467,11 +537,24 @@ case $basic_machine in
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c54x-*)
|
||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c55x-*)
|
||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c6x-*)
|
||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
@@ -503,7 +586,7 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16)
|
||||
cr16 | cr16-*)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
@@ -661,7 +744,6 @@ case $basic_machine in
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i*86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
@@ -700,6 +782,9 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
@@ -719,8 +804,15 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze*)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-mingw64
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
@@ -748,6 +840,10 @@ case $basic_machine in
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
moxiebox)
|
||||
basic_machine=moxie-unknown
|
||||
os=-moxiebox
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
@@ -755,10 +851,18 @@ case $basic_machine in
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
msys)
|
||||
basic_machine=i686-pc
|
||||
os=-msys
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
nacl)
|
||||
basic_machine=le32-unknown
|
||||
os=-nacl
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
@@ -823,6 +927,12 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
neo-tandem)
|
||||
basic_machine=neo-tandem
|
||||
;;
|
||||
nse-tandem)
|
||||
basic_machine=nse-tandem
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@@ -905,9 +1015,10 @@ case $basic_machine in
|
||||
;;
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
@@ -932,7 +1043,11 @@ case $basic_machine in
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
rdos | rdos64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rdos32)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
@@ -1001,6 +1116,9 @@ case $basic_machine in
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
strongarm-* | thumb-*)
|
||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
@@ -1057,20 +1175,8 @@ case $basic_machine in
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
@@ -1140,6 +1246,9 @@ case $basic_machine in
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
xscale-* | xscalee[bl]-*)
|
||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
@@ -1237,9 +1346,12 @@ esac
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
;;
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
@@ -1260,30 +1372,31 @@ case $os in
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -kopensolaris* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -openbsd* | -solidbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1322,7 +1435,7 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
@@ -1371,7 +1484,7 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
@@ -1407,15 +1520,14 @@ case $os in
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1438,10 +1550,10 @@ else
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
@@ -1453,8 +1565,23 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c8051-*)
|
||||
os=-elf
|
||||
;;
|
||||
hexagon-*)
|
||||
os=-elf
|
||||
;;
|
||||
tic54x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic55x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic6x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
@@ -1474,14 +1601,11 @@ case $basic_machine in
|
||||
;;
|
||||
m68000-sun)
|
||||
os=-sunos3
|
||||
# This also exists in the configure program, but was not the
|
||||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
@@ -1508,7 +1632,7 @@ case $basic_machine in
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
@@ -1613,7 +1737,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
|
||||
+8
-1
@@ -82,7 +82,7 @@ CFLAGS="$iverilog_temp_cflags"
|
||||
|
||||
AC_SUBST(DEPENDENCY_FLAG, [-MD])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CC, [""])
|
||||
AC_SUBST(WARNING_FLAGS_CC, ["-Wstrict-prototypes"])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, [""])
|
||||
fi
|
||||
|
||||
@@ -223,6 +223,10 @@ case "${host}" in
|
||||
CPPFLAGS="-mieee $CPPFLAGS"
|
||||
CFLAGS="-mieee $CFLAGS"
|
||||
;;
|
||||
*-*-mingw*)
|
||||
CXXFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CXXFLAGS"
|
||||
CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CFLAGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Do some more operating system specific setup. We put the file64_support
|
||||
@@ -238,6 +242,9 @@ case "${host}" in
|
||||
esac
|
||||
AC_SUBST(file64_support)
|
||||
|
||||
# fstapi.c (from GTKWave) needs this define.
|
||||
AC_CHECK_FUNCS(realpath)
|
||||
|
||||
# Check that these functions exist. They are mostly C99
|
||||
# functions that older compilers may not yet support.
|
||||
AC_CHECK_FUNCS(fopen64)
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
// These are correct and are used to find the base (zero) pin.
|
||||
thisSubtraction:netlist.h:4938
|
||||
thisSubtraction:netlist.h:4947
|
||||
thisSubtraction:netlist.h:4976
|
||||
thisSubtraction:netlist.h:4985
|
||||
|
||||
+9
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -677,8 +677,12 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
<< " scope=" << scope_path(scope());
|
||||
if (negedge_)
|
||||
o << " negedge";
|
||||
else
|
||||
o << " posedge";
|
||||
o << " aset_value=" << aset_value_ << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -1375,6 +1379,7 @@ void NetScope::dump(ostream&o) const
|
||||
if (is_cell()) o << " (cell)";
|
||||
if (nested_module()) o << " (nested)";
|
||||
if (program_block()) o << " (program)";
|
||||
if (is_interface()) o << " (interface)";
|
||||
o << " " << children_.size() << " children, "
|
||||
<< classes_.size() << " classes" << endl;
|
||||
|
||||
@@ -1889,7 +1894,7 @@ void Design::dump(ostream&o) const
|
||||
cur->second->dump(o);
|
||||
}
|
||||
|
||||
o << "$ROOT CLASSESS:" << endl;
|
||||
o << "$ROOT CLASSES:" << endl;
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
cur->second->dump_scope(o);
|
||||
|
||||
@@ -49,6 +49,7 @@ endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o res.o
|
||||
@@ -80,11 +81,12 @@ config.h: $(srcdir)/config.h.in Makefile
|
||||
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);g' \
|
||||
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
|
||||
-e 's;@IVLCXXFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@SHARED@;@shared@;' $< > $@
|
||||
|
||||
# Windows specific...
|
||||
res.rc: $(srcdir)/res.rc.in ../version.exe
|
||||
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%m,%n,0'`';' \
|
||||
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%n,0,0'`';' \
|
||||
$(srcdir)/res.rc.in > $@
|
||||
|
||||
res.o: res.rc
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define IVERILOG_VPI_CC "@IVLCC@"
|
||||
#define IVERILOG_VPI_CXX "@IVLCXX@"
|
||||
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
|
||||
#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@"
|
||||
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
|
||||
#define IVERILOG_SUFFIX "@SUFFIX@"
|
||||
|
||||
+169
-164
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Gus Baldauf ([email protected])
|
||||
* Copyright (c) 2015 Martin Whitaker
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -20,7 +21,7 @@
|
||||
/*
|
||||
* iverilog-vpi.c
|
||||
*
|
||||
* this program provides the functionality of iverilog-vpi.sh under Win32
|
||||
* this program provides the functionality of iverilog-vpi.sh under Windows
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static void setup_ivl_environment();
|
||||
static void setup_ivl_environment(void);
|
||||
static void assign(char **ptr, char *str);
|
||||
|
||||
/* The compile options: compiler, flags, etc. are in here */
|
||||
@@ -43,16 +44,17 @@ static void assign(char **ptr, char *str);
|
||||
static struct global_strings {
|
||||
char *pCCSRC; /* list of C source files (*.c) */
|
||||
char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pMINGW; /* path to MinGW directory */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCFLAGS; /* CFLAGS option */
|
||||
char *pLDLIBS; /* LDLIBS option */
|
||||
char *pNewPath; /* new PATH environment variable setting */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCCFLAGS; /* compiler flags for compiling C source files */
|
||||
char *pCXFLAGS; /* compiler flags for compiling C++ source files */
|
||||
char *pLDLIBS; /* linker flags for final linking stage */
|
||||
char *pCCNAME; /* base name of compiler */
|
||||
char *pLD; /* what to use for a linker */
|
||||
} gstr;
|
||||
|
||||
@@ -75,21 +77,21 @@ static void myExit(int exitVal)
|
||||
deInitDynString(gstr.pOUT);
|
||||
deInitDynString(gstr.pMINGW);
|
||||
deInitDynString(gstr.pIVL);
|
||||
deInitDynString(gstr.pCFLAGS);
|
||||
deInitDynString(gstr.pCCFLAGS);
|
||||
deInitDynString(gstr.pCXFLAGS);
|
||||
deInitDynString(gstr.pLDLIBS);
|
||||
deInitDynString(gstr.pNewPath);
|
||||
free(gstr.pLD);
|
||||
deInitDynString(gstr.pCCNAME);
|
||||
deInitDynString(gstr.pLD);
|
||||
|
||||
exit(exitVal);
|
||||
}
|
||||
|
||||
/* display usage summary and exit */
|
||||
|
||||
static void usage()
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
|
||||
fprintf(stderr, "usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n");
|
||||
fprintf(stderr, " or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ static void initDynString(char **str)
|
||||
*str = (char *) malloc(1);
|
||||
|
||||
if (!*str) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
|
||||
@@ -107,8 +109,10 @@ static void initDynString(char **str)
|
||||
|
||||
/* initialize dynamic memory buffers */
|
||||
|
||||
static void init()
|
||||
static void init(void)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
initDynString(&gstr.pCCSRC);
|
||||
initDynString(&gstr.pCXSRC);
|
||||
initDynString(&gstr.pOBJ);
|
||||
@@ -118,9 +122,17 @@ static void init()
|
||||
initDynString(&gstr.pOUT);
|
||||
initDynString(&gstr.pMINGW);
|
||||
initDynString(&gstr.pIVL);
|
||||
initDynString(&gstr.pCFLAGS);
|
||||
initDynString(&gstr.pCCFLAGS);
|
||||
initDynString(&gstr.pCXFLAGS);
|
||||
initDynString(&gstr.pLDLIBS);
|
||||
initDynString(&gstr.pNewPath);
|
||||
initDynString(&gstr.pCCNAME);
|
||||
initDynString(&gstr.pLD);
|
||||
|
||||
/* Get the base name of the C compiler. */
|
||||
assign(&gstr.pCCNAME, IVERILOG_VPI_CC);
|
||||
ptr = strchr(gstr.pCCNAME, ' ');
|
||||
if (ptr != NULL) *ptr = '\0';
|
||||
|
||||
/* By default use the C compiler to link the programs. */
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CC);
|
||||
}
|
||||
@@ -136,7 +148,7 @@ static int endsIn (char *end, char *str)
|
||||
|
||||
ext = str + (strlen(str) - strlen(end));
|
||||
|
||||
return stricmp(end,ext) ? 0 : 1;
|
||||
return stricmp(end, ext) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* return true if "str" begins with "prefix", case insensitive */
|
||||
@@ -146,35 +158,35 @@ static int startsWith (char *prefix, char *str)
|
||||
if (strlen(prefix) >= strlen(str))
|
||||
return 0;
|
||||
|
||||
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
|
||||
return strnicmp(prefix, str, strlen(prefix)) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "app" */
|
||||
|
||||
static void appendn (char **ptr, char *app, int count)
|
||||
static void appendn (char **ptr, char *app, size_t count)
|
||||
{
|
||||
char *nptr = (char *) realloc(*ptr, strlen(*ptr) +
|
||||
(count?count:strlen(app)) + 1);
|
||||
(count ? count : strlen(app)) + 1);
|
||||
|
||||
if (nptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
free(*ptr);
|
||||
myExit(4);
|
||||
}
|
||||
*ptr = nptr;
|
||||
|
||||
if (count)
|
||||
strncat(*ptr,app,count);
|
||||
strncat(*ptr, app, count);
|
||||
else
|
||||
strcat(*ptr,app);
|
||||
strcat(*ptr, app);
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
|
||||
static void append (char **ptr, char *app)
|
||||
{
|
||||
appendn(ptr,app,0);
|
||||
appendn(ptr, app, 0);
|
||||
}
|
||||
|
||||
/* if the string does not end with a backslash, add one */
|
||||
@@ -182,36 +194,36 @@ static void append (char **ptr, char *app)
|
||||
static void appendBackSlash(char **str)
|
||||
{
|
||||
if ((*str)[strlen(*str)-1] != '\\')
|
||||
append(str,"\\");
|
||||
append(str, "\\");
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "str" */
|
||||
|
||||
static void assignn (char **ptr, char *str, int count)
|
||||
static void assignn (char **ptr, char *str, size_t count)
|
||||
{
|
||||
char *nptr = (char *) realloc(*ptr, (count?count:strlen(str)) + 1);
|
||||
char *nptr = (char *) realloc(*ptr, (count ? count : strlen(str)) + 1);
|
||||
|
||||
if (nptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
free(*ptr);
|
||||
myExit(4);
|
||||
}
|
||||
*ptr = nptr;
|
||||
|
||||
if (count) {
|
||||
strncpy(*ptr,str,count);
|
||||
strncpy(*ptr, str, count);
|
||||
(*ptr)[count] = 0;
|
||||
}
|
||||
else
|
||||
strcpy(*ptr,str);
|
||||
strcpy(*ptr, str);
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
|
||||
static void assign (char **ptr, char *str)
|
||||
{
|
||||
assignn(ptr,str,0);
|
||||
assignn(ptr, str, 0);
|
||||
}
|
||||
|
||||
/* get a copy of a Icarus Verilog registry string key */
|
||||
@@ -223,11 +235,11 @@ static int GetRegistryKey(char *key, char **value)
|
||||
char *regKeyBuffer;
|
||||
DWORD regKeyType, regKeySize;
|
||||
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, KEY_QUERY_VALUE, &hkKey);
|
||||
if (lrv != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,NULL,®KeySize);
|
||||
lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType, NULL, ®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
return 0;
|
||||
@@ -236,7 +248,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
regKeyBuffer = (char *) malloc(regKeySize+1);
|
||||
if (!regKeyBuffer) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
|
||||
@@ -252,7 +264,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
assign(value,regKeyBuffer);
|
||||
assign(value, regKeyBuffer);
|
||||
free(regKeyBuffer);
|
||||
|
||||
return 1;
|
||||
@@ -262,27 +274,30 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
static void SetRegistryKey(char *key, char *value)
|
||||
{
|
||||
long lrv;
|
||||
HKEY hkKey;
|
||||
DWORD res;
|
||||
|
||||
if (RegCreateKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"Software\\Icarus Verilog",
|
||||
0,
|
||||
"",
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,NULL,
|
||||
&hkKey,
|
||||
&res) != ERROR_SUCCESS)
|
||||
return;
|
||||
lrv = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, "",
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, &res);
|
||||
if (lrv != ERROR_SUCCESS) {
|
||||
char message[1024];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lrv, LANG_USER_DEFAULT,
|
||||
message, sizeof(message), NULL);
|
||||
fprintf(stderr, "error: couldn't write to registry - %s\n", message);
|
||||
if (lrv == ERROR_ACCESS_DENIED) {
|
||||
fprintf(stderr, " try running as administrator\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* This needs an unsigned char *, but for MinGW the char is signed. */
|
||||
RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value,
|
||||
strlen(value)+1);
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
printf("info: storing %s in Windows' registry entry\n",value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
|
||||
printf("info: storing %s in Windows' registry entry\n", value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n", key);
|
||||
}
|
||||
|
||||
/* parse the command line, assign results to global variable strings */
|
||||
@@ -299,7 +314,6 @@ static int parse(int argc, char *argv[])
|
||||
char lib_option[] = "-l";
|
||||
char inc_option[] = "-I";
|
||||
char mingw_option[] = "-mingw=";
|
||||
char ivl_option[] = "-ivl=";
|
||||
char def_option[] = "-D";
|
||||
|
||||
if (argc == 1) return 0;
|
||||
@@ -339,7 +353,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for compiled object files */
|
||||
else if (endsIn(dot_o_ext, argv[idx])) {
|
||||
++srcFileCnt;
|
||||
append(&gstr.pOBJ," ");
|
||||
append(&gstr.pOBJ, " ");
|
||||
append(&gstr.pOBJ, argv[idx]);
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT, argv[idx],
|
||||
@@ -349,10 +363,6 @@ static int parse(int argc, char *argv[])
|
||||
else if (startsWith(mingw_option, argv[idx]))
|
||||
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
|
||||
strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
/* Check for the -ivl option */
|
||||
else if (startsWith(ivl_option, argv[idx]))
|
||||
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
|
||||
strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
/* Check for the --name option */
|
||||
else if (startsWith(name_option, argv[idx])) {
|
||||
assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1,
|
||||
@@ -376,7 +386,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --cflags option */
|
||||
else if (stricmp("--cflags", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\n", gstr.pCFLAGS);
|
||||
printf("%s\n", gstr.pCCFLAGS);
|
||||
myExit(0);
|
||||
}
|
||||
/* Check for the --ldflags option */
|
||||
@@ -393,7 +403,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --install-dir option */
|
||||
else if (stricmp("--install-dir", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
|
||||
printf("%s\\lib\\ivl" IVERILOG_SUFFIX "\\.\n", gstr.pIVL);
|
||||
myExit(0);
|
||||
}
|
||||
/* This is different than iverilog-vpi.sh, we don't
|
||||
@@ -402,15 +412,16 @@ static int parse(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* In case there is a --name without source/object files */
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT,"");
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT, "");
|
||||
|
||||
/* Normally it's an error if there are no source or object files */
|
||||
/* Unless we are setting the IVL or MinGW registry entries */
|
||||
if (!*gstr.pOUT) {
|
||||
if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
|
||||
} else
|
||||
if (*gstr.pOUT) {
|
||||
/* We have a valid result file so add the .vpi extension */
|
||||
append(&gstr.pOUT, ".vpi");
|
||||
} else {
|
||||
/* Unless we are setting the MinGW registry entry, it's
|
||||
an error if there are no source or object files */
|
||||
if (!*gstr.pMINGW) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -421,58 +432,27 @@ static void checkMingwDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path, *comp, *cp;
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\");
|
||||
/* Get just the compiler name (the first word) */
|
||||
comp = strdup(IVERILOG_VPI_CC);
|
||||
cp = strchr(comp, ' ');
|
||||
if (cp != NULL) *cp = '\0';
|
||||
append(&path, comp);
|
||||
append(&path,".exe");
|
||||
free(comp);
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
|
||||
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
/* do minimal check that the Icarus Verilog root directory looks valid */
|
||||
|
||||
static void checkIvlDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path;
|
||||
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
assign(&path, gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
|
||||
append(&path, "bin\\");
|
||||
append(&path, gstr.pCCNAME);
|
||||
append(&path, ".exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
|
||||
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
|
||||
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
fprintf(stderr, "error: %s\n", root);
|
||||
fprintf(stderr, " does not appear to be the valid root directory of\n");
|
||||
fprintf(stderr, " MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr, " point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr, " shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr, " For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr, " -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,68 +460,98 @@ static void checkIvlDir(char *root)
|
||||
|
||||
#define IVL_REGKEY_MINGW "MingwDir"
|
||||
|
||||
static void setup_mingw_environment()
|
||||
static void setup_mingw_environment(void)
|
||||
{
|
||||
char *pOldPATH = getenv("PATH"); /* get current path */
|
||||
char buffer[1]; /* doesn't matter how big this is, as we don't use the result */
|
||||
char *path;
|
||||
|
||||
if (*gstr.pMINGW) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
|
||||
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
|
||||
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr," a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
if (!*gstr.pOUT) SetRegistryKey(IVL_REGKEY_MINGW, gstr.pMINGW);
|
||||
|
||||
} else if (GetRegistryKey(IVL_REGKEY_MINGW, &gstr.pMINGW)) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
} else if (SearchPath(NULL, gstr.pCCNAME, ".exe", sizeof(buffer), buffer, NULL)) {
|
||||
return;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "error: cannot locate the MinGW C compiler - either add its location\n");
|
||||
fprintf(stderr, " to the PATH environment variable or use the -mingw option of\n");
|
||||
fprintf(stderr, " iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr, " a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr, " -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr, " something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
|
||||
/* Create new path with MinGW in it */
|
||||
assign(&gstr.pNewPath,"PATH=");
|
||||
append(&gstr.pNewPath,gstr.pMINGW);
|
||||
appendBackSlash(&gstr.pNewPath);
|
||||
append(&gstr.pNewPath, "\\");
|
||||
append(&gstr.pNewPath,"bin;");
|
||||
append(&gstr.pNewPath,pOldPATH);
|
||||
initDynString(&path);
|
||||
assign(&path, "PATH=");
|
||||
append(&path, gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path, "bin;");
|
||||
append(&path, getenv("PATH"));
|
||||
|
||||
/* Place new path in environment */
|
||||
_putenv(gstr.pNewPath);
|
||||
_putenv(path);
|
||||
deInitDynString(path);
|
||||
}
|
||||
|
||||
/* see if we can find iverilog root */
|
||||
/* find the iverilog root and initialise the compiler options */
|
||||
|
||||
#define IVL_REGKEY_IVL "InstallDir"
|
||||
|
||||
static void setup_ivl_environment()
|
||||
static void setup_ivl_environment(void)
|
||||
{
|
||||
if (*gstr.pIVL) {
|
||||
checkIvlDir(gstr.pIVL);
|
||||
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
|
||||
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
|
||||
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," For a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
|
||||
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
}
|
||||
char path[4096];
|
||||
char *ptr;
|
||||
|
||||
/* Build up the CFLAGS option string */
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I\"");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX);
|
||||
/* Extract the Icarus Verilog root directory from the path to the
|
||||
command. The command path will look something like this:
|
||||
|
||||
C:\iverilog\bin\iverilog-vpi.exe
|
||||
|
||||
The corresponding root directory is
|
||||
|
||||
C:\iverilog
|
||||
|
||||
so we chop off the file name and the last directory. */
|
||||
GetModuleFileName(NULL, path, sizeof(path));
|
||||
ptr = strrchr(path, '\\');
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "error: couldn't find start of program name in command path '%s'\n", path);
|
||||
myExit(6);
|
||||
}
|
||||
*ptr = 0;
|
||||
ptr = strrchr(path, '\\');
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "error: couldn't find start of bin directory in command path '%s'\n", path);
|
||||
myExit(6);
|
||||
}
|
||||
*ptr = 0;
|
||||
assign(&gstr.pIVL, path);
|
||||
|
||||
/* Build up the CCFLAGS option string */
|
||||
assign(&gstr.pCCFLAGS, IVERILOG_VPI_CFLAGS " -I\"");
|
||||
append(&gstr.pCCFLAGS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCCFLAGS);
|
||||
append(&gstr.pCCFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the CXFLAGS option string */
|
||||
assign(&gstr.pCXFLAGS, IVERILOG_VPI_CXXFLAGS " -I\"");
|
||||
append(&gstr.pCXFLAGS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCXFLAGS);
|
||||
append(&gstr.pCXFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the LDFLAGS option string */
|
||||
assign(&gstr.pLDLIBS,"-L\"");
|
||||
append(&gstr.pLDLIBS,gstr.pIVL);
|
||||
assign(&gstr.pLDLIBS, "-L\"");
|
||||
append(&gstr.pLDLIBS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pLDLIBS);
|
||||
append(&gstr.pLDLIBS,"\\lib\" " IVERILOG_VPI_LDLIBS);
|
||||
append(&gstr.pLDLIBS, "lib\" " IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
|
||||
/* compile source modules */
|
||||
|
||||
static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
|
||||
static void compile(char *pSource, char *pFlags, char **pObject, int *compile_errors, char *compiler)
|
||||
{
|
||||
char *ptr1 = pSource;
|
||||
char *ptr2 = strchr(ptr1, ' ');
|
||||
@@ -568,7 +578,7 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pDEFS);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pCFLAGS);
|
||||
append(&buf, pFlags);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pINCS);
|
||||
append(&buf, " ");
|
||||
@@ -593,27 +603,22 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
|
||||
/* using the global strings, compile and link */
|
||||
|
||||
static void compile_and_link()
|
||||
static void compile_and_link(void)
|
||||
{
|
||||
char *buf=0;
|
||||
int iRet, compile_errors = 0;
|
||||
|
||||
/* To make the output match iverilog-vpi.sh do not print out the
|
||||
* root directories */
|
||||
|
||||
// printf("MinGW root directory: %s.\n", gstr.pMINGW);
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
// printf("Icarus Verilog root directory: %s.\n", gstr.pIVL);
|
||||
checkIvlDir(gstr.pIVL);
|
||||
|
||||
/* compile the C source files (*.c) */
|
||||
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
compile(gstr.pCCSRC, gstr.pCCFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
/* compile the C++ source files (*.cc, *.cpp) */
|
||||
compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
compile(gstr.pCXSRC, gstr.pCXFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
|
||||
if (compile_errors) {
|
||||
fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
fprintf(stderr, "iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
compile_errors);
|
||||
myExit(2);
|
||||
}
|
||||
@@ -644,7 +649,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
init();
|
||||
|
||||
if (!parse(argc,argv)) usage();
|
||||
if (!parse(argc, argv)) usage();
|
||||
|
||||
setup_mingw_environment();
|
||||
setup_ivl_environment();
|
||||
|
||||
+17
-6
@@ -1,4 +1,4 @@
|
||||
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog 1 "Aug 7th, 2015" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
@@ -30,7 +30,7 @@ different set of programs. The path given is used to locate
|
||||
\fIivlpp\fP, \fIivl\fP, code generators and the VPI modules.
|
||||
.TP 8
|
||||
.B -c\fIfile\fP -f\fIfile\fP
|
||||
These flags specifies an input file that contains a list of Verilog
|
||||
These flags specify an input file that contains a list of Verilog
|
||||
source files. This is similar to the \fIcommand file\fP of other
|
||||
Verilog simulators, in that it is a file that contains the file names
|
||||
instead of taking them on the command line. See \fBCommand Files\fP below.
|
||||
@@ -213,6 +213,12 @@ a reference to a key temporary file that passes information to the
|
||||
compiler proper. To keep that file from being deleted at the end
|
||||
of the process, provide a file name of your own in the environment
|
||||
variable \fBIVERILOG_ICONFIG\fP.
|
||||
|
||||
If the selected target is \fIvvp\fP, the \fB\-v\fP switch is appended
|
||||
to the shebang line in the compiler output file, so directly executing
|
||||
the compiler output file will turn on verbose messages in \fIvvp\fP.
|
||||
This extra verbosity can be avoided by using the \fIvvp\fP command to
|
||||
indirectly execute the compiler output file.
|
||||
.TP 8
|
||||
.B -V
|
||||
Print the version of the compiler, and exit.
|
||||
@@ -286,8 +292,13 @@ after a \fB\-Wall\fP argument to suppress isolated warning types.
|
||||
|
||||
.TP 8
|
||||
.B all
|
||||
This enables the implicit, portbind, select\-range, timescale, and
|
||||
sensitivity\-entire\-array warning categories.
|
||||
This enables the anachronisms, implicit, portbind, select\-range,
|
||||
timescale, and sensitivity\-entire\-array warning categories.
|
||||
|
||||
.TP 8
|
||||
.B anachronisms
|
||||
This enables warnings for use of features that have been deprecated
|
||||
or removed in the selected generation of the Verilog language.
|
||||
|
||||
.TP 8
|
||||
.B implicit
|
||||
@@ -514,14 +525,14 @@ Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
.BR "<http://iverilog.icarus.com/>"
|
||||
|
||||
Tips on using, debugging, and developing the compiler can be found at
|
||||
.BR "<http://iverilog.wikia.com/>"
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2014 Stephen Williams
|
||||
Copyright \(co 2002\-2015 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+15
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -496,6 +496,7 @@ static void process_warning_switch(const char*name)
|
||||
if (strcmp(name,"all") == 0) {
|
||||
process_warning_switch("anachronisms");
|
||||
process_warning_switch("implicit");
|
||||
process_warning_switch("implicit-dimensions");
|
||||
process_warning_switch("portbind");
|
||||
process_warning_switch("select-range");
|
||||
process_warning_switch("timescale");
|
||||
@@ -506,6 +507,9 @@ static void process_warning_switch(const char*name)
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
} else if (strcmp(name,"implicit-dimensions") == 0) {
|
||||
if (! strchr(warning_flags, 'd'))
|
||||
strcat(warning_flags, "d");
|
||||
} else if (strcmp(name,"portbind") == 0) {
|
||||
if (! strchr(warning_flags, 'p'))
|
||||
strcat(warning_flags, "p");
|
||||
@@ -538,6 +542,12 @@ static void process_warning_switch(const char*name)
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-implicit-dimensions") == 0) {
|
||||
char*cp = strchr(warning_flags, 'd');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-portbind") == 0) {
|
||||
char*cp = strchr(warning_flags, 'p');
|
||||
if (cp) while (*cp) {
|
||||
@@ -568,6 +578,9 @@ static void process_warning_switch(const char*name)
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Ignoring unknown warning class "
|
||||
"%s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,19 +1057,10 @@ int main(int argc, char **argv)
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2013 Stephen Williams\n\n");
|
||||
printf("Copyright 1998-2015 Stephen Williams\n\n");
|
||||
puts(NOTICE);
|
||||
}
|
||||
|
||||
if (synth_flag) {
|
||||
fprintf(stderr, "Warning: Synthesis is not currently being "
|
||||
"maintained and may not\n");
|
||||
fprintf(stderr, " function correctly. V0.8 was the "
|
||||
"last release branch to\n");
|
||||
fprintf(stderr, " have active synthesis development "
|
||||
"and support!\n");
|
||||
}
|
||||
|
||||
/* Make a common conf file path to reflect the target. */
|
||||
snprintf(iconfig_common_path, sizeof iconfig_common_path, "%s%c%s%s.conf",
|
||||
base, sep, targ, synth_flag? "-s" : "");
|
||||
|
||||
+117
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -657,10 +657,13 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
lp->expr_type() == IVL_VT_STRING ||
|
||||
rp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_STRING) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< " operator may not have REAL operands." << endl;
|
||||
<< " operator may not have REAL or STRING operands."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -785,8 +788,11 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
right_ = tmp;
|
||||
}
|
||||
NetEConst*rc = dynamic_cast<NetEConst*> (rp);
|
||||
if (rc && (r_width < sizeof(long)*8))
|
||||
r_val = rc->value().as_long();
|
||||
// Adjust the expression width that can be converter depending
|
||||
// on if the R-value is signed or not.
|
||||
unsigned c_width = sizeof(long)*8;
|
||||
if (! right_->has_sign()) c_width -= 1;
|
||||
if (rc && (r_width <= c_width)) r_val = rc->value().as_long();
|
||||
|
||||
if (debug_elaborate && rc) {
|
||||
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
|
||||
@@ -1072,7 +1078,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
if (name=="$ivlh_to_unsigned") {
|
||||
ivl_assert(*this, parms_.size() == 2);
|
||||
// The Icarus Verilog specific $ivl_unsigned() system
|
||||
// The Icarus Verilog specific $ivlh_to_unsigned() system
|
||||
// task takes a second argument which is the output
|
||||
// size. This can be an arbitrary constant function.
|
||||
PExpr*pexpr = parms_[1];
|
||||
@@ -1094,6 +1100,11 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
||||
bool rc = eval_as_long(value, nexpr);
|
||||
ivl_assert(*this, rc && value>=0);
|
||||
|
||||
// The argument type/width is self-determined and doesn't
|
||||
// affect the result type/width.
|
||||
width_mode_t arg_mode = SIZED;
|
||||
parms_[0]->test_width(des, scope, arg_mode);
|
||||
|
||||
expr_width_ = value;
|
||||
signed_flag_= false;
|
||||
return expr_width_;
|
||||
@@ -1324,7 +1335,7 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
// Look fonr built in string attributes.
|
||||
// Look for built in string attributes.
|
||||
if (net->data_type()==IVL_VT_STRING) {
|
||||
|
||||
if (method_name == "len") {
|
||||
@@ -1407,7 +1418,7 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
|
||||
const. This is a more efficient result. */
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
tmp->cast_signed(signed_flag_);
|
||||
if (wid > tmp->expr_width()) {
|
||||
if (wid != tmp->expr_width()) {
|
||||
tmp = new NetEConst(verinum(tmp->value(), wid));
|
||||
tmp->set_line(*this);
|
||||
delete expr;
|
||||
@@ -1443,7 +1454,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
ivl_assert(*this, expr);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr->expr_width(), flags);
|
||||
return cast_to_width_(sub, expr_wid);
|
||||
}
|
||||
|
||||
@@ -1586,7 +1597,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_fileline() << ": error: The function " << name
|
||||
<< " has been called with empty parameters." << endl;
|
||||
<< " has been called with missing/empty parameters." << endl;
|
||||
cerr << get_fileline() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
des->errors += 1;
|
||||
@@ -2178,6 +2189,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const
|
||||
{
|
||||
const netdarray_t*darray = dynamic_cast<const netdarray_t*>(type);
|
||||
assert(darray);
|
||||
return elaborate_expr(des, scope, darray->element_type()->packed_width(), flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
@@ -2259,6 +2278,9 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
|
||||
func->set_line(*this);
|
||||
|
||||
if(res->darray_type())
|
||||
return func;
|
||||
|
||||
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
@@ -2291,6 +2313,21 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||
const unsigned parm_count = parms.size() - parm_off;
|
||||
const unsigned actual_count = parms_.size();
|
||||
|
||||
/* The parser can't distinguish between a function call with
|
||||
no arguments and a function call with one empty argument,
|
||||
and always supplies one empty argument. Handle the no
|
||||
argument case here. */
|
||||
if ((parm_count == 0) && (actual_count == 1) && (parms_[0] == 0))
|
||||
return 0;
|
||||
|
||||
if (actual_count > parm_count) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Too many arguments (" << actual_count
|
||||
<< ", expecting " << parm_count << ")"
|
||||
<< " in call to function." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
unsigned pidx = idx + parm_off;
|
||||
PExpr*tmp = (idx < actual_count) ? parms_[idx] : 0;
|
||||
@@ -2321,7 +2358,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||
} else if (def->port_defe(pidx)) {
|
||||
if (! gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<<"Found (and using) default function argument "
|
||||
<< "Found (and using) default function argument "
|
||||
<< "requires SystemVerilog." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
@@ -2335,7 +2372,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_fileline() << ": error: The function " << path_
|
||||
<< " has been called with empty parameters." << endl;
|
||||
<< " has been called with missing/empty parameters." << endl;
|
||||
cerr << get_fileline() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
parm_errors += 1;
|
||||
@@ -2522,11 +2559,44 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
||||
expr_width_ = t->packed_width();
|
||||
}
|
||||
|
||||
signed_flag_= t->get_signed();
|
||||
signed_flag_ = t->get_signed();
|
||||
min_width_ = expr_width_;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned) const
|
||||
{
|
||||
const netdarray_t*darray = NULL;
|
||||
const netvector_t*vector = NULL;
|
||||
|
||||
// Casting array of vectors to dynamic array type
|
||||
if((darray = dynamic_cast<const netdarray_t*>(type)) &&
|
||||
(vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
unsigned use_wid = base_->test_width(des, scope, mode);
|
||||
NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
|
||||
|
||||
assert(vector->packed_width() > 0);
|
||||
assert(base->expr_width() > 0);
|
||||
|
||||
// Find rounded up length that can fit the whole casted array of vectors
|
||||
int len = base->expr_width() + vector->packed_width() - 1;
|
||||
if(base->expr_width() > vector->packed_width()) {
|
||||
len /= vector->packed_width();
|
||||
} else {
|
||||
len /= base->expr_width();
|
||||
}
|
||||
|
||||
// Number of words in the created dynamic array
|
||||
NetEConst*len_expr = new NetEConst(verinum(len));
|
||||
return new NetENew(type, len_expr, base);
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return elaborate_expr(des, scope, (unsigned) 0, 0);
|
||||
}
|
||||
|
||||
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned, unsigned) const
|
||||
{
|
||||
@@ -2772,9 +2842,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
concat->set(idx, parms[off+idx]);
|
||||
}
|
||||
|
||||
if (wid_sum == 0 && concat_depth < 2) {
|
||||
cerr << get_fileline() << ": error: Concatenation may not "
|
||||
<< "have zero width in this context." << endl;
|
||||
if (wid_sum == 0) {
|
||||
cerr << get_fileline() << ": error: Concatenation/replication "
|
||||
<< "may not have zero width in this context." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
delete concat;
|
||||
@@ -2822,6 +2892,25 @@ NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
|
||||
list<long>&prefix_indices) const
|
||||
{
|
||||
unsigned dimensions = net->unpacked_dimensions() + net->packed_dimensions();
|
||||
switch (net->data_type()) {
|
||||
case IVL_VT_STRING:
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
dimensions += 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (path_.back().index.size() > dimensions) {
|
||||
cerr << get_fileline() << ": error: the number of indices ("
|
||||
<< path_.back().index.size()
|
||||
<< ") is greater than the number of dimensions ("
|
||||
<< dimensions
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
list<index_component_t> index;
|
||||
index = path_.back().index;
|
||||
ivl_assert(*this, index.size() >= net->unpacked_dimensions());
|
||||
@@ -2850,7 +2939,7 @@ bool PEIdent::calculate_bits_(Design*des, NetScope*scope,
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||
"Bit select expressionsmust be constant."
|
||||
"Bit select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << index_tail.msb->get_fileline() << ": : "
|
||||
"This msb expression violates the rule: "
|
||||
@@ -3416,7 +3505,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
indices_flags idx_flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
use_comp.index, net->unpacked_dimensions(),
|
||||
need_const, net->unpacked_count(),
|
||||
need_const,
|
||||
idx_flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
@@ -3769,7 +3858,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
// Maybe this is a method attached to an enumeration name? If
|
||||
// this is system verilog, then test to see if the name is
|
||||
// this is SystemVerilog, then test to see if the name is
|
||||
// really a method attached to an object.
|
||||
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
@@ -4489,7 +4578,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
indices_flags idx_flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
name_tail.index, net->unpacked_dimensions(),
|
||||
need_const, net->unpacked_count(),
|
||||
need_const,
|
||||
idx_flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
@@ -4578,7 +4667,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long> prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
long msv, lsv;
|
||||
bool parts_defined_flag;
|
||||
@@ -4718,7 +4808,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
@@ -4820,7 +4911,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
@@ -4908,7 +5000,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
+25
-11
@@ -157,7 +157,7 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
|
||||
pform_name_t use_path = cur_path;
|
||||
perm_string tmp_name = peek_tail_name(use_path);
|
||||
name_component_t tail = use_path.back();
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet* reg = 0;
|
||||
@@ -171,18 +171,32 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
|
||||
tmp = new NetAssign_(tmp);
|
||||
tmp->set_property(tmp_name);
|
||||
tmp->set_property(tail.name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (reg->struct_type()) {
|
||||
if (reg->struct_type() && reg->struct_type()->packed()) {
|
||||
NetAssign_*tmp = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, scope, tmp, tail);
|
||||
return tmp;
|
||||
}
|
||||
#if 0
|
||||
if (reg->struct_type() && reg->struct_type()->packed()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with struct " << use_path << endl;
|
||||
<< "I don't know what to do with packed struct " << use_path
|
||||
<< " with member " << tail << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (reg->struct_type() && !reg->struct_type()->packed()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with unpacked struct " << use_path
|
||||
<< " with member " << tail << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->class_type()) {
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -316,7 +330,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
if (reg->struct_type() && !method_name.nil()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, method_name);
|
||||
name_component_t tmp_name (method_name);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, tmp_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -470,7 +485,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Found initialzers for property " << class_type->get_prop_name(pidx) << endl;
|
||||
<< "Found initializers for property " << class_type->get_prop_name(pidx) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -528,8 +543,6 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned array_need_words = reg->unpacked_count();
|
||||
|
||||
// Make sure there are enough indices to address an array element.
|
||||
const index_component_t&index_head = name_tail.index.front();
|
||||
if (index_head.sel == index_component_t::SEL_PART) {
|
||||
@@ -547,7 +560,7 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
name_tail.index, reg->unpacked_dimensions(),
|
||||
false, array_need_words,
|
||||
false,
|
||||
flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
@@ -1117,8 +1130,9 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
||||
|
||||
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
NetAssign_*lv,
|
||||
const perm_string&member_name) const
|
||||
const name_component_t&member_comp) const
|
||||
{
|
||||
const perm_string&member_name = member_comp.name;
|
||||
NetNet*reg = lv->sig();
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
|
||||
+1
-1
@@ -630,7 +630,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
path_tail.index, sig->unpacked_dimensions(),
|
||||
true, sig->unpacked_count(),
|
||||
true,
|
||||
flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
|
||||
+17
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -201,16 +201,15 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
verinum one_value ((uint64_t)1, enum_width);
|
||||
one_value.has_sign(enum_type->signed_flag);
|
||||
// Find the maximum allowed enumeration value.
|
||||
verinum min_value (0);
|
||||
verinum max_value (0);
|
||||
if (enum_type->signed_flag) {
|
||||
min_value = -pow(verinum(2), verinum(enum_width-1));
|
||||
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
|
||||
} else {
|
||||
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
|
||||
}
|
||||
min_value.has_sign(true);
|
||||
max_value.has_sign(enum_type->signed_flag);
|
||||
// Variable to indicate when a defined value wraps.
|
||||
bool implicit_wrapped = false;
|
||||
// Process the enumeration definition.
|
||||
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
||||
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
|
||||
@@ -229,6 +228,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
cur_value = val_const->value();
|
||||
// Clear the implicit wrapped flag if a parameter is given.
|
||||
implicit_wrapped = false;
|
||||
|
||||
// A 2-state value can not have a constant with X/Z bits.
|
||||
if (enum_type->base_type==IVL_VT_BOOL &&
|
||||
@@ -335,24 +336,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cast any undefined bits to zero so the comparisons below
|
||||
// return just true (1) or false (0).
|
||||
verinum two_state_value = cur_value;
|
||||
two_state_value.cast_to_int2();
|
||||
|
||||
// The enumeration value must fit into the enumeration bits.
|
||||
if (!cur_value.is_defined()) {
|
||||
if (cur_value.len() > (unsigned long)use_enum->packed_width()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " value=" << cur_value
|
||||
<< " is too wide for enumeration base type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
} else if ((two_state_value > max_value) ||
|
||||
(cur_value.has_sign() && (two_state_value < min_value))) {
|
||||
|
||||
// Check to see if an implicitly wrapped value is used.
|
||||
if (implicit_wrapped) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " has an inferred value that overflowed." << endl;
|
||||
@@ -385,6 +370,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
// In case the next name has an implicit value,
|
||||
// increment the current value by one.
|
||||
if (cur_value.is_defined()) {
|
||||
if (cur_value == max_value) implicit_wrapped = true;
|
||||
cur_value = cur_value + one_value;
|
||||
}
|
||||
}
|
||||
@@ -807,7 +793,7 @@ void elaborate_rootscope_tasks(Design*des)
|
||||
}
|
||||
|
||||
cerr << cur->second->get_fileline() << ": internal error: "
|
||||
<< "elabortae_rootscope_tasks does not understand "
|
||||
<< "elaborate_rootscope_tasks does not understand "
|
||||
<< "this object," << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
@@ -1756,7 +1742,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
// scope searches will continue into the parent scope.
|
||||
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
|
||||
bound_type_? true : false,
|
||||
mod->program_block);
|
||||
mod->program_block,
|
||||
mod->is_interface);
|
||||
my_scope->set_line(get_file(), mod->get_file(),
|
||||
get_lineno(), mod->get_lineno());
|
||||
my_scope->set_module_name(mod->mod_name());
|
||||
@@ -1806,8 +1793,12 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
// so the mapping into the replace list is much easier.
|
||||
if (parms_) {
|
||||
assert(overrides_ == 0);
|
||||
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
|
||||
replace[parms_[jdx].name] = parms_[jdx].parm;
|
||||
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1) {
|
||||
// No expression means that the parameter is not
|
||||
// replaced.
|
||||
if (parms_[jdx].parm)
|
||||
replace[parms_[jdx].name] = parms_[jdx].parm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+52
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -715,16 +715,23 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the port has a default expression that can be used
|
||||
// as a value when the caller doesn't bind, then
|
||||
// elaborate that expression here. This expression
|
||||
// should evaluate down do a constant.
|
||||
// If the port has a default expression, elaborate
|
||||
// that expression here.
|
||||
if (ports_->at(idx).defe != 0) {
|
||||
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe, -1, true);
|
||||
if (tmp_def==0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
<< *ports_->at(idx).defe
|
||||
<< " as a port default (constant) expression." << endl;
|
||||
if (tmp->port_type() == NetNet::PINPUT) {
|
||||
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe,
|
||||
-1, scope->need_const_func());
|
||||
if (tmp_def == 0) {
|
||||
cerr << get_fileline()
|
||||
<< ": error: Unable to evaluate "
|
||||
<< *ports_->at(idx).defe
|
||||
<< " as a port default expression." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
} else {
|
||||
cerr << get_fileline() << ": sorry: Default arguments "
|
||||
"for subroutine output or inout ports are not "
|
||||
"yet supported." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
@@ -909,6 +916,11 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
|
||||
*/
|
||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
// This sets the vector or array dimension size that will
|
||||
// cause a warning. For now, these warnings are permanently
|
||||
// enabled.
|
||||
const long warn_dimension_size = 1 << 30;
|
||||
|
||||
NetNet::Type wtype = type_;
|
||||
bool is_implicit_scalar = false;
|
||||
if (wtype == NetNet::IMPLICIT) {
|
||||
@@ -964,6 +976,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
|
||||
if (warn_implicit_dimensions
|
||||
&& port_set_ && net_set_
|
||||
&& net_.empty() && !port_.empty()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "var/net declaration of " << basename()
|
||||
<< " inherits dimensions from port declaration." << endl;
|
||||
}
|
||||
|
||||
if (warn_implicit_dimensions
|
||||
&& port_set_ && net_set_
|
||||
&& port_.empty() && !net_.empty()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "Port declaration of " << basename()
|
||||
<< " inherits dimensions from var/net." << endl;
|
||||
}
|
||||
|
||||
bool bad_range = false;
|
||||
vector<netrange_t> plist, nlist;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
@@ -1042,7 +1071,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
packed_dimensions = nlist;
|
||||
wid = netrange_width(packed_dimensions);
|
||||
|
||||
if (wid > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Vector size "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned nattrib = 0;
|
||||
@@ -1063,6 +1096,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// put all the packed dimensions there.
|
||||
if (use_lidx==0 && use_ridx==0) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
@@ -1073,6 +1107,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// declaration, which is the dimensions [null:<nil>].
|
||||
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netqueue_t(vec);
|
||||
@@ -1114,6 +1149,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
index_l = lval.as_long();
|
||||
index_r = rval.as_long();
|
||||
}
|
||||
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Array dimension "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
|
||||
}
|
||||
@@ -1194,7 +1234,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, use_type);
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
|
||||
+48
-35
@@ -32,6 +32,44 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Some types have a list of ranges that need to be elaborated. This
|
||||
* function elaborates the ranges referenced by "dims" into the vector
|
||||
* "ranges".
|
||||
*/
|
||||
static void elaborate_array_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&ranges,
|
||||
const list<pform_range_t>*dims)
|
||||
{
|
||||
if (dims == 0)
|
||||
return;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = dims->begin()
|
||||
; cur != dims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ranges.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborations of types may vary depending on the scope that it is
|
||||
* done in, so keep a per-scope cache of the results.
|
||||
@@ -43,8 +81,8 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
use_definitions = des;
|
||||
|
||||
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
|
||||
if (pos->first == use_definitions)
|
||||
return pos->second;
|
||||
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
|
||||
return pos->second;
|
||||
|
||||
ivl_type_s*tmp = elaborate_type_raw(des, scope);
|
||||
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
|
||||
@@ -120,33 +158,7 @@ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
vector<netrange_t> packed;
|
||||
|
||||
if (pdims.get()) {
|
||||
for (list<pform_range_t>::const_iterator cur = pdims->begin()
|
||||
; cur != pdims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
packed.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
elaborate_array_ranges(des, scope, packed, pdims.get());
|
||||
|
||||
netvector_t*tmp = new netvector_t(packed, base_type);
|
||||
tmp->set_signed(signed_flag);
|
||||
@@ -171,13 +183,14 @@ ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_fileline() << " : sorry: "
|
||||
<< "Packed arrays are not currently supported in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
vector<netrange_t>packed;
|
||||
elaborate_array_ranges(des, scope, packed, dims.get());
|
||||
|
||||
ivl_type_t etype = base_type->elaborate_type(des, scope);
|
||||
|
||||
return new netparray_t(packed, etype);
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
|
||||
+127
-73
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -1287,15 +1287,18 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < pins.size() ; idx += 1) {
|
||||
bool unconnected_port = false;
|
||||
|
||||
perm_string port_name = rmod->get_port_name(idx);
|
||||
|
||||
// Skip unconnected module ports. This happens when a
|
||||
// null parameter is passed in.
|
||||
|
||||
if (pins[idx] == 0) {
|
||||
|
||||
if (pins_fromwc[idx]) {
|
||||
cerr << get_fileline() << ": error: Wildcard named port " <<
|
||||
"connection (.*) did not find a matching identifier " <<
|
||||
"for port '" << rmod->ports[idx]->name << "'." << endl;
|
||||
cerr << get_fileline() << ": error: Wildcard named "
|
||||
"port connection (.*) did not find a matching "
|
||||
"identifier for port " << (idx+1) << " ("
|
||||
<< port_name << ")." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
@@ -1330,22 +1333,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
break;
|
||||
}
|
||||
|
||||
// Print a waring for an unconnected input.
|
||||
// Print a warning for an unconnected input.
|
||||
if (warn_portbinding) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "Instantiating module "
|
||||
<< rmod->mod_name()
|
||||
<< " with dangling input port '"
|
||||
<< rmod->ports[idx]->name;
|
||||
<< " with dangling input port "
|
||||
<< (idx+1) << " (" << port_name;
|
||||
switch (rmod->uc_drive) {
|
||||
case Module::UCD_PULL0:
|
||||
cerr << "' (pulled low)." << endl;
|
||||
cerr << ") pulled low." << endl;
|
||||
break;
|
||||
case Module::UCD_PULL1:
|
||||
cerr << "' (pulled high)." << endl;
|
||||
cerr << ") pulled high." << endl;
|
||||
break;
|
||||
case Module::UCD_NONE:
|
||||
cerr << "' (floating)." << endl;
|
||||
cerr << ") floating." << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1361,8 +1364,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: " << get_name()
|
||||
<< ": Port " << (idx+1) << " has " << prts.size()
|
||||
<< " sub-ports." << endl;
|
||||
<< ": Port " << (idx+1) << " (" << port_name
|
||||
<< ") has " << prts.size() << " sub-ports." << endl;
|
||||
}
|
||||
|
||||
// Count the internal vector bits of the port.
|
||||
@@ -1394,7 +1397,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
prt_vector_width += port_width;
|
||||
ptype = PortType::merged(netnet->port_type(), ptype);
|
||||
}
|
||||
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
|
||||
inst_scope->add_module_port_info(idx, port_name, ptype, prt_vector_width );
|
||||
}
|
||||
|
||||
// If I find that the port is unconnected inside the
|
||||
@@ -1454,8 +1457,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], -1);
|
||||
if (tmp_expr == 0) {
|
||||
cerr << pins[idx]->get_fileline()
|
||||
<< ": internal error: Port expression "
|
||||
<< "too complicated for elaboration." << endl;
|
||||
<< ": error: Failed to elaborate port expression."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1541,8 +1545,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Inout port expression must support "
|
||||
<< "continuous assignment." << endl;
|
||||
cerr << pins[idx]->get_fileline() << ": : "
|
||||
<< "Port " << rmod->ports[idx]->name << " of "
|
||||
cerr << pins[idx]->get_fileline() << ": : Port "
|
||||
<< (idx+1) << " (" << port_name << ") of "
|
||||
<< rmod->mod_name() << " is connected to "
|
||||
<< *pins[idx] << endl;
|
||||
des->errors += 1;
|
||||
@@ -1555,9 +1559,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
!prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Cannot automatically connect bit based "
|
||||
"inout port " << rmod->ports[idx]->name
|
||||
<< " of module " << rmod->mod_name() << " to real "
|
||||
"signal " << sig->name() << "." << endl;
|
||||
"inout port " << (idx+1) << " (" << port_name
|
||||
<< ") of module " << rmod->mod_name()
|
||||
<< " to real signal " << sig->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1566,9 +1570,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "No support for connecting real inout ports ("
|
||||
"port "
|
||||
<< rmod->ports[idx]->name << " of module "
|
||||
<< rmod->mod_name() << ")." << endl;
|
||||
"port " << (idx+1) << " (" << port_name
|
||||
<< ") of module " << rmod->mod_name() << ")." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1581,7 +1584,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
// Special case: If the output port is an unpacked
|
||||
// array, then there should be no sub-ports and
|
||||
// the passed pexxpression is processed
|
||||
// the passed port expression is processed
|
||||
// differently. Note that we are calling it the
|
||||
// "r-value" expression, but since this is an
|
||||
// output port, we assign to it from the internal object.
|
||||
@@ -1611,8 +1614,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Output port expression must support "
|
||||
<< "continuous assignment." << endl;
|
||||
cerr << pins[idx]->get_fileline() << ": : "
|
||||
<< "Port " << rmod->ports[idx]->name << " of "
|
||||
cerr << pins[idx]->get_fileline() << ": : Port "
|
||||
<< (idx+1) << " (" << port_name << ") of "
|
||||
<< rmod->mod_name() << " is connected to "
|
||||
<< *pins[idx] << endl;
|
||||
des->errors += 1;
|
||||
@@ -1687,8 +1690,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
instance.size() != 1) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "An arrayed instance of " << rmod->mod_name()
|
||||
<< " cannot have a real port ("
|
||||
<< rmod->ports[idx]->name << ") connected to a "
|
||||
<< " cannot have a real port (port " << (idx+1)
|
||||
<< " : " << port_name << ") connected to a "
|
||||
"real signal (" << sig->name() << ")." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
@@ -1721,8 +1724,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: " << get_name()
|
||||
<< ": Port " << (idx+1) << " has vector width of "
|
||||
<< prts_vector_width << "." << endl;
|
||||
<< ": Port " << (idx+1) << " (" << port_name
|
||||
<< ") has vector width of " << prts_vector_width
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
// Check that the parts have matching pin counts. If
|
||||
@@ -1730,11 +1734,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// based, but users count parameter positions from 1.
|
||||
if ((instance.size() == 1)
|
||||
&& (prts_vector_width != sig->vector_width())) {
|
||||
const char *tmp3 = rmod->ports[idx]->name.str();
|
||||
bool as_signed = false;
|
||||
|
||||
if (tmp3 == 0) tmp3 = "???";
|
||||
|
||||
switch (prts[0]->port_type()) {
|
||||
case NetNet::POUTPUT:
|
||||
as_signed = prts[0]->get_signed();
|
||||
@@ -1754,7 +1755,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": warning: Port " << (idx+1)
|
||||
<< " (" << tmp3 << ") of "
|
||||
<< " (" << port_name << ") of "
|
||||
<< type_ << " expects " << prts_vector_width <<
|
||||
" bits, got " << sig->vector_width() << "." << endl;
|
||||
|
||||
@@ -2282,11 +2283,18 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
rval_->test_width(des, scope, mode);
|
||||
// Create a L-value that matches the function return type.
|
||||
NetNet*tmp;
|
||||
netvector_t*tmp_vec = new netvector_t(rval_->expr_type(),
|
||||
rval_->expr_width()-1, 0,
|
||||
rval_->has_sign());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::REG, tmp_vec);
|
||||
|
||||
if(rval_->expr_type() == IVL_VT_DARRAY) {
|
||||
netdarray_t*darray = new netdarray_t(tmp_vec);
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, darray);
|
||||
} else {
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, tmp_vec);
|
||||
}
|
||||
|
||||
tmp->set_file(rval_->get_file());
|
||||
tmp->set_lineno(rval_->get_lineno());
|
||||
NetAssign_*lv = new NetAssign_(tmp);
|
||||
@@ -3720,7 +3728,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
|
||||
NetExpr*rv = 0;
|
||||
|
||||
if (parms_idx<parms_.size() && parms_[parms_idx]) {
|
||||
if (parms_idx < parms_.size() && parms_[parms_idx]) {
|
||||
rv = elaborate_rval_expr(des, scope, port->net_type(),
|
||||
lv_type, wid, parms_ [parms_idx]);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
|
||||
@@ -3735,7 +3743,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
if (! gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Found (and using) default task expression "
|
||||
<< " requires SystemVerilog." << endl;
|
||||
"requires SystemVerilog." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
rv = def->port_defe(idx);
|
||||
@@ -3782,20 +3790,24 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
|
||||
/* Elaborate an l-value version of the port expression
|
||||
for output and inout ports. If the expression does
|
||||
not exist then quietly skip it, but if the expression
|
||||
is not a valid l-value print an error message. Note
|
||||
that the elaborate_lval method already printed a
|
||||
detailed message. */
|
||||
NetAssign_*lv;
|
||||
if (parms_[idx]) {
|
||||
not exist or is not a valid l-value print an error
|
||||
message. Note that the elaborate_lval method already
|
||||
printed a detailed message for the latter case. */
|
||||
NetAssign_*lv = 0;
|
||||
if (idx < parms_.size() && parms_[idx]) {
|
||||
lv = parms_[idx]->elaborate_lval(des, scope, false, false);
|
||||
if (lv == 0) {
|
||||
cerr << parms_[idx]->get_fileline() << ": error: "
|
||||
<< "I give up on task port " << (idx+1)
|
||||
<< " expression: " << *parms_[idx] << endl;
|
||||
}
|
||||
} else {
|
||||
lv = 0;
|
||||
} else if (port->port_type() == NetNet::POUTPUT) {
|
||||
// Output ports were skipped earlier, so
|
||||
// report the error now.
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Missing argument " << (idx+1)
|
||||
<< " of call to task." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (lv == 0)
|
||||
@@ -4027,9 +4039,18 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PDoWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetDoWhile*loop = new NetDoWhile(tmp, statement_->elaborate(des, scope));
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
NetDoWhile*loop = new NetDoWhile(ce, sub);
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
@@ -4560,7 +4581,11 @@ NetProc* PEventStatement::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PForever::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
NetProc*stat;
|
||||
if (statement_)
|
||||
stat = statement_->elaborate(des, scope);
|
||||
else
|
||||
stat = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (stat == 0) return 0;
|
||||
|
||||
NetForever*proc = new NetForever(stat);
|
||||
@@ -4766,7 +4791,11 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
/* Elaborate the statement that is contained in the foreach
|
||||
loop. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Make a step statement: idx += 1 */
|
||||
NetAssign_*idx_lv = new NetAssign_(idx_sig);
|
||||
@@ -4797,7 +4826,11 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||
ivl_assert(*this, index_vars_.size() > 0);
|
||||
ivl_assert(*this, dims.size() == index_vars_.size());
|
||||
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
NetForLoop*stmt = 0;
|
||||
|
||||
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
||||
@@ -4882,7 +4915,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
sig->data_type(), sig->vector_width(),
|
||||
expr1_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
if (debug_elaborate && initial_expr) {
|
||||
cerr << get_fileline() << ": debug: FOR initial assign: "
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
@@ -4891,36 +4924,35 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
loop. If there is an error, this will return 0 and I should
|
||||
skip the append. No need to worry, the error has been
|
||||
reported so it's OK that the netlist is bogus. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Now elaborate the for_step statement. I really should do
|
||||
some error checking here to make sure the step statement
|
||||
really does step the variable. */
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate for_step statement "
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
|
||||
NetProc*step = step_->elaborate(des, scope);
|
||||
|
||||
|
||||
/* Elaborate the condition expression. Try to evaluate it too,
|
||||
in case it is a constant. This is an interesting case
|
||||
worthy of a warning. */
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
if (ce == 0) {
|
||||
delete sub;
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dynamic_cast<NetEConst*>(ce)) {
|
||||
cerr << get_fileline() << ": warning: condition expression "
|
||||
"of for-loop is constant." << endl;
|
||||
}
|
||||
|
||||
|
||||
/* Error recovery - if we failed to elaborate any of the loop
|
||||
expressions, give up now. */
|
||||
if (initial_expr == 0 || ce == 0 || step == 0 || sub == 0) {
|
||||
delete initial_expr;
|
||||
delete ce;
|
||||
delete step;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
/* All done, build up the loop. */
|
||||
|
||||
NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step);
|
||||
@@ -5013,8 +5045,16 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
// If the expression is real, convert to an integer. 64 bits
|
||||
// should be more enough for any real use case.
|
||||
if (expr->expr_type() == IVL_VT_REAL)
|
||||
expr = cast_to_int4(expr, 64);
|
||||
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
NetProc*stat;
|
||||
if (statement_)
|
||||
stat = statement_->elaborate(des, scope);
|
||||
else
|
||||
stat = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (stat == 0) return 0;
|
||||
|
||||
// If the expression is a constant, handle certain special
|
||||
@@ -5193,9 +5233,18 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetWhile*loop = new NetWhile(tmp, statement_->elaborate(des, scope));
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
NetWhile*loop = new NetWhile(ce, sub);
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
@@ -5679,6 +5728,9 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
"generate " << scheme_type
|
||||
<< " elaborating in scope " << scope_path(container)
|
||||
<< "." << endl;
|
||||
cerr << get_fileline() << ": PGenerate::elaborate: "
|
||||
"generate scope_name=" << scope_name
|
||||
<< ", id_number=" << id_number << endl;
|
||||
}
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
@@ -5713,6 +5765,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
// scheme defined in the Verilog-2005 standard.
|
||||
const char*name = scope_name.str();
|
||||
if (name[0] == '$') {
|
||||
|
||||
if (!scope->auto_name("genblk", '0', name + 4)) {
|
||||
cerr << get_fileline() << ": warning: Couldn't build"
|
||||
<< " unique name for unnamed generate block"
|
||||
@@ -6086,7 +6139,8 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
// Make the root scope. This makes a NetScope object and
|
||||
// pushes it into the list of root scopes in the Design.
|
||||
NetScope*scope = des->make_root_scope(*root, rmod->program_block);
|
||||
NetScope*scope = des->make_root_scope(*root, rmod->program_block,
|
||||
rmod->is_interface);
|
||||
|
||||
// Collect some basic properties of this scope from the
|
||||
// Module definition.
|
||||
|
||||
@@ -2009,6 +2009,12 @@ static bool check_dimension(const NetExpr*dim_expr, long &dim)
|
||||
static bool get_array_info(const NetExpr*arg, long dim,
|
||||
long &left, long &right, bool&defer)
|
||||
{
|
||||
if (const NetEConstParam*param = dynamic_cast<const NetEConstParam*>(arg)) {
|
||||
assert(dim == 1);
|
||||
left = param->expr_width() - 1;
|
||||
right = 0;
|
||||
return false;
|
||||
}
|
||||
/* The argument must be a signal that has enough dimensions. */
|
||||
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
|
||||
if (esig == 0) return true;
|
||||
|
||||
+20
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -1138,18 +1138,29 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
if (sub->vector_width() == expr_width())
|
||||
return sub;
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
|
||||
net_vec->set_signed(has_sign());
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, net_vec);
|
||||
net->set_line(*this);
|
||||
net->local_flag(true);
|
||||
if (has_sign()) {
|
||||
|
||||
// It may still happen that the expression is wider than the selection,
|
||||
// and there was no part select created earlier (size casting).
|
||||
if(expr_width() < sub->vector_width()) {
|
||||
NetPartSelect*sel = new NetPartSelect(sub, 0, expr_width(),
|
||||
NetPartSelect::VP, has_sign());
|
||||
sel->set_line(*this);
|
||||
des->add_node(sel);
|
||||
|
||||
connect(net->pin(0), sel->pin(0));
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
} else if (has_sign()) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope,
|
||||
scope->local_symbol(),
|
||||
expr_width());
|
||||
@@ -1166,7 +1177,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
cat->set_line(*this);
|
||||
des->add_node(cat);
|
||||
|
||||
assert(expr_width() > sub->vector_width());
|
||||
unsigned pad_width = expr_width() - sub->vector_width();
|
||||
verinum pad((uint64_t)0, pad_width);
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(),
|
||||
@@ -1278,6 +1288,8 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
net_->vector_width()-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, tmp_vec);
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width());
|
||||
NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val);
|
||||
tmp_const->set_line(*this);
|
||||
|
||||
+34
-47
@@ -1,10 +1,10 @@
|
||||
.TH iverilog-vpi 1 "April 17th, 2009" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog-vpi
|
||||
[\-\-name=\fIname\fP]
|
||||
[options]
|
||||
\fIsourcefile\fP...
|
||||
|
||||
.SH DESCRIPTION
|
||||
@@ -15,9 +15,9 @@ list of C or C++ source files, and generates as output a linked VPI
|
||||
module. See the \fBvvp\fP(1) man page for a description of how the
|
||||
linked module is loaded by a simulation.
|
||||
|
||||
The output is named after the first source file. For example, if the
|
||||
first source file is named \fIfoo.c\fP, the output becomes
|
||||
\fIfoo.vpi\fP.
|
||||
By default the output is named after the first source file. For
|
||||
example, if the first source file is named \fIfoo.c\fP, the output
|
||||
becomes \fIfoo.vpi\fP.
|
||||
|
||||
.SH OPTIONS
|
||||
\fIiverilog\-vpi\fP accepts the following options:
|
||||
@@ -28,8 +28,8 @@ VPI modules to further reference external libraries.
|
||||
|
||||
.TP 8
|
||||
.B -I\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be search for
|
||||
header files.
|
||||
Add \fIdirectory\fP to the list of directories that will be searched
|
||||
for header files.
|
||||
|
||||
.TP 8
|
||||
.B -D\fIdefine\fP
|
||||
@@ -41,46 +41,38 @@ Normally, the output VPI module will be named after the first source
|
||||
file passed to the command. This flag sets the name (without the .vpi
|
||||
suffix) of the output vpi module.
|
||||
|
||||
.TP 8
|
||||
.B --install-dir
|
||||
This flag causes the program to print the install directory for VPI
|
||||
modules, then exit. It is a convenience for makefiles or automated
|
||||
plug-in installers.
|
||||
|
||||
.TP 8
|
||||
.B --cflags, --ldflags and --ldlibs
|
||||
These flags provide compile time information.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog\-vpi\fP includes two special flags needed to
|
||||
support the more intractable development environment. These flags help
|
||||
the program locate parts that it needs.
|
||||
When built as a native Windows program (using the MinGW toolchain),
|
||||
by default \fIiverilog\-vpi\fP will attempt to locate the MinGW tools
|
||||
needed to compile a VPI module on the system path (as set by the PATH
|
||||
environment variable). As an alternative, the user may specify the
|
||||
location of the MinGW tools via the following option.
|
||||
|
||||
.TP 8
|
||||
.B -mingw=\fIpath\fP
|
||||
Tell the program the root of the Mingw compiler tool suite. The
|
||||
Tell the program the root of the MinGW compiler tool suite. The
|
||||
\fBvvp\fP runtime is compiled with this compiler, and this is the
|
||||
compiler that \fIiverilog\-vpi\fP expects to use to compile your source
|
||||
code. This is normally not needed, and if you do use it, it is only
|
||||
needed once. The compiler will save the \fIpath\fP in the registry for
|
||||
use later.
|
||||
compiler that \fIiverilog\-vpi\fP expects to use to compile your
|
||||
source code. If this option accompanies a list of files, it will
|
||||
apply to the current build only. If this option is provided on its
|
||||
own, \fIiverilog\-vpi\fP will save the \fIpath\fP in the registry
|
||||
and use that path in preference to the system path for subsequent
|
||||
operations, avoiding the need to specify it on the command line
|
||||
every time.
|
||||
|
||||
.SH "INFORMATIONAL OPTIONS"
|
||||
|
||||
\fIiverilog\-vpi\fP includes additional flags to let Makefile gurus
|
||||
peek at the configuration of the \fIiverilog\fP installation. This way,
|
||||
Makefiles can be written that handle complex VPI builds natively, and
|
||||
without hard-coding values that depend on the system and installation.
|
||||
If used at all, these options must be used one at a time, and without
|
||||
any other options or directives.
|
||||
|
||||
.TP 8
|
||||
.B -ivl=\fIpath\fP
|
||||
Set for the use during compilation the root if the Icarus Verilog
|
||||
install. This is the place where you installed Icarus Verilog when you
|
||||
ran the installer. This flag is also only needed once, and the path is
|
||||
stored in the registry for future use.
|
||||
|
||||
.SH "UNIX-ONLY OPTIONS"
|
||||
|
||||
The UNIX version of \fIiverilog\-vpi\fP includes additional flags to
|
||||
let Makefile gurus peek at the configuration of the \fIiverilog\fP
|
||||
installation. This way, Makefiles can be written that handle complex VPI
|
||||
builds natively, and without hard-coding values that depend on the
|
||||
system and installation. If used at all, these options must be
|
||||
used one at a time, and without any other options or directives.
|
||||
.B --install-dir
|
||||
Print the install directory for VPI modules.
|
||||
|
||||
.TP 8
|
||||
.B --cflags
|
||||
@@ -95,11 +87,6 @@ Print the linker flags (LDFLAGS) needed to link a VPI module.
|
||||
.B --ldlibs
|
||||
Print the libraries (LDLIBS) needed to link a VPI module.
|
||||
|
||||
.TP 8
|
||||
.B -m32
|
||||
On 64bit systems that support it (and support vvp32) this flag
|
||||
requests a 32bit vpi binary instead of the default 64bit binary.
|
||||
|
||||
.P
|
||||
Example GNU makefile that takes advantage of these flags:
|
||||
.IP "" 4
|
||||
@@ -123,12 +110,12 @@ Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>",
|
||||
.BR "<http://www.mingw.org>",
|
||||
.BR "<http://iverilog.icarus.com/>",
|
||||
.BR "<http://mingw-w64.yaxm.org/>",
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2009 Stephen Williams
|
||||
Copyright \(co 2002\-2015 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
@@ -125,6 +125,7 @@ ivl_lpm_enable
|
||||
ivl_lpm_file
|
||||
ivl_lpm_lineno
|
||||
ivl_lpm_name
|
||||
ivl_lpm_negedge
|
||||
ivl_lpm_q
|
||||
ivl_lpm_scope
|
||||
ivl_lpm_select
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* Define a safer version of malloc().
|
||||
*/
|
||||
@@ -82,5 +83,6 @@
|
||||
} \
|
||||
__ivl_rtn; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /* IVL_ivl_alloc_H */
|
||||
|
||||
+17
-8
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -41,6 +41,12 @@
|
||||
# define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && defined(_MSC_VER)
|
||||
# define ENUM_UNSIGNED_INT : unsigned int
|
||||
#else
|
||||
# define ENUM_UNSIGNED_INT
|
||||
#endif
|
||||
|
||||
_BEGIN_DECL
|
||||
|
||||
/*
|
||||
@@ -201,7 +207,7 @@ typedef enum ivl_dis_domain_e {
|
||||
IVL_DIS_CONTINUOUS = 2
|
||||
} ivl_dis_domain_t;
|
||||
|
||||
typedef enum ivl_drive_e {
|
||||
typedef enum ivl_drive_e ENUM_UNSIGNED_INT {
|
||||
IVL_DR_HiZ = 0,
|
||||
IVL_DR_SMALL = 1,
|
||||
IVL_DR_MEDIUM = 2,
|
||||
@@ -243,7 +249,7 @@ typedef enum ivl_expr_type_e {
|
||||
IVL_EX_UNARY = 14
|
||||
} ivl_expr_type_t;
|
||||
|
||||
typedef enum ivl_select_type_e {
|
||||
typedef enum ivl_select_type_e ENUM_UNSIGNED_INT {
|
||||
IVL_SEL_OTHER = 0,
|
||||
IVL_SEL_IDX_UP = 1,
|
||||
IVL_SEL_IDX_DOWN = 2
|
||||
@@ -300,7 +306,7 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CONCATZ = 36, /* Transparent concat */
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQX= 37, /* Windcard EQ (==?) */
|
||||
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */
|
||||
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
IVL_LPM_CMP_GE = 1,
|
||||
@@ -345,7 +351,7 @@ typedef enum ivl_path_edge_e {
|
||||
|
||||
/* Processes are initial, always, or final blocks with a statement. This is
|
||||
the type of the ivl_process_t object. */
|
||||
typedef enum ivl_process_type_e {
|
||||
typedef enum ivl_process_type_e ENUM_UNSIGNED_INT {
|
||||
IVL_PR_INITIAL = 0,
|
||||
IVL_PR_ALWAYS = 1,
|
||||
IVL_PR_FINAL = 2
|
||||
@@ -431,7 +437,7 @@ typedef enum ivl_sfunc_as_task_e {
|
||||
|
||||
/* This is the type of a variable, and also used as the type for an
|
||||
expression. */
|
||||
typedef enum ivl_variable_type_e {
|
||||
typedef enum ivl_variable_type_e ENUM_UNSIGNED_INT {
|
||||
IVL_VT_VOID = 0, /* Not used */
|
||||
IVL_VT_NO_TYPE = 1, /* Place holder for missing/unknown type. */
|
||||
IVL_VT_REAL = 2,
|
||||
@@ -1285,8 +1291,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* magnitude compare, the signedness does matter. In any case, the
|
||||
* result of the compare is always unsigned.
|
||||
*
|
||||
* The EQX and EQZ nodes are windcard compares, where xz bits (EQX) or
|
||||
* z bits (EQZ) in the data(1) operand are treated as windcards. no
|
||||
* The EQX and EQZ nodes are wildcard compares, where xz bits (EQX) or
|
||||
* z bits (EQZ) in the data(1) operand are treated as wildcards. no
|
||||
* bits in the data(0) operand are wild. This matches the
|
||||
* SystemVerilog convention for the ==? operator.
|
||||
*
|
||||
@@ -1418,6 +1424,7 @@ extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART IVL_LPM_SUBSTITUTE */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern unsigned ivl_lpm_negedge(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
@@ -2342,4 +2349,6 @@ typedef const char* (*target_query_f) (const char*key);
|
||||
|
||||
_END_DECL
|
||||
|
||||
#undef ENUM_UNSIGNED_INT
|
||||
|
||||
#endif /* IVL_ivl_target_H */
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ keys, with their corresponding values, are:
|
||||
This is exactly the same as the "-Dname=<value>" described above.
|
||||
|
||||
I:<dir>
|
||||
This is exctly the same as "-I<dir>".
|
||||
This is exactly the same as "-I<dir>".
|
||||
|
||||
relative include:<flag>
|
||||
The <flag> can be "true" or "false". This enables "relative
|
||||
|
||||
+200
-320
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,5 +1,5 @@
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1999-2011 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1999-2011,2015 Stephen Williams ([email protected])";
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -432,16 +432,26 @@ TU [munpf]
|
||||
return SYSTEM_IDENTIFIER; }
|
||||
|
||||
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[dD][ \t]*[xzXZ?]_* { yylval.number = make_undef_highz_dec(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
||||
yylval.number = make_unsized_dec(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[dD][ \t]*[xzXZ?]_* {
|
||||
yylval.number = make_undef_highz_dec(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ?][0-1xzXZ?_]* {
|
||||
yylval.number = make_unsized_binary(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ?][0-7xzXZ?_]* {
|
||||
yylval.number = make_unsized_octal(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ?][0-9a-fA-FxzXZ?_]* {
|
||||
yylval.number = make_unsized_hex(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[01xzXZ] {
|
||||
if (generation_flag < GN_VER2005_SV) {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
|
||||
|
||||
@@ -27,6 +27,11 @@ LineInfo::LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
LineInfo::LineInfo(const LineInfo&that) :
|
||||
file_(that.file_), lineno_(that.lineno_)
|
||||
{
|
||||
}
|
||||
|
||||
LineInfo::~LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ using namespace std;
|
||||
class LineInfo {
|
||||
public:
|
||||
LineInfo();
|
||||
LineInfo(const LineInfo&that);
|
||||
virtual ~LineInfo();
|
||||
|
||||
// Get a fully formatted file/lineno
|
||||
|
||||
@@ -36,7 +36,7 @@ double acc_fetch_paramval(handle object)
|
||||
fprintf(pli_trace, "acc_fetch_paramval(%s) --> \"%s\"\n",
|
||||
vpi_get_str(vpiName, object), val.value.str);
|
||||
}
|
||||
return (double) (long)val.value.str;
|
||||
return (double) (intptr_t)val.value.str;
|
||||
|
||||
default:
|
||||
vpi_printf("XXXX: parameter %s has type %d\n",
|
||||
|
||||
@@ -115,7 +115,7 @@ PLI_INT32 tf_getlongtime(PLI_INT32 *high)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is not defined in the IEE standard, but is provided for
|
||||
* This function is not defined in the IEEE standard, but is provided for
|
||||
* compatibility with other simulators. On platforms that support this,
|
||||
* make it a weak symbol just in case the user has defined their own
|
||||
* function for this.
|
||||
|
||||
+20
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -45,6 +45,14 @@ bool Nexus::drivers_constant() const
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we are connected to a tran, there may be a driver
|
||||
on the other side of the tran. We could try checking
|
||||
for this, but for now, be pessimistic. */
|
||||
if (dynamic_cast<const NetTran*>(cur->get_obj())) {
|
||||
driven_ = VAR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Link::DIR cur_dir = cur->get_dir();
|
||||
if (cur_dir == Link::INPUT)
|
||||
continue;
|
||||
@@ -267,11 +275,17 @@ vector<bool> Nexus::driven_mask(void) const
|
||||
}
|
||||
|
||||
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
|
||||
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
|
||||
continue;
|
||||
if (obj_ps && cur->get_pin()!=1)
|
||||
continue;
|
||||
if (obj_ps) {
|
||||
if(obj_ps) {
|
||||
if (obj_ps->dir()==NetPartSelect::VP) {
|
||||
if(cur->get_pin() != 0)
|
||||
continue;
|
||||
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||
mask[idx] = true;
|
||||
return mask;
|
||||
} else {
|
||||
if (cur->get_pin() != 1)
|
||||
continue;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
|
||||
size_t bit = idx + obj_ps->base();
|
||||
ivl_assert(*obj, bit < mask.size());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-2014 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2015 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -153,6 +153,7 @@ FILE *depend_file = NULL;
|
||||
* These are the warning enable flags.
|
||||
*/
|
||||
bool warn_implicit = false;
|
||||
bool warn_implicit_dimensions = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_inf_loop = false;
|
||||
@@ -678,6 +679,9 @@ static void read_iconfig_file(const char*ipath)
|
||||
case 'i':
|
||||
warn_implicit = true;
|
||||
break;
|
||||
case 'd':
|
||||
warn_implicit_dimensions = true;
|
||||
break;
|
||||
case 'l':
|
||||
warn_inf_loop = true;
|
||||
break;
|
||||
@@ -859,6 +863,7 @@ int main(int argc, char*argv[])
|
||||
# if defined(HAVE_TIMES)
|
||||
times_flag = true;
|
||||
# endif
|
||||
flags["VVP_EXTRA_ARGS"] = strdup(" -v");
|
||||
break;
|
||||
case 'V':
|
||||
version_flag = true;
|
||||
|
||||
@@ -1,282 +1,4 @@
|
||||
Please NOTE:
|
||||
Please see the Icarus Verilog Wiki for instruction on building and installing
|
||||
Icarus Verilog as a native Windows application using the MinGW tools:
|
||||
|
||||
These directions are slightly outdated and need to be updated.
|
||||
The plan is to rewrite all this using the latest MinGW at
|
||||
some time in the not too distant future (CR Aug. 2009)
|
||||
|
||||
|
||||
MINGW PORT OF ICARUS VERILOG
|
||||
|
||||
Copyright 2006 Stephen Williams <[email protected]>
|
||||
|
||||
|
||||
Icarus Verilog source can be compiled with the mingw C/C++ compilers
|
||||
to get a Windows binary that does not require the POSIX compatibility
|
||||
cruft of the Cygwin.dll library. The resulting program can be run with
|
||||
or without Cygwin, so this is the preferred Windows distribution form.
|
||||
The configure scripts automatically detect that the compilers in use
|
||||
are the mingw compilers and will configure the Makefiles appropriately.
|
||||
|
||||
The mingw patch doesn't contain tools beyond the compiler, but there
|
||||
is the "msys" package that the makers of Mingw publish that has enough
|
||||
extra tools to get most everything else working. There are a few extra
|
||||
packages needed beyond mingw and msys, and the following instructions
|
||||
explain how to get them and install them.
|
||||
|
||||
* Some Preliminary Comments -- PLEASE READ ME --
|
||||
|
||||
The Windows port of Icarus Verilog is the most difficult of all the
|
||||
ports. The Windows system off the shelf is completely stripped, devoid
|
||||
of any support for software development. Everything needed to compile
|
||||
Icarus Verilog must be collected from various sources and stitched
|
||||
together by hand. Normal human beings with a basic understanding of
|
||||
software development can do this, but some patience (and access to the
|
||||
Internet) is required. You may choose to print these instructions. FOR
|
||||
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
|
||||
|
||||
NOTE that if you have Cygwin installed, it is best to not use a cygwin
|
||||
window to do the build, as the Cygwin tools will intermix with the
|
||||
mingw tools such that it is hard to be sure you are using the right
|
||||
compiler. Thus, it is recommended that these steps be *not* done in a
|
||||
Cygwin window. Use an MSYS window instead, and be careful that your
|
||||
msys/mingw tools are not masked by paths that point to Cygwin binaries.
|
||||
|
||||
I have no plans to intentionally support MSVC++ compilation. Don't ask.
|
||||
|
||||
* Summary of Prerequisites
|
||||
|
||||
This is a brief list of prerequisite packages, along with the URL
|
||||
where each can be found. In most cases, the specific version is not
|
||||
critical, but these are the versions I use.
|
||||
|
||||
msys-1.0 <http://www.mingw/org>
|
||||
msysDTK-1.0 <http://www.mingw.org>
|
||||
Mingw32-5.x <http://www.mingw.org>
|
||||
... including the sub-packages binutils, gcc-core and gcc-g++
|
||||
if you are given the option.
|
||||
readline-5.0-1 <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
||||
bison-2.1 <http://gnuwin32.sourceforge.net>
|
||||
flex-2.5.4a <http://gnuwin32.sourceforge.net>
|
||||
|
||||
The above table lists the packages required. It is convenient to
|
||||
install them in the above order. Many of these packages are also
|
||||
collected into the directory:
|
||||
|
||||
<ftp://icarus.com/pub/eda/verilog/win32-build-parts>
|
||||
|
||||
Incidentally, besides Mingw32, none of these packages are needed after
|
||||
installation of Icarus Verilog is complete. These are only needed to
|
||||
build the compiler. The Mingw32 package can be used to compile VPI
|
||||
modules if you choose.
|
||||
|
||||
* Install MSYS and msysDTK
|
||||
|
||||
The msys package is available from the mingw download site. This is
|
||||
not the compiler but a collection of *nix tools ported to Windows and
|
||||
wrapped in a convenient installer. The msys package is all the various
|
||||
basic tools (shells, file utils, etc) and the msysDTK is extra
|
||||
developer tools other than the compiler.
|
||||
|
||||
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
||||
self-installing packages. Install msys first, and then msysDTC. Most
|
||||
likely, you want to install them in c:/msys. (The msysDTK is installed
|
||||
in the same location, as it is an add-on.)
|
||||
|
||||
This install should be easy and reliable.
|
||||
|
||||
The installation will leave an "msys" icon on your desktop and in the
|
||||
mingw sub-menu of your Start menu. This icon brings up a shell window
|
||||
(a command line) that has paths all set up for executing msys and
|
||||
mingw commands. This is what you will want to use while executing
|
||||
commands below.
|
||||
|
||||
* Install Mingw32
|
||||
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
|
||||
is a convenient remote installer. Download this program and run
|
||||
it. The installer will ask which components you want to install. You
|
||||
need only the base C compiler and the C++ compiler. (You may install
|
||||
other languages if you wish.)
|
||||
|
||||
When I install Mingw32 (using the installer) I typically set a
|
||||
destination directory of d:\mingw or the like. You will be using
|
||||
that path later.
|
||||
|
||||
NOTES:
|
||||
If you intend to compile VPI modules for Icarus Verilog, you
|
||||
need Mingw32, even if you are using a precompiled binary. VPI
|
||||
modules only require Mingw32, and none of the other libraries.
|
||||
|
||||
Finally, as part of installing the mingw32 compilers, remember to add
|
||||
the mingw/bin directory to your path. You will need that to be able to
|
||||
find the compilers later.
|
||||
|
||||
* Install GnuWin32 Packages
|
||||
|
||||
The GnuWin32 project is a collections of open source programs and
|
||||
libraries ported to Windows. These also work well with the Mingw
|
||||
compiler, and in fact Icarus Verilog uses a few pieces from this
|
||||
collection.
|
||||
|
||||
You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||
|
||||
<http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3.exe
|
||||
zlib-1.2.3.exe
|
||||
gperf-3.0.1.exe
|
||||
bison-2.1.exe
|
||||
flex-2.5.4a.exe
|
||||
readline-5.0-1.exe
|
||||
|
||||
I suggest creating a common directory for holding all your gnuwin32
|
||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||
has a "setup" link for each of these packages. Click the setup to
|
||||
download the installer for each of the desired programs, then execute
|
||||
the downloaded .exe files to invoke the installer. Install into the
|
||||
c:\gunwin32 directory.
|
||||
|
||||
NOTES:
|
||||
You need the binaries and the developer files, but you do not
|
||||
need the source to these packages. The installer gives you the
|
||||
choice.
|
||||
|
||||
After you are done installing the gnuwin32 tools, you should add the
|
||||
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
|
||||
your Windows path. The msys shell will pick up your Windows path.
|
||||
|
||||
* Unpack Icarus Verilog source
|
||||
|
||||
Unpack the compressed tar file (.tar.gz) of the source with a command
|
||||
like this:
|
||||
|
||||
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
|
||||
|
||||
This will create a directory "verilog-xxxxxxxx" that contains all the
|
||||
source for Icarus Verilog. Descend into that directory, as that is
|
||||
where we will work from now on.
|
||||
|
||||
$ cd verilog-xxxxxxxx
|
||||
|
||||
NOTES:
|
||||
The exact name of the file will vary according to the
|
||||
snapshot. The 20030303 name is only an example.
|
||||
|
||||
Unpack the source into a directory that has no spaces. The
|
||||
makefiles included in the source get confused by white space in
|
||||
directory names.
|
||||
|
||||
* Preconfigure Icarus Verilog (Not normally needed)
|
||||
|
||||
Under certain cases, you may need to "preconfigure" the Icarus Verilog
|
||||
source tree. You should only need to do this if you are getting the
|
||||
Icarus Verilog source tree from git, or you are using an existing
|
||||
source tree that you've patched to cause configure.in files to change.
|
||||
|
||||
NOTE: If you are building from a fresh, bundled source tree that
|
||||
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
|
||||
the "Configure Icarus Verilog" step below.
|
||||
|
||||
First, remove any autom4te.cache directories that may exist in your
|
||||
source tree. These can make a mess of autoconf runs. Then, generate
|
||||
configure scripts with this command:
|
||||
|
||||
$ sh autoconf.sh
|
||||
|
||||
This script will run the "autoconf" command (part of the msysDTK) to
|
||||
generate all the necessary "configure" scripts. This will take a few
|
||||
minutes. This should go smoothly.
|
||||
|
||||
* Configure Icarus Verilog
|
||||
|
||||
Now we are all set to configure and compile Icarus Verilog. Choose a
|
||||
destination path where you will want to install the binaries. I chose
|
||||
on my system the directory "D:\iverilog". This choice is not
|
||||
permanent, so don't get too much angst over it. Just choose a name
|
||||
without white space.
|
||||
|
||||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run these commands:
|
||||
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=c:/iverilog
|
||||
|
||||
NOTES:
|
||||
The CPPFLAGS and LDFLAGS variables tell configure where
|
||||
the gnuwin32 packages are. The configure program will
|
||||
write these values into the Makefiles, so you only need to
|
||||
keep these variables long enough for the configure program
|
||||
to work.
|
||||
|
||||
Your PATH variable was set in the previous step.
|
||||
|
||||
Use forward slashes as directory characters. All the various
|
||||
tools prefer the forward slash.
|
||||
|
||||
Substitute your chosen directory for the prefix. This will cause the
|
||||
makefiles to build and the source code to configure. The configure
|
||||
program will detect that this is a mingw environment and set things up
|
||||
to build properly.
|
||||
|
||||
(For a prefix, use the drive letter notation; the mingw compiled parts
|
||||
require it, and the Cygwin tools should be able to handle it. You may
|
||||
need to check or upgrade your Cygwin installation if this causes
|
||||
problems for you.)
|
||||
|
||||
|
||||
* Compile Icarus Verilog
|
||||
|
||||
This, believe it or not, should be the easy part:
|
||||
|
||||
$ make
|
||||
|
||||
It could take a while. Now is a good time to go get some coffee or
|
||||
take a tea break.
|
||||
|
||||
|
||||
* Install Icarus Verilog
|
||||
|
||||
If the compile ran OK, then next you install Icarus Verilog in the
|
||||
directory you have chosen. When you are ready, install like this:
|
||||
|
||||
$ make install
|
||||
|
||||
This is part of what the configure program did for you. The Makefiles
|
||||
now know to put the files under the D:\iverilog directory (or whatever
|
||||
directory you chose) and away you go.
|
||||
|
||||
You may find that you need to put some of the prerequisite DLLs into
|
||||
the d:\iverilog\bin directory. These include:
|
||||
|
||||
c:\mingw\bin\mingw10.dll
|
||||
c:\gnuwin32\bin\readline.dll
|
||||
c:\gnuwin32\bin\history.dll
|
||||
c:\gnuwin32\bin\bzip2.dll
|
||||
c:\gnuwin32\bin\zlib.dll
|
||||
|
||||
If you already have these in your Windows path (i.e. your system32
|
||||
directory) then you do not need to copy them into the iverilog
|
||||
directory. However, prepackaged Icarus Verilog binaries include these
|
||||
files.
|
||||
|
||||
* Running Icarus Verilog
|
||||
|
||||
Finally, put the C:\iverilog\bin directory in your Windows path, and
|
||||
you should be able to run the iverilog and vvp commands to your
|
||||
heart's content.
|
||||
|
||||
Currently, the iverilog.exe uses the path to itself to locate the
|
||||
libraries and modules associated with itself. In other words, if you
|
||||
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the C:\iverilog directory and subdirectories below
|
||||
that. This means you can move the Icarus Verilog installation by
|
||||
simply moving the root directory and all its contents.
|
||||
|
||||
The vvp.pdf and iverilog.pdf files document the main commands. View
|
||||
these with Acrobat reader, or any other viewer capable of displaying
|
||||
PDF format files.
|
||||
http://iverilog.wikia.com/wiki/Installation_Guide#Compiling_on_MS_Windows_.28MinGW.29
|
||||
|
||||
+4
-2
@@ -101,11 +101,12 @@ uint64_t Design::scale_to_precision(uint64_t val,
|
||||
return val;
|
||||
}
|
||||
|
||||
NetScope* Design::make_root_scope(perm_string root, bool program_block)
|
||||
NetScope* Design::make_root_scope(perm_string root, bool program_block,
|
||||
bool is_interface)
|
||||
{
|
||||
NetScope *root_scope_;
|
||||
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
|
||||
false, program_block);
|
||||
false, program_block, is_interface);
|
||||
/* This relies on the fact that the basename return value is
|
||||
permallocated. */
|
||||
root_scope_->set_module_name(root_scope_->basename());
|
||||
@@ -846,6 +847,7 @@ NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
|
||||
// the function's signals have been elaborated. If this is
|
||||
// the case, elaborate them now.
|
||||
if (func->elab_stage() < 2) {
|
||||
func->need_const_func(true);
|
||||
const PFunction*pfunc = func->func_pform();
|
||||
assert(pfunc);
|
||||
pfunc->elaborate_sig(this, func);
|
||||
|
||||
+18
-11
@@ -110,8 +110,10 @@ void Definitions::add_class(netclass_t*net_class)
|
||||
* in question.
|
||||
*/
|
||||
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bool prog)
|
||||
: type_(t), name_(n), nested_module_(nest), program_block_(prog), up_(up)
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
|
||||
bool program, bool interface)
|
||||
: type_(t), name_(n), nested_module_(nest), program_block_(program),
|
||||
is_interface_(interface), up_(up)
|
||||
{
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
@@ -262,19 +264,20 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
||||
assert(self != up_->children_.end());
|
||||
assert(self->second == this);
|
||||
|
||||
char tmp[32];
|
||||
int pad_pos = strlen(prefix);
|
||||
int max_pos = sizeof(tmp) - strlen(suffix) - 1;
|
||||
strncpy(tmp, prefix, sizeof(tmp));
|
||||
tmp[31] = 0;
|
||||
// This is to keep the pad attempts from being stuck in some
|
||||
// sort of infinite loop. This should not be a practical
|
||||
// limit, but an extreme one.
|
||||
const size_t max_pad_attempts = 32 + strlen(prefix);
|
||||
|
||||
string use_prefix = prefix;
|
||||
|
||||
// Try a variety of potential new names. Make sure the new
|
||||
// name is not in the parent scope. Keep looking until we are
|
||||
// sure we have a unique name, or we run out of names to try.
|
||||
while (pad_pos <= max_pos) {
|
||||
while (use_prefix.size() <= max_pad_attempts) {
|
||||
// Try this name...
|
||||
strcat(tmp + pad_pos, suffix);
|
||||
hname_t new_name(lex_strings.make(tmp));
|
||||
string tmp = use_prefix + suffix;
|
||||
hname_t new_name(lex_strings.make(tmp.c_str()), name_.peek_numbers());
|
||||
if (!up_->child(new_name)) {
|
||||
// Ah, this name is unique. Rename myself, and
|
||||
// change my name in the parent scope.
|
||||
@@ -283,7 +286,9 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
||||
up_->children_[name_] = this;
|
||||
return true;
|
||||
}
|
||||
tmp[pad_pos++] = pad;
|
||||
|
||||
// Name collides, so try a different name.
|
||||
use_prefix = use_prefix + pad;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -372,6 +377,8 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
|
||||
// To get here the parameter must already exist, so we should
|
||||
// never get here.
|
||||
assert(0);
|
||||
// But return something to avoid a compiler warning.
|
||||
return idx;
|
||||
}
|
||||
|
||||
NetScope::TYPE NetScope::type() const
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_netdarray_H
|
||||
#define IVL_netdarray_H
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -33,6 +33,9 @@ class netdarray_t : public netarray_t {
|
||||
// IVL_VT_DARRAY for dynamic arrays?
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
||||
// A dynamic array may have a type that is signed.
|
||||
inline bool get_signed() const { return element_type()->get_signed(); }
|
||||
|
||||
// This is the base_type() of the element of the array. We
|
||||
// need this in some cases in order to get the base type of
|
||||
// the element, and not the IVL_VT_DARRAY of the array itself.
|
||||
|
||||
+16
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -1153,8 +1153,8 @@ unsigned NetReplicate::repeat() const
|
||||
* ...
|
||||
*/
|
||||
|
||||
NetFF::NetFF(NetScope*s, perm_string n, unsigned width__)
|
||||
: NetNode(s, n, 8), width_(width__)
|
||||
NetFF::NetFF(NetScope*s, perm_string n, bool negedge__, unsigned width__)
|
||||
: NetNode(s, n, 8), negedge_(negedge__), width_(width__)
|
||||
{
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
@@ -1170,6 +1170,11 @@ NetFF::~NetFF()
|
||||
{
|
||||
}
|
||||
|
||||
bool NetFF::is_negedge() const
|
||||
{
|
||||
return negedge_;
|
||||
}
|
||||
|
||||
unsigned NetFF::width() const
|
||||
{
|
||||
return width_;
|
||||
@@ -2738,10 +2743,11 @@ DelayType NetCase::delay_type() const
|
||||
|
||||
for (unsigned idx = 0; idx < nstmts; idx += 1) {
|
||||
if (!expr(idx)) def_stmt = true;
|
||||
DelayType dt = stat(idx) ? stat(idx)->delay_type() : NO_DELAY;
|
||||
if (idx == 0) {
|
||||
result = stat(idx)->delay_type();
|
||||
result = dt;
|
||||
} else {
|
||||
result = combine_delays(result, stat(idx)->delay_type());
|
||||
result = combine_delays(result, dt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2764,6 +2770,7 @@ DelayType NetCondit::delay_type() const
|
||||
*/
|
||||
DelayType NetDoWhile::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, proc_);
|
||||
return proc_->delay_type();
|
||||
}
|
||||
|
||||
@@ -2774,11 +2781,13 @@ DelayType NetEvWait::delay_type() const
|
||||
|
||||
DelayType NetForever::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return statement_->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetForLoop::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return get_loop_delay_type(condition_, statement_);
|
||||
}
|
||||
|
||||
@@ -2801,6 +2810,7 @@ DelayType NetPDelay::delay_type() const
|
||||
|
||||
DelayType NetRepeat::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return get_loop_delay_type(expr_, statement_);
|
||||
}
|
||||
|
||||
@@ -2816,5 +2826,6 @@ DelayType NetUTask::delay_type() const
|
||||
|
||||
DelayType NetWhile::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, proc_);
|
||||
return get_loop_delay_type(cond_, proc_);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_netlist_H
|
||||
#define IVL_netlist_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -90,6 +90,12 @@ class netvector_t;
|
||||
struct target;
|
||||
struct functor_t;
|
||||
|
||||
#if defined(__cplusplus) && defined(_MSC_VER)
|
||||
# define ENUM_UNSIGNED_INT : unsigned int
|
||||
#else
|
||||
# define ENUM_UNSIGNED_INT
|
||||
#endif
|
||||
|
||||
ostream& operator << (ostream&o, ivl_variable_type_t val);
|
||||
|
||||
extern void join_island(NetPins*obj);
|
||||
@@ -102,8 +108,7 @@ class Link {
|
||||
friend class NexusSet;
|
||||
|
||||
public:
|
||||
enum DIR { PASSIVE, INPUT, OUTPUT };
|
||||
|
||||
enum DIR ENUM_UNSIGNED_INT { PASSIVE, INPUT, OUTPUT };
|
||||
private: // Only NetPins can create/delete Link objects
|
||||
Link();
|
||||
~Link();
|
||||
@@ -619,7 +624,7 @@ class NetDelaySrc : public NetObj {
|
||||
class PortType
|
||||
{
|
||||
public:
|
||||
enum Enum { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
|
||||
enum Enum ENUM_UNSIGNED_INT { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
|
||||
|
||||
/*
|
||||
* Merge Port types (used to construct a sane combined port-type
|
||||
@@ -647,7 +652,7 @@ struct PortInfo
|
||||
class NetNet : public NetObj, public PortType {
|
||||
|
||||
public:
|
||||
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||
enum Type ENUM_UNSIGNED_INT { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
||||
UNRESOLVED_WIRE };
|
||||
|
||||
@@ -765,7 +770,7 @@ class NetNet : public NetObj, public PortType {
|
||||
unsigned peek_eref() const;
|
||||
|
||||
// Assignment statements count their lrefs here. And by
|
||||
// asignment statements, we mean BEHAVIORAL assignments.
|
||||
// assignment statements, we mean BEHAVIORAL assignments.
|
||||
void incr_lref();
|
||||
void decr_lref();
|
||||
unsigned peek_lref() const { return lref_count_; }
|
||||
@@ -918,7 +923,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
/* Create a new scope, and attach it to the given parent. The
|
||||
name is expected to have been permallocated. */
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, bool prog=false);
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false,
|
||||
bool program=false, bool interface=false);
|
||||
~NetScope();
|
||||
|
||||
/* Rename the scope using the name generated by inserting as
|
||||
@@ -1008,8 +1014,9 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
// Nested modules have slightly different scope search rules.
|
||||
inline bool nested_module() const { return nested_module_; }
|
||||
// Program blocks have elaboration constraints.
|
||||
// Program blocks and interfaces have elaboration constraints.
|
||||
inline bool program_block() const { return program_block_; }
|
||||
inline bool is_interface() const { return is_interface_; }
|
||||
TYPE type() const;
|
||||
void print_type(ostream&) const;
|
||||
|
||||
@@ -1221,6 +1228,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
bool nested_module_;
|
||||
// True if the scope is a program block
|
||||
bool program_block_;
|
||||
// True if the scope is an interface
|
||||
bool is_interface_;
|
||||
|
||||
perm_string file_;
|
||||
perm_string def_file_;
|
||||
@@ -1618,9 +1627,10 @@ class NetModulo : public NetNode {
|
||||
class NetFF : public NetNode {
|
||||
|
||||
public:
|
||||
NetFF(NetScope*s, perm_string n, unsigned vector_width);
|
||||
NetFF(NetScope*s, perm_string n, bool negedge, unsigned vector_width);
|
||||
~NetFF();
|
||||
|
||||
bool is_negedge() const;
|
||||
unsigned width() const;
|
||||
|
||||
Link& pin_Clock();
|
||||
@@ -1652,6 +1662,7 @@ class NetFF : public NetNode {
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
bool negedge_;
|
||||
unsigned width_;
|
||||
verinum aset_value_;
|
||||
verinum sset_value_;
|
||||
@@ -2212,7 +2223,7 @@ class NetPartSelect : public NetNode {
|
||||
*
|
||||
* wire [7:0] foo = NetSubstitute(bar, bat, off);
|
||||
*
|
||||
* meaus that bar is a vector the same width as foo, bat is a narrower
|
||||
* means that bar is a vector the same width as foo, bat is a narrower
|
||||
* vector. The off is a constant offset into the bar vector. This
|
||||
* looks something like this:
|
||||
*
|
||||
@@ -2283,7 +2294,7 @@ class NetBUFZ : public NetNode {
|
||||
*
|
||||
* 0 -- Output (always returns 0 or 1)
|
||||
* 1 -- Input
|
||||
* 2 -- Input (windcard input for EQX and EQZ variants)
|
||||
* 2 -- Input (wildcard input for EQX and EQZ variants)
|
||||
*/
|
||||
class NetCaseCmp : public NetNode {
|
||||
|
||||
@@ -2614,8 +2625,10 @@ class NetProc : public virtual LineInfo {
|
||||
// picked off by e.g. condit statements as set/reset inputs to
|
||||
// the flipflop being generated.
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clock, NetBus&ff_ce,
|
||||
NetBus&ff_aclr, NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -2895,8 +2908,10 @@ class NetBlock : public NetProc {
|
||||
NetBus&accumulated_nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -3036,8 +3051,10 @@ class NetCondit : public NetProc {
|
||||
NetBus&accumulated_nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -3313,8 +3330,10 @@ class NetEvWait : public NetProc {
|
||||
NetBus&accumulated_nex_out);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -4747,7 +4766,8 @@ class Design : public Definitions {
|
||||
|
||||
const char* get_flag(const string&key) const;
|
||||
|
||||
NetScope* make_root_scope(perm_string name, bool program_block);
|
||||
NetScope* make_root_scope(perm_string name, bool program_block,
|
||||
bool is_interface);
|
||||
NetScope* find_root_scope();
|
||||
std::list<NetScope*> find_root_scopes() const;
|
||||
|
||||
@@ -4990,4 +5010,5 @@ inline unsigned Link::get_pin() const
|
||||
return pin_;
|
||||
}
|
||||
|
||||
#undef ENUM_UNSIGNED_INT
|
||||
#endif /* IVL_netlist_H */
|
||||
|
||||
+3
-5
@@ -480,8 +480,6 @@ void indices_to_expressions(Design*des, NetScope*scope,
|
||||
const list<index_component_t>&src, unsigned count,
|
||||
// True if the expression MUST be constant.
|
||||
bool need_const,
|
||||
// Total words in target array
|
||||
unsigned need_addr,
|
||||
// These are the outputs.
|
||||
indices_flags&flags,
|
||||
list<NetExpr*>&indices, list<long>&indices_const)
|
||||
@@ -692,7 +690,7 @@ NetExpr* make_canonical_index(Design*des, NetScope*scope,
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, loc,
|
||||
src, src.size(),
|
||||
need_const, stype->static_dimensions().size(),
|
||||
need_const,
|
||||
flags,
|
||||
indices_expr, indices_const);
|
||||
|
||||
@@ -893,7 +891,7 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
}
|
||||
}
|
||||
|
||||
// If the context_width sent is is actually the minimim width,
|
||||
// If the context_width sent is is actually the minimum width,
|
||||
// then raise the context_width to be big enough for the
|
||||
// lossless expression.
|
||||
if (force_expand && context_width > 0) {
|
||||
@@ -1428,7 +1426,7 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, loc, indices,
|
||||
net->packed_dimensions(),
|
||||
false, net->unpacked_count(), flags, exprs, exprs_const);
|
||||
false, flags, exprs, exprs_const);
|
||||
ivl_assert(*loc, exprs.size() == net->packed_dimensions());
|
||||
|
||||
// Special Case: there is only 1 packed dimension, so the
|
||||
|
||||
@@ -181,8 +181,6 @@ extern void indices_to_expressions(Design*des, NetScope*scope,
|
||||
const list<index_component_t>&src, unsigned count,
|
||||
// True if the expression MUST be constant.
|
||||
bool need_const,
|
||||
// Total array size, for sizing expressions
|
||||
unsigned need_addr,
|
||||
// These are the outputs.
|
||||
indices_flags&flags,
|
||||
list<NetExpr*>&indices,list<long>&indices_const);
|
||||
|
||||
@@ -34,6 +34,12 @@ netparray_t::~netparray_t()
|
||||
* The packed width of a packed array is the packed width of the
|
||||
* element times the dimension width of the array itself.
|
||||
*/
|
||||
|
||||
bool netparray_t::packed(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long netparray_t::packed_width(void) const
|
||||
{
|
||||
long cur_width = element_type()->packed_width();
|
||||
|
||||
@@ -64,6 +64,7 @@ class netparray_t : public netsarray_t {
|
||||
|
||||
public:
|
||||
// Virtual methods from the ivl_type_s type...
|
||||
bool packed(void) const;
|
||||
long packed_width(void) const;
|
||||
std::vector<netrange_t> slice_dimensions() const;
|
||||
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL__netqueue_H
|
||||
#define IVL__netqueue_H
|
||||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -38,6 +38,9 @@ class netqueue_t : public netdarray_t {
|
||||
// IVL_VT_QUEUE for queues.
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
||||
// A queue may have a type that is signed.
|
||||
inline bool get_signed() const { return element_type()->get_signed(); }
|
||||
|
||||
std::ostream& debug_dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
||||
|
||||
// Now similarly go through the prefix numbers, working
|
||||
// through the dimensions until we run out. Accumulate a
|
||||
// growing slice width (acc_wid) that is used to caculate the
|
||||
// growing slice width (acc_wid) that is used to calculate the
|
||||
// growing offset (acc_off).
|
||||
list<long>::const_iterator icur = prefix.end();
|
||||
do {
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ class netrange_t {
|
||||
inline netrange_t() : msb_(LONG_MAX), lsb_(LONG_MAX) { }
|
||||
// Create a properly defined netrange
|
||||
inline netrange_t(long m, long l) : msb_(m), lsb_(l) { }
|
||||
// Copy constructure.
|
||||
// Copy constructor.
|
||||
inline netrange_t(const netrange_t&that)
|
||||
: msb_(that.msb_), lsb_(that.lsb_) { }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
|
||||
* Copyright CERN 2012-2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -49,6 +49,16 @@ static struct {
|
||||
data_type_t* data_type;
|
||||
} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT, 0};
|
||||
|
||||
/* Modport port declaration lists use this structure for context. */
|
||||
enum modport_port_type_t { MP_NONE, MP_SIMPLE, MP_TF, MP_CLOCKING };
|
||||
static struct {
|
||||
modport_port_type_t type;
|
||||
union {
|
||||
NetNet::PortType direction;
|
||||
bool is_import;
|
||||
};
|
||||
} last_modport_port = { MP_NONE, {NetNet::NOT_A_PORT}};
|
||||
|
||||
/* The task and function rules need to briefly hold the pointer to the
|
||||
task/function that is currently in progress. */
|
||||
static PTask* current_task = 0;
|
||||
@@ -549,6 +559,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||
%type <flag> from_exclude block_item_decls_opt
|
||||
%type <number> number pos_neg_number
|
||||
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||
%type <flag> import_export
|
||||
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
||||
%type <flag> udp_reg_opt edge_operator
|
||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
@@ -562,8 +573,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||
%type <statement> udp_initial udp_init_opt
|
||||
%type <expr> udp_initial_expr_opt
|
||||
|
||||
%type <text> register_variable net_variable endlabel_opt class_declaration_endlabel_opt
|
||||
%type <perm_strings> register_variable_list net_variable_list
|
||||
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
|
||||
%type <perm_strings> register_variable_list net_variable_list event_variable_list
|
||||
%type <perm_strings> list_of_identifiers loop_variables
|
||||
%type <port_list> list_of_port_identifiers
|
||||
|
||||
@@ -583,7 +594,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||
%type <tf_ports> task_item task_item_list task_item_list_opt
|
||||
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
|
||||
|
||||
%type <named_pexpr> port_name parameter_value_byname
|
||||
%type <named_pexpr> modport_simple_port port_name parameter_value_byname
|
||||
%type <named_pexprs> port_name_list parameter_value_byname_list
|
||||
|
||||
%type <named_pexpr> attribute
|
||||
@@ -739,7 +750,7 @@ class_identifier
|
||||
perm_string name = lex_strings.make($1);
|
||||
class_type_t*tmp = new class_type_t(name);
|
||||
FILE_NAME(tmp, @1);
|
||||
pform_set_typedef(name, tmp);
|
||||
pform_set_typedef(name, tmp, NULL);
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
@@ -1033,7 +1044,11 @@ data_type /* IEEE1800-2005: A.2.2.1 */
|
||||
$$ = tmp;
|
||||
}
|
||||
| struct_data_type
|
||||
{ $$ = $1; }
|
||||
{ if (!$1->packed_flag) {
|
||||
yyerror(@1, "sorry: Unpacked structs not supported.");
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
| enum_data_type
|
||||
{ $$ = $1; }
|
||||
| atom2_type signed_unsigned_opt
|
||||
@@ -1051,7 +1066,7 @@ data_type /* IEEE1800-2005: A.2.2.1 */
|
||||
| K_time
|
||||
{ list<pform_range_t>*pd = make_range_from_width(64);
|
||||
vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, false, pd);
|
||||
tmp->reg_flag = true;
|
||||
tmp->reg_flag = !gn_system_verilog();
|
||||
$$ = tmp;
|
||||
}
|
||||
| TYPE_IDENTIFIER dimensions_opt
|
||||
@@ -1117,8 +1132,8 @@ data_type_or_implicit_or_void
|
||||
statements may go. This may be a bad idea, but it is legacy now. */
|
||||
|
||||
/* NOTE 2: The "module" rule of the description combines the
|
||||
module_declaration and program_declaration rules from the
|
||||
standard description. */
|
||||
module_declaration, program_declaration, and interface_declaration
|
||||
rules from the standard description. */
|
||||
|
||||
description /* IEEE1800-2005: A.1.2 */
|
||||
: module
|
||||
@@ -1142,7 +1157,7 @@ description_list
|
||||
;
|
||||
|
||||
|
||||
/* This implements the [ : INDENTIFIER ] part of the constructure
|
||||
/* This implements the [ : IDENTIFIER ] part of the constructor
|
||||
rule documented in IEEE1800-2005: A.1.8 */
|
||||
endnew_opt : ':' K_new | ;
|
||||
|
||||
@@ -1270,6 +1285,11 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||
|
||||
;
|
||||
|
||||
import_export /* IEEE1800-2012: A.2.9 */
|
||||
: K_import { $$ = true; }
|
||||
| K_export { $$ = false; }
|
||||
;
|
||||
|
||||
implicit_class_handle /* IEEE1800-2005: A.8.4 */
|
||||
: K_this { $$ = pform_create_this(); }
|
||||
| K_super { $$ = pform_create_super(); }
|
||||
@@ -1546,6 +1566,115 @@ method_qualifier_opt
|
||||
|
|
||||
;
|
||||
|
||||
modport_declaration /* IEEE1800-2012: A.2.9 */
|
||||
: K_modport
|
||||
{ if (!pform_in_interface())
|
||||
yyerror(@1, "error: modport declarations are only allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
modport_item_list ';'
|
||||
|
||||
modport_item_list
|
||||
: modport_item
|
||||
| modport_item_list ',' modport_item
|
||||
;
|
||||
|
||||
modport_item
|
||||
: IDENTIFIER
|
||||
{ pform_start_modport_item(@1, $1); }
|
||||
'(' modport_ports_list ')'
|
||||
{ pform_end_modport_item(@1); }
|
||||
;
|
||||
|
||||
/* The modport_ports_list is a LALR(2) grammar. When the parser sees a
|
||||
',' it needs to look ahead to the next token to decide whether it is
|
||||
a continuation of the preceding modport_ports_declaration, or the
|
||||
start of a new modport_ports_declaration. bison only supports LALR(1),
|
||||
so we have to handcraft a mini parser for this part of the syntax.
|
||||
last_modport_port holds the state for this mini parser.*/
|
||||
|
||||
modport_ports_list
|
||||
: modport_ports_declaration
|
||||
| modport_ports_list ',' modport_ports_declaration
|
||||
| modport_ports_list ',' modport_simple_port
|
||||
{ if (last_modport_port.type == MP_SIMPLE) {
|
||||
pform_add_modport_port(@3, last_modport_port.direction,
|
||||
$3->name, $3->parm);
|
||||
} else {
|
||||
yyerror(@3, "error: modport expression not allowed here.");
|
||||
}
|
||||
delete $3;
|
||||
}
|
||||
| modport_ports_list ',' modport_tf_port
|
||||
{ if (last_modport_port.type != MP_TF)
|
||||
yyerror(@3, "error: task/function declaration not allowed here.");
|
||||
}
|
||||
| modport_ports_list ',' IDENTIFIER
|
||||
{ if (last_modport_port.type == MP_SIMPLE) {
|
||||
pform_add_modport_port(@3, last_modport_port.direction,
|
||||
lex_strings.make($3), 0);
|
||||
} else if (last_modport_port.type != MP_TF) {
|
||||
yyerror(@3, "error: list of identifiers not allowed here.");
|
||||
}
|
||||
delete[] $3;
|
||||
}
|
||||
| modport_ports_list ','
|
||||
{ yyerror(@2, "error: NULL port declarations are not allowed"); }
|
||||
;
|
||||
|
||||
modport_ports_declaration
|
||||
: attribute_list_opt port_direction IDENTIFIER
|
||||
{ last_modport_port.type = MP_SIMPLE;
|
||||
last_modport_port.direction = $2;
|
||||
pform_add_modport_port(@3, $2, lex_strings.make($3), 0);
|
||||
delete[] $3;
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt port_direction modport_simple_port
|
||||
{ last_modport_port.type = MP_SIMPLE;
|
||||
last_modport_port.direction = $2;
|
||||
pform_add_modport_port(@3, $2, $3->name, $3->parm);
|
||||
delete $3;
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt import_export IDENTIFIER
|
||||
{ last_modport_port.type = MP_TF;
|
||||
last_modport_port.is_import = $2;
|
||||
yyerror(@3, "sorry: modport task/function ports are not yet supported.");
|
||||
delete[] $3;
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt import_export modport_tf_port
|
||||
{ last_modport_port.type = MP_TF;
|
||||
last_modport_port.is_import = $2;
|
||||
yyerror(@3, "sorry: modport task/function ports are not yet supported.");
|
||||
delete $1;
|
||||
}
|
||||
| attribute_list_opt K_clocking IDENTIFIER
|
||||
{ last_modport_port.type = MP_CLOCKING;
|
||||
last_modport_port.direction = NetNet::NOT_A_PORT;
|
||||
yyerror(@3, "sorry: modport clocking declaration is not yet supported.");
|
||||
delete[] $3;
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
|
||||
modport_simple_port
|
||||
: '.' IDENTIFIER '(' expression ')'
|
||||
{ named_pexpr_t*tmp = new named_pexpr_t;
|
||||
tmp->name = lex_strings.make($2);
|
||||
tmp->parm = $4;
|
||||
delete[]$2;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
modport_tf_port
|
||||
: K_task IDENTIFIER
|
||||
| K_task IDENTIFIER '(' tf_port_list_opt ')'
|
||||
| K_function data_type_or_implicit_or_void IDENTIFIER
|
||||
| K_function data_type_or_implicit_or_void IDENTIFIER '(' tf_port_list_opt ')'
|
||||
;
|
||||
|
||||
non_integer_type /* IEEE1800-2005: A.2.2.1 */
|
||||
: K_real { $$ = real_type_t::REAL; }
|
||||
@@ -1667,7 +1796,7 @@ property_expr /* IEEE1800-2012 A.2.10 */
|
||||
|
||||
/* The property_qualifier rule is as literally described in the LRM,
|
||||
but the use is usually as { property_qualifier }, which is
|
||||
implemented bt the property_qualifier_opt rule below. */
|
||||
implemented by the property_qualifier_opt rule below. */
|
||||
|
||||
property_qualifier /* IEEE1800-2005 A.1.8 */
|
||||
: class_item_qualifier
|
||||
@@ -1972,7 +2101,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
||||
} else {
|
||||
// Otherwise, the decorations for this identifier
|
||||
// indicate the type. Save the type for any right
|
||||
// context thta may come later.
|
||||
// context that may come later.
|
||||
port_declaration_context.port_type = use_port_type;
|
||||
if ($2 == 0) {
|
||||
$2 = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
||||
@@ -1990,7 +2119,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
||||
assert(tmp->size()==1);
|
||||
tmp->front().defe = $5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rules to match error cases... */
|
||||
|
||||
@@ -2004,8 +2133,14 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
||||
/* This rule matches the [ = <expression> ] part of the tf_port_item rules. */
|
||||
|
||||
tf_port_item_expr_opt
|
||||
: '=' expression { $$ = $2; }
|
||||
| { $$ = 0; }
|
||||
: '=' expression
|
||||
{ if (! gn_system_verilog()) {
|
||||
yyerror(@1, "error: Task/function default arguments require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
$$ = $2;
|
||||
}
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
tf_port_list /* IEEE1800-2005: A.2.7 */
|
||||
@@ -2186,8 +2321,8 @@ block_item_decl
|
||||
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||
}
|
||||
|
||||
| K_event list_of_identifiers ';'
|
||||
{ pform_make_events($2, @1.text, @1.first_line);
|
||||
| K_event event_variable_list ';'
|
||||
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
||||
}
|
||||
|
||||
| K_parameter param_type parameter_assign_list ';'
|
||||
@@ -2233,9 +2368,9 @@ block_item_decls_opt
|
||||
/* Type declarations are parsed here. The rule actions call pform
|
||||
functions that add the declaration to the current lexical scope. */
|
||||
type_declaration
|
||||
: K_typedef data_type IDENTIFIER ';'
|
||||
: K_typedef data_type IDENTIFIER dimensions_opt ';'
|
||||
{ perm_string name = lex_strings.make($3);
|
||||
pform_set_typedef(name, $2);
|
||||
pform_set_typedef(name, $2, $4);
|
||||
delete[]$3;
|
||||
}
|
||||
|
||||
@@ -2248,7 +2383,7 @@ type_declaration
|
||||
yyerror(@3, "error: Typedef identifier \"%s\" is already a type name.", $3.text);
|
||||
|
||||
} else {
|
||||
pform_set_typedef(name, $2);
|
||||
pform_set_typedef(name, $2, NULL);
|
||||
}
|
||||
delete[]$3.text;
|
||||
}
|
||||
@@ -2261,7 +2396,7 @@ type_declaration
|
||||
perm_string name = lex_strings.make($3);
|
||||
class_type_t*tmp = new class_type_t(name);
|
||||
FILE_NAME(tmp, @3);
|
||||
pform_set_typedef(name, tmp);
|
||||
pform_set_typedef(name, tmp, NULL);
|
||||
delete[]$3;
|
||||
}
|
||||
| K_typedef K_enum IDENTIFIER ';'
|
||||
@@ -2276,7 +2411,7 @@ type_declaration
|
||||
perm_string name = lex_strings.make($2);
|
||||
class_type_t*tmp = new class_type_t(name);
|
||||
FILE_NAME(tmp, @2);
|
||||
pform_set_typedef(name, tmp);
|
||||
pform_set_typedef(name, tmp, NULL);
|
||||
delete[]$2;
|
||||
}
|
||||
|
||||
@@ -2323,34 +2458,34 @@ enum_data_type
|
||||
enum_type->range.reset(make_range_from_width(integer_width));
|
||||
$$ = enum_type;
|
||||
}
|
||||
| K_enum K_logic unsigned_signed_opt dimensions '{' enum_name_list '}'
|
||||
| K_enum K_logic unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
|
||||
{ enum_type_t*enum_type = new enum_type_t;
|
||||
FILE_NAME(enum_type, @1);
|
||||
enum_type->names .reset($6);
|
||||
enum_type->base_type = IVL_VT_LOGIC;
|
||||
enum_type->signed_flag = $3;
|
||||
enum_type->integer_flag = false;
|
||||
enum_type->range.reset($4);
|
||||
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
|
||||
$$ = enum_type;
|
||||
}
|
||||
| K_enum K_reg unsigned_signed_opt dimensions '{' enum_name_list '}'
|
||||
| K_enum K_reg unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
|
||||
{ enum_type_t*enum_type = new enum_type_t;
|
||||
FILE_NAME(enum_type, @1);
|
||||
enum_type->names .reset($6);
|
||||
enum_type->base_type = IVL_VT_LOGIC;
|
||||
enum_type->signed_flag = $3;
|
||||
enum_type->integer_flag = false;
|
||||
enum_type->range.reset($4);
|
||||
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
|
||||
$$ = enum_type;
|
||||
}
|
||||
| K_enum K_bit unsigned_signed_opt dimensions '{' enum_name_list '}'
|
||||
| K_enum K_bit unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
|
||||
{ enum_type_t*enum_type = new enum_type_t;
|
||||
FILE_NAME(enum_type, @1);
|
||||
enum_type->names .reset($6);
|
||||
enum_type->base_type = IVL_VT_BOOL;
|
||||
enum_type->signed_flag = $3;
|
||||
enum_type->integer_flag = false;
|
||||
enum_type->range.reset($4);
|
||||
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
|
||||
$$ = enum_type;
|
||||
}
|
||||
;
|
||||
@@ -3210,6 +3345,22 @@ expr_primary
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| TIME_LITERAL
|
||||
{ int unit;
|
||||
|
||||
based_size = 0;
|
||||
$$ = 0;
|
||||
if ($1 == 0 || !get_time_unit($1, unit))
|
||||
yyerror(@1, "internal error: delay.");
|
||||
else {
|
||||
double p = pow(10.0, (double)(unit - pform_get_timeunit()));
|
||||
double time = atof($1) * p;
|
||||
|
||||
verireal *v = new verireal(time);
|
||||
$$ = new PEFNumber(v);
|
||||
FILE_NAME($$, @1);
|
||||
}
|
||||
}
|
||||
| SYSTEM_IDENTIFIER
|
||||
{ perm_string tn = lex_strings.make($1);
|
||||
PECallFunction*tmp = new PECallFunction(tn);
|
||||
@@ -3244,7 +3395,7 @@ expr_primary
|
||||
|
||||
/* An identifier followed by an expression list in parentheses is a
|
||||
function call. If a system identifier, then a system function
|
||||
call. It can also be a call to a class method (functino). */
|
||||
call. It can also be a call to a class method (function). */
|
||||
|
||||
| hierarchy_identifier '(' expression_list_with_nuls ')'
|
||||
{ list<PExpr*>*expr_list = $3;
|
||||
@@ -4018,6 +4169,9 @@ port_declaration
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
} else if (dynamic_cast<struct_type_t*> ($4)) {
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
} else if (enum_type_t*etype = dynamic_cast<enum_type_t*> ($4)) {
|
||||
if(etype->base_type == IVL_VT_LOGIC)
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
}
|
||||
}
|
||||
ptmp = pform_module_port_reference(name, @2.text, @2.first_line);
|
||||
@@ -4213,13 +4367,13 @@ local_timeunit_prec_decl2
|
||||
}
|
||||
;
|
||||
|
||||
/* This is the global structure of a module. A module in a start
|
||||
/* This is the global structure of a module. A module is a start
|
||||
section, with optional ports, then an optional list of module
|
||||
items, and finally an end marker. */
|
||||
|
||||
module
|
||||
: attribute_list_opt module_start IDENTIFIER
|
||||
{ pform_startmodule(@2, $3, $2==K_program, $1); }
|
||||
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
|
||||
module_package_import_list_opt
|
||||
module_parameter_port_list_opt
|
||||
module_port_list_opt
|
||||
@@ -4258,6 +4412,9 @@ module
|
||||
case K_program:
|
||||
yyerror(@14, "error: program not closed by endprogram.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@14, "error: interface not closed by endinterface.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -4283,6 +4440,10 @@ module
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
"program name.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
"interface name.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -4297,19 +4458,21 @@ module
|
||||
}
|
||||
;
|
||||
|
||||
/* Modules start with module/macromodule or program keyword, and end
|
||||
with the endmodule or endprogram keyword. The syntax for modules
|
||||
and programs is almost identical, so let semantics sort out the
|
||||
differences. */
|
||||
/* Modules start with a module/macromodule, program, or interface
|
||||
keyword, and end with a endmodule, endprogram, or endinterface
|
||||
keyword. The syntax for modules programs, and interfaces is
|
||||
almost identical, so let semantics sort out the differences. */
|
||||
module_start
|
||||
: K_module { $$ = K_module; }
|
||||
| K_macromodule { $$ = K_module; }
|
||||
| K_program { $$ = K_program; }
|
||||
| K_interface { $$ = K_interface; }
|
||||
;
|
||||
|
||||
module_end
|
||||
: K_endmodule { $$ = K_module; }
|
||||
| K_endprogram { $$ = K_program; }
|
||||
: K_endmodule { $$ = K_module; }
|
||||
| K_endprogram { $$ = K_program; }
|
||||
| K_endinterface { $$ = K_interface; }
|
||||
;
|
||||
|
||||
endlabel_opt
|
||||
@@ -4395,8 +4558,8 @@ module_item
|
||||
}
|
||||
pform_makewire(@2, $4, str_strength, $5, $2, data_type);
|
||||
if ($1) {
|
||||
yyerror(@2, "sorry: Attributes not supported "
|
||||
"on net declaration assignments.");
|
||||
yywarn(@2, "Attributes are not supported on net declaration "
|
||||
"assignments and will be discarded.");
|
||||
delete $1;
|
||||
}
|
||||
}
|
||||
@@ -4412,8 +4575,8 @@ module_item
|
||||
}
|
||||
pform_makewire(@2, 0, $4, $5, $2, data_type);
|
||||
if ($1) {
|
||||
yyerror(@2, "sorry: Attributes not supported "
|
||||
"on net declaration assignments.");
|
||||
yywarn(@2, "Attributes are not supported on net declaration "
|
||||
"assignments and will be discarded.");
|
||||
delete $1;
|
||||
}
|
||||
}
|
||||
@@ -4422,8 +4585,8 @@ module_item
|
||||
{ real_type_t*data_type = new real_type_t(real_type_t::REAL);
|
||||
pform_makewire(@2, 0, str_strength, $3, NetNet::WIRE, data_type);
|
||||
if ($1) {
|
||||
yyerror(@2, "sorry: Attributes not supported "
|
||||
"on net declaration assignments.");
|
||||
yywarn(@2, "Attributes are not supported on net declaration "
|
||||
"assignments and will be discarded.");
|
||||
delete $1;
|
||||
}
|
||||
}
|
||||
@@ -4505,7 +4668,12 @@ module_item
|
||||
|
||||
/* */
|
||||
|
||||
| K_defparam defparam_assign_list ';'
|
||||
| K_defparam
|
||||
{ if (pform_in_interface())
|
||||
yyerror(@1, "error: Parameter overrides are not allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
defparam_assign_list ';'
|
||||
|
||||
/* Most gate types have an optional drive strength and optional
|
||||
two/three-value delay. These rules handle the different cases.
|
||||
@@ -4614,7 +4782,7 @@ module_item
|
||||
generate/endgenerate regions do not nest. Generate schemes nest,
|
||||
but generate regions do not. */
|
||||
|
||||
| K_generate module_item_list_opt K_endgenerate
|
||||
| K_generate generate_item_list_opt K_endgenerate
|
||||
{ // Test for bad nesting. I understand it, but it is illegal.
|
||||
if (pform_parent_generate()) {
|
||||
cerr << @1 << ": error: Generate/endgenerate regions cannot nest." << endl;
|
||||
@@ -4651,44 +4819,32 @@ module_item
|
||||
K_endcase
|
||||
{ pform_endgenerate(); }
|
||||
|
||||
/* Handle some anachronistic syntax cases. */
|
||||
| K_generate K_begin module_item_list_opt K_end K_endgenerate
|
||||
{ /* Detect and warn about anachronistic begin/end use */
|
||||
if (generation_flag > GN_VER2001 && warn_anachronisms) {
|
||||
warn_count += 1;
|
||||
cerr << @2 << ": warning: Anachronistic use of begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
}
|
||||
| K_generate K_begin ':' IDENTIFIER {
|
||||
pform_start_generate_nblock(@2, $4);
|
||||
} module_item_list_opt K_end K_endgenerate
|
||||
{ /* Detect and warn about anachronistic named begin/end use */
|
||||
if (generation_flag > GN_VER2001 && warn_anachronisms) {
|
||||
warn_count += 1;
|
||||
cerr << @2 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
pform_endgenerate();
|
||||
}
|
||||
| modport_declaration
|
||||
|
||||
| package_import_declaration
|
||||
|
||||
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
|
||||
|
||||
| attribute_list_opt K_specparam specparam_decl ';'
|
||||
| attribute_list_opt K_specparam
|
||||
{ if (pform_in_interface())
|
||||
yyerror(@1, "error: specparam declarations are not allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
specparam_decl ';'
|
||||
|
||||
/* specify blocks are parsed but ignored. */
|
||||
|
||||
| K_specify K_endspecify
|
||||
{ /* empty lists are legal syntax. */ }
|
||||
| K_specify
|
||||
{ if (pform_in_interface())
|
||||
yyerror(@1, "error: specify blocks are not allowed "
|
||||
"in interfaces.");
|
||||
}
|
||||
specify_item_list_opt K_endspecify
|
||||
|
||||
| K_specify specify_item_list K_endspecify
|
||||
{
|
||||
}
|
||||
|
||||
| K_specify error K_endspecify
|
||||
{ yyerror(@1, "error: syntax error in specify block");
|
||||
yyerrok;
|
||||
}
|
||||
| K_specify error K_endspecify
|
||||
{ yyerror(@1, "error: syntax error in specify block");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
/* These rules match various errors that the user can type into
|
||||
module items. These rules try to catch them at a point where a
|
||||
@@ -4747,6 +4903,16 @@ module_item
|
||||
{ pform_set_timeprecision($2, true, true); }
|
||||
;
|
||||
|
||||
module_item_list
|
||||
: module_item_list module_item
|
||||
| module_item
|
||||
;
|
||||
|
||||
module_item_list_opt
|
||||
: module_item_list
|
||||
|
|
||||
;
|
||||
|
||||
generate_if : K_if '(' expression ')' { pform_start_generate_if(@1, $3); } ;
|
||||
|
||||
generate_case_items
|
||||
@@ -4761,15 +4927,37 @@ generate_case_item
|
||||
{ pform_endgenerate(); }
|
||||
;
|
||||
|
||||
module_item_list
|
||||
: module_item_list module_item
|
||||
| module_item
|
||||
;
|
||||
generate_item
|
||||
: module_item
|
||||
/* Handle some anachronistic syntax cases. */
|
||||
| K_begin generate_item_list_opt K_end
|
||||
{ /* Detect and warn about anachronistic begin/end use */
|
||||
if (generation_flag > GN_VER2001 && warn_anachronisms) {
|
||||
warn_count += 1;
|
||||
cerr << @1 << ": warning: Anachronistic use of begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
}
|
||||
| K_begin ':' IDENTIFIER {
|
||||
pform_start_generate_nblock(@1, $3);
|
||||
} generate_item_list_opt K_end
|
||||
{ /* Detect and warn about anachronistic named begin/end use */
|
||||
if (generation_flag > GN_VER2001 && warn_anachronisms) {
|
||||
warn_count += 1;
|
||||
cerr << @1 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
pform_endgenerate();
|
||||
}
|
||||
;
|
||||
|
||||
module_item_list_opt
|
||||
: module_item_list
|
||||
|
|
||||
;
|
||||
generate_item_list
|
||||
: generate_item_list generate_item
|
||||
| generate_item
|
||||
;
|
||||
|
||||
generate_item_list_opt
|
||||
: generate_item_list
|
||||
|
|
||||
;
|
||||
|
||||
/* A generate block is the thing within a generate scheme. It may be
|
||||
a single module item, an anonymous block of module items, or a
|
||||
@@ -4778,24 +4966,24 @@ module_item_list_opt
|
||||
only need to take note here of the scope name, if any. */
|
||||
|
||||
generate_block
|
||||
: module_item
|
||||
| K_begin module_item_list_opt K_end
|
||||
| K_begin ':' IDENTIFIER module_item_list_opt K_end endlabel_opt
|
||||
{ pform_generate_block_name($3);
|
||||
if ($6) {
|
||||
if (strcmp($3,$6) != 0) {
|
||||
yyerror(@6, "error: End label doesn't match "
|
||||
"begin name");
|
||||
}
|
||||
if (! gn_system_verilog()) {
|
||||
yyerror(@6, "error: Begin end labels require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$6;
|
||||
}
|
||||
delete[]$3;
|
||||
}
|
||||
;
|
||||
: module_item
|
||||
| K_begin generate_item_list_opt K_end
|
||||
| K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt
|
||||
{ pform_generate_block_name($3);
|
||||
if ($6) {
|
||||
if (strcmp($3,$6) != 0) {
|
||||
yyerror(@6, "error: End label doesn't match "
|
||||
"begin name");
|
||||
}
|
||||
if (! gn_system_verilog()) {
|
||||
yyerror(@6, "error: Begin end labels require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$6;
|
||||
}
|
||||
delete[]$3;
|
||||
}
|
||||
;
|
||||
|
||||
generate_block_opt : generate_block | ';' ;
|
||||
|
||||
@@ -5338,6 +5526,23 @@ net_variable_list
|
||||
}
|
||||
;
|
||||
|
||||
event_variable
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ if ($2) {
|
||||
yyerror(@2, "sorry: event arrays are not supported.");
|
||||
delete $2;
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
event_variable_list
|
||||
: event_variable
|
||||
{ $$ = list_from_identifier($1); }
|
||||
| event_variable_list ',' event_variable
|
||||
{ $$ = list_from_identifier($1, $3); }
|
||||
;
|
||||
|
||||
specify_item
|
||||
: K_specparam specparam_decl ';'
|
||||
| specify_simple_path_decl ';'
|
||||
@@ -5450,6 +5655,12 @@ specify_item_list
|
||||
| specify_item_list specify_item
|
||||
;
|
||||
|
||||
specify_item_list_opt
|
||||
: /* empty */
|
||||
{ }
|
||||
| specify_item_list
|
||||
{ }
|
||||
|
||||
specify_edge_path_decl
|
||||
: specify_edge_path '=' '(' delay_value_list ')'
|
||||
{ $$ = pform_assign_path_delay($1, $4); }
|
||||
@@ -5926,7 +6137,7 @@ statement_item /* This is roughly statement_item in the LRM */
|
||||
{ yyerror(@1, "error: Malformed conditional expression.");
|
||||
$$ = $5;
|
||||
}
|
||||
/* SytemVerilog adds the compressed_statement */
|
||||
/* SystemVerilog adds the compressed_statement */
|
||||
|
||||
| compressed_statement ';'
|
||||
{ $$ = $1; }
|
||||
@@ -6566,7 +6777,7 @@ udp_primitive
|
||||
presence is significant. This is a fairly common pattern so
|
||||
collect those rules here. */
|
||||
|
||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false;} ;
|
||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
|
||||
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -29,6 +29,7 @@
|
||||
# include "PPackage.h"
|
||||
# include "PUdp.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PModport.h"
|
||||
# include "PSpec.h"
|
||||
# include "discipline.h"
|
||||
# include <list>
|
||||
@@ -265,6 +266,10 @@ static unsigned scope_generate_counter = 1;
|
||||
always within a module. */
|
||||
static PGenerate*pform_cur_generate = 0;
|
||||
|
||||
/* This tracks the current modport list being processed. This is
|
||||
always within an interface. */
|
||||
static PModport*pform_cur_modport = 0;
|
||||
|
||||
static NetNet::Type pform_default_nettype = NetNet::WIRE;
|
||||
|
||||
/*
|
||||
@@ -534,6 +539,15 @@ bool pform_in_program_block()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pform_in_interface()
|
||||
{
|
||||
if (pform_cur_module.empty())
|
||||
return false;
|
||||
if (pform_cur_module.front()->is_interface)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pform_at_module_level()
|
||||
{
|
||||
return (lexical_scope == pform_cur_module.front())
|
||||
@@ -579,8 +593,11 @@ PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetN
|
||||
return cur;
|
||||
}
|
||||
|
||||
void pform_set_typedef(perm_string name, data_type_t*data_type)
|
||||
void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_range_t>*unp_ranges)
|
||||
{
|
||||
if(unp_ranges)
|
||||
data_type = new uarray_type_t(data_type, unp_ranges);
|
||||
|
||||
// If we are in a lexical scope (i.e. a package or module)
|
||||
// then put the typedef into that scope. Otherwise, put it
|
||||
// into the $root scope.
|
||||
@@ -1062,6 +1079,12 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||
assert(siz->is_defined());
|
||||
unsigned long size = siz->as_ulong();
|
||||
|
||||
if (size == 0) {
|
||||
cerr << file << ":" << lineno << ": error: Sized numeric constant "
|
||||
"must have a size greater than zero." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
verinum::V pad;
|
||||
|
||||
switch (val->get(val->len()-1)) {
|
||||
@@ -1107,7 +1130,8 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||
}
|
||||
|
||||
void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
bool program_block, list<named_pexpr_t>*attr)
|
||||
bool program_block, bool is_interface,
|
||||
list<named_pexpr_t>*attr)
|
||||
{
|
||||
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
||||
cerr << loc << ": error: Module definition " << name
|
||||
@@ -1115,15 +1139,25 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
if (gn_system_verilog() && ! pform_cur_module.empty() &&
|
||||
pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: Program blocks cannot contain nested modules/program blocks." << endl;
|
||||
error_count += 1;
|
||||
if (gn_system_verilog() && ! pform_cur_module.empty()) {
|
||||
if (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: module, program, or interface "
|
||||
"declarations are not allowed in program "
|
||||
"blocks." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (pform_cur_module.front()->is_interface
|
||||
&& !(program_block || is_interface)) {
|
||||
cerr << loc << ": error: module declarations are not "
|
||||
"allowed in interfaces." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string lex_name = lex_strings.make(name);
|
||||
Module*cur_module = new Module(lexical_scope, lex_name);
|
||||
cur_module->program_block = program_block;
|
||||
cur_module->is_interface = is_interface;
|
||||
/* Set the local time unit/precision to the global value. */
|
||||
cur_module->time_unit = pform_time_unit;
|
||||
cur_module->time_precision = pform_time_prec;
|
||||
@@ -1914,7 +1948,6 @@ static void pform_set_net_range(list<perm_string>*names,
|
||||
pform_set_net_range(txt, net_type, range, signed_flag, dt, SR_NET, attr);
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2001,8 +2034,13 @@ void pform_makegates(const struct vlltype&loc,
|
||||
{
|
||||
assert(! pform_cur_module.empty());
|
||||
if (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: Gates and switches may not be instantiated"
|
||||
<< " in program blocks." << endl;
|
||||
cerr << loc << ": error: Gates and switches may not be instantiated in "
|
||||
<< "program blocks." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (pform_cur_module.front()->is_interface) {
|
||||
cerr << loc << ": error: Gates and switches may not be instantiated in "
|
||||
<< "interfaces." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
@@ -2117,8 +2155,13 @@ void pform_make_modgates(const struct vlltype&loc,
|
||||
{
|
||||
assert(! pform_cur_module.empty());
|
||||
if (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: Module instantiations are not allowed"
|
||||
<< " in program blocks." << endl;
|
||||
cerr << loc << ": error: Module instantiations are not allowed in "
|
||||
<< "program blocks." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
if (pform_cur_module.front()->is_interface) {
|
||||
cerr << loc << ": error: Module instantiations are not allowed in "
|
||||
<< "interfaces." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
@@ -2317,6 +2360,11 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
signed_flag = false;
|
||||
prange = 0;
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(vtype)) {
|
||||
data_type = enum_type->base_type;
|
||||
signed_flag = enum_type->signed_flag;
|
||||
prange = enum_type->range.get();
|
||||
|
||||
} else if (vtype) {
|
||||
VLerror(li, "sorry: Given type %s not supported here (%s:%d).",
|
||||
typeid(*vtype).name(), __FILE__, __LINE__);
|
||||
@@ -2374,7 +2422,11 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name,
|
||||
ivl_variable_type_t dtype)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur) {
|
||||
|
||||
// If the wire already exists but isn't yet fully defined,
|
||||
// carry on adding details.
|
||||
if (cur && (cur->get_data_type() == IVL_VT_NO_TYPE ||
|
||||
cur->get_wire_type() == NetNet::IMPLICIT) ) {
|
||||
// If this is not implicit ("implicit" meaning we don't
|
||||
// know what the type is yet) then set the type now.
|
||||
if (type != NetNet::IMPLICIT) {
|
||||
@@ -2392,6 +2444,18 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name,
|
||||
return cur;
|
||||
}
|
||||
|
||||
// If the wire already exists and is fully defined, this
|
||||
// must be a redeclaration. Start again with a new wire.
|
||||
if (cur) {
|
||||
LineInfo tloc;
|
||||
FILE_NAME(&tloc, li);
|
||||
cerr << tloc.get_fileline() << ": error: duplicate declaration "
|
||||
"for net or variable '" << name << "' in '"
|
||||
<< pform_cur_module.front()->mod_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
delete cur;
|
||||
}
|
||||
|
||||
cur = new PWire(name, type, ptype, dtype);
|
||||
FILE_NAME(cur, li.text, li.first_line);
|
||||
|
||||
@@ -2527,6 +2591,15 @@ void pform_makewire(const struct vlltype&li,
|
||||
NetNet::Type type,
|
||||
data_type_t*data_type)
|
||||
{
|
||||
if ((lexical_scope == 0) && (generation_flag < GN_VER2005_SV)) {
|
||||
VLerror(li, "error: variable declarations must be contained within a module.");
|
||||
return;
|
||||
}
|
||||
if (lexical_scope == 0) {
|
||||
VLerror(li, "sorry: variable declarations in the $root scope are not yet supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
list<perm_string>*names = new list<perm_string>;
|
||||
|
||||
for (list<decl_assignment_t*>::iterator cur = assign_list->begin()
|
||||
@@ -2613,7 +2686,10 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
}
|
||||
|
||||
curw->set_signed(signed_flag);
|
||||
if (isint) assert(curw->set_wire_type(NetNet::INTEGER));
|
||||
if (isint) {
|
||||
bool flag = curw->set_wire_type(NetNet::INTEGER);
|
||||
assert(flag);
|
||||
}
|
||||
|
||||
/* If there is a range involved, it needs to be set. */
|
||||
if (range) {
|
||||
@@ -2624,7 +2700,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
}
|
||||
|
||||
delete range;
|
||||
delete names;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2653,7 +2728,6 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
||||
|
||||
res->push_back(pform_tf_port_t(curw));
|
||||
}
|
||||
delete names;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2662,35 +2736,54 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
data_type_t*vtype,
|
||||
list<perm_string>*names)
|
||||
{
|
||||
vector<pform_tf_port_t>*ret = NULL;
|
||||
std::list<pform_range_t>*unpacked_dims = NULL;
|
||||
|
||||
if (uarray_type_t*uarray = dynamic_cast<uarray_type_t*> (vtype)) {
|
||||
unpacked_dims = uarray->dims.get();
|
||||
vtype = uarray->base_type;
|
||||
}
|
||||
|
||||
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
|
||||
list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code);
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL,
|
||||
atype->signed_flag,
|
||||
range_tmp, names);
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, vec_type->base_type,
|
||||
ret = pform_make_task_ports(loc, pt, vec_type->base_type,
|
||||
vec_type->signed_flag,
|
||||
copy_range(vec_type->pdims.get()),
|
||||
names, vec_type->integer_flag);
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_REAL,
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_REAL,
|
||||
true, 0, names);
|
||||
}
|
||||
|
||||
if (dynamic_cast<string_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_STRING,
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_STRING,
|
||||
false, 0, names);
|
||||
}
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
|
||||
return do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
|
||||
}
|
||||
|
||||
return do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
|
||||
|
||||
if (unpacked_dims) {
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(*cur);
|
||||
wire->set_unpacked_idx(*unpacked_dims);
|
||||
}
|
||||
}
|
||||
|
||||
delete names;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2803,6 +2896,14 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||
LexicalScope::range_t*value_range)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
if ((scope == 0) && (generation_flag < GN_VER2005_SV)) {
|
||||
VLerror(loc, "error: parameter declarations must be contained within a module.");
|
||||
return;
|
||||
}
|
||||
if (scope == 0) {
|
||||
VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported.");
|
||||
return;
|
||||
}
|
||||
if (scope == pform_cur_generate) {
|
||||
VLerror("parameter declarations are not permitted in generate blocks");
|
||||
return;
|
||||
@@ -2826,8 +2927,8 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||
error_count += 1;
|
||||
}
|
||||
// Only a Module scope has specparams.
|
||||
if ((scope == pform_cur_module.front()) &&
|
||||
(dynamic_cast<Module*> (scope)) &&
|
||||
if ((dynamic_cast<Module*> (scope)) &&
|
||||
(scope == pform_cur_module.front()) &&
|
||||
(pform_cur_module.front()->specparams.find(name) !=
|
||||
pform_cur_module.front()->specparams.end())) {
|
||||
LineInfo tloc;
|
||||
@@ -2860,8 +2961,8 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||
parm.range = value_range;
|
||||
|
||||
// Only a Module keeps the position of the parameter.
|
||||
if ((scope == pform_cur_module.front()) &&
|
||||
(dynamic_cast<Module*> (scope)))
|
||||
if ((dynamic_cast<Module*> (scope)) &&
|
||||
(scope == pform_cur_module.front()))
|
||||
pform_cur_module.front()->param_names.push_back(name);
|
||||
}
|
||||
|
||||
@@ -2870,7 +2971,14 @@ void pform_set_localparam(const struct vlltype&loc,
|
||||
bool signed_flag, list<pform_range_t>*range, PExpr*expr)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
ivl_assert(loc, scope);
|
||||
if ((scope == 0) && (generation_flag < GN_VER2005_SV)) {
|
||||
VLerror(loc, "error: localparam declarations must be contained within a module.");
|
||||
return;
|
||||
}
|
||||
if (scope == 0) {
|
||||
VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the localparam name is already in the dictionary.
|
||||
if (scope->localparams.find(name) != scope->localparams.end()) {
|
||||
@@ -3136,7 +3244,6 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_
|
||||
perm_string txt = *cur;
|
||||
pform_set_integer_2atom(width, signed_flag, txt, net_type, attr);
|
||||
}
|
||||
delete names;
|
||||
}
|
||||
|
||||
template <class T> static void pform_set2_data_type(const struct vlltype&li, T*data_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
|
||||
@@ -3160,18 +3267,12 @@ template <class T> static void pform_set2_data_type(const struct vlltype&li, T*d
|
||||
}
|
||||
}
|
||||
|
||||
static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
static void pform_set_enum(enum_type_t*enum_type,
|
||||
perm_string name, NetNet::Type net_type,
|
||||
std::list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, enum_type->base_type);
|
||||
// A NULL is returned for a duplicate enumeration.
|
||||
if (! cur) {
|
||||
cerr << li.get_fileline() << ": error: Found duplicate "
|
||||
<< "enumeration named " << name << "." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
assert(cur);
|
||||
|
||||
cur->set_signed(enum_type->signed_flag);
|
||||
|
||||
@@ -3209,10 +3310,9 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_enum(li, enum_type, txt, net_type, attr);
|
||||
pform_set_enum(enum_type, txt, net_type, attr);
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3221,58 +3321,68 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
*/
|
||||
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
|
||||
{
|
||||
const std::list<pform_range_t>*unpacked_dims = NULL;
|
||||
|
||||
if (data_type == 0) {
|
||||
VLerror(li, "internal error: data_type==0.");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if(uarray_type_t*uarray_type = dynamic_cast<uarray_type_t*> (data_type)) {
|
||||
unpacked_dims = uarray_type->dims.get();
|
||||
data_type = uarray_type->base_type;
|
||||
}
|
||||
|
||||
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
|
||||
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
|
||||
else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
|
||||
pform_set_struct_type(struct_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
|
||||
else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
|
||||
pform_set_enum(li, enum_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
|
||||
else if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
|
||||
if (net_type==NetNet::REG && vec_type->integer_flag)
|
||||
net_type=NetNet::INTEGER;
|
||||
|
||||
pform_set_net_range(names, vec_type->pdims.get(),
|
||||
vec_type->signed_flag,
|
||||
vec_type->base_type, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
|
||||
else if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
|
||||
pform_set_net_range(names, 0, true, IVL_VT_REAL, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
|
||||
else if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
|
||||
pform_set_class_type(class_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
|
||||
else if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
|
||||
pform_set2_data_type(li, array_type, names, net_type, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
|
||||
else if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
|
||||
pform_set_string_type(string_type, names, net_type, attr);
|
||||
return;
|
||||
|
||||
} else {
|
||||
VLerror(li, "internal error: Unexpected data_type.");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
VLerror(li, "internal error: Unexpected data_type.");
|
||||
assert(0);
|
||||
if(unpacked_dims) {
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(*cur);
|
||||
wire->set_unpacked_idx(*unpacked_dims);
|
||||
}
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
vector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
@@ -3326,6 +3436,46 @@ PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
|
||||
return pp;
|
||||
}
|
||||
|
||||
void pform_start_modport_item(const struct vlltype&loc, const char*name)
|
||||
{
|
||||
Module*scope = pform_cur_module.front();
|
||||
ivl_assert(loc, scope && scope->is_interface);
|
||||
ivl_assert(loc, pform_cur_modport == 0);
|
||||
|
||||
perm_string use_name = lex_strings.make(name);
|
||||
pform_cur_modport = new PModport(use_name);
|
||||
FILE_NAME(pform_cur_modport, loc);
|
||||
if (scope->modports.find(use_name) != scope->modports.end()) {
|
||||
cerr << loc << ": error: duplicate declaration for modport '"
|
||||
<< name << "' in '" << scope->mod_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
scope->modports[use_name] = pform_cur_modport;
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
void pform_end_modport_item(const struct vlltype&loc)
|
||||
{
|
||||
ivl_assert(loc, pform_cur_modport);
|
||||
pform_cur_modport = 0;
|
||||
}
|
||||
|
||||
void pform_add_modport_port(const struct vlltype&loc,
|
||||
NetNet::PortType port_type,
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
ivl_assert(loc, pform_cur_modport);
|
||||
|
||||
if (pform_cur_modport->simple_ports.find(name)
|
||||
!= pform_cur_modport->simple_ports.end()) {
|
||||
cerr << loc << ": error: duplicate declaration of port '"
|
||||
<< name << "' in modport list '"
|
||||
<< pform_cur_modport->name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
pform_cur_modport->simple_ports[name] = make_pair(port_type, expr);
|
||||
}
|
||||
|
||||
|
||||
FILE*vl_input = 0;
|
||||
extern void reset_lexor();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_pform_H
|
||||
#define IVL_pform_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -136,6 +136,10 @@ extern void pform_set_default_nettype(NetNet::Type net,
|
||||
used to reject statements that cannot exist in program blocks. */
|
||||
extern bool pform_in_program_block(void);
|
||||
|
||||
/* Return true if currently processing an interface. This can be
|
||||
used to reject statements that cannot exist in interfaces. */
|
||||
extern bool pform_in_interface(void);
|
||||
|
||||
/*
|
||||
* Look for the given wire in the current lexical scope. If the wire
|
||||
* (including variables of any type) cannot be found in the current
|
||||
@@ -152,12 +156,14 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
|
||||
* are to apply to the scope of that module. The endmodule causes the
|
||||
* pform to close up and finish the named module.
|
||||
*
|
||||
* The program_flag indicates that the module is actually a program
|
||||
* block. This has implications during parse and during
|
||||
* The program_block flag indicates that the module is actually a program
|
||||
* block. The is_interface flag indicates that the module is actually
|
||||
* an interface. These flags have implications during parse and during
|
||||
* elaboration/code generation.
|
||||
*/
|
||||
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
bool program_block, list<named_pexpr_t>*attr);
|
||||
bool program_block, bool is_interface,
|
||||
list<named_pexpr_t>*attr);
|
||||
extern void pform_check_timeunit_prec();
|
||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||
|
||||
@@ -213,6 +219,15 @@ extern void pform_package_import(const struct vlltype&loc,
|
||||
extern PExpr* pform_package_ident(const struct vlltype&loc,
|
||||
PPackage*pkg, pform_name_t*ident);
|
||||
|
||||
/*
|
||||
* Interface related functions.
|
||||
*/
|
||||
extern void pform_start_modport_item(const struct vlltype&loc, const char*name);
|
||||
extern void pform_end_modport_item(const struct vlltype&loc);
|
||||
extern void pform_add_modport_port(const struct vlltype&loc,
|
||||
NetNet::PortType port_type,
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/*
|
||||
* This creates an identifier aware of names that may have been
|
||||
* imported from other packages.
|
||||
@@ -272,7 +287,8 @@ extern void pform_endgenerate();
|
||||
*/
|
||||
extern PGenerate* pform_parent_generate(void);
|
||||
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type);
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
|
||||
std::list<pform_range_t>*unp_ranges);
|
||||
|
||||
/*
|
||||
* This function makes a PECallFunction of the named function. Decide
|
||||
|
||||
@@ -79,8 +79,8 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, N
|
||||
return;
|
||||
}
|
||||
|
||||
// For now, can only handle packed structs.
|
||||
ivl_assert(*struct_type, 0);
|
||||
// For now, can only handle packed structs. The parser generates
|
||||
// a "sorry" message, so no need to do anything here.
|
||||
}
|
||||
|
||||
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ typedef named<verinum> named_number_t;
|
||||
typedef named<PExpr*> named_pexpr_t;
|
||||
|
||||
/*
|
||||
* The pform_range_t holds variable diimensions for type
|
||||
* The pform_range_t holds variable dimensions for type
|
||||
* declarations. The two expressions are interpreted as the first and
|
||||
* last values of the range. For example:
|
||||
*
|
||||
|
||||
+11
-7
@@ -4,22 +4,26 @@
|
||||
# the number for a snapshot and the path to a temporary directory.
|
||||
# for example:
|
||||
#
|
||||
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||
# sh scripts/MAKE_RELEASE.sh 10.1 ~/tmp
|
||||
#
|
||||
# The above assumes that there is a tag "v0_9_1" at the point
|
||||
# The above assumes that there is a tag "v10_1" at the point
|
||||
# to be released. (The tag has the "v", but the argument to this
|
||||
# script does not have the "v"). This script extracts based on the
|
||||
# tag, uses the temporary directory to stage intermediate results,
|
||||
# and finally creates a file called verilog-0.9.1.tar.gz that
|
||||
# and finally creates a file called verilog-10.1.tar.gz that
|
||||
# contains the release ready to go.
|
||||
#
|
||||
# The complete steps to make a release x.y.z generally are:
|
||||
# The complete steps to make a release x.y generally are:
|
||||
#
|
||||
# git tag -a v0_9_1
|
||||
# Edit version_base.h to suit.
|
||||
#
|
||||
# Edit verilog.spec to suit.
|
||||
#
|
||||
# git tag -a v10_1
|
||||
# (Make the tag in the local git repository.)
|
||||
#
|
||||
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||
# (Make the snapshot bundle verilog-0.9.1.tar.gz)
|
||||
# sh scripts/MAKE_RELEASE.sh 10.1 ~/tmp
|
||||
# (Make the snapshot bundle verilog-10.1.tar.gz)
|
||||
#
|
||||
# git push --tags
|
||||
# (Publish the tag to the repository.)
|
||||
|
||||
@@ -15,7 +15,7 @@ iwidth:32
|
||||
sys_func:vpi/system.sft
|
||||
sys_func:vpi/v2005_math.sft
|
||||
sys_func:vpi/va_math.sft
|
||||
warnings:ailnpstv
|
||||
warnings:adfilnpstv
|
||||
debug:eval_tree
|
||||
debug:elaborate
|
||||
debug:emit
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
return false;
|
||||
|
||||
// The prefix is found to be a scope, so switch to that
|
||||
// scope, set the hier_path to turn of upwards searches,
|
||||
// scope, set the hier_path to turn off upwards searches,
|
||||
// and continue our search for the tail.
|
||||
if (recurse.is_scope()) {
|
||||
scope = recurse.scope;
|
||||
|
||||
+3
-7
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -121,11 +121,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
if (ce) connect(ff->pin_Enable(), ce->pin(0));
|
||||
|
||||
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
||||
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT"));
|
||||
|
||||
|
||||
/* This lval_ represents a reg that is a WIRE in the
|
||||
synthesized results. This function signals the destructor
|
||||
to change the REG that this l-value refers to into a
|
||||
@@ -165,7 +160,8 @@ static void make_DFF_CE(Design*des, NetProcTop*top,
|
||||
|
||||
if (a->sig()) {
|
||||
// cerr << "new NetFF named " << a->name() << endl;
|
||||
NetFF*ff = new NetFF(top->scope(), a->name(),
|
||||
bool negedge = pclk->edge() == NetEvProbe::NEGEDGE;
|
||||
NetFF*ff = new NetFF(top->scope(), a->name(), negedge,
|
||||
a->sig()->vector_width());
|
||||
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ff);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2016 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
|
||||
@@ -34,8 +34,10 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&)
|
||||
}
|
||||
|
||||
bool NetProc::synth_sync(Design*des, NetScope*scope,
|
||||
bool& /* ff_negedge */,
|
||||
NetNet* /* ff_clk */, NetBus& /* ff_ce */,
|
||||
NetBus& /* ff_aclr*/, NetBus& /* ff_aset*/,
|
||||
vector<verinum>& /*ff_aset_value*/,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events)
|
||||
{
|
||||
@@ -70,9 +72,45 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out)
|
||||
{
|
||||
/* If the lval is a concatenation, synthesise each part
|
||||
separately. */
|
||||
if (lval_->more ) {
|
||||
/* Temporarily set the lval_ and rval_ fields for each
|
||||
part in turn and recurse. Restore them when done. */
|
||||
NetAssign_*full_lval = lval_;
|
||||
NetExpr*full_rval = rval_;
|
||||
unsigned offset = 0;
|
||||
bool flag = true;
|
||||
while (lval_) {
|
||||
unsigned width = lval_->lwidth();
|
||||
NetEConst*base = new NetEConst(verinum(offset));
|
||||
base->set_line(*this);
|
||||
rval_ = new NetESelect(full_rval->dup_expr(), base, width);
|
||||
rval_->set_line(*this);
|
||||
eval_expr(rval_, width);
|
||||
NetAssign_*more = lval_->more;
|
||||
lval_->more = 0;
|
||||
if (!synth_async(des, scope, nex_map, nex_out, accumulated_nex_out))
|
||||
flag = false;
|
||||
lval_ = lval_->more = more;
|
||||
offset += width;
|
||||
}
|
||||
lval_ = full_lval;
|
||||
rval_ = full_rval;
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetNet*rsig = rval_->synthesize(des, scope, rval_);
|
||||
assert(rsig);
|
||||
|
||||
if (lval_->word() && ! dynamic_cast<NetEConst*>(lval_->word())) {
|
||||
cerr << get_fileline() << ": sorry: assignment to variable "
|
||||
"location in memory is not currently supported in "
|
||||
"synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet*lsig = lval_->sig();
|
||||
if (!lsig) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
@@ -82,15 +120,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (lval_->more) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "NetAssignBase::synth_async does not support an "
|
||||
<< "L-value concatenation ";
|
||||
dump_lval(cerr);
|
||||
cerr << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetAssignBase::synth_async: "
|
||||
@@ -136,6 +165,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(tmp, base_off, lval_->lwidth(), NetPartSelect::PV);
|
||||
ps->set_line(*this);
|
||||
@@ -166,7 +196,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
//tmp->local_flag(true);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
ivl_assert(*this, accumulated_nex_out.pin_count()==1);
|
||||
NetNet*use_lsig = lsig;
|
||||
@@ -185,7 +216,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
<< " Found no use_sig, resorting to lsig." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
NetSubstitute*ps = new NetSubstitute(use_lsig, rsig,
|
||||
tmp->vector_width(),
|
||||
base_off);
|
||||
@@ -196,6 +226,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
rsig = tmp;
|
||||
}
|
||||
|
||||
rsig = crop_to_width(des, rsig, lsig->vector_width());
|
||||
|
||||
if (nex_out.pin_count() > 1) {
|
||||
NexusSet tmp_set;
|
||||
nex_output(tmp_set);
|
||||
@@ -531,18 +563,24 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
statement_map[sel_idx] = items_[item].statement;
|
||||
}
|
||||
|
||||
// The mux_size is the number of inputs that are selected.
|
||||
unsigned mux_size = max_guard_value + 1;
|
||||
unsigned sel_need = ceil(log2(mux_size));
|
||||
// The minimum selector width is the number of inputs that
|
||||
// are selected, rounded up to the nearest power of 2.
|
||||
unsigned sel_need = ceil(log2(max_guard_value + 1));
|
||||
|
||||
// If the sel_width can select more than just the explicit
|
||||
// guard values, and there is a default statement, then adjust
|
||||
// the mux size to allow for the implicit selections.
|
||||
if (statement_default && (sel_width > sel_need)) {
|
||||
// the sel_need to allow for the implicit selections.
|
||||
if (statement_default && (sel_width > sel_need))
|
||||
sel_need += 1;
|
||||
ivl_assert(*this, sel_need < sizeof mux_size);
|
||||
mux_size = 1<<sel_need;
|
||||
|
||||
// The mux size is always an exact power of 2.
|
||||
if (sel_need >= 8*sizeof(unsigned)) {
|
||||
cerr << get_fileline() << ": sorry: mux select width of "
|
||||
<< sel_need << " bits is too large for synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
unsigned mux_size = 1U << sel_need;
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
@@ -746,7 +784,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
|
||||
netvector_t*condit_type = new netvector_t(IVL_VT_LOGIC, 0, 0);
|
||||
|
||||
NetCaseCmp::kind_t case_kind;
|
||||
NetCaseCmp::kind_t case_kind = NetCaseCmp::EEQ;
|
||||
switch (type()) {
|
||||
case NetCase::EQ:
|
||||
case_kind = NetCaseCmp::EEQ;
|
||||
@@ -782,8 +820,8 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
sel_width, case_kind);
|
||||
des->add_node(condit_dev);
|
||||
condit_dev->set_line(*this);
|
||||
// Note that the expression that may have windcards must
|
||||
// go in the pin(2) input. This is the definiton of the
|
||||
// Note that the expression that may have wildcards must
|
||||
// go in the pin(2) input. This is the definition of the
|
||||
// NetCaseCmp statement.
|
||||
connect(condit_dev->pin(1), esig->pin(0));
|
||||
connect(condit_dev->pin(2), guard->pin(0));
|
||||
@@ -829,6 +867,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, tmp_vec);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
ivl_assert(*this, tmp->vector_width() != 0);
|
||||
connect(mux_cur->pin_Result(), tmp->pin(0));
|
||||
|
||||
@@ -1105,6 +1144,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*otmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
otmp->local_flag(true);
|
||||
otmp->set_line(*this);
|
||||
connect(mux->pin_Result(),otmp->pin(0));
|
||||
|
||||
connect(mux->pin_Sel(), ssig->pin(0));
|
||||
@@ -1115,6 +1155,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(mux->pin_Data(1), tmp->pin(0));
|
||||
}
|
||||
|
||||
@@ -1122,6 +1164,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(mux->pin_Data(0), tmp->pin(0));
|
||||
}
|
||||
|
||||
@@ -1132,6 +1176,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_lwidth-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
NetPartSelect*ps = new NetPartSelect(tmp, mux_off, mux_width, NetPartSelect::PV);
|
||||
des->add_node(ps);
|
||||
connect(ps->pin(0), otmp->pin(0));
|
||||
@@ -1159,8 +1205,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
}
|
||||
vector<bool>mask = statement_input.pin(idx).nexus()->driven_mask();
|
||||
for (size_t bit = mux_off ; bit < mux_off+mux_width ; bit += 1) {
|
||||
ivl_assert(*this, mask[bit]==false);
|
||||
// If the mask is empty then there are no bits in the
|
||||
// nexus to check yet.
|
||||
if (! mask.empty()) {
|
||||
for (size_t bit = mux_off;
|
||||
bit < mux_off+mux_width;
|
||||
bit += 1) {
|
||||
ivl_assert(*this, mask[bit]==false);
|
||||
}
|
||||
}
|
||||
connect(nex_out.pin(idx), statement_input.pin(idx));
|
||||
}
|
||||
@@ -1308,6 +1360,7 @@ bool NetProcTop::synth_async(Design*des)
|
||||
NetNet*tmp_sig = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp_sig->local_flag(true);
|
||||
tmp_sig->set_line(*this);
|
||||
|
||||
NetPartSelect*tmp = new NetPartSelect(tmp_sig, item.base,
|
||||
item.wid, NetPartSelect::PV);
|
||||
@@ -1341,8 +1394,10 @@ bool NetProcTop::synth_async(Design*des)
|
||||
* the statements may each infer different reset and enable signals.
|
||||
*/
|
||||
bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events_in)
|
||||
{
|
||||
@@ -1366,6 +1421,16 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
are used to collect the outputs from the substatement
|
||||
for the inputs of the FF bank. */
|
||||
NetBus tmp_out (scope, tmp_set.size());
|
||||
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
||||
unsigned ptr = nex_map.find_nexus(tmp_set[idx]);
|
||||
ivl_assert(*this, ptr < nex_out.pin_count());
|
||||
if (nex_out.pin(ptr).is_linked()) {
|
||||
cerr << get_fileline() << ": sorry: multiple statements "
|
||||
"assigning to the same flip-flop are not yet "
|
||||
"supported in synthesis." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a temporary ff_ce (FF clock-enable) that
|
||||
accounts for the subset of outputs that this
|
||||
@@ -1385,8 +1450,9 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
subset of the statement. The tmp_map is the output
|
||||
nexa that we expect, and the tmp_out is where we want
|
||||
those outputs connected. */
|
||||
bool ok_flag = cur->synth_sync(des, scope, ff_clk, tmp_ce,
|
||||
ff_aclr, ff_aset,
|
||||
bool ok_flag = cur->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, tmp_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
tmp_set, tmp_out, events_in);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
@@ -1422,8 +1488,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
* expression is connected to an event, or not.
|
||||
*/
|
||||
bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events_in)
|
||||
{
|
||||
@@ -1470,25 +1538,13 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
for (unsigned pin = 0 ; pin < tmp_out.pin_count() ; pin += 1) {
|
||||
Nexus*rst_nex = tmp_out.pin(pin).nexus();
|
||||
|
||||
vector<bool> rst_mask = rst_nex->driven_mask();
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCondit::synth_sync: "
|
||||
<< "nex_out pin=" << pin
|
||||
<< ", rst_mask.size()==" << rst_mask.size()
|
||||
<< ", rst_nex->vector_width()=" << rst_nex->vector_width()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (size_t bit = 0 ; bit < rst_mask.size() ; bit += 1) {
|
||||
if (rst_mask[bit]==false) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Asynchronous LOAD not implemented." << endl;
|
||||
return false;
|
||||
}
|
||||
if (! rst_nex->drivers_constant()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Asynchronous LOAD not implemented." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
verinum rst_drv = rst_nex->driven_vector();
|
||||
ivl_assert(*this, rst_drv.len()==rst_mask.size());
|
||||
|
||||
verinum zero (verinum::V0, rst_drv.len());
|
||||
verinum ones (verinum::V1, rst_drv.len());
|
||||
@@ -1500,22 +1556,20 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
ivl_assert(*this, rst->pin_count()==1);
|
||||
connect(ff_aclr.pin(pin), rst->pin(0));
|
||||
|
||||
} else if (rst_drv==ones) {
|
||||
} else {
|
||||
// Don't yet support multiple asynchronous set inputs.
|
||||
ivl_assert(*this, ! ff_aset.pin(pin).is_linked());
|
||||
|
||||
ivl_assert(*this, rst->pin_count()==1);
|
||||
connect(ff_aset.pin(pin), rst->pin(0));
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Forgot how to implement asynchronous scramble (set to x/z)." << endl;
|
||||
return false;
|
||||
if (rst_drv!=ones)
|
||||
ff_aset_value[pin] = rst_drv;
|
||||
}
|
||||
}
|
||||
|
||||
return else_->synth_sync(des, scope, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset,
|
||||
return else_->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
nex_map, nex_out, vector<NetEvProbe*>(0));
|
||||
}
|
||||
|
||||
@@ -1670,14 +1724,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
}
|
||||
}
|
||||
|
||||
bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, ff_aclr, ff_aset, nex_map, nex_out, events_in);
|
||||
bool flag = if_->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
nex_map, nex_out, events_in);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events_in)
|
||||
{
|
||||
@@ -1747,8 +1806,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||
|
||||
connect(ff_clk->pin(0), pclk->pin(0));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE) {
|
||||
perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
|
||||
ff_clk->attribute(polarity, verinum("INVERT"));
|
||||
ff_negedge = true;
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
@@ -1758,8 +1816,9 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset,
|
||||
bool flag = statement_->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
nex_map, nex_out, events);
|
||||
|
||||
return flag;
|
||||
@@ -1780,6 +1839,7 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
vector<verinum> aset_value(nex_set.size());
|
||||
|
||||
/* Make a model FF that will connect to the first item in the
|
||||
set, and will also take the initial connection of clocks
|
||||
@@ -1789,6 +1849,7 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
NetNet*clock = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::TRI, &netvector_t::scalar_logic);
|
||||
clock->local_flag(true);
|
||||
clock->set_line(*this);
|
||||
|
||||
#if 0
|
||||
NetNet*ce = new NetNet(scope(), scope()->local_symbol(),
|
||||
@@ -1813,7 +1874,10 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
// Connect the input later.
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope(), clock, ce, aclr, aset,
|
||||
bool negedge = false;
|
||||
bool flag = statement_->synth_sync(des, scope(),
|
||||
negedge, clock, ce,
|
||||
aclr, aset, aset_value,
|
||||
nex_set, nex_d,
|
||||
vector<NetEvProbe*>());
|
||||
if (! flag) {
|
||||
@@ -1832,9 +1896,10 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
}
|
||||
|
||||
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
|
||||
nex_set[idx].wid);
|
||||
negedge, nex_set[idx].wid);
|
||||
des->add_node(ff2);
|
||||
ff2->set_line(*this);
|
||||
ff2->aset_value(aset_value[idx]);
|
||||
|
||||
NetNet*tmp = nex_d.pin(idx).nexus()->pick_any_net();
|
||||
tmp->set_line(*this);
|
||||
|
||||
+13
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -171,13 +171,6 @@ extern "C" unsigned ivl_expr_lineno(ivl_expr_t net)
|
||||
return net->lineno;
|
||||
}
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
assert(*inst == '.');
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1090,6 +1083,18 @@ extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_negedge(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.negedge_flag;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -364,6 +364,7 @@ void dll_target::expr_last(const NetELast*net)
|
||||
esig->value_ = IVL_VT_DARRAY;
|
||||
esig->net_type= sig->net_type;
|
||||
esig->width_ = 1;
|
||||
esig->signed_ = sig->net_type->get_signed()? 1 : 0;
|
||||
FILE_NAME(esig, net);
|
||||
esig->u_.signal_.word = 0;
|
||||
esig->u_.signal_.sig = sig;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -151,13 +151,6 @@ void ivl_net_const_s::operator delete(void*, size_t)
|
||||
|
||||
static StringHeapLex net_const_strings;
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
assert(*inst == '.');
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
static perm_string make_scope_name(const hname_t&name)
|
||||
{
|
||||
if (! name.has_numbers())
|
||||
@@ -1057,20 +1050,17 @@ void dll_target::logic(const NetLogic*net)
|
||||
obj->npins_ = net->pin_count();
|
||||
obj->pins_ = new ivl_nexus_t[obj->npins_];
|
||||
|
||||
ivl_nexus_ptr_t out_ptr = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins_[idx] = nex->t_cookie();
|
||||
ivl_nexus_ptr_t tmp = nexus_log_add(obj->pins_[idx], obj, idx);
|
||||
if (idx == 0)
|
||||
out_ptr = tmp;
|
||||
if (idx == 0) {
|
||||
tmp->drive0 = net->pin(0).drive0();
|
||||
tmp->drive1 = net->pin(0).drive1();
|
||||
}
|
||||
}
|
||||
|
||||
out_ptr->drive0 = net->pin(0).drive0();
|
||||
out_ptr->drive1 = net->pin(0).drive1();
|
||||
|
||||
assert(net->scope());
|
||||
ivl_scope_t scop = find_scope(des_, net->scope());
|
||||
assert(scop);
|
||||
@@ -1941,6 +1931,9 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
/* Set the clock polarity. */
|
||||
obj->u_.ff.negedge_flag = net->is_negedge();
|
||||
|
||||
/* Set the clk signal to point to the nexus, and the nexus to
|
||||
point back to this device. */
|
||||
nex = net->pin_Clock().nexus();
|
||||
@@ -1979,7 +1972,10 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
verinum tmp = net->aset_value();
|
||||
obj->u_.ff.aset_value = expr_from_value_(tmp);
|
||||
if (tmp.len() > 0)
|
||||
obj->u_.ff.aset_value = expr_from_value_(tmp);
|
||||
else
|
||||
obj->u_.ff.aset_value = 0;
|
||||
|
||||
} else {
|
||||
obj->u_.ff.aset = 0;
|
||||
@@ -2004,7 +2000,10 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
nexus_lpm_add(obj->u_.ff.sset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
verinum tmp = net->sset_value();
|
||||
obj->u_.ff.sset_value = expr_from_value_(tmp);
|
||||
if (tmp.len() > 0)
|
||||
obj->u_.ff.sset_value = expr_from_value_(tmp);
|
||||
else
|
||||
obj->u_.ff.sset_value = 0;
|
||||
|
||||
} else {
|
||||
obj->u_.ff.sset = 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_t_dll_H
|
||||
#define IVL_t_dll_H
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -370,6 +370,7 @@ struct ivl_lpm_s {
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned negedge_flag :1;
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ using namespace std;
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog BLIF Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2013 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2013,2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
||||
@@ -51,7 +51,7 @@ static int print_lpm_cmp_gt_s(FILE*fd, ivl_lpm_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%u: sorry: blif: Signed agnitude compare not implemented yet\n",
|
||||
fprintf(stderr, "%s:%u: sorry: blif: Signed magnitude compare not implemented yet\n",
|
||||
ivl_lpm_file(net), ivl_lpm_lineno(net));
|
||||
|
||||
return 1;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog NULL Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2000-2014 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2000-2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
||||
+6
-3
@@ -82,12 +82,15 @@ pcb_config.h: stamp-pcb_config-h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
fp_lex.o: fp_lex.cc fp.h
|
||||
|
||||
fp_lex.cc: $(srcdir)/fp.lex
|
||||
$(LEX) -s -ofp_lex.cc $(srcdir)/fp.lex
|
||||
|
||||
fp.cc fp.h: $(srcdir)/fp.y
|
||||
$(YACC) --verbose -t -d -o fp.cc $(srcdir)/fp.y
|
||||
mv fp.cc.h fp.h 2>/dev/null || mv fp.hh fp.h
|
||||
fp.cc: $(srcdir)/fp.y
|
||||
$(YACC) --verbose -t -p fp -d -o $@ $<
|
||||
fp.h: fp.cc
|
||||
mv fp.cc.h $@ 2>/dev/null || mv fp.hh $@
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
%name-prefix="fp"
|
||||
%pure-parser
|
||||
%parse-param {const char*file_path}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014,2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -34,7 +34,7 @@ using namespace std;
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog SIZER Statistics Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2014 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2014,2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
||||
+19
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2013-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -25,13 +25,26 @@
|
||||
|
||||
void show_constant(ivl_net_const_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
const char*bits = ivl_const_bits(net);
|
||||
assert(net);
|
||||
|
||||
fprintf(out, "constant ");
|
||||
for (idx = 0 ; idx < ivl_const_width(net) ; idx += 1)
|
||||
fprintf(out, "%c", bits[idx]);
|
||||
|
||||
switch (ivl_const_type(net)) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
{
|
||||
const char*bits = ivl_const_bits(net);
|
||||
unsigned idx;
|
||||
assert(bits);
|
||||
for (idx = 0 ; idx < ivl_const_width(net) ; idx += 1)
|
||||
fprintf(out, "%c", bits[idx]);
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
fprintf(out, "%f", ivl_const_real(net));
|
||||
break;
|
||||
default:
|
||||
fprintf(out, "<unsupported type>");
|
||||
break;
|
||||
}
|
||||
fprintf(out, " at %s:%u\n", ivl_const_file(net), ivl_const_lineno(net));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// are not used here.
|
||||
|
||||
// target_design()
|
||||
unusedFunction:stub.c:1770
|
||||
unusedFunction:stub.c:1774
|
||||
|
||||
// target_query()
|
||||
unusedFunction:stub.c:1834
|
||||
unusedFunction:stub.c:1844
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog STUB Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2000-2014 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2000-2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
@@ -380,7 +380,7 @@ static void show_lpm_divide(ivl_lpm_t net)
|
||||
*/
|
||||
static void show_lpm_cmp_eeq(ivl_lpm_t net)
|
||||
{
|
||||
const char*str;
|
||||
const char*str = 0;
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
str = "EEQ";
|
||||
@@ -497,10 +497,11 @@ static void show_lpm_concat(ivl_lpm_t net)
|
||||
static void show_lpm_ff(ivl_lpm_t net)
|
||||
{
|
||||
ivl_nexus_t nex;
|
||||
char*edge = ivl_lpm_negedge(net) ? "negedge" : "posedge";
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
fprintf(out, " LPM_FF %s: <width=%u>\n",
|
||||
ivl_lpm_basename(net), width);
|
||||
fprintf(out, " LPM_FF %s: <polarity=%s> <width=%u>\n",
|
||||
ivl_lpm_basename(net), edge, width);
|
||||
|
||||
nex = ivl_lpm_clk(net);
|
||||
fprintf(out, " clk: %p\n", nex);
|
||||
|
||||
+56
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2011-2015 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* 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
|
||||
@@ -1245,7 +1245,43 @@ static void emit_posedge_dff_prim(void)
|
||||
fprintf(vlog_out, "endprimitive\n");
|
||||
}
|
||||
|
||||
static void emit_negedge_dff_prim(void)
|
||||
{
|
||||
fprintf(vlog_out, "\n");
|
||||
fprintf(vlog_out, "/* Icarus generated UDP to represent a synthesized "
|
||||
"negative edge D-FF. */\n");
|
||||
fprintf(vlog_out, "primitive IVL_negedge_DFF "
|
||||
"(q, clk, en, d, clr, set);\n");
|
||||
fprintf(vlog_out, "%*coutput q;\n", indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cinput clk, en, d, clr, set;\n", indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*creg q;\n", indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*ctable\n", indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cf 1 0 0 0 : ? : 0 ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cf 1 1 0 0 : ? : 1 ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cn 1 0 0 0 : 0 : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cn 1 1 0 0 : 1 : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cn x 0 0 0 : 0 : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cn x 1 0 0 : 1 : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cp ? ? 0 0 : ? : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c* 0 ? 0 0 : ? : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? * ? ? ? : ? : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? * ? ? : ? : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? * ? : ? : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? ? * : ? : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? 0 1 : ? : 1 ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? 0 x : 1 : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? 0 x : 0 : x ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? 1 ? : ? : 0 ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? x 0 : 0 : - ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? x 0 : 1 : x ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? x x : ? : x ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*c? ? ? x 1 : ? : x ;\n", 2*indent_incr, ' ');
|
||||
fprintf(vlog_out, "%*cendtable\n", indent_incr, ' ');
|
||||
fprintf(vlog_out, "endprimitive\n");
|
||||
}
|
||||
|
||||
static unsigned need_posedge_dff_prim = 0;
|
||||
static unsigned need_negedge_dff_prim = 0;
|
||||
|
||||
/*
|
||||
* Synthesis creates a D-FF LPM object. To allow this to be simulated as
|
||||
@@ -1263,14 +1299,14 @@ void emit_icarus_generated_udps()
|
||||
{
|
||||
/* Emit the copyright information and LGPL note and then emit any
|
||||
* needed primitives. */
|
||||
if (need_posedge_dff_prim) {
|
||||
if (need_posedge_dff_prim || need_negedge_dff_prim) {
|
||||
fprintf(vlog_out,
|
||||
"\n"
|
||||
"/*\n"
|
||||
" * This is the copyright information for the following primitive(s)\n"
|
||||
" * (library elements).\n"
|
||||
" *\n"
|
||||
" * Copyright (C) 2011 Cary R. ([email protected])\n"
|
||||
" * Copyright (C) 2011-2015 Cary R. ([email protected])\n"
|
||||
" *\n"
|
||||
" * This library is free software; you can redistribute it and/or\n"
|
||||
" * modify it under the terms of the GNU Lesser General Public\n"
|
||||
@@ -1290,13 +1326,12 @@ void emit_icarus_generated_udps()
|
||||
"NOTE: vlog95: Adding LGPL 2.1 primitive(s) at the end of the output file.\n");
|
||||
}
|
||||
if (need_posedge_dff_prim) emit_posedge_dff_prim();
|
||||
if (need_negedge_dff_prim) emit_negedge_dff_prim();
|
||||
}
|
||||
|
||||
static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||
{
|
||||
// HERE: No support for lpm attributes and hence polarity information.
|
||||
// ivl_attribute_t clock_pol = find_lpm_attr(lpm, "Clock:LPM_Polarity");
|
||||
ivl_attribute_t clock_pol = 0;
|
||||
unsigned negedge = ivl_lpm_negedge(lpm);
|
||||
ivl_expr_t aset_expr = ivl_lpm_aset_value(lpm);
|
||||
ivl_expr_t sset_expr = ivl_lpm_sset_value(lpm);
|
||||
ivl_nexus_t nex;
|
||||
@@ -1305,7 +1340,13 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||
const char *sset_bits = 0;
|
||||
/* For now we only support a width of 1 for these bits. */
|
||||
if (aset_expr) {
|
||||
assert(ivl_expr_width(aset_expr) == 1);
|
||||
if (ivl_expr_width(aset_expr) != 1) {
|
||||
fprintf(stderr, "%s:%u: vlog95 sorry: FF LPMs with "
|
||||
"multi-bit asynchronous set values are not "
|
||||
"currently translated.\n",
|
||||
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
|
||||
vlog_errors += 1;
|
||||
}
|
||||
aset_bits = ivl_expr_bits(aset_expr);
|
||||
}
|
||||
if (sset_expr) {
|
||||
@@ -1314,9 +1355,7 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||
}
|
||||
|
||||
fprintf(vlog_out, "%*c", indent, ' ');
|
||||
/* If there is a clock polarity attribute then we have a negative
|
||||
* edge D-FF. */
|
||||
if (clock_pol) {
|
||||
if (negedge) {
|
||||
fprintf(vlog_out, "IVL_negedge_DFF");
|
||||
} else {
|
||||
fprintf(vlog_out, "IVL_posedge_DFF");
|
||||
@@ -1368,7 +1407,7 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||
}
|
||||
nex = ivl_lpm_sync_set(lpm);
|
||||
if (nex) {
|
||||
if (! sset_bits || (sset_bits && (sset_bits[0] == '1'))) {
|
||||
if (! sset_bits || (sset_bits[0] == '1')) {
|
||||
emit_nexus_as_ca(scope, nex, 0, 0);
|
||||
if (have_data) fprintf(vlog_out, " | ");
|
||||
} else {
|
||||
@@ -1404,7 +1443,10 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||
else fprintf(vlog_out, "1'b0");
|
||||
fprintf(vlog_out, ");\n");
|
||||
/* We need to emit a primitive for this instance. */
|
||||
need_posedge_dff_prim = 1;
|
||||
if (negedge)
|
||||
need_negedge_dff_prim = 1;
|
||||
else
|
||||
need_posedge_dff_prim = 1;
|
||||
}
|
||||
|
||||
static ivl_signal_t get_output_from_nexus(ivl_scope_t scope, ivl_nexus_t nex,
|
||||
@@ -1900,7 +1942,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
|
||||
{
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig, 0);
|
||||
unsigned idx, count = ivl_nexus_ptrs(nex);
|
||||
unsigned long emitted = (unsigned long) ivl_nexus_get_private(nex);
|
||||
unsigned long emitted = (uintptr_t) ivl_nexus_get_private(nex);
|
||||
for (idx = 0; idx < count; idx += 1) {
|
||||
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
||||
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
|
||||
@@ -1930,7 +1972,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
|
||||
fprintf(vlog_out, "\n");
|
||||
/* Increment the emitted constant count by one. */
|
||||
ivl_nexus_set_private(nex,
|
||||
(void *) ((unsigned long) ivl_nexus_get_private(nex) + 1U));
|
||||
(void *) ((uintptr_t) ivl_nexus_get_private(nex) + 1U));
|
||||
return;
|
||||
}
|
||||
/* We must find the constant in the nexus. */
|
||||
|
||||
+13
-3
@@ -78,6 +78,7 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
|
||||
{
|
||||
unsigned has_undef = 0;
|
||||
|
||||
assert(nbits > 0);
|
||||
/* Check for an undefined bit. */
|
||||
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
|
||||
if ((bits[idx] != '0') && (bits[idx] != '1')) {
|
||||
@@ -91,8 +92,14 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
|
||||
|
||||
/* Emit as a binary constant. */
|
||||
if (has_undef || (nbits < 2)) {
|
||||
int start = nbits - 1;
|
||||
char sbit = bits[start];
|
||||
/* Trim extra leading bits. */
|
||||
if (! is_signed && (sbit == '1')) sbit = ' ';
|
||||
while (start && (sbit == bits[start-1])) start -= 1;
|
||||
/* Print the trimmed value. */
|
||||
fprintf(vlog_out, "b");
|
||||
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
|
||||
for (int idx = start; idx >= 0; idx -= 1) {
|
||||
fprintf(vlog_out, "%c", bits[idx]);
|
||||
}
|
||||
/* Emit as a hex constant. */
|
||||
@@ -152,9 +159,12 @@ void emit_number(const char *bits, unsigned nbits, unsigned is_signed,
|
||||
vlog_errors += 1;
|
||||
return;
|
||||
} else if (rtype == -2) {
|
||||
fprintf(vlog_out, "'bz");
|
||||
fprintf(vlog_out, "%u'bz", nbits);
|
||||
} else if (rtype == -3) {
|
||||
fprintf(vlog_out, "'bx");
|
||||
/* If this is a 32-bit wide constant then generate the
|
||||
* undefined with integers to get a signed value. */
|
||||
if (nbits == 32) fprintf(vlog_out, "1/0");
|
||||
else fprintf(vlog_out, "%u'bx", nbits);
|
||||
} else {
|
||||
fprintf(vlog_out, "%"PRId32, value);
|
||||
}
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* 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
|
||||
@@ -432,10 +432,13 @@ static void emit_sig_type(ivl_signal_t sig)
|
||||
}
|
||||
/* Check to see if we have a variable (reg) or a net. */
|
||||
if (type == IVL_SIT_REG) {
|
||||
/* The variable data type will be declared later, so here
|
||||
we just want to declare the range and whether or not it
|
||||
is signed. */
|
||||
if (ivl_signal_integer(sig)) {
|
||||
fprintf(vlog_out, " integer");
|
||||
/* nothing to do */
|
||||
} else if (ivl_signal_data_type(sig) == IVL_VT_REAL) {
|
||||
fprintf(vlog_out, " real");
|
||||
/* nothing to do */
|
||||
} else {
|
||||
int msb, lsb;
|
||||
get_sig_msb_lsb(sig, &msb, &lsb);
|
||||
|
||||
+1
-1
@@ -942,7 +942,7 @@ static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
|
||||
static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
{
|
||||
const char *case_type;
|
||||
const char *case_type = 0;
|
||||
unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
|
||||
switch (ivl_statement_type(stmt)) {
|
||||
case IVL_ST_CASE:
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (C) 2010-2013 Cary R. ([email protected])\n\n"
|
||||
"Copyright (C) 2010-2015 Cary R. ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
@@ -208,7 +208,7 @@ int target_design(ivl_design_t des)
|
||||
assert(indent == 0);
|
||||
fprintf(vlog_out, "endmodule /* ivl_root_scope */\n");
|
||||
}
|
||||
/* Emit the rest of the scope objets. */
|
||||
/* Emit the rest of the scope objects. */
|
||||
for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0);
|
||||
|
||||
free_emitted_scope_list();
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ THE VVP TARGET
|
||||
|
||||
SYMBOL NAME CONVENTIONS
|
||||
|
||||
There are some naming conventions that the vp target uses for
|
||||
There are some naming conventions that the vvp target uses for
|
||||
generating symbol names.
|
||||
|
||||
* wires and regs
|
||||
@@ -30,4 +30,4 @@ the drivers are first fed into a resolver (or a tree of resolvers) to
|
||||
form a single output that is the nexus.
|
||||
|
||||
The nexus, then, feeds its output to the inputs of other gates, or to
|
||||
the .net objects in the design.
|
||||
the .net objects in the design.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// are not used here.
|
||||
|
||||
// target_design()
|
||||
unusedFunction:vvp.c:89
|
||||
unusedFunction:vvp.c:149
|
||||
|
||||
// target_query()
|
||||
unusedFunction:vvp.c:184
|
||||
unusedFunction:vvp.c:246
|
||||
|
||||
+12
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -26,10 +26,6 @@
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
|
||||
{
|
||||
unsigned idx;
|
||||
@@ -703,11 +699,12 @@ static void draw_net_input_x(ivl_nexus_t nex,
|
||||
/* If the nexus has no drivers, then send a constant HiZ or
|
||||
0.0 into the net. */
|
||||
if (ndrivers == 0) {
|
||||
unsigned wid = width_of_nexus(nex);
|
||||
/* For real nets put 0.0. */
|
||||
if (signal_data_type_of_nexus(nex) == IVL_VT_REAL) {
|
||||
nex_private = draw_Cr_to_string(0.0);
|
||||
} else {
|
||||
unsigned jdx, wid = width_of_nexus(nex);
|
||||
unsigned jdx;
|
||||
char*tmp = malloc(wid + 5);
|
||||
nex_private = tmp;
|
||||
strcpy(tmp, "C4<");
|
||||
@@ -731,18 +728,17 @@ static void draw_net_input_x(ivl_nexus_t nex,
|
||||
}
|
||||
*tmp++ = '>';
|
||||
*tmp = 0;
|
||||
|
||||
/* Create an "open" driver to hold the HiZ. We
|
||||
need to do this so that .nets have something to
|
||||
hang onto. */
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof buf, "o%p", nex);
|
||||
fprintf(vvp_out, "%s .functor BUFZ %u, %s; HiZ drive\n",
|
||||
buf, wid, nex_private);
|
||||
nex_private = realloc(nex_private, strlen(buf)+1);
|
||||
strcpy(nex_private, buf);
|
||||
}
|
||||
|
||||
/* Create an "open" driver to hold the HiZ or 0.0. We need
|
||||
to do this so that .nets have something to hang onto. */
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof buf, "o%p", nex);
|
||||
fprintf(vvp_out, "%s .functor BUFZ %u, %s; HiZ drive\n",
|
||||
buf, wid, nex_private);
|
||||
nex_private = realloc(nex_private, strlen(buf)+1);
|
||||
strcpy(nex_private, buf);
|
||||
|
||||
if (island) {
|
||||
char*tmp2 = draw_island_port(island, island_input_flag, nex, nex_data, nex_private);
|
||||
free(nex_private);
|
||||
|
||||
+46
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2005-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -36,7 +36,6 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
|
||||
if (ewidth < pwidth)
|
||||
fprintf(vvp_out, " %%pad/u %u;\n", pwidth);
|
||||
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", port, pwidth);
|
||||
}
|
||||
|
||||
static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
||||
@@ -45,54 +44,57 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
||||
assert(ivl_signal_dimensions(port) == 0);
|
||||
|
||||
draw_eval_real(expr);
|
||||
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
function_argument_logic(port, expr);
|
||||
}
|
||||
|
||||
static void function_argument_class(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
draw_eval_object(expr);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void function_argument_darray(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
draw_eval_object(expr);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void function_argument_string(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
draw_eval_string(expr);
|
||||
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
|
||||
}
|
||||
|
||||
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||
static void draw_eval_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
switch (dtype) {
|
||||
case IVL_VT_BOOL:
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
case IVL_VT_LOGIC:
|
||||
function_argument_logic(port, expr);
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
function_argument_real(port, expr);
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
function_argument_bool(port, expr);
|
||||
break;
|
||||
case IVL_VT_CLASS:
|
||||
function_argument_class(port, expr);
|
||||
vvp_errors += draw_eval_object(expr);
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
function_argument_string(port, expr);
|
||||
draw_eval_string(expr);
|
||||
break;
|
||||
case IVL_VT_DARRAY:
|
||||
function_argument_darray(port, expr);
|
||||
vvp_errors += draw_eval_object(expr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
ivl_signal_basename(port), dtype);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_send_function_argument(ivl_signal_t port)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
switch (dtype) {
|
||||
case IVL_VT_BOOL:
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
case IVL_VT_LOGIC:
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n",
|
||||
port, ivl_signal_width(port));
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
|
||||
break;
|
||||
case IVL_VT_CLASS:
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
|
||||
break;
|
||||
case IVL_VT_DARRAY:
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
@@ -111,13 +113,20 @@ static void draw_ufunc_preamble(ivl_expr_t expr)
|
||||
fprintf(vvp_out, " %%alloc S_%p;\n", def);
|
||||
}
|
||||
|
||||
/* evaluate the expressions and send the results to the
|
||||
function ports. */
|
||||
/* Evaluate the expressions and send the results to the
|
||||
function ports. Do this in two passes - evaluate,
|
||||
then send - this avoids the function input variables
|
||||
being overwritten if the same (non-automatic) function
|
||||
is called in one of the expressions. */
|
||||
|
||||
assert(ivl_expr_parms(expr) == (ivl_scope_ports(def)-1));
|
||||
for (idx = 0 ; idx < ivl_expr_parms(expr) ; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx+1);
|
||||
draw_function_argument(port, ivl_expr_parm(expr, idx));
|
||||
draw_eval_function_argument(port, ivl_expr_parm(expr, idx));
|
||||
}
|
||||
for (idx = ivl_expr_parms(expr) ; idx > 0 ; idx -= 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx);
|
||||
draw_send_function_argument(port);
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
struct args_info {
|
||||
char*text;
|
||||
/* True ('s' or 'u' if this argument is a calculated vec4. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014-2016 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
|
||||
@@ -76,8 +76,8 @@ static int draw_condition_binary_compare(ivl_expr_t expr)
|
||||
%cmp instruction. */
|
||||
if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) {
|
||||
ivl_expr_t tmp = le;
|
||||
re = le;
|
||||
le = tmp;
|
||||
le = re;
|
||||
re = tmp;
|
||||
}
|
||||
|
||||
draw_eval_vec4(le);
|
||||
|
||||
+27
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -28,7 +28,6 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
ivl_expr_t size_expr = ivl_expr_oper1(ex);
|
||||
ivl_expr_t init_expr = ivl_expr_oper2(ex);
|
||||
draw_eval_expr_into_integer(size_expr, size_reg);
|
||||
clr_word(size_reg);
|
||||
|
||||
// The new function has a net_type that contains the details
|
||||
// of the type.
|
||||
@@ -39,6 +38,7 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
assert(element_type);
|
||||
|
||||
switch (ivl_type_base(element_type)) {
|
||||
int msb, lsb, wid;
|
||||
case IVL_VT_REAL:
|
||||
// REAL objects are not packable.
|
||||
assert(ivl_type_packed_dimensions(element_type) == 0);
|
||||
@@ -53,19 +53,30 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
// bool objects are vectorable, but for now only support
|
||||
// a single dimensions.
|
||||
assert(ivl_type_packed_dimensions(element_type) == 1);
|
||||
int msb = ivl_type_packed_msb(element_type, 0);
|
||||
int lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
int wid = msb>=lsb? msb - lsb : lsb - msb;
|
||||
msb = ivl_type_packed_msb(element_type, 0);
|
||||
lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
wid = msb>=lsb? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
||||
fprintf(vvp_out, " %%new/darray %u, \"%sb%d\";\n", size_reg,
|
||||
ivl_type_signed(element_type) ? "s" : "", wid);
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
// logic objects are vectorable, but for now only support
|
||||
// a single dimensions.
|
||||
assert(ivl_type_packed_dimensions(element_type) == 1);
|
||||
msb = ivl_type_packed_msb(element_type, 0);
|
||||
lsb = ivl_type_packed_lsb(element_type, 0);
|
||||
wid = msb>=lsb? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
fprintf(vvp_out, " %%new/darray %u, \"%sv%d\";\n", size_reg,
|
||||
ivl_type_signed(element_type) ? "s" : "", wid);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
clr_word(size_reg);
|
||||
|
||||
if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) {
|
||||
unsigned idx;
|
||||
@@ -109,12 +120,15 @@ static int eval_darray_new(ivl_expr_t ex)
|
||||
unsigned wid;
|
||||
switch (ivl_type_base(element_type)) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
wid = width_of_packed_type(element_type);
|
||||
draw_eval_vec4(init_expr);
|
||||
resize_vec4_wid(init_expr, wid);
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
|
||||
draw_eval_vec4(init_expr);
|
||||
fprintf(vvp_out, " %%parti/%c %u, %ld, 6;\n",
|
||||
ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid);
|
||||
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1);
|
||||
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
|
||||
fprintf(vvp_out, " %%pop/vec4 1;\n");
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
@@ -187,11 +201,12 @@ static int eval_object_property(ivl_expr_t expr)
|
||||
|
||||
static int eval_object_shallowcopy(ivl_expr_t ex)
|
||||
{
|
||||
int errors = 0;
|
||||
ivl_expr_t dest = ivl_expr_oper1(ex);
|
||||
ivl_expr_t src = ivl_expr_oper2(ex);
|
||||
|
||||
draw_eval_object(dest);
|
||||
draw_eval_object(src);
|
||||
errors += draw_eval_object(dest);
|
||||
errors += draw_eval_object(src);
|
||||
|
||||
/* The %scopy opcode pops the top of the object stack as the
|
||||
source object, and shallow-copies it to the new top, the
|
||||
@@ -199,7 +214,7 @@ static int eval_object_shallowcopy(ivl_expr_t ex)
|
||||
the stack. */
|
||||
fprintf(vvp_out, " %%scopy;\n");
|
||||
|
||||
return 0;
|
||||
return errors;
|
||||
}
|
||||
|
||||
static int eval_object_signal(ivl_expr_t expr)
|
||||
|
||||
+33
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2013-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -415,7 +415,7 @@ static void draw_binary_vec4_land(ivl_expr_t expr)
|
||||
fprintf(vvp_out, " %%or/r;\n");
|
||||
|
||||
/* Now push the right expression. Again, reduce to a single
|
||||
bit if necessasry. */
|
||||
bit if necessary. */
|
||||
draw_eval_vec4(re);
|
||||
if (ivl_expr_width(re) > 1)
|
||||
fprintf(vvp_out, " %%or/r;\n");
|
||||
@@ -615,7 +615,7 @@ static void draw_binary_vec4_lor(ivl_expr_t expr)
|
||||
fprintf(vvp_out, " %%or/r;\n");
|
||||
|
||||
/* Now push the right expression. Again, reduce to a single
|
||||
bit if necessasry. */
|
||||
bit if necessary. */
|
||||
draw_eval_vec4(re);
|
||||
if (ivl_expr_width(re) > 1)
|
||||
fprintf(vvp_out, " %%or/r;\n");
|
||||
@@ -643,16 +643,16 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr)
|
||||
// the stack and replace it with the result of the shift.
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
case 'l': /* << */
|
||||
fprintf(vvp_out, " %%shiftl %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftl %d;\n", use_index_reg);
|
||||
break;
|
||||
case 'r': /* >> */
|
||||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
|
||||
break;
|
||||
case 'R': /* >>> */
|
||||
if (ivl_expr_signed(le))
|
||||
fprintf(vvp_out, " %%shiftr/s %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftr/s %d;\n", use_index_reg);
|
||||
else
|
||||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -790,10 +790,10 @@ static void draw_concat_number_vec4(ivl_expr_t expr, int as_concati)
|
||||
|
||||
if (accum) {
|
||||
if (count_pushi) {
|
||||
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %u;\n",
|
||||
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %d;\n",
|
||||
val0, valx, accum);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %u;\n",
|
||||
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %d;\n",
|
||||
val0, valx, accum);
|
||||
}
|
||||
}
|
||||
@@ -807,16 +807,27 @@ static void draw_concat_vec4(ivl_expr_t expr)
|
||||
/* This is the number of expressions that go into the
|
||||
concatenation. */
|
||||
unsigned num_sube = ivl_expr_parms(expr);
|
||||
unsigned sub_idx;
|
||||
unsigned sub_idx = 0;
|
||||
ivl_expr_t sube;
|
||||
|
||||
assert(num_sube > 0);
|
||||
|
||||
/* Start with the most-significant bits. */
|
||||
draw_eval_vec4(ivl_expr_parm(expr, 0));
|
||||
sube = ivl_expr_parm(expr, sub_idx);
|
||||
draw_eval_vec4(sube);
|
||||
/* Evaluate, but skip any zero replication expressions at the
|
||||
* head of this concatenation. */
|
||||
while ((ivl_expr_type(sube) == IVL_EX_CONCAT) &&
|
||||
(ivl_expr_repeat(sube) == 0)) {
|
||||
fprintf(vvp_out, " %%pop/vec4 1; skip zero replication\n");
|
||||
sub_idx += 1;
|
||||
sube = ivl_expr_parm(expr, sub_idx);
|
||||
draw_eval_vec4(sube);
|
||||
}
|
||||
|
||||
for (sub_idx = 1 ; sub_idx < num_sube ; sub_idx += 1) {
|
||||
for ( sub_idx += 1 ; sub_idx < num_sube ; sub_idx += 1) {
|
||||
/* Concatenate progressively lower parts. */
|
||||
ivl_expr_t sube = ivl_expr_parm(expr, sub_idx);
|
||||
sube = ivl_expr_parm(expr, sub_idx);
|
||||
|
||||
/* Special case: The next expression is a NUMBER that
|
||||
can be concatenated using %concati/vec4
|
||||
@@ -827,6 +838,13 @@ static void draw_concat_vec4(ivl_expr_t expr)
|
||||
}
|
||||
|
||||
draw_eval_vec4(sube);
|
||||
/* Evaluate, but skip any zero replication expressions in the
|
||||
* rest of this concatenation. */
|
||||
if ((ivl_expr_type(sube) == IVL_EX_CONCAT) &&
|
||||
(ivl_expr_repeat(sube) == 0)) {
|
||||
fprintf(vvp_out, " %%pop/vec4 1; skip zero replication\n");
|
||||
continue;
|
||||
}
|
||||
fprintf(vvp_out, " %%concat/vec4; draw_concat_vec4\n");
|
||||
}
|
||||
|
||||
@@ -934,7 +952,7 @@ static void draw_select_pad_vec4(ivl_expr_t expr)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the speical case of a call to the internal
|
||||
* This function handles the special case of a call to the internal
|
||||
* functions $ivl_darray_method$pop_back et al. The first (and only)
|
||||
* argument is the signal that represents a dynamic queue. Generate a
|
||||
* %qpop instruction to pop a value and push it to the vec4 stack.
|
||||
@@ -1014,7 +1032,7 @@ static void draw_string_vec4(ivl_expr_t expr)
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 8) {
|
||||
tmp <<= 8;
|
||||
tmp |= *p;
|
||||
tmp |= (unsigned long)*p;
|
||||
p += 1;
|
||||
tmp_wid += 8;
|
||||
if (tmp_wid == 32) {
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
static ivl_signal_t find_path_source_port(ivl_delaypath_t path)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
+33
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2011-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -22,11 +22,6 @@
|
||||
# include <assert.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These functions handle the blocking assignment. Use the %set
|
||||
* instruction to perform the actual assignment, and calculate any
|
||||
@@ -143,7 +138,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
|
||||
draw_eval_vec4(part_off_ex);
|
||||
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.part_select_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%dup/vec4;\n");
|
||||
fprintf(vvp_out, " %%ix/vec4 %u;\n", slice->u_.part_select_dynamic.word_idx_reg);
|
||||
fprintf(vvp_out, " %%ix/vec4 %d;\n", slice->u_.part_select_dynamic.word_idx_reg);
|
||||
fprintf(vvp_out, " %%part/u %u;\n", wid);
|
||||
|
||||
} else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {
|
||||
@@ -167,7 +162,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
|
||||
slice->u_.memory_word_dynamic.x_flag = allocate_flag();
|
||||
|
||||
draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%load/vec4a v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
|
||||
} else {
|
||||
@@ -263,7 +258,7 @@ static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
|
||||
break;
|
||||
|
||||
case SLICE_MEMORY_WORD_DYNAMIC:
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%flag_mov 4, %u;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||
fprintf(vvp_out, " %%store/vec4a v%p, %d, 0;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
|
||||
clr_flag(slice->u_.memory_word_dynamic.x_flag);
|
||||
@@ -381,7 +376,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
|
||||
/* Note that flag4 is set by the eval above. */
|
||||
assert(lsig);
|
||||
if (ivl_signal_type(lsig)==IVL_SIT_UWIRE) {
|
||||
fprintf(vvp_out, " %%force/vec4/off v%p_0, %u;\n",
|
||||
fprintf(vvp_out, " %%force/vec4/off v%p_0, %d;\n",
|
||||
lsig, offset_index);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n",
|
||||
@@ -397,7 +392,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
|
||||
assert(!lsig);
|
||||
ivl_type_t sub_type = draw_lval_expr(nest);
|
||||
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
||||
fprintf(vvp_out, " %%store/prop/v %u, %u;\n",
|
||||
fprintf(vvp_out, " %%store/prop/v %d, %u;\n",
|
||||
ivl_lval_property_idx(lval), lwid);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
@@ -444,11 +439,34 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||
fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
|
||||
|
||||
} else if (ivl_expr_value(rval) == IVL_VT_STRING) {
|
||||
/* Special case: vector to string casting */
|
||||
/* Special case: string to vector casting */
|
||||
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
||||
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
|
||||
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
|
||||
ivl_expr_signal(rval), ivl_lval_sig(lval));
|
||||
if (slices) free(slices);
|
||||
return 0;
|
||||
|
||||
} else if (ivl_expr_value(rval) == IVL_VT_DARRAY) {
|
||||
/* Special case: dynamic array to vector casting */
|
||||
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
||||
void*rval_addr = NULL;
|
||||
|
||||
/* Even more special case: function call returning dynamic array */
|
||||
if(ivl_expr_type(rval) == IVL_EX_UFUNC) {
|
||||
rval_addr = ivl_scope_port(ivl_expr_def(rval), 0);
|
||||
draw_ufunc_object(rval);
|
||||
/* We do not need to store the result, it is going to be
|
||||
converted to vector quite soon. */
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0; drop the result\n");
|
||||
} else {
|
||||
rval_addr = ivl_expr_signal(rval);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
|
||||
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
|
||||
rval_addr, ivl_lval_sig(lval));
|
||||
if (slices) free(slices);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
@@ -532,8 +550,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||
break;
|
||||
}
|
||||
|
||||
if (slices)
|
||||
free(slices);
|
||||
if (slices) free(slices);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -868,7 +885,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||
expression to the assignment is of an entire
|
||||
array object. */
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
@@ -882,7 +899,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||
|
||||
/* The property is a class object. */
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
errors += draw_eval_object(rval);
|
||||
if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog VVP Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2001-2011 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2001-2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
@@ -59,7 +59,10 @@ __inline__ static void draw_execute_header(ivl_design_t des)
|
||||
{
|
||||
const char*cp = ivl_design_flag(des, "VVP_EXECUTABLE");
|
||||
if (cp) {
|
||||
fprintf(vvp_out, "#! %s\n", cp);
|
||||
const char *extra_args = ivl_design_flag(des, "VVP_EXTRA_ARGS");
|
||||
if (!extra_args)
|
||||
extra_args = "";
|
||||
fprintf(vvp_out, "#! %s%s\n", cp, extra_args);
|
||||
#if !defined(__MINGW32__)
|
||||
fchmod(fileno(vvp_out), 0755);
|
||||
#endif
|
||||
|
||||
+2
-7
@@ -23,11 +23,6 @@
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
extern int debug_draw;
|
||||
|
||||
/*
|
||||
@@ -242,13 +237,13 @@ extern void draw_eval_real(ivl_expr_t ex);
|
||||
extern int draw_eval_bool64(ivl_expr_t ex);
|
||||
|
||||
/*
|
||||
* The draw_eval_string functio evaluates the expression as a string,
|
||||
* The draw_eval_string function evaluates the expression as a string,
|
||||
* and pushes the string onto the string stack.
|
||||
*/
|
||||
extern void draw_eval_string(ivl_expr_t ex);
|
||||
|
||||
/*
|
||||
* The draw_eval_string functio evaluates the expression as an object,
|
||||
* The draw_eval_string function evaluates the expression as an object,
|
||||
* and pushes the object onto the object stack.
|
||||
*/
|
||||
extern int draw_eval_object(ivl_expr_t ex);
|
||||
|
||||
+47
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,10 +21,7 @@
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
# include <stdbool.h>
|
||||
|
||||
static int show_statement(ivl_statement_t net, ivl_scope_t sscope);
|
||||
|
||||
@@ -114,14 +111,12 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
ivl_expr_t part_off_ex,
|
||||
unsigned nevents)
|
||||
{
|
||||
unsigned skip_assign = transient_id++;
|
||||
int word_ix_reg = 3;
|
||||
int part_off_reg = 0;
|
||||
int delay_index;
|
||||
unsigned long part_off = 0;
|
||||
|
||||
int error_flag = allocate_flag();
|
||||
fprintf(vvp_out, " %%flag_set/imm %d, 0;\n", error_flag);
|
||||
|
||||
/* Figure the constant part offset, if possible. If we can do
|
||||
so, then forget about the expression and use the calculated
|
||||
@@ -143,11 +138,13 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
|
||||
/* Calculate array word index into word index register */
|
||||
draw_eval_expr_into_integer(word_ix, word_ix_reg);
|
||||
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
|
||||
|
||||
if (part_off_ex) {
|
||||
part_off_reg = allocate_word();
|
||||
/* Save the index calculation error flag to a global. */
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
|
||||
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
|
||||
/* Add the error state of the part select to the global. */
|
||||
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
|
||||
|
||||
} else if (part_off != 0) {
|
||||
@@ -158,26 +155,35 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
part_off_reg, part_off);
|
||||
}
|
||||
|
||||
/* Calculated delay... */
|
||||
if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
delay_index = allocate_word();
|
||||
/* If needed save the index calculation error flag. */
|
||||
if (! part_off_ex) {
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
|
||||
}
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
if (word_ix_reg != 3) {
|
||||
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
||||
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
|
||||
clr_word(word_ix_reg);
|
||||
}
|
||||
/* Restore the error state since an undefined delay is okay. */
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
|
||||
lsig, part_off_reg, delay_index);
|
||||
|
||||
clr_word(delay_index);
|
||||
|
||||
/* Event control delay... */
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
/* If needed use the global error state. */
|
||||
if (part_off_ex) {
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
}
|
||||
fprintf(vvp_out, " %%assign/vec4/a/e v%p, %d;\n", lsig, part_off_reg);
|
||||
|
||||
/* Constant delay... */
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||
|
||||
@@ -185,15 +191,18 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu; Constant delay\n",
|
||||
delay_index, low_d, hig_d);
|
||||
if (word_ix_reg != 3) {
|
||||
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
||||
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
|
||||
clr_word(word_ix_reg);
|
||||
}
|
||||
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %u;\n",
|
||||
/* If needed use the global error state. */
|
||||
if (part_off_ex) {
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
|
||||
}
|
||||
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
|
||||
lsig, part_off_reg, delay_index);
|
||||
clr_word(delay_index);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
|
||||
|
||||
clr_flag(error_flag);
|
||||
@@ -662,7 +671,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||
|
||||
/* Duplicate the case expression so that the cmp
|
||||
instructions below do not completely erase the
|
||||
value. Do this in fromt of each compare. */
|
||||
value. Do this in front of each compare. */
|
||||
fprintf(vvp_out, " %%dup/vec4;\n");
|
||||
draw_eval_vec4(cex);
|
||||
|
||||
@@ -758,7 +767,7 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The referene value... */
|
||||
/* The reference value... */
|
||||
fprintf(vvp_out, " %%dup/real;\n");
|
||||
/* The guard value... */
|
||||
draw_eval_real(cex);
|
||||
@@ -1043,7 +1052,14 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
||||
|
||||
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
||||
assert(ivl_signal_dimensions(rsig) != 0);
|
||||
assert(number_is_immediate(rword_idx, IMM_WID, 0));
|
||||
if (!number_is_immediate(rword_idx, IMM_WID, 0)) {
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: procedural continuous "
|
||||
"assignments are not yet fully supported. The RHS of "
|
||||
"this assignment will only be evaluated once, at the "
|
||||
"time the assignment statement is executed.\n",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net));
|
||||
return;
|
||||
}
|
||||
/* An out-of-range or undefined index will have been
|
||||
converted to a canonical offset of 1'bx. Skip the
|
||||
assignment in this case. */
|
||||
@@ -1321,7 +1337,7 @@ static int show_stmt_do_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
the result. If the expression evaluates to true, then
|
||||
branch to the top label. */
|
||||
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
|
||||
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u;\n",
|
||||
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %d;\n",
|
||||
thread_count, top_label, use_flag);
|
||||
clr_flag(use_flag);
|
||||
|
||||
@@ -1665,7 +1681,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
the result. If the expression evaluates to false, then
|
||||
branch to the out label. */
|
||||
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %u;\n",
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %d;\n",
|
||||
thread_count, out_label, use_flag);
|
||||
clr_flag(use_flag);
|
||||
|
||||
@@ -1696,19 +1712,16 @@ static int show_delete_method(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_push_frontback_method(ivl_statement_t net)
|
||||
static int show_push_frontback_method(ivl_statement_t net, bool is_front)
|
||||
{
|
||||
const char*stmt_name = ivl_stmt_name(net);
|
||||
|
||||
show_stmt_file_line(net, "queue: push_back");
|
||||
|
||||
const char*type_code = "?";
|
||||
if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0)
|
||||
const char*type_code;
|
||||
if (is_front) {
|
||||
show_stmt_file_line(net, "queue: push_front");
|
||||
type_code = "qf";
|
||||
else if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0)
|
||||
} else {
|
||||
show_stmt_file_line(net, "queue: push_back");
|
||||
type_code = "qb";
|
||||
else
|
||||
type_code = "??";
|
||||
}
|
||||
|
||||
unsigned parm_count = ivl_stmt_parm_count(net);
|
||||
if (parm_count != 2)
|
||||
@@ -1750,10 +1763,10 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
return show_delete_method(net);
|
||||
|
||||
if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0)
|
||||
return show_push_frontback_method(net);
|
||||
return show_push_frontback_method(net, true);
|
||||
|
||||
if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0)
|
||||
return show_push_frontback_method(net);
|
||||
return show_push_frontback_method(net, false);
|
||||
|
||||
show_stmt_file_line(net, "System task call.");
|
||||
|
||||
@@ -2308,7 +2321,7 @@ int draw_process(ivl_process_t net, void*x)
|
||||
fprintf(vvp_out, " .scope S_%p;\n", scope);
|
||||
|
||||
/* Generate the entry label. Just give the thread a number so
|
||||
that we ar certain the label is unique. */
|
||||
that we are certain the label is unique. */
|
||||
fprintf(vvp_out, "T_%u ;\n", thread_count);
|
||||
|
||||
/* Draw the contents of the thread. */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user