Compare commits

...

111 Commits

Author SHA1 Message Date
Stephen Williams 3d14281e0d Prepare for version 10.2 2017-08-24 08:22:49 -07:00
Stephen Williams 2564554178 Minor tweak to some assertions. 2017-08-24 08:18:55 -07:00
Martin Whitaker 8cd697fd24 Fix for br1019 - allow multiple array words to be attached to a vpi callback.
Normally there is at most one signal attached to a vvp functor, but
due to port collapsing, there can be more than one. If these signals
are array words, we need to trigger vpi callbacks on all the associated
arrays when the functor value changes.

(cherry picked from commit ac87138c44)
2017-08-12 12:31:14 +01:00
Cary R 306d2fb53b V10: Fix class versus struct warning in clang 2017-06-19 21:26:35 -07:00
Martin Whitaker 52b497f74c Don't allow localparams to be overridden (GitHub issue #157)
Currently we only issue a warning if a parameter override references
a parameter that doesn't exist, so do the same in this case.

(cherry picked from commit 42422d9940)
2017-06-16 21:11:18 +01:00
Martin Whitaker ce7f28202a Ensure value passed to named event via vpi_put_value() is initialised.
The __vpiNamedEvent::vpi_put_value() function ignores the value, but
intermediate code looks at it.

(cherry picked from commit e2be64558b)
2017-06-15 09:15:31 +01:00
Martin Whitaker 49bea6a01a Implement vpi_put_value() for named events (GitHub issue #158).
(cherry picked from commit 3de7c234f7)
2017-06-15 08:52:15 +01:00
Martin Whitaker 8ab100c1c7 Fix for GitHub issue #152 - segfault on gate connection syntax error.
If there is a syntax error in the source code, pform_makegate may be
passed a null list of port connections. The error is already reported,
so we just need to ignore it.

(cherry picked from commit 8a5cbd4415)
2017-04-21 21:44:27 +01:00
Martin Whitaker 177ae7c220 Improved error checking for defparam values supplied on the command line.
Fixes GitHub issue #139 plus various assertion failures when invalid
values are specified.

(cherry picked from commit 3c91630b53)
2017-01-29 20:25:04 +00:00
Martin Whitaker b04d5a9068 Fix for GitHub issue #142 - assertion failure when parameter expression
contains undefined variable.

(cherry picked from commit 8f6f999ea7)
2017-01-29 20:24:56 +00:00
Martin Whitaker b8c8f03037 Add library search path option to iverilog-vpi (GitHub issue #145).
(cherry picked from commit 4e2ba29dc6)
2017-01-29 20:24:47 +00:00
Stephen Williams 38013f7a34 Sorry message for procedural assertion statements. 2017-01-10 12:18:38 -08:00
Cary R 561638a31f Allocate the correct amount of memory when escaping a string 2017-01-08 20:46:29 -08:00
Martin Whitaker bb91512e75 Fix for GitHub issue #128 - disable CONCATZ generation for vhdl target.
(cherry picked from commit b4e8a12309)
2016-11-25 22:36:19 +00:00
Martin Whitaker 09ff851483 Fix for GitHub issue #130 part 2 : assertion failure on unsupported cast.
(cherry picked from commit 7cac4677bf)
2016-11-25 22:36:00 +00:00
Martin Whitaker 19d8f43e9b Fix for GitHub issue #130 part 1 - null dereference when assigning int to enum.
(cherry picked from commit 002f118bb5)
2016-11-25 22:35:37 +00:00
Henry Wong ce88deaa97 Fix segfault when error in multi-dimensional part select.
(cherry picked from commit 182c08b528)
2016-11-25 21:33:47 +00:00
Henry Wong 1a8b19baf2 Fix null-pointer when trying to dump null statements.
(cherry picked from commit 69a96112e8)
2016-11-25 21:33:41 +00:00
Henry Wong b3cf533b3c Pop current_block_stack after for_variable_declaration and foreach.
(cherry picked from commit f827e4f748)
2016-11-25 21:33:33 +00:00
Martin Whitaker ba3856ebb0 Fix indentation in previous patch.
(cherry picked from commit 991d7d7582)
2016-10-20 16:49:37 +01:00
Henry Wong c06e2790a7 Adding implementation of NetEvWait::nex_input to handle event controls inside always@(*) blocks
(cherry picked from commit 1f9bf656ed)
2016-10-20 16:49:29 +01:00
Maciej Suminski 6e460a6a3f Fixed warnings about shifting a negative value 2016-10-14 23:41:11 +01:00
Maciej Suminski dbc536c4fb Added missing brackets
(cherry picked from commit 3710d35dd1)
2016-10-14 23:22:26 +01:00
Stephen Williams 5e41c86d01 Merge branch 'v10-branch' of github.com:steveicarus/iverilog into v10-branch 2016-10-14 10:31:58 -07:00
Martin Whitaker 572124e1e9 Allow library files to be specified on the iverilog command line.
This was already supported in command files, using the '-v' flag.
'-v' is already in use on the command line, so use '-l' instead,
and make that an alias for '-v' in command files.

(cherry picked from commit 7ddc514518)
2016-10-02 19:17:24 +01:00
Martin Whitaker 37ecdb4cfb Stop tgt-vvp from generating .alias records.
(partial backport of commit d44c814bab)

Net arrays can be handled by nets directly, instead of creating
.alias records. But keep support for .alias records in vvp. to
maintain backwards compatibility.
2016-09-17 19:49:26 +01:00
Martin Whitaker a11dc8b472 Backport Nexus::has_floating_input() from master branch.
Needed to support check for output port coercion.
2016-09-17 19:40:05 +01:00
Martin Whitaker e7852f8f9c Fix for GitHub issue #127 - coerce output ports to inout when necessary.
(cherry picked from commit 080dd0323d)
2016-09-17 19:24:04 +01:00
Martin Whitaker 9449c46865 Use gn_system_verilog() where appropriate.
Replace explicit comparisons against generation_flag with calls to
the gn_system_verilog helper function, both for code clarity and
to fix a couple of bugs. Also simplify the implementation of the
function, as we already rely on the generation_flag enumeration
being an ordered list.

(cherry picked from commit 3c9b39846c)
2016-09-17 19:23:48 +01:00
Martin Whitaker 8a780ece56 Merge branch 'v10-branch' of github.com:steveicarus/iverilog into v10-branch 2016-08-15 20:49:51 +01:00
Cary R 8bb4777789 Fix getting timeunit outside of module to use a defined check value 2016-08-14 17:26:31 -07:00
Cary R 3b705d95a6 Update fstapi.c to latest from GTKWave 2016-08-14 12:47:15 -07:00
Martin Whitaker f9559853f1 Fix for br1007 - out-of-range constant bit select should be a warning.
An out-of-range constant bit select on the LHS of an assignment was being
treated as an error, whereas an out-of range constant part select would
only result in a warning. In any other context, either case would result
in a warning, so convert the error to a warning.

In addition, all warnings for out-of-range or undefined constant bit/part
selects should be controlled by -Wselect-range.

(cherry picked from commit b51e58fa9d)
2016-08-08 22:26:05 +01:00
Martin Whitaker cda95c1554 Fix vlog95 target to handle hierarchical references in root-level tasks.
(cherry picked from commit 8461e1d9c4)
2016-07-26 22:04:05 +01:00
Martin Whitaker 4066031add Fix for GitHub issue #104 - assigning hierarchical signal from top level task.
When emitting a design, all scopes must be emitted before emitting any
top level task/function/method definitions, otherwise hierarchical
references can't always be resolved.

(cherry picked from commit 2bc42fc6e2)
2016-07-26 22:03:59 +01:00
Martin Whitaker d6d50e9b68 Update vlog95 target to handle timescales for root scope tasks/functions.
(cherry picked from commit b1b91f49c8)
2016-07-23 00:15:55 +01:00
Martin Whitaker 0ffbb2b1de Fix for GitHub issue #115 - synthesis aborts on case with max guard of 0.
The calculation of the required multiplexer width was incorrect for
the corner case of a single guard value of zero.

(cherry picked from commit 27213f2af8)
2016-07-23 00:15:43 +01:00
Martin Whitaker 9b55a3d67f Support timescales in design units that aren't inside a module.
SystemVerilog allows tasks, functions, and classes to be defined at the
root level or inside packages, so we can't rely on an enclosing module
being present to provide the timescale.

(cherry picked from commit 7bed181f68)
2016-07-23 00:15:15 +01:00
Martin Whitaker 07623bef2e Fix assignment of outputs from class methods.
As for inputs, skip over the implicit 'this' parameter.

(cherry picked from commit e316cc708b)
2016-07-23 00:13:07 +01:00
Martin Whitaker 73d688c313 Fix for br1003 - prevent segfault when delays are used outside a module.
(cherry picked from commit b8f9ed27c5)
2016-07-23 00:12:57 +01:00
Martin Whitaker 6155986d1c Fix for br1005 - segfault when SV queue is declared inside a class.
For now, output a "sorry" message to indicate this is not yet
supported.

(cherry picked from commit ad1101cc80)
2016-07-11 20:13:52 +01:00
Martin Whitaker face462cc2 Partial fix for br1006 - allow part selects in path declarations.
This just enables the compiler to parse path declarations that
contain part selects. As for bit selects, the part select is
discarded, and if elaboration of specify blocks is enabled,
the path declaration will be applied to the entire vector. If
elaboration is enabled, a warning message will now be output
when a bit or part select is discarded.

(cherry picked from commit ad87704809)
2016-07-10 20:25:39 +01:00
Martin Whitaker a5f6329500 Improved fix for GitHub issue #112.
This does a better job of setting the intermediate expression types
and widths when calculating the canonical index into a packed array.
It still doesn't properly handle out-of-bound indices (br953).

(cherry picked from commit 7f612270b3)
2016-07-10 13:38:44 +01:00
Martin Whitaker 3e13594816 Fix for GitHub issue 112 - index calculation for >2D packed arrays.
(cherry picked from commit 1448210f28)
2016-07-10 13:38:36 +01:00
Martin Whitaker 99138eafb1 Fix vector width calculation for multi-dimensional packed arrays.
(cherry picked from commit d496b095ff)
2016-07-10 13:38:23 +01:00
Martin Whitaker 86968e3752 Fix for GitHub issue #106 - prevent VPI writes during read-only synch.
(cherry picked from commit 8234f1845d)
2016-06-09 21:29:32 +01:00
Martin Whitaker 27a46f4afe Fix for GitHub issue #105 - fully support SV macro escape sequences.
The existing support for ``, `", and `\`" did not work in nested macro
definitions. Note that the new implementation only detects and replaces
these sequences inside the macro text (as required by the IEEE standard),
whereas the old implementation would detect and replace them anywhere in
the source files.

(cherry picked from commit 332170d36b)
2016-06-06 20:26:52 +01:00
Martin Whitaker d770199550 Add tgt-vvp sorry message for unsupported mixed NB/CA to vector. 2016-05-10 23:02:04 +01:00
Martin Whitaker 06f6a72770 Fix for GitHub issue #103 - vvp assertion failure on part select propagation.
The implementation of vvp_fun_part_pv::recv_vec4_pv was incorrect, and
propagated the incoming widths rather than the stored widths.

(cherry picked from commit 0c66116f51)
2016-05-10 22:41:58 +01:00
Maciej Suminski 30257e0914 ivl: Support for part selection in multidimensional packed ports assignment.
(cherry picked from commit b4baace4b1)
2016-04-19 21:32:38 +01:00
Maciej Suminski b2281b0e65 ivl: Fixed slice base calculation
when range is rising (e.g. logic [0:3] arr) or when it
starts with a non-zero integer (e.g. logic [4:1] arr).

(cherry picked from commit de775975e8)
2016-04-19 21:26:35 +01:00
Maciej Suminski 161cebb178 vvp: Corrected vvp_net_fun_t::recv_vec4_pv() (commit de968e18)
(cherry picked from commit 9cf1dcbae2)
2016-04-19 21:04:48 +01:00
Martin Whitaker b46d8b8389 Fix for br974 - support SV types in non-ansi port declarations.
(cherry picked from commit 6ba2bee977)
2016-04-19 20:47:33 +01:00
Martin Whitaker 2689ebacfe Extended fix for GitHub issue #99.
Most vvp functors need to support recv_vec4_pv. Any that are strength-aware
also need to support recv_vec8_pv. Note the simplifying assumption that is
documented in the base class recv_vec4_pv_ implementation.

(cherry picked from commit 6e5ed73b09)
2016-04-19 20:46:55 +01:00
Martin Whitaker 5bbb054173 Add check for explicit lifetime when initialising static variables.
If a static variable declared in a task, function, or block has an
initialisation expression, SystemVerilog requires the declaration to
have an explicit static lifetime. This is supposed to be a compile
error, but for now just output a warning.

Implementing this required adding support in the parser for explicit
lifetimes in variable declarations. For now, just output an error if
the user asks for a lifetime that isn't the default for that scope.

(cherry picked from commit 9538c81d34)
2016-04-19 20:43:25 +01:00
Martin Whitaker 7d2eeb0137 Added support for default subroutine lifetimes (SystemVerilog).
(cherry picked from commit 6e718c2e0c)
2016-04-19 20:43:14 +01:00
Martin Whitaker 4aef636559 Variable initialization blocks should be unamed.
Also add file/line info to initial process.

(cherry picked from commit 72bb63cf42)
2016-04-19 20:41:48 +01:00
Martin Whitaker 72fc3d712d For SystemVerilog, run variable initialization before main simulation starts.
(cherry picked from commit 54feb89bf5)
2016-04-19 20:41:25 +01:00
Martin Whitaker 3f75f6b155 Fully support variable initialization in tasks/functions/named blocks.
(cherry picked from commit 635adfc01e)
2016-04-19 20:40:14 +01:00
Martin Whitaker 9be3fc3a56 Fix GitHub issue #99 - recv_vec4_pv not implemented for arithmetic functors.
Also initialise the stored operand values to 'bz instead of 'bx to get
the correct results when bits are not driven.

(cherry picked from commit b2f7d09f0d)
2016-04-04 22:41:10 +01:00
Larry Doolittle aa2260f4fa Capitalize Verilog in a few places
(cherry picked from commit 89edf62206)
2016-04-02 22:42:26 +01:00
Martin Whitaker 6974613bff Fix for GitHub issue #96 - support mixed constant/variable delays in vvp.
If all three rise/fall/decay delay values are constant, we can use
the vvp .delay statement variant that takes three literal numbers.
If not, we have to use the variant that takes three net inputs. If
some of the delay values are constant, we need to create constant
drivers for those delay inputs.

(cherry picked from commit 20104c92c8)
2016-04-02 20:04:08 +01:00
Martin Whitaker 8bd4e9d481 Refactor to use new pad_to_width/cast_to_width functions.
(cherry picked from commit 7f475d4210)
2016-03-25 22:42:20 +00:00
Martin Whitaker 04ae07f03c Fix for GitHub issue #94 - enhance support for SystemVerilog size casting.
Allow the size expression to be any constant expression. Also ensure that
the expression width and type are correctly calculated and applied.

(cherry picked from commit dc1c3a4043)
2016-03-25 22:41:50 +00:00
Cary R d9be5318f9 Fix a cppcheck warning 2016-03-24 20:24:03 -07:00
Cary R 88cd5534c4 Use correct type when printing supply pull message 2016-03-15 03:51:39 -07:00
Martin Whitaker 3b577340ad Fix for br1001 - connect undriven wand/wor to 'bz in tgt-vvp.
(cherry picked from commit dbaf2471f2)
2016-03-13 16:45:22 +00:00
Martin Whitaker 583a31c121 Changed default for -gshared-loop-index to false. 2016-03-05 17:52:58 +00:00
Martin Whitaker a391c3ae28 Fix for br1000 - avoid infinite loop when processes share a for-loop index.
(cherry picked from commit b4d5248c67)
2016-03-05 17:45:37 +00:00
Martin Whitaker b551a783e8 Add support for real valued compressed assignment statements in tgt-vvp.
(cherry picked from commit a0bee0a76f)
2016-02-23 23:02:23 +00:00
Martin Whitaker 33db07ab8d Fix expression/operator type for compressed assignment/shift.
(cherry picked from commit a7066e3686)
2016-02-23 21:28:40 +00:00
Martin Whitaker e2aae72880 Fix expression type for compressed assignment statements.
A compressed assignment statement should give exactly the same
result as the equivalent uncompressed statement. This means
that the type (signed/unsigned) of the LHS affects the type of
the RHS expression (unlike in normal assignments). We need to
take care that bit/part selects and concatenations are correctly
identified as unsigned values, even in the cases where they
reduce to a single whole signal.

(cherry picked from commit 0199ad129d)
2016-02-23 21:27:55 +00:00
Martin Whitaker ec9897af5a Fix lval extension for compressed assignment in constant function.
The type of extension (zero/sign) is determined by the expression
type, not the operand type, so we need to cast to the expression
type before extending the value.

(cherry picked from commit 241b6723e5)
2016-02-23 21:22:25 +00:00
Martin Whitaker 2771abf86a Fix compressed assignments to concatenations.
When loading a lval concatenation, tgt-vvp was loading the elements
in the wrong order for the %concat instruction.

(cherry picked from commit b77d758f19)
2016-02-23 21:22:03 +00:00
Martin Whitaker b0461787c8 Extended constant function assignment operator support to real values.
(cherry-picked from master branch)

Also output a "sorry" message if the LHS is a concatenation.
2016-02-22 23:34:27 +00:00
Martin Whitaker 6f41576930 Add support for SystemVerilog assignment operators in constant functions.
(cherry-picked from master branch)
2016-02-22 22:24:11 +00:00
Stephen Williams cc7516eab3 Minor release update. 2016-02-10 11:39:12 -08:00
Stephen Williams 1a5ae96540 Fix broken "inherits dimensions from var/net" warning.
(cherry picked from commit 12c39aa4bb)
2016-02-10 11:23:44 -08:00
Stephen Williams 1ea8a13bf8 Prepare for 10.1 release. 2016-02-06 17:23:23 -08:00
Stephen Williams 490884cf7b Add the -Wimplicit-dimensions warning.
(cherry picked from commit f3647578d4)

Conflicts:
	scripts/devel-stub.conf
2016-02-06 16:48:43 -08:00
Martin Whitaker ca1d7ccffe Temporary fix for br993 - assertion failure in flip-flop synthesis.
(cherry-picked from master branch)

Synthesis does not currently support some commonly used styles for
representing flip-flops, e.g.

  q <= 0;
  if (en) q <= 1;

or

  if (clr) q <= 0;
  if (set) q <= 1;

For now, output a "sorry" message.
2016-01-30 22:44:26 +00:00
Martin Whitaker faf9bfe158 Fix for br994 - assertion failure when synthesising a mux.
(cherry-picked from master branch)

The elaborator allows the RHS of assignment to be wider than the
LHS. When using an if statement to represent a mux, this meant the
mux inputs could be different widths, resulting in an assertion
failure during synthesis. The fix is to prune the RHS to match the
LHS for each assignment. This has the benefit of minimising the
mux width.
2016-01-30 20:19:05 +00:00
Martin Whitaker 086ce04cf5 Temporary fix for br995 - assignment to memory not supported in synthesis.
(cherry-picked from master branch)

For now, output a "sorry" message.
2016-01-30 17:05:09 +00:00
Martin Whitaker 7b7231c417 Fix for br999 - incorrect result from binary comparison.
(cherry-picked from master branch)

When a binary (in)equality comparison has a constant left operand,
the tgt-vvp code generator swaps the left and right operands to
allow the cmpi instruction to be used. The code for swapping the
operands was incorrect.
2016-01-07 19:23:36 +00:00
Cary R d7b919f6d0 Update cppcheck suppression file 2015-12-19 11:58:38 -08:00
Cary R 9b34a96cb9 V10: Fix some compile warnings 2015-12-19 11:15:32 -08:00
Cary R 90cf0e5794 VHDL-10: fix a compile warning and add some missing newlines 2015-12-19 10:50:42 -08:00
Cary R 818379b9bc GTKWave (fstapi.c) needs realpath() so check for it 2015-12-19 09:11:56 -08:00
Cary R 9fbb7f84e6 A VHDL ExpAttribute() can share the base so don't just delete them 2015-12-13 19:02:26 -08:00
Cary R ed7d6c1002 Fix memory leak found with valgrind 2015-12-13 14:56:49 -08:00
Cary R a4306dbac1 Fix the modpath delay to ignore bits that are not changing 2015-10-21 22:02:17 -07:00
Cary R a682e13d82 Update LZ4 files to latest from GTKWave 2015-10-02 10:32:45 -07:00
Cary R 643e0a984e Fix some cppcheck warnings 2015-10-02 09:44:02 -07:00
Stephen Williams 63d2059b85 Have scope auto-rename generate names that use the index numbers
In generate blocks such as for loops, there may be many generated
scopes that have the same generated name. But in these cases, there
is an index number in the hname that can be used. So do so.

(cherry picked from commit 81f54ec0cb)
2015-09-30 09:48:56 -07:00
Martin Whitaker d9e09ceb59 Fix for GitHub issue #79 - literal numbers must have at least one digit.
(cherry-picked from master branch)

The bug report was for an assertion failure when a number contained only
a lowline (e.g. 'b_), but the standard says that a number can't start
with a lowline (e.g. 'b_1). The parser already rejected these cases for
decimal numbers, but allowed them through for binary/octal/hex numbers.
2015-09-23 00:15:50 +01:00
Stephen Williams 6d0ab9978f rpm spec file aware of stable versions. 2015-08-23 14:41:41 -07:00
Martin Whitaker e25cdf86ac Fix for br992 - prevent assertion/crash on declarations outside a module.
parse.y has been updated to allow declarations outside a module (legal
in SystemVerilog), but not all types of declaration are supported yet.
Output a sorry or error message as appropriate.
2015-08-21 00:11:59 +01:00
Stephen Williams 13bff8c50d Remove synthesis warning.
(cherry picked from commit d2c72a126d)
2015-08-20 13:53:13 -07:00
Stephen Williams b1b017251a Fix windres input version string for v10 and later. 2015-08-20 13:50:57 -07:00
Cary R e13a52637a A concatenation or the expression being replicated must have a non-zero width 2015-08-18 16:23:33 -07:00
Stephen Williams 4803f0d12b Rework vvp file version checking. 2015-08-17 15:38:27 -07:00
Martin Whitaker be44289fc0 Updated a few more copyright dates. 2015-08-17 22:23:43 +01:00
Martin Whitaker e682166253 Fix for br991 - compiler crashes due to null statements.
The reported problem was caused by a null statement in a case statement,
which caused the check for an infinite loop to fail. Further testing
exposed more problems with null statements in loop statements - these
caused crashes earlier in elaboration.
2015-08-17 22:19:36 +01:00
Larry Doolittle e2a1f21896 Squelch just a few trailing spaces in source code 2015-08-17 11:44:55 -07:00
Larry Doolittle cb73accd84 Spelling fixes 2015-08-17 11:34:58 -07:00
Stephen Williams a66361a4f2 Update some copyright dates. 2015-08-17 08:02:51 -07:00
Martin Whitaker 1159de0482 Fixed version number in vvp man page. 2015-08-16 23:11:54 +01:00
Stephen Williams ac5d4114ad Update v10 vvp examples to have correct version number 2015-08-16 12:30:43 -07:00
Stephen Williams 85f796fda2 Release compatible version stamp 2015-08-15 14:26:33 -07:00
Stephen Williams 8612ec5452 Main copyright date update. 2015-08-15 14:15:32 -07:00
Stephen Williams 870a351944 Change Version numbering scheme. 2015-08-15 13:42:57 -07:00
148 changed files with 3572 additions and 1673 deletions

View File

@ -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)
{
}

13
HName.h
View File

@ -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();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -35,9 +35,6 @@ Module::Module(LexicalScope*parent, perm_string n)
program_block = false;
uc_drive = UCD_NONE;
timescale_warn_done = false;
time_unit = 0;
time_precision = 0;
time_from_timescale = false;
}
Module::~Module()

View File

@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -121,10 +121,6 @@ class Module : public PScopeExtra, public LineInfo {
map<perm_string,PExpr*> attributes;
/* These are the timescale for this module. The default is
set by the `timescale directive. */
int time_unit, time_precision;
bool time_from_timescale;
bool timescale_warn_done;
/* The module has a list of generate schemes that appear in

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2012 Stephen Williams <steve@icarus.com>
* Copyright (c) 1998-2016 Stephen Williams <steve@icarus.com>
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -137,7 +137,7 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
}
PECastSize::PECastSize(unsigned si, PExpr*b)
PECastSize::PECastSize(PExpr*si, PExpr*b)
: size_(si), base_(b)
{
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PExpr_H
#define IVL_PExpr_H
/*
* Copyright (c) 1998-2014 Stephen Williams <steve@icarus.com>
* Copyright (c) 1998-2016 Stephen Williams <steve@icarus.com>
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -971,7 +971,7 @@ class PECallFunction : public PExpr {
class PECastSize : public PExpr {
public:
explicit PECastSize(unsigned expr_wid, PExpr*base);
explicit PECastSize(PExpr*size, PExpr*base);
~PECastSize();
void dump(ostream &out) const;
@ -984,7 +984,7 @@ class PECastSize : public PExpr {
width_mode_t&mode);
private:
unsigned size_;
PExpr* size_;
PExpr* base_;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008,2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008,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
@ -19,21 +19,9 @@
# include "PScope.h"
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
bool LexicalScope::var_init_needs_explicit_lifetime() const
{
}
PScope::PScope(perm_string n)
: LexicalScope(0), name_(n)
{
}
PScope::~PScope()
{
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
it != typedefs.end(); ++it)
delete it->second;
return false;
}
PWire* LexicalScope::wires_find(perm_string name)
@ -45,17 +33,26 @@ PWire* LexicalScope::wires_find(perm_string name)
return (*cur).second;
}
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
: PScope(n, parent)
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{
time_unit = 0;
time_precision = 0;
time_from_timescale = false;
}
PScopeExtra::PScopeExtra(perm_string n)
: PScope(n)
PScope::~PScope()
{
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
it != typedefs.end(); ++it)
delete it->second;
}
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
: PScope(n, parent)
{
}
PScopeExtra::~PScopeExtra()
{
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-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
@ -36,6 +36,7 @@ class PProcess;
class PClass;
class PTask;
class PWire;
class Statement;
class Design;
class NetScope;
@ -52,10 +53,14 @@ class NetScope;
class LexicalScope {
public:
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
lifetime_t default_lifetime;
struct range_t {
// True if this is an exclude
bool exclude_flag;
@ -108,6 +113,9 @@ class LexicalScope {
// creating implicit nets.
map<perm_string,LineInfo*> genvars;
// Variable initializations in this scope
vector<Statement*> var_inits;
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
@ -117,6 +125,8 @@ class LexicalScope {
LexicalScope* parent_scope() const { return parent_; }
virtual bool var_init_needs_explicit_lifetime() const;
protected:
void dump_typedefs_(ostream&out, unsigned indent) const;
@ -130,6 +140,10 @@ class LexicalScope {
void dump_wires_(ostream&out, unsigned indent) const;
void dump_var_inits_(ostream&out, unsigned indent) const;
bool elaborate_var_inits_(Design*des, NetScope*scope) const;
private:
LexicalScope*parent_;
};
@ -145,12 +159,17 @@ class PScope : public LexicalScope {
// modules do not nest in Verilog, the parent must be nil for
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, LexicalScope*parent);
PScope(perm_string name);
explicit PScope(perm_string name, LexicalScope*parent =0);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
/* These are the timescale for this scope. The default is
set by the `timescale directive or, in SystemVerilog,
by timeunit and timeprecision statements. */
int time_unit, time_precision;
bool time_from_timescale;
protected:
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
@ -168,14 +187,13 @@ class PScope : public LexicalScope {
class PScopeExtra : public PScope {
public:
PScopeExtra(perm_string, LexicalScope*parent);
PScopeExtra(perm_string);
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
~PScopeExtra();
/* Task definitions within this module */
std::map<perm_string,PTask*> tasks;
std::map<perm_string,PFunction*> funcs;
/* class definitions within this module. */
/* Class definitions within this module. */
std::map<perm_string,PClass*> classes;
/* This is the lexical order of the classes, and is used by
elaboration to choose an elaboration order. */

View File

@ -30,6 +30,11 @@ PTaskFunc::~PTaskFunc()
{
}
bool PTaskFunc::var_init_needs_explicit_lifetime() const
{
return default_lifetime == STATIC;
}
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
{
assert(ports_ == 0);

View File

@ -41,6 +41,8 @@ class PTaskFunc : public PScope, public LineInfo {
PTaskFunc(perm_string name, LexicalScope*parent);
~PTaskFunc();
bool var_init_needs_explicit_lifetime() const;
void set_ports(std::vector<pform_tf_port_t>*p);
void set_this(class_type_t*use_type, PWire*this_wire);

View File

@ -115,6 +115,11 @@ PBlock::~PBlock()
delete list_[idx];
}
bool PBlock::var_init_needs_explicit_lifetime() const
{
return default_lifetime == STATIC;
}
PChainConstructor* PBlock::extract_chain_constructor()
{
if (list_.empty())

View File

@ -108,7 +108,8 @@ class PAssign_ : public Statement {
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
ivl_variable_type_t lv_type,
unsigned lv_width) const;
unsigned lv_width,
bool force_unsigned =false) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
@ -182,6 +183,8 @@ class PBlock : public PScope, public Statement {
BL_TYPE bl_type() const { return bl_type_; }
bool var_init_needs_explicit_lifetime() const;
// This is only used if this block is the statement list for a
// constructor. We look for a PChainConstructor as the first
// statement, and if it is there, extract it.

View File

@ -1,7 +1,7 @@
#ifndef IVL_compiler_H
#define IVL_compiler_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -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;
@ -138,7 +142,8 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
/* This is the generation of Verilog that the compiler is asked to
support. Then there are also more detailed controls for more
specific language features. */
specific language features. Note that the compiler often assumes
this is an ordered list. */
enum generation_t {
GN_VER1995 = 1,
GN_VER2001_NOCONFIG = 2,
@ -182,25 +187,24 @@ extern bool gn_strict_ca_eval_flag;
standard expression width rules. */
extern bool gn_strict_expr_width_flag;
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign, then return true. This will be true
for SystemVerilog */
static inline bool gn_var_can_be_uwire(void)
/* If this flag is true, then don't add a for-loop control variable
to an implicit event_expression list if it is only used inside the
loop. */
extern bool gn_shared_loop_index_flag;
static inline bool gn_system_verilog(void)
{
if (generation_flag == GN_VER2005_SV ||
generation_flag == GN_VER2009 ||
generation_flag == GN_VER2012)
if (generation_flag >= GN_VER2005_SV)
return true;
return false;
}
static inline bool gn_system_verilog(void)
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign), then return true. This will be true
for SystemVerilog */
static inline bool gn_var_can_be_uwire(void)
{
if (generation_flag == GN_VER2005_SV ||
generation_flag == GN_VER2009 ||
generation_flag == GN_VER2012)
return true;
return false;
return gn_system_verilog();
}
static inline bool gn_modules_nest(void)

View File

@ -1,7 +1,7 @@
#ifndef IVL_config_H /* -*- c++ -*- */
#define IVL_config_H
/*
* 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
@ -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

View File

@ -242,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)

View File

@ -86,7 +86,7 @@ config.h: $(srcdir)/config.h.in Makefile
# 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

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -124,7 +124,8 @@ int cmdfile_stack_ptr = 0;
"-c" { return TOK_Dc; }
"-f" { return TOK_Dc; }
/* Notice the -v flag. */
/* Notice the -l or -v flag. */
"-l" { return TOK_Dv; }
"-v" { return TOK_Dv; }
/* Notice the -y flag. */

View File

@ -1,14 +1,15 @@
.TH iverilog 1 "Aug 7th, 2015" "" "Version %M.%m.%n %E"
.TH iverilog 1 "Oct 2nd, 2016" "" "Version %M.%n%E"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value]
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g2012|\-g<feature>]
[\-Pparameter=value] [\-pflag=value] [\-dname]
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] [\-lfile]
sourcefile
.SH DESCRIPTION
.PP
@ -30,7 +31,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.
@ -133,12 +134,29 @@ parameter assignment is evaluated as a lossless expression, as is any
expression containing an unsized constant number, and unsized constant
numbers are not truncated to integer width.
.TP 8
.B -gshared-loop-index\fI|\fP-gno-shared-loop-index
Enable or disable (default) the exclusion of for-loop control variables
from implicit event_expression lists. When enabled, if a for-loop control
variable (loop index) is only used inside the for-loop statement, the
compiler will not include it in an implicit event_expression list it
calculates for that statement or any enclosing statement. This allows
the same control variable to be used in multiple processes without risk
of entering an infinite loop caused by each process triggering all other
processes that use the same varaible. For strict compliance with the
standards, this behaviour should be disabled.
.TP 8
.B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched
for Verilog include files. The \fB\-I\fP switch may be used many times
to specify several directories to search, the directories are searched
in the order they appear on the command line.
.TP 8
.B -l\fIfile\fP
Add the specified file to the list of source files to be compiled,
but mark it as a library file. All modules contained within that
file will be treated as library modules, and only elaborated if
they are instantiated by other modules in the design.
.TP 8
.B -M\fIpath\fP
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
compatibility.
@ -402,6 +420,15 @@ A \fB\-c\fP or \fB\-f\fP token prefixes a command file, exactly like it
does on the command line. The cmdfile may be on the same line or the
next non-comment line.
.TP 8
.B -l\ \fIfile\fP -v\ \fIfile\fP
A \fB\-l\fP token prefixes a library file in the command file,
exactly like it does on the command line. The parameter to the \fB\-l\fP
flag may be on the same line or the next non-comment line. \fB\-v\fP is
an alias for \fB\-l\fP, provided for compatibility with other simulators.
Variables in the \fIfile\fP are substituted.
.TP 8
.B -y\ \fIlibdir\fP
A \fB\-y\fP token prefixes a library directory in the command file,
@ -532,7 +559,7 @@ Tips on using, debugging, and developing the compiler can be found at
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2015 Stephen Williams
Copyright \(co 2002\-2016 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-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
@ -44,7 +44,7 @@ const char HELP[] =
" [-M [mode=]depfile] [-m module]\n"
" [-N file] [-o filename] [-p flag=value]\n"
" [-s topmodule] [-t target] [-T min|typ|max]\n"
" [-W class] [-y dir] [-Y suf] source_file(s)\n"
" [-W class] [-y dir] [-Y suf] [-l file] source_file(s)\n"
"\n"
"See the man page for details.";
@ -128,6 +128,7 @@ const char*gen_icarus = "icarus-misc";
const char*gen_io_range_error = "io-range-error";
const char*gen_strict_ca_eval = "no-strict-ca-eval";
const char*gen_strict_expr_width = "no-strict-expr-width";
const char*gen_shared_loop_index = "no-shared-loop-index";
const char*gen_verilog_ams = "no-verilog-ams";
/* Boolean: true means use a default include dir, false means don't */
@ -496,6 +497,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 +508,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 +543,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) {
@ -720,6 +731,12 @@ static int process_generation(const char*name)
else if (strcmp(name,"no-strict-expr-width") == 0)
gen_strict_expr_width = "no-strict-expr-width";
else if (strcmp(name,"shared-loop-index") == 0)
gen_shared_loop_index = "shared-loop-index";
else if (strcmp(name,"no-shared-loop-index") == 0)
gen_shared_loop_index = "no-shared-loop-index";
else if (strcmp(name,"verilog-ams") == 0)
gen_verilog_ams = "verilog-ams";
@ -745,7 +762,8 @@ static int process_generation(const char*name)
" icarus-misc | no-icarus-misc\n"
" io-range-error | no-io-range-error\n"
" strict-ca-eval | no-strict-ca-eval\n"
" strict-expr-width | no-strict-expr-width\n");
" strict-expr-width | no-strict-expr-width\n"
" shared-loop-index | no-shared-loop-index\n");
return 1;
}
@ -910,7 +928,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@ -965,6 +983,10 @@ int main(int argc, char **argv)
process_include_dir(optarg);
break;
case 'l':
process_file_name(optarg, 1);
break;
case 'M':
if (process_depfile(optarg) != 0)
return -1;
@ -1047,19 +1069,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" : "");
@ -1107,6 +1120,7 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
fprintf(iconfig_file, "generation:%s\n", gen_shared_loop_index);
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -90,7 +90,7 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
ivl_variable_type_t lv_type, unsigned lv_width,
PExpr*expr, bool need_const)
PExpr*expr, bool need_const, bool force_unsigned)
{
if (debug_elaborate) {
cerr << expr->get_fileline() << ": elaborate_rval_expr: "
@ -135,7 +135,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
}
return elab_and_eval(des, scope, expr, context_wid, need_const,
false, lv_type);
false, lv_type, force_unsigned);
}
/*
@ -675,10 +675,7 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
NetExpr*tmp = new NetEBComp(op_, lp, rp);
tmp->set_line(*this);
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
@ -716,10 +713,7 @@ NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
NetExpr*tmp = new NetEBLogic(op_, lp, rp);
tmp->set_line(*this);
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
@ -1035,8 +1029,7 @@ NetExpr*PEBShift::elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
tmp->set_line(*this);
tmp = new NetESelect(lp, tmp, 1);
tmp->set_line(*this);
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(true);
tmp = pad_to_width(tmp, expr_wid, true, *this);
delete rp;
return tmp;
@ -1414,23 +1407,7 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
<< " from expr_width()=" << expr->expr_width() << endl;
}
/* If the expression is a const, then replace it with a new
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
tmp->cast_signed(signed_flag_);
if (wid != tmp->expr_width()) {
tmp = new NetEConst(verinum(tmp->value(), wid));
tmp->set_line(*this);
delete expr;
}
return tmp;
}
NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->cast_signed(signed_flag_);
tmp->set_line(*this);
return tmp;
return cast_to_width(expr, wid, signed_flag_, *this);
}
/*
@ -1606,10 +1583,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
if (missing_parms || parm_errors)
return 0;
NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(fun, expr_wid, signed_flag_, *this);
}
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
@ -1666,10 +1640,7 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
NetExpr*tmp = new NetEAccess(branch, nature);
tmp->set_line(*this);
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
/*
@ -2281,10 +2252,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
if(res->darray_type())
return func;
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(func, expr_wid, signed_flag_, *this);
}
cerr << get_fileline() << ": internal error: Unable to locate "
@ -2521,22 +2489,54 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
{
expr_width_ = size_;
ivl_assert(*this, size_);
ivl_assert(*this, base_);
NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true);
NetEConst*size_ce = dynamic_cast<NetEConst*>(size_ex);
expr_width_ = size_ce ? size_ce->value().as_ulong() : 0;
delete size_ex;
if (expr_width_ == 0) {
cerr << get_fileline() << ": error: Cast size expression "
"must be constant and greater than zero." << endl;
des->errors += 1;
return 0;
}
width_mode_t tmp_mode = PExpr::SIZED;
base_->test_width(des, scope, tmp_mode);
return size_;
if (!type_is_vectorable(base_->expr_type())) {
cerr << get_fileline() << ": error: Cast base expression "
"must be a vector type." << endl;
des->errors += 1;
return 0;
}
expr_type_ = base_->expr_type();
min_width_ = expr_width_;
signed_flag_ = base_->has_sign();
return expr_width_;
}
NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned) const
unsigned expr_wid, unsigned flags) const
{
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS);
NetESelect*sel = new NetESelect(sub, 0, size_);
sel->set_line(*this);
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
return sel;
ivl_assert(*this, size_);
ivl_assert(*this, base_);
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), flags);
// Perform the cast. The extension method (zero/sign), if needed,
// depends on the type of the base expression.
NetExpr*tmp = cast_to_width(sub, expr_width_, base_->has_sign(), *this);
// Pad up to the expression width. The extension method (zero/sign)
// depends on the type of enclosing expression.
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
@ -2640,17 +2640,15 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
if((base_->expr_type() != IVL_VT_BOOL) &&
(base_->expr_type() != IVL_VT_LOGIC)) {
cerr << get_fileline() << ": cannot be casted to string." << endl;
cerr << get_fileline() << ": cannot be cast to a string." << endl;
ivl_assert(*this, false);
}
return expr;
}
cerr << get_fileline() << ": sorry: I don't know how to cast expression." << endl;
ivl_assert(*this, false);
return expr;
cerr << get_fileline() << ": sorry: This cast operation is not yet supported." << endl;
return 0;
}
unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
@ -2842,17 +2840,16 @@ 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;
return 0;
}
NetExpr*tmp = pad_to_width(concat, expr_wid, *this);
tmp->cast_signed(signed_flag_);
NetExpr*tmp = pad_to_width(concat, expr_wid, signed_flag_, *this);
concat_depth -= 1;
return tmp;
@ -3769,10 +3766,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (!tmp) return 0;
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
// If the identifier names a signal (a register or wire)
@ -3808,10 +3802,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
<< ", tmp=" << *tmp << endl;
}
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
// If the identifier is a named event
@ -3911,9 +3902,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
member_comp);
if (!tmp) return 0;
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
}
if (net->class_type() != 0) {
@ -4492,7 +4481,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
<< "Elaborate parameter <" << path_
<< "> as enumeration constant." << *etmp << endl;
tmp = etmp->dup_expr();
tmp = pad_to_width(tmp, expr_wid, *this);
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
} else {
perm_string name = peek_tail_name(path_);
@ -5011,6 +5000,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
ivl_assert(*this, index_tail.lsb == 0);
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
if (!mux)
return 0;
if (const netdarray_t*darray = net->sig()->darray_type()) {
// Special case: This is a select of a dynamic
@ -5686,7 +5677,6 @@ unsigned PETernary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
} else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) {
expr_type_ = IVL_VT_LOGIC;
} else {
ivl_assert(*this, tru_type == fal_type);
expr_type_ = tru_type;
}
if (expr_type_ == IVL_VT_REAL) {
@ -6082,7 +6072,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
}
tmp->set_line(*this);
}
tmp = pad_to_width(tmp, expr_wid, *this);
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
break;
case '&': // Reduction AND
@ -6100,7 +6090,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
}
tmp = new NetEUReduce(op_, ip);
tmp->set_line(*this);
tmp = pad_to_width(tmp, expr_wid, *this);
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
break;
case '~':

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -138,6 +138,9 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
continue;
}
/* A concatenation is always unsigned. */
tmp->set_signed(false);
/* Link the new l-value to the previous one. */
NetAssign_*last = tmp;
while (last->more)
@ -287,13 +290,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
}
// We are processing the tail of a string of names. For
// example, the verilog may be "a.b.c", so we are processing
// example, the Verilog may be "a.b.c", so we are processing
// "c" at this point. (Note that if method_name is not nil,
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
const name_component_t&name_tail = path_.back();
// Use the last index to determine what kind of select
// (bit/part/etc) we are processing. For example, the verilog
// (bit/part/etc) we are processing. For example, the Verilog
// may be "a.b.c[1][2][<index>]". All but the last index must
// be simple expressions, only the <index> may be a part
// select etc., so look at it to determine how we will be
@ -399,6 +402,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
/* No select expressions. */
NetAssign_*lv = new NetAssign_(reg);
lv->set_signed(reg->get_signed());
return lv;
}
@ -687,20 +691,24 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
unsigned long lwid;
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, rcl);
cerr << get_fileline() << ": warning: L-value packed array "
<< "select of " << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
if (warn_ob_select) {
cerr << get_fileline()
<< ": warning: L-value packed array select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
}
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
return true;
// The index is undefined and this is a bit select.
} else {
cerr << get_fileline() << ": warning: L-value bit select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
if (warn_ob_select) {
cerr << get_fileline()
<< ": warning: L-value bit select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
}
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
return true;
}
@ -797,12 +805,10 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
// Constant bit select that does something useful.
long loff = reg->sb_to_idx(prefix_indices,lsb);
if (loff < 0 || loff >= (long)reg->vector_width()) {
cerr << get_fileline() << ": error: bit select "
if (warn_ob_select && (loff < 0 || loff >= (long)reg->vector_width())) {
cerr << get_fileline() << ": warning: bit select "
<< reg->name() << "[" <<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
@ -868,10 +874,13 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
ivl_assert(*this, reg);
if (! parts_defined_flag) {
cerr << get_fileline() << ": warning: L-value part select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
if (warn_ob_select) {
cerr << get_fileline()
<< ": warning: L-value part select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
}
// Use a width of two here so we can distinguish between an
// undefined bit or part select.
lv->set_part(new NetEConst(verinum(verinum::Vx)), 2);
@ -934,11 +943,11 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
}
/* If the part select extends beyond the extremes of the
variable, then report an error. Note that loff is
variable, then output a warning. Note that loff is
converted to normalized form so is relative the
variable pins. */
if (loff < 0 || moff >= (long)reg->vector_width()) {
if (warn_ob_select && (loff < 0 || moff >= (long)reg->vector_width())) {
cerr << get_fileline() << ": warning: Part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;

View File

@ -328,39 +328,66 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
return false;
}
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
/* Detect reversed indices of a part select. */
if (lidx_tmp > midx_tmp) {
cerr << get_fileline() << ": error: Part select "
<< sig->name() << "[" << msb << ":"
<< lsb << "] indices reversed." << endl;
cerr << get_fileline() << ": : Did you mean "
<< sig->name() << "[" << lsb << ":"
<< msb << "]?" << endl;
long tmp = midx_tmp;
midx_tmp = lidx_tmp;
lidx_tmp = tmp;
des->errors += 1;
}
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
// Here we have a slice that doesn't have enough indices
// to get to a single slice. For example:
// wire [9:0][5:1] foo
// ... foo[4:3] ...
// Make this work by finding the indexed slices and
// creating a generated slice that spans the whole
// range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, lrc);
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
ivl_assert(*this, lrc);
ivl_assert(*this, lwid == mwid);
/* Warn about a part select that is out of range. */
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
cerr << get_fileline() << ": warning: Part select "
<< sig->name();
if (sig->unpacked_dimensions() > 0) {
cerr << "[]";
if (moff > loff) {
lidx = loff;
midx = moff + mwid - 1;
} else {
lidx = moff;
midx = loff + lwid - 1;
}
cerr << "[" << msb << ":" << lsb
<< "] is out of range." << endl;
}
/* This is completely out side the signal so just skip it. */
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
return false;
}
} else {
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
midx = midx_tmp;
lidx = lidx_tmp;
/* Detect reversed indices of a part select. */
if (lidx_tmp > midx_tmp) {
cerr << get_fileline() << ": error: Part select "
<< sig->name() << "[" << msb << ":"
<< lsb << "] indices reversed." << endl;
cerr << get_fileline() << ": : Did you mean "
<< sig->name() << "[" << lsb << ":"
<< msb << "]?" << endl;
long tmp = midx_tmp;
midx_tmp = lidx_tmp;
lidx_tmp = tmp;
des->errors += 1;
}
/* Warn about a part select that is out of range. */
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
cerr << get_fileline() << ": warning: Part select "
<< sig->name();
if (sig->unpacked_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << msb << ":" << lsb
<< "] is out of range." << endl;
}
/* This is completely out side the signal so just skip it. */
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
return false;
}
midx = midx_tmp;
lidx = lidx_tmp;
}
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -54,6 +54,15 @@
# include <cassert>
# include "ivl_assert.h"
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
{
scope->time_unit(pscope->time_unit);
scope->time_precision(pscope->time_precision);
scope->time_from_timescale(pscope->time_from_timescale);
des->set_precision(pscope->time_precision);
}
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
@ -523,6 +532,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
class_scope->set_class_def(use_class);
use_class->set_class_scope(class_scope);
use_class->set_definition_scope(scope);
set_scope_timescale(des, class_scope, pclass);
// Collect the properties, elaborate them, and add them to the
// elaborated class definition.
@ -654,8 +664,10 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
if (scope==0)
if (scope==0) {
set_scope_timescale(des, task_scope, task);
des->add_root_task(task_scope, task);
}
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: "
@ -719,8 +731,10 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
if (scope==0)
if (scope==0) {
set_scope_timescale(des, task_scope, task);
des->add_root_task(task_scope, task);
}
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: "
@ -793,7 +807,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;
}
@ -1750,11 +1764,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
instances[idx] = my_scope;
// Set time units and precision.
my_scope->time_unit(mod->time_unit);
my_scope->time_precision(mod->time_precision);
my_scope->time_from_timescale(mod->time_from_timescale);
des->set_precision(mod->time_precision);
set_scope_timescale(des, my_scope, mod);
// Look for module parameter replacements. The "replace" map
// maps parameter name to replacement expression that is

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -976,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 */
@ -1168,6 +1185,14 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
NetLogic*pull = 0;
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Generate a SUPPLY pull for the ";
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
else cerr << "supply1";
cerr << " net." << endl;
}
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
? NetLogic::PULLUP
: NetLogic::PULLDOWN;
@ -1178,14 +1203,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
pull->pin(0).drive1(IVL_DR_SUPPLY);
des->add_node(pull);
wtype = NetNet::WIRE;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Generate a SUPPLY pull for the ";
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
else cerr << "supply1";
cerr << " net." << endl;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@ -17,11 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PExpr.h"
# include "pform_types.h"
# include "netlist.h"
# include "netclass.h"
# include "netdarray.h"
# include "netenum.h"
# include "netqueue.h"
# include "netparray.h"
# include "netscalar.h"
# include "netstruct.h"
@ -245,6 +247,16 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
return res;
}
// Special case: if the dimension is null:nil. this is a queue.
if (cur->second==0 && dynamic_cast<PENull*>(cur->first)) {
cerr << get_fileline() << ": sorry: "
<< "SV queues inside classes are not yet supported." << endl;
des->errors += 1;
ivl_type_s*res = new netqueue_t(btype);
return res;
}
vector<netrange_t> dimensions;
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -36,6 +36,7 @@
# include "PEvent.h"
# include "PGenerate.h"
# include "PPackage.h"
# include "PScope.h"
# include "PSpec.h"
# include "netlist.h"
# include "netenum.h"
@ -50,6 +51,9 @@
# include "ivl_assert.h"
// Implemented in elab_scope.cc
extern void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope);
void PGate::elaborate(Design*, NetScope*) const
{
cerr << "internal error: what kind of gate? " <<
@ -787,7 +791,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
if (check_delay_count(des)) return;
NetExpr* rise_time, *fall_time, *decay_time;
eval_delays(des, scope, rise_time, fall_time, decay_time);
eval_delays(des, scope, rise_time, fall_time, decay_time, true);
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
@ -1421,6 +1425,16 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
<< prts[0]->name() << " is coerced to inout." << endl;
}
if (!prts.empty() && (prts[0]->port_type() == NetNet::POUTPUT)
&& (prts[0]->type() != NetNet::REG)
&& prts[0]->pin(0).nexus()->has_floating_input()
&& pins[idx]->is_collapsible_net(des, scope)) {
prts[0]->port_type(NetNet::PINOUT);
cerr << pins[idx]->get_fileline() << ": warning: output port "
<< prts[0]->name() << " is coerced to inout." << endl;
}
// Elaborate the expression that connects to the
// module[s] port. sig is the thing outside the module
// that connects to the port.
@ -2000,7 +2014,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
PDelays tmp_del;
tmp_del.set_delays(overrides_, false);
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
decay_expr);
decay_expr, true);
}
}
@ -2325,7 +2339,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
ivl_type_t lv_net_type,
ivl_variable_type_t lv_type,
unsigned lv_width) const
unsigned lv_width,
bool force_unsigned) const
{
ivl_assert(*this, rval_);
@ -2334,7 +2349,7 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
// should look into fixing calls to this method to pass a
// net_type instead of the separate lv_width/lv_type values.
NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width,
rval(), is_constant_);
rval(), is_constant_, force_unsigned);
if (!is_constant_ || !rv) return rv;
@ -2452,10 +2467,35 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0;
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv));
// Compressed assignments should behave identically to the
// equivalent uncompressed assignments. This means we need
// to take the type of the LHS into account when determining
// the type of the RHS expression.
bool force_unsigned;
switch (op_) {
case 'l':
case 'r':
case 'R':
// The right-hand operand of shift operations is
// self-determined.
force_unsigned = false;
break;
default:
force_unsigned = !lv->get_signed();
break;
}
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(),
count_lval_width(lv), force_unsigned);
if (rv == 0) return 0;
NetAssign*cur = new NetAssign(lv, op_, rv);
// The ivl_target API doesn't support signalling the type
// of a lval, so convert arithmetic shifts into logical
// shifts now if the lval is unsigned.
char op = op_;
if ((op == 'R') && !lv->get_signed())
op = 'r';
NetAssign*cur = new NetAssign(lv, op, rv);
cur->set_line(*this);
return cur;
@ -2677,11 +2717,16 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
return bl;
}
if (lv->enumeration() &&
! lv->enumeration()->matches(rv->enumeration())) {
cerr << get_fileline() << ": error: "
<< "Enumeration type mismatch in assignment." << endl;
des->errors += 1;
if (lv->enumeration()) {
if (! rv->enumeration()) {
cerr << get_fileline() << ": error: "
"This assignment requires an explicit cast." << endl;
des->errors += 1;
} else if (! lv->enumeration()->matches(rv->enumeration())) {
cerr << get_fileline() << ": error: "
"Enumeration type mismatch in assignment." << endl;
des->errors += 1;
}
}
NetAssign*cur = new NetAssign(lv, rv);
@ -2868,14 +2913,27 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
des->errors += 1;
return 0;
}
assert(nscope);
elaborate_behaviors_(des, nscope);
}
NetBlock*cur = new NetBlock(type, nscope);
if (nscope) {
// Handle any variable initialization statements in this scope.
// For automatic scopes these statements need to be executed
// each time the block is entered, so add them to the main
// block. For static scopes, put them in a separate process
// that will be executed at the start of simulation.
if (nscope->is_auto()) {
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
NetProc*tmp = var_inits[idx]->elaborate(des, nscope);
if (tmp) cur->append(tmp);
}
} else {
elaborate_var_inits_(des, nscope);
}
}
if (nscope == 0)
nscope = scope;
@ -3778,7 +3836,9 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
expression that can be a target to a procedural
assignment, including a memory word. */
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
for (unsigned idx = use_this?1:0 ; idx < parm_count ; idx += 1) {
size_t parms_idx = use_this? idx-1 : idx;
NetNet*port = def->port(idx);
@ -3794,12 +3854,12 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
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 (parms_idx < parms_.size() && parms_[parms_idx]) {
lv = parms_[parms_idx]->elaborate_lval(des, scope, false, false);
if (lv == 0) {
cerr << parms_[idx]->get_fileline() << ": error: "
cerr << parms_[parms_idx]->get_fileline() << ": error: "
<< "I give up on task port " << (idx+1)
<< " expression: " << *parms_[idx] << endl;
<< " expression: " << *parms_[parms_idx] << endl;
}
} else if (port->port_type() == NetNet::POUTPUT) {
// Output ports were skipped earlier, so
@ -4039,9 +4099,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;
}
@ -4572,7 +4641,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);
@ -4778,7 +4851,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);
@ -4809,7 +4886,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) {
@ -4903,7 +4984,11 @@ 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
@ -4972,7 +5057,6 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
des->errors += 1;
return;
}
assert(def);
ivl_assert(*this, statement_);
@ -4985,6 +5069,31 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
return;
}
// Handle any variable initialization statements in this scope.
// For automatic functions, these statements need to be executed
// each time the function is called, so insert them at the start
// of the elaborated definition. For static functions, put them
// in a separate process that will be executed before the start
// of simulation.
if (is_auto_) {
// Get the NetBlock of the statement. If it is not a
// NetBlock then create one to wrap the initialization
// statements and the original statement.
NetBlock*blk = dynamic_cast<NetBlock*> (st);
if ((blk == 0) && (var_inits.size() > 0)) {
blk = new NetBlock(NetBlock::SEQU, scope);
blk->set_line(*this);
blk->append(st);
st = blk;
}
for (unsigned idx = var_inits.size(); idx > 0; idx -= 1) {
NetProc*tmp = var_inits[idx-1]->elaborate(des, scope);
if (tmp) blk->prepend(tmp);
}
} else {
elaborate_var_inits_(des, scope);
}
def->set_proc(st);
}
@ -5025,7 +5134,11 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
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
@ -5143,11 +5256,6 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
void PTask::elaborate(Design*des, NetScope*task) const
{
// Elaborate any processes that are part of this scope that
// aren't the definition itself. This can happen, for example,
// with variable initialization statements in this scope.
elaborate_behaviors_(des, task);
NetTaskDef*def = task->task_def();
assert(def);
@ -5166,6 +5274,31 @@ void PTask::elaborate(Design*des, NetScope*task) const
}
}
// Handle any variable initialization statements in this scope.
// For automatic tasks , these statements need to be executed
// each time the task is called, so insert them at the start
// of the elaborated definition. For static tasks, put them
// in a separate process that will be executed before the start
// of simulation.
if (is_auto_) {
// Get the NetBlock of the statement. If it is not a
// NetBlock then create one to wrap the initialization
// statements and the original statement.
NetBlock*blk = dynamic_cast<NetBlock*> (st);
if ((blk == 0) && (var_inits.size() > 0)) {
blk = new NetBlock(NetBlock::SEQU, task);
blk->set_line(*this);
blk->append(st);
st = blk;
}
for (unsigned idx = var_inits.size(); idx > 0; idx -= 1) {
NetProc*tmp = var_inits[idx-1]->elaborate(des, task);
if (tmp) blk->prepend(tmp);
}
} else {
elaborate_var_inits_(des, task);
}
def->set_proc(st);
}
@ -5205,7 +5338,11 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
{
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
NetProc*sub = statement_->elaborate(des, scope);
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;
@ -5618,6 +5755,10 @@ bool Module::elaborate(Design*des, NetScope*scope) const
(*gt)->elaborate(des, scope);
}
// Elaborate the variable initialization statements, making a
// single initial process out of them.
result_flag &= elaborate_var_inits_(des, scope);
// Elaborate the behaviors, making processes out of them. This
// involves scanning the PProcess* list, creating a NetProcTop
// for each process.
@ -5695,6 +5836,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
@ -5729,6 +5873,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"
@ -5804,6 +5949,8 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; ++ cur )
(*cur)->elaborate(des, scope);
elaborate_var_inits_(des, scope);
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); ++ cur )
(*cur)->elaborate(des, scope);
@ -5839,6 +5986,44 @@ bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
return result_flag;
}
bool LexicalScope::elaborate_var_inits_(Design*des, NetScope*scope) const
{
if (var_inits.size() == 0)
return true;
NetProc*proc = 0;
if (var_inits.size() == 1) {
proc = var_inits[0]->elaborate(des, scope);
} else {
NetBlock*blk = new NetBlock(NetBlock::SEQU, 0);
bool flag = true;
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
NetProc*tmp = var_inits[idx]->elaborate(des, scope);
if (tmp)
blk->append(tmp);
else
flag = false;
}
if (flag) proc = blk;
}
if (proc == 0)
return false;
NetProcTop*top = new NetProcTop(scope, IVL_PR_INITIAL, proc);
if (const LineInfo*li = dynamic_cast<const LineInfo*>(this)) {
top->set_line(*li);
}
if (gn_system_verilog()) {
top->attribute(perm_string::literal("_ivl_schedule_init"),
verinum(1));
}
des->add_process(top);
scope->set_var_init(proc);
return true;
}
class elaborate_package_t : public elaborator_work_item_t {
public:
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
@ -6072,6 +6257,7 @@ Design* elaborate(list<perm_string>roots)
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
NetScope*scope = des->make_package_scope(pac->first);
scope->set_line(pac->second);
set_scope_timescale(des, scope, pac->second);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
des->elaboration_work_list.push_back(es);
@ -6108,11 +6294,7 @@ Design* elaborate(list<perm_string>roots)
// Collect some basic properties of this scope from the
// Module definition.
scope->set_line(rmod);
scope->time_unit(rmod->time_unit);
scope->time_precision(rmod->time_precision);
scope->time_from_timescale(rmod->time_from_timescale);
des->set_precision(rmod->time_precision);
set_scope_timescale(des, scope, rmod);
// Save this scope, along with its definition, in the
// "root_elems" list for later passes.

View File

@ -507,7 +507,6 @@ int Design::emit(struct target_t*tgt) const
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope) {
scope->first->emit_scope(tgt);
scope->first->emit_defs(tgt);
}
// enumerate package scopes
@ -521,7 +520,6 @@ int Design::emit(struct target_t*tgt) const
const NetScope*use_scope = cur->second->class_scope();
cur->second->emit_scope(tgt);
tgt->class_type(use_scope, cur->second);
cur->second->emit_defs(tgt);
}
// enumerate root scopes
@ -548,6 +546,12 @@ int Design::emit(struct target_t*tgt) const
// emit task and function definitions
bool tasks_rc = true;
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope)
tasks_rc &= scope->first->emit_defs(tgt);
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur)
tasks_rc &= cur->second->emit_defs(tgt);
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope )
tasks_rc &= scope->second->emit_defs(tgt);

View File

@ -697,7 +697,9 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
// If the left value is longer check it against the pad bit.
if (res == verinum::V1) {
verinum::V pad = verinum::V0;
if (is_signed) pad = rv.get(rv.len()-1);
if (is_signed)
pad = rv.get(rv.len()-1);
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != pad) {
res = verinum::V0;
@ -708,12 +710,15 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
// If the right value is longer check it against the pad bit.
if (res == verinum::V1) {
verinum::V pad = verinum::V0;
if (is_signed) pad = lv.get(lv.len()-1);
if (is_signed)
pad = lv.get(lv.len()-1);
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
if (rv.get(idx) != pad)
if (rv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
}
if (ne_flag) {

View File

@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%m.%n %E"
.TH iverilog-vpi 1 "Jan 29th, 2017" "" "Version %M.%n%E"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
@ -26,6 +26,11 @@ becomes \fIfoo.vpi\fP.
Include the named library in the link of the VPI module. This allows
VPI modules to further reference external libraries.
.TP 8
.B -L\fIdirectory\fP
Add \fIdirectory\fP to the list of directories that will be searched
for library files.
.TP 8
.B -I\fIdirectory\fP
Add \fIdirectory\fP to the list of directories that will be searched
@ -115,7 +120,7 @@ iverilog(1), vvp(1),
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2015 Stephen Williams
Copyright \(co 2002\-2017 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0

View File

@ -35,6 +35,7 @@ CCSRC=
CXSRC=
OBJ=
LIB=
LIBDIR=
OUT=
INCOPT=
DEFS=
@ -81,6 +82,9 @@ do
-l*) LIB="$LIB $parm"
;;
-L*) LIBDIR="$LIBDIR $parm"
;;
-I*) INCOPT="$INCOPT $parm"
;;
@ -148,4 +152,4 @@ then
fi
echo "Making $OUT from $OBJ..."
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS

View File

@ -1,7 +1,7 @@
%option prefix="yy"
%{
/*
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -148,18 +148,38 @@ static void ifdef_leave(void)
free(cur);
}
#define YY_INPUT(buf,result,max_size) do { \
if (istack->file) { \
size_t rc = fread(buf, 1, max_size, istack->file); \
result = (rc == 0) ? YY_NULL : rc; \
} else { \
if (*istack->str == 0) \
result = YY_NULL; \
else { \
buf[0] = *istack->str++; \
result = 1; \
} \
} \
#define YY_INPUT(buf,result,max_size) do { \
if (istack->file) { \
size_t rc = fread(buf, 1, max_size, istack->file); \
result = (rc == 0) ? YY_NULL : rc; \
} else { \
/* We are expanding a macro. Handle the SV macro escape \
sequences. There doesn't seem to be any good reason \
not to allow them in traditional Verilog as well. */ \
while ((istack->str[0] == '`') && \
(istack->str[1] == '`')) { \
istack->str += 2; \
} \
if (*istack->str == 0) { \
result = YY_NULL; \
} else if ((istack->str[0] == '`') && \
(istack->str[1] == '"')) { \
istack->str += 2; \
buf[0] = '"'; \
result = 1; \
} else if ((istack->str[0] == '`') && \
(istack->str[1] == '\\')&& \
(istack->str[2] == '`') && \
(istack->str[3] == '"')) { \
istack->str += 4; \
buf[0] = '\\'; \
buf[1] = '"'; \
result = 2; \
} else { \
buf[0] = *istack->str++; \
result = 1; \
} \
} \
} while (0)
static int comment_enter = 0;
@ -242,12 +262,6 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
}
/* `" overrides the usual lexical meaning of " and `\`" indicates
that the expansion should include the escape sequence \".
*/
`\" { fputc('"', yyout); }
`\\`\" { fprintf(yyout, "\\\""); }
/* Strings do not contain preprocessor directives, but can expand
* macros. If that happens, they get expanded in the context of the
* string.
@ -514,29 +528,19 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
do_expand(0);
}
/* Stringified version of macro expansion. If the sequence `` is
* encountered inside a macro definition, we use the SystemVerilog
* handling of ignoring it so that identifiers can be constructed
* from arguments. If istack->file is NULL, we are reading text
* produced from a macro, so use SystemVerilog's handling;
* otherwise, use the special Icarus handling.
*/
/* Stringified version of macro expansion. This is an Icarus extension.
When expanding macro text, the SV usage of `` takes precedence. */
``[a-zA-Z_][a-zA-Z0-9_$]* {
if (istack->file == NULL)
fprintf(yyout, "%s", yytext+2);
else {
assert(do_expand_stringify_flag == 0);
do_expand_stringify_flag = 1;
fputc('"', yyout);
if (macro_needs_args(yytext+2))
yy_push_state(MA_START);
else
do_expand(0);
}
assert(istack->file);
assert(do_expand_stringify_flag == 0);
do_expand_stringify_flag = 1;
fputc('"', yyout);
if (macro_needs_args(yytext+2))
yy_push_state(MA_START);
else
do_expand(0);
}
`` { if (istack->file != NULL) ECHO; }
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
<MA_START>{W} {}

View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)";
"Copyright (c) 1999-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

View File

@ -4,7 +4,7 @@
%{
/*
* 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
@ -432,18 +432,28 @@ 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) {
if (!gn_system_verilog()) {
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
<< "Using SystemVerilog 'N bit vector. Use at least "
<< "-g2005-sv to remove this warning." << endl;
@ -469,7 +479,7 @@ TU [munpf]
/* This rule handles scaled time values for SystemVerilog. */
[0-9][0-9_]*(\.[0-9][0-9_]*)?{TU}?s {
if(generation_flag & (GN_VER2005_SV | GN_VER2009 | GN_VER2012)) {
if (gn_system_verilog()) {
yylval.text = strdupnew(yytext);
return TIME_LITERAL;
} else REJECT; }
@ -847,7 +857,7 @@ verinum*make_unsized_binary(const char*txt)
ptr += 1;
}
assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV));
assert((tolower(*ptr) == 'b') || gn_system_verilog());
if (tolower(*ptr) == 'b') {
ptr += 1;
} else {

15
main.cc
View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"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
@ -108,6 +108,7 @@ bool gn_assertions_flag = true;
bool gn_io_range_error_flag = true;
bool gn_strict_ca_eval_flag = false;
bool gn_strict_expr_width_flag = false;
bool gn_shared_loop_index_flag = false;
bool gn_verilog_ams_flag = false;
/*
@ -153,6 +154,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;
@ -343,6 +345,12 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
gn_strict_expr_width_flag = false;
} else if (strcmp(gen,"shared-loop-index") == 0) {
gn_shared_loop_index_flag = true;
} else if (strcmp(gen,"no-shared-loop-index") == 0) {
gn_shared_loop_index_flag = false;
} else {
}
}
@ -678,6 +686,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;
@ -1107,7 +1118,7 @@ int main(int argc, char*argv[])
/* Decide if we are going to allow system functions to be called
* as tasks. */
if (generation_flag >= GN_VER2005_SV) {
if (gn_system_verilog()) {
def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
}

View File

@ -43,6 +43,8 @@ NetAssign_::NetAssign_(NetAssign_*n)
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
{
more = 0;
signed_ = false;
turn_sig_to_wire_on_release_ = false;
}
NetAssign_::NetAssign_(NetNet*s)
@ -51,6 +53,7 @@ NetAssign_::NetAssign_(NetNet*s)
lwid_ = sig_->vector_width();
sig_->incr_lref();
more = 0;
signed_ = false;
turn_sig_to_wire_on_release_ = false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@ -88,6 +88,10 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
// fills in the context_map with local variables held by the scope.
scope()->evaluate_function_find_locals(loc, context_map);
// Execute any variable initialization statements.
if (const NetProc*init_proc = scope()->var_init())
init_proc->evaluate_function(loc, context_map);
if (debug_eval_tree && proc_==0) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "Function " << scope_path(scope())
@ -209,6 +213,98 @@ bool NetProc::evaluate_function(const LineInfo&,
return false;
}
void NetAssign::eval_func_lval_op_real_(const LineInfo&loc,
verireal&lv, verireal&rv) const
{
switch (op_) {
case '+':
lv = lv + rv;
break;
case '-':
lv = lv - rv;
break;
case '*':
lv = lv * rv;
break;
case '/':
lv = lv / rv;
break;
case '%':
lv = lv % rv;
break;
default:
cerr << "Illegal assignment operator: "
<< human_readable_op(op_) << endl;
ivl_assert(loc, 0);
}
}
void NetAssign::eval_func_lval_op_(const LineInfo&loc,
verinum&lv, verinum&rv) const
{
unsigned lv_width = lv.len();
bool lv_sign = lv.has_sign();
switch (op_) {
case 'l':
case 'R':
// The left operand is self-determined.
break;
case 'r':
// The left operand is self-determined, but we need to
// cast it to unsigned to get a logical shift.
lv.has_sign(false);
break;
default:
// The left operand must be cast to the expression type/size
lv.has_sign(rv.has_sign());
lv = cast_to_width(lv, rv.len());
}
switch (op_) {
case '+':
lv = lv + rv;
break;
case '-':
lv = lv - rv;
break;
case '*':
lv = lv * rv;
break;
case '/':
lv = lv / rv;
break;
case '%':
lv = lv % rv;
break;
case '&':
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
lv.set(idx, lv[idx] & rv[idx]);
break;
case '|':
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
lv.set(idx, lv[idx] | rv[idx]);
break;
case '^':
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
lv.set(idx, lv[idx] ^ rv[idx]);
break;
case 'l':
lv = lv << rv.as_unsigned();
break;
case 'r':
lv = lv >> rv.as_unsigned();
break;
case 'R':
lv = lv >> rv.as_unsigned();
break;
default:
cerr << "Illegal assignment operator: "
<< human_readable_op(op_) << endl;
ivl_assert(loc, 0);
}
lv = cast_to_width(lv, lv_width);
lv.has_sign(lv_sign);
}
bool NetAssign::eval_func_lval_(const LineInfo&loc,
map<perm_string,LocalVar>&context_map,
const NetAssign_*lval, NetExpr*rval_result) const
@ -269,18 +365,55 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width());
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
ivl_assert(loc, lval_const);
verinum lval_v = lval_const->value();
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
ivl_assert(loc, rval_const);
verinum rval_v = rval_const->value();
for (unsigned idx = 0 ; idx < rval_v.len() ; idx += 1)
lval_v.set(idx+base, rval_v[idx]);
verinum lpart(verinum::Vx, lval->lwidth());
if (op_) {
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
lpart.set(idx, lval_v[base+idx]);
eval_func_lval_op_(loc, lpart, rval_v);
} else {
lpart = cast_to_width(rval_v, lval->lwidth());
}
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
lval_v.set(idx+base, lpart[idx]);
delete base_result;
delete rval_result;
rval_result = new NetEConst(lval_v);
} else {
rval_result = fix_assign_value(lval->sig(), rval_result);
if (op_ == 0) {
rval_result = fix_assign_value(lval->sig(), rval_result);
} else if (dynamic_cast<NetECReal*>(rval_result)) {
NetECReal*lval_const = dynamic_cast<NetECReal*>(old_lval);
ivl_assert(loc, lval_const);
verireal lval_r = lval_const->value();
NetECReal*rval_const = dynamic_cast<NetECReal*>(rval_result);
ivl_assert(loc, rval_const);
verireal rval_r = rval_const->value();
eval_func_lval_op_real_(loc, lval_r, rval_r);
delete rval_result;
rval_result = new NetECReal(lval_r);
} else {
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
ivl_assert(loc, lval_const);
verinum lval_v = lval_const->value();
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
ivl_assert(loc, rval_const);
verinum rval_v = rval_const->value();
eval_func_lval_op_(loc, lval_v, rval_v);
delete rval_result;
rval_result = new NetEConst(lval_v);
}
}
if (old_lval)
@ -318,6 +451,13 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
ivl_assert(*this, rval_const);
if (op_) {
cerr << get_fileline() << ": sorry: Assignment operators "
"inside a constant function are not currently "
"supported if the LHS is a concatenation." << endl;
return false;
}
verinum rval_full = rval_const->value();
delete rval_result;
@ -369,6 +509,10 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
// Now collect the new locals.
subscope_->evaluate_function_find_locals(loc, local_context_map);
use_local_context_map = true;
// Execute any variable initialization statements.
if (const NetProc*init_proc = subscope_->var_init())
init_proc->evaluate_function(loc, local_context_map);
}
// Now use the local context map if there is any local

View File

@ -311,6 +311,20 @@ void Nexus::count_io(unsigned&inp, unsigned&out) const
}
}
bool Nexus::has_floating_input() const
{
bool found_input = false;
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
if (cur->get_dir() == Link::OUTPUT)
return false;
if (cur->get_dir() == Link::INPUT)
found_input = true;
}
return found_input;
}
bool Nexus::drivers_present() const
{
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2013 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
@ -404,6 +404,17 @@ NexusSet* NetDoWhile::nex_input(bool rem_out)
return result;
}
NexusSet* NetEvWait::nex_input(bool rem_out)
{
NexusSet*result;
if (statement_)
result = statement_->nex_input(rem_out);
else
result = new NexusSet;
return result;
}
NexusSet* NetForce::nex_input(bool)
{
cerr << get_fileline() << ": internal warning: NetForce::nex_input()"
@ -427,6 +438,15 @@ NexusSet* NetForLoop::nex_input(bool rem_out)
result->add(*tmp);
delete tmp;
if (gn_shared_loop_index_flag) {
tmp = new NexusSet();
for (unsigned idx = 0 ; idx < index_->pin_count() ; idx += 1)
tmp->add(index_->pin(idx).nexus(), 0, index_->vector_width());
result->rem(*tmp);
delete tmp;
}
return result;
}

View File

@ -56,6 +56,17 @@ void NetBlock::append(NetProc*cur)
}
}
void NetBlock::prepend(NetProc*cur)
{
if (last_ == 0) {
last_ = cur;
cur->next_ = cur;
} else {
cur->next_ = last_->next_;
last_->next_ = cur;
}
}
const NetProc* NetBlock::proc_first() const
{
if (last_ == 0)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2017 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
@ -139,6 +139,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
time_from_timescale_ = false;
}
var_init_ = 0;
switch (t) {
case NetScope::TASK:
task_ = 0;
@ -264,19 +265,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.
@ -285,7 +287,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;
}
@ -296,16 +300,16 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
*/
bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
{
bool flag = false;
if (parameters.find(key) == parameters.end())
return false;
if (parameters.find(key) != parameters.end()) {
param_expr_t&ref = parameters[key];
ref.val_expr = val;
ref.val_scope = scope;
flag = true;
}
param_expr_t&ref = parameters[key];
if (ref.local_flag)
return false;
return flag;
ref.val_expr = val;
ref.val_scope = scope;
return true;
}
bool NetScope::make_parameter_unannotatable(perm_string key)

View File

@ -557,7 +557,7 @@ void NetNet::calculate_slice_widths_from_packed_dims_(void)
ivl_assert(*this, ! slice_wids_.empty());
slice_wids_[0] = netrange_width(slice_dims_);
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1, cur++) {
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
}
}
@ -2743,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);
}
}
@ -2769,6 +2770,7 @@ DelayType NetCondit::delay_type() const
*/
DelayType NetDoWhile::delay_type() const
{
ivl_assert(*this, proc_);
return proc_->delay_type();
}
@ -2779,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_);
}
@ -2806,6 +2810,7 @@ DelayType NetPDelay::delay_type() const
DelayType NetRepeat::delay_type() const
{
ivl_assert(*this, statement_);
return get_loop_delay_type(expr_, statement_);
}
@ -2821,5 +2826,6 @@ DelayType NetUTask::delay_type() const
DelayType NetWhile::delay_type() const
{
ivl_assert(*this, proc_);
return get_loop_delay_type(cond_, proc_);
}

View File

@ -388,6 +388,10 @@ class Nexus {
is a variable, but also if this is a net with a force. */
bool assign_lval() const;
/* This method returns true if there are any inputs
attached to this nexus but no drivers. */
bool has_floating_input() const;
/* This method returns true if there are any drivers
(including variables) attached to this nexus. */
bool drivers_present() const;
@ -713,7 +717,7 @@ class NetNet : public NetObj, public PortType {
/* This method returns a reference to the packed dimensions
for the vector. These are arranged as a list where the
first range in the list (front) is the left-most range in
the verilog declaration. These packed dims are compressed
the Verilog declaration. These packed dims are compressed
to represent the dimensions of all the subtypes. */
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
@ -1020,6 +1024,13 @@ class NetScope : public Definitions, public Attrib {
TYPE type() const;
void print_type(ostream&) const;
// This provides a link to the variable initialisation process
// for use when evaluating a constant function. Note this is
// only used for static functions - the variable initialization
// for automatic functions is included in the function definition.
void set_var_init(const NetProc*proc) { var_init_ = proc; }
const NetProc* var_init() const { return var_init_; }
void set_task_def(NetTaskDef*);
void set_func_def(NetFuncDef*);
void set_class_def(netclass_t*);
@ -1250,6 +1261,8 @@ class NetScope : public Definitions, public Attrib {
vector<PortInfo> ports_;
const NetProc*var_init_;
union {
NetTaskDef*task_;
NetFuncDef*func_;
@ -2732,6 +2745,12 @@ class NetAssign_ {
void set_property(const perm_string&name);
inline perm_string get_property(void) const { return member_; }
// Determine if the assigned object is signed or unsigned.
// This is used when determining the expression type for
// a compressed assignment statement.
bool get_signed() const { return signed_; }
void set_signed(bool flag) { signed_ = flag; }
// Get the width of the r-value that this node expects. This
// method accounts for the presence of the mux, so it is not
// necessarily the same as the pin_count().
@ -2782,6 +2801,7 @@ class NetAssign_ {
// member/property if signal is a class.
perm_string member_;
bool signed_;
bool turn_sig_to_wire_on_release_;
// indexed part select base
NetExpr*base_;
@ -2849,6 +2869,8 @@ class NetAssign : public NetAssignBase {
map<perm_string,LocalVar>&ctx) const;
private:
void eval_func_lval_op_real_(const LineInfo&loc, verireal&lv, verireal&rv) const;
void eval_func_lval_op_(const LineInfo&loc, verinum&lv, verinum&rv) const;
bool eval_func_lval_(const LineInfo&loc, map<perm_string,LocalVar>&ctx,
const NetAssign_*lval, NetExpr*rval_result) const;
@ -2895,6 +2917,7 @@ class NetBlock : public NetProc {
NetScope* subscope() const { return subscope_; }
void append(NetProc*);
void prepend(NetProc*);
const NetProc*proc_first() const;
const NetProc*proc_next(const NetProc*cur) const;
@ -3323,6 +3346,7 @@ class NetEvWait : public NetProc {
// process? This method checks.
virtual bool is_synchronous();
virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&out);
virtual bool synth_async(Design*des, NetScope*scope,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -203,7 +203,7 @@ static NetExpr* make_add_expr(NetExpr*expr, long val)
}
verinum val_v (val, expr->expr_width());
val_v.has_sign(true);
val_v.has_sign(expr->has_sign());
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@ -236,7 +236,7 @@ static NetExpr* make_add_expr(const LineInfo*loc, NetExpr*expr1, NetExpr*expr2)
static NetExpr* make_sub_expr(long val, NetExpr*expr)
{
verinum val_v (val, expr->expr_width());
val_v.has_sign(true);
val_v.has_sign(expr->has_sign());
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@ -249,7 +249,26 @@ static NetExpr* make_sub_expr(long val, NetExpr*expr)
}
/*
* Multiple an existing expression by a signed positive number.
* Subtract a signed constant from an existing expression.
*/
static NetExpr* make_sub_expr(NetExpr*expr, long val)
{
verinum val_v (val, expr->expr_width());
val_v.has_sign(expr->has_sign());
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
NetEBAdd*res = new NetEBAdd('-', expr, val_c, expr->expr_width(),
expr->has_sign());
res->set_line(*expr);
return res;
}
/*
* Multiply an existing expression by a signed positive number.
* This does a lossless multiply, so the arguments will need to be
* sized to match the output size.
*/
@ -258,7 +277,7 @@ static NetExpr* make_mult_expr(NetExpr*expr, unsigned long val)
const unsigned val_wid = ceil(log2((double)val)) ;
unsigned use_wid = expr->expr_width() + val_wid;
verinum val_v (val, use_wid);
val_v.has_sign(true);
val_v.has_sign(expr->has_sign());
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@ -434,17 +453,41 @@ NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
-- pcur;
}
long sb;
if (pcur->get_msb() >= pcur->get_lsb())
sb = pcur->get_lsb();
else
sb = pcur->get_msb();
long sb = min(pcur->get_lsb(), pcur->get_msb());
long loff;
reg->sb_to_slice(indices, sb, loff, lwid);
base = make_mult_expr(base, lwid);
base = make_add_expr(base, loff);
unsigned min_wid = base->expr_width();
if ((sb < 0) && !base->has_sign()) min_wid += 1;
if (min_wid < num_bits(pcur->get_lsb())) min_wid = pcur->get_lsb();
if (min_wid < num_bits(pcur->get_msb())) min_wid = pcur->get_msb();
base = pad_to_width(base, min_wid, *base);
if ((sb < 0) && !base->has_sign()) {
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
tmp->set_line(*base);
tmp->cast_signed(true);
base = tmp;
}
if (pcur->get_msb() >= pcur->get_lsb()) {
if (pcur->get_lsb() != 0)
base = make_sub_expr(base, pcur->get_lsb());
base = make_mult_expr(base, lwid);
min_wid = base->expr_width();
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
if (loff != 0) min_wid += 1;
base = pad_to_width(base, min_wid, *base);
base = make_add_expr(base, loff);
} else {
if (pcur->get_msb() != 0)
base = make_sub_expr(base, pcur->get_msb());
base = make_mult_expr(base, lwid);
min_wid = base->expr_width();
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
if (loff != 0) min_wid += 1;
base = pad_to_width(base, min_wid, *base);
base = make_sub_expr(loff, base);
}
return base;
}
@ -802,9 +845,10 @@ NetExpr* condition_reduce(NetExpr*expr)
}
static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
int context_width, bool need_const, bool annotatable,
bool force_expand,
ivl_variable_type_t cast_type)
int context_width, bool need_const,
bool annotatable, bool force_expand,
ivl_variable_type_t cast_type,
bool force_unsigned)
{
PExpr::width_mode_t mode = PExpr::SIZED;
if ((context_width == -2) && !gn_strict_expr_width_flag)
@ -824,6 +868,11 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
expr_width = pos_context_width;
// If this is the RHS of a compressed assignment, the LHS also
// affects the expression type (signed/unsigned).
if (force_unsigned)
pe->cast_signed(false);
if (debug_elaborate) {
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
<< *pe << endl;
@ -910,15 +959,16 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
int context_width, bool need_const, bool annotatable,
ivl_variable_type_t cast_type)
ivl_variable_type_t cast_type, bool force_unsigned)
{
return do_elab_and_eval(des, scope, pe, context_width,
need_const, annotatable, false, cast_type);
need_const, annotatable, false,
cast_type, force_unsigned);
}
/*
* This variant of elab_and_eval does the expression losslessly, no
* matter what the generation of verilog. This is in support of
* matter what the generation of Verilog. This is in support of
* certain special contexts, notably index expressions.
*/
NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
@ -926,7 +976,8 @@ NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
ivl_variable_type_t cast_type)
{
return do_elab_and_eval(des, scope, pe, context_width,
need_const, annotatable, true, cast_type);
need_const, annotatable, true,
cast_type, false);
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
@ -1392,8 +1443,8 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
{
list<index_component_t>::const_iterator icur = indices.begin();
for (size_t idx = 0 ; (idx+1) < indices.size() ; idx += 1, ++icur) {
assert(icur != indices.end());
assert(icur->sel == index_component_t::SEL_BIT);
ivl_assert(*(icur->msb), icur != indices.end());
ivl_assert(*(icur->msb), icur->sel == index_component_t::SEL_BIT);
NetExpr*texpr = elab_and_eval(des, scope, icur->msb, -1, true);
long tmp;
@ -1404,7 +1455,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
return false;
}
prefix_indices .push_back(tmp);
prefix_indices.push_back(tmp);
delete texpr;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_netmisc_H
#define IVL_netmisc_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -60,12 +60,32 @@ inline NetScope* symbol_search(const LineInfo*li,
}
/*
* This function transforms an expression by padding the high bits
* with V0 until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide
* enough.
* This function transforms an expression by either zero or sign extending
* the high bits until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide enough.
* The extension method and the returned expression type is determined by
* signed_flag.
*/
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info);
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info);
/*
* This version determines the extension method from the base expression type.
*/
inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
{
return pad_to_width(expr, wid, expr->has_sign(), info);
}
/*
* This function transforms an expression by either zero or sign extending
* or discarding the high bits until the expression has the desired width.
* This may mean not transforming the expression at all, if it is already
* the correct width. The extension method (if needed) and the returned
* expression type is determined by signed_flag.
*/
extern NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info);
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w,
const LineInfo&info);
@ -258,7 +278,8 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
PExpr*pe, int context_width,
bool need_const =false,
bool annotatable =false,
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE,
bool force_unsigned =false);
extern NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope,
PExpr*pe, int context_width,
@ -297,7 +318,8 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_type_t lv_net_type,
ivl_variable_type_t lv_type,
unsigned lv_width, PExpr*expr,
bool need_const =false);
bool need_const =false,
bool force_unsigned =false);
extern bool evaluate_ranges(Design*des, NetScope*scope,
std::vector<netrange_t>&llist,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@ -147,13 +147,12 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
do {
-- icur;
acc_wid *= pcur->width();
-- pcur;
if (pcur->get_msb() >= pcur->get_lsb())
acc_off += (*icur - pcur->get_lsb()) * acc_wid;
else
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
-- pcur;
} while (icur != prefix.begin());
// Got our final offset.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -24,21 +24,20 @@
# include "netmisc.h"
/*
* This function transforms an expression by padding the high bits
* with V0 until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide
* enough.
*/
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info)
{
if (wid <= expr->expr_width())
if (wid <= expr->expr_width()) {
expr->cast_signed(signed_flag);
return expr;
}
/* If the expression is a const, then replace it with a wider
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verinum oval = pad_to_width(tmp->value(), wid);
verinum oval = tmp->value();
oval.has_sign(signed_flag);
oval = pad_to_width(oval, wid);
tmp = new NetEConst(oval);
tmp->set_line(info);
delete expr;
@ -46,8 +45,30 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
}
NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->cast_signed(signed_flag);
tmp->set_line(info);
tmp->cast_signed(expr->has_sign());
return tmp;
}
NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info)
{
/* If the expression is a const, then replace it with a new
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
tmp->cast_signed(signed_flag);
if (wid != tmp->expr_width()) {
tmp = new NetEConst(verinum(tmp->value(), wid));
tmp->set_line(info);
delete expr;
}
return tmp;
}
NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->cast_signed(signed_flag);
tmp->set_line(info);
return tmp;
}

390
parse.y
View File

@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -65,6 +65,10 @@ static PTask* current_task = 0;
static PFunction* current_function = 0;
static stack<PBlock*> current_block_stack;
/* The variable declaration rules need to know if a lifetime has been
specified. */
static LexicalScope::lifetime_t var_lifetime;
static pform_name_t* pform_create_this(void)
{
name_component_t name (perm_string::literal("@"));
@ -131,17 +135,17 @@ static list<named_pexpr_t>*attributes_in_context = 0;
static const struct str_pair_t pull_strength = { IVL_DR_PULL, IVL_DR_PULL };
static const struct str_pair_t str_strength = { IVL_DR_STRONG, IVL_DR_STRONG };
static list<pair<perm_string,PExpr*> >* make_port_list(char*id, PExpr*expr)
static list<pform_port_t>* make_port_list(char*id, list<pform_range_t>*udims, PExpr*expr)
{
list<pair<perm_string,PExpr*> >*tmp = new list<pair<perm_string,PExpr*> >;
tmp->push_back(make_pair(lex_strings.make(id), expr));
list<pform_port_t>*tmp = new list<pform_port_t>;
tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr));
delete[]id;
return tmp;
}
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string, PExpr*> >*tmp,
char*id, PExpr*expr)
static list<pform_port_t>* make_port_list(list<pform_port_t>*tmp,
char*id, list<pform_range_t>*udims, PExpr*expr)
{
tmp->push_back(make_pair(lex_strings.make(id), expr));
tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr));
delete[]id;
return tmp;
}
@ -370,7 +374,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
char*text;
list<perm_string>*perm_strings;
list<pair<perm_string,PExpr*> >*port_list;
list<pform_port_t>*port_list;
vector<pform_tf_port_t>* tf_ports;
@ -452,6 +456,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
PSpecPath* specpath;
list<index_component_t> *dimensions;
LexicalScope::lifetime_t lifetime;
};
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
@ -560,7 +566,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%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> 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
%type <letter> udp_input_sym udp_output_sym
@ -576,7 +582,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%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
%type <port_list> list_of_port_identifiers list_of_variable_port_identifiers
%type <net_decl_assign> net_decl_assign net_decl_assigns
@ -607,7 +613,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <gates> gate_instance_list
%type <pform_name> hierarchy_identifier implicit_class_handle
%type <expr> assignment_pattern expression expr_primary expr_mintypmax
%type <expr> assignment_pattern expression expr_mintypmax
%type <expr> expr_primary_or_typename expr_primary
%type <expr> class_new dynamic_array_new
%type <expr> inc_or_dec_expression inside_expression lpvalue
%type <expr> branch_probe_expression streaming_concatenation
@ -635,7 +642,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <ranges> variable_dimension
%type <ranges> dimensions_opt dimensions
%type <nettype> net_type var_type net_type_opt
%type <nettype> net_type net_type_opt
%type <gatetype> gatetype switchtype
%type <porttype> port_direction port_direction_opt
%type <vartype> bit_logic bit_logic_opt
@ -648,6 +655,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <statement> statement statement_item statement_or_null
%type <statement> compressed_statement
%type <statement> loop_statement for_step jump_statement
%type <statement> procedural_assertion_statement
%type <statement_list> statement_or_null_list statement_or_null_list_opt
%type <statement> analog_statement
@ -664,6 +672,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <int_val> atom2_type
%type <int_val> module_start module_end
%type <lifetime> lifetime lifetime_opt
%token K_TAND
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
@ -723,17 +733,17 @@ block_identifier_opt /* */
;
class_declaration /* IEEE1800-2005: A.1.2 */
: K_virtual_opt K_class class_identifier class_declaration_extends_opt ';'
{ pform_start_class_declaration(@2, $3, $4.type, $4.exprs); }
: K_virtual_opt K_class lifetime_opt class_identifier class_declaration_extends_opt ';'
{ pform_start_class_declaration(@2, $4, $5.type, $5.exprs, $3); }
class_items_opt K_endclass
{ // Process a class.
pform_end_class_declaration(@8);
pform_end_class_declaration(@9);
}
class_declaration_endlabel_opt
{ // Wrap up the class.
if ($10 && $3 && $3->name != $10) {
yyerror(@10, "error: Class end label doesn't match class name.");
delete[]$10;
if ($11 && $4 && $4->name != $11) {
yyerror(@11, "error: Class end label doesn't match class name.");
delete[]$11;
}
}
;
@ -1193,7 +1203,7 @@ for_step /* IEEE1800-2005: A.6.8 */
definitions in the func_body to take on the scope of the function
instead of the module. */
function_declaration /* IEEE1800-2005: A.2.6 */
: K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER ';'
: K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER ';'
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
@ -1214,7 +1224,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
"function name");
}
if (! gn_system_verilog()) {
yyerror(@11, "error: Function end label require "
yyerror(@11, "error: Function end labels require "
"SystemVerilog.");
}
delete[]$11;
@ -1222,7 +1232,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
delete[]$4;
}
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
@ -1258,7 +1268,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
/* Detect and recover from some errors. */
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
{ /* */
if (current_function) {
pform_pop_scope();
@ -1364,6 +1374,16 @@ jump_statement /* IEEE1800-2005: A.6.5 */
}
;
lifetime /* IEEE1800-2005: A.2.1.3 */
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
| K_static { $$ = LexicalScope::STATIC; }
;
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
: lifetime { $$ = $1; }
| { $$ = LexicalScope::INHERITED; }
;
/* Loop statements are kinds of statements. */
loop_statement /* IEEE1800-2005: A.6.8 */
@ -1407,6 +1427,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
vector<Statement*>tmp_for_list (1);
tmp_for_list[0] = tmp_for;
PBlock*tmp_blk = current_block_stack.top();
current_block_stack.pop();
tmp_blk->set_statement(tmp_for_list);
$$ = tmp_blk;
delete[]$4;
@ -1457,6 +1478,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
vector<Statement*>tmp_for_list(1);
tmp_for_list[0] = tmp_for;
PBlock*tmp_blk = current_block_stack.top();
current_block_stack.pop();
tmp_blk->set_statement(tmp_for_list);
$$ = tmp_blk;
}
@ -1703,20 +1725,20 @@ open_range_list /* IEEE1800-2005 A.2.11 */
;
package_declaration /* IEEE1800-2005 A.1.2 */
: K_package IDENTIFIER ';'
{ pform_start_package_declaration(@1, $2);
: K_package lifetime_opt IDENTIFIER ';'
{ pform_start_package_declaration(@1, $3, $2);
}
package_item_list_opt
K_endpackage endlabel_opt
{ pform_end_package_declaration(@1);
// If an end label is present make sure it match the package name.
if ($7) {
if (strcmp($2,$7) != 0) {
yyerror(@7, "error: End label doesn't match package name");
if ($8) {
if (strcmp($3,$8) != 0) {
yyerror(@8, "error: End label doesn't match package name");
}
delete[]$7;
delete[]$8;
}
delete[]$2;
delete[]$3;
}
;
@ -1794,6 +1816,21 @@ property_expr /* IEEE1800-2012 A.2.10 */
: expression
;
procedural_assertion_statement /* IEEE1800-2012 A.6.10 */
: K_assert '(' expression ')' statement %prec less_than_K_else
{ yyerror(@1, "sorry: Simple immediate assertion statements not implemented.");
$$ = 0;
}
| K_assert '(' expression ')' K_else statement
{ yyerror(@1, "sorry: Simple immediate assertion statements not implemented.");
$$ = 0;
}
| K_assert '(' expression ')' statement K_else statement
{ yyerror(@1, "sorry: Simple immediate assertion statements not implemented.");
$$ = 0;
}
;
/* The property_qualifier rule is as literally described in the LRM,
but the use is usually as { property_qualifier }, which is
implemented by the property_qualifier_opt rule below. */
@ -1895,7 +1932,7 @@ streaming_concatenation /* IEEE1800-2005: A.8.1 */
task_declaration /* IEEE1800-2005: A.2.7 */
: K_task K_automatic_opt IDENTIFIER ';'
: K_task lifetime_opt IDENTIFIER ';'
{ assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2);
}
@ -1908,7 +1945,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
pform_pop_scope();
current_task = 0;
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
yyerror(@7, "error: Task body with multiple statements requres SystemVerilog.");
yyerror(@7, "error: Task body with multiple statements requires SystemVerilog.");
}
delete $7;
}
@ -1931,7 +1968,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3;
}
| K_task K_automatic_opt IDENTIFIER '('
| K_task lifetime_opt IDENTIFIER '('
{ assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2);
}
@ -1965,7 +2002,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3;
}
| K_task K_automatic_opt IDENTIFIER '(' ')' ';'
| K_task lifetime_opt IDENTIFIER '(' ')' ';'
{ assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2);
}
@ -1982,7 +2019,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
pform_pop_scope();
current_task = 0;
if ($9->size() > 1 && !gn_system_verilog()) {
yyerror(@9, "error: Task body with multiple statements requres SystemVerilog.");
yyerror(@9, "error: Task body with multiple statements requires SystemVerilog.");
}
delete $9;
}
@ -2005,7 +2042,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3;
}
| K_task K_automatic_opt IDENTIFIER error K_endtask
| K_task lifetime_opt IDENTIFIER error K_endtask
{
assert(current_task == 0);
}
@ -2213,7 +2250,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
}
| '[' expression ']'
{ // SystemVerilog canonical range
if (generation_flag < GN_VER2005_SV) {
if (!gn_system_verilog()) {
warn_count += 1;
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
<< "Use at least -g2005-sv to remove this warning." << endl;
@ -2243,6 +2280,19 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
}
;
variable_lifetime
: lifetime
{ if (!gn_system_verilog()) {
yyerror(@1, "error: overriding the default variable lifetime "
"requires SystemVerilog.");
} else if ($1 != pform_peek_scope()->default_lifetime) {
yyerror(@1, "sorry: overriding the default variable lifetime "
"is not yet supported.");
}
var_lifetime = $1;
}
;
/* Verilog-2001 supports attribute lists, which can be attached to a
variety of different objects. The syntax inside the (* *) is a
comma separated list of names or names with assigned values. */
@ -2317,10 +2367,20 @@ block_item_decl
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
}
| variable_lifetime data_type register_variable_list ';'
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
var_lifetime = LexicalScope::INHERITED;
}
| K_reg data_type register_variable_list ';'
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
}
| variable_lifetime K_reg data_type register_variable_list ';'
{ if ($3) pform_set_data_type(@3, $3, $4, NetNet::REG, attributes_in_context);
var_lifetime = LexicalScope::INHERITED;
}
| K_event event_variable_list ';'
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
}
@ -3033,7 +3093,7 @@ branch_probe_expression
;
expression
: expr_primary
: expr_primary_or_typename
{ $$ = $1; }
| inc_or_dec_expression
{ $$ = $1; }
@ -3328,6 +3388,20 @@ expression_list_proper
}
;
expr_primary_or_typename
: expr_primary
/* There are a few special cases (notably $bits argument) where the
expression may be a type name. Let the elaborator sort this out. */
| TYPE_IDENTIFIER
{ PETypename*tmp = new PETypename($1.type);
FILE_NAME(tmp,@1);
$$ = tmp;
delete[]$1.text;
}
;
expr_primary
: number
{ assert($1);
@ -3369,15 +3443,6 @@ expr_primary
delete[]$1;
}
/* There are a few special cases (notably $bits argument) where the
expression may be a type name. Let the elaborator sort this out. */
| TYPE_IDENTIFIER
{ PETypename*tmp = new PETypename($1.type);
FILE_NAME(tmp,@1);
$$ = tmp;
delete[]$1.text;
}
/* The hierarchy_identifier rule matches simple identifiers as well as
indexed arrays and part selects */
@ -3681,12 +3746,11 @@ expr_primary
/* Cast expressions are primaries */
| DEC_NUMBER '\'' '(' expression ')'
| expr_primary '\'' '(' expression ')'
{ PExpr*base = $4;
if (gn_system_verilog()) {
PECastSize*tmp = new PECastSize($1->as_ulong(), base);
PECastSize*tmp = new PECastSize($1, base);
FILE_NAME(tmp, @1);
delete $1;
$$ = tmp;
} else {
yyerror(@1, "error: Size cast requires SystemVerilog.");
@ -4002,14 +4066,21 @@ list_of_identifiers
;
list_of_port_identifiers
: IDENTIFIER
{ $$ = make_port_list($1, 0); }
| IDENTIFIER '=' expression
{ $$ = make_port_list($1, $3); }
| list_of_port_identifiers ',' IDENTIFIER
{ $$ = make_port_list($1, $3, 0); }
| list_of_port_identifiers ',' IDENTIFIER '=' expression
{ $$ = make_port_list($1, $3, $5); }
: IDENTIFIER dimensions_opt
{ $$ = make_port_list($1, $2, 0); }
| list_of_port_identifiers ',' IDENTIFIER dimensions_opt
{ $$ = make_port_list($1, $3, $4, 0); }
;
list_of_variable_port_identifiers
: IDENTIFIER dimensions_opt
{ $$ = make_port_list($1, $2, 0); }
| IDENTIFIER dimensions_opt '=' expression
{ $$ = make_port_list($1, $2, $4); }
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt
{ $$ = make_port_list($1, $3, $4, 0); }
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt '=' expression
{ $$ = make_port_list($1, $3, $4, $6); }
;
@ -4218,7 +4289,7 @@ port_declaration
port_declaration_context.port_net_type = use_type;
port_declaration_context.data_type = $4;
pform_make_reginit(@5, name, $7);
pform_make_var_init(@5, name, $7);
delete[]$5;
$$ = ptmp;
@ -4372,13 +4443,13 @@ local_timeunit_prec_decl2
items, and finally an end marker. */
module
: attribute_list_opt module_start IDENTIFIER
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
: attribute_list_opt module_start lifetime_opt IDENTIFIER
{ pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); }
module_package_import_list_opt
module_parameter_port_list_opt
module_port_list_opt
module_attribute_foreign ';'
{ pform_module_set_ports($7); }
{ pform_module_set_ports($8); }
local_timeunit_prec_decl_opt
{ have_timeunit_decl = true; // Every thing past here is
have_timeprec_decl = true; // a check!
@ -4404,22 +4475,22 @@ module
}
// Check that program/endprogram and module/endmodule
// keywords match.
if ($2 != $14) {
if ($2 != $15) {
switch ($2) {
case K_module:
yyerror(@14, "error: module not closed by endmodule.");
yyerror(@15, "error: module not closed by endmodule.");
break;
case K_program:
yyerror(@14, "error: program not closed by endprogram.");
yyerror(@15, "error: program not closed by endprogram.");
break;
case K_interface:
yyerror(@14, "error: interface not closed by endinterface.");
yyerror(@15, "error: interface not closed by endinterface.");
break;
default:
break;
}
}
pform_endmodule($3, in_celldefine, ucd);
pform_endmodule($4, in_celldefine, ucd);
have_timeunit_decl = false; // We will allow decls again.
have_timeprec_decl = false;
}
@ -4429,19 +4500,19 @@ module
// endlabel_opt but still have the pform_endmodule() called
// early enough that the lexor can know we are outside the
// module.
if ($16) {
if (strcmp($3,$16) != 0) {
if ($17) {
if (strcmp($4,$17) != 0) {
switch ($2) {
case K_module:
yyerror(@16, "error: End label doesn't match "
yyerror(@17, "error: End label doesn't match "
"module name.");
break;
case K_program:
yyerror(@16, "error: End label doesn't match "
yyerror(@17, "error: End label doesn't match "
"program name.");
break;
case K_interface:
yyerror(@16, "error: End label doesn't match "
yyerror(@17, "error: End label doesn't match "
"interface name.");
break;
default:
@ -4452,9 +4523,9 @@ module
yyerror(@8, "error: Module end labels require "
"SystemVerilog.");
}
delete[]$16;
delete[]$17;
}
delete[]$3;
delete[]$4;
}
;
@ -4597,58 +4668,102 @@ module_item
delete $4;
}
| attribute_list_opt port_direction unsigned_signed_opt dimensions_opt delay3_opt list_of_identifiers ';'
{ pform_set_port_type(@2, $6, $4, $3, $2, $1); }
/* The next two rules handle Verilog 2001 statements of the form:
/* The next two rules handle port declarations that include a net type, e.g.
input wire signed [h:l] <list>;
This creates the wire and sets the port type all at once. */
| attribute_list_opt port_direction net_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
{ pform_makewire(@2, $5, $4, $6, $3, $2, IVL_VT_NO_TYPE, $1, SR_BOTH); }
| attribute_list_opt port_direction net_type data_type_or_implicit list_of_port_identifiers ';'
{ pform_module_define_port(@2, $5, $2, $3, $4, $1); }
| attribute_list_opt K_output var_type unsigned_signed_opt dimensions_opt list_of_port_identifiers ';'
{ list<pair<perm_string,PExpr*> >::const_iterator pp;
list<perm_string>*tmp = new list<perm_string>;
for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
tmp->push_back((*pp).first);
| attribute_list_opt port_direction K_wreal list_of_port_identifiers ';'
{ real_type_t*real_type = new real_type_t(real_type_t::REAL);
pform_module_define_port(@2, $4, $2, NetNet::WIRE, real_type, $1);
}
/* The next three rules handle port declarations that include a variable
type, e.g.
output reg signed [h:l] <list>;
and also handle incomplete port declarations, e.g.
input signed [h:l] <list>;
*/
| attribute_list_opt K_inout data_type_or_implicit list_of_port_identifiers ';'
{ NetNet::Type use_type = $3 ? NetNet::IMPLICIT : NetNet::NONE;
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($3)) {
if (dtype->implicit_flag)
use_type = NetNet::NONE;
}
pform_makewire(@2, $5, $4, tmp, $3, NetNet::POUTPUT,
IVL_VT_NO_TYPE, $1, SR_BOTH);
for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
if ((*pp).second) {
pform_make_reginit(@2, (*pp).first, (*pp).second);
}
if (use_type == NetNet::NONE)
pform_set_port_type(@2, $4, NetNet::PINOUT, $3, $1);
else
pform_module_define_port(@2, $4, NetNet::PINOUT, use_type, $3, $1);
}
| attribute_list_opt K_input data_type_or_implicit list_of_port_identifiers ';'
{ NetNet::Type use_type = $3 ? NetNet::IMPLICIT : NetNet::NONE;
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($3)) {
if (dtype->implicit_flag)
use_type = NetNet::NONE;
}
delete $6;
if (use_type == NetNet::NONE)
pform_set_port_type(@2, $4, NetNet::PINPUT, $3, $1);
else
pform_module_define_port(@2, $4, NetNet::PINPUT, use_type, $3, $1);
}
| attribute_list_opt port_direction K_wreal list_of_identifiers ';'
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE, $2,
IVL_VT_REAL, $1, SR_BOTH);
| attribute_list_opt K_output data_type_or_implicit list_of_variable_port_identifiers ';'
{ NetNet::Type use_type = $3 ? NetNet::IMPLICIT : NetNet::NONE;
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($3)) {
if (dtype->implicit_flag)
use_type = NetNet::NONE;
else if (dtype->reg_flag)
use_type = NetNet::REG;
else
use_type = NetNet::IMPLICIT_REG;
// The SystemVerilog types that can show up as
// output ports are implicitly (on the inside)
// variables because "reg" is not valid syntax
// here.
} else if (dynamic_cast<atom2_type_t*> ($3)) {
use_type = NetNet::IMPLICIT_REG;
} else if (dynamic_cast<struct_type_t*> ($3)) {
use_type = NetNet::IMPLICIT_REG;
} else if (enum_type_t*etype = dynamic_cast<enum_type_t*> ($3)) {
if(etype->base_type == IVL_VT_LOGIC)
use_type = NetNet::IMPLICIT_REG;
}
if (use_type == NetNet::NONE)
pform_set_port_type(@2, $4, NetNet::POUTPUT, $3, $1);
else
pform_module_define_port(@2, $4, NetNet::POUTPUT, use_type, $3, $1);
}
/* var_type declaration (reg variables) cannot be input or output,
because the port declaration implies an external driver, which
cannot be attached to a reg. These rules catch that error early. */
| attribute_list_opt K_input var_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
{ pform_makewire(@2, $5, $4, $6, $3, NetNet::PINPUT,
IVL_VT_NO_TYPE, $1);
yyerror(@3, "error: reg variables cannot be inputs.");
}
| attribute_list_opt K_inout var_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
{ pform_makewire(@2, $5, $4, $6, $3, NetNet::PINOUT,
IVL_VT_NO_TYPE, $1);
yyerror(@3, "error: reg variables cannot be inouts.");
}
| attribute_list_opt port_direction unsigned_signed_opt dimensions_opt delay3_opt error ';'
| attribute_list_opt port_direction net_type data_type_or_implicit error ';'
{ yyerror(@2, "error: Invalid variable list in port declaration.");
if ($1) delete $1;
if ($4) delete $4;
if ($5) delete $5;
yyerrok;
}
| attribute_list_opt K_inout data_type_or_implicit error ';'
{ yyerror(@2, "error: Invalid variable list in port declaration.");
if ($1) delete $1;
if ($3) delete $3;
yyerrok;
}
| attribute_list_opt K_input data_type_or_implicit error ';'
{ yyerror(@2, "error: Invalid variable list in port declaration.");
if ($1) delete $1;
if ($3) delete $3;
yyerrok;
}
| attribute_list_opt K_output data_type_or_implicit error ';'
{ yyerror(@2, "error: Invalid variable list in port declaration.");
if ($1) delete $1;
if ($3) delete $3;
yyerrok;
}
@ -5048,10 +5163,6 @@ net_type
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
;
var_type
: K_reg { $$ = NetNet::REG; }
;
param_type
: bit_logic_opt unsigned_signed_opt dimensions_opt
{ param_active_range = $3;
@ -5477,11 +5588,17 @@ register_variable
$$ = $1;
}
| IDENTIFIER dimensions_opt '=' expression
{ perm_string name = lex_strings.make($1);
{ if (pform_peek_scope()->var_init_needs_explicit_lifetime()
&& (var_lifetime == LexicalScope::INHERITED)) {
cerr << @3 << ": warning: Static variable initialization requires "
"explicit lifetime in this context." << endl;
warn_count += 1;
}
perm_string name = lex_strings.make($1);
pform_makewire(@1, name, NetNet::REG,
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
pform_set_reg_idx(name, $2);
pform_make_reginit(@1, name, $4);
pform_make_var_init(@1, name, $4);
$$ = $1;
}
;
@ -5734,7 +5851,23 @@ specify_path_identifiers
delete[]$1;
}
| IDENTIFIER '[' expr_primary ']'
{ list<perm_string>*tmp = new list<perm_string>;
{ if (gn_specify_blocks_flag) {
yywarn(@4, "Bit selects are not currently supported "
"in path declarations. The declaration "
"will be applied to the whole vector.");
}
list<perm_string>*tmp = new list<perm_string>;
tmp->push_back(lex_strings.make($1));
$$ = tmp;
delete[]$1;
}
| IDENTIFIER '[' expr_primary polarity_operator expr_primary ']'
{ if (gn_specify_blocks_flag) {
yywarn(@4, "Part selects are not currently supported "
"in path declarations. The declaration "
"will be applied to the whole vector.");
}
list<perm_string>*tmp = new list<perm_string>;
tmp->push_back(lex_strings.make($1));
$$ = tmp;
delete[]$1;
@ -5746,7 +5879,23 @@ specify_path_identifiers
delete[]$3;
}
| specify_path_identifiers ',' IDENTIFIER '[' expr_primary ']'
{ list<perm_string>*tmp = $1;
{ if (gn_specify_blocks_flag) {
yywarn(@4, "Bit selects are not currently supported "
"in path declarations. The declaration "
"will be applied to the whole vector.");
}
list<perm_string>*tmp = $1;
tmp->push_back(lex_strings.make($3));
$$ = tmp;
delete[]$3;
}
| specify_path_identifiers ',' IDENTIFIER '[' expr_primary polarity_operator expr_primary ']'
{ if (gn_specify_blocks_flag) {
yywarn(@4, "Part selects are not currently supported "
"in path declarations. The declaration "
"will be applied to the whole vector.");
}
list<perm_string>*tmp = $1;
tmp->push_back(lex_strings.make($3));
$$ = tmp;
delete[]$3;
@ -6094,6 +6243,8 @@ statement_item /* This is roughly statement_item in the LRM */
$$ = tmp;
}
| procedural_assertion_statement { $$ = $1; }
| loop_statement { $$ = $1; }
| jump_statement { $$ = $1; }
@ -6777,7 +6928,6 @@ udp_primitive
presence is significant. This is a fairly common pattern so
collect those rules here. */
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; } ;

496
pform.cc
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -40,6 +40,7 @@
# include <sstream>
# include <cstring>
# include <cstdlib>
# include <cctype>
# include "ivl_assert.h"
# include "ivl_alloc.h"
@ -86,6 +87,42 @@ std::string vlltype::get_fileline() const
}
static bool is_hex_digit_str(const char *str)
{
while (*str) {
if (!isxdigit(*str)) return false;
str++;
}
return true;
}
static bool is_dec_digit_str(const char *str)
{
while (*str) {
if (!isdigit(*str)) return false;
str++;
}
return true;
}
static bool is_oct_digit_str(const char *str)
{
while (*str) {
if (*str < '0' || *str > '7') return false;
str++;
}
return true;
}
static bool is_bin_digit_str(const char *str)
{
while (*str) {
if (*str != '0' && *str != '1') return false;
str++;
}
return true;
}
/*
* Parse configuration file with format <key>=<value>, where key
* is the hierarchical name of a valid parameter name, and value
@ -152,90 +189,137 @@ void parm_to_defparam_list(const string&param)
ptr = strchr(nkey, '.');
}
name.push_back(name_component_t(lex_strings.make(nkey)));
free(key);
// Resolve value to PExpr class. Should support all kind of constant
// format including based number, dec number, real number and string.
if (*value == '"') { // string type
char *buf = strdup (value);
char *buf_ptr = buf+1;
// Parse until another '"' or '\0'
while (*buf_ptr != '"' && *buf_ptr != '\0') {
buf_ptr++;
// Check for escape, especially '\"', which does not mean the
// end of string.
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
buf_ptr += 2;
}
if (*buf_ptr == '\0') // String end without '"'
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
cerr << buf_ptr << endl;
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
<< ". Ignore characters after \'\"\'" << endl;
}
*buf_ptr = '\0';
buf_ptr = buf+1;
// Remember to use 'new' to allocate string for PEString
// because 'delete' is used by its destructor.
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
PExpr* ndec = new PEString(nchar);
// Is it a string?
if (*value == '"') {
char *buf = strdup (value);
char *buf_ptr = buf+1;
// Parse until another '"' or '\0'
while (*buf_ptr != '"' && *buf_ptr != '\0') {
buf_ptr++;
// Check for escape, especially '\"', which does not mean the
// end of string.
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
buf_ptr += 2;
}
if (*buf_ptr == '\0') // String end without '"'
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
cerr << buf_ptr << endl;
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
<< ". Ignore characters after \'\"\'" << endl;
}
*buf_ptr = '\0';
buf_ptr = buf+1;
// Remember to use 'new' to allocate string for PEString
// because 'delete' is used by its destructor.
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
PExpr* ndec = new PEString(nchar);
Module::user_defparms.push_back( make_pair(name, ndec) );
free(buf);
free(buf);
free(value);
return;
}
else { // number type
char *num = strchr(value, '\'');
if (num != 0) {
verinum *val;
// BASED_NUMBER, something like - scope.parameter='b11
// make sure to check 'h' first because 'b'&'d' may be included
// in hex format
if (strchr(num, 'h') || strchr(num, 'H'))
val = make_unsized_hex(num);
else if (strchr(num, 'd') || strchr(num, 'D'))
if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z'))
val = make_undef_highz_dec(num);
else
val = make_unsized_dec(num);
else if (strchr(num, 'b') || strchr(num, 'B')) {
val = make_unsized_binary(num);
}
else if (strchr(num, 'o') || strchr(num, 'O'))
val = make_unsized_octal(num);
else {
cerr << "<command line>: error: value specify error for defparam: " << name << endl;
free(key);
free(value);
return;
}
// BASED_NUMBER with size, something like - scope.parameter=2'b11
if (num != value) {
*num = 0;
verinum *siz = make_unsized_dec(value);
val = pform_verinum_with_size(siz, val, "<command line>", 0);
}
PExpr* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
}
else {
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2
if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) {
verireal *val = new verireal(value);
PExpr* nreal = new PEFNumber(val);
Module::user_defparms.push_back( make_pair(name, nreal) );
}
else {
// DEC_NUMBER, something like - scope.parameter=3
verinum *val = make_unsized_dec(value);
PExpr* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
}
}
// Is it a based number?
char *num = strchr(value, '\'');
if (num != 0) {
verinum *val;
const char *base = num + 1;
if (*base == 's' || *base == 'S')
base++;
switch (*base) {
case 'h':
case 'H':
if (is_hex_digit_str(base+1)) {
val = make_unsized_hex(num);
} else {
cerr << "<command line>: error: invalid digit in hex value specified for defparam: " << name << endl;
free(value);
return;
}
break;
case 'd':
case 'D':
if (is_dec_digit_str(base+1)) {
val = make_unsized_dec(num);
} else {
cerr << "<command line>: error: invalid digit in decimal value specified for defparam: " << name << endl;
free(value);
return;
}
break;
case 'o':
case 'O':
if (is_oct_digit_str(base+1)) {
val = make_unsized_octal(num);
} else {
cerr << "<command line>: error: invalid digit in octal value specified for defparam: " << name << endl;
free(value);
return;
}
break;
case 'b':
case 'B':
if (is_bin_digit_str(base+1)) {
val = make_unsized_binary(num);
} else {
cerr << "<command line>: error: invalid digit in binary value specified for defparam: " << name << endl;
free(value);
return;
}
break;
default:
cerr << "<command line>: error: invalid numeric base specified for defparam: " << name << endl;
free(value);
return;
}
if (num != value) { // based number with size
*num = 0;
if (is_dec_digit_str(value)) {
verinum *siz = make_unsized_dec(value);
val = pform_verinum_with_size(siz, val, "<command line>", 0);
} else {
cerr << "<command line>: error: invalid size for value specified for defparam: " << name << endl;
free(value);
return;
}
}
PExpr* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
free(value);
return;
}
free(key);
// Is it a decimal number?
num = (value[0] == '-') ? value + 1 : value;
if (is_dec_digit_str(num)) {
verinum *val = make_unsized_dec(num);
if (value[0] == '-') *val = -(*val);
PExpr* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
free(value);
return;
}
// Is it a real number?
char *end = 0;
double rval = strtod(value, &end);
if (end != value && *end == 0) {
verireal *val = new verireal(rval);
PExpr* nreal = new PEFNumber(val);
Module::user_defparms.push_back( make_pair(name, nreal) );
free(value);
return;
}
// None of the above.
cerr << "<command line>: error: invalid value specified for defparam: " << name << endl;
free(value);
}
@ -312,12 +396,29 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
*/
static LexicalScope* lexical_scope = 0;
LexicalScope* pform_peek_scope(void)
{
assert(lexical_scope);
return lexical_scope;
}
void pform_pop_scope()
{
assert(lexical_scope);
lexical_scope = lexical_scope->parent_scope();
}
static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
{
if (lifetime != LexicalScope::INHERITED)
return lifetime;
if (lexical_scope != 0)
return lexical_scope->default_lifetime;
return LexicalScope::STATIC;
}
static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
{
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
@ -328,17 +429,37 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
return scopex;
}
LexicalScope* pform_peek_scope(void)
/*
* Set the local time unit/precision to the global value.
*/
static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc)
{
assert(lexical_scope);
return lexical_scope;
scope->time_unit = pform_time_unit;
scope->time_precision = pform_time_prec;
/* If we have a timescale file then the time information is from
* a timescale directive. */
scope->time_from_timescale = pform_timescale_file != 0;
if (warn_timescale && (lexical_scope == 0) && pform_timescale_file
&& (strcmp(pform_timescale_file, loc.text) != 0)) {
cerr << loc.get_fileline() << ": warning: "
<< "timescale for " << scope->pscope_name()
<< " inherited from another file." << endl;
cerr << pform_timescale_file << ":" << pform_timescale_line
<< ": ...: The inherited timescale is here." << endl;
}
}
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime)
{
PClass*class_scope = new PClass(name, lexical_scope);
class_scope->default_lifetime = find_lifetime(lifetime);
FILE_NAME(class_scope, loc);
pform_set_scope_timescale(class_scope, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(!pform_cur_generate);
@ -364,22 +485,33 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
return class_scope;
}
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name)
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime)
{
PPackage*pkg_scope = new PPackage(name, lexical_scope);
pkg_scope->default_lifetime = find_lifetime(lifetime);
FILE_NAME(pkg_scope, loc);
pform_set_scope_timescale(pkg_scope, loc);
lexical_scope = pkg_scope;
return pkg_scope;
}
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
LexicalScope::lifetime_t lifetime)
{
perm_string task_name = lex_strings.make(name);
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
PTask*task = new PTask(task_name, lexical_scope, is_auto);
task->default_lifetime = default_lifetime;
FILE_NAME(task, loc);
pform_set_scope_timescale(task, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
if ((scopex == 0) && !gn_system_verilog()) {
cerr << task->get_fileline() << ": error: task declarations "
@ -424,15 +556,21 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
}
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
bool is_auto)
LexicalScope::lifetime_t lifetime)
{
perm_string func_name = lex_strings.make(name);
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
func->default_lifetime = default_lifetime;
FILE_NAME(func, loc);
pform_set_scope_timescale(func, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
if ((scopex == 0) && (generation_flag < GN_VER2005_SV)) {
if ((scopex == 0) && !gn_system_verilog()) {
cerr << func->get_fileline() << ": error: function declarations "
"must be contained within a module." << endl;
error_count += 1;
@ -489,6 +627,7 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
}
PBlock*block = new PBlock(block_name, lexical_scope, bt);
block->default_lifetime = find_lifetime(LexicalScope::INHERITED);
lexical_scope = block;
return block;
@ -1041,7 +1180,10 @@ void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
int pform_get_timeunit()
{
return pform_cur_module.front()->time_unit;
if (pform_cur_module.empty())
return pform_time_unit;
else
return pform_cur_module.front()->time_unit;
}
void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
@ -1131,6 +1273,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, bool is_interface,
LexicalScope::lifetime_t lifetime,
list<named_pexpr_t>*attr)
{
if (! pform_cur_module.empty() && !gn_system_verilog()) {
@ -1139,6 +1282,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
error_count += 1;
}
if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) {
cerr << loc << ": error: Default subroutine lifetimes "
"require SystemVerilog." << 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 "
@ -1158,17 +1307,14 @@ void pform_startmodule(const struct vlltype&loc, const char*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;
cur_module->default_lifetime = find_lifetime(lifetime);
FILE_NAME(cur_module, loc);
pform_set_scope_timescale(cur_module, loc);
tu_local_flag = tu_global_flag;
tp_local_flag = tp_global_flag;
/* If we have a timescale file then the time information is from
* a timescale directive. */
cur_module->time_from_timescale = pform_timescale_file != 0;
FILE_NAME(cur_module, loc);
cur_module->library_flag = pform_library_flag;
pform_cur_module.push_front(cur_module);
@ -1179,15 +1325,6 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
zero. That's just the way it is, thanks to the standard. */
scope_generate_counter = 1;
if (warn_timescale && pform_timescale_file
&& (strcmp(pform_timescale_file,loc.text) != 0)) {
cerr << cur_module->get_fileline() << ": warning: "
<< "timescale for " << name
<< " inherited from another file." << endl;
cerr << pform_timescale_file << ":" << pform_timescale_line
<< ": ...: The inherited timescale is here." << endl;
}
pform_bind_attributes(cur_module->attributes, attr);
}
@ -1199,7 +1336,7 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
void pform_check_timeunit_prec()
{
assert(! pform_cur_module.empty());
if ((generation_flag & (GN_VER2005_SV | GN_VER2009 | GN_VER2012)) &&
if (gn_system_verilog() &&
(pform_cur_module.front()->time_unit < pform_cur_module.front()->time_precision)) {
VLerror("error: a timeprecision is missing or is too large!");
} else assert(pform_cur_module.front()->time_unit >=
@ -1905,6 +2042,7 @@ static void pform_set_net_range(perm_string name,
VLerror("error: name is not a valid net.");
return;
}
// If this is not implicit ("implicit" meaning we don't
// know what the type is yet) then set the type now.
if (net_type != NetNet::IMPLICIT && net_type != NetNet::NONE) {
@ -2000,9 +2138,11 @@ static void pform_makegate(PGBuiltin::Type type,
return;
}
for (list<PExpr*>::iterator cur = info.parms->begin()
; cur != info.parms->end() ; ++cur) {
pform_declare_implicit_nets(*cur);
if (info.parms) {
for (list<PExpr*>::iterator cur = info.parms->begin()
; cur != info.parms->end() ; ++cur) {
pform_declare_implicit_nets(*cur);
}
}
perm_string dev_name = lex_strings.make(info.name);
@ -2248,23 +2388,30 @@ void pform_make_pgassign_list(list<PExpr*>*alist,
}
/*
* this function makes the initial assignment to a register as given
* in the source. It handles the case where a reg variable is assigned
* where it it declared:
* This function makes the initial assignment to a variable as given
* in the source. It handles the case where a variable is assigned
* where it is declared, e.g.
*
* reg foo = <expr>;
*
* This is equivalent to the combination of statements:
* In Verilog-2001 this is only supported at the module level, and is
* equivalent to the combination of statements:
*
* reg foo;
* initial foo = <expr>;
*
* and that is how it is parsed. This syntax is not part of the
* IEEE1364-1995 standard, but is approved by OVI as enhancement
* BTF-B14.
* In SystemVerilog, variable initializations are allowed in any scope.
* For static variables, initializations are performed before the start
* of simulation. For automatic variables, initializations are performed
* each time the enclosing block is entered. Here we store the variable
* assignments in the current scope, and later elaboration creates an
* initialization block that will be executed at the appropriate time.
*
* This syntax is not part of the IEEE1364-1995 standard, but is
* approved by OVI as enhancement BTF-B14.
*/
void pform_make_reginit(const struct vlltype&li,
perm_string name, PExpr*expr)
void pform_make_var_init(const struct vlltype&li,
perm_string name, PExpr*expr)
{
if (! pform_at_module_level() && !gn_system_verilog()) {
VLerror(li, "error: variable declaration assignments are only "
@ -2275,7 +2422,7 @@ void pform_make_reginit(const struct vlltype&li,
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
VLerror(li, "internal error: reginit to non-register?");
VLerror(li, "internal error: var_init to non-register?");
delete expr;
return;
}
@ -2284,10 +2431,8 @@ void pform_make_reginit(const struct vlltype&li,
FILE_NAME(lval, li);
PAssign*ass = new PAssign(lval, expr, true);
FILE_NAME(ass, li);
PProcess*top = new PProcess(IVL_PR_INITIAL, ass);
FILE_NAME(top, li);
pform_put_behavior_in_scope(top);
lexical_scope->var_inits.push_back(ass);
}
/*
@ -2305,7 +2450,8 @@ void pform_module_define_port(const struct vlltype&li,
NetNet::PortType port_kind,
NetNet::Type type,
data_type_t*vtype,
list<named_pexpr_t>*attr)
list<named_pexpr_t>*attr,
bool keep_attr)
{
struct_type_t*struct_type = 0;
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
@ -2394,10 +2540,37 @@ void pform_module_define_port(const struct vlltype&li,
cur->set_unpacked_idx(*urange);
}
pform_bind_attributes(cur->attributes, attr);
pform_bind_attributes(cur->attributes, attr, keep_attr);
pform_put_wire_in_scope(name, cur);
}
void pform_module_define_port(const struct vlltype&li,
list<pform_port_t>*ports,
NetNet::PortType port_kind,
NetNet::Type type,
data_type_t*vtype,
list<named_pexpr_t>*attr)
{
for (list<pform_port_t>::iterator cur = ports->begin()
; cur != ports->end() ; ++ cur ) {
data_type_t*use_type = vtype;
if (cur->udims)
use_type = new uarray_type_t(vtype, cur->udims);
pform_module_define_port(li, cur->name, port_kind, type, use_type,
attr, true);
if (cur->udims)
delete use_type;
if (cur->expr)
pform_make_var_init(li, cur->name, cur->expr);
}
delete ports;
delete attr;
}
/*
* This function makes a single signal (a wire, a reg, etc) as
* requested by the parser. The name is unscoped, so I attach the
@ -2591,6 +2764,15 @@ void pform_makewire(const struct vlltype&li,
NetNet::Type type,
data_type_t*data_type)
{
if ((lexical_scope == 0) && !gn_system_verilog()) {
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()
@ -2887,6 +3069,14 @@ void pform_set_parameter(const struct vlltype&loc,
LexicalScope::range_t*value_range)
{
LexicalScope*scope = lexical_scope;
if ((scope == 0) && !gn_system_verilog()) {
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;
@ -2910,7 +3100,7 @@ void pform_set_parameter(const struct vlltype&loc,
error_count += 1;
}
// Only a Module scope has specparams.
if ((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())) {
@ -2954,7 +3144,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) && !gn_system_verilog()) {
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()) {
@ -3176,24 +3373,53 @@ static void pform_set_port_type(perm_string name, NetNet::PortType pt,
}
void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names,
list<pform_range_t>*range,
bool signed_flag,
list<pform_port_t>*ports,
NetNet::PortType pt,
data_type_t*dt,
list<named_pexpr_t>*attr)
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_port_type(txt, pt, li.text, li.first_line);
pform_set_net_range(txt, NetNet::NONE, range, signed_flag, IVL_VT_NO_TYPE,
SR_PORT, attr);
list<pform_range_t>*range = 0;
bool signed_flag = false;
if (vector_type_t*vt = dynamic_cast<vector_type_t*> (dt)) {
assert(vt->implicit_flag);
range = vt->pdims.get();
signed_flag = vt->signed_flag;
} else {
assert(dt == 0);
}
delete names;
delete range;
bool have_init_expr = false;
for (list<pform_port_t>::iterator cur = ports->begin()
; cur != ports->end() ; ++ cur ) {
pform_set_port_type(cur->name, pt, li.text, li.first_line);
pform_set_net_range(cur->name, NetNet::NONE, range, signed_flag,
IVL_VT_NO_TYPE, SR_PORT, attr);
if (cur->udims) {
cerr << li.text << ":" << li.first_line << ": warning: "
<< "Array dimensions in incomplete port declarations "
<< "are currently ignored." << endl;
cerr << li.text << ":" << li.first_line << ": : "
<< "The dimensions specified in the net or variable "
<< "declaration will be used." << endl;
delete cur->udims;
}
if (cur->expr) {
have_init_expr = true;
delete cur->expr;
}
}
if (have_init_expr) {
cerr << li.text << ":" << li.first_line << ": error: "
<< "Incomplete port declarations cannot be initialized."
<< endl;
error_count += 1;
}
delete ports;
delete dt;
delete attr;
}

53
pform.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_H
#define IVL_pform_H
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -163,18 +163,26 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
*/
extern void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, bool is_interface,
LexicalScope::lifetime_t lifetime,
list<named_pexpr_t>*attr);
extern void pform_check_timeunit_prec();
extern void pform_module_set_ports(vector<Module::port_t*>*);
/* This function is used to support the port definition in a
port_definition_list. In this case, we have everything needed to
define the port, all in one place. */
/* These functions are used when we have a complete port definition, either
in an ansi style or non-ansi style declaration. In this case, we have
everything needed to define the port, all in one place. */
extern void pform_module_define_port(const struct vlltype&li,
perm_string name,
NetNet::PortType,
NetNet::Type type,
data_type_t*vtype,
list<named_pexpr_t>*attr,
bool keep_attr =false);
extern void pform_module_define_port(const struct vlltype&li,
list<pform_port_t>*ports,
NetNet::PortType,
NetNet::Type type,
data_type_t*vtype,
list<named_pexpr_t>*attr);
extern Module::port_t* pform_module_port_reference(perm_string name,
@ -186,7 +194,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine,
extern void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type,
data_type_t*base_type,
std::list<PExpr*>*base_exprs);
std::list<PExpr*>*base_exprs,
LexicalScope::lifetime_t lifetime);
extern void pform_class_property(const struct vlltype&loc,
property_qualifier_t pq,
data_type_t*data_type,
@ -211,7 +220,8 @@ extern void pform_make_udp(perm_string name,
* Package related functions.
*/
extern void pform_start_package_declaration(const struct vlltype&loc,
const char*type);
const char*type,
LexicalScope::lifetime_t lifetime);
extern void pform_end_package_declaration(const struct vlltype&loc);
extern void pform_package_import(const struct vlltype&loc,
PPackage*pkg, const char*ident);
@ -246,13 +256,20 @@ extern void pform_pop_scope();
*/
extern LexicalScope* pform_peek_scope();
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime);
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name);
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime);
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
bool is_auto);
LexicalScope::lifetime_t lifetime);
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
bool is_auto);
LexicalScope::lifetime_t lifetime);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern void pform_put_behavior_in_scope(AProcess*proc);
@ -351,17 +368,17 @@ extern void pform_makewire(const struct vlltype&li,
list<perm_string>*names,
list<named_pexpr_t>*attr);
extern void pform_make_reginit(const struct vlltype&li,
perm_string name, PExpr*expr);
extern void pform_make_var_init(const struct vlltype&li,
perm_string name, PExpr*expr);
/* Look up the names of the wires, and set the port type,
i.e. input, output or inout. If the wire does not exist, create
it. The second form takes a single name. */
/* This function is used when we have an incomplete port definition in
a non-ansi style declaration. Look up the names of the wires, and set
the port type, i.e. input, output or inout, and, if specified, the
range and signedness. If the wire does not exist, create it. */
extern void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names,
list<pform_range_t>*range,
bool signed_flag,
list<pform_port_t>*ports,
NetNet::PortType,
data_type_t*dt,
list<named_pexpr_t>*attr);
extern void pform_set_reg_idx(perm_string name,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -318,7 +318,7 @@ void PECallFunction::dump(ostream &out) const
void PECastSize::dump(ostream &out) const
{
out << size_ << "'(";
out << *size_ << "'(";
base_->dump(out);
out << ")";
}
@ -789,6 +789,8 @@ void PBlock::dump(ostream&out, unsigned ind) const
dump_events_(out, ind+2);
dump_wires_(out, ind+2);
dump_var_inits_(out, ind+2);
}
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
@ -926,7 +928,10 @@ void PDisable::dump(ostream&out, unsigned ind) const
void PDoWhile::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "do" << endl;
statement_->dump(out, ind+3);
if (statement_)
statement_->dump(out, ind+3);
else
out << setw(ind+3) << "" << "/* NOOP */" << endl;
out << setw(ind) << "" << "while (" << *cond_ << ");" << endl;
}
@ -989,13 +994,19 @@ void PForeach::dump(ostream&fd, unsigned ind) const
}
fd << "] /* " << get_fileline() << " */" << endl;
statement_->dump(fd, ind+3);
if (statement_)
statement_->dump(fd, ind+3);
else
fd << setw(ind+3) << "" << "/* NOOP */" << endl;
}
void PForever::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "forever /* " << get_fileline() << " */" << endl;
statement_->dump(out, ind+3);
if (statement_)
statement_->dump(out, ind+3);
else
out << setw(ind+3) << "" << "/* NOOP */" << endl;
}
void PForStatement::dump(ostream&out, unsigned ind) const
@ -1003,7 +1014,10 @@ void PForStatement::dump(ostream&out, unsigned ind) const
out << setw(ind) << "" << "for (" << *name1_ << " = " << *expr1_
<< "; " << *cond_ << "; <for_step>)" << endl;
step_->dump(out, ind+6);
statement_->dump(out, ind+3);
if (statement_)
statement_->dump(out, ind+3);
else
out << setw(ind+3) << "" << "/* NOOP */" << endl;
}
void PFunction::dump(ostream&out, unsigned ind) const
@ -1030,6 +1044,8 @@ void PFunction::dump(ostream&out, unsigned ind) const
dump_wires_(out, ind+2);
dump_var_inits_(out, ind+2);
if (statement_)
statement_->dump(out, ind+2);
else
@ -1045,7 +1061,10 @@ void PRelease::dump(ostream&out, unsigned ind) const
void PRepeat::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "repeat (" << *expr_ << ")" << endl;
statement_->dump(out, ind+3);
if (statement_)
statement_->dump(out, ind+3);
else
out << setw(ind+3) << "" << "/* NOOP */" << endl;
}
void PReturn::dump(ostream&fd, unsigned ind) const
@ -1072,6 +1091,8 @@ void PTask::dump(ostream&out, unsigned ind) const
dump_wires_(out, ind+2);
dump_var_inits_(out, ind+2);
if (statement_)
statement_->dump(out, ind+2);
else
@ -1126,7 +1147,10 @@ void PTrigger::dump(ostream&out, unsigned ind) const
void PWhile::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "while (" << *cond_ << ")" << endl;
statement_->dump(out, ind+3);
if (statement_)
statement_->dump(out, ind+3);
else
out << setw(ind+3) << "" << "/* NOOP */" << endl;
}
void PProcess::dump(ostream&out, unsigned ind) const
@ -1136,7 +1160,10 @@ void PProcess::dump(ostream&out, unsigned ind) const
dump_attributes_map(out, attributes, ind+2);
statement_->dump(out, ind+2);
if (statement_)
statement_->dump(out, ind+2);
else
out << setw(ind+2) << "" << "/* NOOP */" << endl;
}
void AProcess::dump(ostream&out, unsigned ind) const
@ -1157,7 +1184,10 @@ void AProcess::dump(ostream&out, unsigned ind) const
dump_attributes_map(out, attributes, ind+2);
statement_->dump(out, ind+2);
if (statement_)
statement_->dump(out, ind+2);
else
out << setw(ind+2) << "" << "/* NOOP */" << endl;
}
void PSpecPath::dump(std::ostream&out, unsigned ind) const
@ -1269,6 +1299,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2);
}
dump_var_inits_(out, indent+2);
for (list<PProcess*>::const_iterator idx = behaviors.begin()
; idx != behaviors.end() ; ++ idx ) {
(*idx)->dump(out, indent+2);
@ -1408,6 +1440,14 @@ void LexicalScope::dump_wires_(ostream&out, unsigned indent) const
}
}
void LexicalScope::dump_var_inits_(ostream&out, unsigned indent) const
{
// Iterate through and display all the register initializations.
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
var_inits[idx]->dump(out, indent);
}
}
void PScopeExtra::dump_classes_(ostream&out, unsigned indent) const
{
// Dump the task definitions.
@ -1564,6 +1604,7 @@ void Module::dump(ostream&out) const
(*gate)->dump(out);
}
dump_var_inits_(out, 4);
for (list<PProcess*>::const_iterator behav = behaviors.begin()
; behav != behaviors.end() ; ++ behav ) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -35,12 +35,13 @@ map<perm_string,PPackage*> pform_packages;
static PPackage*pform_cur_package = 0;
void pform_start_package_declaration(const struct vlltype&loc, const char*name)
void pform_start_package_declaration(const struct vlltype&loc, const char*name,
LexicalScope::lifetime_t lifetime)
{
ivl_assert(loc, pform_cur_package == 0);
perm_string use_name = lex_strings.make(name);
PPackage*pkg_scope = pform_push_package_scope(loc, use_name);
PPackage*pkg_scope = pform_push_package_scope(loc, use_name, lifetime);
FILE_NAME(pkg_scope, loc);
pform_cur_package = pkg_scope;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@ -36,9 +36,13 @@ static PClass*pform_cur_class = 0;
* if present, are the "exprs" that would be passed to a chained
* constructor.
*/
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list<PExpr*>*base_exprs)
void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type,
data_type_t*base_type,
list<PExpr*>*base_exprs,
LexicalScope::lifetime_t lifetime)
{
PClass*class_scope = pform_push_class_scope(loc, type->name);
PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime);
class_scope->type = type;
assert(pform_cur_class == 0);
pform_cur_class = class_scope;
@ -75,6 +79,7 @@ void pform_class_property(const struct vlltype&loc,
if (! curp->index.empty()) {
list<pform_range_t>*pd = new list<pform_range_t> (curp->index);
use_type = new uarray_type_t(use_type, pd);
FILE_NAME(use_type, loc);
}
pform_cur_class->type->properties[curp->name]
@ -127,7 +132,7 @@ void pform_set_constructor_return(PFunction*net)
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
{
assert(pform_cur_class);
PFunction*func = pform_push_function_scope(loc, "new", true);
PFunction*func = pform_push_function_scope(loc, "new", LexicalScope::AUTOMATIC);
return func;
}
@ -138,7 +143,7 @@ void pform_end_class_declaration(const struct vlltype&loc)
// If there were initializer statements, then collect them
// into an implicit constructor function.
if (! pform_cur_class->type->initialize.empty()) {
PFunction*func = pform_push_function_scope(loc, "new@", true);
PFunction*func = pform_push_function_scope(loc, "new@", LexicalScope::AUTOMATIC);
func->set_ports(0);
pform_set_constructor_return(func);
pform_set_this_class(loc, func);

View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_types_H
#define IVL_pform_types_H
/*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-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
@ -72,6 +72,21 @@ typedef named<PExpr*> named_pexpr_t;
*/
typedef std::pair<PExpr*,PExpr*> pform_range_t;
/*
* The pform_port_t holds the name and optional unpacked dimensions
* and initialization expression for a single port in a list of port
* declarations.
*/
struct pform_port_t {
pform_port_t(perm_string n, list<pform_range_t>*ud, PExpr*e)
: name(n), udims(ud), expr(e) { }
~pform_port_t() { }
perm_string name;
list<pform_range_t>*udims;
PExpr*expr;
};
/*
* Semantic NOTES:
* - The SEL_BIT is a single expression. This might me a bit select

View File

@ -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.)

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2015 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
@ -103,6 +103,14 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
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: "
@ -218,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);
@ -555,7 +565,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
// 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));
unsigned sel_need = max(ceil(log2(max_guard_value + 1)), 1.0);
// If the sel_width can select more than just the explicit
// guard values, and there is a default statement, then adjust
@ -1411,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

View File

@ -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);

View File

@ -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())

View File

@ -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 (steve@icarus.com)\n\n"
"Copyright (c) 2013,2015 Stephen Williams (steve@icarus.com)\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"

View File

@ -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 (steve@icarus.com)\n\n"
"Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)\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"

View File

@ -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 (steve@icarus.com)\n\n"
"Copyright (c) 2014,2015 Stephen Williams (steve@icarus.com)\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"

View File

@ -42,7 +42,6 @@ void show_constant(ivl_net_const_t net)
case IVL_VT_REAL:
fprintf(out, "%f", ivl_const_real(net));
break;
break;
default:
fprintf(out, "<unsupported type>");
break;

View File

@ -2,7 +2,7 @@
// are not used here.
// target_design()
unusedFunction:stub.c:1773
unusedFunction:stub.c:1774
// target_query()
unusedFunction:stub.c:1843
unusedFunction:stub.c:1844

View File

@ -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 (steve@icarus.com)\n\n"
"Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)\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"

View File

@ -1180,7 +1180,7 @@ static long get_number_as_long(ivl_expr_t expr)
}
if (ivl_expr_signed(expr) && bits[nbits-1] == '1' &&
nbits < 8*sizeof(long)) imm |= -1L << nbits;
nbits < 8*sizeof(long)) imm |= -1UL << nbits;
}
break;
}

View File

@ -1,3 +1,4 @@
functor:cprop
functor:nodangle
flag:DLL=vhdl.tgt
flag:DISABLE_CONCATZ_GENERATION=true

View File

@ -1407,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 {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2016 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
@ -747,7 +747,9 @@ void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex, unsigned allow_UD)
* This function traverses the scope tree looking for the enclosing module
* scope. When it is found the module scope is returned. As far as this
* translation is concerned a package is a special form of a module
* definition and a class is also a top level scope.
* definition and a class is also a top level scope. In SystemVerilog,
* tasks and functions can also be top level scopes - we create a wrapper
* module for these later.
*/
ivl_scope_t get_module_scope(ivl_scope_t scope)
{
@ -756,6 +758,12 @@ ivl_scope_t get_module_scope(ivl_scope_t scope)
(ivl_scope_type(scope) != IVL_SCT_PACKAGE) &&
(ivl_scope_type(scope) != IVL_SCT_CLASS)) {
ivl_scope_t pscope = ivl_scope_parent(scope);
if (pscope == 0) {
if (ivl_scope_type(scope) == IVL_SCT_TASK)
break;
if (ivl_scope_type(scope) == IVL_SCT_FUNCTION)
break;
}
assert(pscope);
scope = pscope;
}
@ -872,7 +880,8 @@ void emit_scope_path(ivl_scope_t scope, ivl_scope_t call_scope)
/* Check to see if this is a root scope task or function. */
if (ivl_scope_parent(call_scope) == 0) {
fprintf(vlog_out, "ivl_root_scope.");
fprintf(vlog_out, "ivl_root_scope_%s.",
ivl_scope_basename(call_scope));
mod_scope = 0;
call_mod_scope = 0;
} else {
@ -938,3 +947,30 @@ void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb)
break;
}
}
const char*get_time_const(int time_value)
{
switch (time_value) {
case 2: return "100s";
case 1: return "10s";
case 0: return "1s";
case -1: return "100ms";
case -2: return "10ms";
case -3: return "1ms";
case -4: return "100us";
case -5: return "10us";
case -6: return "1us";
case -7: return "100ns";
case -8: return "10ns";
case -9: return "1ns";
case -10: return "100ps";
case -11: return "10ps";
case -12: return "1ps";
case -13: return "100fs";
case -14: return "10fs";
case -15: return "1fs";
default:
fprintf(stderr, "Invalid time constant value %d.\n", time_value);
return "N/A";
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2016 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
@ -24,33 +24,6 @@
const char *func_rtn_name = 0;
static const char*get_time_const(int time_value)
{
switch (time_value) {
case 2: return "100s";
case 1: return "10s";
case 0: return "1s";
case -1: return "100ms";
case -2: return "10ms";
case -3: return "1ms";
case -4: return "100us";
case -5: return "10us";
case -6: return "1us";
case -7: return "100ns";
case -8: return "10ns";
case -9: return "1ns";
case -10: return "100ps";
case -11: return "10ps";
case -12: return "1ps";
case -13: return "100fs";
case -14: return "10fs";
case -15: return "1fs";
default:
fprintf(stderr, "Invalid time constant value %d.\n", time_value);
return "N/A";
}
}
static void emit_func_return(ivl_signal_t sig)
{
if (ivl_signal_dimensions(sig) > 0) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2013 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2016 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
@ -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. (cygcary@yahoo.com)\n\n"
"Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)\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"
@ -60,7 +60,6 @@ int target_design(ivl_design_t des)
{
ivl_scope_t *roots;
unsigned nroots, idx;
unsigned has_root_scope = 0;
const char*path = ivl_design_flag(des, "-o");
/* Set the indent spacing with the -pspacing flag passed to iverilog
* (e.g. -pspacing=4). The default is 2 spaces. */
@ -190,23 +189,27 @@ int target_design(ivl_design_t des)
switch(ivl_scope_type(roots[idx])) {
case IVL_SCT_FUNCTION:
case IVL_SCT_TASK:
if (! has_root_scope) {
fprintf(vlog_out, "module ivl_root_scope;\n");
indent += indent_incr;
has_root_scope = 1;
}
/* Create a separate module for each task/function.
This allows us to handle different timescales. */
fprintf(vlog_out, "\n`timescale %s/%s\n",
get_time_const(ivl_scope_time_units(roots[idx])),
get_time_const(ivl_scope_time_precision(roots[idx])));
fprintf(vlog_out, "module ivl_root_scope_%s;\n",
ivl_scope_basename(roots[idx]));
indent += indent_incr;
/* Say this task/function has a parent so the
* definition is emitted correctly. */
emit_scope(roots[idx], roots[idx]);
indent -= indent_incr;
assert(indent == 0);
fprintf(vlog_out, "endmodule /* ivl_root_scope_%p */\n",
roots[idx]);
break;
default:
break;
}
}
if (has_root_scope) {
indent -= indent_incr;
assert(indent == 0);
fprintf(vlog_out, "endmodule /* ivl_root_scope */\n");
}
/* Emit the rest of the scope objects. */
for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0);

View File

@ -1,7 +1,7 @@
#ifndef IVL_vlog95_priv_H
#define IVL_vlog95_priv_H
/*
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2016 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
@ -145,6 +145,11 @@ extern char * get_package_name(ivl_scope_t scope);
*/
extern void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb);
/*
* Convert a timescale value to a string.
*/
extern const char*get_time_const(int time_value);
/*
* Cleanup functions.
*/

View File

@ -47,8 +47,8 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = vvp.o draw_class.o draw_enum.o draw_mux.o draw_substitute.o draw_net_input.o \
draw_switch.o draw_ufunc.o draw_vpi.o \
O = vvp.o draw_class.o draw_delay.o draw_enum.o draw_mux.o draw_net_input.o \
draw_substitute.o draw_switch.o draw_ufunc.o draw_vpi.o \
eval_bool.o \
eval_condit.o \
eval_expr.o eval_object.o eval_real.o eval_string.o \

127
tgt-vvp/draw_delay.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 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
* 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 "vvp_priv.h"
# include <assert.h>
# include <stdlib.h>
# include <string.h>
/*
* This function draws a BUFT to drive a constant delay value.
*/
static char* draw_const_net(void*ptr, char*suffix, uint64_t value)
{
char tmp[64];
char c4_value[69];
unsigned idx;
c4_value[0] = 'C';
c4_value[1] = '4';
c4_value[2] = '<';
for (idx = 0; idx < 64; idx += 1) {
c4_value[66-idx] = (value & 1) ? '1' : '0';
value >>= 1;
}
c4_value[67] = '>';
c4_value[68] = 0;
/* Make the constant an argument to a BUFT, which is
what we use to drive the value. */
fprintf(vvp_out, "L_%p/%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
ptr, suffix, c4_value);
snprintf(tmp, sizeof tmp, "L_%p/%s", ptr, suffix);
return strdup(tmp);
}
/*
* Draw the appropriate delay statement.
*/
void draw_delay(void*ptr, unsigned wid, const char*input, ivl_expr_t rise_exp,
ivl_expr_t fall_exp, ivl_expr_t decay_exp)
{
char tmp[64];
if (input == 0) {
snprintf(tmp, sizeof tmp, "L_%p/d", ptr);
input = tmp;
}
/* If the delays are all constants then process them here. */
if (number_is_immediate(rise_exp, 64, 0) &&
number_is_immediate(fall_exp, 64, 0) &&
number_is_immediate(decay_exp, 64, 0)) {
assert(! number_is_unknown(rise_exp));
assert(! number_is_unknown(fall_exp));
assert(! number_is_unknown(decay_exp));
fprintf(vvp_out, "L_%p .delay %u "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") %s;\n",
ptr, wid,
get_number_immediate64(rise_exp),
get_number_immediate64(fall_exp),
get_number_immediate64(decay_exp),
input);
/* For a variable delay we indicate only two delays by setting the
* decay time to zero. */
} else {
char*rise_const = 0;
char*fall_const = 0;
char*decay_const = 0;
const char*rise_str;
const char*fall_str;
const char*decay_str;
if (number_is_immediate(rise_exp, 64, 0)) {
uint64_t value = get_number_immediate64(rise_exp);
rise_str = rise_const = draw_const_net(ptr, "tr", value);
} else {
ivl_signal_t sig = ivl_expr_signal(rise_exp);
assert(sig && ivl_signal_dimensions(sig) == 0);
rise_str = draw_net_input(ivl_signal_nex(sig,0));
}
if (number_is_immediate(fall_exp, 64, 0)) {
uint64_t value = get_number_immediate64(fall_exp);
fall_str = fall_const = draw_const_net(ptr, "tf", value);
} else {
ivl_signal_t sig = ivl_expr_signal(fall_exp);
assert(sig && ivl_signal_dimensions(sig) == 0);
fall_str = draw_net_input(ivl_signal_nex(sig,0));
}
if (decay_exp == 0) {
decay_str = "0";
} else if (number_is_immediate(decay_exp, 64, 0)) {
uint64_t value = get_number_immediate64(decay_exp);
decay_str = decay_const = draw_const_net(ptr, "td", value);
} else {
ivl_signal_t sig = ivl_expr_signal(decay_exp);
assert(sig && ivl_signal_dimensions(sig) == 0);
decay_str = draw_net_input(ivl_signal_nex(sig,0));
}
fprintf(vvp_out, "L_%p .delay %u %s, %s, %s, %s;\n",
ptr, wid, input, rise_str, fall_str, decay_str);
free(rise_const);
free(fall_const);
free(decay_const);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2012 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
@ -51,44 +51,8 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
if (data_type_of_nexus(ivl_lpm_q(net)) == IVL_VT_REAL)
dly_width = 0;
draw_delay(net, dly_width, 0, d_rise, d_fall, d_decay);
dly = "/d";
if (number_is_immediate(d_rise, 64, 0) &&
number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 64, 0)) {
assert( ! number_is_unknown(d_rise));
assert( ! number_is_unknown(d_fall));
assert( ! number_is_unknown(d_decay));
fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
net, dly_width,
get_number_immediate64(d_rise),
get_number_immediate64(d_fall),
get_number_immediate64(d_decay), net);
} else {
ivl_signal_t sig;
// We do not currently support calculating the decay from
// the rise and fall variable delays.
assert(d_decay != 0);
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
fprintf(vvp_out, "L_%p .delay %u L_%p/d",
net, dly_width, net);
sig = ivl_expr_signal(d_rise);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_fall);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_decay);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0;\n", sig);
}
}
input[0] = draw_net_input(ivl_lpm_data(net,0));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -330,9 +330,11 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
cptr = ivl_nexus_ptr_con(nptr);
if (cptr) {
char tmp[64];
char *result = 0;
ivl_expr_t d_rise, d_fall, d_decay;
unsigned dly_width = 0;
char *dly;
/* Constants should have exactly 1 pin, with a literal value. */
assert(nptr_pin == 0);
@ -368,68 +370,17 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
d_fall = ivl_const_delay(cptr, 1);
d_decay = ivl_const_delay(cptr, 2);
/* We have a delayed constant, so we need to build some code. */
dly = "";
if (d_rise != 0) {
char tmp[128];
fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
free(result);
/* Is this a fixed or variable delay? */
if (number_is_immediate(d_rise, 64, 0) &&
number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 64, 0)) {
assert(! number_is_unknown(d_rise));
assert(! number_is_unknown(d_fall));
assert(! number_is_unknown(d_decay));
fprintf(vvp_out, "L_%p .delay %u "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
cptr, dly_width,
get_number_immediate64(d_rise),
get_number_immediate64(d_fall),
get_number_immediate64(d_decay), cptr);
} else {
ivl_signal_t sig;
// We do not currently support calculating the decay
// from the rise and fall variable delays.
assert(d_decay != 0);
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
fprintf(vvp_out, "L_%p .delay %u L_%p/d",
cptr, dly_width, cptr);
sig = ivl_expr_signal(d_rise);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_fall);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_decay);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0;\n", sig);
}
snprintf(tmp, sizeof tmp, "L_%p", cptr);
result = strdup(tmp);
} else {
char tmp[64];
fprintf(vvp_out, "L_%p .functor BUFT 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
free(result);
snprintf(tmp, sizeof tmp, "L_%p", cptr);
result = strdup(tmp);
draw_delay(cptr, dly_width, 0, d_rise, d_fall, d_decay);
dly = "/d";
}
fprintf(vvp_out, "L_%p%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
cptr, dly, result);
free(result);
return result;
snprintf(tmp, sizeof tmp, "L_%p", cptr);
return strdup(tmp);
}
lpm = ivl_nexus_ptr_lpm(nptr);
@ -711,6 +662,8 @@ static void draw_net_input_x(ivl_nexus_t nex,
tmp += strlen(tmp);
switch (res) {
case IVL_SIT_TRI:
case IVL_SIT_TRIAND:
case IVL_SIT_TRIOR:
case IVL_SIT_UWIRE:
for (jdx = 0 ; jdx < wid ; jdx += 1)
*tmp++ = 'z';

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2010,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-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
@ -38,18 +38,6 @@ void draw_switch_in_scope(ivl_switch_t sw)
ivl_expr_t fall_exp = ivl_switch_delay(sw, 1);
ivl_expr_t decay_exp= ivl_switch_delay(sw, 2);
if ((rise_exp || fall_exp || decay_exp) &&
(!number_is_immediate(rise_exp, 64, 0) ||
number_is_unknown(rise_exp) ||
!number_is_immediate(fall_exp, 64, 0) ||
number_is_unknown(fall_exp) ||
!number_is_immediate(decay_exp, 64, 0) ||
number_is_unknown(decay_exp))) {
fprintf(stderr, "%s:%u: error: Invalid tranif delay expression.\n",
ivl_switch_file(sw), ivl_switch_lineno(sw));
vvp_errors += 1;
}
island = ivl_switch_island(sw);
if (ivl_island_flag_test(island, 0) == 0)
draw_tran_island(island);
@ -67,24 +55,18 @@ void draw_switch_in_scope(ivl_switch_t sw)
char str_e_buf[4 + 2*sizeof(void*)];
if (enable && rise_exp) {
assert(fall_exp && decay_exp);
/* If the enable has a delay, then generate a .delay
node to delay the input by the specified amount. Do
the delay outside of the island so that the island
processing doesn't have to deal with it. */
const char*raw = draw_net_input(enable);
draw_delay(sw, 1, raw, rise_exp, fall_exp, decay_exp);
snprintf(str_e_buf, sizeof str_e_buf, "p%p", sw);
str_e = str_e_buf;
fprintf(vvp_out, "%s/d .delay 1 "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") %s;\n",
str_e, get_number_immediate64(rise_exp),
get_number_immediate64(fall_exp),
get_number_immediate64(decay_exp), raw);
fprintf(vvp_out, "%s .import I%p, %s/d;\n", str_e, island, str_e);
fprintf(vvp_out, "%s .import I%p, L_%p;\n", str_e, island, sw);
} else if (enable) {
str_e = draw_island_net_input(island, enable);

View File

@ -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);

View File

@ -139,7 +139,7 @@ long get_number_immediate(ivl_expr_t expr)
assert(0);
}
if (ivl_expr_signed(expr) && bits[nbits-1]=='1' &&
nbits < 8*sizeof(long)) imm |= -1L << nbits;
nbits < 8*sizeof(long)) imm |= -1UL << nbits;
break;
}

View File

@ -1032,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) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-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
@ -183,17 +183,17 @@ static void get_vec_from_lval(ivl_statement_t net, struct vec_slice_info*slices)
unsigned wid = ivl_stmt_lwidth(net);
cur_bit = 0;
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
for (lidx = ivl_stmt_lvals(net) ; lidx > 0 ; lidx -= 1) {
ivl_lval_t lval;
unsigned bit_limit = wid - cur_bit;
lval = ivl_stmt_lval(net, lidx);
lval = ivl_stmt_lval(net, lidx-1);
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
get_vec_from_lval_slice(lval, slices+lidx, bit_limit);
if (lidx > 0) {
get_vec_from_lval_slice(lval, slices+lidx-1, bit_limit);
if (cur_bit > 0) {
fprintf(vvp_out, " %%concat/vec4;\n");
}
@ -555,28 +555,130 @@ static int show_stmt_assign_vector(ivl_statement_t net)
return 0;
}
/*
* This function assigns a value to a real variable. This is destined
* for /dev/null when typed ivl_signal_t takes over all the real
* variable support.
*/
static int show_stmt_assign_sig_real(ivl_statement_t net)
enum real_lval_type_e {
REAL_NO_TYPE = 0,
REAL_SIMPLE_WORD,
REAL_MEMORY_WORD_STATIC,
REAL_MEMORY_WORD_DYNAMIC
};
struct real_lval_info {
enum real_lval_type_e type;
union {
struct {
unsigned long use_word;
} simple_word;
struct {
unsigned long use_word;
} memory_word_static;
struct {
/* Index reg that holds the memory word index */
int word_idx_reg;
/* Stored x/non-x flag */
unsigned x_flag;
} memory_word_dynamic;
} u_;
};
static void get_real_from_lval(ivl_lval_t lval, struct real_lval_info*slice)
{
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_expr_t word_ix = ivl_lval_idx(lval);
unsigned long use_word = 0;
/* If the word index is a constant expression, then evaluate
it to select the word, and pay no further heed to the
expression itself. */
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
assert(! number_is_unknown(word_ix));
use_word = get_number_immediate(word_ix);
word_ix = 0;
}
if (ivl_signal_dimensions(sig)==0 && word_ix==0) {
slice->type = REAL_SIMPLE_WORD;
slice->u_.simple_word.use_word = use_word;
fprintf(vvp_out, " %%load/real v%p_%lu;\n", sig, use_word);
} else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {
slice->type = REAL_MEMORY_WORD_STATIC;
slice->u_.memory_word_static.use_word = use_word;
if (use_word < ivl_signal_array_count(sig)) {
fprintf(vvp_out, " %%ix/load 3, %lu, 0;\n",
use_word);
fprintf(vvp_out, " %%load/reala v%p, 3;\n", sig);
} else {
fprintf(vvp_out, " %%pushi/real 0, 0;\n");
}
} else if (ivl_signal_dimensions(sig) > 0 && word_ix != 0) {
slice->type = REAL_MEMORY_WORD_DYNAMIC;
slice->u_.memory_word_dynamic.word_idx_reg = allocate_word();
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 %u, 4;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%load/reala v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
} else {
assert(0);
}
}
static void put_real_to_lval(ivl_lval_t lval, struct real_lval_info*slice)
{
ivl_signal_t sig = ivl_lval_sig(lval);
switch (slice->type) {
default:
fprintf(vvp_out, " ; XXXX slice->type=%d\n", slice->type);
assert(0);
break;
case REAL_SIMPLE_WORD:
fprintf(vvp_out, " %%store/real v%p_%lu;\n",
sig, slice->u_.simple_word.use_word);
break;
case REAL_MEMORY_WORD_STATIC:
if (slice->u_.memory_word_static.use_word < ivl_signal_array_count(sig)) {
int word_idx = allocate_word();
fprintf(vvp_out," %%flag_set/imm 4, 0;\n");
fprintf(vvp_out," %%ix/load %d, %lu, 0;\n", word_idx, slice->u_.memory_word_static.use_word);
fprintf(vvp_out," %%store/reala v%p, %d;\n", sig, word_idx);
clr_word(word_idx);
} else {
fprintf(vvp_out," ; Skip this slice write to v%p [%lu]\n", sig, slice->u_.memory_word_static.use_word);
}
break;
case REAL_MEMORY_WORD_DYNAMIC:
fprintf(vvp_out, " %%flag_mov 4, %u;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%store/reala v%p, %d;\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);
break;
}
}
static void store_real_to_lval(ivl_lval_t lval)
{
ivl_lval_t lval;
ivl_signal_t var;
assert(ivl_stmt_opcode(net) == 0);
draw_eval_real(ivl_stmt_rval(net));
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
var = ivl_lval_sig(lval);
assert(var != 0);
if (ivl_signal_dimensions(var) == 0) {
fprintf(vvp_out, " %%store/real v%p_0;\n", var);
return 0;
return;
}
// For now, only support 1-dimensional arrays.
@ -612,7 +714,66 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
}
clr_word(word_ix);
}
/*
* This function assigns a value to a real variable. This is destined
* for /dev/null when typed ivl_signal_t takes over all the real
* variable support.
*/
static int show_stmt_assign_sig_real(ivl_statement_t net)
{
struct real_lval_info*slice = 0;
ivl_lval_t lval;
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
/* If this is a compressed assignment, then get the contents
of the l-value. We need this value as part of the r-value
calculation. */
if (ivl_stmt_opcode(net) != 0) {
fprintf(vvp_out, " ; show_stmt_assign_real: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net));
slice = calloc(1, sizeof(struct real_lval_info));
get_real_from_lval(lval, slice);
}
draw_eval_real(ivl_stmt_rval(net));
switch (ivl_stmt_opcode(net)) {
case 0:
store_real_to_lval(lval);
if (slice) free(slice);
return 0;
case '+':
fprintf(vvp_out, " %%add/wr;\n");
break;
case '-':
fprintf(vvp_out, " %%sub/wr;\n");
break;
case '*':
fprintf(vvp_out, " %%mul/wr;\n");
break;
case '/':
fprintf(vvp_out, " %%div/wr;\n");
break;
case '%':
fprintf(vvp_out, " %%mod/wr;\n");
break;
default:
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
assert(0);
break;
}
put_real_to_lval(lval, slice);
free(slice);
return 0;
}

View File

@ -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 (steve@icarus.com)\n\n"
"Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)\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"

View File

@ -256,6 +256,13 @@ extern void show_stmt_file_line(ivl_statement_t net, const char*desc);
extern int test_immediate_vec4_ok(ivl_expr_t expr);
extern void draw_immediate_vec4(ivl_expr_t expr, const char*opcode);
/*
* Draw a delay statement.
*/
extern void draw_delay(void*ptr, unsigned wid, const char*input,
ivl_expr_t rise_exp, ivl_expr_t fall_exp,
ivl_expr_t decay_exp);
/*
* These functions manage word register allocation.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -225,6 +225,15 @@ static void assign_to_lvector(ivl_lval_t lval,
const unsigned long use_word = 0;
if (ivl_signal_type(sig) == IVL_SIT_UWIRE) {
fprintf(stderr, "%s:%u: tgt-vvp sorry: V10 does not support "
"mixed continuous and non-blocking assignments to "
"different parts of the same vector (%s).\n",
ivl_signal_file(sig), ivl_signal_lineno(sig),
ivl_signal_basename(sig));
vvp_errors += 1;
}
// Detect the case that this is actually a non-blocking assign
// to an array word. In that case, run off somewhere else to
// deal with it.
@ -2298,6 +2307,7 @@ int draw_process(ivl_process_t net, void*x)
ivl_scope_t scope = ivl_process_scope(net);
ivl_statement_t stmt = ivl_process_stmt(net);
int init_flag = 0;
int push_flag = 0;
(void)x; /* Parameter is not used. */
@ -2306,6 +2316,12 @@ int draw_process(ivl_process_t net, void*x)
ivl_attribute_t attr = ivl_process_attr_val(net, idx);
if (strcmp(attr->key, "_ivl_schedule_init") == 0) {
init_flag = 1;
}
if (strcmp(attr->key, "_ivl_schedule_push") == 0) {
push_flag = 1;
@ -2349,7 +2365,9 @@ int draw_process(ivl_process_t net, void*x)
case IVL_PR_INITIAL:
case IVL_PR_ALWAYS:
if (push_flag) {
if (init_flag) {
fprintf(vvp_out, " .thread T_%u, $init;\n", thread_count);
} else if (push_flag) {
fprintf(vvp_out, " .thread T_%u, $push;\n", thread_count);
} else {
fprintf(vvp_out, " .thread T_%u;\n", thread_count);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -669,7 +669,7 @@ static void draw_net_in_scope(ivl_signal_t sig)
swapped ? last : first );
}
fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
fprintf(vvp_out, "v%p_%u .net%s v%p %u, %d %d, "
"v%p_%u; Alias to %s\n", sig, iword,
datatype_flag, sig, iword, msb, lsb,
nex_data->net, nex_data->net_word,
@ -717,7 +717,7 @@ static unsigned need_delay(ivl_net_logic_t lptr)
/*
* Draw the appropriate delay statement. Returns zero if there is not a delay.
*/
static void draw_delay(ivl_net_logic_t lptr)
static void draw_logic_delay(ivl_net_logic_t lptr)
{
ivl_expr_t rise_exp = ivl_logic_delay(lptr, 0);
ivl_expr_t fall_exp = ivl_logic_delay(lptr, 1);
@ -730,49 +730,7 @@ static void draw_delay(ivl_net_logic_t lptr)
delay_wid = 0;
}
/* If the delays are all constants then process them here. */
if (number_is_immediate(rise_exp, 64, 0) &&
number_is_immediate(fall_exp, 64, 0) &&
number_is_immediate(decay_exp, 64, 0)) {
assert(! number_is_unknown(rise_exp));
assert(! number_is_unknown(fall_exp));
assert(! number_is_unknown(decay_exp));
fprintf(vvp_out, "L_%p .delay %u "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
lptr, delay_wid,
get_number_immediate64(rise_exp),
get_number_immediate64(fall_exp),
get_number_immediate64(decay_exp), lptr);
/* For a variable delay we indicate only two delays by setting the
* decay time to zero. */
} else {
ivl_signal_t sig;
assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
assert((decay_exp == 0) ||
(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL));
fprintf(vvp_out, "L_%p .delay %u L_%p/d", lptr, delay_wid, lptr);
sig = ivl_expr_signal(rise_exp);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", %s", draw_net_input(ivl_signal_nex(sig,0)));
sig = ivl_expr_signal(fall_exp);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", %s", draw_net_input(ivl_signal_nex(sig,0)));
if (decay_exp) {
sig = ivl_expr_signal(decay_exp);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", %s;\n",
draw_net_input(ivl_signal_nex(sig,0)));
} else {
fprintf(vvp_out, ", 0;\n");
}
}
draw_delay(lptr, delay_wid, 0, rise_exp, fall_exp, decay_exp);
}
static void draw_udp_def(ivl_udp_t udp)
@ -908,7 +866,7 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
fprintf(vvp_out, ";\n");
/* Generate a delay when needed. */
if (need_delay_flag) draw_delay(lptr);
if (need_delay_flag) draw_logic_delay(lptr);
}
static void draw_logic_in_scope(ivl_net_logic_t lptr)
@ -1112,7 +1070,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
free(input_strings);
/* Generate a delay when needed. */
if (need_delay_flag) draw_delay(lptr);
if (need_delay_flag) draw_logic_delay(lptr);
}
static void draw_event_in_scope(ivl_event_t obj)
@ -1312,20 +1270,8 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net, ivl_variable_type_t dt)
const char*dly = "";
if (d_rise != 0) {
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
assert(! number_is_unknown(d_rise));
assert(! number_is_unknown(d_fall));
assert(! number_is_unknown(d_decay));
draw_delay(net, width, 0, d_rise, d_fall, d_decay);
dly = "/d";
fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ")"
" L_%p/d;\n", net, width,
get_number_immediate64(d_rise),
get_number_immediate64(d_fall),
get_number_immediate64(d_decay), net);
}
return dly;

View File

@ -1,6 +1,6 @@
#norootforbuild
#
%define rev_date 20150603
%define rev_date 20170824
# Normally, the suff-ix is %nil, meaning the suffix is to not be used.
# But if the builder wants to make a suffixed package, he may set this
# to a value (i.e. -test) to cause suffixes to be put in all the right
@ -10,11 +10,11 @@
#
Summary: Icarus Verilog
Name: verilog%{suff}
Version: 0.10.0.%{rev_date}
Version: 10.2
Release: 0
License: GPL
Group: Productivity/Scientific/Electronics
Source: verilog%{suff}-%{rev_date}.tar.gz
Source: verilog%{suff}-%{version}.tar.gz
URL: http://www.icarus.com/eda/verilog/index.html
Packager: Stephen Williams <steve@icarus.com>
@ -32,7 +32,7 @@ engineering formats, including simulation. It strives to be true
to the IEEE-1364 standard.
%prep
%setup -n verilog%{suff}-%{rev_date}
%setup -n verilog-%{version}
%build
if test X%{suff} != X

View File

@ -29,10 +29,7 @@ static void run_string(const char*txt)
if (cp[0] == '%' && cp[1] != 0) {
switch (cp[1]) {
case 'M':
fprintf(stdout, "%u", VERSION_MAJOR1);
break;
case 'm':
fprintf(stdout, "%u", VERSION_MAJOR2);
fprintf(stdout, "%u", VERSION_MAJOR);
break;
case 'n':
fprintf(stdout, "%u", VERSION_MINOR);

View File

@ -3,17 +3,17 @@
* Edit this definition in version_base.in to define the base version
* number for the compiled result.
*/
# define VERSION_MAJOR1 0
# define VERSION_MAJOR2 10
# define VERSION_MINOR 0
# define VERSION_EXTRA "(devel)"
# define VERSION_MAJOR 10
# define VERSION_MINOR 2
/* This is a concatenation of MAJOR1.MAJOR2 that is used by
vams_simparam.c to make a double value. */
# define VERSION_MAJOR 0.10
/*
* This will be appended to the version. Use this to mark development
* versions and the like.
*/
# define VERSION_EXTRA " (stable)"
# define VERSION_STRINGIFY(x) #x
# define VERSION_STR(a,b,extra) VERSION_STRINGIFY(a.b) " " extra
# define VERSION_STR(a,b,extra) VERSION_STRINGIFY(a.b) extra
#define VERSION VERSION_STR(VERSION_MAJOR,VERSION_MINOR,VERSION_EXTRA)
#endif

View File

@ -61,7 +61,9 @@ ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam)
ExpAttribute::~ExpAttribute()
{
delete base_;
/* Different attributes can point to the same base so we cannot delete this here.
* Look at the vhdl_range test with valgrind to see this issue. */
// delete base_;
}
Expression*ExpAttribute::clone() const

View File

@ -874,7 +874,7 @@ const VType* ExpName::probe_prefix_type_(Entity*ent, ScopeBase*scope) const
}
/*
* This method is the probe_type() imlementation for ExpName objects
* This method is the probe_type() implementation for ExpName objects
* that have prefix parts. In this case we try to get the type of the
* prefix and interpret the name in that context.
*/

View File

@ -38,7 +38,7 @@ const char COPYRIGHT[] =
* information to the file named <path>.
*
* elaboration=<path>
* Enable debugging of elaboratin by dumping elaboration
* Enable debugging of elaboration by dumping elaboration
* process information to the file named <path>.
*
* entities=<path>

View File

@ -665,7 +665,7 @@ component_configuration
block_configuration_opt
K_end K_for ';'
{
sorrymsg(@1, "Component configuration in not yet supported");
sorrymsg(@1, "Component configuration in not yet supported\n");
if($3) delete $3;
delete $2;
}
@ -834,14 +834,14 @@ else_when_waveform
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
: concurrent_simple_signal_assignment
| IDENTIFIER ':' concurrent_simple_signal_assignment
| IDENTIFIER ':' concurrent_simple_signal_assignment
{ delete[] $1;
$$ = $3;
}
| concurrent_conditional_signal_assignment
| IDENTIFIER ':' concurrent_conditional_signal_assignment
| IDENTIFIER ':' concurrent_conditional_signal_assignment
{ delete[] $1;
$$ = $3;
}
@ -878,7 +878,7 @@ configuration_declaration
K_end K_configuration_opt identifier_opt ';'
{
if(design_entities.find(lex_strings.make($4)) == design_entities.end())
errormsg(@4, "Couldn't find entity %s used in configuration declaration", $4);
errormsg(@4, "Couldn't find entity %s used in configuration declaration\n", $4);
//choose_architecture_for_entity();
sorrymsg(@1, "Configuration declaration is not yet supported.\n");
}
@ -1873,10 +1873,10 @@ primary
else if(!strcasecmp($2, "fs"))
unit = ExpTime::FS;
else
errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s).");
errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s).\n");
if($1 < 0)
errormsg(@1, "Time cannot be negative.");
errormsg(@1, "Time cannot be negative.\n");
ExpTime*tmp = new ExpTime($1, unit);
FILE_NAME(tmp, @1);
@ -2586,7 +2586,7 @@ suffix
{ $$ = $1; }
| K_all
{ //do not have now better idea than using char constant
$$ = strcpy(new char[strlen("all"+1)], "all");
$$ = strdup("all");
}
;

View File

@ -169,7 +169,7 @@ class ActiveScope : public ScopeBase {
bool is_vector_name(perm_string name) const;
// Locate the subprogram by name. The subprogram body uses
// this to locate the sobprogram declaration. Note that the
// this to locate the subprogram declaration. Note that the
// subprogram may be in a package header.
SubprogramHeader* recall_subprogram(perm_string name) const;

View File

@ -56,7 +56,7 @@ O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_
sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \
sys_sdf.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \
sys_priv.o sdf_parse.o sdf_lexor.o stringheap.o vams_simparam.o \
table_mod.o table_mod_lexor.o table_mod_parse.o
table_mod.o table_mod_parse.o table_mod_lexor.o
OPP = vcd_priv2.o
ifeq (@HAVE_LIBZ@,yes)

View File

@ -3,143 +3,143 @@
// problems will not be fixed.
// fstapi.c from GTKWave
obsoleteFunctionsasctime:fstapi.c:929
obsoleteFunctionsalloca:fstapi.c:2304
unreadVariable:fstapi.c:1647
variableScope:fstapi.c:665
variableScope:fstapi.c:1337
obsoleteFunctionsasctime:fstapi.c:930
obsoleteFunctionsalloca:fstapi.c:2305
unreadVariable:fstapi.c:1648
variableScope:fstapi.c:666
variableScope:fstapi.c:1338
variableScope:fstapi.c:1395
variableScope:fstapi.c:1978
variableScope:fstapi.c:2107
variableScope:fstapi.c:2540
variableScope:fstapi.c:1339
variableScope:fstapi.c:1396
variableScope:fstapi.c:1979
variableScope:fstapi.c:2108
variableScope:fstapi.c:2541
variableScope:fstapi.c:2732
variableScope:fstapi.c:2542
variableScope:fstapi.c:2733
variableScope:fstapi.c:2737
variableScope:fstapi.c:2853
variableScope:fstapi.c:2892
variableScope:fstapi.c:2734
variableScope:fstapi.c:2738
variableScope:fstapi.c:2854
variableScope:fstapi.c:2893
variableScope:fstapi.c:3611
variableScope:fstapi.c:3785
variableScope:fstapi.c:3787
variableScope:fstapi.c:4229
variableScope:fstapi.c:2894
variableScope:fstapi.c:3612
variableScope:fstapi.c:3786
variableScope:fstapi.c:3788
variableScope:fstapi.c:4230
variableScope:fstapi.c:4239
variableScope:fstapi.c:4502
variableScope:fstapi.c:4773
variableScope:fstapi.c:4776
variableScope:fstapi.c:5270
variableScope:fstapi.c:5274
variableScope:fstapi.c:4231
variableScope:fstapi.c:4240
variableScope:fstapi.c:4503
variableScope:fstapi.c:4774
variableScope:fstapi.c:4777
variableScope:fstapi.c:5271
variableScope:fstapi.c:5275
variableScope:fstapi.c:5431
variableScope:fstapi.c:5489
variableScope:fstapi.c:5802
variableScope:fstapi.c:5805
variableScope:fstapi.c:6041
variableScope:fstapi.c:6146
variableScope:fstapi.c:5276
variableScope:fstapi.c:5432
variableScope:fstapi.c:5490
variableScope:fstapi.c:5803
variableScope:fstapi.c:5806
variableScope:fstapi.c:6042
variableScope:fstapi.c:6147
variableScope:fstapi.c:6178
variableScope:fstapi.c:6406
variableScope:fstapi.c:6148
variableScope:fstapi.c:6179
variableScope:fstapi.c:6407
// These functions are not used by Icarus
// fstReaderClrFacProcessMask()
unusedFunction:fstapi.c:3343
unusedFunction:fstapi.c:3344
// fstReaderClrFacProcessMaskAll()
unusedFunction:fstapi.c:3372
unusedFunction:fstapi.c:3373
// fstReaderGetAliasCount()
unusedFunction:fstapi.c:3435
unusedFunction:fstapi.c:3436
// fstReaderGetCurrentFlatScope()
unusedFunction:fstapi.c:3181
unusedFunction:fstapi.c:3182
// fstReaderGetAliasCount()
unusedFunction:fstapi.c:3278
unusedFunction:fstapi.c:3279
// fstReaderGetCurrentScopeUserInfo()
unusedFunction:fstapi.c:3195
unusedFunction:fstapi.c:3196
// fstReaderGetDateString()
unusedFunction:fstapi.c:3463
unusedFunction:fstapi.c:3464
// fstReaderGetDoubleEndianMatchState()
unusedFunction:fstapi.c:3449
unusedFunction:fstapi.c:3450
// fstReaderGetDumpActivityChangeTime()
unusedFunction:fstapi.c:3491
unusedFunction:fstapi.c:3492
// fstReaderGetDumpActivityChangeValue()
unusedFunction:fstapi.c:3506
unusedFunction:fstapi.c:3507
// fstReaderGetEndTime()
unusedFunction:fstapi.c:3400
unusedFunction:fstapi.c:3401
// fstReaderGetFacProcessMask()
unusedFunction:fstapi.c:3306
unusedFunction:fstapi.c:3307
// fstReaderGetFileType()
unusedFunction:fstapi.c:3470
unusedFunction:fstapi.c:3471
// fstReaderGetFseekFailed()
unusedFunction:fstapi.c:3291
unusedFunction:fstapi.c:3292
// fstReaderGetMaxHandle()
unusedFunction:fstapi.c:3428
unusedFunction:fstapi.c:3429
// fstReaderGetMemoryUsedByWriter()
unusedFunction:fstapi.c:3407
unusedFunction:fstapi.c:3408
// fstReaderGetNumberDumpActivityChanges()
unusedFunction:fstapi.c:3484
unusedFunction:fstapi.c:3485
// fstReaderGetScopeCount()
unusedFunction:fstapi.c:3414
unusedFunction:fstapi.c:3415
// fstReaderGetStartTime()
unusedFunction:fstapi.c:3393
unusedFunction:fstapi.c:3394
// fstReaderGetTimescale()
unusedFunction:fstapi.c:3386
unusedFunction:fstapi.c:3387
// fstReaderGetTimezero()
unusedFunction:fstapi.c:3477
unusedFunction:fstapi.c:3478
// fstReaderGetValueChangeSectionCount()
unusedFunction:fstapi.c:3442
unusedFunction:fstapi.c:3443
// fstReaderGetValueFromHandleAtTime()
unusedFunction:fstapi.c:5684
unusedFunction:fstapi.c:5685
// fstReaderGetVarCount()
unusedFunction:fstapi.c:3421
unusedFunction:fstapi.c:3422
// fstReaderGetVersionString()
unusedFunction:fstapi.c:3456
unusedFunction:fstapi.c:3457
// fstReaderIterBlocks()
unusedFunction:fstapi.c:4651
unusedFunction:fstapi.c:4652
// fstReaderIterBlocksSetNativeDoublesOnCallback()
unusedFunction:fstapi.c:3556
unusedFunction:fstapi.c:3557
// fstReaderIterateHier()
unusedFunction:fstapi.c:3781
unusedFunction:fstapi.c:3782
// fstReaderIterateHierRewind()
unusedFunction:fstapi.c:3761
unusedFunction:fstapi.c:3762
// fstReaderOpen()
unusedFunction:fstapi.c:4549
unusedFunction:fstapi.c:4550
// fstReaderOpenForUtilitiesOnly()
unusedFunction:fstapi.c:4541
unusedFunction:fstapi.c:4542
// fstReaderPushScope()
unusedFunction:fstapi.c:3243
unusedFunction:fstapi.c:3244
// fstReaderResetScope()
unusedFunction:fstapi.c:3232
unusedFunction:fstapi.c:3233
// fstReaderSetFacProcessMask()
unusedFunction:fstapi.c:3325
unusedFunction:fstapi.c:3326
// fstReaderSetFacProcessMaskAll()
unusedFunction:fstapi.c:3361
unusedFunction:fstapi.c:3362
// fstReaderSetLimitTimeRange()
unusedFunction:fstapi.c:3521
unusedFunction:fstapi.c:3522
// fstReaderSetUnlimitedTimeRange()
unusedFunction:fstapi.c:3534
unusedFunction:fstapi.c:3535
// fstReaderSetVcdExtensions()
unusedFunction:fstapi.c:3545
unusedFunction:fstapi.c:3546
// fstUtilityEscToBin()
unusedFunction:fstapi.c:6484
unusedFunction:fstapi.c:6485
// fstWriterCreateVar2()
unusedFunction:fstapi.c:2527
unusedFunction:fstapi.c:2528
// fstWriterEmitVariableLengthValueChange()
unusedFunction:fstapi.c:2846
unusedFunction:fstapi.c:2847
// fstWriterGetFseekFailed()
unusedFunction:fstapi.c:2510
unusedFunction:fstapi.c:2511
// fstWriterSetAttrEnd()
unusedFunction:fstapi.c:2713
unusedFunction:fstapi.c:2714
// fstWriterSetComment()
unusedFunction:fstapi.c:2359
unusedFunction:fstapi.c:2360
// fstWriterSetEnvVar()
unusedFunction:fstapi.c:2371
unusedFunction:fstapi.c:2372
// fstWriterSetFileType()
unusedFunction:fstapi.c:2234
unusedFunction:fstapi.c:2235
// fstWriterSetParallelMode()
unusedFunction:fstapi.c:2470
unusedFunction:fstapi.c:2471
// fstWriterSetTimezero()
unusedFunction:fstapi.c:2435
unusedFunction:fstapi.c:2436
// fstWriterSetValueList()
unusedFunction:fstapi.c:2365
unusedFunction:fstapi.c:2366
// These functions are not used by Icarus
//unusedFunction:fstapi.c:226
@ -234,59 +234,63 @@ unusedFunction:fastlz.c:150
// lz4.c from GTKWave
// These functions are not used by Icarus
// LZ4_compress_continue()
unusedFunction:lz4.c:883
unusedFunction:lz4.c:1460
// LZ4_compress_destSize()
unusedFunction:lz4.c:912
// LZ4_compress_fast_force()
unusedFunction:lz4.c:705
// LZ4_compress_forceExtDict()
unusedFunction:lz4.c:895
unusedFunction:lz4.c:1063
// LZ4_compress_limitedOutput()
unusedFunction:lz4.c:730
unusedFunction:lz4.c:1455
// LZ4_compress_limitedOutput_continue()
unusedFunction:lz4.c:888
unusedFunction:lz4.c:1459
// LZ4_compress_limitedOutput_withState()
unusedFunction:lz4.c:1343
unusedFunction:lz4.c:1457
// LZ4_compress_withState()
unusedFunction:lz4.c:1332
unusedFunction:lz4.c:1458
// LZ4_create()
unusedFunction:lz4.c:1314
unusedFunction:lz4.c:1489
// LZ4_createStream()
unusedFunction:lz4.c:765
unusedFunction:lz4.c:935
// LZ4_createStreamDecode()
unusedFunction:lz4.c:1152
unusedFunction:lz4.c:1319
// LZ4_decompress_fast_continue()
unusedFunction:lz4.c:1217
unusedFunction:lz4.c:1384
// LZ4_decompress_fast_usingDict()
unusedFunction:lz4.c:1272
unusedFunction:lz4.c:1439
// LZ4_decompress_fast_withPrefix64k()
unusedFunction:lz4.c:1361
unusedFunction:lz4.c:1510
// LZ4_decompress_safe_continue()
unusedFunction:lz4.c:1188
unusedFunction:lz4.c:1355
// LZ4_decompress_safe_forceExtDict()
unusedFunction:lz4.c:1278
unusedFunction:lz4.c:1445
// LZ4_decompress_safe_usingDict()
unusedFunction:lz4.c:1267
unusedFunction:lz4.c:1434
// LZ4_decompress_safe_withPrefix64k()
unusedFunction:lz4.c:1356
unusedFunction:lz4.c:1505
// LZ4_freeStream()
unusedFunction:lz4.c:773
unusedFunction:lz4.c:948
// LZ4_freeStreamDecode()
unusedFunction:lz4.c:1158
unusedFunction:lz4.c:1325
// LZ4_loadDict()
unusedFunction:lz4.c:780
unusedFunction:lz4.c:956
// LZ4_resetStreamState()
unusedFunction:lz4.c:1307
unusedFunction:lz4.c:1482
// LZ4_setStreamDecode()
unusedFunction:lz4.c:1171
unusedFunction:lz4.c:1338
// LZ4_sizeofState()
unusedFunction:lz4.c:1330
unusedFunction:lz4.c:373
// LZ4_sizeofStreamState()
unusedFunction:lz4.c:1299
unusedFunction:lz4.c:1474
// LZ4_slideInputBuffer()
unusedFunction:lz4.c:1321
unusedFunction:lz4.c:1496
// LZ4_uncompress()
unusedFunction:lz4.c:1293
unusedFunction:lz4.c:1468
// LZ4_uncompress_unknownOutputSize()
unusedFunction:lz4.c:1294
unusedFunction:lz4.c:1469
// LZ4_versionNumber()
unusedFunction:lz4.c:428
unusedFunction:lz4.c:371
// The routines in sys_random.c are exact copies from IEEE1364-2005 and
// they have scope warnings that we need to ignore.

View File

@ -279,7 +279,6 @@ return(ftruncate(fd, length));
static char *fstRealpath(const char *path, char *resolved_path)
{
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
#if (defined(__MACH__) && defined(__APPLE__))
if(!resolved_path)
{
@ -297,6 +296,8 @@ if(!resolved_path)
}
return(_fullpath(resolved_path, path, PATH_MAX));
#else
(void)path;
(void)resolved_path;
return(NULL);
#endif
#endif
@ -3073,6 +3074,7 @@ uint32_t *rvat_chain_table_lengths;
uint64_t rvat_vc_maxhandle;
off_t rvat_vc_start;
uint32_t *rvat_sig_offs;
int rvat_packtype;
uint32_t rvat_chain_len;
unsigned char *rvat_chain_mem;
@ -5885,6 +5887,7 @@ if(frame_uclen == frame_clen)
xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f);
xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
xc->rvat_packtype = fgetc(xc->f);
#ifdef FST_DEBUG
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
@ -5909,37 +5912,84 @@ xc->rvat_chain_table_lengths = calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t
pnt = chain_cmem;
idx = 0;
pval = 0;
do
if(sectype == FST_BL_VCDATA_DYN_ALIAS2)
{
int skiplen;
uint64_t val = fstGetVarint32(pnt, &skiplen);
if(!val)
{
pnt += skiplen;
val = fstGetVarint32(pnt, &skiplen);
xc->rvat_chain_table[idx] = 0;
xc->rvat_chain_table_lengths[idx] = -val;
idx++;
}
else
if(val&1)
{
pval = xc->rvat_chain_table[idx] = pval + (val >> 1);
if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; }
pidx = idx++;
}
else
{
fstHandle loopcnt = val >> 1;
for(i=0;i<loopcnt;i++)
uint32_t prev_alias = 0;
do {
int skiplen;
if(*pnt & 0x01)
{
xc->rvat_chain_table[idx++] = 0;
int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1;
if(shval > 0)
{
pval = xc->rvat_chain_table[idx] = pval + shval;
if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; }
pidx = idx++;
}
else if(shval < 0)
{
xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
xc->rvat_chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */
idx++;
}
else
{
xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
xc->rvat_chain_table_lengths[idx] = prev_alias; /* because during this loop iter would give stale data! */
idx++;
}
}
}
pnt += skiplen;
} while (pnt != (chain_cmem + chain_clen));
else
{
uint64_t val = fstGetVarint32(pnt, &skiplen);
fstHandle loopcnt = val >> 1;
for(i=0;i<loopcnt;i++)
{
xc->rvat_chain_table[idx++] = 0;
}
}
pnt += skiplen;
} while (pnt != (chain_cmem + chain_clen));
}
else
{
do
{
int skiplen;
uint64_t val = fstGetVarint32(pnt, &skiplen);
if(!val)
{
pnt += skiplen;
val = fstGetVarint32(pnt, &skiplen);
xc->rvat_chain_table[idx] = 0;
xc->rvat_chain_table_lengths[idx] = -val;
idx++;
}
else
if(val&1)
{
pval = xc->rvat_chain_table[idx] = pval + (val >> 1);
if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; }
pidx = idx++;
}
else
{
fstHandle loopcnt = val >> 1;
for(i=0;i<loopcnt;i++)
{
xc->rvat_chain_table[idx++] = 0;
}
}
pnt += skiplen;
} while (pnt != (chain_cmem + chain_clen));
}
free(chain_cmem);
xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start;
@ -6003,10 +6053,20 @@ if(!xc->rvat_chain_mem)
unsigned char *mc = malloc(xc->rvat_chain_table_lengths[facidx]);
unsigned long destlen = xc->rvat_chain_len;
unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx];
int rc;
int rc = Z_OK;
fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f);
rc = uncompress(mu, &destlen, mc, sourcelen);
switch(xc->rvat_packtype)
{
case '4': rc = (destlen == (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen)) ? Z_OK : Z_DATA_ERROR;
break;
case 'F': fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */
break;
default: rc = uncompress(mu, &destlen, mc, sourcelen);
break;
}
free(mc);
if(rc != Z_OK)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2012 Tony Bybell.
* Copyright (c) 2003-2016 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -1029,12 +1029,12 @@ for(i=len;i>0;i--)
if(!i)
{
sprintf(tname, "%s_%03d.lxt", lt->lxtname, ++lt->break_number);
sprintf(tname, "%s_%03u.lxt", lt->lxtname, ++lt->break_number);
}
else
{
memcpy(tname, lt->lxtname, i);
sprintf(tname+i, "_%03d.lxt", ++lt->break_number);
sprintf(tname+i, "_%03u.lxt", ++lt->break_number);
}
f2 = fopen(tname, "wb");

687
vpi/lz4.c

File diff suppressed because it is too large Load Diff

237
vpi/lz4.h
View File

@ -1,7 +1,8 @@
/*
LZ4 - Fast LZ compression algorithm
Header File
Copyright (C) 2011-2014, Yann Collet.
Copyright (C) 2011-2015, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
@ -28,7 +29,7 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : http://code.google.com/p/lz4/
- LZ4 source repository : https://github.com/Cyan4973/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#pragma once
@ -38,22 +39,22 @@ extern "C" {
#endif
/*
* lz4.h provides raw compression format functions, for optimal performance and integration into programs.
* If you need to generate data using an inter-operable format (respecting the framing specification),
* please use lz4frame.h instead.
* lz4.h provides block compression functions, and gives full buffer control to programmer.
* If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
* and can let the library handle its own memory, please use lz4frame.h instead.
*/
/**************************************
Version
* Version
**************************************/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 5 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
int LZ4_versionNumber (void);
/**************************************
Tuning parameter
* Tuning parameter
**************************************/
/*
* LZ4_MEMORY_USAGE :
@ -66,77 +67,90 @@ int LZ4_versionNumber (void);
/**************************************
Simple Functions
* Simple Functions
**************************************/
int LZ4_compress (const char* source, char* dest, int sourceSize);
int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
/*
LZ4_compress() :
Compresses 'sourceSize' bytes from 'source' into 'dest'.
Destination buffer must be already allocated,
and must be sized to handle worst cases situations (input data not compressible)
Worst case size evaluation is provided by function LZ4_compressBound()
inputSize : Max supported value is LZ4_MAX_INPUT_SIZE
return : the number of bytes written in buffer dest
or 0 if the compression fails
LZ4_compress_default() :
Compresses 'sourceSize' bytes from buffer 'source'
into already allocated 'dest' buffer of size 'maxDestSize'.
Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
It also runs faster, so it's a recommended setting.
If the function cannot compress 'source' into a more limited 'dest' budget,
compression stops *immediately*, and the function result is zero.
As a consequence, 'dest' content is not valid.
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
or 0 if compression fails
LZ4_decompress_safe() :
compressedSize : is obviously the source size
maxDecompressedSize : is the size of the destination buffer, which must be already allocated.
return : the number of bytes decompressed into the destination buffer (necessarily <= maxDecompressedSize)
If the destination buffer is not large enough, decoding will stop and output an error code (<0).
compressedSize : is the precise full size of the compressed block.
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
If destination buffer is not large enough, decoding will stop and output an error code (<0).
If the source stream is detected malformed, the function will stop decoding and return a negative result.
This function is protected against buffer overflow exploits,
and never writes outside of output buffer, nor reads outside of input buffer.
It is also protected against malicious data packets.
This function is protected against buffer overflow exploits, including malicious data packets.
It never writes outside output buffer, nor reads outside input buffer.
*/
/**************************************
Advanced Functions
* Advanced Functions
**************************************/
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
#define LZ4_COMPRESSBOUND(isize) ((unsigned int)(isize) > (unsigned int)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
/*
LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (output buffer size).
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
isize : is the input size. Max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
*/
int LZ4_compressBound(int isize);
int LZ4_compressBound(int inputSize);
/*
LZ4_compress_fast() :
Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LZ4_compress_default()
Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
*/
int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
/*
LZ4_compress_limitedOutput() :
Compress 'sourceSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'.
If it cannot achieve it, compression will stop, and result of the function will be zero.
This saves time and memory on detecting non-compressible (or barely compressible) data.
This function never writes outside of provided output buffer.
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
maxOutputSize : is the size of the destination buffer (which must be already allocated)
return : the number of bytes written in buffer 'dest'
or 0 if compression fails
*/
int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
/*
LZ4_compress_withState() :
Same compression functions, but using an externally allocated memory space to store compression state.
LZ4_compress_fast_extState() :
Same compression function, just using an externally allocated memory space to store compression state.
Use LZ4_sizeofState() to know how much memory must be allocated,
and then, provide it as 'void* state' to compression functions.
and allocate it on 8-bytes boundaries (using malloc() typically).
Then, provide it as 'void* state' to compression function.
*/
int LZ4_sizeofState(void);
int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
/*
LZ4_compress_destSize() :
Reverse the logic, by compressing as much data as possible from 'source' buffer
into already allocated buffer 'dest' of size 'targetDestSize'.
This function either compresses the entire 'source' content into 'dest' if it's large enough,
or fill 'dest' buffer completely with as much data as possible from 'source'.
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
New value is necessarily <= old value.
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
or 0 if compression fails
*/
int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
/*
@ -152,7 +166,6 @@ LZ4_decompress_fast() :
*/
int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
/*
LZ4_decompress_safe_partial() :
This function decompress a compressed block of size 'compressedSize' at position 'source'
@ -169,9 +182,8 @@ int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedS
/***********************************************
Streaming Compression Functions
* Streaming Compression Functions
***********************************************/
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
/*
@ -187,7 +199,7 @@ typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
* LZ4_resetStream
* Use this function to init an allocated LZ4_stream_t structure
*/
void LZ4_resetStream (LZ4_stream_t* LZ4_streamPtr);
void LZ4_resetStream (LZ4_stream_t* streamPtr);
/*
* LZ4_createStream will allocate and initialize an LZ4_stream_t structure
@ -196,7 +208,7 @@ void LZ4_resetStream (LZ4_stream_t* LZ4_streamPtr);
* They are more future proof, in case of a change of LZ4_stream_t size.
*/
LZ4_stream_t* LZ4_createStream(void);
int LZ4_freeStream (LZ4_stream_t* LZ4_streamPtr);
int LZ4_freeStream (LZ4_stream_t* streamPtr);
/*
* LZ4_loadDict
@ -205,36 +217,31 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_streamPtr);
* Loading a size of 0 is allowed.
* Return : dictionary size, in bytes (necessarily <= 64 KB)
*/
int LZ4_loadDict (LZ4_stream_t* LZ4_streamPtr, const char* dictionary, int dictSize);
int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*
* LZ4_compress_continue
* Compress data block 'source', using blocks compressed before as dictionary to improve compression ratio
* Previous data blocks are assumed to still be present at their previous location.
* LZ4_compress_fast_continue
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
* Important : Previous data blocks are assumed to still be present and unmodified !
* 'dst' buffer must be already allocated.
* If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
*/
int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
/*
* LZ4_compress_limitedOutput_continue
* Same as before, but also specify a maximum target compressed size (maxOutputSize)
* If objective cannot be met, compression exits, and returns a zero.
*/
int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
/*
* LZ4_saveDict
* If previously compressed data block is not guaranteed to remain available at its memory location
* save it into a safer place (char* safeBuffer)
* Note : you don't need to call LZ4_loadDict() afterwards,
* dictionary is immediately usable, you can therefore call again LZ4_compress_continue()
* Return : dictionary size in bytes, or 0 if error
* Note : any dictSize > 64 KB will be interpreted as 64KB.
* dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
*/
int LZ4_saveDict (LZ4_stream_t* LZ4_streamPtr, char* safeBuffer, int dictSize);
int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
/************************************************
Streaming Decompression Functions
* Streaming Decompression Functions
************************************************/
#define LZ4_STREAMDECODESIZE_U64 4
@ -265,8 +272,18 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti
*_continue() :
These decoding functions allow decompression of multiple blocks in "streaming" mode.
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
If this condition is not possible, save the relevant part of decoded data into a safe buffer,
and indicate where is its new address using LZ4_setStreamDecode()
In the case of a ring buffers, decoding buffer must be either :
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
In which case, encoding and decoding buffers do not need to be synchronized,
and encoding ring buffer can have any size, including small ones ( < 64 KB).
- _At least_ 64 KB + 8 bytes + maxBlockSize.
In which case, encoding and decoding buffers do not need to be synchronized,
and encoding ring buffer can have any size, including larger than decoding buffer.
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
and indicate where it is saved using LZ4_setStreamDecode()
*/
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
@ -276,8 +293,8 @@ int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
Advanced decoding functions :
*_usingDict() :
These decoding functions work the same as
a combination of LZ4_setDictDecode() followed by LZ4_decompress_x_continue()
They are stand-alone and don't use nor update an LZ4_streamDecode_t structure.
a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
*/
int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
@ -285,29 +302,57 @@ int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalS
/**************************************
Obsolete Functions
* Obsolete Functions
**************************************/
/*
Obsolete decompression functions
These function names are deprecated and should no longer be used.
They are only provided here for compatibility with older user programs.
- LZ4_uncompress is the same as LZ4_decompress_fast
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
These function prototypes are now disabled; uncomment them if you really need them.
It is highly recommended to stop using these functions and migrate to newer ones */
/* Deprecate Warnings */
/* Should these warnings messages be a problem,
it is generally possible to disable them,
with -Wno-deprecated-declarations for gcc
or _CRT_SECURE_NO_WARNINGS in Visual for example.
You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
# define LZ4_DEPRECATE_WARNING_DEFBLOCK
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif (LZ4_GCC_VERSION >= 301)
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
# elif defined(_MSC_VER)
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
# else
# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
# define LZ4_DEPRECATED(message)
# endif
#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
/* Obsolete compression functions */
/* These functions are planned to start generate warnings by r131 approximately */
int LZ4_compress (const char* source, char* dest, int sourceSize);
int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/* Obsolete decompression functions */
/* These function names are completely deprecated and must no longer be used.
They are only provided here for compatibility with older programs.
- LZ4_uncompress is the same as LZ4_decompress_fast
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
These function prototypes are now disabled; uncomment them only if you really need them.
It is highly recommended to stop using these prototypes and migrate to maintained ones */
/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
/* Obsolete streaming functions; use new streaming interface whenever possible */
void* LZ4_create (const char* inputBuffer);
int LZ4_sizeofStreamState(void);
int LZ4_resetStreamState(void* state, const char* inputBuffer);
char* LZ4_slideInputBuffer (void* state);
LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer);
LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state);
/* Obsolete streaming decoding functions */
int LZ4_decompress_safe_withPrefix64k (const char* source, char* dest, int compressedSize, int maxOutputSize);
int LZ4_decompress_fast_withPrefix64k (const char* source, char* dest, int originalSize);
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
#if defined (__cplusplus)

View File

@ -74,7 +74,7 @@ static void my_mcd_rawwrite(PLI_UINT32 mcd, const char*buf, size_t count)
if (fp) {
while (count > 0) {
size_t rc = fwrite(buf, 1, count, fp);
if (rc <= 0) break;
if (rc == 0) break;
count -= rc;
buf += rc;
}
@ -1971,12 +1971,7 @@ static PLI_INT32 sys_printtimescale_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
item = vpi_scan(argv);
vpi_free_object(argv);
}
if (vpi_get(vpiType, item) != vpiModule) {
scope = vpi_handle(vpiModule, item);
} else {
scope = item;
}
scope = sys_func_module(item);
vpi_printf("Time scale of (%s) is ", vpi_get_str(vpiFullName, item));
vpi_printf("%s / ", pts_convert(vpi_get(vpiTimeUnit, scope)));

View File

@ -60,7 +60,7 @@ static PLI_INT32 missing_optional_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpi_printf("SORRY: %s:%d: %s() is not available in Icarus verilog.\n",
vpi_printf("SORRY: %s:%d: %s() is not available in Icarus Verilog.\n",
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
name);
vpi_control(vpiFinish, 1);

Some files were not shown because too many files have changed in this diff Show More