Compare commits

...
880 Commits
Author SHA1 Message Date
Stephen Williams 3c2fb6a601 Fix dynamic array assignment to make a copy of the rvalue.
IEEE Std 1800-2017 Section 7.6 Array assignments

Assignment of a dynamic array creates a duplicate of the source,
so that assignments to the copy don't impact the original. Handle
all sorts of dynamic array base types.
2020-11-26 12:52:06 -08:00
Stephen Williams 7277f4e807 Merge pull request #394 from steveicarus/super-new-handling
Fixes for issues #387 and #390
2020-11-22 16:48:45 -08:00
Stephen Williams 919fd22a79 Handle the special case that constructor only chains.
Fix the case that a constructure is only a chaining constructor,
with no other content.
2020-11-22 16:13:01 -08:00
Stephen Williams 156644d91e Detect and complain about some constructor chain errors
This.new is not allowed.

super.new beyond the first statement is not allowed.

And while I'm at it, clean up the use of "@" and "#" in
the code as tokens for this and super.
2020-11-22 15:31:40 -08:00
Cary R 292d174cad Add support for an empty ';' in the description text 2020-11-20 21:42:39 -08:00
Cary R b14a623eef Update module items to include just a ';' 2020-11-20 20:48:55 -08:00
Martin Whitaker 1b3f0dd689 Add enumeration assignment compatibility check for continuous assignments. 2020-11-20 17:34:55 +00:00
Martin Whitaker 0fada92389 Fix expression type for packed struct member access (GitHub issue #386)
A NetESelect is used for accessing packed struct members and also for
accessing dynamic array elements. In these cases the expr_type() and
enumeration() methods should reflect the member/element type.
2020-11-20 16:50:11 +00:00
Cary R ad862020bb Move GNU lesser to tgt-vvp since that is the only place where LGPL code is located 2020-11-14 19:03:27 -08:00
Cary R d209e7533a Update some queue code since deques support random access 2020-11-14 17:09:51 -08:00
Martin Whitaker d6e01d0c55 Fix assertion failure when no value supplied with -P option (GitHub issue #377) 2020-10-24 22:48:00 +01:00
Martin Whitaker 359b2b65c2 Support escaped identifiers as macro names. 2020-10-09 11:38:16 +01:00
Martin Whitaker 6566072741 Fix GitHub issue #374 - ordering of `` and embedded macro expansion.
The IEEE standard does not clearly state whether the `` directive is applied
before or after embedded macros are expanded. Other simulators vary in their
behaviour. For maximum compatibility, this fix adopts the behaviour found in
Verilator, where `prefix``suffix expands to <prefix>suffix if prefix is a
defined macro, otherwise it expands to <prefixsuffix> (where <...> is the
expanded macro text). Other simulators show this behaviour in at least some
circumstances.
2020-10-09 08:09:04 +01:00
Martin Whitaker 8f8737198c Bump version to 12.0 in vvp/examples/*.vvp. 2020-10-03 10:57:25 +01:00
Martin Whitaker 4e79c1c861 Bump major version to 12. 2020-10-03 10:13:45 +01:00
Martin Whitaker 6880b39770 Refactor task declaration parsing and fix warning for empty port list.
1364-2005 and later allow a task declaration with an empty port list.
2020-10-03 09:30:51 +01:00
Martin Whitaker c4883da334 Fix width of localparam created from genvar when using -gstrict-expr-width. 2020-10-01 11:33:24 +01:00
Stephen Williams fec003bd36 vvp: Remove a dead rule for the .port_info statement.
We left an old rule that matched a port_info statement without a
trailing semicolon. Remove that rule ahead of the release.
2020-09-22 14:18:24 -07:00
Stephen Williams a831108c96 Merge pull request #371 from larsclausen/enum_implicit_reg
parse.y: Mark enum output ports always as IMPLICT_REG
2020-09-21 08:10:18 -07:00
Lars-Peter Clausen 1064543d27 parse.y: Mark enum output ports always as IMPLICT_REG
Unless explicitly declared a wire an enum output port is of variable type
and should be marked as IMPLICT_REG.

Currently this is only done when the base type of the enum is `logic`. But
it should be done for all enums regardless of their base type.

Without this change for example the following snippet

```
  typedef enum {
      A,
      B
  } E;

  module M (
      input E ei,
      output E eo
  );

      always_comb eo = ei;

  endmodule
```

fails with the following error message

  test_enum.sv:11: error: eo is not a valid l-value in M.
  test_enum.sv:8:       : eo is declared here as wire.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2020-09-20 19:14:28 +02:00
Stephen Williams b8c5fd6314 Merge pull request #370 from larsclausen/remove-empty-file
tgt-vvp: Remove (almost) empty file vector.c
2020-09-19 08:19:38 -07:00
Lars-Peter Clausen 1ec5a441f3 tgt-vvp: Remove (almost) empty file vector.c
Since commit 62fce50f8c ("Remove dead code for allocate_vec handling.")
vector.c only contains the license header and some include directives
but no actual code.

Remove the file.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2020-09-19 12:39:04 +02:00
Martin Whitaker 10685ed89d Remove redundant test for whether a vvp thread is joinable.
Since commit 15cda5fe, forked threads are never embedded in the parent
thread, so we no longer need the special case code that ensured that
task/function calls were reaped before a join.

This also fixes GitHub issue #368.
2020-09-11 21:18:54 +01:00
Martin Whitaker d8556e4c86 Fix handling of the SV `` delimiter when combined with macro usage.
Given a macro definition like this:

  `define name  `macro``text

the preprocessor should expand `macro, not `macrotext, when it expands
`name. This also ensures that

  `define name(p,s)     p``_``s
  `define PREFIX        my_prefix
  `define SUFFIX        my_suffix

  `name(`PREFIX, `SUFFIX)

expands to

  my_prefix_my_suffix

as the user would expect.
2020-08-24 20:29:15 +01:00
Martin Whitaker dc2aa6efa0 Fix handling of SV " and \`" escape sequences in macros (GitHub issue #366).
`" overrides the normal behaviour of disabling macro expansion within
a string.
2020-08-24 14:48:40 +01:00
Martin Whitaker bd0a1c75ed Add support for string values in event expressions (GitHub issue #365). 2020-08-23 11:06:15 +01:00
Martin Whitaker a69de8b94a Rework last value storage in vvp_fun_anyedge functors.
This prepares the way to support strings and object handle values.
2020-08-23 11:04:44 +01:00
Cary R 0a69303164 Refactor array store for string/real and skip saving when given an undefined index 2020-08-16 19:49:34 -07:00
Cary R 505ee1a96c Refactor store for real/string 2020-08-16 19:23:41 -07:00
Cary R aa013a0ef0 Refactor store prop 2020-08-16 19:08:34 -07:00
Cary R 4bf502741d Refactor store DAR 2020-08-16 18:37:28 -07:00
Cary R 8e3afebb7b Refactor set DAR object 2020-08-16 18:00:41 -07:00
Martin Whitaker bd0133b386 Fix GitHub issue #361 - explicit cast check on function return value.
A function call returning an enumeration value can be assigned to an
enumeration variable without an explict cast.
2020-08-14 12:30:05 +01:00
Cary R 43441066eb More refactoring in vthread 2020-08-13 23:28:18 -07:00
Cary R f3e4287d0a Refactor prop routines to use common template 2020-08-13 22:30:21 -07:00
Cary R 52c3b901e0 When available print file/line information with thread error messages 2020-08-13 22:05:31 -07:00
Cary R 294005c5b2 Refactor load DAR routines 2020-08-13 21:48:52 -07:00
Cary R 3993241d04 Refactor more of the queue code 2020-08-11 19:46:36 -07:00
Cary R f6d8cfc80c Add file/line to Sorry queue message 2020-08-11 19:46:22 -07:00
Cary R 112ebb48d8 Add file/line information to procedural warnings and darray fixes
When -pfileline=1 is used the queue procedural warnings have file
and line information added to the messages. Also switch the trace
debugging to be off by default.

Also, Add some preliminary missing darray functionality.
2020-08-10 22:01:55 -07:00
Cary R 61884e559c Add support for assigning a queue using a normal concatenation 2020-08-09 21:10:30 -07:00
Cary R 1a0c06566d Update vvp code generation to properly emit file/line for void functions 2020-08-09 20:11:46 -07:00
Cary R e77d22e135 Add file and line information to warning message 2020-08-07 01:02:00 -07:00
Cary R bff115b9f7 Add initial support for assigning between queues and darrays 2020-08-07 00:23:43 -07:00
Martin Whitaker 3a70a84e68 Don't use libhistory if libreadline includes the history functions. 2020-08-06 23:58:45 +01:00
Martin Whitaker a5b3c0483a Set default nm tool if $NM is not defined. 2020-08-06 23:49:45 +01:00
Martin Whitaker 9d15b771b1 Fix GitHub issue #356 - use pull strength for tri0/tri1 tie-offs.
When connecting module inout ports, an island is created. If there
is no other driver on one of the island ports, a tie-off is added.
In the case of a tri0 or tri1 net, this must have the correct (pull)
drive strength.
2020-08-06 14:20:16 +01:00
Cary R eb8f457803 Fix a spacing issue in output 2020-08-05 23:19:39 -07:00
Cary R 761dc35e0b A queue or darray can be assign from a queue or darray. 2020-08-05 23:19:32 -07:00
Martin Whitaker 2f317065aa Fix GitHub issue #352 - typo in README.txt (%time -> $time). 2020-08-05 11:33:34 +01:00
Cary R a0ef23605a Update some functions to use inline 2020-08-04 22:11:36 -07:00
Cary R 538a03ba8e Add templates for queue push 2020-08-04 22:07:02 -07:00
Cary R f638e9dd5d Add templates for queue pop 2020-08-04 21:48:47 -07:00
Cary R 84eb70660d Switch qinsert to use a template 2020-08-04 21:14:17 -07:00
Cary R d1d6c0f5d2 Start refactoring the queue routines 2020-08-03 23:45:56 -07:00
Cary R 199ed39abe Report when the array pattern is larger than the maximum queue size 2020-08-02 23:40:35 -07:00
Cary R 83db691586 Merge branch 'master' of github.com:steveicarus/iverilog 2020-07-30 19:54:59 -07:00
Cary R 2530041a38 Add support for assign array patterns to a queue 2020-07-30 19:52:38 -07:00
Martin Whitaker 07bbf4ce0f CI: run on both Ubuntu 16.04 and 18.04. 2020-07-30 16:40:40 +01:00
Martin Whitaker 8e4cc8e887 Use GNU make pattern rules to handle multiple file output from bison.
With a pattern rule, the recipe will only be executed once, even when
the rule has multiple targets. Using this to handle the output from
bison is included as an example in the GNU make manual.

This fixes the makefiles so that bison-generated header files will be
regenerated if they are deleted.
2020-07-30 16:27:01 +01:00
martinwhitaker a4c9919e3a Merge pull request #349 from hzeller/fix-bison-include
Bison includes its generated header in *.cc. Generate with correct name.
2020-07-30 15:53:21 +01:00
martinwhitaker 929ffed6ab Merge pull request #347 from vowstar/fix-nm
aclocal.m4: fix issue in cross-compiling
2020-07-30 09:38:22 +01:00
Cary R a2ba8a16b1 Add support for inserting into a queue 2020-07-29 23:00:19 -07:00
Cary R bed4758b0f A value of all X or Z can be an immediate number 2020-07-29 23:00:09 -07:00
Henner Zeller 5b699c1be7 Bison includes its generated header in *.cc. Generate with correct name.
The current bison (3.7) generates a *.cc file that includes the header
it generated. For parse.cc this would be parse.hh. Right now, we rename
this header to have a common name used in other files, but this results
in a compile error for the parse.cc file:

parse.cc:462:10: fatal error: parse.hh: No such file or directory
  462 | #include "parse.hh"
      |          ^~~~~~~~~~

Fix this by telling bison to output the header file to the correct
filename in the first place so that we don't have to rename it.
(using the --defines instead of -d option).

This looks like a bison specific option not available in Posix yacc;
but looks like we're requiring bison anyway.

Signed-off-by: Henner Zeller <[email protected]>
2020-07-29 15:29:08 -07:00
Huang Rui d827f674cc aclocal.m4: fix the comment contradicts the previous line
Changed to "the nm(1) utility or an equivalent is available,
and its name is defined by the $NM variable.

Signed-off-by: Huang Rui <[email protected]>
2020-07-28 21:15:49 +08:00
Martin Whitaker e69549034d Fix potential buffer overflows (GitHub issue #346). 2020-07-28 13:17:57 +01:00
Cary R fdd902e446 Remove some clang warnings 2020-07-27 21:56:29 -07:00
Cary R 14ade1a9f4 Pass the max size when storing to a queue 2020-07-27 21:24:22 -07:00
Cary R cf8222fcfe A queue does not have dimensions so just assume the base is 0 for an L-val 2020-07-26 14:02:37 -07:00
Cary R c969c324ed Add initial support for using a queue element as an L-value 2020-07-26 14:02:29 -07:00
Cary R 520d5b392a Add support for pop_back/front without () 2020-07-25 22:16:54 -07:00
Cary R 6ecd43d947 Add/update queue compile time error messages 2020-07-25 16:33:30 -07:00
Cary R d1b75d9407 Update some queue warning messages and optimize element erase 2020-07-25 15:32:28 -07:00
Cary R 1a4345cce9 Add the ability to delete an element of a queue 2020-07-25 00:49:42 -07:00
Huang Rui f3396d502d aclocal.m4: fix issue in cross-compiling
The aclocal.m4 called nm directly.
It can cause issue in cross-compiling and because is not possible
use a different NM implementation (like llvm-nm).
The compile error log:
https://bugs.gentoo.org/attachment.cgi?id=648556

Closes: https://bugs.gentoo.org/731906
Signed-off-by: Huang Rui <[email protected]>
2020-07-25 12:50:49 +08:00
Cary R e94291c88f Handle negative and undefined queue addresses correctly 2020-07-23 22:49:33 -07:00
Cary R f0f045f1f9 Add warning messages when popping from an empty queue 2020-07-23 22:04:27 -07:00
Cary R 1b52a4a578 Don't fail when pushing/poping from an empty queue 2020-07-23 19:12:35 -07:00
Cary R 5f8aa24093 Remove duplicate FILE_NAME() call 2020-07-23 18:49:54 -07:00
Cary R e1870acfac Return the correct value when a queue or darray references an undefined element 2020-07-22 21:47:37 -07:00
Cary R 5ebd08c7f8 The queue needs to be implemented using a deque 2020-07-21 20:02:11 -07:00
Cary R 2999f351d2 Update queue error/warning messages 2020-07-20 20:34:17 -07:00
Cary R 1b7cd5c237 Add initial support for real queues 2020-07-19 21:34:56 -07:00
Cary R bf6c4329b9 Add push front for string queues and improve some warning messages 2020-07-19 19:18:59 -07:00
Cary R 83c86735bb Update vlog95 to not crash with queue maximum index 2020-07-17 02:19:36 -07:00
Cary R 6ff07c1074 Enable support for providing a queue maximum index 2020-07-17 01:32:53 -07:00
martinwhitaker 2c9cce2303 Merge pull request #342 from purdeaandrei/f_add_assert_before_dereferencing_pointer
Add assert to protect against potentially dereferencing null pointer.
2020-07-16 10:48:11 +01:00
Martin Whitaker 4cc929c71a CI: ignore line-endings when checking results on Windows. 2020-07-11 09:26:23 +01:00
Purdea Andrei 8889886efd Add assert to protect against potentially dereferencing null pointer.
Assert is apropriate, since it's not expected that the returned value is NULL in this case.
2020-07-11 03:54:29 +03:00
martinwhitaker 3d305b33df Merge pull request #339 from dredozubov/update-osx-readme
Update MacOS instructions
2020-07-11 00:10:42 +01:00
Martin Whitaker b36bca1f1b Add support for return statements in void functions. 2020-07-10 23:34:11 +01:00
martinwhitaker 07256646a5 Merge pull request #334 from purdeaandrei/f_fix_portless_declarationless_functions
Fix port-list-less declaration-less functions for SystemVerilog
2020-07-10 22:47:53 +01:00
Martin Whitaker 4e7dfac6c4 CI: automatically update expected results for msys2. 2020-07-10 22:05:07 +01:00
Cary R dd80607ceb Add CA version of the <-> operator 2020-07-09 01:45:43 -07:00
Cary R c003bcc59a Add support for <-> in constant and procedural contexts 2020-07-07 23:29:19 -07:00
Cary R 018a649f59 A time variable defaults to unsigned, but can be declared as signed 2020-07-07 20:33:03 -07:00
Cary R b8ae9a85fa Update size check in $fread() 2020-07-03 23:15:39 -07:00
Denis Redozubov e5ca8c4fa4 Update MacOS instructions
* Update README to reflect that bison fails to generate correct code
  on newer MacOS as well and bison 3.6+ works fine as well
* macos.txt removed because it contains outdated instructions
2020-06-30 22:09:54 +03:00
Cary R 6d8dea8d05 Update fstapi.c to latest from GTKWave 2020-06-28 20:12:14 -07:00
Martin Whitaker 085f466377 Fix GitHub issue #337 - incorrect uninitialised function return value. 2020-06-25 00:31:43 +01:00
Purdea Andrei a4d91c9023 Fix port-list-less declaration-less functions for SystemVerilog
For functions without a port list in parantheses, declarations are optional in SystemVerilog.
This is true even in IEEE1800-2005, but not in IEEE1364-2005
2020-06-22 23:51:10 +03:00
martinwhitaker ed7734c795 Merge pull request #328 from purdeaandrei/f_allow_libext_and_y_commands_to_be_given_in_any_order
Allow +libext+ and -y commands to be given in any order (and small fix in manpage)
2020-06-03 14:57:09 +01:00
Purdea Andrei c217d7d759 fix compilation issues on older gcc5 2020-06-03 15:58:27 +03:00
Purdea Andrei 859341273e Don't use C++11 feature std::tuple, instead use std::pair 2020-06-03 14:47:11 +03:00
martinwhitaker a849ca28ef Merge pull request #327 from purdeaandrei/f_fix_how_explicitly_unconnected_ports_are_handled_with_dotstar
Fix how explicitly unconnected ports are handled in the presence of .*
2020-06-03 11:42:29 +01:00
martinwhitaker 0b87ecb173 Merge pull request #325 from tpambor/fix-missing-include
Add missing include for malloc
2020-06-02 20:56:37 +01:00
Martin Whitaker 8e4593bf90 CI: really fix Windows build, check VVP results, run VPI tests. 2020-06-02 20:27:58 +01:00
Martin Whitaker 4466a19fb1 Attempt to fix Travis CI on Windows. 2020-06-01 13:18:00 +01:00
Cary R 0fca1bdab0 Add vpiIndex for array words 2020-05-31 14:27:19 -07:00
Cary R fb237fb006 Update the user visible copyright to be 2020 2020-05-31 13:41:38 -07:00
Cary R 89d3342804 Increase the thread flag count from 256 to 512 2020-05-31 12:39:54 -07:00
Cary R 1fefa8eb1b Add support for vpi_put_value for vpiBit 2020-05-31 10:49:54 -07:00
Cary R 7eb0efd424 Add basic support for vpiBit 2020-05-31 00:27:15 -07:00
Purdea Andrei 37da3c530c Allow +libext+ and -y .f command file options to be given in any order. 2020-05-19 22:49:35 +03:00
Purdea Andrei 13f6a916b3 man page: fix typo regarding +libext+ command 2020-05-19 22:49:35 +03:00
Cary R a1518b5761 Report any failures in $fclose() 2020-05-18 22:58:24 -07:00
Cary R 19d63f0c96 A VPI by index will only work for a reg or a net 2020-05-18 22:57:18 -07:00
Purdea Andrei 01ee6bd5b4 Fix how explicitly unconnected ports are handled in the presence of .*
See this PR: https://github.com/steveicarus/ivtest/pull/15
Which adds test implicit-port7
2020-05-18 22:49:05 +03:00
Cary R 38d16e5f2f Use a common routine to get and check the FD/MCD 2020-05-16 21:06:35 -07:00
Cary R 0a06ecb203 Update vpi_mcd_close() to return the correct value 2020-05-16 19:19:45 -07:00
Cary R fc7f0739d3 When a FD is passed to vpi_mcd_(v)print return EOF since this is an error 2020-05-16 19:19:30 -07:00
Cary R 9b9be11cf6 Factor out the common code for checking if a FD/MCD is valid 2020-05-16 18:04:09 -07:00
Tim Pambor 514ddade39 Add missing include for malloc() 2020-05-11 19:00:38 +02:00
Martin Whitaker cf44f05cd3 Fix GitHub issue #324 - replace __CYGWIN32__ with __CYGWIN__.
__CYGWIN32__ is not defined when building with the 64-bit Cygwin
toolchain. According to the Cygwin FAQ, __CYGWIN__ has been defined
since 1998, so this should still work for users on 32-bit systems.
2020-05-10 14:06:53 +01:00
Cary R cb3469cf51 Fix space issue 2020-05-09 23:08:43 -07:00
Cary R cf193b3055 Cleanup vpiClassTypespec when running valgrind 2020-05-09 23:04:37 -07:00
Martin Whitaker 40d2a49b90 Update vlog95 target to handle buffers/tran_vps used to prevent port collapsing. 2020-05-07 23:05:52 +01:00
Martin Whitaker e19109e58f Fix GitHub issue #316 - isolate modpath delays from multi-driven nets.
When module ports are collapsed, we can't tell which of the nexus drivers
are associated with a given module port and should be routed through an
associated modpath delay. Work round this by inserting a transparent
buffer or tran_vp if an output or inout port has a modpath delay. The
target code generator can elide this once it has handled the modpath
delays.
2020-05-07 22:51:38 +01:00
Cary R 58eb202376 Update find_scope and vpi_handle_by_name to work with escaped identifiers 2020-05-02 19:47:56 -07:00
Martin Whitaker 8da7a14800 Fix elaboration and evaluation of SV queue push arguments.
These are assignments to a queue element, so need to consider the
element base type when determining the expression width.
2020-05-01 15:30:44 +01:00
Martin Whitaker 7af04c62ee Fix GitHub issue #319 - export ivl_path_is_parallel for Windows DLLs. 2020-04-30 22:55:44 +01:00
Martin Whitaker 3f49dfcd97 Fix translation of module path connection type in vlog95 target.
The target API needed to be changed to pass the connection type
through to the target code generator.
2020-04-02 12:40:59 +01:00
Martin Whitaker a44ffe5746 Fix GitHub issue #315 - support modpath delays on multiply-driven nets. 2020-04-02 10:56:03 +01:00
Cary R f76e1c1ecb Update to the latest GTKWAve files 2020-03-30 15:49:28 -07:00
Stephen Williams 7bbafe6109 Merge pull request #66 from themperek/master
Add travis-ci integration (linux + windows)
2020-03-24 09:35:37 -07:00
Stephen Williams 462ee62f8b Merge pull request #300 from vowstar/fix-makefile
Fix iverilog files not update bug during overwrite installation
2020-02-29 09:38:42 -08:00
Martin Whitaker 875431a3ea Merge pull request #311 from nmoroze/master.
Replaces assertion in evaluate_index_prefix() with useful error message.
2020-02-18 19:53:22 +00:00
Noah Moroze d0fe513c7e Replace assertion in evaluate_index_prefix with useful error message. 2020-02-15 16:32:32 -05:00
Martin Whitaker 8b85064341 Fix GitHub issue 310 - improve port declaration error message. 2020-02-15 12:02:15 +00:00
Huang Rui 11001f58d5 Thoroughly fix parallel installation issues
In PR #300, @xdch47 pointed out a stable way to fix parallel
installation problems.

This fix applied the method, thanks!

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:42:04 +08:00
Huang Rui 969426a21e Fix install missing file bug in PR #300
When installing tgt-stub and tgt-vhdl, due to the wrong target
path, the install scripts can't find the file to be installed.

The missing file is: stub.conf, stub-s.conf, vhdl.conf, vhdl-s.conf
Changed to right path fixed this problem.

Thanks @minux help to fix.

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:39:30 +08:00
Huang Rui 357d9ae6f0 [20/20]Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui dd5a288567 [19/20]cadpli/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 9e8692fac5 [18/20]driver-vpi/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 0602ef46c6 [17/20]driver/Makefile.in:fix install timestamp check
Fix tgt-fpga/Makefile.in vvp/Makefile.in doc

Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 593d5b5c83 [16/20]ivlpp/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 80bcd36cb8 [15/20]libveriuser/Makefile.in:Remove useless $(INSTALL32)
fix install timestamp check and Remove useless $(INSTALL32)

Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 93d2aa03d6 [14/20]tgt-blif/Makefile.in:Remove useless $(INSTALL_DOC)
fix install timestamp check and Remove useless $(INSTALL_DOC)

Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui f517b5fc4e [13/20]tgt-fpga/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 5f0f186b51 [12/20]tgt-null/Makefile.in:Remove useless $(INSTALL_DOC)
fix install timestamp check and Remove useless $(INSTALL_DOC)

Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 1313722438 [11/20]tgt-pal/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui d7e1df5638 [10/20]tgt-pcb/Makefile.in:Remove useless $(INSTALL_DOC)
fix install timestamp check and Remove useless $(INSTALL_DOC)

Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui b5a44195ff [9/20]tgt-sizer/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui af152bec32 [8/20]tgt-stub/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 404e475022 [7/20]tgt-verilog/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 439d4405dd [6/20]tgt-vhdl/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui c1229b7565 [5/20]tgt-vlog95:Remove useless $(INSTALL_DOC)
fix install timestamp check and Remove useless $(INSTALL_DOC)

Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui bd130786ff [4/20]tgt-vvp/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 0100c0bc5c [3/20]vhdlpp/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 0c12a24cfd [2/20]vpi/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Huang Rui 081fe1c816 [1/20]vvp/Makefile.in:fix install timestamp check
Fix bug: https://bugs.gentoo.org/705412
Fix bug: https://github.com/gentoo/gentoo/pull/14096
Related: https://github.com/steveicarus/iverilog/pull/294

Signed-off-by: Huang Rui <[email protected]>
2020-02-12 22:08:40 +08:00
Martin Whitaker 387d18d222 Fix GitHub issue #306 - segfault when synthesising deassign statement.
Synthesis doesn't properly support any of the procedural continuous
assignment statements, so output a "sorry" message and abort synthesis.
2020-02-09 18:22:58 +00:00
Martin Whitaker fb29da0bd8 Fix for GitHub issue #309 - allow braced expressions as macro arguments.
As for parentheses, we need to ignore commas within a pair of braces
when parsing a macro argument, e.g. `MACRO({a,b}) has one argument.

This fix is a little crude in that it doesn't distinguish between
parentheses and braces, e.g. it will accept {a,b). But any errors
like that will be caught by the compiler proper.
2020-02-08 20:51:50 +00:00
Martin Whitaker 97edccceab Merge pull request #308 from blackgnezdo/blackgnezdo-master.
Fixes loop end condition in __vpiDecConst::vpi_get_value().
2020-02-08 19:29:49 +00:00
Greg Steuck 3ed7e7b295 Merge pull request #1 from blackgnezdo/blackgnezdo-patch-1
Fix bad bounds check in for loop
2020-02-05 08:06:44 -08:00
Greg Steuck 398d0cb82f Fix bad bounds check in for loop 2020-02-05 08:05:50 -08:00
Martin Whitaker b1114760fc Fix for compatibility with old C++ standard. 2020-02-02 09:25:05 +00:00
Martin Whitaker 33b822d997 Add support for local genvar declaration in generate loops.
As requested in GitHub issue #304.
2020-01-31 20:29:22 +00:00
Martin Whitaker 0023804777 Add support for increment/decrement operators in generate loop iteration.
As requested in GitHub issue #303.
2020-01-30 21:45:04 +00:00
Martin Whitaker 20d7309ec2 Merge pull request #302 from vowstar/vowstar-fix-gcc10.
Fixes build with -fno-common (default in GCC 10).
2020-01-30 18:34:21 +00:00
Huang Rui d49d26a5c5 Fix fails to build with -fno-common or gcc-10
See also: https://bugs.gentoo.org/706366

gcc-10 and above flipped a default from -fcommon to -fno-common:
https://gcc.gnu.org/PR85678

Usually all it takes is to add a few 'extern' declarations and
move definitions from header files to modules. I've port iverilog
to gcc-10 accroding to this guide:
https://wiki.gentoo.org/wiki/Gcc_10_porting_notes/fno_common

To fix this, I analyzed the code, and found ``pli_trace`` has been
defined at here:
https://github.com/steveicarus/iverilog/blob/v10_3/libveriuser/priv.c#L24

So I changed ``FILE* pli_trace;`` to ``extern FILE* pli_trace;``.

The var ``current_file`` only in ``cfparse_misc.h``, I changed it
from ``char *current_file;`` to ``extern char *current_file;`` and
declaring it in cflexor.lex

And then it works.

Signed-off-by: Huang Rui <[email protected]>
2020-01-29 00:08:59 +08:00
Stephen Williams 78f12dec1c Merge pull request #294 from minux/fix-make-j-install
Makefile.in: fix mkdir race during "make -j N install"
2020-01-06 12:30:33 -08:00
minux 7de00ee73a Makefile.in: fix mkdir race during "make -j N install" 2020-01-06 00:46:14 -05:00
Cary R 9c777c0420 Update to the latest fstapi files from GTKWave 2020-01-01 19:59:33 -08:00
Martin Whitaker b91d5d1a82 vvp: recognise signed logic types when parsing class properties. 2019-12-23 09:48:07 +00:00
Martin Whitaker 8dc395940d Fix issue #298: elaborate types in the scope where they were declared.
The compiler elaborates types on the fly as they are used. For user-
defined types (typedefs) we must do the elaboration in the scope where
the type was declared, not in the scope where it is used.
2019-12-22 17:29:23 +00:00
Martin Whitaker e8e2c35df0 Fix some errors in pform dumps. 2019-12-22 11:26:13 +00:00
Martin Whitaker 732a763188 Record typedef name in data_type_t struct.
This will be used to locate the scope where the type was declared.
2019-12-22 11:21:05 +00:00
Martin Whitaker 95147a2cc2 Record data type for all pform "wires" added the new way.
For unpacked arrays, record both the array type and the base type.
This will be needed to elaborate typedefs in the correct scope.
2019-12-22 11:03:50 +00:00
Martin Whitaker 465e0d2710 Allow classes to reference declarations in their enclosing scope(s).
The original implementation made each class a root scope. They should
be added to the scope hierarchy just like any other declaration.
2019-12-22 10:46:38 +00:00
Stephen Williams 7f95abc6ab Make a pass at implementing cbAtEndOfSimTime.
In Icarus Verilog, AtEndOfSimTime is practically the same as
cbReadWriteSync, since the latter is after non-blocking events
in Icarus Verilog.
2019-11-25 17:57:10 -08:00
Stephen Williams b25df08c99 Fix possible buffer overflow. 2019-11-21 18:48:57 -08:00
Stephen Williams f147cf9c61 Merge branch 'master' of github.com:steveicarus/iverilog 2019-11-21 18:35:55 -08:00
Stephen Williams 7cf8bb9875 Put some buffer overflow checks in.
Also, do a minor rework of StringHeap, and have it check its
assumptions more thoroughly.
2019-11-21 18:35:43 -08:00
Martin Whitaker 351a4e5f5e Improve vvp handling of excessively large shift distances. 2019-11-16 12:11:49 +00:00
Martin Whitaker 0a4cae2644 Fix vvp %shift instructions to treat right operand as unsigned.
1364-2005 section 5.1.12 says "The right operand is always treated
as an unsigned number".

This fixes GitHub issue #283.
2019-11-15 21:24:47 +00:00
Martin Whitaker 4a8f4d65d0 Fix spelling of pulsere_flag in vpi_user.h (from Pablo Bleyer). 2019-11-12 18:01:39 +00:00
Martin Whitaker 9f712429c8 Fix elaboration of void functions with no arguments (GitHub issue #281)
N.B. commit 82c8a495 incorrectly referenced issue #281. It should have
referenced issue #280.
2019-11-09 20:16:25 +00:00
Martin Whitaker a8f71d3c92 Additional cleanup of void function elaboration. 2019-11-09 20:15:31 +00:00
Martin Whitaker cab9526e6c vlog95 target: better solution for void functions with no arguments. 2019-11-09 20:14:57 +00:00
Martin Whitaker 39238fd1cd vlog95 target: ! operator does not require explicit type conversion. 2019-11-09 16:52:28 +00:00
Martin Whitaker 58aa08ab64 Handle SV void functions in vlog95 target. 2019-11-09 16:14:09 +00:00
Martin Whitaker 82c8a49573 Fix for issue #281 - the condition operator may return a valid enum type.
If the condition expression is 2-state, the result won't be blended, so
the result will be a valid enum value if both true and false expressions
return the same enum type.
2019-11-09 13:11:16 +00:00
Stephen Williams 7feb26ff6b Cleaner elaboration of void functions.
This fixed githun issue # 281.
2019-11-07 14:25:51 -08:00
Martin Whitaker a621fa48a6 Merge branch 'sft-rework' 2019-11-04 22:24:45 +00:00
Martin Whitaker d1d409fd88 Add version check for VPI routines callback. 2019-10-30 20:16:30 +00:00
Stephen Williams eeeb9ff099 Create files with default suffix when $dumpfile doesn't include a suffix. 2019-10-30 12:23:24 -07:00
Stephen Williams d718e7b468 Handle case that strings are arguments of functions/tasks.
When strings are arguments to functions/tasks, that doesn't suddenly
make them implicitly scalar. Strings are vectors and should be treated
that was, even if they are IMPLICIT_REG.
2019-10-29 22:58:48 -07:00
Martin Whitaker 16e8563c6e Fix for GitHub issue #277 - incorrect sensitivity calculation.
The fix for the compiler hang when calculating the sensitivity list
for an always_comb construct containing recursive function calls
could cause the compiler to ignore sequential calls to the same
function, and thus not add the arguments of those calls to the
sensitivity list.
2019-10-28 21:01:42 +00:00
Martin Whitaker 9fb952ed72 Use functions instead of macros for VPI routine redirection in Windows. 2019-10-27 09:06:55 +00:00
Martin Whitaker 3f1253039a Only use VPI routine jump table in Windows. 2019-10-25 10:07:57 +01:00
Martin Whitaker f0326bc9c2 Fix bug in converting directory separators for MinGW. 2019-10-23 13:05:48 +01:00
Martin Whitaker 160bfbf2fc Another makefile fix. 2019-10-23 13:03:32 +01:00
Martin Whitaker c98f8b17ba Support IVERILOG_VPI_MODULE_PATH in compiler driver.
Also make sure we convert '/' to '\' before doing any searches when
running in Windows.
2019-10-23 12:26:28 +01:00
Martin Whitaker a8fc131fc9 Use more explicit name for VPI routine jump table. 2019-10-23 11:41:14 +01:00
Martin Whitaker 1c26bcef2d Update vpi.txt. 2019-10-23 10:04:58 +01:00
Martin Whitaker 79d3a21b65 Minor code tidy-up. 2019-10-22 21:52:52 +01:00
Martin Whitaker f5cb5b2d90 Make sure vlog_startup_routines is exported from Windows VPI modules. 2019-10-22 20:33:52 +01:00
Martin Whitaker 5f0bbe4cdb One more makefile fix. 2019-10-22 20:30:09 +01:00
Martin Whitaker e6b0396e6f Makefile fixes. 2019-10-22 16:51:14 +01:00
Martin Whitaker a59b183bd1 Allow VPI modules to be loaded by multiple clients under Windows.
The old scheme of linking the VPI modules with the vvp exports meant they
did not work when loaded by the compiler. Instead, let each client create
a jump table for the VPI routines and pass that to each VPI module as it
is loaded.
2019-10-22 16:00:13 +01:00
Martin Whitaker e63135b412 Add -BM driver option to specify different base path for VPI modules.
This is needed for 'make check'.
2019-10-21 19:43:00 +01:00
Martin Whitaker 1c7f7aedbe Update man page. 2019-10-21 15:33:39 +01:00
Martin Whitaker 8d3e895593 Remove obsolete SFT files. 2019-10-21 13:53:53 +01:00
Martin Whitaker d1ae818a9f Remove static system function return descriptors.
The information is provided by the VPI modules.
2019-10-21 13:49:19 +01:00
Martin Whitaker a92a3074c0 Fix some missing/incorrect function return types in the system VPI modules. 2019-10-21 13:45:09 +01:00
Martin Whitaker 9f93989944 Extract system function return types from VPI modules, not SFT files. 2019-10-21 13:40:40 +01:00
Cary R df38460d26 Add the missing ivl_stmt_case_quality to ivl.def 2019-10-20 16:35:31 -07:00
Cary R 077d8d6c4d Update fstapi.c to latest from GTKWave 2019-10-20 16:35:24 -07:00
Martin Whitaker 1069a0ef02 Don't evaluate built-in system functions if they are overridden.
We don't support evaluating user-defined system functions at compile
time. If possible, defer evaluation until run time. If used in a
constant expression, output a "sorry" message.
2019-10-19 16:12:17 +01:00
Stephen Williams bf655003e8 Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-14 14:11:58 -07:00
Stephen Williams 0abf91ca4e Make vvp exit with FAILURE if $fatal is used to exit the simulation. 2019-10-14 14:11:50 -07:00
Martin Whitaker cb69a321ab Enable user-defined system functions to override built-in functions.
Fixes bug reported on iverilog-devel on 2019-10-13.
2019-10-14 21:41:58 +01:00
Martin Whitaker b82c185051 iverilog: Allow the user to specify the location of VPI modules.
Make it explicit in the manual that a path can be supplied with the -m
option, and when it is, search for a SFT file there, not in the base
directory.
2019-10-14 21:34:40 +01:00
Martin Whitaker 9f7dc732ab Add error recovery for invalid cast expressions. 2019-10-11 19:04:23 +01:00
Martin Whitaker d56e90c3f4 Fix casts to integer types.
Casting from signed to unsigned types and vice versa is legal in SV,
as is casting from a larger to a smaller size. Obey Verilog rules
for expression bit width and signedness.
2019-10-10 23:48:11 +01:00
Stephen Williams 1a40a6f902 Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-09 09:02:57 -07:00
Stephen Williams 55efaf8769 Merge pull request #269 from nbrereton/features/nsb/check-case-handled
Validate that value is  handled for case priority qualifier.
2019-10-09 09:00:31 -07:00
Stephen Williams a5ddf129a4 Merge pull request #273 from pkrc267/master
corrected a few typos for better readability
2019-10-09 08:44:45 -07:00
Prakhar Yadav f795e2be18 corrected a few typos for better readability 2019-10-09 21:02:08 +05:30
Stephen Williams 54d7d26933 Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-07 13:21:22 -07:00
Stephen Williams 0d29bd7c1c Add a little note about Xcode bison not cutting it. 2019-10-07 13:21:16 -07:00
Martin Whitaker f2ca63a5a1 Disable debug output when debug_elaborate is not set. 2019-10-06 18:10:58 +01:00
Martin Whitaker 68a6fa06a2 Improve old code for detecting missing explicit cast. 2019-10-06 18:03:37 +01:00
Martin Whitaker de54a58991 Fix issue #265 - emit a sensible error message when an explicit cast is needed. 2019-10-06 17:54:44 +01:00
Martin Whitaker 06a60cac01 For SystemVerilog, support localparam in module parameter port lists. 2019-10-06 08:44:51 +01:00
Nick Brereton 414fafda2b Check that value is handled for case priority and unique qualifiers. 2019-10-05 21:42:17 -04:00
nbrereton cce30e89bb Merge pull request #1 from steveicarus/master
update
2019-10-05 21:04:03 -04:00
Stephen Williams 763cc9c162 Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-05 16:23:16 -07:00
Stephen Williams befc91340c Parse and elaborate unique and priority case statements
The unique, unique0, and priority keywords can decorate case statements
to tell the run time (or synthesis) to do extra tests (or make extra
assumptions). These tests are not implemented in the vvp run time, but
now the decorations make it to the code generators.
2019-10-05 16:23:04 -07:00
Cary R b1699a2781 Fix two compiler warnings 2019-10-05 15:29:08 -07:00
Martin Whitaker 70da8db6b5 Fix assignment to scalar class property in tgt-vvp. 2019-10-05 20:12:52 +01:00
Martin Whitaker 862010ac19 SV does not require constant expression in variable initialisation. 2019-10-05 20:11:38 +01:00
Martin Whitaker c86dc285cc Fix for br1004 - fully support class construction in variable initialisation. 2019-10-05 20:10:11 +01:00
Martin Whitaker c9d849ed7b Fix style in iverilog man page. 2019-10-05 13:41:50 +01:00
Martin Whitaker 05641f386f Add -g option to only enable supported assertion statements. 2019-10-05 13:37:03 +01:00
Martin Whitaker 455702810e Add support for parsing (and ignoring) the other unsupported SV assertions. 2019-10-05 08:55:11 +01:00
Martin Whitaker 9167a236d8 Support import statements in packages and in the unit scope. 2019-10-03 19:44:44 +01:00
Stephen Williams 2ced291d33 Replace an assert with an internal error message. 2019-10-03 08:38:36 -07:00
Stephen Williams 4f48a7ed41 Fix assertion in error recovery. 2019-10-02 19:30:47 -07:00
Martin Whitaker ed75bc22ec Fix incorrect loop termination test when searching for typedefs. 2019-10-03 00:32:09 +01:00
Stephen Williams 1147881176 Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-02 09:34:36 -07:00
Stephen Williams 30fbc020e6 Don't allow nil bytes in string literals. 2019-10-02 09:34:18 -07:00
Cary R eeae2bfee9 Fix a syntax issue found while compiling with gcc 5.4 2019-10-01 18:58:28 -07:00
Martin Whitaker 7cead04e6a Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-02 00:16:18 +01:00
Stephen Williams 5651adf73a Handle breakage in nested module parsing. 2019-10-01 15:19:46 -07:00
Martin Whitaker 9bb2147fb5 Merge branch 'package-imports-rework' 2019-10-01 23:04:23 +01:00
Stephen Williams c62472f7ac Merge branch 'master' of github.com:steveicarus/iverilog 2019-10-01 09:29:30 -07:00
Stephen Williams da36cee8f0 Detect errors elaborating delay expressions. 2019-10-01 09:29:13 -07:00
Martin Whitaker 1cc872be8c Downward references may also activate potential imports. 2019-10-01 09:08:15 +01:00
Martin Whitaker 1fca7b41a4 Delay potential imports for task/function calls until end of scope.
A local task/function definition takes precedence, even if it appears
after the call.
2019-10-01 09:08:07 +01:00
Martin Whitaker 17f0dd7e6e Enable package imports in blocks. 2019-10-01 09:07:59 +01:00
Martin Whitaker c5c264400e Add support for package scope resolution for named events. 2019-10-01 09:07:54 +01:00
Martin Whitaker 12fe4f2bf3 Fix handling of wildcard-imported types.
Don't add them to the explicit imports until they are referenced legally.
Stop searching when a matching name is found, even if it isn't a type name.
2019-10-01 09:07:48 +01:00
Martin Whitaker b0142a6406 Add support for named events in packages. 2019-10-01 09:07:39 +01:00
Martin Whitaker 1e26a808ad Fix error message for failed elaboration of event expression. 2019-10-01 09:07:30 +01:00
Martin Whitaker f69eccf903 Merge remote-tracking branch 'origin/master' into package-imports-rework 2019-10-01 09:06:15 +01:00
Cary R ea4e41207c Update cppcheck standards that are checked 2019-09-30 22:14:15 -07:00
Stephen Williams 1d2259e0a7 Merge branch 'master' of github.com:steveicarus/iverilog 2019-09-30 13:14:58 -07:00
Stephen Williams 3cc6e74e38 Have $readmem() print a warning if there are too many digits in words.
If there are more digits than needed to fill a word, print a warning
message. The excess bits are thrown away, so there is no need for an
error.
2019-09-30 13:14:40 -07:00
Stephen Williams d232335d9d Merge pull request #267 from sielicki/master
replace deprecated yacc directives
2019-09-30 08:23:38 -07:00
Stephen Williams 80478db6cc Support typedefs in class definitions. 2019-09-30 08:07:56 -07:00
Cary R 6d71870853 Merge branch 'master' of github.com:steveicarus/iverilog 2019-09-29 20:20:23 -07:00
Cary R 5047aa2839 Add support for recursive function support for always_* sensitivity 2019-09-29 20:20:10 -07:00
Stephen Williams 185586e5ec Merge branch 'master' of github.com:steveicarus/iverilog 2019-09-29 18:37:39 -07:00
Stephen Williams 50d71c8512 Support for enumerations in classes. 2019-09-29 18:27:27 -07:00
Cary R e4ef928751 Fix some space issues 2019-09-29 17:11:19 -07:00
Cary R ba82ef463e Fix some always_* issues 2019-09-29 16:59:59 -07:00
Nicholas Sielicki 031caca8ca replace deprecated yacc directives
bison 3.4.2 complains when encountering '%pure-parser':
"warning: deprecated directive, use ‘%define api.pure’"

A quick google suggests this option has been around since at least
2012, maybe longer, so probably safe to replace.

Signed-off-by: Nicholas Sielicki <[email protected]>
2019-09-29 18:19:45 -05:00
Cary R 8a85d62ec7 Update to latest GTKWave files 2019-09-29 09:59:56 -07:00
Martin Whitaker e73da43cc1 Remove obsolete checks for name collisions during elaboration.
This is now handled by the parser.
2019-09-27 22:19:30 +01:00
Martin Whitaker 439688fa46 Add anonymous enums to the scope local symbols. 2019-09-27 22:19:30 +01:00
Martin Whitaker 2ae910750b Put generate case item block names in correct scope.
The compiler creates an artificial scope around the case items. We need
to add the block names to the real containing scope.
2019-09-27 22:19:30 +01:00
Martin Whitaker 03c4c63df1 Fix file/line reported for duplicate named blocks. 2019-09-27 22:19:30 +01:00
Martin Whitaker 628f5645bf Fix file/line reported for duplicate parameter declarations.
We need to retain the old parameter information until we have reported
the error.
2019-09-27 22:19:30 +01:00
Martin Whitaker d3bced57cc Correctly handle explicit and wildcard package imports.
Explicit imports should always conflict with local declarations using
the same name. Wildcard imports only conflict if they are referenced
before a local declaration with the same name.

This also unifies the detection of identifier conflicts.
2019-09-27 22:19:30 +01:00
Martin Whitaker b88d91c617 Create new base class for all named items that can be added to a scope.
Provide a helper function to identify the derived classes when reporting
errors.
2019-09-27 22:19:30 +01:00
Martin Whitaker 269ec2f042 Remove redundant checks for package imports during parsing.
The find_* and symbol_search functions now handle this.
2019-09-27 22:19:30 +01:00
Martin Whitaker 55219773fd Allow nested scopes to use their parent's imports. 2019-09-27 22:19:30 +01:00
Stephen Williams d7ee6bb6bb Support struct member part selects in l-values. 2019-09-27 13:51:51 -07:00
Stephen Williams 65aff65344 Better job choosing unique scope-local symbols during elaboration. 2019-09-25 12:18:41 -07:00
Stephen Williams ecd7b39244 Merge branch 'master' of github.com:steveicarus/iverilog 2019-09-24 15:05:51 -07:00
Stephen Williams 7b66de0711 Handle nested packed strucdts in r-values. 2019-09-24 15:05:39 -07:00
Martin Whitaker 714b211d9f Document the iverilog '-i' option in the man page. 2019-09-23 20:10:38 +01:00
Martin Whitaker abd63e80e1 With '-i', don't return an error when there are no top-level modules.
The '-i' option is there to allow the compiler to be used to check an
incomplete design for errors. With no top-level modules, nothing will
be elaborated, but at least will be checked for syntax errors.
2019-09-23 20:05:03 +01:00
Martin Whitaker 791c056b77 Document -gassertions/-gno-assertions in driver man page. 2019-09-20 21:30:43 +01:00
Martin Whitaker 823a508d6b Implement SV immediate assertions. 2019-09-20 21:30:43 +01:00
Stephen Williams 9e10645722 Merge branch 'master' of github.com:steveicarus/iverilog 2019-09-17 14:12:43 -07:00
Stephen Williams 2aa7700970 Add support for packed arrays in nested struct l-values. 2019-09-17 13:34:36 -07:00
Stephen Williams 1c281c2d77 Support nested struct l-values. 2019-09-16 13:50:17 -07:00
Martin Whitaker 41ac0b2621 Include wires in items imported by an "import ::*". 2019-09-16 20:42:32 +01:00
Martin Whitaker d6391490e3 Resize vector before assigning to a dynamic array word.
Failing to do this leads to an assertion failure in vvp.
2019-09-16 20:39:19 +01:00
Martin Whitaker 02ee1c65d0 Support dynamic array initialisation in variable declarations. 2019-09-16 20:35:27 +01:00
Stephen Williams b639c4c9aa Clean up some debug dump formatting. 2019-09-15 21:17:16 -07:00
Martin Whitaker 832adc5c74 Improve handling of invalid packed and unpacked dimensions.
As reported on iverilog-devel on 2018-10-12, a dimension size of zero
could case the compiler to go into an infinite loop. Further tests
showed that unsized or queue dimensions entered as packed dimensions
would cause the compiler to crash.
2019-09-14 09:10:52 +01:00
Martin Whitaker a6bcbc3d1d Remove obsolete private VPI functions. 2019-09-13 08:40:58 +01:00
Martin Whitaker a0ef6c4b62 Fix design dump to correctly report cast operations. 2019-09-11 22:14:03 +01:00
Martin Whitaker c066e2d15c Properly implement casts from strings and dynamic arrays to vectors.
As discussed on iverilog-devel (2018-03-09), the existing implementation
(using Icarus-specific vpi functions) only worked with assignments to
simple variables, and could not be easily modified to work more generally.
So use the new vvp instructions added in the previous two commits.
2019-09-11 22:08:46 +01:00
Martin Whitaker 1aa22735ce Add new %cast/vec2/dar and %cast/vec4/dar instructions to vvp. 2019-09-11 21:56:27 +01:00
Martin Whitaker 74ff44314e Add new %cast/vec4/str instruction to vvp. 2019-09-11 21:56:09 +01:00
Martin Whitaker 34bb98676a Fix assertion failure on illegal SV cast.
Bug reported on iverilog-devel on 2018-02027.
2019-09-07 14:35:19 +01:00
Martin Whitaker b43fcccc0f Add support for PATHPULSE, PATHPULSEPERCENT, and PERIOD in SDF parser.
As requested on iverilog-devel. These are all parsed then ignored for now.
2019-08-24 00:23:29 +01:00
Martin Whitaker 3bdb50da29 Schedule UDP initial 0/1 assignments to occur during time 0.
This allows any always processes that are sensitive to the UDP output
to start first. This fixes a time 0 race that was found in a Lattice
Semiconductor simulation library (reported on iverilog-devel).

If the initial value is 'x', propagate the value to the UDP output
before the start of simulation, to avoid unwanted update events on
the z -> x transition on downstream nets.
2019-08-09 21:00:10 +01:00
Martin Whitaker a8318db21c Fix assertion failure when top level module has array ports.
Reported by Kustaa Nyholm on iverilog-devel, 2017-10-17.
2019-08-03 18:52:49 +01:00
Martin Whitaker 7fa781d5f3 Re-enable disabled compiler warnings for Windows builds. 2019-08-03 12:41:38 +01:00
Martin Whitaker 326945329e Add note that bison 2.3 is known to generate bad code (br1028). 2019-08-02 15:45:20 +01:00
Martin Whitaker e97883b1db Fix for br1015 : assertion failure when task/function port is an array.
This is an error for Verilog and not yet supported for SystemVerilog.
2019-08-02 15:34:31 +01:00
Martin Whitaker 866cc46915 Fix for GitHub issue #256 - don't use V as Makefile variable name.
Some build systems override V on the make command line, wrongly assuming
it is the automake verbose option.
2019-08-02 10:27:40 +01:00
Martin Whitaker b7769dd059 Merge branch 'fix-cfparse-include-order' of https://github.com/StefanBruens/iverilog 2019-08-01 19:13:31 +01:00
Martin Whitaker 10168d542c Change minimum gperf version to 3.0.
vhdlpp uses the --ignore-case option, which isn't supported in 2.7.
2019-08-01 19:11:44 +01:00
Martin Whitaker c383d2048c Fix initialisation of vvp symbol table values.
In 64-bit Windows, an unsigned long is 32 bits, so initialising the num
member of the union did not properly initialise the ptr member. The num
member isn't actually needed, so eliminate it.
2019-08-01 12:34:47 +01:00
StefanBruens d58fde6f36 Fix redefinition of YYLTYPE struct caused by wrong include order
cfparse.h defines the YYLTYPE struct in case it has not been defined, and
also declares an extern YYLTYPE cflloc which is used in cflexor.

As cfparse_misc.h defines an extended YYLTYPE, the cflloc instance in
cfparse.c has this extended type, i.e. there is a type mismatch.

Changing the include order in cflexor causes both cflexor.c and
cfparse.c to use the definition from cfparse_misc.h.

This has been uncovered by GCC when using LTO:
---
gcc -flto=8 main.o substit.o cflexor.o cfparse.o -o iverilog 
cfparse.h:105:16: warning: type of 'cflloc' does not match original declaration [-Wlto-type-mismatch]
  105 | extern YYLTYPE cflloc;
      |                ^
cfparse.c:1162:9: note: type 'struct cfltype' should match type 'struct YYLTYPE'
 1162 | YYLTYPE yylloc
      |         ^
cfparse.c:1162:9: note: 'cflloc' was previously declared here
cfparse.c:1162:9: note: code may be misoptimized unless '-fno-strict-aliasing' is used
---
2019-07-26 21:26:08 +02:00
Martin Whitaker 893bb62d82 Fix broken 'make install' in MSYS2.
The commands added to copy MINGW DLLs into the install directory only
work when cross-compiling.
2019-07-26 17:29:27 +01:00
Martin Whitaker 6309674a8d Fix GitHub issue #231 - support packed array indexing in foreach statement. 2019-07-25 11:10:08 +01:00
Martin Whitaker 8402696676 Fix VPI interface to APV objects.
- type is vpiPartSelect, not vpiMemoryWord
- left/right range is for part, not full word
- index is not valid for a part select

The user will now get a sensible error message if they pass part of an
array word to $dumpvars (GitHub issue #230).
2019-07-25 08:58:00 +01:00
Martin Whitaker 0cb1ebddf1 Fix for GitHub issue #239 - segfault when library file has syntax errors.
If there are errors when parsing a file, it is not safe to elaborate any
modules that have been found in that file.
2019-07-24 10:22:55 +01:00
Martin Whitaker 8cd8bed22e Fix GitHub issue #243 - support arbitrary width static bit arrays in vvp. 2019-07-24 09:15:44 +01:00
Martin Whitaker 89cbc42094 Reset parser tracking variables when starting a new compilation unit.
This fixes the problem reported in GitHub issue #254, where if the
parser aborted on one compilation unit, spurious errors were reported
for the next compilation unit.
2019-07-23 22:18:39 +01:00
Martin Whitaker acdd78db7d Merge branch 'primitive_redefinition' of https://github.com/thasti/iverilog
- make primitive redefinition a warning, not an error
- make edge-sensitive ifnone a warning, not an error

This allows Icarus to be used to simulate designs using third-party
cell libraries that contain such things.
2019-07-23 21:53:57 +01:00
Stefan Biereigel ca19ebe5d5 remove Error:/Warning: prefix from VLerror/VLwarn 2019-07-23 18:58:20 +02:00
Martin Whitaker 4055752959 Fix white space errors. 2019-07-23 10:08:37 +01:00
Martin Whitaker 93ea864106 Merge branch 'antmicro-attribute_support' 2019-07-23 10:06:57 +01:00
Maciej Kurc b619b43ddd Added support for parsing attributes on function calls
Signed-off-by: Maciej Kurc <[email protected]>
2019-06-05 16:42:52 +02:00
Maciej Kurc e6fa2625a4 Added support for parsing attributes on port connections
Signed-off-by: Maciej Kurc <[email protected]>
2019-06-05 16:28:45 +02:00
Martin Whitaker 5bb6c7f53a Fix makefile rules for header files generated by bison.
bison 3.4.1 writes the header file before the c++ file. Our makefile
rules make the header files depend on the c++ files, so we need to
fix the timestamps accordingly.
2019-06-02 18:50:18 +01:00
Stefan Biereigel c6cf83a13a make ifnone-error a warning 2019-05-17 16:17:08 +02:00
Stefan Biereigel 0cfb66ecbc fix warning call 2019-05-17 15:32:45 +02:00
Stefan Biereigel 7f5145d758 emit only warning for primitive redefinition 2019-05-17 15:20:49 +02:00
Cary R e93ee3967e Update cppcheck suppression file 2019-05-14 22:34:58 -07:00
Cary R 4c58b88792 Update files from GTKWave 2019-05-14 22:34:34 -07:00
Martin Whitaker ffb34861cf Fix GitHub issue #244: handle mixed signed/unsigned power operations.
The signed version of the power operation in vvp should only be used
if the exponent is signed. Both signed and unsigned versions will
produce the correct result regardless of the type of the base operand,
provided it has been appropriately extended to the result size.
2019-05-11 21:33:29 +01:00
Martin Whitaker c4f71db00a Update some comments. 2019-05-10 20:00:04 +01:00
Cary R a9388a895e Update cppcheck waivers 2019-03-26 22:43:03 -07:00
Cary R 407b5a1d7a Update fstapi.c to the latest from GTKWave 2019-03-26 19:59:18 -07:00
Stephen Williams cc921de717 Improve mingw cross instructions. 2019-03-24 10:42:36 -07:00
Stephen Williams a518d594d2 Merge pull request #135 from udif/cross_compile
Fixed cross-compile using mingw 64 bit under Windows 10 Linux subsyst…
2019-03-24 10:28:23 -07:00
Stephen Williams c3575d379b Merge branch 'master' into cross_compile 2019-03-24 10:27:33 -07:00
Martin Whitaker 51a13e883a Fix for GitHub issue 235: segfault when calling vpi_handle_by_name().
When vpi_handle_by_name() iterates over the VPI objects in a scope, handle
the case that vpi_get_str() returns a null value. This currently occurs if
the scope contains an enum type definition, as vpi_get_str() is not
implemented for __vpiEnumTypespec.
2019-03-23 17:21:40 +00:00
Tomasz Hemperek 45fa3b1dec cleanup travis.yml 2019-03-23 16:29:09 +01:00
Stephen Williams df92caadbc Document cross-compile from Linux to Windows.
This uses the mingw32 tool chain on Linux to build Windows
binaries.
2019-03-22 13:57:38 -07:00
Stephen Williams c3d5b23ac4 Fix some Windows build issues. 2019-03-22 08:08:29 -07:00
Martin Whitaker 9369d6db57 Update README to say "or later" for build tool versions. 2019-03-16 12:40:08 +00:00
martinwhitaker 3b32288c6f Merge pull request #232 from cdlscpmv/fix
Fix a typo in the man page
2019-03-16 12:32:00 +00:00
Konst Mayer f95ae911d0 Fix a typo in the man page 2019-03-13 00:16:41 +07:00
Martin Whitaker dc5429e5e7 Fix assertion failure on assignment to part of variable member (GitHub issue #226)
For now, output a "sorry" message, as the compiler doesn't support this.
2019-01-26 17:36:19 +00:00
Martin Whitaker 2ff6af254b Use LLONG_MIN instead of LONG_LONG_MIN.
GCC 8 no longer defines LONG_LONG_MIN. We already assume a C99 compliant
compiler in other places.
2019-01-26 16:47:28 +00:00
Martin Whitaker e745304cc4 Fix for GitHub issue #224 - import * does not import enum members. 2019-01-15 19:58:37 +00:00
Martin Whitaker 7cd078e7ab Restrict cast type to what's allowed by the IEEE standard. 2018-12-15 12:26:33 +00:00
Martin Whitaker 230f0bc13c Fix GitHub issue #219 and #220 - incorrect results from SV size cast. 2018-12-15 11:11:35 +00:00
Cary R 172d7eb0a3 Fix space issues in a couple files 2018-11-13 21:57:46 -08:00
Tomasz Hemperek 5cb562be48 No clang for travis. 2018-11-03 22:43:16 +01:00
Tomasz Hemperek 5911fbf872 Merge remote-tracking branch 'upstream/master' 2018-11-03 22:22:41 +01:00
Tomasz Hemperek cbe9bba291 Add windows build to travis-ci 2018-11-03 21:35:13 +01:00
Tomasz Hemperek a96609d482 Update .travis.yml 2018-11-03 08:15:22 +01:00
Tomasz Hemperek 8b67c9ff62 Update .travis.yml 2018-11-03 08:07:11 +01:00
Martin Whitaker 3612076943 Undo redefinition of unique_ptr at end of header files.
It seems that clang both defines __cplusplus < 201103L and provides
unique_ptr (GitHub issue #215).
2018-11-02 21:22:10 +00:00
Martin Whitaker 6887c31d8c Refactor vpi module path code.
Also restore the original behaviour of the '-M -' option, although it's
probably not needed now we add the default path last.
2018-10-29 20:33:52 +00:00
Martin Whitaker dd33da0d5b Merge branch 'alexforencich-master' 2018-10-29 19:37:33 +00:00
Alex Forencich a1ad6d4b51 Support IVERILOG_VPI_MODULE_PATH environment variable 2018-10-28 12:44:09 -07:00
Alex Forencich a638d1eed0 Check for too many paths specified and fix path priority so paths specified on command line supersede built-in paths 2018-10-28 12:43:40 -07:00
Cary R 844fa056f7 Update fstapi files to the latest from GTKWave 2018-10-12 21:30:20 -07:00
Martin Whitaker fdf353af29 Don't use MinGW strtod workaround when building for MinGW-w64.
The host triplet for MinGW-w64 has changed to more closely match that
for MinGW, so we need to update the pattern in the test.
2018-10-07 23:49:19 +01:00
Martin Whitaker 2f142c4858 Revert "Fix x86_64-w64-mingw32 build: undefined ___strtod"
This reverts commit bef04508f2.
2018-10-07 23:47:26 +01:00
Martin Whitaker 9d0d1938dc Fix bug in output of null character with %c format. 2018-10-07 18:59:53 +01:00
Martin Whitaker 5aae9ea770 Fix bit width when converting real value to binary/hex string in VPI. 2018-10-07 17:17:33 +01:00
Martin Whitaker a03995b4da Fix another implicit fallthrough warning. 2018-10-07 11:23:40 +01:00
Martin Whitaker 5cd0ba08b1 Fix alloc size warning when building with recent GCC. 2018-10-06 23:25:13 +01:00
Martin Whitaker 6415d84ed5 Fix invalid cast of TF sizetf callback. 2018-10-06 22:56:04 +01:00
Martin Whitaker 3e25b04685 SIGHUP is not available in Windows. 2018-10-06 21:07:13 +01:00
Martin Whitaker 4ea18196c8 Fix deprecated dynamic exception specification warnings. 2018-10-06 21:02:41 +01:00
Martin Whitaker e71a76a1e2 Fix signed/unsigned comparison warning. 2018-10-06 20:40:54 +01:00
Martin Whitaker 0d20c50de4 Fix typo in last commit. 2018-10-06 20:22:12 +01:00
Martin Whitaker f1608e163f Fix implicit fallthrough warnings when building with recent GCC. 2018-10-06 20:15:42 +01:00
Cary R 27b5c2cdc8 Merge branch 'master' of github.com:steveicarus/iverilog 2018-10-06 09:27:10 -07:00
Cary R 7fa6eaef0a Update to latest GTKWAve files 2018-10-06 09:26:39 -07:00
Martin Whitaker 78317a2799 Fix auto_ptr deprecated warnings when building with recent GCC. 2018-10-06 17:15:31 +01:00
Martin Whitaker 542fe2cf77 Enable checks for VPI const-correctness.
Note we only want these enabled when building the compiler and runtime
binaries. If we included the ICARUS_VPI_CONST definition in the global
CPP_FLAGS, that would propagate to the flags used by iverilog-vpi, so
would affect compilation of user VPI code.
2018-10-06 11:48:19 +01:00
Martin Whitaker 603ff303f5 Cleanly terminate vvp on SIGHUP or SIGTERM (GitHub issue #203). 2018-09-29 23:25:04 +01:00
Martin Whitaker b066a5815e Allow %c format to output null characters (GitHub issue #209)
Currently $display et al. output nothing when the expression
corresponding to a %c format specification has the value 0. As
Verilog provides no other way to write raw bytes to a file, we
should allow 0 values to be written. Other simulators allow this.
2018-09-29 21:22:17 +01:00
Martin Whitaker 0d494da702 Further fixes for const-correctness.
- allow ICARUS_VPI_CONST to be pre-defined by the user
- use it for sizetf as well as for compiletf and calltf
- fix remaining warnings when it is defined as 'const'
2018-09-29 12:04:16 +01:00
Martin Whitaker 8df2f0cadf Fix broken links to SourceForge bug/patch trackers (GitHub issue #207).
Also add link to GitHub issues, as a lot of users report bugs there.
2018-09-28 10:03:06 +01:00
Cary R 3f24557e90 Add some more always_ff synth checks 2018-09-23 22:32:22 -07:00
Cary R e6f957b0b6 Add support for a constant $countbits() function 2018-09-03 15:58:57 -07:00
Cary R 1da9b2cea0 Add support for constant $countones, $isunknown, $onehot, $onehot0 2018-09-03 08:32:41 -07:00
Cary R 2b030ce27a Update the bit vector table name 2018-09-03 08:32:35 -07:00
Cary R b35f9e13c7 Move the bit vector functions to the SV table 2018-09-03 08:32:28 -07:00
Cary R 40558160e7 Add support for bit vector system function in vpi 2018-08-30 22:31:15 -07:00
Cary R ff8ccc0b3e Update fstapi.c to the latest version 2018-07-16 09:03:38 -07:00
Martin Whitaker 11c826216a Fix for GitHub issue #198 - support octal display for thread variables. 2018-06-12 22:58:07 +01:00
Martin Whitaker 7ad5b59a6f Fix for GitHub issue #199: handle signed division overflow.
When performing a signed division or modulus operation using native
arithmetic, trap the special case that the numerator is the minimum
integer value and the denominator is -1, as this gives an undefined
result in C++.
2018-06-12 21:59:58 +01:00
Martin Whitaker 6e49ab10ec Further fix for br1029.
The code in vpi_callback.cc is replicated in vpi_vthr_vector.cc,
so we have to replicate the fix. This should really be factored
out.
2018-05-14 22:14:51 +01:00
Martin Whitaker 87c01c55c0 Don't allow non-vectorable arguments to $signed/$unsigned.
This led to an assertion failure in many cases (see br1029).
1364-2012 indicates it is illegal.
2018-05-14 22:13:56 +01:00
Martin Whitaker 5a4e99b0e8 Fix br1029 - correct rounding when vpi_get_value converts real to integer string. 2018-05-12 23:49:11 +01:00
Stephen Williams 6c39348d1a Merge branch 'master' of github.com:steveicarus/iverilog 2018-04-11 13:40:04 -07:00
Stephen Williams 6c9b3c39b4 Add the --ccflags option to iverilog-vpi 2018-04-11 13:39:53 -07:00
Stephen Williams 797fe44011 Merge pull request #186 from anparks/master
Fixed install step misnomer in README
2018-03-28 12:42:37 -07:00
Aaron Parks fdaf923532 Fixed install step misnomer in README 2018-03-28 12:24:47 -07:00
Stephen Williams 64618af4a9 Merge pull request #123 from dcandrade/master
Added missing compilation instruction on README
2018-03-26 09:55:34 -07:00
Martin Whitaker 5cfb7d68ae Add support for rtran switches in vvp. 2018-02-23 22:30:32 +00:00
Martin Whitaker 36eef5154f Implement supply->strong strength reduction for non-resistive switches.
As specified in 1364-2005 section 7.11.
2018-02-23 22:07:59 +00:00
Martin Whitaker 69d80839a5 Improved check for missing task/function port direction. 2018-02-21 20:07:13 +00:00
Martin Whitaker 6b1b402a79 Fix for br1027: incorrect inference of task/function port direction.
In traditional Verilog, each task_port_item must have an explicit port
direction.

In SystemVerilog, if the port direction is not specified, it should be
inherited from the preceding task_port_item for that task/function, and
only the first task_port_item should infer the direction to be 'input'.
2018-02-20 20:59:26 +00:00
Martin Whitaker f8a2a4816c Enable parameter/localparameter definitions in the compilation unit scope. 2018-02-18 19:21:18 +00:00
Martin Whitaker 2a21fe77ac Output an error message when a SV variable declaration reuses a name.
Assertion failures are not the right way to handle user code errors.
2018-02-18 17:51:56 +00:00
Martin Whitaker caf83b02c1 Enable variable declarations/initialisations in the compilation unit scope. 2018-02-18 14:09:03 +00:00
Martin Whitaker 0f95770418 Include compilation units in pform dump. 2018-02-18 12:53:29 +00:00
Cary R e7a9662b3d A #0 is not allowed in a final block 2018-01-01 21:35:26 -08:00
Cary R 24a4ec3bb2 Hide the always_comb/latch TO event by not attaching it to a scope. 2018-01-01 21:19:58 -08:00
Cary R ca01385797 The synth check needs to check the task scope 2017-12-28 08:50:32 -08:00
Cary R 932241ee87 Check system/user tasks for always_comb/ff/latch synth. 2017-12-27 23:08:32 -08:00
Cary R 7d11fa662e Fix space issues 2017-12-27 14:51:56 -08:00
Cary R 2bbd077dc9 Add some synthesis checks for the always_comb/ff/latch blocks 2017-12-27 14:51:17 -08:00
Stephen Williams 0caa109174 Merge pull request #181 from phire/portinfo_grammar
vvp grammar: .port_info statements should require/generate semicolons.
2017-12-18 10:04:42 -08:00
Scott Mansell d01e5accc0 vpp: Require semicolon after .port_info statements
Optional until 12.0
2017-12-17 00:06:09 +13:00
Scott Mansell 7b84b29bbc tgt-vvp: Output semicolon after .port_info statements
Backwards compatablity is perserved due to the parser interperting the
unexpected semicolon as an empty statement.
2017-12-16 23:59:48 +13:00
Cary R 9a8212a54f Update tp the latest files from GTKWave 2017-12-13 21:56:59 -08:00
Cary R f17992bcd0 Report the lines that have delay or event control in an always_comb/ff/latch process 2017-12-06 00:22:43 -08:00
Cary R cb0ffd734e Check to see that always_comb/ff/latch do not have delays/events 2017-12-05 22:10:43 -08:00
Cary R 39c14edb76 The delay for a join_any and join_none is different than join 2017-12-05 21:49:52 -08:00
Cary R c38ca2114b Note the always_comb/ff/latch have not been looked at for synthesis 2017-12-03 20:17:42 -08:00
Cary R db1ea05452 Fix #0 to trigger in the inactive region and add a trigger for always_comb/latch 2017-12-03 20:17:42 -08:00
Cary R a5b945f8f5 Initialize the t0 trigger value to false. 2017-12-03 20:17:42 -08:00
Cary R e611e8acc0 Add support to convert always_comb/latch to vlog95 2017-12-03 20:17:42 -08:00
Cary R 575aa9b0fb Fix spelling in always_comb 2017-12-03 20:17:42 -08:00
Cary R 84d0df8a8a Pass to the targets if an implicit T0 trigger event is needed. 2017-12-03 20:17:42 -08:00
Cary R 585a0232cb Add preliminary support for always_comb, always_ff and always_latch 2017-11-20 07:50:05 -08:00
Cary R c68a7fede3 Fix spacing 2017-11-20 07:30:52 -08:00
Cary R 3fc9ad2db0 Add support for the wild compare operators ==? and !=? 2017-11-17 19:32:50 -08:00
Cary R d23b046203 Update the enumeration methods to set their width test attributes correctly 2017-11-17 13:09:14 -08:00
Cary R 21418c6a41 Fix a couple memory leaks in $sdf_annotate() 2017-11-16 19:42:07 -08:00
Cary R f03033e612 Update flex destroy routines to work for version 2.6 and greater 2017-11-16 19:11:50 -08:00
Martin Whitaker d1487c10f1 Fix shadow warning when using older versions of gcc. 2017-11-08 21:23:22 +00:00
Martin Whitaker ad83a135e5 Fix assertion failure in vvp wide functor.
If the functor output is read before any values have propagated to
the functor inputs, the internal storage won't have been initialised.
2017-11-08 20:35:18 +00:00
Martin Whitaker 0f2ce7da45 Fix for GitHub issue #172: don't use %precedence in parser.
Older versions of bison don't support this. Use %nonassoc instead.
2017-11-08 20:20:04 +00:00
Martin Whitaker c0845d8bea Fix assertion failure when using -Wmacro-redefinition, -y, and -D.
Predefined macros get stored in the precompiled macro file that gets
read back in when processing library files. This means the predefined
macros get processed twice. We need to skip the check in this case.
2017-11-08 20:07:38 +00:00
Martin Whitaker 02daffc97e Add option to only warn about macro redefinitions that change the text.
A common use case (prior to the introduction of localparam) was to
use macros to define constant values, and to put global constant
values in an include file that gets included by each source file.
This will generate a lot of spurious warnings if we warn about all
redefinitions. Make this new option the default for -Wall.
2017-11-08 19:50:42 +00:00
Martin Whitaker c622d372f9 Fix for GitHub issue #169: nets can get given wrong scope in VPI.
In vvp, the __vpiSignal object holds a pointer to the scope containing
the signal. This was getting set to the current scope when the net was
finally resolved, rather than to the scope where the net was declared.
2017-11-07 18:48:48 +00:00
Martin Whitaker 1f85cd4154 Merge branch 'nekromant-master'
Adds warning about macro redefinition (GitHub pull request #168).
2017-11-06 21:07:47 +00:00
Martin Whitaker af1ea13c47 Don't check for macro redefinition if the warning is disabled.
And reword the comment to be a bit less dictatorial.
2017-11-06 21:03:03 +00:00
Martin Whitaker e408550d9d Merge branch 'master' of https://github.com/nekromant/iverilog into nekromant-master 2017-11-06 20:59:27 +00:00
Martin Whitaker f83e01847a Fix a couple of minor bugs in the timescale parsing rework. 2017-11-06 00:37:56 +00:00
Martin Whitaker 479af09cc3 Fix trailing whitespace. 2017-11-05 22:28:53 +00:00
Martin Whitaker fd807a7700 Rework handling of timescales in parser.
This implements and enforces the full set of rules for determining
timescales in SystemVerilog. The previous relaxation of the rules
that allowed timescales to be redefined within the compilation unit
scope has been removed. Time unit and precision redeclarations are
now recognised after a nested module declaration.
2017-11-05 17:50:05 +00:00
Martin Whitaker 9382d22063 Factor out common code for warning about inconsistent timescales.
Also reword the warning for SystemVerilog, where `timescale is not
the only (or indeed preferred) way of specifying timescales.
2017-11-05 09:39:21 +00:00
Martin Whitaker e54d19e2d2 Fix $printtimescale to support 10s and 100s values. 2017-11-05 09:28:19 +00:00
Martin Whitaker 913fb34799 Add support for the $unit scope identifier.
This relies on using the automatically generated name for the unit scope.
This could collide with an escaped identifier, so it would be better to
identify the scope by a reference to the PPackage object, but for now,
do it the easy way.
2017-10-31 20:39:49 +00:00
Martin Whitaker 988816c0b1 Support separate compilation units in SystemVerilog.
The compilation unit scope is now treated as a specialised form of
package (with an automatically generated name). All items declared
outside a design element are added to the current compilation unit
package. Apart from when searching for a symbol, once we get into
elaboration we can treat these just like any other package.
2017-10-31 20:38:59 +00:00
Martin Whitaker dfddbea26b First step towards supporting separate compilation units in SV.
This adds a -u option to the driver to allow the user to specify that
they want each source file to be treated as a separate compilation
unit, and modifies the compiler to accept a list of files (either on
the command line or via a file specified by a new -F option). This
list of files is then preprocessed and parsed separately, causing all
compiler directives (including macro definitions) to only apply to the
file containing them, as required by the SystemVerilog standard.
2017-10-31 20:36:27 +00:00
Cary R 7d78f5b2ea A few updates based on cppcheck results 2017-10-23 00:22:01 -07:00
Cary R d9478bd837 Update cppcheck waiver files 2017-10-23 00:21:51 -07:00
Cary R 97e2123724 Update to latest files from GTKWave 2017-10-22 19:41:14 -07:00
Andrew Andrianov 3e87a4d242 driver: Add -Wno-macro-redefinition, properly pass -Wredef to ivlpp
Signed-off-by: Andrew Andrianov <[email protected]>
2017-10-22 13:53:07 +03:00
Andrew Andrianov 9e2252bc39 ivlpp: Actually take warn_redef flag into account
Signed-off-by: Andrew Andrianov <[email protected]>
2017-10-22 13:28:15 +03:00
Andrew Andrianov 94e42e5bfc driver: Update manpage
Signed-off-by: Andrew Andrianov <[email protected]>
2017-10-19 11:40:50 +03:00
Andrew Andrianov 6c2fba1139 driver: Implement -Wr handling for macro redefinitions
Signed-off-by: Andrew Andrianov <[email protected]>
2017-10-19 11:40:07 +03:00
Andrew Andrianov 0c84413347 ivlpp: Add -Wredef option to enable redefinition warnings
Signed-off-by: Andrew Andrianov <[email protected]>
2017-10-18 19:18:14 +03:00
Martin Whitaker 4f383a8a11 Enable base class tasks to be used in an extended class. 2017-10-08 21:16:50 +01:00
Martin Whitaker 87cddf33dc Fix for GitHub issue #98 and #167
Two fixes needed:
  - when searching for a base class, we need to look in the root scope
    if the base class isn't found in the scope hierarchy
  - the classes in the root scope need to be stored in an ordered
    list, not a map, to ensure they are elaborated in the order they
    were declared. Without this, the compiler may try elaborating an
    extended class before its base class is known about.
2017-10-08 21:15:11 +01:00
Martin Whitaker 5ca058bfb5 Add support for darray initialisation from another darray.
Fixes GitHub issue #164.
2017-10-08 17:51:33 +01:00
Martin Whitaker 1aeaafa96c Add support for vec4 darray initialisation from an array pattern.
This was just a missing case label in tgt-vvp.
2017-10-08 17:41:58 +01:00
Martin Whitaker 8a36849fda Generate proper error messages for invalid dynamic array initialisers.
Invalid user code should not result in an "internal_error".
2017-10-08 12:59:30 +01:00
Andrew Andrianov 73167563d5 ivlpp: Warn about macro redefinition
Verilog spec has a very nasty system of macros jumping from
file to file, resulting in a global macro scope. We abosolutely
MUST track macro redefinitions and warn user about them.

Signed-off-by: Andrew Andrianov <[email protected]>
2017-10-08 14:22:40 +03:00
Martin Whitaker e315cafa01 Fix for GitHub issue #165 : assertion failure on thread join.
If a thread becomes detached due to a join_any statement, that
thread must not attempt to join its parent, even if the parent
is waiting on a subsequent join statement.
2017-10-07 16:41:26 +01:00
Martin Whitaker 85fa24fa58 Fix for br1025 : support nested scopes in root level tasks/functions. 2017-10-04 21:31:56 +01:00
Martin Whitaker 3566ff4cd4 Fix for GitHub issue #163 : assertion failure caused by syntax error in task. 2017-09-28 19:24:04 +01:00
Martin Whitaker a1a7f5deff Fix error in last commit. 2017-09-17 19:58:13 +01:00
Martin Whitaker 0bed890bc6 Fix use after free bug in vvp when a task or function is disabled.
Use test_joinable() and do_join() to ensure everything gets cleaned
up before the thread is reaped. This should fix br1016, br1017, and
br1018.
2017-09-17 19:48:54 +01:00
Martin Whitaker c855b8926e Fix for GitHub issue #162 : very wide busses cause assertion failure.
This occurs when tgt-vvp attempts to generate a C4<..> constant
value with a bit width >= 65536. The actual failure occurs in the
StringHeap class, which originally supported a maximum string length
of 65535. This fix enables the StringHeap class to support any size
string (provided the system has sufficient memory).
2017-09-11 21:49:35 +01:00
Martin Whitaker ac87138c44 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.
2017-08-12 12:23:43 +01:00
Cary R 917d754e37 Fix space issue 2017-07-22 13:00:50 -07:00
Daniel Andrade 7362c7cbf8 Clarifying compilation instructions 2017-06-30 20:41:55 -03:00
Cary R 62e0f59b07 No need for class in previous patch 2017-06-19 21:26:24 -07:00
Cary R 10ef0eb109 Fix class versus struct warning in clang 2017-06-19 21:26:16 -07:00
Martin Whitaker 42422d9940 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.
2017-06-16 20:56:31 +01:00
Martin Whitaker e2be64558b 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.
2017-06-15 09:11:11 +01:00
Martin Whitaker 3de7c234f7 Implement vpi_put_value() for named events (GitHub issue #158). 2017-06-15 08:47:29 +01:00
Martin Whitaker 8a5cbd4415 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.
2017-04-21 21:37:17 +01:00
Stephen Williams 0f57cceecc Merge pull request #154 from 8tab/depfile
Return if unable to open dependencies file
2017-04-10 09:43:05 -07:00
8tab cac5388451 Return if unable to open dependencies file
Return and print an error if iverilog is unable to open dependencies
file. User can pass e.g path to existing directory in '-M' option,
which makes fopen to return NULL followed by crash in fclose.
2017-04-09 23:18:49 +02:00
Stephen Williams 02ed16a50e Merge pull request #151 from tumik/master
Added an option for ignoring errors about missing modules
2017-03-22 15:33:58 -07:00
Mikael Tuomisalo c967ed238c Added option for ignoring errors about missing modules 2017-03-21 17:34:44 +02:00
Stephen Williams 135b7fba7e Merge pull request #149 from jersey99/master
Add support to handle attributes at module instantiation sites.
2017-03-16 09:38:04 -07:00
Vamsi Vytla cfd3b893be Add support to handle attributes at module instantiation sites.
(* my_fancy_attribute *)
foobar1 foobar (clk(clk), rst(rst) ...);

  - Modifies PGModule to hold the attribute map (can be verified with pform_dump)
  - pform_make_modgate(s) bind the attributes from the parser to the above map
  - The attributes from PGModule are inserted into the NetScope of that module
    PGModule::elaborate_scope_mod_instances_
  - Currently these attributes automatically make it into netlist
  - These attributes are accessible via ivl_scope_attr_cnt and ivl_scope_attr_val
    from ivl_target.h
2017-03-16 07:41:10 -07:00
Stephen Williams fbd69e1774 Merge pull request #148 from Jesus89/mingw-fix
Fix x86_64-w64-mingw32 build: undefined ___strtod
2017-02-27 15:12:12 -08:00
Jesús Arroyo Torrens bef04508f2 Fix x86_64-w64-mingw32 build: undefined ___strtod 2017-02-24 10:43:30 +01:00
Stephen Williams a427440054 Merge branch 'master' of github.com:steveicarus/iverilog 2017-02-17 10:40:14 -08:00
Johann Klammer 8bccbe7cb5 fix for const eval 2017-02-17 09:55:39 -08:00
Martin Whitaker 3c91630b53 Improved error checking for defparam values supplied on the command line.
Fixes GitHub issue #139 plus various assertion failures when invalid
values are specified.
2017-01-29 20:13:01 +00:00
Martin Whitaker 8f6f999ea7 Fix for GitHub issue #142 - assertion failure when parameter expression
contains undefined variable.
2017-01-29 10:47:54 +00:00
Martin Whitaker 4e2ba29dc6 Add library search path option to iverilog-vpi (GitHub issue #145). 2017-01-29 09:32:14 +00:00
Stephen Williams 221084d838 Sorry message for procedural assertion statements. 2017-01-10 11:38:38 -08:00
Cary R 3d9e777ae5 Allocate the correct amount of memory when escaping a string 2017-01-08 20:46:20 -08:00
Udi Finkelstein 7cf279b8a5 Turn off warnings caused by gcc 6.2.0 as installed by the MSYS2 mingw32
package. This probably affects all gcc 5.x installs as well.
2017-01-02 22:46:07 +02:00
Johann Klammer c79df7c44b fix failing VPI callbacks the vpip_cur_task was left dangling 2017-01-01 17:44:54 -08:00
Stephen Williams 6e5558e67d Trivial fixes to pform dumps. 2016-12-29 09:39:45 -08:00
Udi Finkelstein a3bedb8e00 mingw installs now also pack the required DLLs. 2016-12-11 16:18:36 +02:00
Udi Finkelstein f48b0e3434 Allows compiling for Windows (32 or 64 bits) under Linux. 2016-12-11 03:40:35 +02:00
Udi Finkelstein 2127680e49 Fixed cross-compile using mingw 64 bit under Windows 10 Linux subsystem (Ubunto 14.04)
Should work with true Ubuntu 14.04 as-is.
2016-12-08 00:11:22 +02:00
Stephen Williams 063ae77568 Merge pull request #132 from Fatsie/master
[vhdlpp]Added to_bit and to_bitvector standard functions
2016-11-29 08:59:51 -08:00
Staf Verhaegen 447f941f35 [vhdlpp]Added to_bit and to_bitvector standard functions 2016-11-27 01:28:39 +01:00
Martin Whitaker b4e8a12309 Fix for GitHub issue #128 - disable CONCATZ generation for vhdl target. 2016-11-25 22:23:58 +00:00
Martin Whitaker 7cac4677bf Fix for GitHub issue #130 part 2 : assertion failure on unsupported cast. 2016-11-25 22:11:13 +00:00
Martin Whitaker 002f118bb5 Fix for GitHub issue #130 part 1 - null dereference when assigning int to enum. 2016-11-25 21:53:35 +00:00
Henry Wong 182c08b528 Fix segfault when error in multi-dimensional part select. 2016-10-27 10:59:31 -07:00
Henry Wong 69a96112e8 Fix null-pointer when trying to dump null statements. 2016-10-27 10:55:50 -07:00
Henry Wong f827e4f748 Pop current_block_stack after for_variable_declaration and foreach. 2016-10-27 10:29:18 -07:00
Martin Whitaker 991d7d7582 Fix indentation in previous patch. 2016-10-20 16:25:34 +01:00
Henry Wong 1f9bf656ed Adding implementation of NetEvWait::nex_input to handle event controls inside always@(*) blocks 2016-10-20 16:19:55 +01:00
Martin Whitaker a9f1f306f1 Replace strndup with strdup and fix a few potential buffer overrun bugs.
strndup is not available in Windows.
2016-10-14 22:19:33 +01:00
Martin Whitaker edb922f613 Use correct format strings for PLI_UINT64 in printf/scanf functions. 2016-10-14 20:35:36 +01:00
Martin Whitaker 7ddc514518 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.
2016-10-02 18:57:32 +01:00
Martin Whitaker 0fdf29e099 Fix for GitHub issue #117 - delays in VPI simulation time callbacks.
Change cbReadWriteSynch and cbReadOnlySynch to interpret the passed
time value as a relative delay, not an absolute time. This matches
the behaviour of other simulators.
2016-09-25 20:43:58 +01:00
Stephen Williams e56e52bc42 Merge branch 'master' of github.com:steveicarus/iverilog 2016-09-19 12:59:41 -07:00
Maciej Suminski f32b64f497 Fixed warnings about shifting a negative value 2016-09-19 12:54:15 -07:00
Maciej Suminski 151f061298 vhdlpp: Removed unused parameters to mute warnings 2016-09-19 12:53:41 -07:00
Maciej Suminski 3710d35dd1 Added missing brackets 2016-09-19 12:53:06 -07:00
Maciej Suminski aaf0a9e623 vhdlpp: Accept uppercase letters in based literals 2016-09-19 12:46:24 -07:00
Martin Whitaker 080dd0323d Fix for GitHub issue #127 - coerce output ports to inout when necessary. 2016-09-17 19:20:48 +01:00
Cary R 5853e32f82 Fix some cppcheck warning issues 2016-09-13 23:45:25 -07:00
Cary R c706c5dd90 The array properties can be available in a constant context
For most arrays the various properties are available as constant
values and can be evaluated in the compiler.
2016-09-11 14:25:00 -07:00
Martin Whitaker 3c9b39846c 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.
2016-09-08 23:00:48 +01:00
Daniel Andrade fb2cd4775f Added missing compilation instruction on README 2016-09-04 00:51:57 -03:00
Stephen Williams 301e85a8ca Merge pull request #122 from orsonmmz/resize_fix
vhdlpp update
2016-09-02 10:01:02 -07:00
Maciej Suminski 5dd2e6a7c8 vhdlpp: Corrected standard library function headers 2016-09-01 12:08:44 +02:00
Maciej Suminski 8ba3d62071 vhdlpp: Better resize() implementation.
Previous version did not work well with signed expressions or expressions that
were temporarily resized (e.g. a + 32'd42, where a is a[7:0]).
2016-09-01 12:08:44 +02:00
Maciej Suminski bab39dae19 vhdlpp: Some of the standard library functions are imported only on request
Previously they have been always enabled, now it is required to put a
'use' directive.
2016-09-01 12:08:44 +02:00
Maciej Suminski 089dd037d6 vhdlpp: Use the wider variable size for arith operations on (un)signed 2016-09-01 12:08:44 +02:00
Maciej Suminski 25f4a54852 vhdlpp: Subprograms are matched once. ExpFunc::probe_type() return exact type 2016-09-01 12:08:44 +02:00
Maciej Suminski 8f86004100 vhdlpp: Clearer error messages 2016-09-01 12:08:44 +02:00
Maciej Suminski 07543315cf vhdlpp: Stricter array type matching
Arrays type match if they have a common parent, instead of the
element type. Now (un)signed & std_logic_vector types do not match,
as it should be in VHDL.
2016-09-01 12:08:43 +02:00
Maciej Suminski fe77b0ac87 vhdlpp: VTypeArray::dimensions() returns std::vector<range_t> 2016-09-01 12:08:43 +02:00
Maciej Suminski 643a3f2f2c vhdlpp: Do not evaluate generics.
They might change depending on the instance, so they cannot be evaluated using the default value.
2016-09-01 12:08:43 +02:00
Maciej Suminski ed3e67926f vhdlpp: Evaluate conditional signal assignments upon simulation start. 2016-09-01 12:08:43 +02:00
Maciej Suminski 798adc9863 vhdlpp: Support for unary sign operator. 2016-09-01 12:08:43 +02:00
Maciej Suminski 9e95ae5859 vhdlpp: Moved Exp*::dump() methods from debug.cc to expression_debug.cc. 2016-09-01 12:08:39 +02:00
Stephen Williams d44c814bab Remove .alias records from vvp generated code.
Net arrays can be handled by nets directly, instead of creating
.alias records.
2016-08-31 14:05:09 -07:00
Martin Whitaker 41075a45e6 Fix for GitHub issue #121 - correctly determine ivl_root.
Pull request #116 added the ability for the iverilog driver to determine
ivl_root from the location of the iverilog executable (this is needed to
support relocation at the time iverilog is installed). However, the code
did not support the possible variations in the library path name.
2016-08-24 00:00:24 +01:00
Cary R a2fbdeff78 Add some pass by reference to vvp 2016-08-14 22:26:16 -07:00
Cary R ad5a7f7ca3 Update cppcheck vvp suppression file 2016-08-14 21:18:55 -07:00
Cary R d0e0776910 Make the base class match the derived classes regarding passing by reference 2016-08-14 21:18:44 -07:00
Cary R 255701a787 Fix space issue 2016-08-14 20:55:55 -07:00
Cary R 5f1e63604c Update cppcheck vpi suppression file 2016-08-14 20:53:57 -07:00
Cary R 9cf23b4c3b Make getting ivl_root more robust 2016-08-14 19:41:35 -07:00
Cary R 446e825ed3 Fix space issues 2016-08-14 19:37:40 -07:00
Cary R 1d4230472a Fix getting timeunit outside of module to use a defined check value 2016-08-14 17:26:23 -07:00
Cary R 13189f7431 Update fstapi.c to latest from GTKWave 2016-08-14 12:46:48 -07:00
Martin Whitaker b51e58fa9d 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.
2016-08-08 22:10:16 +01:00
Martin Whitaker 8461e1d9c4 Fix vlog95 target to handle hierarchical references in root-level tasks. 2016-07-26 22:01:22 +01:00
Martin Whitaker 2bc42fc6e2 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.
2016-07-26 22:01:22 +01:00
Martin Whitaker 7d5f6c551a Fix unused variable warning and assumed buffer size from last merge. 2016-07-23 12:01:58 +01:00
Martin Whitaker 191811f78f Merge branch 'conda-fix' of https://github.com/tfors/iverilog 2016-07-23 11:40:09 +01:00
Martin Whitaker b1b91f49c8 Update vlog95 target to handle timescales for root scope tasks/functions. 2016-07-23 00:10:01 +01:00
Martin Whitaker 27213f2af8 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.
2016-07-22 23:09:36 +01:00
Martin Whitaker 7bed181f68 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.
2016-07-22 22:48:20 +01:00
Martin Whitaker e316cc708b Fix assignment of outputs from class methods.
As for inputs, skip over the implicit 'this' parameter.
2016-07-21 19:06:21 +01:00
Martin Whitaker b8f9ed27c5 Fix for br1003 - prevent segfault when delays are used outside a module. 2016-07-21 08:40:45 +01:00
Thomas Fors cada40ebd1 Updated comments 2016-07-18 08:10:41 -05:00
Thomas Fors 3afbb903d6 Use /proc/self/exe on linux, if it exists, to find ivl_root 2016-07-18 08:05:16 -05:00
Yury Gribov 43cd693fe0 Put start events to proper queue. 2016-07-17 09:47:08 -07:00
Stephen Williams c37d6ac3ac Merge branch 'master' of github.com:steveicarus/iverilog
Conflicts:
	vhdlpp/parse_misc.cc
	vhdlpp/vtype.cc
2016-07-17 09:36:34 -07:00
Martin Whitaker ad1101cc80 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.
2016-07-11 20:04:24 +01:00
Martin Whitaker ad87704809 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.
2016-07-10 20:00:39 +01:00
Martin Whitaker 7f612270b3 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).
2016-07-10 13:30:58 +01:00
Martin Whitaker 1448210f28 Fix for GitHub issue 112 - index calculation for >2D packed arrays. 2016-07-09 23:33:33 +01:00
Martin Whitaker d496b095ff Fix vector width calculation for multi-dimensional packed arrays. 2016-07-09 17:10:22 +01:00
martinwhitaker e1ec23d160 Merge pull request #114 from wzab/master
Changes necessary to compile with gcc on Debian/Linux testing
2016-07-09 09:04:24 +01:00
Wojciech M. Zabolotny 2c52fd65d3 Changes necessary to compile with gcc on Debian/Linux testing 2016-07-07 23:01:02 +02:00
Stephen Williams 6c7495c93e Merge branch 'master' of github.com:steveicarus/iverilog 2016-07-05 07:59:29 -07:00
Stephen Williams f03e9d4180 Merge pull request #113 from CastMi/original_master
Checks for pointers
2016-07-05 07:59:16 -07:00
Stephen Williams 540bb5afa6 Revert "Update parse_misc.cc"
This reverts commit 6d06e9351a.
2016-07-05 07:56:18 -07:00
Stephen Williams f657d1d7d7 Revert "Update vtype.cc"
This reverts commit 49515ff62b.
2016-07-05 07:56:06 -07:00
Stephen Williams 70031c9d0f Merge pull request #111 from forflo/master
Resolved #110
2016-07-05 07:50:52 -07:00
Michele Castellana 0aa5487214 Check pointers before dereferencing 2016-06-30 17:47:34 +02:00
Michele Castellana 3aa9d535f1 Avoid out of bounds 2016-06-30 17:47:34 +02:00
Michele Castellana 9ad46044b4 Cleanup 2016-06-30 17:47:34 +02:00
Yury Gribov 2d7534b005 Implement barrel shifter LPM for BLIF target 2016-06-13 10:55:38 -07:00
Yury Gribov 31482cbceb Implement sign extension LPM for BLIF target 2016-06-13 10:51:46 -07:00
Yury Gribov 2d5a48c579 Support PULLUP/DOWN and BUFZ in BLIF backend 2016-06-13 10:26:46 -07:00
anon 6d06e9351a Update parse_misc.cc
Fixed bug described in #110
2016-06-13 00:56:43 +02:00
anon 49515ff62b Update vtype.cc
Fixed bug described in #110
2016-06-13 00:55:28 +02:00
Martin Whitaker 8234f1845d Fix for GitHub issue #106 - prevent VPI writes during read-only synch. 2016-06-09 21:27:20 +01:00
Martin Whitaker 332170d36b 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.
2016-06-06 20:12:04 +01:00
Cary R 45fbf55806 Add basic support for parameters using typedefs 2016-05-14 10:34:50 -07:00
Martin Whitaker 61c82d2cb0 Handle mixed continuous and non-blocking assignments to same vector.
SystemVerilog allows a mixture of procedural and continuous assignments
to be applied to different parts of the same vector. The previous attempt
to make this work for non-blocking assignments was flawed (see preceding
fix for vvp_fun_part_pv::recv_vec4_pv). Instead, handle this case by
converting the non-blocking assignment into a delayed force statement,
which matches the way mixed continuous and blocking assignments are
handled.
2016-05-10 22:16:40 +01:00
Martin Whitaker 0c66116f51 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.
2016-05-10 21:59:21 +01:00
Stephen Williams a219df2f18 Merge pull request #95 from orsonmmz/automatic_rebased
vhdlpp: Specify lifetime for variables.
2016-05-04 08:05:01 -07:00
Martin Whitaker 6e5ed73b09 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.
2016-04-18 23:47:43 +01:00
Martin Whitaker b2f7d09f0d 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.
2016-04-04 22:29:54 +01:00
Martin Whitaker 6ba2bee977 Fix for br974 - support SV types in non-ansi port declarations. 2016-04-04 20:40:30 +01:00
Martin Whitaker 9f88b26a67 Fix vlog95 target to handle delayed CA to vector part select. 2016-04-02 22:24:14 +01:00
Martin Whitaker 20104c92c8 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.
2016-04-02 19:55:56 +01:00
Larry Doolittle 4521be4510 More spelling, comments only 2016-04-01 11:02:34 -07:00
Larry Doolittle 89edf62206 Capitalize Verilog in a few places 2016-04-01 11:02:24 -07:00
Maciej Suminski 163a913559 vhdlpp: Specify lifetime for variables. 2016-03-29 11:27:14 +02:00
Maciej Suminski b7d263462c vhdlpp: Fixed automatic variables initalization in subprograms. 2016-03-29 11:27:14 +02:00
Maciej Suminski 4c82352229 vhdlpp: Corrected the comment mark from the previous commit. 2016-03-29 11:27:14 +02:00
Maciej Suminski 97e31ec9fa vhdlpp: Workaround to make subprograms work as if they were automatic. 2016-03-29 11:27:14 +02:00
Maciej Suminski d6ef813a20 vhdlpp: Emit subprograms as automatic by default. 2016-03-29 11:27:14 +02:00
Martin Whitaker 7f475d4210 Refactor to use new pad_to_width/cast_to_width functions. 2016-03-25 22:23:45 +00:00
Martin Whitaker dc1c3a4043 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.
2016-03-25 21:49:28 +00:00
Cary R b5324c7ba2 Fix reference to undefined value (valgrind) 2016-03-24 23:43:07 -07:00
Cary R fb77cc4000 Fix a cppcheck warning 2016-03-24 20:23:47 -07:00
Martin Whitaker 9538c81d34 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.
2016-03-19 20:44:36 +00:00
Martin Whitaker 6e718c2e0c Added support for default subroutine lifetimes (SystemVerilog). 2016-03-19 17:27:27 +00:00
Martin Whitaker 7c3cee5f7a Updated comment in tgt-vlog95 to reflect changes in variable initialization. 2016-03-19 14:47:38 +00:00
Martin Whitaker 0dcb46e4c4 Fix shadow warning. 2016-03-19 14:42:34 +00:00
Martin Whitaker 72bb63cf42 Variable initialization blocks should be unamed.
Also add file/line info to initial process.
2016-03-19 14:21:10 +00:00
Martin Whitaker 54feb89bf5 For SystemVerilog, run variable initialization before main simulation starts. 2016-03-19 13:46:09 +00:00
Martin Whitaker 635adfc01e Fully support variable initialization in tasks/functions/named blocks. 2016-03-19 13:04:38 +00:00
Cary R 28b446ca30 Use correct type when printing supply pull message 2016-03-15 03:49:20 -07:00
Stephen Williams 78a49eacef Merge branch 'master' of github.com:steveicarus/iverilog 2016-03-14 12:26:12 -07:00
Larry Doolittle 1784488096 Spelling and whitespace 2016-03-14 12:25:50 -07:00
Martin Whitaker dbaf2471f2 Fix for br1001 - connect undriven wand/wor to 'bz in tgt-vvp. 2016-03-13 16:38:55 +00:00
Martin Whitaker a5dac08a50 tgt-vlog95: Find the original signal when a port connection is cast. 2016-03-12 23:22:14 +00:00
Martin Whitaker c4b3f256af Don't mislabel signals as ports when casting port connections.
The original signal should retain the port type. Moving it to the cast
signal was confusing the vlog95 and stub targets.
2016-03-12 23:17:54 +00:00
Martin Whitaker 081f5e6960 tgt-vlog95: Fix infinite loop caused by searching the wrong scope. 2016-03-12 23:11:11 +00:00
Martin Whitaker 5d9a196819 tgt-vlog95: Handle variable initialisation in named blocks. 2016-03-12 23:06:54 +00:00
Martin Whitaker dc189fec8c Added new vvp latch statement to README file. 2016-03-12 12:14:03 +00:00
Maciej Suminski 9d487c6951 vhdlpp: Fixed a few shadow warnings. 2016-03-12 12:03:17 +00:00
Martin Whitaker 708a7d0621 Move some redundant initialisation of bitmasks in synthesis.
These are made obsolete by an earlier bugfix.
2016-03-12 12:02:22 +00:00
Martin Whitaker b4d438ea9f Fixed bug in vlog95 dff output when using asynchronous set. 2016-03-12 11:39:32 +00:00
Martin Whitaker 22bc798696 Added warning when a latch enable is a synthesised expression. 2016-03-12 11:21:23 +00:00
Martin Whitaker c0542af6bf Updated copyright dates following previous patch. 2016-03-12 09:10:58 +00:00
Johann Klammer 89333fa3a5 add latch primitive for vlog95 2016-03-12 09:06:42 +00:00
Martin Whitaker 99afea6946 Added support for LPM latches to vvp. 2016-03-12 09:04:51 +00:00
Martin Whitaker b47482880c Added support for LPM latches to stub target. 2016-03-12 09:03:42 +00:00
Martin Whitaker 5dfc9fdefb Code and comment cleanup for latches in target interface. 2016-03-12 00:10:47 +00:00
Johann Klammer d7736d7eba latch for vvp output 2016-03-11 23:44:06 +00:00
Johann Klammer 35a61b4680 Add LATCH to target interface 2016-03-11 23:43:58 +00:00
Martin Whitaker 0e537c5465 Enable latch generation in synthesis.
(reworked patch supplied by Johann Klammer)
2016-03-11 23:29:58 +00:00
Martin Whitaker 81d3b7a25c Updated copyright notices. 2016-03-11 23:14:55 +00:00
Johann Klammer c92b630728 NetLatch class 2016-03-11 23:11:54 +00:00
Martin Whitaker f176106c54 Added notes on synthesis implementation. 2016-03-11 18:35:13 +00:00
Martin Whitaker c1c4d8c863 Fix bitmask merging in synthesis.
A conditional clause that doesn't drive any bits of a particular nexus
should not affect the bitmask generated for that nexus. The completely
undriven case is handled by the enable signal.
2016-03-11 17:32:12 +00:00
Stephen Williams 6a8303bdaf Merge pull request #92 from orsonmmz/vhdlpp_fixes
Vhdlpp fixes
2016-03-07 09:05:36 -08:00
Maciej Suminski de775975e8 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).
2016-03-07 17:11:53 +01:00
Maciej Suminski 770906ba0d vhdlpp: Write binary constants as a string of bits. 2016-03-07 17:11:53 +01:00
Maciej Suminski c25be111a3 vhdlpp: Apply case equality operator for logic type. 2016-03-07 17:11:53 +01:00
Maciej Suminski 41a45a8db0 vhdlpp: Avoid unnecessary toupper() call. 2016-03-07 17:11:53 +01:00
Maciej Suminski 7c10de918e vhdlpp: read() takes into account the size of the destination variable. 2016-03-07 17:11:53 +01:00
Maciej Suminski 94f7504372 vhdlpp: Subprograms are linked to Package instead of generic Scope. 2016-03-07 17:11:53 +01:00
Maciej Suminski 78d6ee26dd vhdlpp: Do not allow 'wire real' nets. 2016-03-07 17:11:49 +01:00
Maciej Suminski 7bb4cef9bc vhdlpp: ExpScopedName class to handle names with a specified scope. 2016-03-07 11:38:11 +01:00
Maciej Suminski 03e85850e1 vhdlpp: Variables are moved to respective process scopes. 2016-03-07 11:38:11 +01:00
Maciej Suminski b037d533f9 vhdlpp: ProcessStatement inherits after ScopeBase. 2016-03-07 11:38:11 +01:00
Maciej Suminski 25cd0827ba vhdlpp: Removed ProcessStatement::rewrite_as_always_edge_() & extract_anyedge_().
Processes sensitive to edges are now handled with $ivlh_{rising,falling}_edge().
2016-03-07 11:38:11 +01:00
Maciej Suminski 7cbb275ffe vhdlpp: Handle limited-length strings in reports.
Currently limited-length strings (e.g. string(1 to 4)) are
emulated using 2D array of bits (e.g. bit [1:4][7:0]).
Because of that, ivl treats them as standard vectors and
$display() does not show them as strings. Now, they are
wrapped with $sformatf("%s", ..) to fix it.
2016-03-07 11:38:11 +01:00
Maciej Suminski e4bc404e99 vhdlpp: ExprVisitor stores the recursion level. 2016-03-07 09:54:28 +01:00
Maciej Suminski cef45ff21a vhdlpp: Emit init values for wires as a weak assignment. 2016-03-07 09:54:28 +01:00
Maciej Suminski fca2fff24e vhdlpp: VTypeRange::type_match() 2016-03-07 09:54:28 +01:00
Maciej Suminski 1ed4603a18 vhdlpp: Set EOF flag right after reaching the end of file. 2016-03-07 09:54:28 +01:00
Maciej Suminski 83330c22fb vhdlpp: Refactored code for format matching in read/write() sys functions. 2016-03-07 09:54:28 +01:00
Maciej Suminski a7f4d65aaa vhdlpp: More robust report messages display. 2016-03-07 09:54:28 +01:00
Maciej Suminski 9cf1dcbae2 vvp: Corrected vvp_net_fun_t::recv_vec4_pv() (commit de968e18) 2016-03-07 09:54:28 +01:00
Maciej Suminski c23f970a5f vhdlpp: Do not display an error message when probing type without a context. 2016-03-07 09:54:28 +01:00
Maciej Suminski f620727555 vhdlpp: Added a few missing FILE_NAME directives in the parser. 2016-03-07 09:54:28 +01:00
Maciej Suminski b4baace4b1 ivl: Support for part selection in multidimensional packed ports assignment. 2016-03-07 09:54:28 +01:00
Maciej Suminski 045d9e7117 vhdlpp: Improved type matching rules. 2016-03-07 09:54:28 +01:00
Maciej Suminski 69b7c000d0 vvp: Implemented vvp_net_fun_t::recv_vec4_pv(). 2016-03-07 09:54:28 +01:00
Maciej Suminski a40d1a65c4 vhdlpp: Emit enum type as int. 2016-03-07 09:54:28 +01:00
Maciej Suminski 248275e5e1 vhdlpp: Refactored VType::emit_decl(). 2016-03-07 09:54:28 +01:00
Maciej Suminski 5f1cd624fe vhdlpp: Set reg flag only for arrays of unpacked types. 2016-03-07 09:54:28 +01:00
Maciej Suminski 996201a745 vhdlpp: Time type can be packed. 2016-03-07 09:54:28 +01:00
Maciej Suminski 1647e192e5 vhdlpp: Added ExpDelay::visit() method. 2016-03-07 09:54:28 +01:00
Maciej Suminski f802c782b8 vhdlpp: Elaborate wait statement argument as time type. 2016-03-07 09:54:28 +01:00
Maciej Suminski f88b48c7da vhdlpp: Do not emit explicit 'reg' for user-defined types. 2016-03-07 09:54:28 +01:00
Maciej Suminski d20549b27a vhdlpp: Fixed a crash in case of dynamic_cast failure. 2016-03-07 09:54:28 +01:00
Maciej Suminski bba312fee1 vhdlpp: Minor code formatting. 2016-03-07 09:54:28 +01:00
Maciej Suminski 78bd9a389d vhdlpp: Handle multidimensional arrays based on typedefs. 2016-03-07 09:54:28 +01:00
Maciej Suminski f584b4ea50 vhdlpp: Treat range as an expression. 2016-03-07 09:54:28 +01:00
Maciej Suminski 5488ea1e2c vhdlpp: Support for ExpNames with multiple indices. 2016-03-07 09:54:28 +01:00
Maciej Suminski 34b5834a84 vhdlpp: Added file_open() variant that returns status. 2016-03-07 09:54:28 +01:00
Maciej Suminski 0f3f8907c3 vhdlpp: Removed an unnecessary check. 2016-03-07 09:54:28 +01:00
Maciej Suminski 08150eae83 vhdlpp: Add line information for procedure calls. 2016-03-07 09:54:28 +01:00
Maciej Suminski 609f266a8c vhdlpp: Additional variants for standard library functions. 2016-03-07 09:54:28 +01:00
Maciej Suminski 2c4deee0c3 vhdlpp: Support for subprogram overloading. 2016-03-07 09:54:28 +01:00
Maciej Suminski cfa038e75c vhdlpp: VType::type_match() fixes. 2016-03-07 09:54:28 +01:00
Maciej Suminski ad5b003488 vhdlpp: Improved handling for subprogram-related errors. 2016-03-07 09:54:28 +01:00
Maciej Suminski 8d3f559b38 vhdlpp: ExpName::probe_prefixed() returns correct type for complex expressions.
E.g. array_of_records(2).fieldname
2016-03-07 09:54:28 +01:00
Maciej Suminski 25671048f6 vhdlpp: ExpInteger::probe_type() returns either INTEGER or NATURAL, depending on the value. 2016-03-07 09:54:28 +01:00
Maciej Suminski 6b1e08cdb0 vhdlpp: Removed a non-existing method declaration. 2016-03-07 09:54:28 +01:00
Maciej Suminski 32f202bddc vhdlpp: VTypeRangeExpr::elaborate() 2016-03-07 09:54:28 +01:00
Maciej Suminski 42ead3a482 vhdlpp: Elaborate types for signals & variables. 2016-03-07 09:54:28 +01:00
Maciej Suminski 414f240694 vhdlpp: Code cleaning (std_funcs). 2016-03-07 09:54:28 +01:00
Maciej Suminski cc729e8dd9 vhdlpp: Removed redundant ActiveScope::bind_name() for subprograms. 2016-03-07 09:54:28 +01:00
Maciej Suminski 8298c96dee vhdlpp: Turned elaborate_argument() into a SubprogramHeader method. 2016-03-07 09:54:28 +01:00
Maciej Suminski b707228171 vhdlpp: file_open_status enum. 2016-03-07 09:54:28 +01:00
Maciej Suminski f2c8fb0479 vhdlpp: Display an error message when calling a function with too many arguments. 2016-03-07 09:54:28 +01:00
Maciej Suminski 3b165a5f25 vhdlpp: Skip package name emission when calling functions from the same package. 2016-03-07 09:54:28 +01:00
Maciej Suminski f1c07b86a3 vhdlpp: Implemented ReturnStmt::elaborate() method. 2016-03-07 09:54:28 +01:00
Maciej Suminski 00f5785f2c vhdlpp: Minor changes to write_to_stream functions. 2016-03-07 09:54:28 +01:00
Maciej Suminski b79f0d763f vhdlpp: Implemented ExpLogical::write_to_stream() method. 2016-03-07 09:54:28 +01:00
Maciej Suminski daed47eb45 vhdlpp: Improved conditional assignments.
Now they handle expressions without the final 'else'.
2016-03-07 09:54:28 +01:00
Maciej Suminski 19a187fa90 vhdlpp: Fixed the Expression visitor code. 2016-03-07 09:54:28 +01:00
Maciej Suminski db77fafe72 vhdlpp: Clone the initializing expression in signal declarations. 2016-03-07 09:54:28 +01:00
Maciej Suminski 7f6f4157d1 vhdlpp: ExpRange::emit() now returns the number of errors. 2016-03-07 09:54:28 +01:00
Maciej Suminski a884faa8c1 vhdlpp: Delayed assignment statements. 2016-03-07 09:54:28 +01:00
Maciej Suminski eeb5728e20 vhdlpp: emit() methods are const. 2016-03-07 09:54:28 +01:00
Maciej Suminski 730fdaf0f0 vhdlpp: Concurrent assertion statements. 2016-03-07 09:54:28 +01:00
Maciej Suminski 5748018409 vhdlpp: Limited support for final wait statement. 2016-03-07 09:54:28 +01:00
Maciej Suminski f6ee5d0f22 vhdlpp: Corrected an error message. 2016-03-07 09:54:28 +01:00
Maciej Suminski 2e6fb9b3f6 vhdlpp: shift_left/right() functions. 2016-03-07 09:54:28 +01:00
Maciej Suminski 03434efed3 vhdlpp: Elaborate ExpAttribute arguments. 2016-03-07 09:54:28 +01:00
Maciej Suminski 3af3c12b11 vhdlpp: Added system function NOW. 2016-03-07 09:54:28 +01:00
Maciej Suminski 2606d0e897 vhdlpp: Minor code clean up. 2016-03-07 09:54:28 +01:00
Maciej Suminski 52c912c4af vhdlpp: Allow calling functions without parameters and brackets. 2016-03-07 09:54:28 +01:00
Maciej Suminski b08ae23d0d vhdlpp: line feed character (LF). 2016-03-07 09:54:28 +01:00
Maciej Suminski 054dfdf0cf vhdlpp: Simpler enum definitions storage. 2016-03-07 09:54:28 +01:00
Maciej Suminski f52de62729 vhdlpp: Elaborate if statement condition as bool. 2016-03-07 09:54:28 +01:00
Maciej Suminski b6f1cb221e vhdlpp: Fixes for subtypes handling. 2016-03-07 09:54:28 +01:00
Maciej Suminski 79f38b8c56 vhdlpp: Basic loop support (loop..end loop). 2016-03-07 09:54:28 +01:00
Martin Whitaker b4d5248c67 Fix for br1000 - avoid infinite loop when processes share a for-loop index. 2016-03-05 17:43:25 +00:00
Stephen Williams 9a7f31c728 Functions that return strings pass the return value on the stack. 2016-03-01 15:38:28 -08:00
Cary R 7d21891147 Fix space issues. 2016-02-28 22:09:39 -08:00
Martin Whitaker ca02b3ae53 vlog95 target enhanced to support constant input to LPM_SUBSTITUTE. 2016-02-27 21:13:57 +00:00
Martin Whitaker f84f0535cf Renamed synthsplit to exposenodes.
This was needed to avoid automatically setting the synth flag in the
compiler.
2016-02-27 20:24:28 +00:00
Martin Whitaker a33255f0e0 Add support for LPM_SUBSTITUTE and wider LPM_MUX objects in vlog95 target. 2016-02-27 18:08:56 +00:00
Martin Whitaker 9d5f4ad048 Add new synthsplit functor.
This provides support for handling synthesis constructs in the vlog95
target.
2016-02-27 16:40:55 +00:00
Martin Whitaker 8348c25104 Take heed of disable_concatz_generation flag in mux synthesis. 2016-02-27 16:39:15 +00:00
Martin Whitaker a0bee0a76f Add support for real valued compressed assignment statements in tgt-vvp. 2016-02-23 22:02:03 +00:00
Martin Whitaker a85c64d347 Revert "Add support for real valued compressed assignment statements in tgt-vvp."
This reverts commit 3fede95f5e.
2016-02-23 21:49:49 +00:00
Martin Whitaker 3fede95f5e Add support for real valued compressed assignment statements in tgt-vvp. 2016-02-23 20:58:30 +00:00
Martin Whitaker a7066e3686 Fix expression/operator type for compressed assignment/shift. 2016-02-23 20:57:30 +00:00
Martin Whitaker 0199ad129d 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.
2016-02-23 16:53:01 +00:00
Martin Whitaker 241b6723e5 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.
2016-02-23 16:46:26 +00:00
Martin Whitaker b77d758f19 Fix compressed assignments to concatenations.
When loading a lval concatenation, tgt-vvp was loading the elements
in the wrong order for the %concat instruction.
2016-02-23 16:44:03 +00:00
Martin Whitaker 1a78784205 Removed some dead code. 2016-02-23 11:58:27 +00:00
Martin Whitaker f9f51db7ba Extended constant function assignment operator support to real values.
Also output a "sorry" message if the LHS is a concatenation.
2016-02-22 23:31:35 +00:00
Martin Whitaker 74b8c04b91 Add support for SystemVerilog assignment operators in constant functions. 2016-02-22 22:22:22 +00:00
Stephen Williams bc23bc71e3 Merge branch 'master' of github.com:steveicarus/iverilog 2016-02-22 09:49:28 -08:00
Peter Jakobsen cbced021a1 Add missing symbols for dlltool to export 2016-02-22 09:49:06 -08:00
Martin Whitaker f3cf7ca546 Updated comments for synthesis. 2016-02-21 22:39:52 +00:00
Martin Whitaker f29935d8dd Enhanced support for asynchronous set/reset in synthesis.
Added the ability to coalesce set/reset values to different parts
of the same vector. Also added a check that all bits of the vector
are assigned a value.
Enabled coalescence of asynchronous set/reset part-vectors
2016-02-21 21:46:36 +00:00
Martin Whitaker 3fc0204b99 Fix cleanup of NetEvWait class.
The destructor needs to delete the stored NetEvent objects. Failure
to do this was causing a compiler crash after synthesis if the
nodangle functor was disabled.
2016-02-21 21:22:35 +00:00
Martin Whitaker 5286fb858d Synthesis rework.
Synthesis could only handle relatively simple conditional constructs.
This rework aims to make it handle anything the user can throw at it
(or output a sensible message as to why it can't).
2016-02-21 00:00:39 +00:00
Martin Whitaker 46105e0c5a Delayed output of vvp dff to end of current time slot.
Flip-flops are generally modelled in behavioural code using non-blocking
assignments. This change makes the synthesised code behave the same as
the behavioural code. It's a more realistic model of a real flip-flop
too, which will always have some clock-to-output delay.
2016-02-21 00:00:39 +00:00
Cary R 70a350f2e8 Merge branch 'master' of github.com:steveicarus/iverilog 2016-02-10 22:33:21 -08:00
Cary R 03cb74ba57 Fix compile warning 2016-02-10 22:33:10 -08:00
Maciej Suminski 71084109f6 Save the time format suffix string.
In case of a vhdlpp-specific () call, the timeformat suffix string was overridden,
therefore it has to be restored to the previous value after the call.
2016-02-10 22:33:06 -08:00
Stephen Williams 12c39aa4bb Fix broken "inherits dimensions from var/net" warning. 2016-02-10 10:56:14 -08:00
Stephen Williams 139c4154c3 Merge branch 'master' of github.com:steveicarus/iverilog 2016-02-06 16:08:15 -08:00
Stephen Williams f3647578d4 Add the -Wimplicit-dimensions warning. 2016-02-06 16:07:50 -08:00
Cary R eef3e8c09f Fix memory leak in time suffix code (VHDL) 2016-02-04 07:21:22 -08:00
Cary R 3e52b2be66 Fix valgrind compile 2016-02-03 22:25:57 -08:00
Cary R 841593d013 Remove some compile warnings 2016-02-03 21:40:18 -08:00
Stephen Williams 76ced1cf7c Fix %ret/* and %retload/* opcodes to search up for function thread. 2016-02-01 14:51:18 -08:00
Stephen Williams f494b478cc Merge branch 'master' into return-stack
# Conflicts:
#	sv_vpi_user.h
2016-02-01 14:47:44 -08:00
Stephen Williams 469d4fefa7 Handle compressed assign to function return value. 2016-02-01 12:38:48 -08:00
Stephen Williams ce692f90ad Implement and use the %retload/real opcode. 2016-02-01 09:31:06 -08:00
Stephen Williams c114edfa6c Handle void functions with new .scope format. 2016-02-01 09:29:49 -08:00
Stephen Williams fac7de2133 Better handle some different function types in the .scope setup. 2016-01-31 16:16:02 -08:00
Stephen Williams 604a62379c Make .scope aware of return type, and extend %ret/vec4 operands
The .scope needs to be aware of return types so that the %call/vec4
function knows how to intialize the return value. We also need to
extend the %ret/vec4 to support writing parts of the return value.
2016-01-31 15:29:52 -08:00
Martin Whitaker 83a82914e0 Temporary fix for br993 - assertion failure in flip-flop synthesis.
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:38:08 +00:00
Martin Whitaker a006dee990 Fix for br994 - assertion failure when synthesising a mux.
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:11:58 +00:00
Martin Whitaker fbeee1bae3 Temporary fix for br995 - assignment to memory not supported in synthesis.
For now, output a "sorry" message.
2016-01-30 17:01:13 +00:00
Stephen Williams e435a879fc Add ability to read back return value / Add vec4 stacked user functions.
Also:
- handle functions as arguments to system tasks.
- Cleanup detect of signal as return value.
2016-01-24 18:36:26 -08:00
Stephen Williams 0c91a6b041 Add .ufunc/real functor to handle functions with return value on stack. 2016-01-17 16:23:28 -08:00
Stephen Williams bfc9cd8715 Make real functions in processes use parent stack for return value. 2016-01-10 17:09:33 -08:00
Stephen Williams 37a63e5d6d Merge pull request #88 from orsonmmz/image_attr
'image attribute
2016-01-10 15:49:26 -08:00
Martin Whitaker eb2a9be0c9 Fix for br999 - incorrect result from binary comparison.
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:11:42 +00:00
Maciej Suminski 32fab21e95 ivl: Allow concatenating strings returned by function calls. 2016-01-07 11:11:04 +01:00
Maciej Suminski ba274936e5 vhdlpp: Added 'image attribute for time type. 2016-01-06 15:30:24 +01:00
Maciej Suminski 214c940a1a vhdlpp: Fixing memory leaks and muting valgrind. 2016-01-06 15:30:20 +01:00
Maciej Suminski b711f16f05 vhdlpp: 'image attribute. 2016-01-06 15:30:06 +01:00
Maciej Suminski dff1ad08b0 vhdlpp: ExpAttribute split to Exp{Obj,Type}Attribute. 2016-01-06 15:30:06 +01:00
Maciej Suminski 71c63bf993 vhdlpp: Added argument_list token. 2016-01-06 15:30:06 +01:00
Maciej Suminski e0b2a5b337 vhdlpp: Refactored prange_t (class ExpRange). 2016-01-06 15:30:06 +01:00
Maciej Suminski 2c010d34bb vhdlpp: Unified Expression::evaluate() method. 2016-01-06 15:30:06 +01:00
Maciej Suminski 23633c498f vhdlpp: Moved dump_scope() to ScopeBase class. 2016-01-06 15:30:06 +01:00
Maciej Suminski 40075e11ab Code formatting. 2016-01-06 15:30:06 +01:00
Maciej Suminski 1d2aef7142 vpi: $sformatf() function. 2016-01-06 15:30:06 +01:00
Maciej Suminski 9276515e19 vhdlpp: Minor fix for ReportStmt::write_to_stream. 2016-01-05 14:23:25 +01:00
Maciej Suminski 3b310e8227 vhdlpp: Elaborate subprograms in packages. 2016-01-05 14:23:25 +01:00
Maciej Suminski 517c9785e8 vvp: Code cleaning (vpi_tasks). 2016-01-05 14:23:25 +01:00
Maciej Suminski df6b24fd3a ivl & vvp: Enabled 'string' as the return type in VPI functions. 2016-01-05 14:23:25 +01:00
Maciej Suminski 9886b8cb36 vhdlpp: Distinguish character and an array of bits during emission. 2016-01-05 13:55:22 +01:00
Maciej Suminski 1c4b1c12e4 vhdlpp: Fixes for 'wait for' statements emission. 2016-01-05 13:55:22 +01:00
Maciej Suminski ef3d0e4e0d vhdlpp: ExpString::emit distinguishes between array and string types. 2016-01-05 13:55:22 +01:00
Maciej Suminski 442750ca2c vhdlpp: Refactored {Report,Assert}Stmt so they handle expressions instead of strings. 2016-01-05 13:55:22 +01:00
Maciej Suminski 597001ee2f vhdlpp: Variables have always reg_flag set. 2016-01-05 13:55:22 +01:00
Maciej Suminski acb4ca8e47 vhdlpp: More descriptive error message for a missing function. 2016-01-05 13:55:22 +01:00
Cary R e44010c2a3 Remove redundant class keyword 2015-12-29 13:02:58 -08:00
Cary R 71ff9e70ea Fix valgrind release code to work with new scope definition 2015-12-29 12:46:42 -08:00
Cary R 8367285f3b Fix some struct versus class warnings for vpiScope 2015-12-29 12:29:10 -08:00
Stephen Williams 63ad15ee2e Rework user function calls to use specialized opcodes.
Create The %callf/* opcodes to invoke user defined functions in a
more specialized way. This allows for some sanity checking on the
way, and also is a step towards keeping return values on stacks.
2015-12-27 20:29:10 -08:00
Stephen Williams 1b33bf8615 Normalize the parsing of %fork and %disable opcodes. 2015-12-27 13:07:42 -08:00
Stephen Williams f275dac7a8 Kill a bunch of __vpiScope struct vs class warnings. 2015-12-27 11:37:10 -08:00
Stephen Williams 2fedb4942e C++-ify more __vpiScope members. 2015-12-23 17:38:13 -08:00
Stephen Williams fff69390ac C++-ify the __vpiScope classes. 2015-12-20 20:26:57 -08:00
Stephen Williams c88a60537a Merge branch 'master' of github.com:steveicarus/iverilog 2015-12-20 16:31:15 -08:00
Stephen Williams 3e3f245d8c Document the vvp .scope record.
Also clean up some dead code in the vvp parser.
2015-12-20 16:31:03 -08:00
Cary R 3b7ebf6aa2 If ret is already defined then don't overwrite it. 2015-12-20 12:28:29 -08:00
Cary R eb8ad92422 Add cppcheck suppressions for libveriuser 2015-12-19 19:56:49 -08:00
Cary R 1b8ed5f3ed Fix a few more cppcheck warnings and ignore the exported functions 2015-12-19 18:51:18 -08:00
Cary R 399384d81b Fix some cppcheck warnings and bugs 2015-12-19 17:19:19 -08:00
Cary R 2aaa050b7c Update cppcheck suppression file 2015-12-19 11:58:31 -08:00
Cary R a4177f6ddc VHDL: Add some missing newlines 2015-12-19 10:50:16 -08:00
Cary R 4b9b0b7125 GTKWave (fstapi.c) needs realpath() so check for it 2015-12-19 09:11:48 -08:00
Cary R e85d95a659 Cleanup any allocated event queue data 2015-12-14 21:08:17 -08:00
Cary R ad4b523edc A VHDL ExpAttribute() can share the base so don't just delete them 2015-12-13 19:01:33 -08:00
Cary R 45fc06cf11 A format is a vpiStringVal not vpiStringVar, fix memory leak 2015-12-13 18:57:09 -08:00
Cary R aacb4df1dd Fix memory leak found with valgrind 2015-12-13 14:55:05 -08:00
Cary R 24d1f49f3e Fix compile warning from recent patch 2015-12-08 22:07:27 -08:00
Stephen Williams fbeac729af Merge pull request #86 from orsonmmz/files
Basic support for std.textio/ieee.std_logic_textio
2015-12-07 10:37:13 -08:00
Maciej Suminski ab025f1e3b vhdlpp: VTypeRange split to VTypeRangeConst and VTypeRangeExpr.
When range cannot be evaluated it uses the original expressions.
2015-12-04 11:40:03 +01:00
Maciej Suminski 7cebed7382 vhdlpp: Disabled evaluation for ExpTime.
It was always evaluated to a value expressed in femtoseconds,
which not always might be the case.
2015-12-04 11:38:19 +01:00
Maciej Suminski 96a0a84e6c vhdlpp: Fixed the range boundaries order. 2015-12-04 10:29:08 +01:00
Maciej Suminski 2e9c3555cb vhdlpp: AssertStmt::elaborate() probes the condition type. 2015-12-03 17:56:56 +01:00
Maciej Suminski f4238eb563 vhdlpp: Minor code cleaning. 2015-12-03 17:56:41 +01:00
Maciej Suminski 652fe378b8 vhdlpp:: Added ExpUnary::probe_type() function. 2015-12-03 17:54:22 +01:00
Maciej Suminski 9df470c341 vhdlpp: While loops. 2015-12-03 17:53:13 +01:00
Maciej Suminski bb695c6e11 vhdlpp: Fixed infinite recursion when evaluating ExpTime. 2015-12-01 16:38:54 +01:00
Maciej Suminski d5853ff5d7 vhdlpp: File declarations with specified file name and open mode. 2015-12-01 16:38:54 +01:00
Maciej Suminski 83f01a5fc4 vhdlpp: Support for implicit initalizers and finalizers. 2015-12-01 16:38:54 +01:00
Maciej Suminski e4ba4b5acd vhdlpp: Added means to use 'initial' and 'final' blocks during translation. 2015-12-01 10:33:20 +01:00
Maciej Suminski cb40a845e1 vhdlpp: Allow procedure calls with empty param list. 2015-12-01 10:33:20 +01:00
Maciej Suminski 5535b7d26c vhdlpp: Corrected error messages. 2015-12-01 10:33:20 +01:00
Maciej Suminski 2f40c96527 vhdlpp: Basic support for std.textio & ieee.std_logic_textio. 2015-12-01 10:33:20 +01:00
Maciej Suminski 7b483e69d8 vhdlpp: Minor changes. 2015-12-01 10:32:47 +01:00
Maciej Suminski 46ea9e6954 vhdlpp: Out & inout arguments in subprogram calls are turned to registers.
Otherwise it is not possible to modify their values in subprograms.
Argument elaboration has been moved to a separate function, so now it is
common for procedure and function calls.
2015-12-01 10:32:47 +01:00
Maciej Suminski 637d7c9633 vhdlpp: Special handling for STRING type during type emission. 2015-11-24 17:19:33 +01:00
Maciej Suminski ba3c07a59a vhdlpp: CHARACTER type is converted to bit[7:0] instead of byte.
This way it is possible to have limited size strings. Previously they
were translated to unpacked array of bytes, which cannot be assigned as
it was a string.
2015-11-24 17:19:33 +01:00
Maciej Suminski b414733f34 vhdlpp: std.textio & ieee.std_logic_textio functions implemented using VPI. 2015-11-24 17:16:51 +01:00
Maciej Suminski 6fee37a640 vhdlpp: Simplified regex to detect string literals. 2015-11-23 16:25:08 +01:00
Maciej Suminski 925827d2c2 vhdlpp: Escape quotation marks in emitted strings. 2015-11-23 16:25:08 +01:00
Maciej Suminski 6f5addb1b7 vhdlpp: Fixed a gcc warning. 2015-11-23 16:25:08 +01:00
Maciej Suminski 5b0bf08638 vhdlpp: Simplified a few find_* functions. 2015-11-23 16:25:08 +01:00
Maciej Suminski 0569474d17 vhdlpp: Evaluate power (**) and division remainder (REM) operators. 2015-11-23 16:25:08 +01:00
Stephen Williams a62a095717 Merge pull request #83 from chrta/fix_compiler_warnings
Fix 3 compiler warnings
2015-11-02 17:20:57 -08:00
Cary R 6c91588d33 Fix some errors found with cppcheck 2015-11-02 00:14:29 -08:00
Christian Taedcke 3ffe6684e2 Add definition of _DEFAULT_SOURCE.
Since glibc version 2.20, _SVID_SOURCE is deprecated, see
'man 7 feature_test_macros'. To be able to compile this code without compiler
warnings in new and old glibc versions, both _DEFAULT_SOURCE and _SVID_SOURCE
must be defined.
2015-10-31 11:17:18 +01:00
Christian Taedcke be06aa39ab Remove unused static function basename. 2015-10-31 11:17:18 +01:00
Stephen Williams 1b3da449dc Merge pull request #82 from chrta/fix_cppcheck_issues
Make a few constructors explicit.
2015-10-30 15:57:34 -07:00
Christian Taedcke 6d5aabd4f0 Make a few constructors explicit.
This removes cppcheck warnings.
2015-10-22 12:33:33 +02:00
Cary R 97fca3fc4b Fix the modpath delay to ignore bits that are not changing 2015-10-21 22:01:24 -07:00
Stephen Williams a93139f141 Merge branch 'master' of github.com:steveicarus/iverilog 2015-10-17 17:06:26 -07:00
Stephen Williams da9f7878bc Fix minor uninitialized memory access. 2015-10-17 17:06:12 -07:00
Stephen Williams 35b6bdf578 Don't warning about floating local/internal symbols. 2015-10-02 11:23:05 -07:00
Cary R fbc94a95df Update LZ4 files to latest from GTKWave 2015-10-02 10:32:34 -07:00
Cary R a65c007fdb Fix some cppcheck warnings 2015-10-02 09:43:54 -07:00
Stephen Williams 8f095f12de Add -Wfloating-nets warnings. 2015-10-01 15:17:03 -07:00
Stephen Williams 466b6464bc Some minor vvp runtime performance tweaks. 2015-10-01 12:43:56 -07:00
Stephen Williams 4338d43cea Opcodes documentation fixes. 2015-09-30 16:25:35 -07:00
Stephen Williams f01a312f17 Minor code generation improvements
Use $flag_inv instead of %inv is several places.
2015-09-30 16:25:10 -07:00
Stephen Williams fe7156289b Remove some useless vvp opcodes. 2015-09-30 15:41:22 -07:00
Stephen Williams 571109481f Use cmpi in more cases
Before this patch, only literals on the right side of a < compare
(or left side of a > compare) would be blended into a %cmpi instruction.
This patch broadends the cases where the %cmpi can be used.
2015-09-30 12:35:19 -07:00
Stephen Williams 81f54ec0cb 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.
2015-09-29 17:44:28 -07:00
Stephen Williams 66de0fc3e2 Merge branch 'master' of github.com:steveicarus/iverilog 2015-09-22 16:15:47 -07:00
Stephen Williams 8803eb3288 Handle numeric literals with no digits. 2015-09-22 16:15:41 -07:00
Martin Whitaker a1e0040d82 Fix for GitHub issue #79 - literal numbers must have at least one digit.
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:01:39 +01:00
Tomasz Hemperek 821b87a3eb Update .travis.yml 2015-08-24 10:58:54 +02:00
Tomasz Hemperek a844f4a8a2 use docker infrastructure for travis 2015-08-24 10:57:47 +02:00
Martin Whitaker 027e060865 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:02:42 +01:00
Stephen Williams d2c72a126d Remove synthesis warning. 2015-08-20 13:51:42 -07:00
Stephen Williams 238c7b3b9a Merge branch 'master' of github.com:steveicarus/iverilog 2015-08-20 13:49:53 -07:00
Stephen Williams f372cb0c0b Fix windres input version string for v10 and later. 2015-08-20 13:49:38 -07:00
Cary R 19009ec808 Merge branch 'master' of github.com:steveicarus/iverilog 2015-08-18 16:23:02 -07:00
Cary R e682029648 A concatenation or the expression being replicated must have a non-zero width 2015-08-18 16:22:50 -07:00
Stephen Williams df7b1879dd Rework vvp file version checking. 2015-08-17 15:37:28 -07:00
Martin Whitaker 9f4b485c1c Updated copyright dates displayed for main programs and targets. 2015-08-17 22:05:08 +01:00
Martin Whitaker 5dc8edef84 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 21:52:31 +01:00
Larry Doolittle 29478eba4c Squelch just a few trailing spaces in source code 2015-08-17 11:44:45 -07:00
Larry Doolittle 4dd65926ae Spelling fixes 2015-08-17 11:35:10 -07:00
Martin Whitaker 94595fb5f2 Fixed version number in vvp man page. 2015-08-16 23:07:09 +01:00
Cary R 3082dceb6e Update vvp examples to have correct version number 2015-08-15 20:30:20 -07:00
Stephen Williams caffcc14cd Switch devel branch to version 11. 2015-08-15 14:23:20 -07:00
Stephen Williams f66f573fb6 Change Version numbering scheme. 2015-08-15 14:20:41 -07:00
Tomasz Hemperek 50180ac4a6 Add clang support for travis 2015-05-13 21:35:21 +02:00
Tomasz Hemperek 914f959c67 Add .travis.yml 2015-05-05 16:39:28 +02:00
401 changed files with 28159 additions and 11246 deletions
+71
View File
@@ -0,0 +1,71 @@
language: cpp
sudo: required
dist: xenial
addons:
apt:
packages:
- gperf
sudo: false
notifications:
email: false
jobs:
include:
- stage: Test
os: linux
dist: xenial
before_install:
- git clone https://github.com/steveicarus/ivtest.git
- export PATH=$HOME/bin:$PATH
script:
- autoconf
- ./configure --prefix=$HOME
- make install
- make check
- cd ivtest
- perl vvp_reg.pl
- diff regression_report-devel.txt regression_report.txt
- perl vpi_reg.pl
- stage: Test
os: linux
dist: bionic
before_install:
- git clone https://github.com/steveicarus/ivtest.git
- export PATH=$HOME/bin:$PATH
script:
- autoconf
- ./configure --prefix=$HOME
- make install
- make check
- cd ivtest
- perl vvp_reg.pl
- diff regression_report-devel.txt regression_report.txt
- perl vpi_reg.pl
- stage: Test
os: windows
before_install:
- git clone https://github.com/steveicarus/ivtest.git
- choco uninstall -y mingw
- choco upgrade --no-progress -y msys2
- export msys2='cmd //C RefreshEnv.cmd '
- export msys2+='& set MSYS=winsymlinks:nativestrict '
- export msys2+='& C:\\tools\\msys64\\msys2_shell.cmd -defterm -no-start'
- export mingw64="$msys2 -mingw64 -full-path -here -c "\"\$@"\" --"
- export msys2+=" -msys2 -c "\"\$@"\" --"
- $msys2 pacman --sync --noconfirm --needed base-devel mingw-w64-x86_64-toolchain
script:
- $mingw64 ./autoconf.sh
- $mingw64 ./configure
- $mingw64 make install
- $mingw64 make check
- cd ivtest
- $mingw64 perl update_msys2_report.pl
- $mingw64 perl vvp_reg.pl
- diff --strip-trailing-cr regression_report-msys2.txt regression_report.txt
- $mingw64 perl vpi_reg.pl
+13 -9
View File
@@ -116,13 +116,17 @@ programs.
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
bug tracking system. Once you believe you have found a bug, you may
browse the bugs database for existing bugs that may be related to
yours. You might find that your bug has already been fixed in a later
release or snapshot. If that's the case, then you are set. Also,
consider if you are reporting a bug or really asking for a new
feature, and use the appropriate tracker.
The URL <https://sourceforge.net/p/iverilog/bugs/> is the main
bug tracking system, although some users have reported bugs at
<https://github.com/steveicarus/iverilog/issues/>. Once you believe
you have found a bug, you may browse the bugs database for existing
bugs that may be related to yours. You might find that your bug has
already been fixed in a later release or snapshot. If that's the case,
then you are set. Also, consider if you are reporting a bug or really
asking for a new feature, and use the appropriate tracker.
system (although you will also find bug rep
The bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
@@ -145,7 +149,7 @@ version from git. Please see the developer documentation for more
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
When you make a patch, submit it to the "Patches" tracker at
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
<https://sourceforge.net/p/iverilog/patches/>. Patches added to
the "Patches" tracker enter the developer workflow, are checked,
applied to the appropriate git branch, and are pushed. Then the
tracker item is closed.
@@ -158,7 +162,7 @@ clarification before applying it.)
COPYRIGHT ISSUES
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
Icarus Verilog is Copyright (c) 1998-2018 Stephen Williams except
where otherwise noted. Minor patches are covered as derivative works
(or editorial comment or whatever the appropriate legal term is) and
folded into the rest of ivl. However, if a submission can reasonably
+1 -1
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)
{
}
+9 -4
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();
+49 -54
View File
@@ -70,7 +70,8 @@ dllib=@DLLIB@
HOSTCC = @CC@
HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CC = @CC@
BUILDCC = @CC_FOR_BUILD@
BUILDEXT = @BUILD_EXEEXT@
CXX = @CXX@
DLLTOOL = @DLLTOOL@
INSTALL = @INSTALL@
@@ -100,7 +101,7 @@ CTARGETFLAGS = @CTARGETFLAGS@
M = LineInfo.o StringHeap.o
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
FF = cprop.o exposenodes.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
@@ -116,10 +117,10 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
PFunction.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o vpi_modules.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PFunction.o \
PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o \
PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@@ -127,9 +128,9 @@ all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vp
# In the windows world, the installer will need a dosify program to
# dosify text files.
ifeq (@MINGW32@,yes)
all: dosify.exe
dosify.exe: $(srcdir)/dosify.c
$(HOSTCC) $(HOSTCFLAGS) -o dosify.exe $(srcdir)/dosify.c
all: dosify$(BUILDEXT)
dosify$(BUILDEXT): $(srcdir)/dosify.c
$(BUILDCC) $(CFLAGS) -o dosify$(BUILDEXT) $(srcdir)/dosify.c
endif
# This rule rules the compiler in the trivial hello.vl program to make
@@ -137,7 +138,7 @@ endif
check: all
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
test -r check.conf || cp $(srcdir)/check.conf .
driver/iverilog -B. -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl
driver/iverilog -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl
ifeq (@WIN32@,yes)
ifeq (@install_suffix@,)
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
@@ -156,7 +157,7 @@ clean:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
rm -f *.o parse.cc parse.h lexor.cc
rm -f ivl.exp iverilog-vpi.man iverilog-vpi.pdf iverilog-vpi.ps
rm -f parse.output syn-rules.output dosify.exe ivl@EXEEXT@ check.vvp
rm -f parse.output syn-rules.output dosify$(BUILDEXT) ivl@EXEEXT@ check.vvp
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc
rm -rf dep
rm -f version.exe
@@ -174,7 +175,8 @@ endif
rm -rf autom4te.cache
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
--suppressions-list=$(srcdir)/cppcheck.sup \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
@@ -239,7 +241,7 @@ iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
endif
version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h
$(HOSTCC) $(HOSTCFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c
$(BUILDCC) $(CFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c
%.o: %.cc config.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
@@ -252,11 +254,9 @@ lexor.o: lexor.cc parse.h
parse.o: parse.cc
# Build this in two steps to avoid parallel build issues (see pr3462585)
parse.cc: $(srcdir)/parse.y
$(YACC) --verbose -t -p VL -d -o $@ $<
parse.h: parse.cc
mv parse.cc.h $@ 2>/dev/null || mv parse.hh $@
# Use pattern rules to avoid parallel build issues (see pr3462585)
parse%cc parse%h: $(srcdir)/parse%y
$(YACC) --verbose -t -p VL --defines=parse.h -o parse.cc $<
syn-rules.cc: $(srcdir)/syn-rules.y
$(YACC) --verbose -t -p syn_ -o $@ $<
@@ -305,66 +305,61 @@ version_tag.h version:
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = installman
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = installman
else
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = installpdf installman
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = installman
INSTALL_DOCDIR = $(mandir)/man1
endif
ifeq (@MINGW32@,yes)
WIN32_INSTALL =
else
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
WIN32_INSTALL = installwin32
endif
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/sv_vpi_user.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
install: all installdirs installfiles
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
F = ./ivl@EXEEXT@ \
$(srcdir)/constants.vams \
$(srcdir)/disciplines.vams \
$(srcdir)/ivl_target.h \
./_pli_types.h \
$(srcdir)/sv_vpi_user.h \
$(srcdir)/vpi_user.h \
$(srcdir)/acc_user.h \
$(srcdir)/veriuser.h \
$(INSTALL_DOC) \
$(WIN32_INSTALL)
installwin32: ./iverilog-vpi installdirs
$(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)"
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@"
$(libdir)/ivl$(suffix)/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams"
$(libdir)/ivl$(suffix)/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams"
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(includedir)/ivl_target.h"
$(includedir)/_pli_types.h: _pli_types.h
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_pli_types.h"
$(includedir)/sv_vpi_user.h: $(srcdir)/sv_vpi_user.h
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"
$(includedir)/acc_user.h: $(srcdir)/acc_user.h
$(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(includedir)/acc_user.h"
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(includedir)/veriuser.h"
$(mandir)/man1/iverilog-vpi$(suffix).1: iverilog-vpi.man
installman: iverilog-vpi.man installdirs
$(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1"
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
installpdf: iverilog-vpi.pdf installdirs
$(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf"
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@"
$(INSTALL_DATA) $(srcdir)/constants.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams"
$(INSTALL_DATA) $(srcdir)/disciplines.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams"
$(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(includedir)/ivl_target.h"
$(INSTALL_DATA) ./_pli_types.h "$(DESTDIR)$(includedir)/_pli_types.h"
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"
$(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(includedir)/acc_user.h"
$(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(includedir)/veriuser.h"
installdirs: $(srcdir)/mkinstalldirs
$(srcdir)/mkinstalldirs "$(DESTDIR)$(bindir)" \
+12 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -32,12 +32,9 @@ Module::Module(LexicalScope*parent, perm_string n)
{
library_flag = false;
is_cell = false;
is_interface = false;
program_block = false;
uc_drive = UCD_NONE;
timescale_warn_done = false;
time_unit = 0;
time_precision = 0;
time_from_timescale = false;
}
Module::~Module()
@@ -125,3 +122,13 @@ const list<PGate*>& Module::get_gates() const
{
return gates_;
}
PNamedItem::SymbolType Module::symbol_type() const
{
if (program_block)
return PROGRAM;
if (is_interface)
return INTERFACE;
return MODULE;
}
+6 -10
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,7 +28,7 @@
# include "HName.h"
# include "named.h"
# include "PScope.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "netlist.h"
# include "pform_types.h"
class PExpr;
@@ -54,7 +54,7 @@ class NetScope;
* these containers as well.
*/
class Module : public PScopeExtra, public LineInfo {
class Module : public PScopeExtra, public PNamedItem {
/* The module ports are in general a vector of port_t
objects. Each port has a name and an ordered list of
@@ -97,7 +97,7 @@ class Module : public PScopeExtra, public LineInfo {
/* specparams are simpler than other parameters, in that they
can have a range, but not an explicit type. The restrictions
are enforced by the parser. */
map<perm_string,param_expr_t>specparams;
map<perm_string,param_expr_t*>specparams;
/* The module also has defparam assignments which don't create
new parameters within the module, but may be used to set
@@ -121,12 +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
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
@@ -166,6 +160,8 @@ class Module : public PScopeExtra, public LineInfo {
bool elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
private:
void dump_specparams_(ostream&out, unsigned indent) const;
list<PGate*> gates_;
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 Stephen Williams ([email protected])
* Copyright (c) 2012-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,3 +28,8 @@ PClass::PClass(perm_string name, LexicalScope*parent)
PClass::~PClass()
{
}
PNamedItem::SymbolType PClass::symbol_type() const
{
return CLASS;
}
+5 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PClass_H
#define IVL_PClass_H
/*
* Copyright (c) 2012-2014 Stephen Williams ([email protected])
* Copyright (c) 2012-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,7 +20,7 @@
*/
# include "PScope.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <iostream>
@@ -32,7 +32,7 @@ class PChainConstructor;
* collected.
*/
class PClass : public PScopeExtra, public LineInfo {
class PClass : public PScopeExtra, public PNamedItem {
public:
explicit PClass (perm_string name, LexicalScope*parent);
@@ -40,6 +40,8 @@ class PClass : public PScopeExtra, public LineInfo {
void dump(std::ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
public:
class_type_t*type;
};
+2 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams ([email protected])
* Copyright (c) 1999-2017 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,11 +26,6 @@
# include "verinum.h"
# include "netmisc.h"
bool dly_used_no_timescale = false;
bool dly_used_timescale = false;
bool display_ts_dly_warning = true;
PDelays::PDelays()
{
delete_flag_ = true;
@@ -80,19 +75,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
+5 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 Stephen Williams ([email protected])
* Copyright (c) 2004-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -35,3 +35,7 @@ perm_string PEvent::name() const
return name_;
}
PNamedItem::SymbolType PEvent::symbol_type() const
{
return EVENT;
}
+5 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PEvent_H
#define IVL_PEvent_H
/*
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
* Copyright (c) 2000-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <string>
@@ -31,7 +31,7 @@ class NetScope;
* are declared in Verilog as ``event foo;'' The name passed to the
* constructor is the "foo" part of the declaration.
*/
class PEvent : public LineInfo {
class PEvent : public PNamedItem {
public:
// The name is a perm-allocated string. It is the simple name
@@ -43,6 +43,8 @@ class PEvent : public LineInfo {
void elaborate_scope(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
private:
perm_string name_;
+12 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2012 Stephen Williams <[email protected]>
* Copyright (c) 1998-2020 Stephen Williams <[email protected]>
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -126,9 +126,8 @@ PEBinary::~PEBinary()
void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
assert(left_ && right_);
left_->declare_implicit_nets(scope, type);
right_->declare_implicit_nets(scope, type);
if (left_) left_->declare_implicit_nets(scope, type);
if (right_) right_->declare_implicit_nets(scope, type);
}
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
@@ -137,7 +136,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)
{
}
@@ -169,7 +168,7 @@ PEBComp::~PEBComp()
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
assert(op == 'a' || op == 'o');
assert(op == 'a' || op == 'o' || op == 'q' || op == 'Q');
}
PEBLogic::~PEBLogic()
@@ -204,12 +203,12 @@ PEBShift::~PEBShift()
}
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
: package_(0), path_(n), parms_(parms)
: package_(0), path_(n), parms_(parms), is_overridden_(false)
{
}
PECallFunction::PECallFunction(PPackage*pkg, const pform_name_t&n, const vector<PExpr *> &parms)
: package_(pkg), path_(n), parms_(parms)
: package_(pkg), path_(n), parms_(parms), is_overridden_(false)
{
}
@@ -222,7 +221,7 @@ static pform_name_t pn_from_ps(perm_string n)
}
PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *> &parms)
: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size())
: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size()), is_overridden_(false)
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
@@ -232,18 +231,18 @@ PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *>
}
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
: package_(0), path_(pn_from_ps(n)), parms_(parms)
: package_(0), path_(pn_from_ps(n)), parms_(parms), is_overridden_(false)
{
}
PECallFunction::PECallFunction(perm_string n)
: package_(0), path_(pn_from_ps(n))
: package_(0), path_(pn_from_ps(n)), is_overridden_(false)
{
}
// NOTE: Anachronism. Try to work all use of svector out.
PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
: package_(0), path_(n), parms_(parms.size())
: package_(0), path_(n), parms_(parms.size()), is_overridden_(false)
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
@@ -253,7 +252,7 @@ PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
}
PECallFunction::PECallFunction(perm_string n, const list<PExpr*>&parms)
: package_(0), path_(pn_from_ps(n)), parms_(parms.size())
: package_(0), path_(pn_from_ps(n)), parms_(parms.size()), is_overridden_(false)
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
+12 -11
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PExpr_H
#define IVL_PExpr_H
/*
* Copyright (c) 1998-2014 Stephen Williams <[email protected]>
* Copyright (c) 1998-2019 Stephen Williams <[email protected]>
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -379,6 +379,8 @@ class PEIdent : public PExpr {
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
const PPackage* package() const { return package_; }
const pform_name_t& path() const { return path_; }
private:
@@ -433,10 +435,10 @@ class PEIdent : public PExpr {
bool need_const_idx) const;
NetAssign_*elaborate_lval_net_class_member_(Design*, NetScope*,
NetNet*,
const perm_string&) const;
pform_name_t) const;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const name_component_t&) const;
pform_name_t member_path) const;
bool elaborate_lval_darray_bit_(Design*, NetScope*,
NetAssign_*) const;
@@ -521,17 +523,13 @@ class PEIdent : public PExpr {
unsigned flags) const;
unsigned test_width_method_(Design*des, NetScope*scope, width_mode_t&mode);
NetExpr*elaborate_expr_method_(Design*des,
NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
NetAssign_*scan_lname_for_nested_members_(Design*des, NetScope*scope,
const pform_name_t&path) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
long&midx, long&lidx) const;
};
@@ -930,6 +928,9 @@ class PECallFunction : public PExpr {
pform_name_t path_;
std::vector<PExpr *> parms_;
// For system functions.
bool is_overridden_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
@@ -971,7 +972,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 +985,7 @@ class PECastSize : public PExpr {
width_mode_t&mode);
private:
unsigned size_;
PExpr* size_;
PExpr* base_;
};
+9 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2013 Stephen Williams ([email protected])
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -43,7 +43,7 @@ void PFunction::set_statement(Statement*s)
void PFunction::push_statement_front(Statement*stmt)
{
// This can only happen after the statement is initially set.
// This should not be possible.
ivl_assert(*this, statement_);
// Get the PBlock of the statement. If it is not a PBlock,
@@ -75,7 +75,8 @@ PChainConstructor* PFunction::extract_chain_constructor()
PChainConstructor*res = 0;
if ((res = dynamic_cast<PChainConstructor*> (statement_))) {
statement_ = 0;
statement_ = new PBlock(PBlock::BL_SEQ);
statement_->set_line(*this);
} else if (PBlock*blk = dynamic_cast<PBlock*>(statement_)) {
res = blk->extract_chain_constructor();
@@ -83,3 +84,8 @@ PChainConstructor* PFunction::extract_chain_constructor()
return res;
}
PNamedItem::SymbolType PFunction::symbol_type() const
{
return FUNCTION;
}
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2013 Stephen Williams ([email protected])
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -117,6 +117,11 @@ unsigned PGate::delay_count() const
return delay_.delay_count();
}
PNamedItem::SymbolType PGate::symbol_type() const
{
return INSTANCE;
}
PGAssign::PGAssign(list<PExpr*>*pins)
: PGate(perm_string(), pins)
{
+7 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PGate_H
#define IVL_PGate_H
/*
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,7 +22,7 @@
# include "svector.h"
# include "StringHeap.h"
# include "named.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "PDelays.h"
# include "netlist.h"
# include <map>
@@ -47,7 +47,7 @@ class Module;
* single strength pair. There is a strength of the 0 drive, and a
* strength of the 1 drive.
*/
class PGate : public LineInfo {
class PGate : public PNamedItem {
public:
explicit PGate(perm_string name, list<PExpr*>*pins,
@@ -88,6 +88,8 @@ class PGate : public LineInfo {
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
protected:
const vector<PExpr*>& get_pins() const { return pins_; }
@@ -217,6 +219,8 @@ class PGModule : public PGate {
// method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb);
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2011 Stephen Williams ([email protected])
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,6 +26,7 @@ PGenerate::PGenerate(LexicalScope*parent, unsigned id)
{
direct_nested_ = false;
scheme_type = GS_NONE;
local_index = false;
loop_init = 0;
loop_test = 0;
loop_step = 0;
@@ -112,3 +113,8 @@ ostream& operator << (ostream&out, PGenerate::scheme_t type)
}
return out;
}
PNamedItem::SymbolType PGenerate::symbol_type() const
{
return GENBLOCK;
}
+8 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PGenerate_H
#define IVL_PGenerate_H
/*
* Copyright (c) 2006-2014 Stephen Williams ([email protected])
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include "HName.h"
# include "PScope.h"
@@ -50,7 +50,7 @@ class PWire;
* The parent points to the GS_CASE that contains this item.
* the loop_test is compared with the parent->loop_test expression.
*/
class PGenerate : public LineInfo, public LexicalScope {
class PGenerate : public PNamedItem, public LexicalScope {
public:
explicit PGenerate(LexicalScope*parent, unsigned id_number);
@@ -71,6 +71,9 @@ class PGenerate : public LineInfo, public LexicalScope {
// generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>)
// the index is local if it was declared in the init expression,
// e.g. for (genvar index = <init>; <test>; index=<step>)
bool local_index;
perm_string loop_index;
PExpr*loop_init;
PExpr*loop_test;
@@ -107,6 +110,8 @@ class PGenerate : public LineInfo, public LexicalScope {
void dump(ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
private:
bool generate_scope_loop_(Design*des, NetScope*container);
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Stephen Williams ([email protected])
* Copyright (c) 2015-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -29,3 +29,8 @@ PModport::PModport(perm_string n)
PModport::~PModport()
{
}
PNamedItem::SymbolType PModport::symbol_type() const
{
return MODPORT;
}
+5 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PModport_H
#define IVL_PModport_H
/*
* Copyright (c) 2015 Stephen Williams ([email protected])
* Copyright (c) 2015-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "PScope.h"
# include "StringHeap.h"
# include "netlist.h"
@@ -28,7 +28,7 @@
/*
* The PModport class represents a parsed SystemVerilog modport list.
*/
class PModport : public LineInfo {
class PModport : public PNamedItem {
public:
// The name is a perm-allocated string. It is the simple name
@@ -41,6 +41,8 @@ class PModport : public LineInfo {
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
map<perm_string,simple_port_t> simple_ports;
SymbolType symbol_type() const;
private:
perm_string name_;
+116
View File
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2019 Martin Whitaker ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include <ostream>
PNamedItem::PNamedItem()
{
}
PNamedItem::~PNamedItem()
{
}
PNamedItem::SymbolType PNamedItem::symbol_type() const
{
return ANY;
}
std::ostream& operator << (std::ostream&o, PNamedItem::SymbolType st)
{
switch (st) {
case PNamedItem::ANY:
o << "a symbol";
break;
case PNamedItem::PARAM:
o << "a parameter";
break;
case PNamedItem::NET:
o << "a net";
break;
case PNamedItem::VAR:
o << "a variable";
break;
case PNamedItem::GENVAR:
o << "a genvar";
break;
case PNamedItem::EVENT:
o << "an event";
break;
case PNamedItem::TYPE:
o << "a type";
break;
case PNamedItem::ENUM:
o << "an enum type or value";
break;
case PNamedItem::CLASS:
o << "a class";
break;
case PNamedItem::FUNCTION:
o << "a function";
break;
case PNamedItem::TASK:
o << "a task";
break;
case PNamedItem::BLOCK:
o << "a named block";
break;
case PNamedItem::GENBLOCK:
o << "a generate block";
break;
case PNamedItem::MODPORT:
o << "a modport";
break;
case PNamedItem::PACKAGE:
o << "a package";
break;
case PNamedItem::MODULE:
o << "a module";
break;
case PNamedItem::PROGRAM:
o << "a program";
break;
case PNamedItem::INTERFACE:
o << "an interface";
break;
case PNamedItem::PRIMITIVE:
o << "a primitive";
break;
case PNamedItem::INSTANCE:
o << "an instance name";
break;
default:
break;
}
return o;
}
PGenvar::PGenvar()
{
}
PGenvar::~PGenvar()
{
}
PNamedItem::SymbolType PGenvar::symbol_type() const
{
return GENVAR;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef IVL_PNamedItem_H
#define IVL_PNamedItem_H
/*
* Copyright (c) 2019 Martin Whitaker ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
/*
* The PNamedItem class is the base class for all items that can be added
* to a scope's local symbol map.
*/
class PNamedItem : virtual public LineInfo {
public:
enum SymbolType { ANY, PARAM, NET, VAR, GENVAR, EVENT, TYPE, ENUM,
CLASS, FUNCTION, TASK, BLOCK, GENBLOCK, MODPORT,
PACKAGE, MODULE, PROGRAM, INTERFACE, PRIMITIVE,
INSTANCE };
explicit PNamedItem();
virtual ~PNamedItem();
virtual SymbolType symbol_type() const;
};
extern std::ostream& operator << (std::ostream&, PNamedItem::SymbolType);
/*
* The PGenvar class represents a genvar. This is only used to represent
* genvar in a scope's local symbol map.
*/
class PGenvar : public PNamedItem {
public:
explicit PGenvar();
virtual ~PGenvar();
SymbolType symbol_type() const;
};
#endif /* IVL_PNamedItem_H */
+26 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008,2010 Stephen Williams ([email protected])
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,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,34 @@ PWire* LexicalScope::wires_find(perm_string name)
return (*cur).second;
}
PNamedItem::SymbolType LexicalScope::param_expr_t::symbol_type() const
{
return PARAM;
}
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{
time_unit = 0;
time_precision = 0;
time_unit_is_default = true;
time_prec_is_default = true;
}
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(perm_string n)
: PScope(n)
{
time_unit_is_local = false;
time_prec_is_local = false;
}
PScopeExtra::~PScopeExtra()
{
}
+60 -15
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
@@ -36,6 +36,7 @@ class PProcess;
class PClass;
class PTask;
class PWire;
class Statement;
class Design;
class NetScope;
@@ -52,10 +53,32 @@ 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;
// Symbols that are defined or declared in this scope.
std::map<perm_string,PNamedItem*>local_symbols;
// Symbols that are explicitly imported. Bind the imported name
// to the package from which the name is imported.
std::map<perm_string,PPackage*>explicit_imports;
// Packages that are wildcard imported. When identifiers from
// these packages are referenced, they will be added to the
// explicit imports (IEEE 1800-2012 26.3).
std::set<PPackage*>potential_imports;
// A task or function call may reference a task or function defined
// later in the scope. So here we stash the potential imports for
// task and function calls. They will be added to the explicit
// imports if we don't find a local definition.
std::map<perm_string,PPackage*>possible_imports;
struct range_t {
// True if this is an exclude
bool exclude_flag;
@@ -74,7 +97,7 @@ class LexicalScope {
/* The scope has parameters that are evaluated when the scope
is elaborated. During parsing, I put the parameters into
this map. */
struct param_expr_t : public LineInfo {
struct param_expr_t : public PNamedItem {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
@@ -85,9 +108,11 @@ class LexicalScope {
PExpr*expr;
// If there are range constraints, list them here
range_t*range;
SymbolType symbol_type() const;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
map<perm_string,param_expr_t*>parameters;
map<perm_string,param_expr_t*>localparams;
// Defined types in the scope.
map<perm_string,data_type_t*>typedefs;
@@ -95,10 +120,6 @@ class LexicalScope {
// Named events in the scope.
map<perm_string,PEvent*>events;
// Symbols that are imported. Bind the imported name to the
// package from which the name is imported.
std::map<perm_string,PPackage*>imports;
// Nets and variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
@@ -108,6 +129,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 +141,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 +156,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 +175,24 @@ 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 value is
set by the `timescale directive or, in SystemVerilog,
by timeunit and timeprecision statements. */
int time_unit, time_precision;
/* Flags used to support warnings about timescales. */
bool time_unit_is_default;
bool time_prec_is_default;
bool has_explicit_timescale() const {
return !(time_unit_is_default || time_prec_is_default);
}
protected:
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
@@ -168,19 +210,22 @@ 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. */
std::vector<PClass*> classes_lexical;
/* Flags used to support warnings about timescales. */
bool time_unit_is_local;
bool time_prec_is_local;
protected:
void dump_classes_(ostream&out, unsigned indent) const;
void dump_tasks_(ostream&out, unsigned indent) const;
+11 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2008,2010 Stephen Williams ([email protected])
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -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);
@@ -68,3 +73,8 @@ void PTask::set_statement(Statement*s)
assert(statement_ == 0);
statement_ = s;
}
PNamedItem::SymbolType PTask::symbol_type() const
{
return TASK;
}
+9 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PTask_H
#define IVL_PTask_H
/*
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PScope.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <string>
# include <vector>
@@ -35,12 +35,14 @@ class Statement;
class PExpr;
class PTaskFunc : public PScope, public LineInfo {
class PTaskFunc : public PScope, public PNamedItem {
public:
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);
@@ -97,6 +99,8 @@ class PTask : public PTaskFunc {
void dump(ostream&, unsigned) const;
SymbolType symbol_type() const;
private:
Statement*statement_;
bool is_auto_;
@@ -146,6 +150,8 @@ class PFunction : public PTaskFunc {
void dump(ostream&, unsigned) const;
SymbolType symbol_type() const;
private:
data_type_t* return_type_;
Statement *statement_;
+15 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2012 Stephen Williams ([email protected])
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -29,7 +29,7 @@ PWire::PWire(perm_string n,
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), set_data_type_(0),
error_cnt_(0), uarray_type_(0), set_data_type_(0),
discipline_(0)
{
if (t == NetNet::INTEGER) {
@@ -67,6 +67,7 @@ bool PWire::set_wire_type(NetNet::Type t)
isint_ = true;
return true;
}
if (t == NetNet::IMPLICIT_REG) return true;
return false;
case NetNet::REG:
if (t == NetNet::INTEGER) {
@@ -282,3 +283,15 @@ ivl_discipline_t PWire::get_discipline(void) const
{
return discipline_;
}
PNamedItem::SymbolType PWire::symbol_type() const
{
switch (type_) {
case NetNet::IMPLICIT_REG:
case NetNet::INTEGER:
case NetNet::REG:
return VAR;
default:
return NET;
}
}
+7 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PWire_H
#define IVL_PWire_H
/*
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,7 +20,7 @@
*/
# include "netlist.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include <list>
# include <map>
# include "StringHeap.h"
@@ -51,7 +51,7 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
* from that perspective, sub-scopes within the module are a part of
* the wire name.
*/
class PWire : public LineInfo {
class PWire : public PNamedItem {
public:
PWire(perm_string name,
@@ -80,6 +80,7 @@ class PWire : public LineInfo {
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
void set_uarray_type(uarray_type_t*type) { uarray_type_ = type; }
void set_data_type(data_type_t*type);
@@ -93,6 +94,8 @@ class PWire : public LineInfo {
NetNet* elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
private:
perm_string name_;
NetNet::Type type_;
@@ -117,6 +120,7 @@ class PWire : public LineInfo {
// If this wire is actually a memory, these indices will give
// me the size and address ranges of the memory.
std::list<pform_range_t>unpacked_;
uarray_type_t*uarray_type_;
// This is the complex type of the wire. the data_type_ may
// modify how this is interpreted.
+49 -33
View File
@@ -1,12 +1,12 @@
THE ICARUS VERILOG COMPILATION SYSTEM
Copyright 2000-2004 Stephen Williams
Copyright 2000-2019 Stephen Williams
1.0 What is ICARUS Verilog?
Icarus Verilog is intended to compile ALL of the Verilog HDL as
described in the IEEE-1364 standard. Of course, it's not quite there
yet. It does currently handle a mix of structural and behavioral
yet. It does currently handle a mix of structural and behavioural
constructs. For a view of the current state of Icarus Verilog, see its
home page at <http://iverilog.icarus.com/>.
@@ -20,13 +20,13 @@ tools.
2.0 Building/Installing Icarus Verilog From Source
If you are starting from source, the build process is designed to be
If you are starting from the source, the build process is designed to be
as simple as practical. Someone basically familiar with the target
system and C/C++ compilation should be able to build the source
distribution with little effort. Some actual programming skills are
not required, but helpful in case of problems.
If you are building for Windows, see the mingw.txt file.
If you are building on Windows, see the mingw.txt file.
2.1 Compile Time Prerequisites
@@ -46,8 +46,12 @@ on a UNIX-like system:
to work. MSVC++ 5 and 6 are known to definitely *not* work.
- bison and flex
OSX note: bison 2.3 shipped with MacOS including Catalina generates
broken code, but bison 3+ works. We recommend using the Fink
project version of bison and flex (finkproject.org), brew version
works fine either.
- gperf 2.7
- gperf 3.0 or later
The lexical analyzer doesn't recognize keywords directly,
but instead matches symbols and looks them up in a hash
table in order to get the proper lexical code. The gperf
@@ -56,18 +60,18 @@ on a UNIX-like system:
A version problem with this program is the most common cause
of difficulty. See the Icarus Verilog FAQ.
- readline 4.2
- readline 4.2 or later
On Linux systems, this usually means the readline-devel
rpm. In any case, it is the development headers of readline
that are needed.
- termcap
The readline library in turn uses termcap.
The readline library, in turn, uses termcap.
If you are building from git, you will also need software to generate
the configure scripts.
- autoconf 2.53
- autoconf 2.53 or later
This generates configure scripts from configure.in. The 2.53
or later versions are known to work, autoconf 2.13 is
reported to *not* work.
@@ -75,15 +79,21 @@ the configure scripts.
2.2 Compilation
Unpack the tar-ball and cd into the verilog-######### directory
(presumably that is how you got to this README) and compile the source
(presumably, that is how you got to this README) and compile the source
with the commands:
./configure
make
If you are building from git, you have to run the command below before
compiling the source. This will generate the "configure" file, which is
automatically done when building from tarball.
sh autoconf.sh
Normally, this command automatically figures out everything it needs
to know. It generally works pretty well. There are a few flags to the
configure script that modify its behavior:
configure script that modify its behaviour:
--prefix=<root>
The default is /usr/local, which causes the tool suite to
@@ -106,6 +116,12 @@ configure script that modify its behavior:
with the same prefix but different suffix are guaranteed
to not interfere with each other.
--host=<host-type>
Compile iverilog for a different platform. You can use:
x64_64-w64-mingw32 for building 64-bit Windows executables
i686-w64-mingw32 for building 32-bit Windows executables
Both options require installing the required mingw-w64 packages.
2.3 (Optional) Testing
To run a simple test before installation, execute
@@ -155,7 +171,7 @@ output of the parse is a list of Module objects in "pform". The pform
step. There may be dangling references, and it is not yet clear which
module is the root.
One can see a human readable version of the final pform by using the
One can see a human-readable version of the final pform by using the
``-P <path>'' flag to the ``ivl'' subcommand. This will cause ivl
to dump the pform into the file named <path>. (Note that this is not
normally done, unless debugging the ``ivl'' subcommand.)
@@ -167,17 +183,17 @@ This phase takes the pform and generates a netlist. The driver selects
resolves references and expands the instantiations to form the design
netlist. (See netlist.txt.) Final semantic checks are performed during
elaboration, and some simple optimizations are performed. The netlist
includes all the behavioral descriptions, as well as gates and wires.
includes all the behavioural descriptions, as well as gates and wires.
The elaborate() function performs the elaboration.
One can see a human readable version of the final, elaborated and
One can see a human-readable version of the final, elaborated and
optimized netlist by using the ``-N <path>'' flag to the compiler. If
elaboration succeeds, the final netlist (i.e., after optimizations but
before code generation) will be dumped into the file named <path>.
Elaboration is actually performed in two steps: scopes and parameters
first, followed by the structural and behavioral elaboration.
Elaboration is performed in two steps: scopes and parameters
first, followed by the structural and behavioural elaboration.
3.3.1 Scope Elaboration
@@ -186,7 +202,7 @@ tree of NetScope objects is built up and placed in the Design object,
with the root module represented by the root NetScope object. The
elab_scope.cc file contains most of the code for handling this phase.
The tail of the elaborate_scope behavior (after the pform is
The tail of the elaborate_scope behaviour (after the pform is
traversed) includes a scan of the NetScope tree to locate defparam
assignments that were collected during scope elaboration. This is when
the defparam overrides are applied to the parameters.
@@ -195,14 +211,14 @@ the defparam overrides are applied to the parameters.
After the scopes and parameters are generated and the NetScope tree
fully formed, the elaboration runs through the pform again, this time
generating the structural and behavioral netlist. Parameters are
generating the structural and behavioural netlist. Parameters are
elaborated and evaluated by now so all the constants of code
generation are now known locally, so the netlist can be generated by
simply passing through the pform.
3.4 Optimization
This is actually a collection of processing steps that perform
This is a collection of processing steps that perform
optimizations that do not depend on the target technology. Examples of
some useful transformations are
@@ -220,7 +236,7 @@ generator (see target.h). This may require transforming the
design to suit the technology.
The emit() method of the Design class performs this step. It runs
through the design elements, calling target functions as need arises
through the design elements, calling target functions as the need arises
to generate actual output.
The user selects the target code generator with the -t flag on the
@@ -228,7 +244,7 @@ command line.
3.6 ATTRIBUTES
NOTE: The $attribute syntax will soon be deprecated in favor of the
NOTE: The $attribute syntax will soon be deprecated in favour of the
Verilog-2001 attribute syntax, which is cleaner and standardized.
The parser accepts, as an extension to Verilog, the $attribute module
@@ -251,7 +267,7 @@ Attributes can also be applied to gate types. When this is done, the
attribute is given to every instantiation of the primitive. The syntax
for the attribute statement is the same, except that the <identifier>
names a primitive earlier in the compilation unit and the statement is
placed in global scope, instead of within a module. The semicolon is
placed in the global scope, instead of within a module. The semicolon is
not part of a type attribute.
Note that attributes are also occasionally used for communication
@@ -310,7 +326,7 @@ by the compiler. See the iverilog(1) man page.
Icarus Verilog is in development - as such it still only supports a
(growing) subset of Verilog. Below is a description of some of the
currently unsupported Verilog features. This list is not exhaustive,
currently unsupported Verilog features. This list is not exhaustive
and does not account for errors in the compiler. See the Icarus
Verilog web page for the current state of support for Verilog, and in
particular, browse the bug report database for reported unsupported
@@ -339,7 +355,7 @@ constructs.
5.1 Nonstandard Constructs or Behaviors
Icarus Verilog includes some features that are not part of the
IEEE1364 standard, but have well defined meaning, and also sometimes
IEEE1364 standard, but have well-defined meaning, and also sometimes
gives nonstandard (but extended) meanings to some features of the
language that are defined. See the "extensions.txt" documentation for
more details.
@@ -356,7 +372,7 @@ more details.
function is undefined if the argument doesn't have a
self-determined size.
The $sizeof function is deprecated in favor of $bits, which is
The $sizeof function is deprecated in favour of $bits, which is
the same thing, but included in the SystemVerilog definition.
$simtime
@@ -382,8 +398,8 @@ more details.
Builtin system functions
Certain of the system functions have well defined meanings, so
can theoretically be evaluated at compile time, instead of
Certain of the system functions have well-defined meanings, so
can theoretically be evaluated at compile-time, instead of
using runtime VPI code. Doing so means that VPI cannot
override the definitions of functions handled in this
manner. On the other hand, this makes them synthesizable, and
@@ -402,8 +418,8 @@ more details.
Icarus Verilog does preprocess modules that are loaded from
libraries via the -y mechanism. However, the only macros
defined during compilation of that file are those that it
defines itself (or includes) or that are defined on the
defined during the compilation of that file are those that it
defines itself (or includes) or that are defined in the
command line or command file.
Specifically, macros defined in the non-library source files
@@ -420,7 +436,7 @@ more details.
Standard Verilog does not allow width fields in the %t formats
of display strings. For example, this is illegal:
$display("Time is %0t", %time);
$display("Time is %0t", $time);
Standard Verilog instead relies on the $timeformat to
completely specify the format.
@@ -444,7 +460,7 @@ more details.
time 0 race resolution.
Combinational logic is routinely modeled using always
Combinational logic is routinely modelled using always
blocks. However, this can lead to race conditions if the
inputs to the combinational block are initialized in initial
statements. Icarus Verilog slightly modifies time 0 scheduling
@@ -455,7 +471,7 @@ more details.
Nets with Types
Icarus Verilog support an extension syntax that allows nets
Icarus Verilog supports an extended syntax that allows nets
and regs to be explicitly typed. The currently supported types
are logic, bool and real. This implies that "logic" and "bool"
are new keywords. Typical syntax is:
@@ -472,6 +488,6 @@ more details.
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
Copyright Stephen Williams. The proper notices are in the head of each
file. However, I have early on received aid in the form of fixes,
Verilog guidance, and especially testing from many people. Testers in
particular include a larger community of people interested in a GPL
Verilog guidance, and especially testing from many people. Testers, in
particular, include a larger community of people interested in a GPL
Verilog for Linux.
+19 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2013 Stephen Williams ([email protected])
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -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())
@@ -153,6 +158,11 @@ void PBlock::push_statement_front(Statement*that)
list_[0] = that;
}
PNamedItem::SymbolType PBlock::symbol_type() const
{
return BLOCK;
}
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
: package_(0), path_(n), parms_(p.size())
{
@@ -196,8 +206,8 @@ const pform_name_t& PCallTask::path() const
return path_;
}
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: type_(t), expr_(ex), items_(l)
PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: quality_(q), type_(t), expr_(ex), items_(l)
{
}
@@ -289,20 +299,20 @@ PDoWhile::~PDoWhile()
}
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
: expr_(ee), statement_(0)
: expr_(ee), statement_(0), always_sens_(false)
{
assert(expr_.count() > 0);
}
PEventStatement::PEventStatement(PEEvent*ee)
: expr_(1), statement_(0)
: expr_(1), statement_(0), always_sens_(false)
{
expr_[0] = ee;
}
PEventStatement::PEventStatement(void)
: statement_(0)
PEventStatement::PEventStatement(bool always_sens)
: statement_(0), always_sens_(always_sens)
{
}
@@ -406,8 +416,8 @@ PReturn::~PReturn()
delete expr_;
}
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&e)
: package_(pkg), event_(e)
{
}
+24 -9
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Statement_H
#define IVL_Statement_H
/*
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -75,7 +75,7 @@ class PProcess : public LineInfo {
* fact, the Statement class is abstract and represents all the
* possible kinds of statements that exist in Verilog.
*/
class Statement : public LineInfo {
class Statement : virtual public LineInfo {
public:
Statement() { }
@@ -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*,
@@ -169,7 +170,7 @@ class PAssignNB : public PAssign_ {
* statements before constructing this object, so it knows a priori
* what is contained.
*/
class PBlock : public PScope, public Statement {
class PBlock : public PScope, public Statement, public PNamedItem {
public:
enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY };
@@ -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.
@@ -202,6 +205,8 @@ class PBlock : public PScope, public Statement {
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
private:
BL_TYPE bl_type_;
std::vector<Statement*>list_;
@@ -227,6 +232,8 @@ class PCallTask : public Statement {
NetProc*elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag = false) const;
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
NetFuncDef*def) const;
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const;
@@ -234,6 +241,10 @@ class PCallTask : public Statement {
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
PPackage*package_;
@@ -249,7 +260,7 @@ class PCase : public Statement {
Statement*stat;
};
PCase(NetCase::TYPE, PExpr*ex, svector<Item*>*);
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector<Item*>*);
~PCase();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@@ -258,6 +269,7 @@ class PCase : public Statement {
virtual void dump(ostream&out, unsigned ind) const;
private:
ivl_case_quality_t quality_;
NetCase::TYPE type_;
PExpr*expr_;
@@ -289,7 +301,7 @@ class PCAssign : public Statement {
*/
class PChainConstructor : public Statement {
public:
PChainConstructor(const list<PExpr*>&parms);
explicit PChainConstructor(const list<PExpr*>&parms);
~PChainConstructor();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@@ -399,8 +411,9 @@ class PEventStatement : public Statement {
explicit PEventStatement(const svector<PEEvent*>&ee);
explicit PEventStatement(PEEvent*ee);
// Make an @* statement.
explicit PEventStatement(void);
// Make an @* statement or make a special @* version with the items
// from functions added and outputs removed for always_comb/latch.
explicit PEventStatement(bool always_sens = false);
~PEventStatement();
@@ -426,6 +439,7 @@ class PEventStatement : public Statement {
private:
svector<PEEvent*>expr_;
Statement*statement_;
bool always_sens_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);
@@ -556,13 +570,14 @@ class PReturn : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(const pform_name_t&ev);
explicit PTrigger(PPackage*pkg, const pform_name_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PPackage*package_;
pform_name_t event_;
};
Vendored
+134 -3
View File
@@ -23,11 +23,13 @@ AC_SUBST(install_suffix)
# ------------------------------
# Sub-macro for AX_C_UNDERSCORES_LEADING and AX_C_UNDERSCORES_TRAILING.
# Unwarranted assumptions:
# - the object file produced by AC_COMPILE_IFELSE is called "conftest.$ac_objext"
# - the nm(1) utility is available, and its name is "nm".
# - the object file produced by AC_COMPILE_IFELSE is called
# "conftest.$ac_objext"
# - the nm(1) utility or an equivalent is available, and its name
# is defined by the $NM variable.
AC_DEFUN([_AX_C_UNDERSCORES_MATCH_IF],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([void underscore(void){}])],
[AS_IF([nm conftest.$ac_objext|grep $1 >/dev/null 2>/dev/null],[$2],[$3])],
[AS_IF([$NM conftest.$ac_objext|grep $1 >/dev/null 2>/dev/null],[$2],[$3])],
[AC_MSG_ERROR([underscore test crashed])]
)])
@@ -225,6 +227,8 @@ AC_DEFUN([AX_C99_STRTOD],
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
case "${host}" in
x86_64-w64-mingw32)
;;
*-*-mingw32)
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
;;
@@ -244,3 +248,130 @@ _config_header=$1
_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h
echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name
]) #_AC_AM_CONFIG_HEADER_HOOK
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_CC_FOR_BUILD
#
# DESCRIPTION
#
# This macro searches for a C compiler that generates native executables,
# that is a C compiler that surely is not a cross-compiler. This can be
# useful if you have to generate source code at compile-time like for
# example GCC does.
#
# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
# The value of these variables can be overridden by the user by specifying
# a compiler with an environment variable (like you do for standard CC).
#
# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
# substituted in the Makefile.
#
# LICENSE
#
# Copyright (c) 2008 Paolo Bonzini <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 8
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_CPP])dnl
AC_REQUIRE([AC_EXEEXT])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
dnl Use the standard macros, but make them use other variable names
dnl
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
pushdef([ac_exeext], ac_build_exeext)dnl
pushdef([ac_objext], ac_build_objext)dnl
pushdef([CC], CC_FOR_BUILD)dnl
pushdef([CPP], CPP_FOR_BUILD)dnl
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
pushdef([host], build)dnl
pushdef([host_alias], build_alias)dnl
pushdef([host_cpu], build_cpu)dnl
pushdef([host_vendor], build_vendor)dnl
pushdef([host_os], build_os)dnl
pushdef([ac_cv_host], ac_cv_build)dnl
pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
pushdef([ac_cpp], ac_build_cpp)dnl
pushdef([ac_compile], ac_build_compile)dnl
pushdef([ac_link], ac_build_link)dnl
save_cross_compiling=$cross_compiling
save_ac_tool_prefix=$ac_tool_prefix
cross_compiling=no
ac_tool_prefix=
AC_PROG_CC
AC_PROG_CPP
AC_EXEEXT
ac_tool_prefix=$save_ac_tool_prefix
cross_compiling=$save_cross_compiling
dnl Restore the old definitions
dnl
popdef([ac_link])dnl
popdef([ac_compile])dnl
popdef([ac_cpp])dnl
popdef([ac_cv_host_os])dnl
popdef([ac_cv_host_vendor])dnl
popdef([ac_cv_host_cpu])dnl
popdef([ac_cv_host_alias])dnl
popdef([ac_cv_host])dnl
popdef([host_os])dnl
popdef([host_vendor])dnl
popdef([host_cpu])dnl
popdef([host_alias])dnl
popdef([host])dnl
popdef([LDFLAGS])dnl
popdef([CPPFLAGS])dnl
popdef([CFLAGS])dnl
popdef([CPP])dnl
popdef([CC])dnl
popdef([ac_objext])dnl
popdef([ac_exeext])dnl
popdef([ac_cv_objext])dnl
popdef([ac_cv_exeext])dnl
popdef([ac_cv_prog_cc_g])dnl
popdef([ac_cv_prog_cc_cross])dnl
popdef([ac_cv_prog_cc_works])dnl
popdef([ac_cv_prog_gcc])dnl
popdef([ac_cv_prog_CPP])dnl
dnl Finally, set Makefile variables
dnl
BUILD_EXEEXT=$ac_build_exeext
BUILD_OBJEXT=$ac_build_objext
AC_SUBST(BUILD_EXEEXT)dnl
AC_SUBST(BUILD_OBJEXT)dnl
AC_SUBST([CFLAGS_FOR_BUILD])dnl
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
])
+7 -5
View File
@@ -59,7 +59,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=cadpli/$@
@@ -71,17 +71,19 @@ dep:
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $<
mv $*.d dep
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
SYSTEM_VPI_LDFLAGS = -L../vpi -lvpi
ifeq (@MINGW32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
cadpli.vpl: $O ../vvp/libvpi.a ../libveriuser/libveriuser.o
cadpli.vpl: $O ../vpi/libvpi.a ../libveriuser/libveriuser.o
$(CC) @shared@ $(LDFLAGS) -o $@ $O ../libveriuser/libveriuser.o $(SYSTEM_VPI_LDFLAGS)
install: all installdirs $(vpidir)/cadpli.vpl
install: all installdirs installfiles
$(vpidir)/cadpli.vpl: ./cadpli.vpl
F = ./cadpli.vpl
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./cadpli.vpl "$(DESTDIR)$(vpidir)/cadpli.vpl"
installdirs: $(srcdir)/../mkinstalldirs
+44 -19
View File
@@ -1,7 +1,7 @@
#ifndef IVL_compiler_H
#define IVL_compiler_H
/*
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -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;
@@ -100,6 +104,9 @@ extern bool warn_sens_entire_arr;
/* Warn about level-appropriate anachronisms. */
extern bool warn_anachronisms;
/* Warn about nets that are references but not driven. */
extern bool warn_floating_nets;
/* This is true if verbose output is requested. */
extern bool verbose_flag;
@@ -110,6 +117,13 @@ extern bool debug_emit;
extern bool debug_synth2;
extern bool debug_optimizer;
/* Ignore errors about missing modules */
extern bool ignore_missing_modules;
/* Treat each source file as a separate compilation unit (as defined
by SystemVerilog). */
extern bool separate_compilation;
/* Control evaluation of functions at compile time:
* 0 = only for functions in constant expressions
* 1 = only for automatic functions
@@ -138,7 +152,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,
@@ -162,9 +177,12 @@ extern bool gn_icarus_misc_flag;
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* If this flag is true, then elaborate assertions. If this flag is
false, then stub out assertion statements. */
extern bool gn_assertions_flag;
/* If this flag is true, then elaborate supported assertion statements. If
this flag is false, then stub out supported assertion statements. */
extern bool gn_supported_assertions_flag;
/* If this flag is true, then error on unsupported assertion statements. If
this flag is false, then stub out unsupported assertion statements. */
extern bool gn_unsupported_assertions_flag;
/* If this flag is true, then support/elaborate Verilog-AMS. */
extern bool gn_verilog_ams_flag;
@@ -182,25 +200,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)
@@ -269,12 +286,20 @@ struct sfunc_return_type {
const char* name;
ivl_variable_type_t type;
unsigned wid;
int signed_flag;
bool signed_flag;
bool override_flag;
};
extern void add_sys_func(const struct sfunc_return_type&ret_type);
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path);
extern void cleanup_sys_func_table();
/*
* This temporarily loads a VPI module, to determine the return values
* of system functions provided by that module, and adds the return values
* to the system function table.
*/
extern bool load_vpi_module(const char*path);
/*
* In system Verilog it is allowed with a warning to call a function
+2 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL_config_H /* -*- c++ -*- */
#define IVL_config_H
/*
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
* Copyright (c) 2001-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -55,6 +55,7 @@
# undef HAVE_FSEEKO
/* And this is needed by the fst files (copied from GTKWave). */
# undef HAVE_LIBPTHREAD
# undef HAVE_REALPATH
/*
* Define this if you want to compile vvp with memory freeing and
+14 -1
View File
@@ -54,6 +54,10 @@ then
exit 1
fi
if test "x$NM" = "x"; then
NM=nm
fi
AC_EXEEXT
AC_SUBST(EXEEXT)
@@ -135,7 +139,13 @@ AC_CHECK_SIZEOF(unsigned)
# vvp uses these...
AC_CHECK_LIB(termcap, tputs)
AC_CHECK_LIB(readline, readline)
AC_CHECK_LIB(readline, add_history, NEED_LIBHISTORY=no, NEED_LIBHISTORY=yes)
if test "$NEED_LIBHISTORY" = "yes"; then
AC_CHECK_LIB(history, add_history)
else
# libreadline includes libhistory functions
AC_DEFINE(HAVE_LIBHISTORY, 1)
fi
AC_CHECK_HEADERS(readline/readline.h readline/history.h sys/resource.h)
case "${host}" in *linux*) AC_DEFINE([LINUX], [1], [Host operating system is Linux.]) ;; esac
@@ -242,6 +252,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)
@@ -322,5 +335,5 @@ then
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
fi
AC_MSG_RESULT(ok)
AX_PROG_CC_FOR_BUILD
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile)
+618 -2
View File
@@ -1,3 +1,619 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:4976
thisSubtraction:netlist.h:4985
thisSubtraction:netlist.h:5126
thisSubtraction:netlist.h:5135
// These are the functions that the compiler exports to the targets.
//ivl_branch_island()
unusedFunction:t-dll-api.cc:39
//ivl_branch_terminal()
unusedFunction:t-dll-api.cc:45
//ivl_const_bits()
unusedFunction:t-dll-api.cc:196
//ivl_const_delay()
unusedFunction:t-dll-api.cc:214
//ivl_const_file()
unusedFunction:t-dll-api.cc:221
//ivl_const_lineno()
unusedFunction:t-dll-api.cc:227
//ivl_const_nex()
unusedFunction:t-dll-api.cc:233
//ivl_const_real()
unusedFunction:t-dll-api.cc:239
//ivl_const_scope()
unusedFunction:t-dll-api.cc:246
//ivl_const_signed()
unusedFunction:t-dll-api.cc:252
//ivl_const_type()
unusedFunction:t-dll-api.cc:190
//ivl_const_width()
unusedFunction:t-dll-api.cc:258
//ivl_design_const()
unusedFunction:t-dll-api.cc:127
//ivl_design_consts()
unusedFunction:t-dll-api.cc:121
//ivl_design_delay_sel()
unusedFunction:t-dll-api.cc:52
//ivl_design_discipline()
unusedFunction:t-dll-api.cc:140
//ivl_design_disciplines()
unusedFunction:t-dll-api.cc:134
//ivl_design_flag()
unusedFunction:t-dll-api.cc:59
//ivl_design_process()
unusedFunction:t-dll-api.cc:66
//ivl_design_root()
unusedFunction:t-dll-api.cc:80
//ivl_design_roots()
unusedFunction:t-dll-api.cc:89
//ivl_design_time_precision()
unusedFunction:t-dll-api.cc:115
//ivl_discipline_domain()
unusedFunction:t-dll-api.cc:147
//ivl_discipline_flow()
unusedFunction:t-dll-api.cc:153
//ivl_discipline_name()
unusedFunction:t-dll-api.cc:159
//ivl_discipline_potential()
unusedFunction:t-dll-api.cc:165
//ivl_enum_bits()
unusedFunction:t-dll-api.cc:277
//ivl_enum_file()
unusedFunction:t-dll-api.cc:302
//ivl_enum_lineno()
unusedFunction:t-dll-api.cc:308
//ivl_enum_name()
unusedFunction:t-dll-api.cc:270
//ivl_enum_names()
unusedFunction:t-dll-api.cc:264
//ivl_enum_signed()
unusedFunction:t-dll-api.cc:296
//ivl_enum_type()
unusedFunction:t-dll-api.cc:284
//ivl_enum_width()
unusedFunction:t-dll-api.cc:290
//ivl_event_any()
unusedFunction:t-dll-api.cc:369
//ivl_event_file()
unusedFunction:t-dll-api.cc:345
//ivl_event_lineno()
unusedFunction:t-dll-api.cc:351
//ivl_event_name()
unusedFunction:t-dll-api.cc:314
//ivl_event_nany()
unusedFunction:t-dll-api.cc:363
//ivl_event_neg()
unusedFunction:t-dll-api.cc:382
//ivl_event_nneg()
unusedFunction:t-dll-api.cc:376
//ivl_event_npos()
unusedFunction:t-dll-api.cc:389
//ivl_event_pos()
unusedFunction:t-dll-api.cc:395
//ivl_event_scope()
unusedFunction:t-dll-api.cc:357
//ivl_expr_bits()
unusedFunction:t-dll-api.cc:402
//ivl_expr_branch()
unusedFunction:t-dll-api.cc:409
//ivl_expr_def()
unusedFunction:t-dll-api.cc:416
//ivl_expr_delay_val()
unusedFunction:t-dll-api.cc:432
//ivl_expr_dvalue()
unusedFunction:t-dll-api.cc:439
//ivl_expr_enumtype()
unusedFunction:t-dll-api.cc:446
//ivl_expr_event()
unusedFunction:t-dll-api.cc:656
//ivl_expr_file()
unusedFunction:t-dll-api.cc:178
//ivl_expr_lineno()
unusedFunction:t-dll-api.cc:184
//ivl_expr_name()
unusedFunction:t-dll-api.cc:459
//ivl_expr_nature()
unusedFunction:t-dll-api.cc:483
//ivl_expr_net_type()
unusedFunction:t-dll-api.cc:453
//ivl_expr_opcode()
unusedFunction:t-dll-api.cc:490
//ivl_expr_oper1()
unusedFunction:t-dll-api.cc:506
//ivl_expr_oper2()
unusedFunction:t-dll-api.cc:544
//ivl_expr_oper3()
unusedFunction:t-dll-api.cc:570
//ivl_expr_parameter()
unusedFunction:t-dll-api.cc:584
//ivl_expr_parm()
unusedFunction:t-dll-api.cc:599
//ivl_expr_parms()
unusedFunction:t-dll-api.cc:626
//ivl_expr_repeat()
unusedFunction:t-dll-api.cc:649
//ivl_expr_scope()
unusedFunction:t-dll-api.cc:670
//ivl_expr_sel_type()
unusedFunction:t-dll-api.cc:677
//ivl_expr_signed()
unusedFunction:t-dll-api.cc:702
//ivl_expr_sized()
unusedFunction:t-dll-api.cc:708
//ivl_expr_string()
unusedFunction:t-dll-api.cc:714
//ivl_expr_type()
unusedFunction:t-dll-api.cc:171
//ivl_expr_uvalue()
unusedFunction:t-dll-api.cc:721
//ivl_expr_value()
unusedFunction:t-dll-api.cc:747
//ivl_expr_width()
unusedFunction:t-dll-api.cc:753
//ivl_file_table_index()
unusedFunction:t-dll-api.cc:795
//ivl_file_table_item()
unusedFunction:t-dll-api.cc:785
//ivl_file_table_size()
unusedFunction:t-dll-api.cc:813
//ivl_island_flag_set()
unusedFunction:t-dll-api.cc:822
//ivl_island_flag_test()
unusedFunction:t-dll-api.cc:837
//ivl_logic_attr()
unusedFunction:t-dll-api.cc:864
//ivl_logic_attr_cnt()
unusedFunction:t-dll-api.cc:880
//ivl_logic_attr_val()
unusedFunction:t-dll-api.cc:886
//ivl_logic_basename()
unusedFunction:t-dll-api.cc:935
//ivl_logic_delay()
unusedFunction:t-dll-api.cc:974
//ivl_logic_drive0()
unusedFunction:t-dll-api.cc:894
//ivl_logic_drive1()
unusedFunction:t-dll-api.cc:911
//ivl_logic_file()
unusedFunction:t-dll-api.cc:846
//ivl_logic_is_cassign()
unusedFunction:t-dll-api.cc:858
//ivl_logic_lineno()
unusedFunction:t-dll-api.cc:852
//ivl_logic_name()
unusedFunction:t-dll-api.cc:928
//ivl_logic_pins()
unusedFunction:t-dll-api.cc:953
//ivl_logic_scope()
unusedFunction:t-dll-api.cc:941
//ivl_logic_type()
unusedFunction:t-dll-api.cc:947
//ivl_logic_udp()
unusedFunction:t-dll-api.cc:966
//ivl_logic_width()
unusedFunction:t-dll-api.cc:981
//ivl_lpm_array()
unusedFunction:t-dll-api.cc:1109
//ivl_lpm_aset_value()
unusedFunction:t-dll-api.cc:1160
//ivl_lpm_async_clr()
unusedFunction:t-dll-api.cc:1054
//ivl_lpm_async_set()
unusedFunction:t-dll-api.cc:1085
//ivl_lpm_base()
unusedFunction:t-dll-api.cc:1121
//ivl_lpm_basename()
unusedFunction:t-dll-api.cc:1048
//ivl_lpm_clk()
unusedFunction:t-dll-api.cc:1148
//ivl_lpm_data()
unusedFunction:t-dll-api.cc:1221
//ivl_lpm_datab()
unusedFunction:t-dll-api.cc:1321
//ivl_lpm_define()
unusedFunction:t-dll-api.cc:1183
//ivl_lpm_delay()
unusedFunction:t-dll-api.cc:1078
//ivl_lpm_drive0()
unusedFunction:t-dll-api.cc:1453
//ivl_lpm_drive1()
unusedFunction:t-dll-api.cc:1470
//ivl_lpm_enable()
unusedFunction:t-dll-api.cc:1195
//ivl_lpm_file()
unusedFunction:t-dll-api.cc:1209
//ivl_lpm_lineno()
unusedFunction:t-dll-api.cc:1215
//ivl_lpm_name()
unusedFunction:t-dll-api.cc:1355
//ivl_lpm_negedge()
unusedFunction:t-dll-api.cc:1136
//ivl_lpm_select()
unusedFunction:t-dll-api.cc:1493
//ivl_lpm_selects()
unusedFunction:t-dll-api.cc:1510
//ivl_lpm_signed()
unusedFunction:t-dll-api.cc:1528
//ivl_lpm_size()
unusedFunction:t-dll-api.cc:1587
//ivl_lpm_sset_value()
unusedFunction:t-dll-api.cc:1171
//ivl_lpm_string()
unusedFunction:t-dll-api.cc:1640
//ivl_lpm_sync_clr()
unusedFunction:t-dll-api.cc:1066
//ivl_lpm_sync_set()
unusedFunction:t-dll-api.cc:1097
//ivl_lpm_trigger()
unusedFunction:t-dll-api.cc:1659
//ivl_lpm_type()
unusedFunction:t-dll-api.cc:1647
//ivl_lpm_width()
unusedFunction:t-dll-api.cc:1653
//ivl_lval_idx()
unusedFunction:t-dll-api.cc:1681
//ivl_lval_mux()
unusedFunction:t-dll-api.cc:1676
//ivl_lval_nest()
unusedFunction:t-dll-api.cc:1726
//ivl_lval_part_off()
unusedFunction:t-dll-api.cc:1690
//ivl_lval_property_idx()
unusedFunction:t-dll-api.cc:1708
//ivl_lval_sel_type()
unusedFunction:t-dll-api.cc:1696
//ivl_lval_sig()
unusedFunction:t-dll-api.cc:1714
//ivl_nature_name()
unusedFunction:t-dll-api.cc:1735
//ivl_nexus_get_private()
unusedFunction:t-dll-api.cc:1756
//ivl_nexus_name()
unusedFunction:t-dll-api.cc:1745
//ivl_nexus_ptr_branch()
unusedFunction:t-dll-api.cc:1799
//ivl_nexus_ptr_con()
unusedFunction:t-dll-api.cc:1808
//ivl_nexus_ptr_sig()
unusedFunction:t-dll-api.cc:1835
//ivl_nexus_ptr_switch()
unusedFunction:t-dll-api.cc:1844
//ivl_nexus_set_private()
unusedFunction:t-dll-api.cc:1762
//ivl_parameter_basename()
unusedFunction:t-dll-api.cc:1853
//ivl_parameter_expr()
unusedFunction:t-dll-api.cc:1896
//ivl_parameter_file()
unusedFunction:t-dll-api.cc:1902
//ivl_parameter_lineno()
unusedFunction:t-dll-api.cc:1908
//ivl_parameter_local()
unusedFunction:t-dll-api.cc:1859
//ivl_parameter_lsb()
unusedFunction:t-dll-api.cc:1877
//ivl_parameter_msb()
unusedFunction:t-dll-api.cc:1871
//ivl_parameter_scope()
unusedFunction:t-dll-api.cc:1914
//ivl_parameter_signed()
unusedFunction:t-dll-api.cc:1865
//ivl_parameter_width()
unusedFunction:t-dll-api.cc:1887
//ivl_path_condit()
unusedFunction:t-dll-api.cc:1920
//ivl_path_delay()
unusedFunction:t-dll-api.cc:1932
//ivl_path_is_condit()
unusedFunction:t-dll-api.cc:1926
//ivl_path_scope()
unusedFunction:t-dll-api.cc:1938
//ivl_path_source()
unusedFunction:t-dll-api.cc:1945
//ivl_path_source_negedge()
unusedFunction:t-dll-api.cc:1957
//ivl_path_source_posedge()
unusedFunction:t-dll-api.cc:1951
//ivl_process_analog()
unusedFunction:t-dll-api.cc:1981
//ivl_process_attr_cnt()
unusedFunction:t-dll-api.cc:1999
//ivl_process_attr_val()
unusedFunction:t-dll-api.cc:2005
//ivl_process_file()
unusedFunction:t-dll-api.cc:1963
//ivl_process_lineno()
unusedFunction:t-dll-api.cc:1969
//ivl_process_scope()
unusedFunction:t-dll-api.cc:1987
//ivl_process_stmt()
unusedFunction:t-dll-api.cc:1993
//ivl_process_type()
unusedFunction:t-dll-api.cc:1975
//ivl_scope_attr_cnt()
unusedFunction:t-dll-api.cc:2013
//ivl_scope_attr_val()
unusedFunction:t-dll-api.cc:2019
//ivl_scope_basename()
unusedFunction:t-dll-api.cc:2027
//ivl_scope_child()
unusedFunction:t-dll-api.cc:2054
//ivl_scope_children()
unusedFunction:t-dll-api.cc:2033
//ivl_scope_childs()
unusedFunction:t-dll-api.cc:2047
//ivl_scope_class()
unusedFunction:t-dll-api.cc:2061
//ivl_scope_classes()
unusedFunction:t-dll-api.cc:2068
//ivl_scope_def()
unusedFunction:t-dll-api.cc:2075
//ivl_scope_def_file()
unusedFunction:t-dll-api.cc:2081
//ivl_scope_def_lineno()
unusedFunction:t-dll-api.cc:2087
//ivl_scope_enumerate()
unusedFunction:t-dll-api.cc:2099
//ivl_scope_enumerates()
unusedFunction:t-dll-api.cc:2093
//ivl_scope_event()
unusedFunction:t-dll-api.cc:2112
//ivl_scope_events()
unusedFunction:t-dll-api.cc:2106
//ivl_scope_file()
unusedFunction:t-dll-api.cc:2119
//ivl_scope_func_signed
unusedFunction:t-dll-api.cc:2132
//ivl_scope_func_type
unusedFunction:t-dll-api.cc:2125
//ivl_scope_func_width
unusedFunction:t-dll-api.cc:2140
//ivl_scope_is_auto()
unusedFunction:t-dll-api.cc:2148
//ivl_scope_is_cell()
unusedFunction:t-dll-api.cc:2154
//ivl_scope_lineno()
unusedFunction:t-dll-api.cc:2160
//ivl_scope_log()
unusedFunction:t-dll-api.cc:2172
//ivl_scope_logs()
unusedFunction:t-dll-api.cc:2166
//ivl_scope_lpm()
unusedFunction:t-dll-api.cc:2185
//ivl_scope_lpms()
unusedFunction:t-dll-api.cc:2179
//ivl_scope_mod_module_port_name()
unusedFunction:t-dll-api.cc:2264
//ivl_scope_mod_module_port_type()
unusedFunction:t-dll-api.cc:2273
//ivl_scope_mod_module_port_width()
unusedFunction:t-dll-api.cc:2285
//ivl_scope_mod_module_ports()
unusedFunction:t-dll-api.cc:2257
//ivl_scope_mod_port()
unusedFunction:t-dll-api.cc:2310
//ivl_scope_param()
unusedFunction:t-dll-api.cc:2243
//ivl_scope_params()
unusedFunction:t-dll-api.cc:2237
//ivl_scope_parent()
unusedFunction:t-dll-api.cc:2250
//ivl_scope_port()
unusedFunction:t-dll-api.cc:2301
//ivl_scope_ports()
unusedFunction:t-dll-api.cc:2292
//ivl_scope_sig()
unusedFunction:t-dll-api.cc:2324
//ivl_scope_sigs()
unusedFunction:t-dll-api.cc:2318
//ivl_scope_switch()
unusedFunction:t-dll-api.cc:2337
//ivl_scope_switches()
unusedFunction:t-dll-api.cc:2331
//ivl_scope_time_precision()
unusedFunction:t-dll-api.cc:2344
//ivl_scope_time_units()
unusedFunction:t-dll-api.cc:2350
//ivl_scope_tname()
unusedFunction:t-dll-api.cc:2362
//ivl_scope_type()
unusedFunction:t-dll-api.cc:2356
//ivl_signal_array_addr_swapped()
unusedFunction:t-dll-api.cc:2380
//ivl_signal_array_base()
unusedFunction:t-dll-api.cc:2368
//ivl_signal_array_count()
unusedFunction:t-dll-api.cc:2374
//ivl_signal_attr()
unusedFunction:t-dll-api.cc:2398
//ivl_signal_attr_cnt()
unusedFunction:t-dll-api.cc:2414
//ivl_signal_attr_val()
unusedFunction:t-dll-api.cc:2420
//ivl_signal_basename()
unusedFunction:t-dll-api.cc:2427
//ivl_signal_data_type()
unusedFunction:t-dll-api.cc:2578
//ivl_signal_dimensions()
unusedFunction:t-dll-api.cc:2386
//ivl_signal_discipline()
unusedFunction:t-dll-api.cc:2392
//ivl_signal_file()
unusedFunction:t-dll-api.cc:2555
//ivl_signal_forced_net()
unusedFunction:t-dll-api.cc:2549
//ivl_signal_integer()
unusedFunction:t-dll-api.cc:2567
//ivl_signal_lineno()
unusedFunction:t-dll-api.cc:2561
//ivl_signal_local()
unusedFunction:t-dll-api.cc:2536
//ivl_signal_lsb()
unusedFunction:t-dll-api.cc:2501
//ivl_signal_module_port_index()
unusedFunction:t-dll-api.cc:2530
//ivl_signal_msb()
unusedFunction:t-dll-api.cc:2491
//ivl_signal_name()
unusedFunction:t-dll-api.cc:2433
//ivl_signal_nex()
unusedFunction:t-dll-api.cc:2454
//ivl_signal_npath()
unusedFunction:t-dll-api.cc:2591
//ivl_signal_packed_dimensions()
unusedFunction:t-dll-api.cc:2471
//ivl_signal_packed_lsb()
unusedFunction:t-dll-api.cc:2484
//ivl_signal_packed_msb()
unusedFunction:t-dll-api.cc:2477
//ivl_signal_path()
unusedFunction:t-dll-api.cc:2597
//ivl_signal_port()
unusedFunction:t-dll-api.cc:2524
//ivl_signal_scope()
unusedFunction:t-dll-api.cc:2511
//ivl_signal_signed()
unusedFunction:t-dll-api.cc:2542
//ivl_signal_width()
unusedFunction:t-dll-api.cc:2517
//ivl_statement_type()
unusedFunction:t-dll-api.cc:2610
//ivl_stmt_block_count()
unusedFunction:t-dll-api.cc:2643
//ivl_stmt_block_scope()
unusedFunction:t-dll-api.cc:2628
//ivl_stmt_block_stmt()
unusedFunction:t-dll-api.cc:2658
//ivl_stmt_call()
unusedFunction:t-dll-api.cc:2674
//ivl_stmt_case_count()
unusedFunction:t-dll-api.cc:2695
//ivl_stmt_case_expr()
unusedFunction:t-dll-api.cc:2710
//ivl_stmt_case_stmt()
unusedFunction:t-dll-api.cc:2727
//ivl_stmt_cond_expr()
unusedFunction:t-dll-api.cc:2744
//ivl_stmt_cond_false()
unusedFunction:t-dll-api.cc:2771
//ivl_stmt_cond_true()
unusedFunction:t-dll-api.cc:2781
//ivl_stmt_delay_expr()
unusedFunction:t-dll-api.cc:2791
//ivl_stmt_delay_val()
unusedFunction:t-dll-api.cc:2808
//ivl_stmt_events()
unusedFunction:t-dll-api.cc:2834
//ivl_stmt_file()
unusedFunction:t-dll-api.cc:2616
//ivl_stmt_lexp()
unusedFunction:t-dll-api.cc:2862
//ivl_stmt_lineno()
unusedFunction:t-dll-api.cc:2622
//ivl_stmt_lval()
unusedFunction:t-dll-api.cc:2874
//ivl_stmt_lvals()
unusedFunction:t-dll-api.cc:2893
//ivl_stmt_lwidth()
unusedFunction:t-dll-api.cc:2911
//ivl_stmt_name()
unusedFunction:t-dll-api.cc:2944
//ivl_stmt_nevent()
unusedFunction:t-dll-api.cc:2815
//ivl_stmt_opcode()
unusedFunction:t-dll-api.cc:2957
//ivl_stmt_parm()
unusedFunction:t-dll-api.cc:2969
//ivl_stmt_parm_count()
unusedFunction:t-dll-api.cc:2983
//ivl_stmt_rval()
unusedFunction:t-dll-api.cc:2995
//ivl_stmt_sfunc_as_task()
unusedFunction:t-dll-api.cc:3013
//ivl_stmt_sub_stmt()
unusedFunction:t-dll-api.cc:3026
//ivl_switch_a()
unusedFunction:t-dll-api.cc:3067
//ivl_switch_b()
unusedFunction:t-dll-api.cc:3073
//ivl_switch_basename()
unusedFunction:t-dll-api.cc:3049
//ivl_switch_delay()
unusedFunction:t-dll-api.cc:3103
//ivl_switch_enable()
unusedFunction:t-dll-api.cc:3079
//ivl_switch_file()
unusedFunction:t-dll-api.cc:3110
//ivl_switch_island()
unusedFunction:t-dll-api.cc:3116
//ivl_switch_lineno()
unusedFunction:t-dll-api.cc:3122
//ivl_switch_offset()
unusedFunction:t-dll-api.cc:3097
//ivl_switch_part()
unusedFunction:t-dll-api.cc:3091
//ivl_switch_scope()
unusedFunction:t-dll-api.cc:3055
//ivl_switch_type()
unusedFunction:t-dll-api.cc:3061
//ivl_switch_width()
unusedFunction:t-dll-api.cc:3085
//ivl_type_base()
unusedFunction:t-dll-api.cc:3128
//ivl_type_element()
unusedFunction:t-dll-api.cc:3134
//ivl_type_name()
unusedFunction:t-dll-api.cc:3166
//ivl_type_packed_dimensions()
unusedFunction:t-dll-api.cc:3143
//ivl_type_packed_lsb()
unusedFunction:t-dll-api.cc:3150
//ivl_type_packed_msb()
unusedFunction:t-dll-api.cc:3158
//ivl_type_prop_type()
unusedFunction:t-dll-api.cc:3191
//ivl_type_properties()
unusedFunction:t-dll-api.cc:3174
//ivl_type_signed()
unusedFunction:t-dll-api.cc:3199
//ivl_udp_file()
unusedFunction:t-dll-api.cc:1036
//ivl_udp_init()
unusedFunction:t-dll-api.cc:999
//ivl_udp_lineno()
unusedFunction:t-dll-api.cc:1042
//ivl_udp_name()
unusedFunction:t-dll-api.cc:1029
//ivl_udp_nin()
unusedFunction:t-dll-api.cc:993
//ivl_udp_port()
unusedFunction:t-dll-api.cc:1005
//ivl_udp_row()
unusedFunction:t-dll-api.cc:1014
//ivl_udp_rows()
unusedFunction:t-dll-api.cc:1023
// ivl_udp_sequ()
unusedFunction:t-dll-api.cc:987
+88 -23
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -187,9 +187,15 @@ ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
case NetCaseCmp::NEQ:
fd << "!==";
break;
case NetCaseCmp::XEQ:
case NetCaseCmp::WEQ:
fd << "==?";
break;
case NetCaseCmp::WNE:
fd << "!=?";
break;
case NetCaseCmp::XEQ:
fd << "==x?";
break;
case NetCaseCmp::ZEQ:
fd << "==z?";
break;
@@ -226,13 +232,15 @@ ostream& netdarray_t::debug_dump(ostream&o) const
ostream& netqueue_t::debug_dump(ostream&fd) const
{
fd << "queue of " << *element_type();
fd << "queue of ";
if (max_idx_ >= 0) fd << "(maximum of " << max_idx_+1 << " elements) ";
fd << *element_type();
return fd;
}
ostream& netvector_t::debug_dump(ostream&o) const
{
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
o << "netvector_t:" << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
return o;
}
@@ -344,6 +352,10 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
if (has_condit()) o << " if";
else o << " ifnone";
}
if (parallel_)
o << " parallel";
else
o << " full";
o << " src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
@@ -688,6 +700,14 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetLatch::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_LATCH: " << name()
<< " scope=" << scope_path(scope()) << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetLiteral::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant real " << real_
@@ -721,6 +741,12 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
case CMOS:
o << "cmos";
break;
case EQUIV:
o << "<->";
break;
case IMPL:
o << "->";
break;
case NAND:
o << "nand";
break;
@@ -976,6 +1002,18 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
o << "always /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_COMB:
o << "always_comb /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_FF:
o << "always_ff /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_LATCH:
o << "always_latch /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_FINAL:
o << "final /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
@@ -1003,6 +1041,13 @@ void NetAnalogTop::dump(ostream&o, unsigned ind) const
<< scope_path(scope_) << " */" << endl;
break;
// These are not used in an analog context.
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
assert(0);
break;
case IVL_PR_FINAL:
o << "analog final /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
@@ -1020,7 +1065,11 @@ void NetAlloc::dump(ostream&o, unsigned ind) const
void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) o << sig_->name();
else if (nest_) nest_->dump_lval(o);
else if (nest_) {
o << "(";
nest_->dump_lval(o);
o << ")";
}
else o << "<?>";
if (! member_.nil()) {
@@ -1113,15 +1162,29 @@ void NetBlock::dump(ostream&o, unsigned ind) const
void NetCase::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "";
switch (quality_) {
case IVL_CASE_QUALITY_BASIC:
break;
case IVL_CASE_QUALITY_UNIQUE:
o << "unique ";
break;
case IVL_CASE_QUALITY_UNIQUE0:
o << "unique0 ";
break;
case IVL_CASE_QUALITY_PRIORITY:
o << "priority ";
break;
}
switch (type_) {
case EQ:
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl;
o << "case (" << *expr_ << ")" << endl;
break;
case EQX:
o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl;
o << "casex (" << *expr_ << ")" << endl;
break;
case EQZ:
o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl;
o << "casez (" << *expr_ << ")" << endl;
break;
}
@@ -1382,6 +1445,8 @@ void NetScope::dump(ostream&o) const
if (is_interface()) o << " (interface)";
o << " " << children_.size() << " children, "
<< classes_.size() << " classes" << endl;
if (unit() && !is_unit())
o << " in compilation unit " << unit()->basename() << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
o << " (* " << attr_key(idx) << " = "
@@ -1621,11 +1686,14 @@ void NetEBinary::dump(ostream&o) const
case 'A':
o << "~&";
break;
case 'e':
o << "==";
break;
case 'E':
o << "===";
break;
case 'e':
o << "==";
case 'w':
o << "==?";
break;
case 'G':
o << ">=";
@@ -1642,6 +1710,9 @@ void NetEBinary::dump(ostream&o) const
case 'N':
o << "!==";
break;
case 'W':
o << "!=?";
break;
case 'o':
o << "||";
break;
@@ -1651,6 +1722,12 @@ void NetEBinary::dump(ostream&o) const
case 'p':
o << "**";
break;
case 'q':
o << "->";
break;
case 'Q':
o << "<->";
break;
case 'r':
o << ">>";
break;
@@ -1670,7 +1747,7 @@ void NetECast::dump(ostream&fd) const
{
if (op_=='2')
fd << "bool<" << expr_width() << ">(" << *expr_ << ")";
else if (op_=='4')
else if (op_=='v')
fd << "logic<" << expr_width() << ">(" << *expr_ << ")";
else
NetEUnary::dump(fd);
@@ -1894,18 +1971,6 @@ void Design::dump(ostream&o) const
cur->second->dump(o);
}
o << "$ROOT CLASSES:" << endl;
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
cur->second->dump_scope(o);
}
o << "$ROOT TASKS/FUNCTIONS:" << endl;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
cur->first->dump(o);
}
o << "SCOPES:" << endl;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope ) {
+1 -1
View File
@@ -19,7 +19,7 @@
/*
* This is a simple program to make a dosified copy of the
* original. That is, it converts unix style line ends to DOS
* original. That is, it converts Unix style line ends to DOS
* style. This is useful for installing text files.
*
* The exact substitution is to replace \n with \r\n. If the line
+14 -4
View File
@@ -36,6 +36,7 @@ mandir = @mandir@
dllib=@DLLIB@
CC = @CC@
HOSTCC := @CC@
WINDRES = @WINDRES@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -65,7 +66,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: main.c
cppcheck --enable=all -f $(INCLUDE_PATH) $^
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver-vpi/$@
@@ -86,17 +87,26 @@ 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
$(WINDRES) -i res.rc -o res.o
#
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
install: all installdirs installfiles
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
F = ./iverilog-vpi@EXEEXT@
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
ifeq (@WIN32@,yes)
ifneq ($(HOSTCC),$(CC))
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libwinpthread-1.dll) "$(DESTDIR)$(bindir)"
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libgcc_s_sjlj-1.dll) "$(DESTDIR)$(bindir)"
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libstdc++-6.dll) "$(DESTDIR)$(bindir)"
endif
endif
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(bindir)"
+16 -14
View File
@@ -67,7 +67,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f \
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
-UYY_USER_INIT \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
@@ -85,10 +85,9 @@ iverilog@EXEEXT@: $O
cflexor.c: $(srcdir)/cflexor.lex
$(LEX) -s -t $< > $@
# Build this in two steps to avoid parallel build issues (see pr3462585)
cfparse.c: $(srcdir)/cfparse.y
$(YACC) --verbose -t -p cf -d -o $@ $<
cfparse.h: cfparse.c
# Use pattern rules to avoid parallel build issues (see pr3462585)
cfparse%c cfparse%h: $(srcdir)/cfparse%y
$(YACC) --verbose -t -p cf -d -o cfparse.c $<
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
@@ -112,32 +111,35 @@ iverilog.pdf: iverilog.ps
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = installman
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = installman
else
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = installpdf installman
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = installman
INSTALL_DOCDIR = $(mandir)/man1
endif
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
install: all installdirs installfiles
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
F = ./iverilog@EXEEXT@ \
$(INSTALL_DOC)
$(mandir)/man1/iverilog$(suffix).1: iverilog.man
installman: iverilog.man installdirs
$(INSTALL_DATA) iverilog.man "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1"
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
installpdf: iverilog.pdf installdirs
$(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(prefix)/iverilog$(suffix).pdf"
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" "$(DESTDIR)$(INSTALL_DOCDIR)"
+7 -4
View File
@@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
* Copyright (c) 2001-2017 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,11 +22,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "cfparse.h"
# include "cfparse_misc.h"
# include "cfparse.h"
# include "globals.h"
# include <string.h>
char *current_file = NULL;
static int comment_enter;
static char* trim_trailing_white(char*txt, int trim);
@@ -124,7 +126,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. */
@@ -251,7 +254,7 @@ void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
+1 -1
View File
@@ -39,6 +39,6 @@ int cferror(const char *);
int cfparse(void);
void switch_to_command_file(const char *);
void destroy_lexor(void);
char *current_file;
extern char *current_file;
#endif /* IVL_cfparse_misc_H */
+124 -23
View File
@@ -1,14 +1,16 @@
.TH iverilog 1 "Aug 7th, 2015" "" "Version %M.%m.%n %E"
.TH iverilog 1 "Aug 10th, 2020" "" "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>]
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
[\-EiSuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value] [\-dname]
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
[\-Iincludedir] [\-Lmoduledir] [\-mmodule] [\-M[mode=]file] [\-Nfile]
[\-ooutputfilename] [\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass]
[\-ypath] [\-lfile]
sourcefile
.SH DESCRIPTION
.PP
@@ -30,7 +32,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.
@@ -79,6 +81,12 @@ use any of the new \fIIEEE1800\fP keywords.
Enable or disable (default) support for Verilog\-AMS.
Very little Verilog\-AMS specific functionality is currently supported.
.TP 8
.B -gassertions\fI|\fP-gsupported-assertions\fI|\fP-gno-assertions
Enable (default) or disable SystemVerilog assertions. When enabled,
assertion statements are elaborated. When disabled, assertion statements
are parsed but ignored. The \fB\-gsupported-assertions\fP option only
enables assertions that are currently supported by the compiler.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable or disable (default) specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
@@ -123,7 +131,7 @@ default, parts of the expression that do not depend on the changed
input value(s) are not re-evaluated. If an expression contains a call
to a function that doesn't depend solely on its input values or that
has side effects, the resulting behavior will differ from that
required by the standard. Using \fI\-gstrict\-ca\-eval\fP will force
required by the standard. Using \fB\-gstrict\-ca\-eval\fP will force
standard compliant behavior (with some loss in performance).
.TP 8
.B -gstrict-expr-width\fI|\fP-gno-strict-expr-width
@@ -133,12 +141,42 @@ 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 (default) or disable 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 -i
Ignore missing modules. Normally it is an error if a module instantiation
refers to an undefined module. This option causes the compiler to skip
over that instantiation. It will also stop the compiler returning an
error if there are no top level modules. This allows the compiler to be
used to check incomplete designs for errors.
.TP 8
.B -L\fIpath\fP
This flag adds a directory to the path list used to locate VPI
modules. The default path includes only the install directory for the
system.vpi module, but this flag can add other directories. Multiple
paths are allowed, and the paths will be searched in order.
.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.
@@ -159,9 +197,13 @@ prefixed by "I " and other files are prefixed by "M ".
.B -m\fImodule\fP
Add this module to the list of VPI modules to be loaded by the
simulation. Many modules can be specified, and all will be loaded, in
the order specified. The system module is implicit and always included.
If a System Function Table file (<module>.sft) exists for the module it
will be loaded automatically.
the order specified. The system module is implicit and always included
(and loaded last).
If the specified name includes at least one directory character, it is
assumed to be prefixed by the path to the module, otherwise the module
is searched for in the paths specified by preceding \fB-L\fP options,
and if not found there, in the \fIiverilog\fP base directory.
.TP 8
.B -N\fIpath\fP
This is used for debugging the compiler proper. Dump the final netlist
@@ -204,6 +246,12 @@ will suppress the warning that the compiler is making a choice.
Use this switch to specify the target output format. See the
\fBTARGETS\fP section below for a list of valid output formats.
.TP 8
.B -u
Treat each source file as a separate compilation unit (as defined in
SystemVerilog). If compiling for an \fIIEEE1364\fP generation, this
will just reset all compiler directives (including macro definitions)
before each new file is processed.
.TP 8
.B -v
Turn on verbose messages. This will print the command lines that are
executed to perform the actual compilation, along with version
@@ -246,7 +294,7 @@ that contain Verilog source files. During elaboration, the compiler
notices the instantiation of undefined module types. If the user
specifies library search directories, the compiler will search the
directory for files with the name of the missing module type. If it
finds such a file, it loads it as a Verilog source file, they tries
finds such a file, it loads it as a Verilog source file, then tries
again to elaborate the module.
Library module files should contain only a single module, but this is
@@ -269,7 +317,10 @@ This is the default. The vvp target generates code for the vvp
runtime. The output is a complete program that simulates the design
but must be run by the \fBvvp\fP command. The -pfileline=1 option
can be used to add procedural statement debugging opcodes to the
generated code.
generated code. These opcodes are also used to generate file and
line information for procedural warning/error messages. To enable
the debug command tracing us the trace command (trace on) from
the vvp interactive prompt.
.TP 8
.B fpga
This is a synthesis target that supports a variety of fpga devices,
@@ -292,8 +343,9 @@ after a \fB\-Wall\fP argument to suppress isolated warning types.
.TP 8
.B all
This enables the anachronisms, implicit, portbind, select\-range,
timescale, and sensitivity\-entire\-array warning categories.
This enables the anachronisms, implicit, macro-replacement, portbind,
select\-range, timescale, and sensitivity\-entire\-array warning
categories.
.TP 8
.B anachronisms
@@ -306,6 +358,13 @@ This enables warnings for creation of implicit declarations. For
example, if a scalar wire X is used but not declared in the Verilog
source, this will print a warning at its first use.
.TP 8
.B macro-redefinition\fI | \fPmacro-replacement
This enables preprocessor warnings when a macro is being redefined.
The first variant prints a warning any time a macro is redefined.
The second variant only prints a warning if the macro text changes.
Use \fBno-macro-redefinition\fP to turn off all warnings of this type.
.TP 8
.B portbind
This enables warnings for ports of module instantiations that are not
@@ -357,13 +416,23 @@ sensitivity list. Although this behaviour is prescribed by the IEEE
standard, it is not what might be expected and can have performance
implications if the array is large.
.SH "SYSTEM FUNCTION TABLE FILES"
If the source file name as a \fB.sft\fP suffix, then it is taken to be
a system function table file. A System function table file is used to
describe to the compiler the return types for system functions. This
.SH "VPI MODULES"
If the source file name has a \fB.vpi\fP or \fB.vpl\fP suffix, then it
is taken to be a VPI module. VPI modules supplied by the user are scanned
to determine the return types of any system functions they provide. This
is necessary because the compiler needs this information to elaborate
expressions that contain these system functions, but cannot run the
sizetf functions since it has no run-time.
expressions that contain these system functions. The module path/name is
passed on to the target to allow the VPI module to be automatically loaded
at the start of simulation.
VPI modules may also be supplied using the \fB-L\fP and \fB-m\fP options.
.SH "SYSTEM FUNCTION TABLE FILES [deprecated]"
If the source file name has a \fB.sft\fP suffix, then it is taken to be a
system function table file. A system function table file is the old method
used to describe to the compiler the return types for system functions.
Users are encouraged to switch to the new method of simply supplying the
VPI module.
The format of the table is ASCII, one function per line. Empty lines
are ignored, and lines that start with the '\fI#\fP' character are
@@ -384,6 +453,11 @@ The function returns an integer.
The function returns a vector with the given width, and is signed or
unsigned according to the flag.
.TP 8
.B vpiSysFuncString
The function returns a string. This is an Icarus-specific extension, not
available in the VPI standard.
.SH "COMMAND FILES"
The command file allows the user to place source file names and
certain command line switches into a text file instead of on a long
@@ -402,6 +476,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,
@@ -422,7 +505,7 @@ Variables in the \fIincludedir\fP are substituted.
.TP 8
.B +libext+\fIext\fP
The \fB+libext\fP token in command files fives file extensions to try
The \fB+libext\fP token in command files lists file extensions to try
when looking for a library file. This is useful in conjunction with
\fB\-y\fP flags to list suffixes to try in each directory before moving
on to the next library directory.
@@ -503,6 +586,24 @@ This is always defined when compiling with Icarus Verilog.
.B __VAMS_ENABLE__ = 1
This is defined if Verilog\-AMS is enabled.
.SH ENVIRONMENT
.PP
\fIiverilog\fP also accepts some environment variables that control
its behavior. These can be used to make semi-permanent changes.
.TP 8
.B IVERILOG_ICONFIG=\fIfile-name\fP
This sets the name used for the temporary file that passes parameters
to the compiler proper, and prevents that file being deleted after the
compiler has exited.
.TP 8
.B IVERILOG_VPI_MODULE_PATH=\fI/some/path:/some/other/path\fP
This adds additional components to the VPI module search path. Paths
specified in this way are searched after paths specified with \fB-L\fP,
but before the default search path. Multiple paths can be separated with
colons (semicolons if using Windows).
.SH EXAMPLES
These examples assume that you have a Verilog source file called hello.v in
the current directory
@@ -532,7 +633,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\-2020 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+358 -98
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 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,13 +38,13 @@ const char NOTICE[] =
;
const char HELP[] =
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]\n"
"Usage: iverilog [-EiSuvV] [-B base] [-c cmdfile|-f cmdfile]\n"
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g<feature>]\n"
" [-D macro[=defn]] [-I includedir]\n"
" [-D macro[=defn]] [-I includedir] [-L moduledir]\n"
" [-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.";
@@ -99,13 +99,16 @@ extern const char*optarg;
#ifdef __MINGW32__
const char sep = '\\';
const char path_sep = ';';
#else
const char sep = '/';
const char path_sep = ':';
#endif
extern void cfreset(FILE*fd, const char*path);
const char*base = 0;
const char*vpi_dir = 0;
const char*ivlpp_dir = 0;
const char*vhdlpp_dir= 0;
const char*vhdlpp_work = 0;
@@ -128,6 +131,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 = "shared-loop-index";
const char*gen_verilog_ams = "no-verilog-ams";
/* Boolean: true means use a default include dir, false means don't */
@@ -137,7 +141,12 @@ int gen_std_include = 1;
of the include list. */
int gen_relative_include = 0;
char warning_flags[16] = "n";
char warning_flags[17] = "n";
int separate_compilation_flag = 0;
/* Boolean: true means ignore errors about missing modules */
int ignore_missing_modules = 0;
unsigned integer_width = 32;
@@ -163,6 +172,12 @@ char*compiled_defines_path = 0;
static char iconfig_common_path[4096] = "";
static const char**vpi_path_list = 0;
static unsigned vpi_path_list_size = 0;
static const char**env_vpi_path_list = 0;
static unsigned env_vpi_path_list_size = 0;
int synth_flag = 0;
int verbose_flag = 0;
@@ -340,10 +355,15 @@ static int t_version_only(void)
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\" ",
ivlpp_dir, sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
ivlpp_dir, sep,
verbose_flag ? " -v" : "",
e_flag ? "" : " -L",
strchr(warning_flags, 'r') ? " -Wredef-all " :
strchr(warning_flags, 'R') ? " -Wredef-chg " : "",
defines_path, source_path,
compiled_defines_path,
e_flag ? "" : " | ");
}
static int t_preprocess_only(void)
@@ -406,8 +426,12 @@ static int t_compile(void)
{
unsigned rc;
/* Start by building the preprocess command line. */
build_preprocess_command(0);
/* Start by building the preprocess command line, if required.
This pipes into the main ivl command. */
if (!separate_compilation_flag)
build_preprocess_command(0);
else
strcpy(tmp, "");
size_t ncmd = strlen(tmp);
char*cmd = malloc(ncmd + 1);
@@ -417,8 +441,8 @@ static int t_compile(void)
int rtn;
#endif
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s%civl", base, sep);
/* Build the ivl command. */
snprintf(tmp, sizeof tmp, "%s%civl", base, sep);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@@ -446,7 +470,16 @@ static int t_compile(void)
strcpy(cmd+ncmd, tmp);
ncmd += rc;
snprintf(tmp, sizeof tmp, " -C\"%s\" -- -", iconfig_common_path);
snprintf(tmp, sizeof tmp, " -C\"%s\"", iconfig_common_path);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
ncmd += rc;
if (separate_compilation_flag)
snprintf(tmp, sizeof tmp, " -F\"%s\"", source_path);
else
snprintf(tmp, sizeof tmp, " -- -");
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@@ -496,6 +529,8 @@ 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("macro-replacement");
process_warning_switch("portbind");
process_warning_switch("select-range");
process_warning_switch("timescale");
@@ -503,9 +538,21 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"anachronisms") == 0) {
if (! strchr(warning_flags, 'n'))
strcat(warning_flags, "n");
} else if (strcmp(name,"floating-nets") == 0) {
if (! strchr(warning_flags, 'f'))
strcat(warning_flags, "f");
} 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,"macro-redefinition") == 0) {
if (! strchr(warning_flags, 'r'))
strcat(warning_flags, "r");
} else if (strcmp(name,"macro-replacement") == 0) {
if (! strchr(warning_flags, 'R'))
strcat(warning_flags, "R");
} else if (strcmp(name,"portbind") == 0) {
if (! strchr(warning_flags, 'p'))
strcat(warning_flags, "p");
@@ -532,12 +579,35 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-floating-nets") == 0) {
char*cp = strchr(warning_flags, 'f');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-implicit") == 0) {
char*cp = strchr(warning_flags, 'i');
if (cp) while (*cp) {
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-macro-redefinition") == 0) {
char*cp = strchr(warning_flags, 'r');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
cp = strchr(warning_flags, 'R');
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) {
@@ -612,14 +682,19 @@ void process_timescale(const char*ts_string)
/*
* This function is called while processing a file name in a command
* file, or a file name on the command line. Look to see if there is a
* .sft suffix, and if so pass that as a sys_func file. Otherwise, it
* is a Verilog source file to be written into the file list.
* .sft or .vpi suffix, and if so pass that as a sys_func or module
* file. Otherwise, it is a Verilog source file to be written into the
* file list.
*/
void process_file_name(const char*name, int lib_flag)
{
if (strlen(name) > 4 && strcasecmp(".sft", name+strlen(name)-4) == 0) {
fprintf(stderr, "SFT files are deprecated. Please pass the VPI module instead.\n");
fprintf(iconfig_file,"sys_func:%s\n", name);
} else if (strlen(name) > 4 && strcasecmp(".vpi", name+strlen(name)-4) == 0) {
fprintf(iconfig_file,"module:%s\n", name);
} else {
fprintf(source_file, "%s\n", name);
source_count += 1;
@@ -687,6 +762,9 @@ static int process_generation(const char*name)
else if (strcmp(name,"assertions") == 0)
gen_assertions = "assertions";
else if (strcmp(name,"supported-assertions") == 0)
gen_assertions = "supported-assertions";
else if (strcmp(name,"no-assertions") == 0)
gen_assertions = "no-assertions";
@@ -720,6 +798,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";
@@ -737,6 +821,7 @@ static int process_generation(const char*name)
" 2009 -- IEEE1800-2009\n"
" 2012 -- IEEE1800-2012\n"
"Other generation flags:\n"
" assertions | supported-assertions | no-assertions\n"
" specify | no-specify\n"
" verilog-ams | no-verilog-ams\n"
" std-include | no-std-include\n"
@@ -745,7 +830,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;
}
@@ -784,18 +870,217 @@ static int process_depfile(const char*name)
return 0;
}
/*
* If it exists add the SFT file for the given module.
*/
static void add_sft_file(const char *module)
static void add_env_vpi_module_path(const char*path)
{
char *file;
env_vpi_path_list_size += 1;
env_vpi_path_list = (const char**)realloc(env_vpi_path_list,
env_vpi_path_list_size*sizeof(char*));
env_vpi_path_list[env_vpi_path_list_size-1] = path;
}
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
sprintf(file, "%s%c%s.sft", base, sep, module);
if (access(file, R_OK) == 0)
fprintf(iconfig_file, "sys_func:%s\n", file);
free(file);
static void get_env_vpi_module_paths(void)
{
char *var = getenv("IVERILOG_VPI_MODULE_PATH");
char *ptr, *end;
if (!var)
return;
var = strdup(var);
#ifdef __MINGW32__
convert_to_MS_path(var);
#endif
ptr = var;
end = var+strlen(var);
int len = 0;
while (ptr <= end) {
if (*ptr == 0 || *ptr == path_sep) {
*ptr = 0;
if (len > 0) {
add_env_vpi_module_path(var);
}
len = 0;
var = ptr+1;
} else {
len++;
}
ptr++;
}
}
static void add_vpi_module_path(const char*path)
{
#ifdef __MINGW32__
char*tmp_path = strdup(path);
convert_to_MS_path(tmp_path);
path = tmp_path;
#endif
vpi_path_list_size += 1;
vpi_path_list = (const char**)realloc(vpi_path_list,
vpi_path_list_size*sizeof(char*));
vpi_path_list[vpi_path_list_size-1] = path;
}
static int probe_for_vpi_module(const char*base_path, const char*name,
char*path, unsigned path_size)
{
snprintf(path, path_size, "%s%c%s.vpi", base_path, sep, name);
if (access(path, R_OK) == 0)
return 1;
snprintf(path, path_size, "%s%c%s.vpl", base_path, sep, name);
if (access(path, R_OK) == 0)
return 1;
return 0;
}
/*
* If it exists add the VPI file for the given module.
*/
static void add_vpi_file(const char *name)
{
const char*base_dir = vpi_dir ? vpi_dir : base;
char path[4096];
#ifdef __MINGW32__
char*tmp_name = strdup(name);
convert_to_MS_path(tmp_name);
name = tmp_name;
#endif
int found = 0;
if (strchr(name, sep)) {
/* If the name has at least one directory character in it
then assume it is a complete name, maybe including any
possible .vpi or .vpl suffix. */
found = access(name, R_OK) == 0;
if (!found) {
snprintf(path, sizeof(path), "%s.vpi", name);
found = access(path, R_OK) == 0;
if (!found) {
snprintf(path, sizeof(path), "%s.vpl", name);
found = access(path, R_OK) == 0;
}
} else {
strncpy(path, name, sizeof(path) - 1);
}
} else {
for (unsigned idx = 0; !found && (idx < vpi_path_list_size); idx += 1) {
found = probe_for_vpi_module(vpi_path_list[idx], name,
path, sizeof(path));
}
for (unsigned idx = 0; !found && (idx < env_vpi_path_list_size); idx += 1) {
found = probe_for_vpi_module(env_vpi_path_list[idx], name,
path, sizeof(path));
}
if (!found) {
found = probe_for_vpi_module(base_dir, name,
path, sizeof(path));
}
}
if (found) {
fprintf(iconfig_file, "module:%s\n", path);
} else {
fprintf(stderr, "Unable to find VPI module '%s'\n", name);
}
#ifdef __MINGW32__
free(tmp_name);
#endif
}
static void find_ivl_root_failed(const char *reason)
{
fprintf(stderr, "Cannot locate IVL modules : %s\n", reason);
exit(1);
}
static void find_ivl_root(void)
{
#ifdef __MINGW32__
const char *ivl_lib_prefix = "\\lib";
const char *ivl_lib_suffix = "\\ivl" IVL_SUFFIX;
#else
const char *ivl_lib_prefix = IVL_LIB;
const char *ivl_lib_suffix = "/ivl" IVL_SUFFIX;
#endif
ssize_t len = 0;
char *s;
#ifndef __MINGW32__
/* First try the location specified in the build process. */
if (access(IVL_ROOT, F_OK) != -1) {
assert(strlen(IVL_ROOT) < sizeof ivl_root);
strcpy(ivl_root, IVL_ROOT);
return;
}
#endif
/* If that fails, calculate the ivl_root from the path to the
command. This is always necessary on Windows because of the
installation process, but may also be necessary on other OSs
if the package has been relocated.
On Windows we know the command path is formed like this:
$(prefix)\bin\iverilog.exe
The module path in a Windows installation is the path:
$(prefix)\lib\ivl$(suffix)
so we chop the file name and the last directory by
turning the last two \ characters to null. Then we append
the lib\ivl$(suffix) to finish.
On other OSs, we expect the command path to be:
$(prefix)/bin/iverilog
and the module path to be:
$(prefix)/$(lib)/ivl$(suffix)
so we extract the $(prefix) from the command location as for
Windows and the $(lib) from IVL_LIB. This will of course fail
if the user has overridden $(bindir) or $(libdir), but there's
not a lot we can do in that case.
*/
#ifdef __MINGW32__
char tmppath[MAXSIZE];
len = GetModuleFileName(NULL, tmppath, sizeof tmppath);
if (len >= (ssize_t) sizeof ivl_root) {
find_ivl_root_failed("command path exceeds size of string buffer.");
}
/* Convert to a short name to remove any embedded spaces. */
len = GetShortPathName(tmppath, ivl_root, sizeof ivl_root);
#else
len = readlink("/proc/self/exe", ivl_root, sizeof ivl_root);
#endif
if (len >= (ssize_t) sizeof ivl_root) {
find_ivl_root_failed("command path exceeds size of string buffer.");
}
if (len <= 0) {
find_ivl_root_failed("couldn't get command path from OS.");
}
s = strrchr(ivl_root, sep);
if (s == 0) {
find_ivl_root_failed("missing first separator in command path.");
}
*s = 0;
s = strrchr(ivl_root, sep);
if (s == 0) {
find_ivl_root_failed("missing second separator in command path.");
}
*s = 0;
len = s - ivl_root;
s = strrchr(ivl_lib_prefix, sep);
assert(s);
if (len + strlen(s) + strlen(ivl_lib_suffix) >= (ssize_t) sizeof ivl_root) {
find_ivl_root_failed("module path exceeds size of string buffer.");
}
strcat(ivl_root, s);
strcat(ivl_root, ivl_lib_suffix);
}
int main(int argc, char **argv)
@@ -804,51 +1089,10 @@ int main(int argc, char **argv)
int version_flag = 0;
int opt;
#ifdef __MINGW32__
/* Calculate the ivl_root from the path to the command. This
is necessary because of the installation process on
Windows. Mostly, it is those darn drive letters, but oh
well. We know the command path is formed like this:
D:\iverilog\bin\iverilog.exe
The module path in a Windows installation is the path:
D:\iverilog\lib\ivl$(suffix)
so we chop the file name and the last directory by
turning the last two \ characters to null. Then we append
the lib\ivl$(suffix) to finish. */
char *s;
char tmppath[MAXSIZE];
GetModuleFileName(NULL, tmppath, sizeof tmppath);
/* Convert to a short name to remove any embedded spaces. */
GetShortPathName(tmppath, ivl_root, sizeof ivl_root);
s = strrchr(ivl_root, sep);
if (s) *s = 0;
else {
fprintf(stderr, "%s: Missing first %c in exe path!\n",
argv[0], sep);
exit(1);
}
s = strrchr(ivl_root, sep);
if (s) *s = 0;
else {
fprintf(stderr, "%s: Missing second %c in exe path!\n",
argv[0], sep);
exit(1);
}
strcat(ivl_root, "\\lib\\ivl" IVL_SUFFIX);
find_ivl_root();
base = ivl_root;
#else
/* In a UNIX environment, the IVL_ROOT from the Makefile is
dependable. It points to the $prefix/lib/ivl directory,
where the sub-parts are installed. */
strcpy(ivl_root, IVL_ROOT);
base = ivl_root;
#endif
get_env_vpi_module_paths();
/* Create a temporary file for communicating input parameters
to the preprocessor. */
@@ -910,7 +1154,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:iL:M:m:N:o:P:p:Ss:T:t:uvVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@@ -919,6 +1163,9 @@ int main(int argc, char **argv)
character of the path indicates which path the
user is specifying. */
switch (optarg[0]) {
case 'M': /* Path for the VPI modules */
vpi_dir = optarg+1;
break;
case 'P': /* Path for the ivlpp preprocessor */
ivlpp_dir = optarg+1;
break;
@@ -965,14 +1212,25 @@ int main(int argc, char **argv)
process_include_dir(optarg);
break;
case 'i':
ignore_missing_modules = 1;
break;
case 'L':
add_vpi_module_path(optarg);
break;
case 'l':
process_file_name(optarg, 1);
break;
case 'M':
if (process_depfile(optarg) != 0)
return -1;
break;
case 'm':
fprintf(iconfig_file, "module:%s\n", optarg);
add_sft_file(optarg);
add_vpi_file(optarg);
break;
case 'N':
@@ -1005,6 +1263,9 @@ int main(int argc, char **argv)
case 't':
targ = optarg;
break;
case 'u':
separate_compilation_flag = 1;
break;
case 'v':
verbose_flag = 1;
break;
@@ -1040,6 +1301,8 @@ int main(int argc, char **argv)
}
}
if (vpi_dir == 0)
vpi_dir = base;
if (ivlpp_dir == 0)
ivlpp_dir = base;
if (vhdlpp_dir == 0)
@@ -1047,19 +1310,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-2020 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" : "");
@@ -1067,11 +1321,10 @@ int main(int argc, char **argv)
/* Write values to the iconfig file. */
fprintf(iconfig_file, "basedir:%s\n", base);
/* Tell the core where to find the system.sft. This file
describes the system functions so that elaboration knows
how to handle them. */
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
fprintf(iconfig_file, "sys_func:%s%cvhdl_sys.sft\n", base, sep);
/* Tell the core where to find the system VPI modules. */
fprintf(iconfig_file, "module:%s%csystem.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "module:%s%cvhdl_sys.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "module:%s%cvhdl_textio.vpi\n", vpi_dir, sep);
/* If verilog-2005/09/12 is enabled or icarus-misc or verilog-ams,
* then include the v2005_math library. */
@@ -1080,23 +1333,20 @@ int main(int argc, char **argv)
strcmp(generation, "2012") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0 ||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
fprintf(iconfig_file, "module:v2005_math\n");
fprintf(iconfig_file, "module:%s%cv2005_math.vpi\n", vpi_dir, sep);
}
/* If verilog-ams or icarus_misc is enabled, then include the
* va_math module as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0) {
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
fprintf(iconfig_file, "module:va_math\n");
fprintf(iconfig_file, "module:%s%cva_math.vpi\n", vpi_dir, sep);
}
/* If verilog-2009 (SystemVerilog) is enabled, then include the
v2009 module. */
if (strcmp(generation, "2005-sv") == 0 ||
strcmp(generation, "2009") == 0 ||
strcmp(generation, "2012") == 0) {
fprintf(iconfig_file, "sys_func:%s%cv2009.sft\n", base, sep);
fprintf(iconfig_file, "module:v2009\n");
fprintf(iconfig_file, "module:%s%cv2009.vpi\n", vpi_dir, sep);
}
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
@@ -1107,9 +1357,11 @@ 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);
fprintf(iconfig_file, "ignore_missing_modules:%s\n", ignore_missing_modules ? "true" : "false");
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) {
fprintf(iconfig_file, "depfile:%s\n", depfile);
@@ -1186,8 +1438,12 @@ int main(int argc, char **argv)
will append to the file, so this is necessary to make sure
it starts out empty. */
if (depfile) {
FILE*fd = fopen(depfile, "w");
fclose(fd);
FILE *fd = fopen(depfile, "w");
if (!fd) {
fprintf(stderr, "%s: can't open %s file.\n\n%s\n", argv[0], depfile, HELP);
return 1;
}
fclose(fd);
}
if (source_count == 0 && !version_flag) {
@@ -1202,8 +1458,12 @@ int main(int argc, char **argv)
/* Write the preprocessor command needed to preprocess a
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\"\n",
ivlpp_dir, sep, defines_path, compiled_defines_path);
fprintf(iconfig_file, "ivlpp:%s%civlpp %s -L -F\"%s\" -P\"%s\"\n",
ivlpp_dir, sep,
strchr(warning_flags, 'r') ? "-Wredef-all" :
strchr(warning_flags, 'R') ? "-Wredef-chg" : "",
defines_path, compiled_defines_path
);
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2019 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
@@ -233,7 +233,7 @@ NetESelect* NetESelect::dup_expr() const
NetESFunc* NetESFunc::dup_expr() const
{
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms());
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms(), is_overridden_);
ivl_assert(*this, tmp);
tmp->cast_signed(has_sign());
+787 -400
View File
File diff suppressed because it is too large Load Diff
+457 -240
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -29,6 +29,7 @@
# include "netdarray.h"
# include "netparray.h"
# include "netvector.h"
# include "netenum.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
@@ -75,15 +76,8 @@
*/
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const
{
NetNet*ll = 0;
if (ll == 0) {
cerr << get_fileline() << ": Assignment l-value too complex."
<< endl;
return 0;
}
NetAssign_*lv = new NetAssign_(ll);
return lv;
cerr << get_fileline() << ": Assignment l-value too complex." << endl;
return 0;
}
/*
@@ -138,6 +132,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)
@@ -150,57 +147,6 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
return res;
}
NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
const pform_name_t&cur_path) const
{
if (cur_path.size() == 1)
return 0;
pform_name_t use_path = cur_path;
name_component_t tail = use_path.back();
use_path.pop_back();
NetNet* reg = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(this, des, scope, use_path, reg, par, eve);
if (reg == 0) {
NetAssign_*tmp = scan_lname_for_nested_members_(des, scope, use_path);
if (tmp == 0)
return 0;
tmp = new NetAssign_(tmp);
tmp->set_property(tail.name);
return tmp;
}
if (reg->struct_type() && reg->struct_type()->packed()) {
NetAssign_*tmp = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, scope, tmp, tail);
return tmp;
}
#if 0
if (reg->struct_type() && reg->struct_type()->packed()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with packed struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
#endif
if (reg->struct_type() && !reg->struct_type()->packed()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with unpacked struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
if (reg->class_type()) {
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
}
return 0;
}
/*
* Handle the ident as an l-value. This includes bit and part selects
@@ -214,7 +160,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
NetNet* reg = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
perm_string method_name;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
@@ -235,35 +180,31 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
ivl_assert(*this, use_scope);
}
symbol_search(this, des, use_scope, path_, reg, par, eve);
/* If the signal is not found, check to see if this is a
member of a struct. Take the name of the form "a.b.member",
remove the member and store it into method_name, and retry
the search with "a.b". */
if (reg == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
perm_string tmp_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, use_scope, use_path, reg, par, eve);
if (reg && reg->struct_type()) {
method_name = tmp_name;
} else if (reg && reg->class_type()) {
method_name = tmp_name;
} else if (NetAssign_*subl = scan_lname_for_nested_members_(des, use_scope, path_)) {
return subl;
} else {
reg = 0;
}
/* Try to find the base part of the path that names the
variable. The remainer is the member path. For example, if
the path is a.b.c.d, and a.b is the path to a variable,
then a.b becomes the base_path and c.d becomes the
member_path. If we cannot find the variable with any
prefix, then the base_path will be empty after this loop
and reg will remain nil. */
pform_name_t base_path = path_;
pform_name_t member_path;
while (reg == 0 && base_path.size() > 0) {
symbol_search(this, des, use_scope, base_path, reg, par, eve);
// Found it!
if (reg != 0) break;
// Not found. Try to pop another name off the base_path
// and push it to the front of the member_path.
member_path.push_front( base_path.back() );
base_path.pop_back();
}
/* The l-value must be a variable. If not, then give up and
print a useful error message. */
if (reg == 0) {
if (use_scope->type()==NetScope::FUNC
&& use_scope->func_def()->return_sig()==0
&& use_scope->func_def()->is_void()
&& use_scope->basename()==peek_tail_name(path_)) {
cerr << get_fileline() << ": error: "
<< "Cannot assign to " << path_
@@ -282,18 +223,21 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
<< "Found l-value as reg."
<< "Found l-value path_=" << path_
<< " as reg=" << reg->name()
<< " base_path=" << base_path
<< ", member_path=" << member_path
<< " unpacked_dimensions()=" << reg->unpacked_dimensions() << endl;
}
// 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
@@ -328,21 +272,27 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
if (reg->struct_type() && !method_name.nil()) {
// If we find that the matched variable is a packed struct,
// then we can handled it with the net_packed_member_ method.
if (reg->struct_type() && member_path.size() > 0) {
NetAssign_*lv = new NetAssign_(reg);
name_component_t tmp_name (method_name);
elaborate_lval_net_packed_member_(des, use_scope, lv, tmp_name);
elaborate_lval_net_packed_member_(des, use_scope, lv, member_path);
return lv;
}
if (reg->class_type() && !method_name.nil() && gn_system_verilog()) {
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, method_name);
// If the variable is a class object, then handle it with the
// net_class_member_ method.
if (reg->class_type() && member_path.size() > 0 && gn_system_verilog()) {
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, member_path);
return lv;
}
// Past this point, we should have taken care of the cases
// where the name is a member/method of a struct/class.
ivl_assert(*this, method_name.nil());
// XXXX ivl_assert(*this, method_name.nil());
ivl_assert(*this, member_path.size() == 0);
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
@@ -399,6 +349,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
/* No select expressions. */
NetAssign_*lv = new NetAssign_(reg);
lv->set_signed(reg->get_signed());
return lv;
}
@@ -408,7 +359,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
{
if (!gn_system_verilog())
return 0;
if (scope->parent() == 0)
if (scope->parent() == 0 || scope->type() == NetScope::CLASS)
return 0;
if (path_.size() != 1)
return 0;
@@ -427,7 +378,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
NetScope*scope_method = find_method_containing_scope(*this, scope);
ivl_assert(*this, scope_method);
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
if (this_net == 0) {
cerr << get_fileline() << ": internal error: "
<< "Unable to find 'this' port of " << scope_path(scope_method)
@@ -687,20 +638,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 +752,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 +821,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 +890,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;
@@ -1061,87 +1017,140 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
return true;
}
/*
* When the l-value turns out to be a class object, this method is
* called with the bound variable, and the method path. For example,
* if path_=a.b.c and a.b binds to the variable, then sig is b, and
* member_path=c. if path_=obj.base.x, and base_path=obj, then sig is
* obj, and member_path=base.x.
*/
NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope,
NetNet*sig, const perm_string&method_name) const
NetNet*sig, pform_name_t member_path) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": elaborate_lval_net_class_member_: "
<< "l-value is property " << method_name
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_class_member_: "
<< "l-value is property " << member_path
<< " of " << sig->name() << "." << endl;
}
const netclass_t*class_type = sig->class_type();
ivl_assert(*this, class_type);
/* Make sure the property is really present in the class. If
not, then generate an error message and return an error. */
int pidx = class_type->property_idx_from_name(method_name);
if (pidx < 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
des->errors += 1;
return 0;
}
// Iterate over the member_path. This handles nested class
// object, by generating nested NetAssign_ object. We start
// with lv==0, so the front of the member_path is the member
// of the outermost class. This generates an lv from sig. Then
// iterate over the remaining of the member_path, replacing
// the outer lv with an lv that nests the lv from the previous
// iteration.
NetAssign_*lv = 0;
do {
// Start with the first component of the member path...
perm_string method_name = peek_head_name(member_path);
// Pull that component from the member_path. We need to
// know the current member being worked on, and will
// need to know if there are more members to be worked on.
name_component_t member_cur = member_path.front();
member_path.pop_front();
property_qualifier_t qual = class_type->get_prop_qual(pidx);
if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
cerr << get_fileline() << ": error: "
<< "Local property " << class_type->get_prop_name(pidx)
<< " is not accessible (l-value) in this context."
<< " (scope=" << scope_path(scope) << ")" << endl;
des->errors += 1;
} else if (qual.test_static()) {
// Special case: this is a static property. Ignore the
// "this" sig and use the property itself, which is not
// part of the sig, as the l-value.
NetNet*psig = class_type->find_static_property(method_name);
ivl_assert(*this, psig);
NetAssign_*lv = new NetAssign_(psig);
return lv;
} else if (qual.test_const()) {
cerr << get_fileline() << ": error: "
<< "Property " << class_type->get_prop_name(pidx)
<< " is constant in this context." << endl;
des->errors += 1;
}
NetAssign_*lv = new NetAssign_(sig);
lv->set_property(method_name);
ivl_type_t ptype = class_type->get_prop_type(pidx);
const netdarray_t*mtype = dynamic_cast<const netdarray_t*> (ptype);
if (mtype) {
const name_component_t&name_tail = path_.back();
if (! name_tail.index.empty()) {
cerr << get_fileline() << ": sorry: "
<< "Array index of array properties not supported."
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_class_member_: "
<< "Processing member_cur=" << member_cur
<< endl;
}
// Make sure the property is really present in the class. If
// not, then generate an error message and return an error.
int pidx = class_type->property_idx_from_name(method_name);
if (pidx < 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
des->errors += 1;
return 0;
}
property_qualifier_t qual = class_type->get_prop_qual(pidx);
if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
cerr << get_fileline() << ": error: "
<< "Local property " << class_type->get_prop_name(pidx)
<< " is not accessible (l-value) in this context."
<< " (scope=" << scope_path(scope) << ")" << endl;
des->errors += 1;
} else if (qual.test_static()) {
// Special case: this is a static property. Ignore the
// "this" sig and use the property itself, which is not
// part of the sig, as the l-value.
NetNet*psig = class_type->find_static_property(method_name);
ivl_assert(*this, psig);
lv = new NetAssign_(psig);
return lv;
} else if (qual.test_const()) {
cerr << get_fileline() << ": error: "
<< "Property " << class_type->get_prop_name(pidx)
<< " is constant in this context." << endl;
des->errors += 1;
}
}
lv = lv? new NetAssign_(lv) : new NetAssign_(sig);
lv->set_property(method_name);
// Now get the type of the property.
ivl_type_t ptype = class_type->get_prop_type(pidx);
const netdarray_t*mtype = dynamic_cast<const netdarray_t*> (ptype);
if (mtype) {
if (! member_cur.index.empty()) {
cerr << get_fileline() << ": sorry: "
<< "Array index of array properties not supported."
<< endl;
des->errors += 1;
}
}
// If the current member is a class object, then get the
// type. We may wind up iterating, and need the proper
// class type.
class_type = dynamic_cast<const netclass_t*>(ptype);
} while (member_path.size() > 0);
return lv;
}
/*
* This method is caled to handle l-value identifiers that are packed
* structs. The lv is already attached to the variable, so this method
* calculates the part select that is defined by the member_path. For
* example, if the path_ is main.sub.sub_local, and the variable is
* main, then we know at this point that main is a packed struct, and
* lv contains the reference to the bound variable (main). In this
* case member_path==sub.sub_local, and it is up to this method to
* work out the part select that the member_path represents.
*/
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetAssign_*lv,
const name_component_t&member_comp) const
pform_name_t member_path) const
{
const perm_string&member_name = member_comp.name;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "path_=" << path_
<< " member_path=" << member_path
<< endl;
}
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
const netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: elaborate lval packed member: "
<< "path_=" << path_ << endl;
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Type=" << *struct_type
<< endl;
}
if (! struct_type->packed()) {
@@ -1151,94 +1160,302 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
return false;
}
// Shouldn't be seeing unpacked arrays of packed structs...
ivl_assert(*this, reg->unpacked_dimensions() == 0);
// This is a packed member, so the name is of the form
// "a.b[...].c[...]" which means that the path_ must have at
// least 2 components. We are processing "c[...]" at that
// point (otherwise known as member_name) so we'll save a
// reference to it in name_tail. We are also processing "b[]"
// so save that as name_base.
ivl_assert(*this, path_.size() >= 2);
// Looking for the base name. We need that to know about
// indices we may need to apply. This is to handle the case
// that the base is an array of structs, and not just a
// struct.
pform_name_t::const_reverse_iterator name_idx = path_.rbegin();
ivl_assert(*this, name_idx->name == member_name);
const name_component_t&name_tail = *name_idx;
++ name_idx;
const name_component_t&name_base = *name_idx;
// Calculate the offset within the packed structure of the
// member, and any indices. We will add in the offset of the
// struct into the packed array later. Note that this works
// for packed unions as well (although the offset will be 0
// for union members).
unsigned long off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
if (member == 0) {
cerr << get_fileline() << ": error: Member " << member_name
<< " is not a member of variable " << reg->name() << endl;
for (size_t idx = 1 ; idx < member_path.size() ; idx += 1)
++ name_idx;
if (name_idx->name != peek_head_name(member_path)) {
cerr << get_fileline() << ": internal error: "
<< "name_idx=" << name_idx->name
<< ", expecting member_name=" << peek_head_name(member_path)
<< endl;
des->errors += 1;
return false;
}
ivl_assert(*this, name_idx->name == peek_head_name(member_path));
++ name_idx;
const name_component_t&name_base = *name_idx;
unsigned long use_width = member->net_type->packed_width();
// Shouldn't be seeing unpacked arrays of packed structs...
ivl_assert(*this, reg->unpacked_dimensions() == 0);
// Get the index component type. At this point, we only
// support bit select or none.
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
// These make up the "part" select that is the equivilent of
// following the member path through the nested structs. To
// start with, the off[set] is zero, and use_width is the
// width of the entire variable. The first member_comp is at
// some offset within the variable, and will have a reduced
// width. As we step through the member_path the off
// increases, and use_width shrinks.
unsigned long off = 0;
unsigned long use_width = struct_type->packed_width();
ivl_assert(*this, use_sel == index_component_t::SEL_NONE || use_sel == index_component_t::SEL_BIT);
pform_name_t completed_path;
do {
const name_component_t member_comp = member_path.front();
const perm_string&member_name = member_comp.name;
if (! name_tail.index.empty()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Processing member_comp=" << member_comp
<< " (completed_path=" << completed_path << ")"
<< endl;
}
// If there are index expressions in this l-value
// expression, then the implicit assumption is that the
// member is a vector type with packed dimensions. For
// example, if the l-value expression is "foo.member[1][2]",
// then the member should be something like:
// ... logic [h:l][m:n] foo;
// Get the dimensions from the netvector_t that this implies.
const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type);
ivl_assert(*this, mem_vec);
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
// This is a packed member, so the name is of the form
// "a.b[...].c[...]" which means that the path_ must have at
// least 2 components. We are processing "c[...]" at that
// point (otherwise known as member_name) and we have a
// reference to it in member_comp.
if (name_tail.index.size() > mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Too many index expressions for member." << endl;
// The member_path is the members we want to follow for the
// variable. For example, main[N].a.b may have main[N] as the
// base_name, and member_path=a.b. The member_name is the
// start of the member_path, and is "a". The member_name
// should be a member of the struct_type type.
// Calculate the offset within the packed structure of the
// member, and any indices. We will add in the offset of the
// struct into the packed array later. Note that this works
// for packed unions as well (although the offset will be 0
// for union members).
unsigned long tmp_off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, tmp_off);
if (member == 0) {
cerr << get_fileline() << ": error: Member " << member_name
<< " is not a member of struct type of "
<< reg->name()
<< "." << completed_path << endl;
des->errors += 1;
return false;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Member type: " << *(member->net_type)
<< endl;
}
off += tmp_off;
ivl_assert(*this, use_width >= (unsigned long)member->net_type->packed_width());
use_width = member->net_type->packed_width();
// At this point, off and use_width are the part select
// expressed by the member_comp, which is a member of the
// struct. We can further refine the part select with any
// indices that might be present.
// Get the index component type. At this point, we only
// support bit select or none.
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!member_comp.index.empty())
use_sel = member_comp.index.back().sel;
if (use_sel != index_component_t::SEL_NONE
&& use_sel != index_component_t::SEL_BIT
&& use_sel != index_component_t::SEL_PART) {
cerr << get_fileline() << ": sorry: Assignments to part selects of "
"a struct member are not yet supported." << endl;
des->errors += 1;
return false;
}
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, name_tail.index);
ivl_assert(*this, rc);
if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type)) {
// If the member type is a netvector_t, then it is a
// vector of atom or scaler objects. For example, if the
// l-value expression is "foo.member[1][2]",
// then the member should be something like:
// ... logic [h:l][m:n] member;
// There should be index expressions index the vector
// down, but there doesn't need to be all of them. We
// can, for example, be selecting a part of the vector.
// Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, name_tail.index.back().msb, -1, true);
long tmp;
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
cerr << get_fileline() << ": error: "
"Array index expressions must be constant here." << endl;
// We only need to process this if there are any
// index expressions. If not, then the packed
// vector can be handled atomically.
// In any case, this should be the tail of the
// member_path, because the array element of this
// kind of array cannot be a struct.
if (member_comp.index.size() > 0) {
// These are the dimensions defined by the type
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
if (member_comp.index.size() > mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Too many index expressions for member." << endl;
des->errors += 1;
return false;
}
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, member_comp.index);
ivl_assert(*this, rc);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "prefix_indices.size()==" << prefix_indices.size()
<< ", mem_packed_dims.size()==" << mem_packed_dims.size()
<< " (netvector_t context)"
<< endl;
}
long tail_off = 0;
unsigned long tail_wid = 0;
rc = calculate_part(this, des, scope, member_comp.index.back(), tail_off, tail_wid);
ivl_assert(*this, rc);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "calculate_part for tail returns tail_off=" << tail_off
<< ", tail_wid=" << tail_wid
<< endl;
}
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(mem_packed_dims, prefix_indices, tail_off, loff, lwid);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Calculate loff=" << loff << " lwid=" << lwid
<< " tail_off=" << tail_off << " tail_wid=" << tail_wid
<< " off=" << off << " use_width=" << use_width
<< endl;
}
off += loff;
use_width = lwid * tail_wid;
}
// The netvector_t only has atom elements, to
// there is no next struct type.
struct_type = 0;
} else if (const netparray_t*array = dynamic_cast<const netparray_t*> (member->net_type)) {
// If the member is a parray, then the elements
// are themselves packed object, including
// possibly a struct. Handle this by taking the
// part select of the current part of the
// variable, then stepping to the element type to
// possibly iterate through more of the member_path.
ivl_assert(*this, array->packed());
ivl_assert(*this, member_comp.index.size() > 0);
// These are the dimensions defined by the type
const vector<netrange_t>&mem_packed_dims = array->static_dimensions();
if (member_comp.index.size() != mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Incorrect number of index expressions for member "
<< member_name << "." << endl;
des->errors += 1;
return false;
}
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, member_comp.index);
ivl_assert(*this, rc);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "prefix_indices.size()==" << prefix_indices.size()
<< ", mem_packed_dims.size()==" << mem_packed_dims.size()
<< " (netparray_t context)"
<< endl;
}
// Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, member_comp.index.back().msb, -1, true);
long tmp;
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
cerr << get_fileline() << ": error: "
<< "Array index expressions for member " << member_name
<< " must be constant here." << endl;
des->errors += 1;
return false;
}
delete texpr;
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
ivl_type_t element_type = array->element_type();
long element_width = element_type->packed_width();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "parray subselection loff=" << loff
<< ", lwid=" << lwid
<< ", element_width=" << element_width
<< endl;
}
// The width and offset calculated from the
// indices is actually in elements, and not
// bits. In fact, in this context, the lwid should
// come down to 1 (one element).
off += loff * element_width;
ivl_assert(*this, lwid==1);
use_width = element_width;
// To move on to the next component in the member
// path, get the element type. For example, for
// the path a.b[1].c, we are processing b[1] here,
// and the element type should be a netstruct_t
// that will wind up containing the member c.
struct_type = dynamic_cast<const netstruct_t*> (element_type);
} else if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*> (member->net_type)) {
// If the member is itself a struct, then get
// ready to go on to the next iteration.
struct_type = tmp_struct;
} else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member->net_type)) {
// If the element is an enum, then we don't have
// anything special to do.
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Tail element is an enum: " << *tmp_enum
<< endl;
}
struct_type = 0;
} else {
// Unknown type?
cerr << get_fileline() << ": internal error: "
<< "Unexpected member type? " << *(member->net_type)
<< endl;
des->errors += 1;
return false;
struct_type = 0;
}
delete texpr;
// Complete this component of the path, mark it
// completed, and set up for the next component.
completed_path .push_back(member_comp);
member_path.pop_front();
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
} while (member_path.size() > 0 && struct_type != 0);
off += loff;
use_width = lwid;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "After processing member_path, "
<< "off=" << off
<< ", use_width=" << use_width
<< ", completed_path=" << completed_path
<< ", member_path=" << member_path
<< endl;
}
// The dimensions in the expression must match the packed
+57 -30
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;
}
+109 -450
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -54,7 +54,16 @@
# include <cassert>
# include "ivl_assert.h"
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
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->has_explicit_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,
const LexicalScope::param_expr_t&cur,
@@ -101,65 +110,37 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
}
static void collect_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
const map<perm_string,LexicalScope::param_expr_t*>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
// A parameter can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: parameter and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, false);
collect_parm_item_(des, scope, cur->first, *(cur->second), false, false);
}
}
static void collect_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
const map<perm_string,LexicalScope::param_expr_t*>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
// A localparam can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: localparam and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, true);
collect_parm_item_(des, scope, cur->first, *(cur->second), false, true);
}
}
static void collect_scope_specparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&specparams)
const map<perm_string,LexicalScope::param_expr_t*>&specparams)
{
for (mparm_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
// A specparam can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: specparam and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true, false);
collect_parm_item_(des, scope, cur->first, *(cur->second), true, false);
}
}
/*
* Elaborate the enumeration into the given scope. If scope==0, then
* the enumeration goes into $root instead of a scope.
* Elaborate the enumeration into the given scope.
*/
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type)
@@ -184,10 +165,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type);
use_enum->set_line(enum_type->li);
if (scope)
scope->add_enumeration_set(enum_type, use_enum);
else
des->add_enumeration_set(enum_type, use_enum);
scope->add_enumeration_set(enum_type, use_enum);
size_t name_idx = 0;
// Find the enumeration width.
@@ -355,10 +333,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
}
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
if (scope)
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
else
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
if (! rc_flag) {
cerr << use_enum->get_fileline()
@@ -388,15 +363,6 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_enumerations(Design*des)
{
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
; cur != pform_enum_sets.end() ; ++ cur) {
enum_type_t*curp = *cur;
elaborate_scope_enumeration(des, 0, curp);
}
}
/*
* If the pclass includes an implicit and explicit constructor, then
* merge the implicit constructor into the explicit constructor as
@@ -487,7 +453,9 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
if (debug_scopes) {
cerr << pclass->get_fileline() <<": elaborate_scope_class: "
<< "Elaborate scope class " << pclass->pscope_name() << endl;
<< "Elaborate scope class " << pclass->pscope_name()
<< " within scope " << scope_path(scope)
<< endl;
}
class_type_t*base_class = dynamic_cast<class_type_t*> (use_type->base_type);
@@ -500,7 +468,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0;
if (base_class) {
ivl_assert(*pclass, scope);
use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: "
@@ -515,21 +482,34 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
use_type->save_elaborated_type = use_class;
// Class scopes have no parent scope, because references are
// not allowed to escape a class method.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
NetScope::CLASS);
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
NetScope::CLASS, scope->unit());
class_scope->set_line(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);
class_scope->add_typedefs(&pclass->typedefs);
// Elaborate enum types declared in the class. We need these
// now because enumeration constants can be used during scope
// elaboration.
if (debug_scopes) {
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
<< "Elaborate " << pclass->enum_sets.size() << " enumerations"
<< " in class " << scope_path(class_scope)
<< ", scope=" << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, class_scope, pclass->enum_sets);
// Collect the properties, elaborate them, and add them to the
// elaborated class definition.
for (map<perm_string, class_type_t::prop_info_t>::iterator cur = use_type->properties.begin()
; cur != use_type->properties.end() ; ++ cur) {
ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope);
ivl_type_s*tmp = cur->second.type->elaborate_type(des, class_scope);
ivl_assert(*pclass, tmp);
if (debug_scopes) {
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
@@ -548,6 +528,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Task methods are always automatic...
method_scope->is_auto(true);
method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@@ -566,6 +547,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Function methods are always automatic...
method_scope->is_auto(true);
method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@@ -576,12 +558,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
cur->second->elaborate_scope(des, method_scope);
}
if (scope) {
scope->add_class(use_class);
} else {
des->add_class(use_class, pclass);
}
scope->add_class(use_class);
}
static void elaborate_scope_classes(Design*des, NetScope*scope,
@@ -593,18 +570,6 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_classes(Design*des)
{
if (pform_classes.empty())
return;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
blend_class_constructors(cur->second);
elaborate_scope_class(des, 0, cur->second);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
@@ -653,9 +618,7 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
if (scope==0)
des->add_root_task(task_scope, task);
task_scope->add_imports(&task->explicit_imports);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: "
@@ -673,39 +636,6 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
for (tasks_it_t cur = tasks.begin()
; cur != tasks.end() ; ++ cur ) {
hname_t use_name( (*cur).first );
// A task can not have the same name as another scope object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << cur->second->get_fileline() << ": error: task and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
continue;
}
// A task can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second->get_fileline()
<< ": error: task and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
// A task can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: task and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
elaborate_scope_task(des, scope, cur->second);
}
@@ -718,9 +648,7 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
if (scope==0)
des->add_root_task(task_scope, task);
task_scope->add_imports(&task->explicit_imports);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: "
@@ -738,67 +666,11 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
for (funcs_it_t cur = funcs.begin()
; cur != funcs.end() ; ++ cur ) {
hname_t use_name( (*cur).first );
// A function can not have the same name as another scope object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << cur->second->get_fileline()
<< ": error: function and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
continue;
}
// A function can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second->get_fileline()
<< ": error: function and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
// A function can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: function and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
elaborate_scope_func(des, scope, cur->second);
}
}
void elaborate_rootscope_tasks(Design*des)
{
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
elaborate_scope_task(des, 0, task);
continue;
}
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
elaborate_scope_func(des, 0, func);
continue;
}
cerr << cur->second->get_fileline() << ": internal error: "
<< "elabortae_rootscope_tasks does not understand "
<< "this object," << endl;
des->errors += 1;
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
@@ -838,12 +710,23 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
<< "Elaborate package " << scope_path(scope) << "." << endl;
}
scope->add_typedefs(&typedefs);
collect_scope_parameters_(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
if (debug_scopes) {
cerr << get_fileline() << ": PPackage::elaborate_scope: "
<< "Elaborate " << enum_sets.size() << " enumerations"
<< " in package scope " << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, scope, enum_sets);
elaborate_scope_classes(des, scope, classes_lexical);
elaborate_scope_funcs(des, scope, funcs);
elaborate_scope_tasks(des, scope, tasks);
elaborate_scope_events_(des, scope, events);
return true;
}
@@ -855,6 +738,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
<< "Elaborate " << scope_path(scope) << "." << endl;
}
scope->add_typedefs(&typedefs);
// Add the genvars to the scope.
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
@@ -877,6 +762,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
replace_scope_parameters_(scope, *this, replacements);
if (debug_scopes) {
cerr << get_fileline() << ": Module::elaborate_scope: "
<< "Elaborate " << enum_sets.size() << " enumerations"
<< " in scope " << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, scope, enum_sets);
assert(classes.size() == classes_lexical.size());
@@ -1008,17 +899,19 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// Check that the loop_index variable was declared in a
// genvar statement.
NetScope*cscope = container;
while (cscope && !cscope->find_genvar(loop_index))
cscope = cscope->parent();
if (!cscope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
des->errors += 1;
return false;
if (!local_index) {
// Check that the loop_index variable was declared in a
// genvar statement.
NetScope*cscope = container;
while (cscope && !cscope->find_genvar(loop_index))
cscope = cscope->parent();
if (!cscope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
des->errors += 1;
return false;
}
}
// We're going to need a genvar...
@@ -1036,56 +929,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
return false;
}
// Check the generate block name.
// A generate "loop" can not have the same name as another
// scope object. Find any scope with this name, not just an
// exact match scope.
const NetScope *child = container->child_byname(scope_name);
if (child) {
cerr << get_fileline() << ": error: generate \"loop\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "loop" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a parameter.
const NetExpr*tmsb;
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(des, scope_name,
tmsb, tlsb);
if (texpr != 0) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// These have all been checked so we just need to skip the actual
// generation for these name conflicts. Not skipping these two will
// cause the compiler to have problems (assert, inf. loop, etc.).
if (container->get_parameter(des, loop_index, tmsb, tlsb)) return false;
if (container->find_event(loop_index)) return false;
genvar = init->value().as_long();
delete init_ex;
@@ -1116,13 +959,18 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
// block. Code within this scope thus has access to the
// genvar as a constant.
{
verinum genvar_verinum(genvar);
verinum genvar_verinum;
if (gn_strict_expr_width_flag)
genvar_verinum = verinum(genvar, integer_width);
else
genvar_verinum = verinum(genvar);
genvar_verinum.has_sign(true);
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
@@ -1155,7 +1003,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
test_ex = elab_and_eval(des, container, loop_test, -1);
test_ex = elab_and_eval(des, container, loop_test, -1, true);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
}
@@ -1192,45 +1040,6 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
}
hname_t use_name (scope_name);
// A generate "if" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"if\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "if" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"if\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"if\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"if\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
@@ -1251,6 +1060,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
// for myself. That is what I will pass to the subscope.
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope);
@@ -1334,44 +1144,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
// A generate "case" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"case\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "case" can not have the same name as a genvar.
if (container->find_genvar(item->scope_name)) {
cerr << get_fileline() << ": error: generate \"case\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a named event.
const NetEvent *event = container->find_event(item->scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"case\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, item->scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"case\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
item->probe_for_direct_nesting_();
if (item->direct_nested_) {
@@ -1391,6 +1163,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
item->elaborate_subscope_(des, scope);
return true;
@@ -1399,46 +1173,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
{
hname_t use_name (scope_name);
// A generate "block" can not have the same name as another scope
// object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"block\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "block" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"block\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"block\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"block\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate named block "
<< ": Generate scope=" << use_name << endl;
@@ -1446,6 +1180,7 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope);
@@ -1469,6 +1204,8 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
scope->add_typedefs(&typedefs);
// Add the genvars to this scope.
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
@@ -1577,36 +1314,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// Missing module instance names have already been rejected.
assert(get_name() != "");
// A module instance can not have the same name as another scope object.
const NetScope *child = sc->child(hname_t(get_name()));
if (child) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and ";
child->print_type(cerr);
cerr << " in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
return;
}
// A module instance can not have the same name as a genvar.
if (sc->find_genvar(get_name())) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and genvar in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// A module instance can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = sc->get_parameter(des, get_name(), ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and parameter in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// check for recursive instantiation by scanning the current
// scope and its parents. Look for a module instantiation of
// the same module, but farther up in the scope.
@@ -1714,6 +1421,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
<< "." << endl;
}
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
// Run through the module instances, and make scopes out of
// them. Also do parameter overrides that are done on the
// instantiation line.
@@ -1740,21 +1451,21 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// Create the new scope as a MODULE with my name. Note
// that if this is a nested module, mark it thus so that
// scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, 0,
bound_type_? true : false,
mod->program_block,
mod->is_interface);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
my_scope->add_imports(&mod->explicit_imports);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
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
@@ -1810,6 +1521,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
mod->elaborate_scope(des, my_scope, replace);
}
delete[]attrib_list;
/* Stash the instance array of scopes into the parent
scope. Later elaboration passes will use this vector to
@@ -1828,36 +1540,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
* no hierarchy, but neither does the NetEvent, until it is stored in
* the NetScope object.
*/
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
void PEvent::elaborate_scope(Design*, NetScope*scope) const
{
// A named event can not have the same name as another scope object.
const NetScope *child = scope->child(hname_t(name_));
if (child) {
cerr << get_fileline() << ": error: named event and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a genvar.
if (scope->find_genvar(name_)) {
cerr << get_fileline() << ": error: named event and "
<< "genvar in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named event and "
<< "parameter in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
NetEvent*ev = new NetEvent(name_);
ev->set_line(*this);
scope->add_event(ev);
@@ -1875,6 +1559,8 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
// find otherwise.
scope->is_const_func(true);
scope->add_typedefs(&typedefs);
// Scan the parameters in the function, and store the information
// needed to evaluate the parameter expressions.
@@ -1893,6 +1579,8 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
scope->add_typedefs(&typedefs);
// Scan the parameters in the task, and store the information
// needed to evaluate the parameter expressions.
@@ -1928,37 +1616,6 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
if (pscope_name() != 0) {
hname_t use_name(pscope_name());
// A named block can not have the same name as another scope
// object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << get_fileline() << ": error: named block and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return;
}
// A named block can not have the same name as a genvar.
if (scope->find_genvar(pscope_name())) {
cerr << get_fileline() << ": error: named block and "
"genvar in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A named block can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, pscope_name(),
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named block and "
"parameter in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Elaborate block scope " << use_name
@@ -1971,6 +1628,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());
my_scope->is_auto(scope->is_auto());
my_scope->add_imports(&explicit_imports);
my_scope->add_typedefs(&typedefs);
// Scan the parameters in the scope, and store the information
// needed to evaluate the parameter expressions.
+104 -121
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -47,6 +47,8 @@
using namespace std;
#if 0
/* These functions are not currently used. */
static bool get_const_argument(NetExpr*exp, verinum&res)
{
switch (exp->expr_type()) {
@@ -73,8 +75,6 @@ static bool get_const_argument(NetExpr*exp, verinum&res)
return true;
}
#if 0
/* This function is not currently used. */
static bool get_const_argument(NetExpr*exp, long&res)
{
verinum tmp;
@@ -578,10 +578,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
// source code for the definition may be:
// function new(...);
// endfunction
// In this case, the "@" port is the synthetic "this"
// argument and we also use it as a return value at the
// same time.
ret_sig = scope->find_signal(perm_string::literal("@"));
// In this case, the "@" port (THIS_TOKEN) is the synthetic
// "this" argument and we also use it as a return value at
// the same time.
ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN));
ivl_assert(*this, ret_sig);
if (debug_elaborate)
@@ -757,6 +757,11 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
<< "Function arguments must be input ports." << endl;
des->errors += 1;
}
if (tmp->unpacked_dimensions() != 0) {
cerr << get_fileline() << ": sorry: Subroutine ports with "
"unpacked dimensions are not yet supported." << endl;
des->errors += 1;
}
}
}
@@ -871,13 +876,13 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
return 0;
}
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, const LineInfo*li,
parray_type_t*data_type)
{
vector<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->dims);
ivl_assert(*data_type, !bad_range);
bool dimensions_ok = evaluate_ranges(des, scope, li, packed_dimensions, * data_type->dims);
ivl_assert(*data_type, dimensions_ok);
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
@@ -927,56 +932,54 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
wtype = NetNet::WIRE;
is_implicit_scalar = true;
}
// Certain contexts, such as arguments to functions, presume
// "reg" instead of "wire". The parser reports these as
// IMPLICIT_REG. Also, certain cases, such as:
// fun(string arg1) ...
// are implicitly NOT scalar, so detect that case here.
if (wtype == NetNet::IMPLICIT_REG) {
wtype = NetNet::REG;
is_implicit_scalar = true;
if (data_type_!=IVL_VT_STRING)
is_implicit_scalar = true;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Signal " << basename()
<< ", wtype=" << wtype
<< ", data_type_=" << data_type_
<< ", is_implicit_scalar=" << (is_implicit_scalar?"true":"false")
<< endl;
}
unsigned wid = 1;
vector<netrange_t>packed_dimensions;
NetScope*base_type_scope = scope;
if (set_data_type_ && !set_data_type_->name.nil())
base_type_scope = scope->find_typedef_scope(des, set_data_type_);
des->errors += error_cnt_;
// A signal can not have the same name as a scope object.
const NetScope *child = scope->child_byname(name_);
if (child) {
cerr << get_fileline() << ": error: signal and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a genvar.
const LineInfo *genvar = scope->find_genvar(name_);
if (genvar) {
cerr << get_fileline() << ": error: signal and genvar in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a parameter. Note
// that we treat enumeration literals similar to parameters,
// so if the name matches an enumeration literal, it will be
// caught here.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: signal and parameter in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a named event.
const NetEvent *event = scope->find_event(name_);
if (event) {
cerr << get_fileline() << ": error: signal and named event in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
if (port_set_ || net_set_) {
bool bad_range = false;
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 dimensions_ok = true;
vector<netrange_t> plist, nlist;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && !port_.empty()) {
@@ -984,7 +987,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Evaluate ranges for port " << basename() << endl;
}
bad_range |= evaluate_ranges(des, scope, plist, port_);
dimensions_ok &= evaluate_ranges(des, scope, this, plist, port_);
nlist = plist;
/* An implicit port can have a range so note that here. */
is_implicit_scalar = false;
@@ -992,13 +995,13 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
assert(port_set_ || port_.empty());
/* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && !net_.empty() && !bad_range) {
if (net_set_ && !net_.empty() && dimensions_ok) {
nlist.clear();
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Evaluate ranges for net " << basename() << endl;
}
bad_range |= evaluate_ranges(des, scope, nlist, net_);
dimensions_ok &= evaluate_ranges(des, base_type_scope, this, nlist, net_);
}
assert(net_set_ || net_.empty());
@@ -1069,6 +1072,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
list<netrange_t>unpacked_dimensions;
netdarray_t*netdarray = 0;
NetScope*array_type_scope = scope;
if (uarray_type_ && !uarray_type_->name.nil())
array_type_scope = scope->find_typedef_scope(des, uarray_type_);
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
; cur != unpacked_.end() ; ++cur) {
PExpr*use_lidx = cur->first;
@@ -1087,51 +1094,51 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
// Special case: Detect the mark for a QUEUE
// declaration, which is the dimensions [null:<nil>].
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
// declaration, which is the dimensions [null:max_idx].
if (dynamic_cast<PENull*>(use_lidx)) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
vec->set_signed(get_signed());
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netqueue_t(vec);
long max_idx;
if (use_ridx) {
NetExpr*tmp = elab_and_eval(des, array_type_scope, use_ridx,
-1, true);
NetEConst*cv = dynamic_cast<NetEConst*>(tmp);
if (cv == 0) {
cerr << get_fileline() << ": error: queue '" << name_
<< "' bound must be a constant!" << endl;
des->errors += 1;
max_idx = -1;
} else {
verinum res = cv->value();
if (res.is_defined()) {
max_idx = res.as_long();
if (max_idx < 0) {
cerr << get_fileline() << ": error: queue '"
<< name_ << "' bound must be positive ("
<< max_idx << ")!" << endl;
des->errors += 1;
max_idx = -1;
}
} else {
cerr << get_fileline() << ": error: queue '" << name_
<< "' bound is undefined!" << endl;
des->errors += 1;
max_idx = -1;
}
}
} else max_idx = -1;
netdarray = new netqueue_t(vec, max_idx);
continue;
}
// Cannot handle dynamic arrays of arrays yet.
ivl_assert(*this, netdarray==0);
ivl_assert(*this, use_lidx && use_ridx);
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, use_ridx, -1, true);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is "
<< "a problem evaluating indices for ``"
<< name_ << "''." << endl;
des->errors += 1;
return 0;
}
bool const_flag = true;
verinum lval, rval;
const_flag &= get_const_argument(lexp, lval);
const_flag &= get_const_argument(rexp, rval);
delete rexp;
delete lexp;
long index_l, index_r;
if (! const_flag) {
cerr << get_fileline() << ": error: The indices "
<< "are not constant for array ``"
<< name_ << "''." << endl;
des->errors += 1;
/* Attempt to recover from error, */
index_l = 0;
index_r = 0;
} else {
index_l = lval.as_long();
index_r = rval.as_long();
}
evaluate_range(des, array_type_scope, this, *cur, index_l, index_r);
if (abs(index_r - index_l) > warn_dimension_size) {
cerr << get_fileline() << ": warning: Array dimension "
"is greater than " << warn_dimension_size
@@ -1168,6 +1175,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 +1193,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;
}
}
@@ -1221,7 +1228,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
const netenum_t*use_enum = scope->find_enumeration_for_name(sample_name->name);
const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
@@ -1254,7 +1261,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// The trick here is that the parray type has an
// arbitrary sub-type, and not just a scalar bit...
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
netparray_t*use_type = elaborate_parray_type(des, scope, this, parray_type);
// Should not be getting packed dimensions other than
// through the parray type declaration.
ivl_assert(*this, packed_dimensions.empty());
@@ -1316,27 +1323,3 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
return sig;
}
void Design::root_elaborate_sig(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate_sig(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate_sig(this, cur->first);
}
}
+30 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2020 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"
@@ -76,9 +78,13 @@ static void elaborate_array_ranges(Design*des, NetScope*scope,
*/
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
{
// User-defined types must be elaborated in the context
// where they were defined.
if (!name.nil())
scope = scope->find_typedef_scope(des, this);
ivl_assert(*this, scope);
Definitions*use_definitions = scope;
if (use_definitions == 0)
use_definitions = des;
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
@@ -145,13 +151,13 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
* available at the right time. At that time, the netenum_t* object is
* stashed in the scope so that I can retrieve it here.
*/
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
ivl_type_s* enum_type_t::elaborate_type_raw(Design*, NetScope*scope) const
{
ivl_assert(*this, scope);
ivl_type_s*tmp = scope->enumeration_for_key(this);
if (tmp) return tmp;
tmp = des->enumeration_for_key(this);
if (tmp == 0 && scope->unit()) {
tmp = scope->unit()->enumeration_for_key(this);
}
return tmp;
}
@@ -214,9 +220,9 @@ netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
// There may be several names that are the same type:
// <data_type> name1, name2, ...;
// Process all the member, and give them a type.
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
; name != curp->names->end() ; ++ name) {
decl_assignment_t*namep = *name;
for (list<decl_assignment_t*>::iterator cur_name = curp->names->begin()
; cur_name != curp->names->end() ; ++ cur_name) {
decl_assignment_t*namep = *cur_name;
netstruct_t::member_t memb;
memb.name = namep->name;
@@ -245,10 +251,21 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
return res;
}
vector<netrange_t> dimensions;
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
// Special case: if the dimension is null:nil. this is a queue.
if (dynamic_cast<PENull*>(cur->first)) {
cerr << get_fileline() << ": sorry: "
<< "SV queues inside classes are not yet supported." << endl;
des->errors += 1;
if (bad_range) {
// FIXME: Need to set the max size if cur->second is defined
ivl_type_s*res = new netqueue_t(btype, -1);
return res;
}
vector<netrange_t> dimensions;
bool dimensions_ok = evaluate_ranges(des, scope, this, dimensions, *dims);
if (!dimensions_ok) {
cerr << get_fileline() << " : warning: "
<< "Bad dimensions for type here." << endl;
}
+979 -200
View File
File diff suppressed because it is too large Load Diff
+7 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@@ -123,6 +123,12 @@ bool NetFF::emit_node(struct target_t*tgt) const
return true;
}
bool NetLatch::emit_node(struct target_t*tgt) const
{
tgt->lpm_latch(this);
return true;
}
bool NetLiteral::emit_node(struct target_t*tgt) const
{
return tgt->net_literal(this);
@@ -504,26 +510,12 @@ int Design::emit(struct target_t*tgt) const
if (tgt->start_design(this) == false)
return -2;
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
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope) {
scope->second->emit_scope(tgt);
}
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
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
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); ++ scope ) {
+298 -155
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2020 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
@@ -545,7 +545,7 @@ NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetE
bool flag = get_real_arguments(le, re, lval, rval);
if (! flag) return 0;
verinum result(((lval == rval) ^ ne_flag) ?
verinum result(((lval == rval) != ne_flag) ?
verinum::V1 : verinum::V0, 1);
NetEConst*res = new NetEConst(result);
ivl_assert(*this, res);
@@ -570,11 +570,11 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
unsigned top = lv.len();
if (rv.len() < top)
top = rv.len();
for (unsigned idx = 0 ; idx < top ; idx += 1) {
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
bool x_bit_present = false;
@@ -611,60 +611,6 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
}
}
if (res != verinum::Vx) {
verinum::V lpad = verinum::V0;
verinum::V rpad = verinum::V0;
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
lpad = verinum::V1;
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
rpad = verinum::V1;
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && rpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && rpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
for (unsigned idx = top ; idx < rv.len() ; idx += 1)
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && lpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && lpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
@@ -681,41 +627,15 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
verinum::V res = verinum::V1;
// Find the smallest argument length.
unsigned cnt = lv.len();
if (cnt > rv.len()) cnt = rv.len();
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
// Check the common bits.
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != rv.get(idx)) {
res = verinum::V0;
break;
}
bool is_signed = lv.has_sign() && rv.has_sign();
// 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);
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
// 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);
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
if (rv.get(idx) != pad)
res = verinum::V0;
break;
}
}
if (ne_flag) {
if (res == verinum::V0) res = verinum::V1;
else res = verinum::V0;
@@ -726,6 +646,55 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
return result;
}
NetEConst* NetEBComp::eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
{
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
if (lc == 0 || rc == 0) return 0;
const verinum&lv = lc->value();
const verinum&rv = rc->value();
const verinum::V eq_res = ne_flag ? verinum::V0 : verinum::V1;
const verinum::V ne_res = ne_flag ? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
// An X or Z in the R-value matches any L-value.
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
continue;
default:
break;
}
// An X or Z in the L-value that is not matches by an R-value X/Z returns undefined.
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
continue;
default:
break;
}
// A hard (0/1) mismatch gives a not-equal result.
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
}
NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
NetEConst*res = 0;
@@ -739,6 +708,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
res = eval_eqeq_(false, l, r);
break;
case 'w': // Wild equality (==?)
res = eval_weqeq_(false, l, r);
break;
case 'G': // >=
res = eval_gteq_(l, r);
break;
@@ -755,6 +728,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
res = eval_eqeq_(true, l, r);
break;
case 'W': // Wild not-equal (!=?)
res = eval_weqeq_(true, l, r);
break;
case '<': // Less than
res = eval_less_(l, r);
break;
@@ -831,44 +808,10 @@ NetExpr* NetEBDiv::eval_arguments_(const NetExpr*l, const NetExpr*r) const
return tmp;
}
NetEConst* NetEBLogic::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
{
double lval;
double rval;
bool flag = get_real_arguments(l, r, lval, rval);
if (! flag) return 0;
verinum::V res;
switch (op_) {
case 'a': // Logical AND (&&)
if ((lval != 0.0) && (rval != 0.0))
res = verinum::V1;
else
res = verinum::V0;
break;
case 'o': // Logical OR (||)
if ((lval != 0.0) || (rval != 0.0))
res = verinum::V1;
else
res = verinum::V0;
break;
default:
return 0;
}
NetEConst*tmp = new NetEConst(verinum(res, 1));
ivl_assert(*this, tmp);
eval_debug(this, tmp, true);
return tmp;
}
NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
if (l->expr_type() == IVL_VT_REAL || r->expr_type() == IVL_VT_REAL)
return eval_tree_real_(l,r);
// NetEBLogic arguments should have already been reduced so real is not possible.
ivl_assert(*this, (l->expr_type() != IVL_VT_REAL) && (r->expr_type() != IVL_VT_REAL));
assert(expr_type() == IVL_VT_LOGIC);
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
@@ -901,25 +844,39 @@ NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
case 'a': // Logical AND (&&)
if ((lv == verinum::V0) || (rv == verinum::V0))
res = verinum::V0;
else if ((lv == verinum::V1) && (rv == verinum::V1))
res = verinum::V1;
else
res = verinum::Vx;
break;
case 'o': // Logical OR (||)
if ((lv == verinum::V1) || (rv == verinum::V1))
res = verinum::V1;
else if ((lv == verinum::V0) && (rv == verinum::V0))
res = verinum::V0;
else
res = verinum::Vx;
break;
case 'q': // Logical implication (->)
if ((lv == verinum::V0) || (rv == verinum::V1))
res = verinum::V1;
else if ((lv == verinum::V1) && (rv == verinum::V0))
res = verinum::V0;
else
res = verinum::Vx;
break;
case 'Q': // Logical equivalence (<->)
if (((lv == verinum::V0) && (rv == verinum::V0)) ||
((lv == verinum::V1) && (rv == verinum::V1)))
res = verinum::V1;
else if (((lv == verinum::V0) && (rv == verinum::V1)) ||
((lv == verinum::V1) && (rv == verinum::V0)))
res = verinum::V0;
else
res = verinum::Vx;
break;
default:
@@ -1097,6 +1054,7 @@ NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
break;
case 'r':
lv.has_sign(false);
// fallthrough
case 'R':
val = cast_to_width(lv >> shift, wid);
break;
@@ -1548,6 +1506,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'A':
invert = true;
// fallthrough
case '&': {
res = verinum::V1;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@@ -1557,6 +1516,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'N':
invert = true;
// fallthrough
case '|': {
res = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@@ -1566,6 +1526,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'X':
invert = true;
// fallthrough
case '^': {
/* Reduction XOR. */
unsigned ones = 0, unknown = 0;
@@ -1617,6 +1578,7 @@ NetExpr* NetECast::eval_arguments_(const NetExpr*ex) const
res_val = cast_to_width(res_val, expr_width());
res = new NetEConst(res_val);
}
// fallthrough
case 'v':
if (const NetECReal*val = dynamic_cast<const NetECReal*>(ex)) {
verinum res_val(val->value().as_double(), false);
@@ -1931,15 +1893,111 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
return res;
}
NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/,
const NetExpr* /*arg1*/) const
static void no_string_arg(const NetESFunc*info, unsigned arg_num)
{
return 0;
cerr << info->get_fileline() << ": error: constant function "
<< info->name() << "() does not support a string argument ("
<< arg_num+1 << ")." << endl;
}
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const
NetEConst* NetESFunc::evaluate_countbits_() const
{
return 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(parms_[0]);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
/* Find which values need to be counted. */
bool count_0 = false;
bool count_1 = false;
bool count_z = false;
bool count_x = false;
for (unsigned arg=1; arg < parms_.size(); ++arg) {
const NetEConst*argi = dynamic_cast<const NetEConst*>(parms_[arg]);
if (! argi) return 0;
verinum check_for = argi->value();
if (check_for.is_string()) {
no_string_arg(this, arg);
return 0;
}
switch (check_for[0]) {
case verinum::V0:
count_0 = true;
break;
case verinum::V1:
count_1 = true;
break;
case verinum::Vz:
count_z = true;
break;
case verinum::Vx:
count_x = true;
break;
}
}
/* Search each bit of the vector looking for the values to
* be counted. */
int count = 0;
for (unsigned bit=0; bit < value.len(); ++bit) {
switch (value[bit]) {
case verinum::V0:
if (count_0) ++count;
break;
case verinum::V1:
if (count_1) ++count;
break;
case verinum::Vz:
if (count_z) ++count;
break;
case verinum::Vx:
if (count_x) ++count;
break;
}
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
int count = 0;
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) ++count;
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
/* Get the total number of dimensions for the given expression. */
@@ -1962,19 +2020,92 @@ NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
return new NetEConst(verinum(verinum(res), integer_width));
}
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const
{
return 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
unsigned is_unknown = 1;
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
if (value.is_defined()) is_unknown = 0;
verinum tmp (is_unknown, 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const
static bool is_onehot(verinum&value, bool zero_is_okay)
{
return 0;
bool found_a_one = false;
for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) {
if (found_a_one) return false;
found_a_one = true;
}
}
/* If no one bit was found return true if zero is okay. */
if (zero_is_okay) found_a_one = true;
return found_a_one;
}
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const
{
return 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
verinum tmp (is_onehot(value, false), 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
verinum tmp (is_onehot(value, true), 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
/* Get the number of unpacked dimensions for the given expression. */
@@ -2146,7 +2277,7 @@ NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
{
switch (id) {
case CTBITS:
return evaluate_countbits_(arg0, arg1);
return evaluate_countbits_();
/* The array functions are handled together. */
case HIGH:
case INCR:
@@ -2217,12 +2348,12 @@ NetESFunc::ID NetESFunc::built_in_id_() const
built_in_func["$unpacked_dimensions" ] = UPDIMS;
}
/* These are available in 1800-2009 and later. */
/* This is available in 1800-2009 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2009)) {
built_in_func["$countones" ] = CTONES;
}
/* These are available in 1800-2012 and later. */
/* This is available in 1800-2012 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2012)) {
built_in_func["$countbits" ] = CTBITS;
}
@@ -2249,7 +2380,11 @@ NetESFunc::ID NetESFunc::built_in_id_() const
NetExpr* NetESFunc::eval_tree()
{
/* Get the ID for this system function if it is can be used as a
/* We don't support evaluating overridden functions. */
if (is_overridden_)
return 0;
/* Get the ID for this system function if it can be used as a
* constant function. */
ID id = built_in_id_();
if (id == NOT_BUILT_IN) return 0;
@@ -2257,8 +2392,9 @@ NetExpr* NetESFunc::eval_tree()
switch (parms_.size()) {
case 1:
if (! takes_nargs_(id, 1)) {
cerr << get_fileline() << ": error: " << name_
<< "() does not support a single argument." << endl;
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support a single argument."
<< endl;
return 0;
}
eval_expr(parms_[0]);
@@ -2266,8 +2402,9 @@ NetExpr* NetESFunc::eval_tree()
case 2:
if (! takes_nargs_(id, 2)) {
cerr << get_fileline() << ": error: " << name_
<< "() does not support two arguments." << endl;
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support two arguments."
<< endl;
return 0;
}
eval_expr(parms_[0]);
@@ -2277,15 +2414,21 @@ NetExpr* NetESFunc::eval_tree()
default:
/* Check to see if the function was called correctly. */
if (! takes_nargs_(id, parms_.size())) {
cerr << get_fileline() << ": error: " << name_
<< "() does not support " << parms_.size()
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support " << parms_.size()
<< " arguments." << endl;
return 0;
}
// HERE: Need to add support for a multi argument $countbits().
cerr << get_fileline() << ": sorry: functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
if (id == CTBITS) {
for (unsigned bit = 0; bit < parms_.size(); ++bit) {
eval_expr(parms_[bit]);
}
return evaluate_countbits_();
} else {
cerr << get_fileline() << ": sorry: constant functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
}
return 0;
}
}
+128
View File
@@ -0,0 +1,128 @@
/*
* Copyright (c) 2016 Martin Whitaker (icarus@martin-whitaker.me.uk)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include <cstdlib>
# include <sstream>
# include "netlist.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
/*
* The exposenodes functor is primarily provided for use by the vlog95
* target. To implement some LPM objects, it needs to take a bit or part
* of one of the LPM inputs. If that input is not connected to a real
* net in the design, we need to create a net at that point so that
* there is something to which we can apply a bit or part select. This
* has the effect of splitting the synthesised structure at that point.
* Rather than creating a new net, we just look for a temporary net
* created by the synthesis process (there should be at least one) and
* reset its "local" flag. We also prepend another '_' to the synthetic
* name to avoid name collisions when we recompile the vlog95 output
* (because NetScope::local_symbol() doesn't actually check that the
* name it generates is unique).
*/
struct exposenodes_functor : public functor_t {
unsigned count;
virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
virtual void lpm_substitute(Design*des, NetSubstitute*obj);
};
static bool expose_nexus(Nexus*nex)
{
NetNet*sig = 0;
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
// Don't expose nodes that are attached to constants
if (dynamic_cast<NetConst*> (cur->get_obj()))
return false;
if (dynamic_cast<NetLiteral*> (cur->get_obj()))
return false;
NetNet*cur_sig = dynamic_cast<NetNet*> (cur->get_obj());
if (cur_sig == 0)
continue;
if (!cur_sig->local_flag())
return false;
sig = cur_sig;
}
assert(sig);
ostringstream res;
res << "_" << sig->name();
sig->rename(lex_strings.make(res.str()));
sig->local_flag(false);
return true;
}
/*
* The vlog95 target implements a wide mux as a hierarchy of 2:1 muxes,
* picking off one bit of the select input at each level of the hierarchy.
*/
void exposenodes_functor::lpm_mux(Design*, NetMux*obj)
{
if (obj->sel_width() == 1)
return;
if (expose_nexus(obj->pin_Sel().nexus()))
count += 1;
}
/*
* A VP part select is going to select a part from its input.
*/
void exposenodes_functor::lpm_part_select(Design*, NetPartSelect*obj)
{
if (obj->dir() != NetPartSelect::VP)
return;
if (expose_nexus(obj->pin(1).nexus()))
count += 1;
}
/*
* A substitute is going to select one or two parts from the wider input signal.
*/
void exposenodes_functor::lpm_substitute(Design*, NetSubstitute*obj)
{
if (expose_nexus(obj->pin(1).nexus()))
count += 1;
}
void exposenodes(Design*des)
{
exposenodes_functor exposenodes;
exposenodes.count = 0;
if (verbose_flag) {
cout << " ... Look for intermediate nodes" << endl << flush;
}
des->functor(&exposenodes);
if (verbose_flag) {
cout << " ... Exposed " << exposenodes.count
<< " intermediate signals." << endl << flush;
}
}
+50 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2020 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
@@ -274,7 +274,18 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
width, op_=='E' ? NetCaseCmp::EEQ : NetCaseCmp::NEQ);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
des->add_node(gate);
return osig;
}
if (op_ == 'w' || op_ == 'W') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='w' ? NetCaseCmp::WEQ : NetCaseCmp::WNE);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
@@ -335,6 +346,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->errors += 1;
return 0;
}
// fallthrough
case 'e': // ==
connect(dev->pin_AEB(), osig->pin(0));
break;
@@ -353,6 +365,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->errors += 1;
return 0;
}
// fallthrough
case 'n': // !=
connect(dev->pin_ANEB(), osig->pin(0));
break;
@@ -386,7 +399,8 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
powr->set_line(*this);
des->add_node(powr);
powr->set_signed( has_sign() );
// The lpm_pwr object only cares about the signedness of the exponent.
powr->set_signed( right_->has_sign() );
connect(powr->pin_DataA(), lsig->pin(0));
connect(powr->pin_DataB(), rsig->pin(0));
@@ -531,27 +545,40 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
return 0;
}
netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_tmp);
osig->set_line(*this);
osig->local_flag(true);
NetLogic*olog;
perm_string oname = scope->local_symbol();
/* Create the logic OR/AND gate. This has a single bit output,
* with single bit inputs for the two operands. */
if (op() == 'o') {
olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true);
} else {
assert(op() == 'a');
switch (op()) {
case 'a':
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true);
break;
case 'o':
olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true);
break;
case 'q':
olog = new NetLogic(scope, oname, 3, NetLogic::IMPL, 1, true);
break;
case 'Q':
olog = new NetLogic(scope, oname, 3, NetLogic::EQUIV, 1, true);
break;
default:
cerr << get_fileline() << ": sorry: "
<< human_readable_op(op_)
<< " is not currently supported." << endl;
des->errors += 1;
return 0;
}
olog->set_line(*this);
des->add_node(olog);
netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_tmp);
osig->set_line(*this);
osig->local_flag(true);
connect(osig->pin(0), olog->pin(0));
/* The left and right operands have already been reduced to a
@@ -733,12 +760,18 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
}
if (flag == false) return 0;
if (flag == false) {
delete[]tmp;
return 0;
}
ivl_assert(*this, data_type != IVL_VT_NO_TYPE);
/* If this is a replication of zero just return 0. */
if (expr_width() == 0) return 0;
if (expr_width() == 0) {
delete[]tmp;
return 0;
}
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
@@ -1341,6 +1374,7 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root)
if (nset && (nset->size() > 0)) {
NetEvent*ev = new NetEvent(scope->local_symbol());
ev->set_line(*root);
ev->local_flag(true);
NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(),
ev, NetEvProbe::ANYEDGE,
+19 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2012 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
@@ -78,6 +78,10 @@ void functor_t::lpm_ff(Design*, NetFF*)
{
}
void functor_t::lpm_latch(Design*, NetLatch*)
{
}
void functor_t::lpm_logic(Design*, NetLogic*)
{
}
@@ -102,6 +106,10 @@ void functor_t::sign_extend(Design*, NetSignExtend*)
{
}
void functor_t::lpm_substitute(Design*, NetSubstitute*)
{
}
void functor_t::lpm_ureduce(Design*, NetUReduce*)
{
}
@@ -215,6 +223,11 @@ void NetFF::functor_node(Design*des, functor_t*fun)
fun->lpm_ff(des, this);
}
void NetLatch::functor_node(Design*des, functor_t*fun)
{
fun->lpm_latch(des, this);
}
void NetLiteral::functor_node(Design*des, functor_t*fun)
{
fun->lpm_literal(des, this);
@@ -255,6 +268,11 @@ void NetSignExtend::functor_node(Design*des, functor_t*fun)
fun->sign_extend(des, this);
}
void NetSubstitute::functor_node(Design*des, functor_t*fun)
{
fun->lpm_substitute(des, this);
}
void NetUReduce::functor_node(Design*des, functor_t*fun)
{
fun->lpm_ureduce(des, this);
+7 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL_functor_H
#define IVL_functor_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
@@ -75,6 +75,9 @@ struct functor_t {
/* This method is called for each FF in the design. */
virtual void lpm_ff(class Design*des, class NetFF*);
/* This method is called for each LATCH in the design. */
virtual void lpm_latch(class Design*des, class NetLatch*);
/* Handle LPM combinational logic devices. */
virtual void lpm_logic(class Design*des, class NetLogic*);
@@ -89,6 +92,9 @@ struct functor_t {
/* This method is called for each power. */
virtual void lpm_pow(class Design*des, class NetPow*);
/* This method is called for each part substitute. */
virtual void lpm_substitute(class Design*des, class NetSubstitute*);
/* This method is called for each unary reduction gate. */
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
+7 -2
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
+10 -1
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"
;;
@@ -92,6 +96,11 @@ do
exit;
;;
--ccflags)
echo "$CXXFLAGS"
exit;
;;
--ldflags)
echo "$LDFLAGS"
exit;
@@ -148,4 +157,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
+6
View File
@@ -181,6 +181,7 @@ ivl_parameter_width
ivl_path_condit
ivl_path_delay
ivl_path_is_condit
ivl_path_is_parallel
ivl_path_scope
ivl_path_source
ivl_path_source_negedge
@@ -211,6 +212,9 @@ ivl_scope_enumerates
ivl_scope_event
ivl_scope_events
ivl_scope_file
ivl_scope_func_type
ivl_scope_func_signed
ivl_scope_func_width
ivl_scope_is_auto
ivl_scope_is_cell
ivl_scope_lineno
@@ -277,6 +281,7 @@ ivl_stmt_block_stmt
ivl_stmt_call
ivl_stmt_case_count
ivl_stmt_case_expr
ivl_stmt_case_quality
ivl_stmt_case_stmt
ivl_stmt_cond_expr
ivl_stmt_cond_false
@@ -291,6 +296,7 @@ ivl_stmt_lval
ivl_stmt_lvals
ivl_stmt_lwidth
ivl_stmt_name
ivl_stmt_needs_t0_trigger
ivl_stmt_nevent
ivl_stmt_opcode
ivl_stmt_parm
+56 -14
View File
@@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_H
#define IVL_ivl_target_H
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 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
@@ -265,6 +265,8 @@ typedef enum ivl_logic_e {
IVL_LO_BUFT = 24, /* transparent bufz. (NOT "tri-state") */
IVL_LO_BUFZ = 5,
IVL_LO_CMOS = 22,
IVL_LO_EQUIV = 25,
IVL_LO_IMPL = 26,
IVL_LO_NAND = 6,
IVL_LO_NMOS = 7,
IVL_LO_NOR = 8,
@@ -280,7 +282,6 @@ typedef enum ivl_logic_e {
IVL_LO_RPMOS = 16,
IVL_LO_XNOR = 18,
IVL_LO_XOR = 19,
IVL_LO_UDP = 21
} ivl_logic_t;
@@ -306,8 +307,10 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CONCAT = 16,
IVL_LPM_CONCATZ = 36, /* Transparent concat */
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (casex) */
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
IVL_LPM_CMP_WEQ= 41,
IVL_LPM_CMP_WNE= 42,
IVL_LPM_CMP_EQ = 10,
IVL_LPM_CMP_GE = 1,
IVL_LPM_CMP_GT = 2,
@@ -315,6 +318,7 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CMP_NEE= 19, /* Case NE (!==) */
IVL_LPM_DIVIDE = 12,
IVL_LPM_FF = 3,
IVL_LPM_LATCH = 40,
IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5,
@@ -352,9 +356,12 @@ typedef enum ivl_path_edge_e {
/* Processes are initial, always, or final blocks with a statement. This is
the type of the ivl_process_t object. */
typedef enum ivl_process_type_e ENUM_UNSIGNED_INT {
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1,
IVL_PR_FINAL = 2
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1,
IVL_PR_ALWAYS_COMB = 3,
IVL_PR_ALWAYS_FF = 4,
IVL_PR_ALWAYS_LATCH = 5,
IVL_PR_FINAL = 2
} ivl_process_type_t;
/* These are the sorts of reasons a scope may come to be. These types
@@ -428,6 +435,14 @@ typedef enum ivl_statement_type_e {
IVL_ST_WHILE = 23
} ivl_statement_type_t;
/* Case statements can be tagged as unique/unique0/priority. */
typedef enum ivl_case_quality_t {
IVL_CASE_QUALITY_BASIC = 0, /* no quality flags */
IVL_CASE_QUALITY_UNIQUE = 1,
IVL_CASE_QUALITY_UNIQUE0 = 2,
IVL_CASE_QUALITY_PRIORITY = 3
} ivl_case_quality_t;
/* SystemVerilog allows a system function to be called as a task. */
typedef enum ivl_sfunc_as_task_e {
IVL_SFUNC_AS_TASK_ERROR = 0,
@@ -510,6 +525,10 @@ extern ivl_island_t ivl_branch_island(ivl_branch_t obj);
* ivl_path_is_condit
* Is this a conditional structure? Needed for ifnone.
*
* ivl_path_is_parallel
* This returns true if the path is a parallel connection and
* false if the path is a full connection.
*
* ivl_path_source_posedge
* ivl_path_source_negedge
* These functions return true if the source is edge sensitive.
@@ -520,6 +539,8 @@ extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt);
extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj);
extern int ivl_path_is_condit(ivl_delaypath_t obj);
extern int ivl_path_is_parallel(ivl_delaypath_t obj);
extern int ivl_path_source_posedge(ivl_delaypath_t obj);
extern int ivl_path_source_negedge(ivl_delaypath_t obj);
@@ -1245,8 +1266,10 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* width of a general power is the XXXX of the widths of the
* inputs.
*
* Power may be signed. If so, the output should be sign extended
* to fill in its result.
* Power may be signed. This indicates the type of the exponent. The
* base will always be treated as unsigned. The compiler must ensure
* the width of the base is equal to the width of the output to
* obtain the correct result when the base is really a signed value.
*
* - Part Select (IVL_LPM_PART_VP and IVL_LPM_PART_PV)
* There are two part select devices, one that extracts a part from a
@@ -1309,8 +1332,13 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* inputs and the Q. All the types must be exactly the same.
*
* - D-FlipFlop (IVL_LPM_FF)
* This data is an edge sensitive register. The ivl_lpm_q output and
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
* This device is an edge sensitive register. The ivl_lpm_q output and
* single ivl_lpm_data input are the same width, ivl_lpm_width. This
* device carries a vector like other LPM devices.
*
* - Latch (IVL_LPM_LATCH)
* This device is an asynchronous latch. The ivl_lpm_q output and
* single ivl_lpm_data input are the same width, ivl_lpm_width. This
* device carries a vector like other LPM devices.
*
* - Memory port (IVL_LPM_RAM) (deprecated in favor of IVL_LPM_ARRAY)
@@ -1428,18 +1456,18 @@ extern unsigned ivl_lpm_negedge(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF */
/* IVL_LPM_FF IVL_LPM_LATCH*/
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE */
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ
IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE */
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);
@@ -1745,6 +1773,13 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
* ivl_scope_lineno
* Returns the instantiation file and line for this scope.
*
* ivl_scope_func_type
* ivl_scope_func_signed
* ivl_scope_func_width
*
* If the scope is a function, these function can be used to get
* the type of the return value.
*
* ivl_scope_is_auto
* Is the task or function declared to be automatic?
*
@@ -1863,6 +1898,9 @@ extern const char* ivl_scope_tname(ivl_scope_t net);
extern int ivl_scope_time_precision(ivl_scope_t net);
extern int ivl_scope_time_units(ivl_scope_t net);
extern ivl_variable_type_t ivl_scope_func_type(ivl_scope_t net);
extern int ivl_scope_func_signed(ivl_scope_t net);
extern unsigned ivl_scope_func_width(ivl_scope_t net);
/* SIGNALS
* Signals are named things in the Verilog source, like wires and
@@ -2084,6 +2122,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* handle disable statements.
*
* ivl_stmt_events
* ivl_stmt_needs_t0_trigger
* ivl_stmt_nevent
* Statements that have event arguments (TRIGGER and WAIT) make
* those event objects available through these methods.
@@ -2198,6 +2237,8 @@ extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
extern unsigned ivl_stmt_case_count(ivl_statement_t net);
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i);
/* IVL+ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net);
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i);
/* IVL_ST_CONDIT IVL_ST_CASE IVL_ST_REPEAT IVL_ST_WHILE */
@@ -2211,6 +2252,7 @@ extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net);
/* IVL_ST_DELAY */
extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
/* IVL_ST_WAIT IVL_ST_TRIGGER */
extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net);
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
/* IVL_ST_CONTRIB */
@@ -2319,7 +2361,7 @@ extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
#if defined(__MINGW32__) || defined (__CYGWIN32__)
#if defined(__MINGW32__) || defined (__CYGWIN__)
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT
+1 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_priv_H
#define IVL_ivl_target_priv_H
/*
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2019 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,8 +51,6 @@ struct ivl_design_s {
ivl_process_t threads_;
// Keep arrays of root scopes.
std::map<const NetScope*,ivl_scope_t> classes;
std::map<const NetScope*,ivl_scope_t> root_tasks;
std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots;
+5 -3
View File
@@ -60,7 +60,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=ivlpp/$@
@@ -71,9 +71,11 @@ ivlpp@EXEEXT@: $O
lexor.c: $(srcdir)/lexor.lex
$(LEX) -t $< > $@
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
install: all installdirs installfiles
$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
F = ivlpp@EXEEXT@
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@"
installdirs: $(srcdir)/../mkinstalldirs
+4 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL_globals_H
#define IVL_globals_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@@ -53,6 +53,9 @@ extern char dep_mode;
extern int verbose_flag;
extern int warn_redef;
extern int warn_redef_all;
/* This is the entry to the lexer. */
extern int yylex(void);
+162 -84
View File
@@ -1,7 +1,7 @@
%option prefix="yy"
%{
/*
* Copyright (c) 1999-2015 Stephen Williams ([email protected])
* Copyright (c) 1999-2020 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -148,38 +148,49 @@ 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 `` delimiter. \
If the delimiter terminates a defined macro usage, leave \
it in place, otherwise remove it now. */ \
if (!(yytext[0] == '`' && is_defined(yytext+1))) { \
while ((istack->str[0] == '`') && \
(istack->str[1] == '`')) { \
istack->str += 2; \
} \
} \
if (*istack->str == 0) { \
result = YY_NULL; \
} else { \
buf[0] = *istack->str++; \
result = 1; \
} \
} \
} while (0)
static int comment_enter = 0;
static int pragma_enter = 0;
static int string_enter = 0;
static int prev_state = 0;
static int ma_parenthesis_level = 0;
%}
%option stack
%option nounput
%option noinput
%option noyy_top_state
%option noyywrap
%x PPINCLUDE
%x DEF_NAME
%x DEF_ESC
%x DEF_ARG
%x DEF_SEP
%x DEF_TXT
%x MN_ESC
%x MA_START
%x MA_ADD
%x CCOMMENT
@@ -188,6 +199,11 @@ static int ma_parenthesis_level = 0;
%x CSTRING
%x ERROR_LINE
%x IFDEF_NAME
%x IFNDEF_NAME
%x ELSIF_NAME
%x ELSIF_SUPR
%x IFDEF_FALSE
%s IFDEF_TRUE
%x IFDEF_SUPR
@@ -242,15 +258,7 @@ 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.
/* Strings do not contain preprocessor directives or macro expansions.
*/
\" { string_enter = YY_START; BEGIN(CSTRING); ECHO; }
<CSTRING>\\\\ |
@@ -332,6 +340,11 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*{W}? { BEGIN(DEF_TXT); def_start(); }
<DEF_NAME>\\ { BEGIN(DEF_ESC); }
<DEF_ESC>[^ \t\b\f\n\r]+{W}"("{W}? { BEGIN(DEF_ARG); def_start(); }
<DEF_ESC>[^ \t\b\f\n\r]+{W} { BEGIN(DEF_TXT); def_start(); }
/* define arg: <name> = <text> */
<DEF_ARG>[a-zA-Z_][a-zA-Z0-9_$]*{W}*"="[^,\)]*{W}? { BEGIN(DEF_SEP); def_add_arg(); }
/* define arg: <name> */
@@ -346,7 +359,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<DEF_ARG,DEF_SEP>(\n|"\r\n"|"\n\r"|\r){W}? { istack->lineno += 1; fputc('\n', yyout); }
<DEF_NAME,DEF_ARG,DEF_SEP>. {
<DEF_NAME,DEF_ESC,DEF_ARG,DEF_SEP>. {
emit_pathline(istack);
fprintf(stderr, "error: malformed `define directive.\n");
error_count += 1;
@@ -393,56 +406,51 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
* condition that stacks on top of the IFDEF_FALSE so that output is
* not accidentally turned on within nested ifdefs.
*/
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char* name = strchr(yytext, '`'); assert(name);
name += 6;
name += strspn(name, " \t\b\f");
`ifdef{W} {
ifdef_enter();
if (is_defined(name))
yy_push_state(IFDEF_TRUE);
else
yy_push_state(IFDEF_FALSE);
yy_push_state(IFDEF_NAME);
}
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char* name = strchr(yytext, '`'); assert(name);
name += 7;
name += strspn(name, " \t\b\f");
`ifndef{W} {
ifdef_enter();
if (!is_defined(name))
yy_push_state(IFDEF_TRUE);
else
yy_push_state(IFDEF_FALSE);
yy_push_state(IFNDEF_NAME);
}
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} |
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { ifdef_enter(); yy_push_state(IFDEF_SUPR); }
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { BEGIN(IFDEF_SUPR); }
<IFDEF_TRUE>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_SUPR); }
<IFDEF_FALSE>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_NAME); }
<IFDEF_SUPR>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_SUPR); }
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char* name = strchr(yytext, '`'); assert(name);
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else {}
name += 6;
name += strspn(name, " \t\b\f");
if (is_defined(name))
<IFDEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
if (is_defined(yytext))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
<IFNDEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
if (!is_defined(yytext))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else {}
<ELSIF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
if (is_defined(yytext))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<ELSIF_SUPR>[a-zA-Z_][a-zA-Z0-9_$]* {
BEGIN(IFDEF_SUPR);
}
<IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* {}
@@ -463,25 +471,45 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
<IFDEF_NAME>(\n|\r) |
<IFDEF_NAME>. |
`ifdef {
error_count += 1;
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
if (YY_START == IFDEF_NAME) {
ifdef_leave();
yy_pop_state();
unput(yytext[0]);
}
}
<IFNDEF_NAME>(\n|\r) |
<IFNDEF_NAME>. |
`ifndef {
error_count += 1;
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
if (YY_START == IFNDEF_NAME) {
ifdef_leave();
yy_pop_state();
unput(yytext[0]);
}
}
<ELSIF_NAME,ELSIF_SUPR>(\n|\r) |
<ELSIF_NAME,ELSIF_SUPR>. |
`elsif {
error_count += 1;
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1);
if (YY_START != INITIAL) {
BEGIN(prev_state);
unput(yytext[0]);
}
}
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
<INITIAL>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
error_count += 1;
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
@@ -514,28 +542,53 @@ 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.
*/
``[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);
}
`\\ { yy_push_state(MN_ESC); }
<MN_ESC>[^ \t\b\f\n\r]+ {
yy_pop_state();
if (macro_needs_args(yytext))
yy_push_state(MA_START);
else
do_expand(0);
}
`` { if (istack->file != NULL) ECHO; }
<MN_ESC>. {
yy_pop_state();
unput(yytext[0]);
emit_pathline(istack);
fprintf(stderr, "error: malformed macro name.\n");
error_count += 1;
}
/* Stringified version of macro expansion. This is an Icarus extension.
When expanding macro text, the SV usage of `` takes precedence. */
``[a-zA-Z_][a-zA-Z0-9_$]* {
if (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);
} else {
REJECT;
}
}
/* If we are expanding a macro, remove the SV `` delimiter, otherwise
* leave it to be handled by the normal rules.
*/
`` { if (istack->file) REJECT; }
/* If we are expanding a macro, handle the SV `" override. This avoids
* entering CSTRING state, thus allowing nested macro expansions.
*/
`\" { if (!istack->file) fputc('"', yyout); else REJECT; }
/* If we are expanding a macro, handle the SV `\`" escape sequence.
*/
`\\`\" { if (!istack->file) fputs("\\\"", yyout); else REJECT; }
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
@@ -571,7 +624,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<MA_ADD>{W} { macro_add_to_arg(1); }
<MA_ADD>"(" { macro_add_to_arg(0); ma_parenthesis_level++; }
<MA_ADD>[({] { macro_add_to_arg(0); ma_parenthesis_level++; }
<MA_ADD>"," {
if (ma_parenthesis_level > 0)
@@ -580,7 +633,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
macro_finish_arg();
}
<MA_ADD>")" {
<MA_ADD>[)}] {
if (ma_parenthesis_level > 0) {
macro_add_to_arg(0);
ma_parenthesis_level--;
@@ -797,8 +850,13 @@ static void def_add_arg(void)
/* This can happen because we are also processing "argv[0]", the
macro name, as a pseudo-argument. The lexor will match that
as name(, so chop off the ( here. */
if (yytext[length - 1] == '(') length--;
as name(, so chop off the ( here. If we have an escaped name,
we also need to strip off the white space that terminates the
name. */
if (yytext[length - 1] == '(') {
length--;
while (isspace((int)yytext[length - 1])) length--;
}
yytext[length] = 0;
@@ -854,6 +912,25 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
{
int idx;
struct define_t* def;
struct define_t* prev;
/* Verilog has a very nasty system of macros jumping from
* file to file, resulting in a global macro scope. Here
* we optionally warn about any redefinitions.
*
* If istack is empty, we are processing a configuration
* or precompiled macro file, so don't want to check for
* redefinitions - when a precompiled macro file is used,
* it will contain copies of any predefined macros.
*/
if (warn_redef && istack) {
prev = def_lookup(name);
if (prev && (warn_redef_all || (strcmp(prev->value, value) != 0))) {
emit_pathline(istack);
fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n",
name, prev->value, value);
}
}
def = malloc(sizeof(struct define_t));
def->name = strdup(name);
@@ -1658,7 +1735,8 @@ static void do_include(void)
}
for (idx = start ; idx < include_cnt ; idx += 1) {
sprintf(path, "%s/%s", include_dir[idx], standby->path);
snprintf(path, sizeof(path), "%s/%s",
include_dir[idx], standby->path);
if ((standby->file = fopen(path, "r"))) {
standby->file_close = fclose;
@@ -2096,7 +2174,7 @@ void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
+19 -3
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2011 Stephen Williams ([email protected])";
"Copyright (c) 1999-2020 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -98,6 +98,10 @@ int line_direct_flag = 0;
unsigned error_count = 0;
FILE *depend_file = NULL;
/* Should we warn about macro redefinitions? */
int warn_redef = 0;
int warn_redef_all = 0;
static int flist_read_flags(const char*path)
{
char line_buf[2048];
@@ -282,7 +286,7 @@ int main(int argc, char*argv[])
include_dir[0] = 0; /* 0 is reserved for the current files path. */
include_dir[1] = strdup(".");
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vVW:")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
@@ -336,6 +340,15 @@ int main(int argc, char*argv[])
break;
}
case 'W':
if (strcmp(optarg, "redef-all") == 0) {
warn_redef_all = 1;
warn_redef = 1;
} else if (strcmp(optarg, "redef-chg") == 0) {
warn_redef = 1;
}
break;
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
@@ -366,7 +379,10 @@ int main(int argc, char*argv[])
" -p<fil> - Write precompiled defines to <fil>\n"
" -P<fil> - Read precompiled defines from <fil>\n"
" -v - Verbose\n"
" -V - Print version information and quit\n",
" -V - Print version information and quit\n"
" -W<cat> - Enable extra ivlpp warning category:\n"
" o redef-all - all macro redefinitions\n"
" o redef-chg - macro definition changes\n",
argv[0]);
return flag_errors;
}
+84 -33
View File
@@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -51,6 +51,22 @@
*/
extern YYLTYPE yylloc;
char* yytext_string_filter(const char*str, size_t str_len)
{
if (str == 0) return 0;
char*buf = new char[str_len+1];
for (size_t idx = 0 ; idx < str_len ; idx += 1) {
if (str[idx] == 0) {
VLerror(yylloc, "error: Found nil (\\000) in string literal, replacing with space (\\015) character.");
buf[idx] = ' ';
} else {
buf[idx] = str[idx];
}
}
buf[str_len] = 0;
return buf;
}
char* strdupnew(char const *str)
{
return str ? strcpy(new char [strlen(str)+1], str) : 0;
@@ -72,6 +88,7 @@ static const char* set_file_name(char*text)
void reset_lexor();
static void line_directive();
static void line_directive2();
static void reset_all();
verinum*make_unsized_binary(const char*txt);
verinum*make_undef_highz_dec(const char*txt);
@@ -187,8 +204,11 @@ TU [munpf]
"!=" { return K_NE; }
"===" { return K_CEQ; }
"!==" { return K_CNE; }
"==?" { return K_WEQ; }
"!=?" { return K_WNE; }
"||" { return K_LOR; }
"&&" { return K_LAND; }
"<->" { return K_LEQUIV; }
"&&&" { return K_TAND; }
"~|" { return K_NOR; }
"~^" { return K_NXOR; }
@@ -227,12 +247,12 @@ TU [munpf]
<CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
<CSTRING>\n { BEGIN(0);
yylval.text = strdupnew(yytext);
yylval.text = yytext_string_filter(yytext, yyleng);
VLerror(yylloc, "Missing close quote of string.");
yylloc.first_line += 1;
return STRING; }
<CSTRING>\" { BEGIN(0);
yylval.text = strdupnew(yytext);
yylval.text = yytext_string_filter(yytext, yyleng);
yylval.text[strlen(yytext)-1] = 0;
return STRING; }
<CSTRING>. { yymore(); }
@@ -310,15 +330,6 @@ TU [munpf]
BEGIN(UDPTABLE);
break;
/* Translate these to checks if we already have or are
* outside the declaration region. */
case K_timeunit:
if (have_timeunit_decl) rc = K_timeunit_check;
break;
case K_timeprecision:
if (have_timeprec_decl) rc = K_timeprecision_check;
break;
default:
yylval.text = 0;
break;
@@ -368,7 +379,7 @@ TU [munpf]
/* If this identifier names a previously declared type, then
return this as a TYPE_IDENTIFIER instead. */
if (rc == IDENTIFIER && gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
rc = TYPE_IDENTIFIER;
@@ -389,7 +400,7 @@ TU [munpf]
}
}
if (gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
return TYPE_IDENTIFIER;
@@ -428,22 +439,38 @@ TU [munpf]
if (strcmp(yytext,"$attribute") == 0)
return KK_attribute;
if (gn_system_verilog() && strcmp(yytext,"$unit") == 0) {
yylval.package = pform_units.back();
return PACKAGE_IDENTIFIER;
}
yylval.text = strdupnew(yytext);
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 +496,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; }
@@ -556,11 +583,7 @@ TU [munpf]
"definition." << endl;
error_count += 1;
} else {
pform_set_default_nettype(NetNet::WIRE, yylloc.text,
yylloc.first_line);
in_celldefine = false;
uc_drive = UCD_NONE;
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
reset_all();
} }
/* Notice and handle the `unconnected_drive directive. */
@@ -847,7 +870,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 {
@@ -862,6 +885,14 @@ verinum*make_unsized_binary(const char*txt)
for (const char*idx = ptr ; *idx ; idx += 1)
if (*idx != '_') size += 1;
if (size == 0) {
VLerror(yylloc, "Numeric literal has no digits in it.");
verinum*out = new verinum();
out->has_sign(sign_flag);
out->is_single(single_flag);
return out;
}
if ((based_size > 0) && (size > based_size)) yywarn(yylloc,
"extra digits given for sized binary constant.");
@@ -1579,6 +1610,18 @@ static void line_directive2()
yylloc.first_line = lineno;
}
/*
* Reset all compiler directives. This will be called when a `resetall
* directive is encountered or when a new compilation unit is started.
*/
static void reset_all()
{
pform_set_default_nettype(NetNet::WIRE, yylloc.text, yylloc.first_line);
in_celldefine = false;
uc_drive = UCD_NONE;
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
}
extern FILE*vl_input;
void reset_lexor()
{
@@ -1587,6 +1630,14 @@ void reset_lexor()
/* Announce the first file name. */
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
if (separate_compilation) {
reset_all();
if (!keyword_mask_stack.empty()) {
lexor_keyword_mask = keyword_mask_stack.back();
keyword_mask_stack.clear();
}
}
}
/*
@@ -1596,7 +1647,7 @@ void destroy_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
+36 -9
View File
@@ -29,11 +29,13 @@ static char **string_pool = NULL;
static unsigned string_pool_count = 0;
#endif
static const unsigned DEFAULT_CELL_SIZE = 0x10000;
StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
cell_ptr_ = 0;
}
StringHeap::~StringHeap()
@@ -45,28 +47,53 @@ StringHeap::~StringHeap()
const char* StringHeap::add(const char*text)
{
unsigned len = strlen(text);
assert((len+1) <= HEAPCELL);
unsigned rem = cell_base_==0? 0 : (DEFAULT_CELL_SIZE - cell_ptr_);
unsigned rem = HEAPCELL - cell_ptr_;
// Special case: huge items get their own allocation.
if ( (len+1) >= DEFAULT_CELL_SIZE ) {
char*buf = strdup(text);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char**)realloc(string_pool,
string_pool_count*sizeof(char**));
string_pool[string_pool_count-1] = buf;
#endif
return buf;
}
// If the current cell that I'm working through cannot hold
// the current string, then set it aside and get another cell
// to put the string into.
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
// release any unused memory. This assumes that a
// realloc shrink of the memory region will return the
// same pointer.
if (rem > 0) {
char*old = cell_base_;
cell_base_ = (char*)realloc(cell_base_, cell_ptr_);
assert(cell_base_ != 0);
assert(cell_base_ == old);
}
// start new cell
cell_base_ = (char*)malloc(DEFAULT_CELL_SIZE);
cell_ptr_ = 0;
rem = DEFAULT_CELL_SIZE;
assert(cell_base_ != 0);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_;
#endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
assert( (len+1) <= rem );
char*res = cell_base_ + cell_ptr_;
memcpy(res, text, len);
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL);
assert(cell_ptr_ <= DEFAULT_CELL_SIZE);
return res;
}
+1 -4
View File
@@ -46,7 +46,7 @@ class perm_string {
private:
friend class StringHeap;
friend class StringHeapLex;
perm_string(const char*t) : text_(t) { };
explicit perm_string(const char*t) : text_(t) { };
private:
const char*text_;
@@ -78,11 +78,8 @@ class StringHeap {
perm_string make(const char*);
private:
enum { HEAPCELL = 0x10000 };
char*cell_base_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);
+8 -4
View File
@@ -47,7 +47,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@
LDTARGETFLAGS = @LDTARGETFLAGS@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
@@ -76,7 +76,9 @@ distclean: clean
rm -f config.h stamp-config-h
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
--suppressions-list=$(srcdir)/cppcheck.sup \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in
cd ..; ./config.status --file=libveriuser/$@
@@ -101,9 +103,11 @@ libveriuser.a: libveriuser.o
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep
install:: all installdirs $(libdir)/libveriuser$(suffix).a $(INSTALL32)
install:: all installdirs installfiles
$(libdir)/libveriuser$(suffix).a: ./libveriuser.a
F = ./libveriuser.a
installfiles: $(F) | installdirs
$(INSTALL_DATA) ./libveriuser.a "$(DESTDIR)$(libdir)/libveriuser$(suffix).a"
installdirs: $(srcdir)/../mkinstalldirs
+187
View File
@@ -0,0 +1,187 @@
// These are the functions that the runtime exports.
// The ACC functions.
// acc_close()
unusedFunction:a_close.c:23
// acc_compare_handles()
unusedFunction:a_compare_handles.c:23
// acc_configure()
unusedFunction:a_configure.c:25
// acc_fetch_argc()
unusedFunction:a_fetch_argc.c:27
// acc_fetch_argv()
unusedFunction:a_fetch_argv.c:27
// acc_fetch_defname()
unusedFunction:a_fetch_fullname.c:37
// acc_fetch_direction()
unusedFunction:a_fetch_dir.c:26
// acc_fetch_fulltype()
unusedFunction:a_fetch_type.c:66
// acc_fetch_itfarg()
unusedFunction:a_fetch_tfarg.c:27
// acc_fetch_location()
unusedFunction:a_fetch_location.c:23
// acc_fetch_name()
unusedFunction:a_fetch_fullname.c:32
// acc_fetch_paramtype()
unusedFunction:a_fetch_type_str.c:47
// acc_fetch_paramval()
unusedFunction:a_fetch_param.c:25
// acc_fetch_range()
unusedFunction:a_fetch_range.c:26
// acc_fetch_size()
unusedFunction:a_fetch_type.c:24
// acc_fetch_tfarg()
unusedFunction:a_fetch_tfarg.c:56
// acc_fetch_tfarg_int()
unusedFunction:a_fetch_tfarg.c:91
// acc_fetch_timescale_info()
unusedFunction:a_fetch_time.c:24
// acc_fetch_type()
unusedFunction:a_fetch_type.c:29
// acc_fetch_type_str()
unusedFunction:a_fetch_type_str.c:24
// acc_fetch_value()
unusedFunction:a_fetch_value.c:115
// acc_handle_by_name()
unusedFunction:a_handle_by_name.c:29
// acc_handle_hiconn()
unusedFunction:a_handle_hiconn.c:26
// acc_handle_object()
unusedFunction:a_handle_object.c:26
// acc_handle_parent()
unusedFunction:a_handle_parent.c:24
// acc_handle_scope()
unusedFunction:a_handle_parent.c:34
// acc_handle_simulated_net()
unusedFunction:a_handle_simulated_net.c:26
// acc_handle_tfarg()
unusedFunction:a_handle_tfarg.c:26
// acc_handle_tfinst()
unusedFunction:a_handle_tfarg.c:53
// acc_initialize()
unusedFunction:a_initialize.c:24
// acc_next_bit()
unusedFunction:a_next_bit.c:26
// acc_next_port()
unusedFunction:a_next_port.c:26
// acc_next_scope()
unusedFunction:a_next.c:86
// acc_next_topmod()
unusedFunction:a_next_topmod.c:30
// acc_product_version()
unusedFunction:a_product_version.c:23
// acc_set_scope()
unusedFunction:a_handle_object.c:40
// acc_set_value()
unusedFunction:a_set_value.c:27
// acc_vcl_add()
unusedFunction:a_vcl.c:157
// acc_vcl_delete()
unusedFunction:a_vcl.c:196
// acc_version()
unusedFunction:a_version.c:23
// These are the TF routines.
// io_printf()
unusedFunction:io_print.c:26
// mc_scan_plusargs()
unusedFunction:mc_scan_plusargs.c:27
// tf_asynchoff()
unusedFunction:asynch.c:34
// tf_asynchon()
unusedFunction:asynch.c:28
// tf_dofinish()
unusedFunction:finish.c:26
// tf_dostop()
unusedFunction:finish.c:32
// tf_error()
unusedFunction:io_print.c:45
// tf_exprinfo()
unusedFunction:exprinfo.c:26
// tf_getcstringp()
unusedFunction:getcstringp.c:26
// tf_getlongp()
unusedFunction:getlongp.c:29
// tf_getlongtime()
unusedFunction:getsimtime.c:112
// tf_getp()
unusedFunction:getp.c:73
// tf_getrealp()
unusedFunction:getp.c:120
// tf_gettime()
unusedFunction:getsimtime.c:77
// tf_getworkarea()
unusedFunction:workarea.c:62
// tf_igettimeprecision()
unusedFunction:getsimtime.c:198
// tf_igettimeunit()
unusedFunction:getsimtime.c:228
// tf_long_to_real()
unusedFunction:math.c:47
// tf_message()
unusedFunction:io_print.c:56
// tf_mipname()
unusedFunction:spname.c:47
// tf_multiply_long()
unusedFunction:math.c:27
// tf_nodeinfo()
unusedFunction:nodeinfo.c:27
// tf_nump()
unusedFunction:nump.c:42
// tf_putlongp()
unusedFunction:putlongp.c:28
// tf_putp()
unusedFunction:putp.c:88
// tf_putrealp()
unusedFunction:putp.c:137
// tf_real_to_long()
unusedFunction:math.c:40
// tf_rosynchronize()
unusedFunction:veriusertfs.c:391
// tf_scale_longdelay()
unusedFunction:getsimtime.c:136
// tf_scale_realdelay()
unusedFunction:getsimtime.c:161
// tf_setdelay()
unusedFunction:delay.c:75
// tf_setrealdelay()
unusedFunction:veriusertfs.c:426
// tf_setworkarea()
unusedFunction:workarea.c:36
// tf_spname()
unusedFunction:spname.c:25
// tf_strgetp()
unusedFunction:getp.c:177
// tf_strgettime()
unusedFunction:getsimtime.c:85
// tf_synchronize()
unusedFunction:veriusertfs.c:364
// tf_typep()
unusedFunction:typep.c:24
// tf_unscale_longdelay()
unusedFunction:getsimtime.c:144
// tf_unscale_realdelay()
unusedFunction:getsimtime.c:171
// tf_warning()
unusedFunction:io_print.c:34
// Non-standard TF routines the Icarus provides.
// tf_getlongsimtime()
unusedFunction:getsimtime.c:126
// veriusertfs_register_table()
unusedFunction:veriusertfs.c:76
+1 -1
View File
@@ -31,6 +31,6 @@ extern char* __acc_newstring(const char*txt);
/*
* Trace file for logging ACC and TF calls.
*/
FILE* pli_trace;
extern FILE* pli_trace;
#endif /* IVL_priv_H */
+33 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2018 Michael Ruff (mruff at chiaro.com)
* Michael Runyan (mrunyan at chiaro.com)
*
* This source code is free software; you can redistribute it
@@ -42,8 +42,9 @@ typedef struct t_pli_data {
int paramvc; /* parameter number for misctf */
} s_pli_data, *p_pli_data;
static PLI_INT32 compiletf(char *);
static PLI_INT32 calltf(char *);
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 callback(p_cb_data);
/*
@@ -150,7 +151,7 @@ void veriusertfs_register_table(p_tfcell vtable)
tf_data.tfname = tf->tfname;
tf_data.compiletf = compiletf;
tf_data.calltf = calltf;
tf_data.sizetf = (PLI_INT32 (*)(PLI_BYTE8 *))tf->sizetf;
tf_data.sizetf = sizetf;
tf_data.user_data = (char *)data;
if (pli_trace) {
@@ -180,7 +181,7 @@ void veriusertfs_register_table(p_tfcell vtable)
* This function calls the veriusertfs checktf and sets up all the
* callbacks misctf requires.
*/
static PLI_INT32 compiletf(char *data)
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
p_pli_data pli;
p_tfcell tf;
@@ -260,7 +261,7 @@ static PLI_INT32 compiletf(char *data)
/*
* This function is the wrapper for the veriusertfs calltf routine.
*/
static PLI_INT32 calltf(char *data)
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
int rc = 0;
p_pli_data pli;
@@ -283,6 +284,32 @@ static PLI_INT32 calltf(char *data)
return rc;
}
/*
* This function is the wrapper for the veriusertfs sizetf routine.
*/
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
int rc = 32;
p_pli_data pli;
p_tfcell tf;
/* cast back from opaque */
pli = (p_pli_data)data;
tf = pli->tf;
/* execute sizetf */
if (tf->sizetf) {
if (pli_trace) {
fprintf(pli_trace, "Call %s->sizetf(%d, %d)\n",
tf->tfname, tf->data, reason_sizetf);
}
rc = tf->sizetf(tf->data, reason_sizetf);
}
return rc;
}
/*
* This function is the wrapper for all the misctf callbacks
*/
+30 -5
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
@@ -102,6 +102,17 @@ bool Nexus::drivers_constant() const
break;
}
const NetSubstitute*ps = dynamic_cast<const NetSubstitute*>(cur->get_obj());
if (ps) {
if (ps->pin(1).nexus()->drivers_constant() &&
ps->pin(2).nexus()->drivers_constant() ) {
constant_drivers += 1;
continue;
}
driven_ = VAR;
return false;
}
if (! dynamic_cast<const NetConst*>(cur->get_obj())) {
driven_ = VAR;
return false;
@@ -162,13 +173,13 @@ verinum::V Nexus::driven_value() const
if ((sig->type() == NetNet::SUPPLY0) ||
(sig->type() == NetNet::TRI0)) {
// Multiple drivers are not currently supported.
ivl_assert(*obj, val == verinum::Vz);
ivl_assert(*sig, val == verinum::Vz);
val = verinum::V0;
}
if ((sig->type() == NetNet::SUPPLY1) ||
(sig->type() == NetNet::TRI1)) {
// Multiple drivers are not currently supported.
ivl_assert(*obj, val == verinum::Vz);
ivl_assert(*sig, val == verinum::Vz);
val = verinum::V1;
}
}
@@ -199,10 +210,12 @@ verinum Nexus::driven_vector() const
const Link*cur = list_;
verinum val;
verinum pval;
unsigned width = 0;
for (cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
const NetSubstitute*ps;
const NetConst*obj;
const NetNet*sig;
if ((obj = dynamic_cast<const NetConst*>(cur->get_obj()))) {
@@ -212,6 +225,18 @@ verinum Nexus::driven_vector() const
val = obj->value();
width = val.len();
} else if ((ps = dynamic_cast<const NetSubstitute*>(cur->get_obj()))) {
if (cur->get_pin() != 0)
continue;
// Multiple drivers are not currently supported.
ivl_assert(*ps, val.len() == 0);
val = ps->pin(1).nexus()->driven_vector();
pval = ps->pin(2).nexus()->driven_vector();
for (unsigned idx = 0; idx < pval.len(); idx += 1)
val.set(ps->base() + idx, pval.get(idx));
width = val.len();
} else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
width = sig->vector_width();
@@ -222,13 +247,13 @@ verinum Nexus::driven_vector() const
if ((sig->type() == NetNet::SUPPLY0) ||
(sig->type() == NetNet::TRI0)) {
// Multiple drivers are not currently supported.
ivl_assert(*obj, val.len() == 0);
ivl_assert(*sig, val.len() == 0);
val = verinum(verinum::V0, width);
}
if ((sig->type() == NetNet::SUPPLY1) ||
(sig->type() == NetNet::TRI1)) {
// Multiple drivers are not currently supported.
ivl_assert(*obj, val.len() == 0);
ivl_assert(*sig, val.len() == 0);
val = verinum(verinum::V1, width);
}
}
+9 -33
View File
@@ -54,11 +54,13 @@ extern FILE *depend_file;
* Use the type name as a key, and search the module library for a
* file name that has that key.
*/
bool load_module(const char*type)
bool load_module(const char*type, int&parser_errors)
{
char path[4096];
char*ltype = strdup(type);
parser_errors = 0;
for (char*tmp = ltype ; *tmp ; tmp += 1)
*tmp = tolower(*tmp);
@@ -71,7 +73,8 @@ bool load_module(const char*type)
if (cur == lcur->name_map.end())
continue;
sprintf(path, "%s%c%s", lcur->dir, dir_character, (*cur).second);
snprintf(path, sizeof(path), "%s%c%s",
lcur->dir, dir_character, (*cur).second);
if(depend_file) {
if (depfile_mode == 'p') {
@@ -82,44 +85,17 @@ bool load_module(const char*type)
fflush(depend_file);
}
if (ivlpp_string) {
char*cmdline = (char*)malloc(strlen(ivlpp_string) +
strlen(path) + 4);
strcpy(cmdline, ivlpp_string);
strcat(cmdline, " \"");
strcat(cmdline, path);
strcat(cmdline, "\"");
if (verbose_flag)
cerr << "Loading library file " << path << "." << endl;
if (verbose_flag)
cerr << "Executing: " << cmdline << endl<< flush;
FILE*file = popen(cmdline, "r");
if (verbose_flag)
cerr << "...parsing output from preprocessor..." << endl << flush;
pform_parse(path, file);
pclose(file);
free(cmdline);
} else {
if (verbose_flag)
cerr << "Loading library file "
<< path << "." << endl;
FILE*file = fopen(path, "r");
assert(file);
pform_parse(path, file);
fclose(file);
}
parser_errors = pform_parse(path);
if (verbose_flag)
cerr << "... Load module complete." << endl << flush;
return true;
return parser_errors == 0;
}
return false;
}
-88
View File
@@ -1,88 +0,0 @@
This file describes the procedure to build and install Icarus Verilog
on Mac OS X. I assume that you have experience with Unix and
Terminal.app and a basic knowledge of how to download, compile and
install software from source form.
Yasuhisa Kato wrote another set of instructions that has also been
known to work: <http://adwis.com/verilog/index.html>. You may try
those instructions instead of these, although they are essentially
quite similar.
1) Obtain and install a libdl compatibility library.
If you don't already have /usr/local/lib/libdl.{a,dylib} and
/usr/local/include/dlfcn.h, you can obtain the source for a
compatibility layer from at least one of two places:
http://download.sourceforge.net/fink/dlcompat-20010831.tar.gz
http://www.omnigroup.com/~bungi/dlcompat-20010831.tar.gz
Unpack this tar file and read the README and Makefile. Install the
library according to the instructions. Installation in /usr/local
is strongly recommended since otherwise autoconf very likely won't
be able to find it.
2) Make sure you have a copy of the 'gperf' tool. This does not come
with the Mac OS X 10.1 developer tools, so you probably don't. You
can check with:
% which gperf
If not found, grab a gperf source package and install it. See "GPERF
FOR MACOSX" below.
Snapshots of Icarus Verilog source now come with the
lexor_keyword.cc file pre-made, so if you have trouble with gperf,
then just make sure the distributed lexor_keyword.cc is newer than
lexor_keyword.gperf, and use that.
3) If working with source from git, you must run autoconf in the top
directory. This is simplified by the 'autoconf.sh' script at the
top of the source tree:
sh ./autoconf.sh
This will also run the gperf command, so make sure you've completed
step #2 first.
4) Configure, build and install the Icarus Verilog sources as normal.
The only change you need to make here is to use a configure command like:
% CC="cc -no-cpp-precomp" ./configure
This assumes you are using 'sh', 'zsh', or 'bash'. If you are using
'csh' or 'tcsh', then you'll want something like:
% setenv CC "cc -no-cpp-precomp"
% ./configure
You can, of course, add other configure options.
6) NOTE: 'make check' will not work until after 'make install' has been run
since dynamically loaded code is searched for in the install location
rather than the build location. The dlopen emulation library doesn't
support a search path option.
If you are worried about overwriting a working installation with a new,
potentially broken one, you can always configure using --prefix="/some/path",
and install there to make sure everything is working and then re-configure
with the real path you want to install at, make clean, and make install.
5) Done!
GPERF FOR MACOSX
Get version 2.7.2 of gperf from here:
<ftp://ftp.gnu.org/gnu/gperf/gperf-2.7.2.tar.gz>
Get a MacosX patch from here:
http://www.eternal.nest.or.jp/~shiro/binaries/gperf-2.7.2-macosx-patch.gz
Apply the patch to the gperf-2.7.2 source that you previously
downloaded, then follow the remaining gperf installation
instructions.
+142 -38
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2014 Stephen Williams ([email protected])";
"Copyright (c) 1998-2020 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
@@ -68,7 +68,7 @@ extern "C" int optind;
extern "C" const char*optarg;
#endif
#if defined(__CYGWIN32__) && !defined(HAVE_GETOPT_H)
#if defined(__CYGWIN__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt);
extern "C" int optind;
extern "C" const char*optarg;
@@ -104,10 +104,12 @@ generation_t generation_flag = GN_DEFAULT;
bool gn_icarus_misc_flag = true;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
bool gn_assertions_flag = true;
bool gn_supported_assertions_flag = true;
bool gn_unsupported_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 = true;
bool gn_verilog_ams_flag = false;
/*
@@ -134,11 +136,14 @@ void add_vpi_module(const char*name)
vpi_module_list = tmp;
}
flags["VPI_MODULE_LIST"] = vpi_module_list;
load_vpi_module(name);
}
map<perm_string,unsigned> missing_modules;
map<perm_string,bool> library_file_map;
vector<perm_string> source_files;
list<const char*> library_suff;
list<perm_string> roots;
@@ -153,6 +158,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;
@@ -160,6 +166,12 @@ bool warn_ob_select = false;
bool warn_sens_entire_vec = false;
bool warn_sens_entire_arr = false;
bool warn_anachronisms = false;
bool warn_floating_nets = false;
/*
* Ignore errors about missing modules
*/
bool ignore_missing_modules = false;
/*
* Debug message class flags.
@@ -171,6 +183,11 @@ bool debug_emit = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
/*
* Compilation control flags.
*/
bool separate_compilation = false;
/*
* Optimization control flags.
*/
@@ -224,6 +241,7 @@ const bool CASE_SENSITIVE = true;
bool synthesis = false;
extern void cprop(Design*des);
extern void exposenodes(Design*des);
extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
@@ -234,10 +252,11 @@ static struct net_func_map {
const char*name;
void (*func)(Design*);
} func_table[] = {
{ "cprop", &cprop },
{ "nodangle",&nodangle },
{ "synth", &synth },
{ "synth2", &synth2 },
{ "cprop", &cprop },
{ "exposenodes", &exposenodes },
{ "nodangle", &nodangle },
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
{ 0, 0 }
};
@@ -314,10 +333,16 @@ static void process_generation_flag(const char*gen)
gn_specify_blocks_flag = false;
} else if (strcmp(gen,"assertions") == 0) {
gn_assertions_flag = true;
gn_supported_assertions_flag = true;
gn_unsupported_assertions_flag = true;
} else if (strcmp(gen,"supported-assertions") == 0) {
gn_supported_assertions_flag = true;
gn_unsupported_assertions_flag = false;
} else if (strcmp(gen,"no-assertions") == 0) {
gn_assertions_flag = false;
gn_supported_assertions_flag = false;
gn_unsupported_assertions_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;
@@ -343,6 +368,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 {
}
}
@@ -559,11 +590,15 @@ static bool set_default_timescale(const char*ts_string)
*
* warnings:<string>
* Warning flag letters.
*
* ignore_missing_modules:<bool>
* true to ignore errors about missing modules
*/
bool had_timescale = false;
static void read_iconfig_file(const char*ipath)
{
char buf[8*1024];
vector<pair<char*,bool> > to_build_library_index;
FILE*ifile = fopen(ipath, "r");
if (ifile == 0) {
@@ -572,6 +607,14 @@ static void read_iconfig_file(const char*ipath)
}
while (fgets(buf, sizeof buf, ifile) != 0) {
assert(strlen(buf) < sizeof buf);
if ((strlen(buf) == ((sizeof buf) - 1))
&& buf[sizeof buf -2] != '\n') {
cerr << "WARNING: Line buffer overflow reading iconfig file: "
<< ipath
<< "." << endl;
assert(0);
}
if (buf[0] == '#')
continue;
char*cp = strchr(buf, ':');
@@ -675,9 +718,15 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(buf,"warnings") == 0) {
/* Scan the warnings enable string for warning flags. */
for ( ; *cp ; cp += 1) switch (*cp) {
case 'f':
warn_floating_nets = true;
break;
case 'i':
warn_implicit = true;
break;
case 'd':
warn_implicit_dimensions = true;
break;
case 'l':
warn_inf_loop = true;
break;
@@ -703,11 +752,15 @@ static void read_iconfig_file(const char*ipath)
break;
}
} else if (strcmp(buf, "ignore_missing_modules") == 0) {
if (strcmp(cp, "true") == 0)
ignore_missing_modules = true;
} else if (strcmp(buf, "-y") == 0) {
build_library_index(cp, CASE_SENSITIVE);
to_build_library_index.push_back(make_pair(strdup(cp), CASE_SENSITIVE));
} else if (strcmp(buf, "-yl") == 0) {
build_library_index(cp, false);
to_build_library_index.push_back(make_pair(strdup(cp), false));
} else if (strcmp(buf, "-Y") == 0) {
library_suff.push_back(strdup(cp));
@@ -746,6 +799,54 @@ static void read_iconfig_file(const char*ipath)
}
}
fclose(ifile);
for (vector<pair<char *, bool> >::iterator it = to_build_library_index.begin() ;
it != to_build_library_index.end() ; ++ it ) {
build_library_index(it->first, it->second);
free(it->first);
}
}
/*
* This function reads a list of source file names. Each name starts
* with the first non-space character, and ends with the last non-space
* character. Spaces in the middle are OK.
*/
static void read_sources_file(const char*path)
{
char line_buf[2048];
FILE*fd = fopen(path, "r");
if (fd == 0) {
cerr << "ERROR: Unable to read source file list: " << path << endl;
return;
}
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
// assertion test that we are not overflowing the line
// buffer. Really should make this more robust, but
// better to assert then go weird.
assert(strlen(line_buf) < sizeof line_buf);
if ((strlen(line_buf) == ((sizeof line_buf) - 1))
&& line_buf[sizeof line_buf -2] != '\n') {
cerr << "WARNING: Line buffer overflow reading sources file: "
<< path
<< "." << endl;
assert(0);
}
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
char*tail = cp + strlen(cp);
while (tail > cp) {
if (! isspace((int)tail[-1]))
break;
tail -= 1;
tail[0] = 0;
}
if (cp < tail)
source_files.push_back(filename_strings.make(cp));
}
fclose(fd);
}
extern Design* elaborate(list <perm_string> root);
@@ -825,20 +926,18 @@ int main(int argc, char*argv[])
}
library_suff.push_back(strdup(".v"));
// Start the module list with the base system module.
add_vpi_module("system");
add_vpi_module("vhdl_sys");
flags["-o"] = strdup("a.out");
min_typ_max_flag = TYP;
min_typ_max_warn = 10;
while ((opt = getopt(argc, argv, "C:f:hN:P:p:Vv")) != EOF) switch (opt) {
while ((opt = getopt(argc, argv, "C:F:f:hN:P:p:Vv")) != EOF) switch (opt) {
case 'C':
read_iconfig_file(optarg);
break;
case 'F':
read_sources_file(optarg);
break;
case 'f':
parm_to_flagmap(optarg);
break;
@@ -891,6 +990,7 @@ int main(int argc, char*argv[])
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
"\t-F <file> List of source files from driver.\n"
"\t-h Print usage information, and exit.\n"
"\t-N <file> Dump the elaborated netlist to <file>.\n"
"\t-P <file> Write the parsed input to <file>.\n"
@@ -906,11 +1006,19 @@ int main(int argc, char*argv[])
return 0;
}
if (optind == argc) {
int arg = optind;
while (arg < argc) {
perm_string path = filename_strings.make(argv[arg++]);
source_files.push_back(path);
}
if (source_files.empty()) {
cerr << "No input files." << endl;
return 1;
}
separate_compilation = source_files.size() > 1;
if( depfile_name ) {
depend_file = fopen(depfile_name, "a");
if(! depend_file) {
@@ -922,16 +1030,22 @@ int main(int argc, char*argv[])
switch (generation_flag) {
case GN_VER2012:
lexor_keyword_mask |= GN_KEYWORDS_1800_2012;
// fallthrough
case GN_VER2009:
lexor_keyword_mask |= GN_KEYWORDS_1800_2009;
// fallthrough
case GN_VER2005_SV:
lexor_keyword_mask |= GN_KEYWORDS_1800_2005;
// fallthrough
case GN_VER2005:
lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
// fallthrough
case GN_VER2001:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
// fallthrough
case GN_VER2001_NOCONFIG:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
// fallthrough
case GN_VER1995:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
}
@@ -1005,8 +1119,10 @@ int main(int argc, char*argv[])
if (flag_tmp) disable_concatz_generation = strcmp(flag_tmp,"true")==0;
/* Parse the input. Make the pform. */
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
int rc = pform_parse(argv[optind]);
int rc = 0;
for (unsigned idx = 0; idx < source_files.size(); idx += 1) {
rc += pform_parse(source_files[idx]);
}
if (pf_path) {
ofstream out (pf_path);
@@ -1020,22 +1136,16 @@ int main(int argc, char*argv[])
; cur != disciplines.end() ; ++ cur ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl;
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
pform_dump(out, cur->second);
out << "PFORM DUMP COMPILATION UNITS:" << endl;
for (vector<PPackage*>::iterator pac = pform_units.begin()
; pac != pform_units.end() ; ++ pac) {
pform_dump(out, *pac);
}
out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
pform_dump(out, pac->second);
}
out << "PFORM DUMP MODULES:" << endl;
for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
@@ -1092,7 +1202,7 @@ int main(int argc, char*argv[])
if (roots.empty()) {
cerr << "No top level modules, and no -s option." << endl;
return 1;
return ignore_missing_modules ? 0 : 1;
}
@@ -1107,7 +1217,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;
}
@@ -1153,12 +1263,6 @@ int main(int argc, char*argv[])
(*idx).second = 0;
}
for(map<perm_string,data_type_t*>::iterator it = pform_typedefs.begin()
; it != pform_typedefs.end() ; ++it) {
delete (*it).second;
(*it).second = 0;
}
if (verbose_flag) {
if (times_flag) {
times(cycles+2);
+27
View File
@@ -0,0 +1,27 @@
These are instructions for building Icarus Verilog binaries for
Windows using mingw cross compiler tools on Linux.
To start with, you need the mingw64-cross-* packages for your linux
distribution, which gives you the x86_64-w64-mingw32-* commands
installed on your system. Installing the cross environment is outside
the scope of this writeup.
First, configure with this command:
$ ./configure --host=x86_64-w64-mingw32
This generates the Makefiles needed to cross compile everything with
the mingw32 compiler. The configure script will generate the command
name paths, so long as commands line x86_64-w64-mingw32-gcc
et. al. are in your path.
Next, compile with the command:
$ make
The configure generated the cross compiler flags, but there are a few
bits that need to be compiled with the native compiler. (version.exe
for example is used by the build process but is not installed.) The
configure script should have gotten all that right.
+5 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -42,7 +42,10 @@ unsigned count_lval_width(const NetAssign_*idx)
NetAssign_::NetAssign_(NetAssign_*n)
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
{
lwid_ = 0;
more = 0;
signed_ = false;
turn_sig_to_wire_on_release_ = false;
}
NetAssign_::NetAssign_(NetNet*s)
@@ -51,6 +54,7 @@ NetAssign_::NetAssign_(NetNet*s)
lwid_ = sig_->vector_width();
sig_->incr_lref();
more = 0;
signed_ = false;
turn_sig_to_wire_on_release_ = false;
}
+138 -88
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 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
@@ -101,11 +101,11 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val;
}
NetScope* Design::make_root_scope(perm_string root, bool program_block,
bool is_interface)
NetScope* Design::make_root_scope(perm_string root, NetScope*unit_scope,
bool program_block, bool is_interface)
{
NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, unit_scope,
false, program_block, is_interface);
/* This relies on the fact that the basename return value is
permallocated. */
@@ -125,31 +125,18 @@ list<NetScope*> Design::find_root_scopes() const
return root_scopes_;
}
NetScope* Design::make_package_scope(perm_string name)
NetScope* Design::make_package_scope(perm_string name, NetScope*unit_scope,
bool is_unit)
{
NetScope*scope;
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, false, false);
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, unit_scope,
false, false, false, is_unit);
scope->set_module_name(scope->basename());
packages_[name] = scope;
return scope;
}
void Design::add_class(netclass_t*cl, PClass*pclass)
{
Definitions::add_class(cl);
class_to_pclass_[cl] = pclass;
}
netclass_t* Design::find_class(perm_string name) const
{
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
return 0;
}
NetScope* Design::find_package(perm_string name) const
{
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
@@ -170,17 +157,6 @@ list<NetScope*> Design::find_package_scopes() const
return res;
}
list<NetScope*> Design::find_roottask_scopes() const
{
list<NetScope*>res;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
res.push_back (cur->first);
}
return res;
}
/*
* This method locates a scope in the design, given its rooted
* hierarchical name. Each component of the key is used to scan one
@@ -211,25 +187,6 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
}
}
for (map<NetScope*,PTaskFunc*>::const_iterator root = root_tasks_.begin()
; root != root_tasks_.end() ; ++ root) {
NetScope*cur = root->first;
if (path.front() != cur->fullname())
continue;
std::list<hname_t> tmp = path;
tmp.pop_front();
while (cur) {
if (tmp.empty()) return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
}
}
return 0;
}
@@ -253,6 +210,55 @@ NetScope* Design::find_scope(const hname_t&path) const
return 0;
}
static bool is_design_unit(NetScope*scope)
{
return (scope->type() == NetScope::MODULE && !scope->nested_module())
|| (scope->type() == NetScope::PACKAGE);
}
static bool is_subroutine(NetScope::TYPE type)
{
return type == NetScope::TASK || type == NetScope::FUNC;
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const std::list<hname_t>&path,
NetScope::TYPE type) const
{
std::list<hname_t> tmp = path;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (scope->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& scope->module_name()==key.peek_name()) {
/* Up references may match module name */
} else {
NetScope*found_scope = scope->child(key);
if (found_scope == 0) {
found_scope = scope->find_import(this, key.peek_name());
if (found_scope)
found_scope = found_scope->child(key);
}
scope = found_scope;
if (scope == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
return scope;
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@@ -266,36 +272,68 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
if (path.empty())
return scope;
for ( ; scope ; scope = scope->parent()) {
// Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
std::list<hname_t> tmp = path;
// First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
NetScope*cur = scope;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& cur->module_name()==key.peek_name()) {
// Avoid searching the unit scope twice.
if (scope == unit_scope)
unit_scope = 0;
/* Up references may match module name */
// Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} else {
cur = cur->child( key );
if (cur == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
unit_scope = 0;
}
if (cur) return cur;
scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
}
// Last chance. Look for the name starting at the root.
return find_scope(path);
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const hname_t&path,
NetScope::TYPE type) const
{
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if ((scope->type() == NetScope::MODULE) && (type == NetScope::MODULE)
&& (scope->module_name() == path.peek_name())) {
/* Up references may match module name */
return scope;
}
NetScope*found_scope = scope->child(path);
if (found_scope == 0) {
found_scope = scope->find_import(this, path.peek_name());
if (found_scope)
found_scope = found_scope->child(path);
}
return found_scope;
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@@ -307,24 +345,36 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path,
{
assert(scope);
for ( ; scope ; scope = scope->parent()) {
// Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
NetScope*cur = scope;
// First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE)
&& cur->module_name()==path.peek_name()) {
// Avoid searching the unit scope twice.
if (scope == unit_scope)
unit_scope = 0;
/* Up references may match module name */
// Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} else {
cur = cur->child( path );
unit_scope = 0;
}
if (cur) return cur;
scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
}
// Last chance. Look for the name starting at the root.
@@ -826,6 +876,11 @@ NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
if (NetNet*net = scope->find_signal(key))
return net;
if (NetScope*import_scope = scope->find_import(this, key)) {
scope = import_scope;
continue;
}
if (scope->type() == NetScope::MODULE)
break;
@@ -867,11 +922,6 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
return 0;
}
void Design::add_root_task(NetScope*tscope, PTaskFunc*tf)
{
root_tasks_[tscope] = tf;
}
void Design::add_node(NetNode*net)
{
assert(net->design_ == 0);
@@ -890,8 +940,8 @@ void Design::add_node(NetNode*net)
void Design::del_node(NetNode*net)
{
assert(net->design_ == this);
assert(net != 0);
assert(net->design_ == this);
/* Interact with the Design::functor method by manipulating the
cur and nxt pointers that it is using. */
+9 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 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
@@ -28,6 +28,7 @@
NetEvent::NetEvent(perm_string n)
: name_(n)
{
local_flag_ = false;
scope_ = 0;
snext_ = 0;
probes_ = 0;
@@ -345,7 +346,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
}
NetEvWait::NetEvWait(NetProc*pr)
: statement_(pr)
: statement_(pr), has_t0_trigger_(false)
{
}
@@ -369,6 +370,7 @@ NetEvWait::~NetEvWait()
tmp->next = tmp->next->next;
delete tmp;
}
delete tgt;
}
events_.clear();
}
@@ -441,3 +443,8 @@ NetProc* NetEvWait::statement()
{
return statement_;
}
const NetProc* NetEvWait::statement() const
{
return statement_;
}
+21 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2020 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
@@ -403,7 +403,14 @@ ivl_variable_type_t NetEProperty::expr_type() const
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
ivl_select_type_t sel_type)
: expr_(exp), base_(base), sel_type_(sel_type)
: expr_(exp), base_(base), use_type_(0), sel_type_(sel_type)
{
expr_width(wid);
}
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
ivl_type_t use_type)
: expr_(exp), base_(base), use_type_(use_type), sel_type_(IVL_SEL_OTHER)
{
expr_width(wid);
}
@@ -431,6 +438,9 @@ ivl_select_type_t NetESelect::select_type() const
ivl_variable_type_t NetESelect::expr_type() const
{
if (use_type_)
return use_type_->base_type();
ivl_variable_type_t type = expr_->expr_type();
// Special case: If the sub-expression is an IVL_VT_STRING,
@@ -439,20 +449,12 @@ ivl_variable_type_t NetESelect::expr_type() const
if (type == IVL_VT_STRING && expr_width()==8)
return IVL_VT_BOOL;
if (type != IVL_VT_DARRAY)
return type;
return type;
}
ivl_assert(*this, type == IVL_VT_DARRAY);
// Special case: If the expression is a DARRAY, then the
// sub-expression must be a NetESignal and the type of the
// NetESelect expression is the element type of the arrayed signal.
NetESignal*sig = dynamic_cast<NetESignal*>(expr_);
ivl_assert(*this, sig);
const netarray_t*array_type = dynamic_cast<const netarray_t*> (sig->sig()->net_type());
ivl_assert(*this, array_type);
return array_type->element_type()->base_type();
const netenum_t* NetESelect::enumeration() const
{
return dynamic_cast<const netenum_t*> (use_type_);
}
bool NetESelect::has_width() const
@@ -461,15 +463,15 @@ bool NetESelect::has_width() const
}
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
unsigned width, unsigned np)
: name_(0), type_(t), enum_type_(0), parms_(np)
unsigned width, unsigned np, bool is_overridden)
: name_(0), type_(t), enum_type_(0), parms_(np), is_overridden_(is_overridden)
{
name_ = lex_strings.add(n);
expr_width(width);
}
NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np)
: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np), is_overridden_(false)
{
name_ = lex_strings.add(n);
expr_width(rtype->packed_width());
@@ -485,7 +487,7 @@ NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
}
NetESFunc::NetESFunc(const char*n, const netenum_t*enum_type, unsigned np)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np), is_overridden_(false)
{
name_ = lex_strings.add(n);
expr_width(enum_type->packed_width());
+154 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2018 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
@@ -23,6 +23,10 @@
# include <typeinfo>
# include "ivl_assert.h"
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
using namespace std;
/*
@@ -88,6 +92,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 +217,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 +369,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 +455,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 +513,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
@@ -874,7 +1022,7 @@ NetExpr* NetESignal::evaluate_function(const LineInfo&loc,
NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{
auto_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
unique_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
switch (const_logical(cval.get())) {
+26 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 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
@@ -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()) {
@@ -467,6 +481,17 @@ NetNet* Nexus::pick_any_net()
return 0;
}
NetNode* Nexus::pick_any_node()
{
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
NetNode*node = dynamic_cast<NetNode*>(cur->get_obj());
if (node != 0)
return node;
}
return 0;
}
const char* Nexus::name() const
{
if (name_)
+258 -136
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2019 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,37 +19,37 @@
# include "config.h"
# include <iostream>
# include <iostream>
# include <set>
# include <cassert>
# include <typeinfo>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
NexusSet* NetExpr::nex_input(bool)
NexusSet* NetExpr::nex_input(bool, bool, bool) const
{
cerr << get_fileline()
<< ": internal error: nex_input not implemented: "
<< *this << endl;
return 0;
return new NexusSet;
}
NexusSet* NetProc::nex_input(bool)
NexusSet* NetProc::nex_input(bool, bool, bool) const
{
cerr << get_fileline()
<< ": internal error: NetProc::nex_input not implemented"
<< endl;
return 0;
return new NexusSet;
}
NexusSet* NetEArrayPattern::nex_input(bool rem_out)
NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
if (items_[idx]==0) continue;
NexusSet*tmp = items_[idx]->nex_input(rem_out);
NexusSet*tmp = items_[idx]->nex_input(rem_out, always_sens, nested_func);
if (tmp == 0) continue;
result->add(*tmp);
@@ -58,32 +58,32 @@ NexusSet* NetEArrayPattern::nex_input(bool rem_out)
return result;
}
NexusSet* NetEBinary::nex_input(bool rem_out)
NexusSet* NetEBinary::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = left_->nex_input(rem_out);
NexusSet*tmp = right_->nex_input(rem_out);
NexusSet*result = left_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = right_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEConcat::nex_input(bool rem_out)
NexusSet* NetEConcat::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
if (parms_[0] == NULL) return new NexusSet;
NexusSet*result = parms_[0]->nex_input(rem_out, always_sens, nested_func);
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx] == NULL) {
delete result;
return NULL;
return new NexusSet;
}
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetEAccess::nex_input(bool)
NexusSet* NetEAccess::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
@@ -91,63 +91,73 @@ NexusSet* NetEAccess::nex_input(bool)
/*
* A constant has not inputs, so always return an empty set.
*/
NexusSet* NetEConst::nex_input(bool)
NexusSet* NetEConst::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetECReal::nex_input(bool)
NexusSet* NetECReal::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEEvent::nex_input(bool)
NexusSet* NetEEvent::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetELast::nex_input(bool)
NexusSet* NetELast::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetENetenum::nex_input(bool)
NexusSet* NetENetenum::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetENew::nex_input(bool)
NexusSet* NetENew::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetENull::nex_input(bool)
NexusSet* NetENull::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEProperty::nex_input(bool)
NexusSet* NetEProperty::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEScope::nex_input(bool)
NexusSet* NetEScope::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetESelect::nex_input(bool rem_out)
NexusSet* NetESelect::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
NexusSet*result = base_? base_->nex_input(rem_out, always_sens, nested_func) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out, always_sens, nested_func);
bool const_select = result->size() == 0;
if (always_sens && const_select) {
if (NetEConst *val = dynamic_cast <NetEConst*> (base_)) {
assert(select_type() == IVL_SEL_OTHER);
if (NetESignal *sig = dynamic_cast<NetESignal*> (expr_)) {
delete tmp;
tmp = sig->nex_input_base(rem_out, always_sens, nested_func,
val->value().as_unsigned(), expr_width());
} else {
cerr << get_fileline() << ": Sorry, cannot determine the sensitivity "
<< "for the select of " << *expr_ << ", using all bits." << endl;
}
}
}
result->add(*tmp);
delete tmp;
/* See the comment for NetESignal below. */
if (base_ && warn_sens_entire_vec) {
if (base_ && ! always_sens && warn_sens_entire_vec) {
cerr << get_fileline() << ": warning: @* is sensitive to all "
"bits in '" << *expr_ << "'." << endl;
}
@@ -157,30 +167,35 @@ NexusSet* NetESelect::nex_input(bool rem_out)
/*
* The $fread, etc. system functions can have NULL arguments.
*/
NexusSet* NetESFunc::nex_input(bool rem_out)
NexusSet* NetESFunc::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
if (parms_.empty())
return new NexusSet;
NexusSet*result = new NexusSet;
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_.empty()) return result;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
}
return result;
}
NexusSet* NetEShallowCopy::nex_input(bool)
NexusSet* NetEShallowCopy::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetESignal::nex_input(bool rem_out)
NexusSet* NetESignal::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
return nex_input_base(rem_out, always_sens, nested_func, 0, 0);
}
NexusSet* NetESignal::nex_input_base(bool rem_out, bool always_sens, bool nested_func,
unsigned base, unsigned width) const
{
/*
* This is not what I would expect for the various selects (bit,
@@ -188,48 +203,88 @@ NexusSet* NetESignal::nex_input(bool rem_out)
* instead of building the appropriate select and then using it
* as the trigger. Other simulators also add everything.
*/
bool const_select = false;
unsigned const_word = 0;
NexusSet*result = new NexusSet;
/* Local signals are not added to the sensitivity list. */
if (net_->local_flag()) return result;
/* If we have an array index add it to the sensitivity list. */
if (word_) {
NexusSet*tmp;
tmp = word_->nex_input(rem_out);
tmp = word_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
if (warn_sens_entire_arr) {
if (!always_sens && warn_sens_entire_arr) {
cerr << get_fileline() << ": warning: @* is sensitive to all "
<< net_->unpacked_count() << " words in array '"
<< name() << "'." << endl;
}
if (always_sens) if (NetEConst *val = dynamic_cast <NetEConst*> (word_)) {
const_select = true;
const_word = val->value().as_unsigned();
}
}
if ((base == 0) && (width == 0)) width = net_->vector_width();
if (const_select) {
result->add(net_->pin(const_word).nexus(), base, width);
} else {
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
result->add(net_->pin(idx).nexus(), base, width);
}
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
result->add(net_->pin(idx).nexus(), 0, net_->vector_width());
return result;
}
NexusSet* NetETernary::nex_input(bool rem_out)
NexusSet* NetETernary::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*tmp;
NexusSet*result = cond_->nex_input(rem_out);
NexusSet*result = cond_->nex_input(rem_out, always_sens, nested_func);
tmp = true_val_->nex_input(rem_out);
tmp = true_val_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
tmp = false_val_->nex_input(rem_out);
tmp = false_val_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEUFunc::nex_input(bool rem_out)
NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (always_sens) {
NetFuncDef*func = func_->func_def();
// Avoid recursive function calls.
static set<NetFuncDef*> func_set;
if (!nested_func)
func_set.clear();
if (!func_set.insert(func).second)
return result;
NexusSet*tmp = func->proc()->nex_input(rem_out, always_sens, true);
// Remove the function inputs
NexusSet*in = new NexusSet;
for (unsigned idx = 0 ; idx < func->port_count() ; idx += 1) {
NetNet*net = func->port(idx);
assert(net->pin_count() == 1);
in->add(net->pin(0).nexus(), 0, net->vector_width());
}
tmp->rem(*in);
delete in;
result->add(*tmp);
delete tmp;
}
@@ -237,21 +292,28 @@ NexusSet* NetEUFunc::nex_input(bool rem_out)
return result;
}
NexusSet* NetEUnary::nex_input(bool rem_out)
NexusSet* NetEUnary::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
return expr_->nex_input(rem_out);
return expr_->nex_input(rem_out, always_sens, nested_func);
}
NexusSet* NetAssign_::nex_input(bool rem_out)
NexusSet* NetAlloc::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetAssign_::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
assert(! nest_);
NexusSet*result = new NexusSet;
if (word_) {
NexusSet*tmp = word_->nex_input(rem_out);
NexusSet*tmp = word_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (base_) {
NexusSet*tmp = base_->nex_input(rem_out);
NexusSet*tmp = base_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
@@ -259,15 +321,21 @@ NexusSet* NetAssign_::nex_input(bool rem_out)
return result;
}
NexusSet* NetAssignBase::nex_input(bool rem_out)
NexusSet* NetAssignBase::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = rval_->nex_input(rem_out);
NexusSet*result = new NexusSet;
// For the deassign and release statements there is no R-value.
if (rval_) {
NexusSet*tmp = rval_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
/* It is possible that the lval_ can have nex_input values. In
particular, index expressions are statement inputs as well,
so should be addressed here. */
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
NexusSet*tmp = cur->nex_input(rem_out);
NexusSet*tmp = cur->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
@@ -292,16 +360,15 @@ NexusSet* NetAssignBase::nex_input(bool rem_out)
* In this example, "t" should not be in the input set because it is
* used by the sequence as a temporary value.
*/
NexusSet* NetBlock::nex_input(bool rem_out)
NexusSet* NetBlock::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
if (last_ == 0)
return new NexusSet;
if (last_ == 0) return new NexusSet;
if (type_ != SEQU) {
if (! always_sens && (type_ != SEQU)) {
cerr << get_fileline() << ": internal error: Sorry, "
<< "I don't know how to synthesize fork/join blocks."
<< endl;
return 0;
return new NexusSet;
}
NetProc*cur = last_->next_;
@@ -312,10 +379,10 @@ NexusSet* NetBlock::nex_input(bool rem_out)
do {
/* Get the inputs for the current statement. */
NexusSet*tmp = cur->nex_input(rem_out);
NexusSet*tmp = cur->nex_input(rem_out, always_sens, nested_func);
/* Add the current input set to the accumulated input set. */
if (tmp != 0) result->add(*tmp);
result->add(*tmp);
delete tmp;
/* Add the current outputs to the accumulated output set if
@@ -339,11 +406,9 @@ NexusSet* NetBlock::nex_input(bool rem_out)
* the inputs to all the guards, and the inputs to all the guarded
* statements.
*/
NexusSet* NetCase::nex_input(bool rem_out)
NexusSet* NetCase::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = expr_->nex_input(rem_out);
if (result == 0)
return 0;
NexusSet*result = expr_->nex_input(rem_out, always_sens, nested_func);
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
@@ -351,8 +416,7 @@ NexusSet* NetCase::nex_input(bool rem_out)
if (items_[idx].statement == 0)
continue;
NexusSet*tmp = items_[idx].statement->nex_input(rem_out);
assert(tmp);
NexusSet*tmp = items_[idx].statement->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
@@ -360,8 +424,7 @@ NexusSet* NetCase::nex_input(bool rem_out)
case is special and is identified by a null
guard. The default guard obviously has no input. */
if (items_[idx].guard) {
tmp = items_[idx].guard->nex_input(rem_out);
assert(tmp);
tmp = items_[idx].guard->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
@@ -370,24 +433,18 @@ NexusSet* NetCase::nex_input(bool rem_out)
return result;
}
NexusSet* NetCAssign::nex_input(bool)
NexusSet* NetCondit::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
cerr << get_fileline() << ": internal warning: NetCAssign::nex_input()"
<< " not implemented." << endl;
return new NexusSet;
}
NexusSet*result = expr_->nex_input(rem_out, always_sens, nested_func);
NexusSet* NetCondit::nex_input(bool rem_out)
{
NexusSet*result = expr_->nex_input(rem_out);
if (if_ != 0) {
NexusSet*tmp = if_->nex_input(rem_out);
NexusSet*tmp = if_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (else_ != 0) {
NexusSet*tmp = else_->nex_input(rem_out);
NexusSet*tmp = else_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
@@ -395,47 +452,100 @@ NexusSet* NetCondit::nex_input(bool rem_out)
return result;
}
NexusSet* NetDoWhile::nex_input(bool rem_out)
NexusSet* NetDisable::nex_input(bool, bool, bool) const
{
NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetForce::nex_input(bool)
{
cerr << get_fileline() << ": internal warning: NetForce::nex_input()"
<< " not implemented." << endl;
return new NexusSet;
}
NexusSet* NetForLoop::nex_input(bool rem_out)
NexusSet* NetDoWhile::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = init_expr_->nex_input(rem_out);
NexusSet*result = cond_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = condition_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = step_statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
if (proc_) {
NexusSet*tmp = proc_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetForever::nex_input(bool rem_out)
NexusSet* NetEvTrig::nex_input(bool, bool, bool) const
{
NexusSet*result = statement_->nex_input(rem_out);
return new NexusSet;
}
NexusSet* NetEvWait::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetForever::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetForLoop::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
if (init_expr_) {
NexusSet*tmp = init_expr_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (condition_) {
NexusSet*tmp = condition_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (step_statement_) {
NexusSet*tmp = step_statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (gn_shared_loop_index_flag) {
NexusSet*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;
}
NexusSet* NetFree::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
/*
* The NetPDelay statement is a statement of the form
*
@@ -445,36 +555,44 @@ NexusSet* NetForever::nex_input(bool rem_out)
* include the input set of the <expr> because it does not affect the
* result. The statement can be omitted.
*/
NexusSet* NetPDelay::nex_input(bool rem_out)
NexusSet* NetPDelay::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
if (statement_ == 0) return 0;
NexusSet*result = statement_->nex_input(rem_out);
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetRepeat::nex_input(bool rem_out)
NexusSet* NetRepeat::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = statement_->nex_input(rem_out);
NexusSet*tmp = expr_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
NexusSet*result = expr_->nex_input(rem_out, always_sens, nested_func);
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
/*
* The $display, etc. system tasks can have NULL arguments.
*/
NexusSet* NetSTask::nex_input(bool rem_out)
NexusSet* NetSTask::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
if (parms_.empty())
return new NexusSet;
NexusSet*result = new NexusSet;
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_.empty()) return result;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
@@ -488,16 +606,20 @@ NexusSet* NetSTask::nex_input(bool rem_out)
* parameters to consider, because the compiler already removed them
* and converted them to blocking assignments.
*/
NexusSet* NetUTask::nex_input(bool)
NexusSet* NetUTask::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
NexusSet* NetWhile::nex_input(bool rem_out)
NexusSet* NetWhile::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
NexusSet*result = cond_->nex_input(rem_out, always_sens, nested_func);
if (proc_) {
NexusSet*tmp = proc_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
+35 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-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
@@ -36,8 +36,13 @@ void NetProc::nex_output(NexusSet&)
<< endl;
}
void NetAlloc::nex_output(NexusSet&)
{
}
void NetAssign_::nex_output(NexusSet&out)
{
assert(! nest_);
assert(sig_);
unsigned use_word = 0;
unsigned use_base = 0;
@@ -89,8 +94,7 @@ void NetAssignBase::nex_output(NexusSet&out)
void NetBlock::nex_output(NexusSet&out)
{
if (last_ == 0)
return;
if (last_ == 0) return;
NetProc*cur = last_;
do {
@@ -104,10 +108,8 @@ void NetCase::nex_output(NexusSet&out)
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
// Empty statements clearly have no output.
if (items_[idx].statement == 0)
continue;
if (items_[idx].statement == 0) continue;
assert(items_[idx].statement);
items_[idx].statement->nex_output(out);
}
@@ -115,22 +117,31 @@ void NetCase::nex_output(NexusSet&out)
void NetCondit::nex_output(NexusSet&out)
{
if (if_ != 0)
if_->nex_output(out);
if (else_ != 0)
else_->nex_output(out);
if (if_) if_->nex_output(out);
if (else_) else_->nex_output(out);
}
void NetDisable::nex_output(NexusSet&)
{
}
void NetDoWhile::nex_output(NexusSet&out)
{
if (proc_ != 0)
proc_->nex_output(out);
if (proc_) proc_->nex_output(out);
}
void NetEvTrig::nex_output(NexusSet&)
{
}
void NetEvWait::nex_output(NexusSet&out)
{
assert(statement_);
statement_->nex_output(out);
if (statement_) statement_->nex_output(out);
}
void NetForever::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetForLoop::nex_output(NexusSet&out)
@@ -138,11 +149,20 @@ void NetForLoop::nex_output(NexusSet&out)
if (statement_) statement_->nex_output(out);
}
void NetFree::nex_output(NexusSet&)
{
}
void NetPDelay::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetRepeat::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
/*
* For the purposes of synthesis, system task calls have no output at
* all. This is OK because most system tasks are not synthesizable in
@@ -163,6 +183,5 @@ void NetUTask::nex_output(NexusSet&)
void NetWhile::nex_output(NexusSet&out)
{
if (proc_ != 0)
proc_->nex_output(out);
if (proc_) proc_->nex_output(out);
}
+15 -3
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
@@ -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)
@@ -72,8 +83,8 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
return cur->next_;
}
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: type_(c), expr_(ex), items_(cnt)
NetCase::NetCase(ivl_case_quality_t q, NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: quality_(q), type_(c), expr_(ex), items_(cnt)
{
ivl_assert(*this, expr_);
}
@@ -188,6 +199,7 @@ NetForever::~NetForever()
NetForLoop::NetForLoop(NetNet*ind, NetExpr*iexpr, NetExpr*cond, NetProc*sub, NetProc*step)
: index_(ind), init_expr_(iexpr), condition_(cond), statement_(sub), step_statement_(step)
{
as_block_ = NULL;
}
void NetForLoop::wrap_up()
+159 -48
View File
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -23,6 +24,8 @@
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "netvector.h"
# include "PPackage.h"
# include <cstring>
# include <cstdlib>
# include <sstream>
@@ -110,11 +113,13 @@ void Definitions::add_class(netclass_t*net_class)
* in question.
*/
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
bool program, bool interface)
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_unit,
bool nest, bool program, bool interface, bool compilation_unit)
: type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), up_(up)
is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
{
imports_ = 0;
typedefs_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
@@ -122,8 +127,10 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
calls_stask_ = false;
in_final_ = false;
if (compilation_unit)
unit_ = this;
if (up) {
assert(t!=CLASS);
need_const_func_ = up->need_const_func_;
is_const_func_ = up->is_const_func_;
time_unit_ = up->time_unit();
@@ -131,6 +138,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
time_from_timescale_ = up->time_from_timescale();
// Need to check for duplicate names?
up_->children_[name_] = this;
if (unit_ == 0)
unit_ = up_->unit_;
} else {
need_const_func_ = false;
is_const_func_ = false;
@@ -139,6 +148,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;
@@ -161,6 +171,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
lineno_ = 0;
def_lineno_ = 0;
genvar_tmp_val = 0;
tie_hi_ = 0;
tie_lo_ = 0;
}
NetScope::~NetScope()
@@ -195,16 +207,72 @@ void NetScope::set_line(perm_string file, perm_string def_file,
def_lineno_ = def_lineno;
}
void NetScope::add_imports(const map<perm_string,PPackage*>*imports)
{
if (!imports->empty())
imports_ = imports;
}
NetScope*NetScope::find_import(const Design*des, perm_string name)
{
if (imports_ == 0)
return 0;
map<perm_string,PPackage*>::const_iterator cur = imports_->find(name);
if (cur != imports_->end()) {
return des->find_package(cur->second->pscope_name());
} else
return 0;
}
void NetScope::add_typedefs(const map<perm_string,data_type_t*>*typedefs)
{
if (!typedefs->empty())
typedefs_ = typedefs;
}
NetScope*NetScope::find_typedef_scope(const Design*des, data_type_t*type)
{
assert(type);
NetScope *cur_scope = this;
while (cur_scope) {
if (cur_scope->typedefs_ && cur_scope->typedefs_->find(type->name) != cur_scope->typedefs_->end())
return cur_scope;
NetScope*import_scope = cur_scope->find_import(des, type->name);
if (import_scope)
cur_scope = import_scope;
else if (cur_scope == unit_)
return 0;
else
cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
}
return 0;
}
/*
* Look for the enumeration in the current scope and any parent scopes.
*/
const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_string name)
{
NetScope *cur_scope = this;
while (cur_scope) {
NetEConstEnum*tmp = cur_scope->enum_names_[name];
if (tmp) break;
cur_scope = cur_scope->parent();
NetScope*import_scope = cur_scope->find_import(des, name);
if (import_scope)
cur_scope = import_scope;
else if (cur_scope == unit_)
return 0;
else
cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
}
assert(cur_scope);
@@ -264,19 +332,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 +354,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 +367,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)
@@ -356,12 +427,7 @@ const NetExpr* NetScope::get_parameter(Design*des,
msb = 0;
lsb = 0;
const NetExpr*tmp = enumeration_expr(key);
if (tmp) return tmp;
tmp = des->enumeration_expr(key);
if (tmp) return tmp;
return 0;
return tmp;
}
NetScope::param_ref_t NetScope::find_parameter(perm_string key)
@@ -378,11 +444,6 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
return idx;
}
NetScope::TYPE NetScope::type() const
{
return type_;
}
void NetScope::print_type(ostream&stream) const
{
switch (type_) {
@@ -501,6 +562,7 @@ void NetScope::add_module_port_info( unsigned idx, perm_string name, PortType::E
unsigned long width )
{
assert(type_ == MODULE);
assert(ports_.size() > idx);
PortInfo &info = ports_[idx];
info.name = name;
info.type = ptype;
@@ -648,15 +710,11 @@ netclass_t*NetScope::find_class(perm_string name)
if (type_==CLASS && name_==hname_t(name))
return class_def_;
// Look for the class that directly within this scope.
// Look for the class directly within this scope.
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
// If this is a module scope, then look no further.
if (type_==MODULE)
return 0;
if (up_==0 && type_==CLASS) {
assert(class_def_);
@@ -664,12 +722,16 @@ netclass_t*NetScope::find_class(perm_string name)
return def_parent->find_class(name);
}
// If there is no further to look, ...
if (up_ == 0)
return 0;
// Try looking up for the class.
return up_->find_class(name);
if (up_!=0 && type_!=MODULE)
return up_->find_class(name);
// Try the compilation unit.
if (unit_ != 0)
return unit_->find_class(name);
// Nowhere left to try...
return 0;
}
/*
@@ -737,7 +799,56 @@ const NetScope* NetScope::child_byname(perm_string name) const
perm_string NetScope::local_symbol()
{
ostringstream res;
res << "_s" << (lcounter_++);
return lex_strings.make(res.str());
perm_string sym;
do {
ostringstream res;
res << "_ivl_" << (lcounter_++);
perm_string sym_tmp = lex_strings.make(res.str());
// If the name already exists as a signal, try again.
if (signals_map_.find(sym_tmp) != signals_map_.end())
continue;
// If the name already exists as a parameter, try again.
if (parameters.find(sym_tmp) != parameters.end())
continue;
if (genvars_.find(sym_tmp) != genvars_.end())
continue;
// If the name already exists as a class, try again.
if (classes_.find(sym_tmp) != classes_.end())
continue;
// No collisions, this is the one.
sym = sym_tmp;
} while (sym.nil());
return sym;
}
void NetScope::add_tie_hi(Design*des)
{
if (tie_hi_ == 0) {
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC1"),
NetNet::WIRE, &netvector_t::scalar_logic);
sig->local_flag(true);
tie_hi_ = new NetLogic(this, local_symbol(),
1, NetLogic::PULLUP, 1);
des->add_node(tie_hi_);
connect(sig->pin(0), tie_hi_->pin(0));
}
}
void NetScope::add_tie_lo(Design*des)
{
if (tie_lo_ == 0) {
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC0"),
NetNet::WIRE, &netvector_t::scalar_logic);
sig->local_flag(true);
tie_lo_ = new NetLogic(this, local_symbol(),
1, NetLogic::PULLDOWN, 1);
des->add_node(tie_lo_);
connect(sig->pin(0), tie_lo_->pin(0));
}
}
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@@ -165,7 +165,8 @@ bool netclass_t::test_for_missing_initializers() const
NetScope*netclass_t::method_from_name(perm_string name) const
{
NetScope*task = class_scope_->child( hname_t(name) );
if (task == 0) return 0;
if ((task == 0) && super_)
task = super_->method_from_name(name);
return task;
}
+12 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2020 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
@@ -18,6 +18,7 @@
*/
# include "netdarray.h"
# include "netqueue.h"
# include <iostream>
using namespace std;
@@ -38,9 +39,16 @@ ivl_variable_type_t netdarray_t::base_type(void) const
bool netdarray_t::test_compatibility(ivl_type_t that) const
{
const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that);
if (that_da == 0)
ivl_type_t elem_type = 0;
if (const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that))
elem_type = that_da->element_type();
if (const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that))
elem_type = that_q->element_type();
if (elem_type == 0)
return false;
return element_type()->type_compatible(that_da->element_type());
return element_type()->type_compatible(elem_type);
}
+745 -44
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -24,6 +24,7 @@
# include <typeinfo>
# include <cstdlib>
# include <climits>
# include <cstring>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
@@ -175,6 +176,7 @@ bool NetPins::pins_are_virtual(void) const
NetPins::NetPins(unsigned npins)
: npins_(npins)
{
default_dir_ = Link::PASSIVE;
pins_ = NULL; // Wait until someone asks.
if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
}
@@ -307,11 +309,12 @@ unsigned NetBus::find_link(const Link&that) const
}
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
bool condit_src, bool conditional)
bool condit_src, bool conditional, bool parallel)
: NetObj(s, n, npins + (condit_src?1:0))
{
condit_flag_ = false;
conditional_ = conditional;
parallel_ = parallel;
posedge_ = false;
negedge_ = false;
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
@@ -470,6 +473,11 @@ const Link& NetDelaySrc::condit_pin() const
return pin(pin_count()-1);
}
bool NetDelaySrc::is_parallel() const
{
return parallel_;
}
PortType::Enum PortType::merged( Enum lhs, Enum rhs )
{
if( lhs == NOT_A_PORT || rhs == NOT_A_PORT )
@@ -557,7 +565,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();
}
}
@@ -1021,11 +1029,36 @@ NetProc::~NetProc()
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
: type_(t), statement_(st), scope_(s)
{
synthesized_design_ = 0;
}
NetProcTop::~NetProcTop()
{
if (!synthesized_design_) {
delete statement_;
return;
}
NexusSet nex_set;
statement_->nex_output(nex_set);
delete statement_;
bool flag = false;
for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) {
NetNet*net = nex_set[idx].lnk.nexus()->pick_any_net();
if (net->peek_lref() > 0) {
cerr << get_fileline() << ": warning: '" << net->name()
<< "' is driven by more than one process." << endl;
flag = true;
}
}
if (flag) {
cerr << get_fileline() << ": sorry: Cannot synthesize signals "
"that are driven by more than one process." << endl;
synthesized_design_->errors += 1;
}
}
NetProc* NetProcTop::statement()
@@ -1280,6 +1313,60 @@ const verinum& NetFF::sset_value() const
return sset_value_;
}
/*
* The NetLatch class represents an LPM_LATCH device. The pinout is assigned
* like so:
* 0 -- Enable
* 1 -- Data
* 2 -- Q
*/
NetLatch::NetLatch(NetScope*s, perm_string n, unsigned width__)
: NetNode(s, n, 3), width_(width__)
{
pin_Enable().set_dir(Link::INPUT);
pin_Data().set_dir(Link::INPUT);
pin_Q().set_dir(Link::OUTPUT);
}
NetLatch::~NetLatch()
{
}
unsigned NetLatch::width() const
{
return width_;
}
Link& NetLatch::pin_Enable()
{
return pin(0);
}
const Link& NetLatch::pin_Enable() const
{
return pin(0);
}
Link& NetLatch::pin_Data()
{
return pin(1);
}
const Link& NetLatch::pin_Data() const
{
return pin(1);
}
Link& NetLatch::pin_Q()
{
return pin(2);
}
const Link& NetLatch::pin_Q() const
{
return pin(2);
}
NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
@@ -2154,6 +2241,14 @@ ivl_variable_type_t NetEUFunc::expr_type() const
return IVL_VT_VOID;
}
const netenum_t* NetEUFunc::enumeration() const
{
if (result_sig_)
return result_sig_->enumeration();
return 0;
}
NetUTask::NetUTask(NetScope*def)
: task_(def)
{
@@ -2443,6 +2538,20 @@ NetETernary::~NetETernary()
delete false_val_;
}
const netenum_t* NetETernary::enumeration() const
{
// If the condition can evaluate to an ambiguous value,
// the result may be blended, and so is not guaranteed
// to be a valid enumeration value.
if (cond_->expr_type() != IVL_VT_BOOL)
return 0;
if (true_val_->enumeration() != false_val_->enumeration())
return 0;
return true_val_->enumeration();
}
const NetExpr* NetETernary::cond_expr() const
{
return cond_;
@@ -2688,7 +2797,7 @@ static DelayType delay_type_from_expr(const NetExpr*expr)
* The looping structures can use the same basic code so put it here
* instead of duplicating it for each one (repeat and while).
*/
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, bool print_delay)
{
DelayType result;
@@ -2699,12 +2808,20 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
break;
/* We have a constant true expression so the body always runs. */
case DEFINITE_DELAY:
result = proc->delay_type();
if (proc) {
result = proc->delay_type(print_delay);
} else {
result = NO_DELAY;
}
break;
/* We don't know if the body will run so reduce a DEFINITE_DELAY
* to a POSSIBLE_DELAY. All other stay the same. */
case POSSIBLE_DELAY:
result = combine_delays(NO_DELAY, proc->delay_type());
if (proc) {
result = combine_delays(NO_DELAY, proc->delay_type(print_delay));
} else {
result = NO_DELAY;
}
break;
/* This should never happen since delay_type_from_expr() only
* returns three different values. */
@@ -2717,25 +2834,40 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
}
/* The default object does not have any delay. */
DelayType NetProc::delay_type() const
DelayType NetProc::delay_type(bool /* print_delay */ ) const
{
return NO_DELAY;
}
DelayType NetBlock::delay_type() const
DelayType NetBlock::delay_type(bool print_delay) const
{
DelayType result = NO_DELAY;
// A join_none has no delay.
if (type() == PARA_JOIN_NONE) return NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break;
DelayType result;
// A join_any has the minimum delay.
if (type() == PARA_JOIN_ANY) {
result = DEFINITE_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(print_delay);
if (dt < result) result = dt;
if ((dt == NO_DELAY) && !print_delay) break;
}
// A begin or join has the maximum delay.
} else {
result = NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(print_delay);
if (dt > result) result = dt;
if ((dt == DEFINITE_DELAY) && !print_delay) break;
}
}
return result;
}
DelayType NetCase::delay_type() const
DelayType NetCase::delay_type(bool print_delay) const
{
DelayType result = NO_DELAY;
bool def_stmt = false;
@@ -2743,13 +2875,15 @@ 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(print_delay) : 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);
}
}
// FIXME: If all the cases are covered (e.g. an enum) then this is not true.
/* If we don't have a default statement we don't know for sure
* that we have a delay. */
if (!def_stmt) result = combine_delays(NO_DELAY, result);
@@ -2757,69 +2891,636 @@ DelayType NetCase::delay_type() const
return result;
}
DelayType NetCondit::delay_type() const
DelayType NetCondit::delay_type(bool print_delay) const
{
DelayType if_type = if_ ? if_->delay_type() : NO_DELAY;
DelayType el_type = else_? else_->delay_type() : NO_DELAY;
DelayType if_type = if_ ? if_->delay_type(print_delay) : NO_DELAY;
DelayType el_type = else_? else_->delay_type(print_delay) : NO_DELAY;
return combine_delays(if_type, el_type);
}
/*
* A do/while will execute the body at least once.
*/
DelayType NetDoWhile::delay_type() const
DelayType NetDoWhile::delay_type(bool print_delay) const
{
return proc_->delay_type();
if (proc_) return proc_->delay_type(print_delay);
return ZERO_DELAY;
}
DelayType NetEvWait::delay_type() const
DelayType NetEvWait::delay_type(bool print_delay) const
{
if (print_delay) {
cerr << get_fileline() << ": error: an event control is not allowed "
"in an always_comb, always_ff or always_latch process."
<< endl;
}
return DEFINITE_DELAY;
}
DelayType NetForever::delay_type() const
DelayType NetForever::delay_type(bool print_delay) const
{
return statement_->delay_type();
if (statement_) return statement_->delay_type(print_delay);
return ZERO_DELAY;
}
DelayType NetForLoop::delay_type() const
DelayType NetForLoop::delay_type(bool print_delay) const
{
return get_loop_delay_type(condition_, statement_);
return get_loop_delay_type(condition_, statement_, print_delay);
}
DelayType NetPDelay::delay_type() const
DelayType NetPDelay::delay_type(bool print_delay) const
{
if (print_delay) {
cerr << get_fileline() << ": error: a blocking delay is not allowed "
"in an always_comb, always_ff or always_latch process."
<< endl;
}
if (expr_) {
return delay_type_from_expr(expr_);
} else {
if (delay() > 0) {
return DEFINITE_DELAY;
if (statement_) {
return combine_delays(delay_type_from_expr(expr_),
statement_->delay_type(print_delay));
} else {
if (statement_) {
return statement_->delay_type();
} else {
return NO_DELAY;
}
return delay_type_from_expr(expr_);
}
}
if (delay() > 0) return DEFINITE_DELAY;
if (statement_) {
return combine_delays(ZERO_DELAY,
statement_->delay_type(print_delay));
} else {
return ZERO_DELAY;
}
}
DelayType NetRepeat::delay_type(bool print_delay) const
{
return get_loop_delay_type(expr_, statement_, print_delay);
}
DelayType NetTaskDef::delay_type(bool print_delay) const
{
if (proc_) {
return proc_->delay_type(print_delay);
} else {
return NO_DELAY;
}
}
DelayType NetUTask::delay_type(bool print_delay) const
{
return task()->task_def()->delay_type(print_delay);
}
static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt)
{
// The event wait should only have a single event.
if (evwt->nevents() != 1) return false;
// The event should have a single probe.
const NetEvent *evt = evwt->event(0);
if (evt->nprobe() != 1) return false;
// The probe should be for any edge.
const NetEvProbe *prb = evt->probe(0);
if (prb->edge() != NetEvProbe::ANYEDGE) return false;
// Create a NexusSet from the event probe signals.
NexusSet *ns_evwt = new NexusSet;
for (unsigned idx =0; idx < prb->pin_count(); idx += 1) {
if (! prb->pin(idx).is_linked()) {
delete ns_evwt;
return false;
}
// Casting away const is safe since this nexus set is only being read.
ns_evwt->add(const_cast<Nexus*> (prb->pin(idx).nexus()),
0, prb->pin(idx).nexus()->vector_width());
}
// Get the NexusSet for the expression.
NexusSet *ns_expr = expr->nex_input();
// Make sure the event and expression NexusSets match exactly.
if (ns_evwt->size() != ns_expr->size()) {
delete ns_evwt;
delete ns_expr;
return false;
}
ns_expr->rem(*ns_evwt);
delete ns_evwt;
if (ns_expr->size() != 0) {
delete ns_expr;
return false;
}
delete ns_expr;
return true;
}
static bool while_is_wait(const NetExpr*expr, const NetProc*stmt)
{
if (const NetEvWait*evwt = dynamic_cast<const NetEvWait*>(stmt)) {
if (evwt->statement()) return false;
const NetEBComp*cond = dynamic_cast<const NetEBComp*>(expr);
if (! cond) return false;
if (cond->op() != 'N') return false;
const NetEConst*cval = dynamic_cast<const NetEConst*>(cond->right());
if (! cval) return false;
const verinum val = cval->value();
if (val.len() != 1) return false;
if (val.get(0) != verinum::V1) return false;
if (! do_expr_event_match(cond->left(), evwt)) return false;
if (evwt->get_lineno() != cond->get_lineno()) return false;
if (evwt->get_file() != cond->get_file()) return false;
return true;
}
return false;
}
DelayType NetWhile::delay_type(bool print_delay) const
{
// If the wait was a constant value the compiler already removed it
// so we know we can only have a possible delay.
if (while_is_wait(cond_, proc_)) {
if (print_delay) {
cerr << get_fileline() << ": error: a wait statement is "
"not allowed in an "
"always_comb, always_ff or always_latch process."
<< endl;
}
return POSSIBLE_DELAY;
}
return get_loop_delay_type(cond_, proc_, print_delay);
}
/*
* These are the check_synth() functions. They are used to print
* a warning if the item is not synthesizable.
*/
static const char * get_process_type_as_string(ivl_process_type_t pr_type)
{
switch (pr_type) {
case IVL_PR_ALWAYS_COMB:
return "in an always_comb process.";
break;
case IVL_PR_ALWAYS_FF:
return "in an always_ff process.";
break;
case IVL_PR_ALWAYS_LATCH:
return "in an always_latch process.";
break;
default:
assert(0);
return 0;
}
}
static void print_synth_warning(const NetProc *net_proc, const char *name,
ivl_process_type_t pr_type)
{
cerr << net_proc->get_fileline() << ": warning: " << name
<< " statement cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_if_logic_l_value(const NetAssignBase *base,
ivl_process_type_t pr_type)
{
if (base->l_val_count() != 1) return;
const NetAssign_*lval = base->l_val(0);
if (! lval) return;
NetNet*sig = lval->sig();
if (! sig) return;
if ((sig->data_type() != IVL_VT_BOOL) &&
(sig->data_type() != IVL_VT_LOGIC)) {
cerr << base->get_fileline() << ": warning: Assinging to a "
"non-integral variable ("<< sig->name()
<< ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
/* By default elements can be synthesized or ignored. */
bool NetProc::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return false;
}
// FIXME: User function calls still need to be checked (NetEUFunc).
// : Non-constant system functions need a warning (NetESFunc).
// : Constant functions should already be elaborated.
/* By default assign elements can be synthesized. */
bool NetAssignBase::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return false;
}
bool NetAssign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
check_if_logic_l_value(this, pr_type);
// FIXME: Check that ff/latch only use this for internal signals.
return false;
}
bool NetAssignNB::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
bool result = false;
if (pr_type == IVL_PR_ALWAYS_COMB) {
cerr << get_fileline() << ": warning: A non-blocking assignment "
"should not be used in an always_comb process." << endl;
}
if (event_) {
cerr << get_fileline() << ": error: A non-blocking assignment "
"cannot be synthesized with an event control "
<< get_process_type_as_string(pr_type) << endl;
result = true;
}
check_if_logic_l_value(this, pr_type);
return result;
}
bool NetBlock::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
// Only a begin/end can be synthesized.
if (type() != SEQU) {
cerr << get_fileline() << ": error: A fork/";
switch (type()) {
case PARA:
cerr << "join";
break;
case PARA_JOIN_ANY:
cerr << "join_any";
break;
case PARA_JOIN_NONE:
cerr << "join_none";
break;
default:
assert(0);
}
cerr << " statement cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
result = true;
}
const NetScope*save_scope = scope;
if (subscope()) scope = subscope();
if (scope != save_scope) {
result |= scope->check_synth(pr_type, scope);
}
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
result |= cur->check_synth(pr_type, scope);
}
scope = save_scope;
return result;
}
bool NetCase::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
for (unsigned idx = 0; idx < nitems(); idx += 1) {
if (stat(idx)) result |= stat(idx)->check_synth(pr_type, scope);
}
// FIXME: Check for ff/latch/comb structures.
return result;
}
bool NetCAssign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A procedural assign", pr_type);
return false;
}
bool NetCondit::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
if (if_) result |= if_->check_synth(pr_type, scope);
if (else_) result |= else_->check_synth(pr_type, scope);
// FIXME: Check for ff/latch/comb structures.
return result;
}
bool NetDeassign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A procedural deassign", pr_type);
return false;
}
bool NetDisable::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
while (scope) {
if (scope != target_) scope = scope->parent();
else break;
}
if (! scope) {
cerr << get_fileline() << ": warning: A disable statement can "
"only be synthesized when disabling an enclosing block "
<< get_process_type_as_string(pr_type) << endl;
}
return false;
}
bool NetDoWhile::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
print_synth_warning(this, "A do/while", pr_type);
if (proc_) result |= proc_->check_synth(pr_type, scope);
return result;
}
bool NetEvTrig::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "An event trigger", pr_type);
return false;
}
// The delay check above has already marked this as an error.
bool NetEvWait::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
bool NetForce::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A force", pr_type);
return false;
}
bool NetForever::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
print_synth_warning(this, "A forever", pr_type);
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
/*
* A bunch of private routines to verify that a for loop has the correct
* structure for synthesis.
*/
static void print_for_idx_warning(const NetProc*proc, const char*check,
ivl_process_type_t pr_type, NetNet*idx)
{
cerr << proc->get_fileline() << ": warning: A for statement must use "
"the index (" << idx->name() << ") in the " << check
<< " expression to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_for_const_synth(const NetExpr*expr, const NetProc*proc,
const char*str, ivl_process_type_t pr_type)
{
if (! dynamic_cast<const NetEConst*>(expr)) {
cerr << proc-> get_fileline() << ": warning: A for "
"statement must " << str
<< " value to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
static void check_for_bin_synth(const NetExpr*left,const NetExpr*right,
const char*str, const char*check,
const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
const NetESignal*lsig = dynamic_cast<const NetESignal*>(left);
const NetESignal*rsig = dynamic_cast<const NetESignal*>(right);
if (lsig && (lsig->sig() == index)) {
check_for_const_synth(right, proc, str, pr_type);
} else if (rsig && (rsig->sig() == index)) {
check_for_const_synth(left, proc, str, pr_type);
} else {
print_for_idx_warning(proc, check, pr_type, index);
}
}
static void print_for_step_warning(const NetProc*proc,
ivl_process_type_t pr_type)
{
cerr << proc->get_fileline() << ": warning: A for statement step must "
"be a simple assignment statement to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void print_for_step_warning(const NetProc*proc,
ivl_process_type_t pr_type, NetNet*idx)
{
cerr << proc->get_fileline() << ": warning: A for statement step must "
"be an assignment to the index variable ("
<< idx->name() << ") to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_for_bstep_synth(const NetExpr*expr, const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
if (const NetECast*tmp = dynamic_cast<const NetECast*>(expr)) {
expr = tmp->expr();
}
if (const NetEBAdd*tmp = dynamic_cast<const NetEBAdd*>(expr)) {
check_for_bin_synth(tmp->left(), tmp->right(),
"change by a constant", "step", proc, pr_type,
index);
} else {
cerr << proc->get_fileline() << ": warning: A for statement "
"step must be a simple binary +/- "
"to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
static void check_for_step_synth(const NetAssign*assign, const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
if (assign->l_val_count() != 1) {
print_for_step_warning(proc, pr_type);
} else if (assign->l_val(0)->sig() != index) {
print_for_step_warning(proc, pr_type, index);
} else {
switch (assign->assign_operator()) {
case '+':
case '-':
check_for_const_synth(assign->rval(), proc,
"have a constant step", pr_type);
break;
case 0:
check_for_bstep_synth(assign->rval(), proc, pr_type, index);
break;
default:
cerr << proc->get_fileline() << ": warning: A for statement "
"step does not support operator '"
<< assign->assign_operator()
<< "' it must be +/- to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
break;
}
}
}
DelayType NetRepeat::delay_type() const
bool NetForLoop::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
return get_loop_delay_type(expr_, statement_);
bool result = false;
// FIXME: What about an enum (NetEConstEnum)?
if (! dynamic_cast<const NetEConst*>(init_expr_)) {
cerr << get_fileline() << ": warning: A for statement must "
"have a constant initial value to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
// FIXME: Do the following also need to be supported in the condition?
// It would seem like they are hard to use to find the bounds.
// From NetEBinary
// What about NetEBits sig & constant, etc.
// From NetEUnary
// What about NetEUBits ! sig or ! (sig == constat)
// What about NetEUReduce &signal
if (const NetESignal*tmp = dynamic_cast<const NetESignal*>(condition_)) {
if (tmp->sig() != index_) {
print_for_idx_warning(this, "condition", pr_type, index_);
}
} else if (const NetEBComp*cmp = dynamic_cast<const NetEBComp*>(condition_)) {
check_for_bin_synth(cmp->left(), cmp->right(),
"compare against a constant", "condition",
this, pr_type, index_);
} else {
print_for_idx_warning(this, "condition", pr_type, index_);
}
if (const NetAssign*tmp = dynamic_cast<const NetAssign*>(step_statement_)) {
check_for_step_synth(tmp, this, pr_type, index_);
} else {
print_for_step_warning(this, pr_type);
}
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
DelayType NetTaskDef::delay_type() const
// The delay check above has already marked this as an error.
bool NetPDelay::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return proc_->delay_type();
return false;
}
DelayType NetUTask::delay_type() const
bool NetRelease::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
return task()->task_def()->delay_type();
print_synth_warning(this, "A release", pr_type);
return false;
}
DelayType NetWhile::delay_type() const
bool NetRepeat::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
return get_loop_delay_type(cond_, proc_);
bool result = false;
print_synth_warning(this, "A repeat", pr_type);
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
bool NetScope::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
bool result = false;
// Skip local events/signals
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
if (cur->local_flag()) continue;
cerr << cur->get_fileline() << ": warning: An event ("
<< cur->name() << ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
for (signals_map_iter_t cur = signals_map_.begin();
cur != signals_map_.end() ; ++ cur) {
const NetNet*sig = cur->second;
if ((sig->data_type() != IVL_VT_BOOL) &&
(sig->data_type() != IVL_VT_LOGIC)) {
cerr << sig->get_fileline() << ": warning: A non-integral "
"variable (" << sig->name() << ") cannot be "
"synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
return result;
}
bool NetSTask::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
if (strcmp(name(), "$ivl_darray_method$delete") == 0) {
cerr << get_fileline() << ": warning: Dynamic array "
"delete method cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
} else {
cerr << get_fileline() << ": warning: System task ("
<< name() << ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
return false;
}
bool NetTaskDef::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
bool result = false;
const NetScope *tscope = this->scope();
result |= tscope->check_synth(pr_type, tscope);
if (! tscope->is_auto()) {
cerr << tscope->get_def_file() << ":"
<< tscope->get_def_lineno()
<< ": warning: user task (" << tscope->basename()
<< ") must be automatic to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
if (proc_) result |= proc_->check_synth(pr_type, tscope);
return result;
}
bool NetUTask::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
return task()->task_def()->check_synth(pr_type, scope);
}
bool NetWhile::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
// A wait is already maked as an error in the delay check above.
if (! while_is_wait(cond_, proc_)) {
print_synth_warning(this, "A while", pr_type);
if (proc_) result |= proc_->check_synth(pr_type, scope);
}
return result;
}
+346 -128
View File
File diff suppressed because it is too large Load Diff
+250 -62
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2020 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
@@ -158,7 +158,7 @@ NetExpr* cast_to_int2(NetExpr*expr, unsigned width)
NetExpr* cast_to_int4(NetExpr*expr, unsigned width)
{
// Special case: The expression is already LOGIC or BOOL
if (expr->expr_type() != IVL_VT_REAL)
if (expr->expr_type() == IVL_VT_LOGIC || expr->expr_type() == IVL_VT_BOOL)
return expr;
if (debug_elaborate)
@@ -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;
@@ -876,6 +925,19 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
if (tmp == 0) return 0;
if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) {
switch (tmp->expr_type()) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
case IVL_VT_REAL:
break;
default:
cerr << tmp->get_fileline() << ": error: "
"The expression '" << *pe << "' cannot be implicitly "
"cast to the target type." << endl;
des->errors += 1;
delete tmp;
return 0;
}
switch (cast_type) {
case IVL_VT_REAL:
tmp = cast_to_real(tmp);
@@ -910,15 +972,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 +989,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,
@@ -945,6 +1009,41 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
flags |= PExpr::NEED_CONST;
NetExpr*tmp = pe->elaborate_expr(des, scope, lv_net_type, flags);
if (tmp == 0) return 0;
ivl_variable_type_t cast_type = ivl_type_base(lv_net_type);
if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) {
// Catch some special cases.
switch (cast_type) {
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
if (NetESignal*net = dynamic_cast<NetESignal*>(tmp)) {
ivl_variable_type_t type = net->expr_type();
if ((type == IVL_VT_DARRAY) || (type == IVL_VT_QUEUE))
return tmp;
}
if (dynamic_cast<PEAssignPattern*>(pe))
return tmp;
// fall through
case IVL_VT_STRING:
if (dynamic_cast<PEConcat*>(pe))
return tmp;
break;
case IVL_VT_CLASS:
if (dynamic_cast<PENull*>(pe))
return tmp;
break;
default:
break;
}
cerr << tmp->get_fileline() << ": error: "
"The expression '" << *pe << "' cannot be implicitly "
"cast to the target type." << endl;
des->errors += 1;
delete tmp;
return 0;
}
return tmp;
}
@@ -986,50 +1085,94 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
return tmp;
}
bool evaluate_ranges(Design*des, NetScope*scope,
bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li,
const pform_range_t&range, long&index_l, long&index_r)
{
bool dimension_ok = true;
// Unsized and queue dimensions should be handled before calling
// this function. If we find them here, we are in a context where
// they are not allowed.
if (range.first == 0) {
cerr << li->get_fileline() << ": error: "
"An unsized dimension is not allowed here." << endl;
dimension_ok = false;
des->errors += 1;
} else if (dynamic_cast<PENull*>(range.first)) {
cerr << li->get_fileline() << ": error: "
"A queue dimension is not allowed here." << endl;
dimension_ok = false;
des->errors += 1;
} else {
NetExpr*texpr = elab_and_eval(des, scope, range.first, -1, true);
if (! eval_as_long(index_l, texpr)) {
cerr << range.first->get_fileline() << ": error: "
"Dimensions must be constant." << endl;
cerr << range.first->get_fileline() << " : "
<< (range.second ? "This MSB" : "This size")
<< " expression violates the rule: "
<< *range.first << endl;
dimension_ok = false;
des->errors += 1;
}
delete texpr;
if (range.second == 0) {
// This is a SystemVerilog [size] dimension. The IEEE
// standard does not allow this in a packed dimension,
// but we do. At least one commercial simulator does too.
if (!dimension_ok) {
// bail out
} else if (index_l > 0) {
index_l = index_l - 1;
index_r = 0;
} else {
cerr << range.first->get_fileline() << ": error: "
"Dimension size must be greater than zero." << endl;
cerr << range.first->get_fileline() << " : "
"This size expression violates the rule: "
<< *range.first << endl;
dimension_ok = false;
des->errors += 1;
}
} else {
texpr = elab_and_eval(des, scope, range.second, -1, true);
if (! eval_as_long(index_r, texpr)) {
cerr << range.second->get_fileline() << ": error: "
"Dimensions must be constant." << endl;
cerr << range.second->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *range.second << endl;
dimension_ok = false;
des->errors += 1;
}
delete texpr;
}
}
/* Error recovery */
if (!dimension_ok) {
index_l = 0;
index_r = 0;
}
return dimension_ok;
}
bool evaluate_ranges(Design*des, NetScope*scope, const LineInfo*li,
vector<netrange_t>&llist,
const list<pform_range_t>&rlist)
{
bool bad_msb = false, bad_lsb = false;
bool dimensions_ok = true;
for (list<pform_range_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
long use_msb, use_lsb;
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
if (! eval_as_long(use_msb, texpr)) {
cerr << cur->first->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->first->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *cur->first << endl;
des->errors += 1;
bad_msb = true;
}
delete texpr;
texpr = elab_and_eval(des, scope, cur->second, -1, true);
if (! eval_as_long(use_lsb, texpr)) {
cerr << cur->second->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->second->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *cur->second << endl;
des->errors += 1;
bad_lsb = true;
}
delete texpr;
/* Error recovery */
if (bad_lsb) use_lsb = 0;
if (bad_msb) use_msb = use_lsb;
llist.push_back(netrange_t(use_msb, use_lsb));
long index_l, index_r;
dimensions_ok &= evaluate_range(des, scope, li, *cur, index_l, index_r);
llist.push_back(netrange_t(index_l, index_r));
}
return bad_msb | bad_lsb;
return dimensions_ok;
}
void eval_expr(NetExpr*&expr, int context_width)
@@ -1198,9 +1341,11 @@ const char *human_readable_op(const char op, bool unary)
case '|': type = "|"; break; // Bitwise OR
case 'O': type = "~|"; break; // NOR
case '!': type = "!"; break; // Logical NOT
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case '!': type = "!"; break; // Logical NOT
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case 'q': type = "->"; break; // Logical implication
case 'Q': type = "<->"; break; // Logical equivalence
case 'e': type = "=="; break;
case 'n': type = "!="; break;
@@ -1209,6 +1354,8 @@ const char *human_readable_op(const char op, bool unary)
if (unary) type = "~|"; // NOR
else type = "!=="; // Case inequality
break;
case 'w': type = "==?"; break; // Wild equality
case 'W': type = "!=?"; break; // Wild inequality
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
@@ -1393,7 +1540,13 @@ 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);
if (icur->sel != index_component_t::SEL_BIT) {
cerr << icur->msb->get_fileline() << ": error: "
"All but the final index in a chain of indices must be "
"a single value, not a range." << endl;
des->errors += 1;
return false;
}
NetExpr*texpr = elab_and_eval(des, scope, icur->msb, -1, true);
long tmp;
@@ -1404,7 +1557,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
return false;
}
prefix_indices .push_back(tmp);
prefix_indices.push_back(tmp);
delete texpr;
}
@@ -1614,3 +1767,38 @@ NetScope* find_method_containing_scope(const LineInfo&, NetScope*scope)
return scope;
}
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
void check_for_inconsistent_delays(NetScope*scope)
{
static bool used_implicit_timescale = false;
static bool used_explicit_timescale = false;
static bool display_ts_dly_warning = true;
if (scope->time_from_timescale())
used_explicit_timescale = true;
else
used_implicit_timescale = true;
if (display_ts_dly_warning &&
used_explicit_timescale &&
used_implicit_timescale) {
if (gn_system_verilog()) {
cerr << "warning: Found both default and explicit "
"timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the design "
"element(s) with no explicit" << endl;
cerr << " : timescale." << endl;
} else {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the "
"module(s) with no `timescale." << endl;
}
display_ts_dly_warning = false;
}
}
+42 -14
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-2019 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);
@@ -155,7 +175,7 @@ extern NetExpr*normalize_variable_slice_base(const list<long>&indices, NetExpr *
* index values in the form [<>][<>]....
*/
template <class TYPE> struct __IndicesManip {
inline __IndicesManip(const std::list<TYPE>&v) : val(v) { }
explicit inline __IndicesManip(const std::list<TYPE>&v) : val(v) { }
const std::list<TYPE>&val;
};
template <class TYPE> inline __IndicesManip<TYPE> as_indices(const std::list<TYPE>&indices)
@@ -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,9 +318,14 @@ 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,
extern bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li,
const pform_range_t&range,
long&index_l, long&index_r);
extern bool evaluate_ranges(Design*des, NetScope*scope, const LineInfo*li,
std::vector<netrange_t>&llist,
const std::list<pform_range_t>&rlist);
/*
@@ -356,10 +382,6 @@ const char *human_readable_op(const char op, bool unary = false);
enum const_bool { C_NON, C_0, C_1, C_X };
const_bool const_logical(const NetExpr*expr);
extern bool dly_used_no_timescale;
extern bool dly_used_timescale;
extern bool display_ts_dly_warning;
/*
* When scaling a real value to a time we need to do some standard
* processing.
@@ -387,4 +409,10 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
extern NetPartSelect* detect_partselect_lval(Link&pin);
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
extern void check_for_inconsistent_delays(NetScope*scope);
#endif /* IVL_netmisc_H */
+13 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014-2020 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,8 +22,8 @@
using namespace std;
netqueue_t::netqueue_t(ivl_type_t vec)
: netdarray_t(vec)
netqueue_t::netqueue_t(ivl_type_t vec, long max_idx)
: netdarray_t(vec), max_idx_(max_idx)
{
}
@@ -38,9 +38,16 @@ ivl_variable_type_t netqueue_t::base_type() const
bool netqueue_t::test_compatibility(ivl_type_t that) const
{
const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that);
if (that_q == 0)
ivl_type_t elem_type = 0;
if (const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that))
elem_type = that_q->element_type();
if (const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that))
elem_type = that_da->element_type();
if (elem_type == 0)
return false;
return element_type()->type_compatible(that_q->element_type());
return element_type()->type_compatible(elem_type);
}
+8 -2
View File
@@ -1,7 +1,7 @@
#ifndef IVL__netqueue_H
#define IVL__netqueue_H
/*
* Copyright (c) 2014-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014-2020 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -30,7 +30,7 @@
class netqueue_t : public netdarray_t {
public:
explicit netqueue_t(ivl_type_t vec);
explicit netqueue_t(ivl_type_t vec, long max_idx);
~netqueue_t();
// This is the "base_type()" virtual method of the
@@ -41,10 +41,16 @@ class netqueue_t : public netdarray_t {
// A queue may have a type that is signed.
inline bool get_signed() const { return element_type()->get_signed(); }
// Use the packed width to pass the element width
long packed_width(void) const { return element_type()->packed_width(); }
long max_idx(void) const { return max_idx_; }
std::ostream& debug_dump(std::ostream&) const;
private:
bool test_compatibility(ivl_type_t that) const;
long max_idx_;
};
#endif
+2 -3
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.

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