Compare commits

..
217 Commits
Author SHA1 Message Date
Stephen Williams bb444b6178 Snapshot 2015-05-13 2015-05-13 10:21:19 -07:00
Stephen Williams 7442c14689 Merge pull request #67 from orsonmmz/boolean
Boolean & asserts for vhdlpp
2015-05-13 09:57:18 -07:00
Stephen Williams 0082795967 Merge pull request #61 from orsonmmz/asserts
Asserts
2015-05-13 09:56:27 -07:00
Martin Whitaker ac4f4cf1a0 Update man pages.
Removed obsolete -m32 and -ivl options from iverilog-vpi man page
and revised description of -mingw option. Also removed duplicate
descriptions of --cflags, --ldflags, and --ldlibs options. Updated
link to main iverilog web page in all man pages.
2015-05-10 13:19:51 +01:00
Martin Whitaker 676d23f973 Add extra whitespace in driver-vpi/main.c for readability. 2015-05-10 13:19:16 +01:00
Martin Whitaker 6069cbfc3c Remove outdated instructions in mingw.txt and point to the Wiki instead. 2015-05-10 12:03:58 +01:00
Martin Whitaker cfbc90812b Enable use of MinGW ANSI stdio routines.
Defining __USE_MINGW_ANSI_STDIO=1 provides C99 compatible printf
and scanf routines, which avoids the need for workarounds for the
various failings of the Microsoft C runtime library.
2015-05-10 11:45:42 +01:00
Cary R e530b4e642 Update fstapi.c to the latest from GTKWave 2015-05-08 16:36:12 -07:00
Martin Whitaker 6a3edc63d5 Fix printf format for size_t values when using 64-bit MinGW.
The Microsoft C runtime does not support the %zu and %zd formats.
Previously these were replaced with %u and %d, but for 64-bit we
need to use %llu and %lld.
2015-05-08 20:20:14 +01:00
Martin Whitaker 3069b8dd51 Simplify use of iverilog-vpi under Windows.
iverilog-vpi now automatically finds the IVL root directory,
eliminating the need for the -ivl option. Also, if the MinGW
root path hasn't been added to the registry, it now searches
the system path for it.
2015-05-08 20:15:54 +01:00
Maciej Suminski 7db01d8ded vhdlpp: ScopeBase::is_enum_name() returns VTypeEnum* instead of bool. 2015-05-07 16:28:30 +02:00
Maciej Suminski e4694cb6cb vhdlpp: Changed emitted type from 'bool' to 'bit'. 2015-05-07 16:09:02 +02:00
Maciej Suminski 08e5aa021a vhdlpp: Emits typedef for boolean type. 2015-05-07 16:09:02 +02:00
Larry Doolittle 4304fd503e vhdlpp: and_reduce() and or_reduce() functions. 2015-05-06 10:03:02 +02:00
Maciej Suminski 5438464d67 vhdlpp: Support for reports & asserts. 2015-05-06 10:02:56 +02:00
Maciej Suminski 6df2979998 vhdlpp: Added missing std_logic values in ExpChar and ExpString::emit(). 2015-05-06 09:55:08 +02:00
Maciej Suminski 9de4ced133 vhdlpp: Stop compilation on invalid attributes. 2015-05-06 09:55:08 +02:00
Martin Whitaker 45dc13e496 Use uintptr_t/intptr_t when casting between pointer and integer.
The code was using (unsigned) long, but a long is 32-bits in the
Windows 64-bit ABI.
2015-05-05 23:00:09 +01:00
Martin Whitaker 9e3f1ef1ff Only apply linker renaming of strtod() when using 32-bit MinGW.
mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
2015-05-05 22:55:15 +01:00
Martin Whitaker 1b3e321d35 Eliminate a few new compiler warnings. 2015-05-04 22:32:29 +01:00
Martin Whitaker a27274aa04 Fix driver-vpi makefile to add C++ compiler flags to source code.
Also fix a few compiler warnings.
2015-05-04 22:10:29 +01:00
Martin Whitaker f1be16be7c Update PC version of iverilog-vpi to use CXXFLAGS for C++ compiles.
CFLAGS was being used for both C and C++ source files, but the
rcently added -Wstrict-prototypes flag is not valid for C++.
2015-05-04 18:40:53 +01:00
Martin Whitaker 9ac374501c Updated config.guess and config.sub.
Sourced from the config project at http://git.savannah.gnu.org. This
version correctly identifies both 32 and 64 bit versions of mingw-w64.
2015-05-04 18:40:53 +01:00
Martin Whitaker 250b278d0e Attempt to allow native line endings in Windows git checkouts.
Up to now, I've had to set git to preserve line endings when
building with MinGW. The problem seems to be gperf. Let's see
if this fixes it.
2015-05-01 22:55:19 +01:00
Cary R 52275deb0e Fix compile build failure 2015-04-30 10:18:21 -07:00
Cary R 120ad59017 Merge branch 'master' of github.com:steveicarus/iverilog 2015-04-30 10:13:10 -07:00
Cary R 2ac8a555e1 Remove bison warning and make YACC rule match the rest 2015-04-30 10:12:57 -07:00
Cary R 8d845ae49f Remove bison warning and make YACC rule match the rest 2015-04-27 16:25:40 -07:00
Martin Whitaker 352175d921 Fix for br973 - add support for enum declarations with no dimensions. 2015-04-26 12:46:08 +01:00
Martin Whitaker e78205eacf GitHub issue #60 (part 2) - warn about excessive array/vector dimensions. 2015-04-26 12:00:21 +01:00
Martin Whitaker c6e618350d Fix for GitHub issue #60 (part 1) - reject numeric constant with zero size. 2015-04-26 11:04:02 +01:00
Martin Whitaker 301a7e587b Fix for GitHub issue #62 - assertion failure on too many array/vector indices.
Provide an error message for invalid code that contains more indices than
there are dimensions.
2015-04-25 22:57:14 +01:00
Martin Whitaker 3cee5d4567 Fix br972 - assertion failure with combinational loop on logic function.
Observe the warning note on nexus_log_add! The returned pointer is only
valid until the next pin is added to the nexus.
2015-04-25 19:50:00 +01:00
Martin Whitaker e1ae5020c4 Another sorry message to catch non-constant RHS in procedural CA. 2015-04-25 11:25:33 +01:00
Martin Whitaker 22d15f9ca9 Fix handling of expression width with $ivlh_to_unsigned.
The first argument to $ivlh_to_unsigned should be treated as having
a self-determined width.
2015-04-25 09:20:31 +01:00
Larry Doolittle 19d966e235 Try to eliminate spurious -dirty in version_tag.h 2015-04-24 14:31:46 -07:00
Larry Doolittle c8fe897446 vhdlpp: and_reduce() and or_reduce() functions. 2015-04-24 13:46:30 +02:00
Maciej Suminski 5101b3b64b vhdlpp: Boolean values handled without using keywords. 2015-04-24 13:39:41 +02:00
Maciej Suminski bed5ee4529 vhdlpp: Handle 'severity' statements without using keywords. 2015-04-24 13:39:41 +02:00
Maciej Suminski 7c0a191626 vhdlpp: Handle true/false values. 2015-04-23 11:58:40 +02:00
Maciej Suminski cfa43c7742 vhdlpp: Support for reports & asserts. 2015-04-23 11:58:40 +02:00
Maciej Suminski a5138e238f vhdlpp: Added missing std_logic values in ExpChar and ExpString::emit(). 2015-04-23 11:57:27 +02:00
Maciej Suminski d352d8ead3 vhdlpp: Stop compilation on invalid attributes. 2015-04-23 11:57:27 +02:00
Cary R 02ee3874e7 Space/code cleanup and warn that vvp does not support S/R D-FF 2015-04-20 15:41:44 -07:00
Johann Klammer f9fef5d00b driven_mask... 2015-04-20 15:11:52 -07:00
Johann Klammer 891399185f lhs partsel and sync scramble 2015-04-20 15:11:40 -07:00
Larry Doolittle 5dc1396eea Spelling fixes 2015-04-13 11:35:12 -07:00
Martin Whitaker ccf7c042c9 Fix null pointer dereference in debug output.
Don't display an elaborated for loop initial assignment if elaboration
has failed. Also remove duplicated message.
2015-04-13 16:31:28 +01:00
Martin Whitaker 560b9530fd Fix for br970 - iverilog silently eats warnings when comma present in -W flag.
The -W option does not (currently) support comma separated lists and
silently ignores any string that doesn't match a known warning class.
Fix by outputing a warning message when the -W argument is unknown.
2015-04-13 14:53:56 +01:00
Martin Whitaker b89c059153 Fix compiler crash on source code errors in always @* block loops.
The compiler was correctly detecting and reporting errors in loop
expressions and statements, but then crashing when it tried to build
the sensitivity list. Fix this by not adding a loop statement to the
netlist unless all its components have been successfully elaborated.
2015-04-13 14:39:10 +01:00
Cary R 8326fe843b Update format string to use correct format character 2015-04-08 19:36:33 -07:00
Cary R 1cbc38100e Update some cppcheck suppression files 2015-04-08 19:36:21 -07:00
Cary R ba31252226 Update fstapi files to latest from GTKWave 2015-04-02 14:59:38 -07:00
Stephen Williams 008affe557 Merge pull request #57 from orsonmmz/br942
bugfix #942: VHDL function bodies in arch declaration not supported
2015-04-01 08:22:03 -07:00
Maciej Suminski 0ca856d4e8 bugfix #942: VHDL function bodies in arch declaration not supported 2015-03-31 10:46:24 +02:00
Stephen Williams 2a210dfee1 Merge pull request #56 from orsonmmz/expfunc
Expfunc
2015-03-27 17:44:13 -07:00
Maciej Suminski 83d721232d ivl: $ivlh_to_unsigned() also tests its argument width. 2015-03-27 20:53:14 +01:00
Maciej Suminski d5ffb55bfd Corrected ambiguous copyright info. 2015-03-27 18:57:40 +01:00
Maciej Suminski ab9a8ccbf3 vhdlpp: Added fit_type() & probe_type() for ExpFunc. 2015-03-27 18:57:40 +01:00
Maciej Suminski e6525ec35f vhdlpp: Added a constructor for VTypeArray that takes integers as ranges. 2015-03-27 18:57:40 +01:00
Maciej Suminski afaedbd06d vhdlpp: Corrected to_integer() & resize() functions.
to_integer() handles sign and resize() really applies size casting.
2015-03-27 14:53:43 +01:00
Maciej Suminski d4237774a5 vhdlpp: Error message for missing types in VTypePrimitive::get_width(). 2015-03-27 14:53:43 +01:00
Maciej Suminski 2f2539e557 vhdlpp: Renamed a range_t constructor parameter to be more descriptive. 2015-03-27 14:53:43 +01:00
Maciej Suminski 11a86794d9 ivl: Fixed size casting. 2015-03-27 14:53:43 +01:00
Maciej Suminski 3b14797075 vhdlpp: Prefix probe for VTypeArray. 2015-03-27 14:53:43 +01:00
Martin Whitaker e006f9e132 Fix vvp crash when a part select of a wire is passed to $monitor.
When the PV expression is compiled, the parent net may not yet be
resolved, so we may not be able to get its VPI handle straight away.
2015-03-17 21:14:30 +00:00
Stephen Williams 437dc10341 Merge pull request #55 from orsonmmz/const_record
Const record
2015-03-12 10:30:56 -07:00
Cary R 102d2d534f Remove extra warning code. 2015-03-09 14:35:31 -07:00
Cary R 5e437145bf A SV queue can be signed. 2015-03-07 18:07:00 -08:00
Maciej Suminski d1dc98b7f7 vhdlpp: Changed the workaround for accessing localparam arrays & records. 2015-03-07 20:47:20 +01:00
Cary R 50b45dac7b Update queue push front/back code generation 2015-03-06 16:56:22 -08:00
Maciej Suminski 295e4e7dfb vhdlpp: Fixed crash on unassociated generics. 2015-03-06 20:39:10 +01:00
Maciej Suminski 807ad8002d vhdlpp: Check generics when searching through constants. 2015-03-06 20:39:10 +01:00
Maciej Suminski d3229b9068 vhdlpp: 'string' type is emitted as 'string' instead of 'array <> of character'. 2015-03-06 17:58:04 +01:00
Maciej Suminski 099bb427bc vhdlpp: ComponentBase::write_to_stream() saves generics. 2015-03-06 17:58:04 +01:00
Maciej Suminski d406545331 vpi: $ivlh_{rising,falling}_edge functions. 2015-03-06 17:58:04 +01:00
Maciej Suminski 1de3fb1625 vhdlpp: "resize" function. 2015-03-06 17:58:04 +01:00
Maciej Suminski e33b8b4dde vhdlpp: VType::get_width() uses information from Scope to determine the type width. 2015-03-06 17:58:04 +01:00
Maciej Suminski 9128eb67b9 vhdlpp: Evaluates attributes if possible. 2015-03-06 17:32:25 +01:00
Maciej Suminski afbda099fb vhdlpp: Workaround to handle constant arrays of vectors & records. 2015-03-06 17:32:25 +01:00
Maciej Suminski 4b0d220671 vhdlpp: get_width() for VType. 2015-03-06 17:32:25 +01:00
Maciej Suminski a42b056b24 vhdlpp: Alternative way of accessing constant arrays of vectors. 2015-03-06 17:32:25 +01:00
Maciej Suminski 1852c5ab9d Revert "vhdlpp: Support for accessing words in constant arrays."
This reverts commit 9ca754b6db.
2015-03-06 17:32:25 +01:00
Cary R 24be13d825 Add support for SV strings to the scanf routines 2015-03-03 17:13:16 -08:00
Cary R bddfcac823 The === and !== operators cannot be used with a SV string 2015-03-02 15:34:22 -08:00
Cary R ea1c07e234 A dynamic array can have a signed type so pass that correctly 2015-03-02 14:40:38 -08:00
Cary R 8e0ae733ca Add support for a SV string to $swrite and $sformat 2015-02-28 11:46:58 -08:00
Cary R feb710a186 Add support for any width 2-state darray objects 2015-02-27 11:43:25 -08:00
Cary R 62abb199d7 Add support for 4-state dynamic arrays 2015-02-26 17:56:49 -08:00
Cary R 7373bf2224 Merge branch 'master' of github.com:steveicarus/iverilog 2015-02-25 19:21:00 -08:00
Cary R ae629f8c41 Add ability to put a string value to a SV string (from plusargs) 2015-02-25 19:20:50 -08:00
Stephen Williams 03e0e96832 Merge branch 'master' of github.com:steveicarus/iverilog 2015-02-25 17:54:24 -08:00
Larry Doolittle 3c38b2972d Add -Wstrict-prototypes to CFLAGS
... and patch vpi/sys_lxt.c so no new warnings are triggered.
2015-02-25 17:52:44 -08:00
Larry Doolittle 4f1fc6e302 Add -Wstrict-prototypes to CFLAGS
... and patch vpi/sys_lxt.c so no new warnings are triggered.
2015-02-25 17:48:38 -08:00
Cary R f1436fbe62 Update fstapi.h to latest from GTKWave 2015-02-25 17:40:18 -08:00
Stephen Williams a79533ddc9 Merge pull request #54 from orsonmmz/const_array
Update
2015-02-20 10:49:53 -08:00
Stephen Williams d47afb588b Merge pull request #52 from orsonmmz/unbounded_function
Unbounded vectors in VHDL functions.
2015-02-20 10:36:19 -08:00
Stephen Williams 386774ac19 Work towards handing packed arrayed members. 2015-02-19 20:02:15 -08:00
Maciej Suminski 9ca754b6db vhdlpp: Support for accessing words in constant arrays. 2015-02-19 17:07:41 +01:00
Maciej Suminski 0f0bef32f2 vhdlpp: Architecture elaboration counts errors coming from expression elaboration. 2015-02-19 17:07:41 +01:00
Maciej Suminski cd55f30a27 vhdlpp: Minor change to ScopeBase::find_constant(). 2015-02-19 17:07:41 +01:00
Maciej Suminski 5884879b02 vhdlpp: to_integer() function. 2015-02-19 17:07:41 +01:00
Maciej Suminski a1a4f47894 vhdlpp: Unnecessary comment. 2015-02-19 17:07:41 +01:00
Maciej Suminski e569e07d4e vhdlpp: Type 'NATURAL' is translated to 'int unsigned'. 2015-02-19 17:07:41 +01:00
Maciej Suminski ee840391d6 vhdlpp: std_logic_vector, signed & unsigned are considered global types. 2015-02-19 17:07:41 +01:00
Maciej Suminski 0046e9eca0 vhdlpp: ActiveScope::is_vector_name() checks also for constants. 2015-02-19 17:07:41 +01:00
Maciej Suminski f51c037432 vhdlpp: Generics from external packages are accepted (warning instead of error). 2015-02-19 17:07:37 +01:00
Maciej Suminski 763c6fe3c9 vhdlpp: Support for shift operators (SRL, SRR, SRA, SLA).
To be done: ROR & ROL.
2015-02-17 10:15:57 +01:00
Maciej Suminski 49b6ddf93c vhdlpp: Signal/variable assignments can have labels. 2015-02-17 10:15:57 +01:00
Maciej Suminski 12b4914b63 vhdlpp: ExpName resolves enum values. 2015-02-17 10:15:57 +01:00
Maciej Suminski fc0728ab6f vhdlpp: Forward typedefs.
It was required to make it possible to use typedefs in port types.
Types from packages are emitted in `ifdef..`endif instead of package..endpackage.

The purest solution is to keep package..endpackage and emit appropriate prefix.
Also, it would be great to have constants emitted in the same way.
2015-02-17 10:15:57 +01:00
Maciej Suminski 46c41f9be2 ivl: Enum type can be used in port declarations. 2015-02-05 17:17:33 +01:00
Maciej Suminski cdf18de10e vhdlpp: Make integer expressions sized during the emission step. 2015-02-05 16:20:49 +01:00
Maciej Suminski 19ff6a434b vhdlpp: Alternative way of dealing with unbounded vectors in fuctions (instances). 2015-02-05 12:00:25 +01:00
Maciej Suminski 5349ca9a55 vhdlpp: Added Subprogram::write_to_stream_body() method. 2015-02-05 12:00:25 +01:00
Maciej Suminski 5b7b980ead vhdlpp: Support for multiple choices in case statements. 2015-02-05 12:00:25 +01:00
Maciej Suminski a1c2a8e605 vhdlpp: Generic syntax errors display messages. 2015-02-05 11:25:03 +01:00
Maciej Suminski 8777cd8e7c vhdlpp: Fixed ExpBitstring & ExpRelation write_to_stream() method. 2015-02-05 11:25:03 +01:00
Maciej Suminski 11bb7ac348 vhdlpp: Expression::write_to_stream becomes const. 2015-02-05 11:25:03 +01:00
Maciej Suminski 9de69f2f24 vhdlpp: SequentialStmts write_to_stream() methods. 2015-02-05 11:25:03 +01:00
Maciej Suminski dae3410dcd vhdlpp: Variable::write_to_stream(). 2015-02-05 11:25:03 +01:00
Maciej Suminski 1a367c84b6 vhdlpp: Subprograms can have instances that take a different set of parameter types. 2015-02-05 11:25:03 +01:00
Maciej Suminski 8a854affa6 vhdlpp: Clone routines for Expression & VType classes. 2015-02-05 11:25:03 +01:00
Maciej Suminski 60077f4f06 vhdlpp: ExpBitstring elaborate_expr(). 2015-02-05 11:25:03 +01:00
Maciej Suminski 51ce9f1a60 vhdlpp: Minor correction for casting to integer. 2015-02-05 11:25:03 +01:00
Maciej Suminski 48265ecd9b vhdlpp: Subprograms return types have their ranges evaluated if possible.
Added VTypeArray::evaluate_ranges() method.
2015-02-05 11:24:59 +01:00
Maciej Suminski abbcea64d0 vhdlpp: Array attributes can be evaluated in packages/functions. 2015-02-04 16:57:43 +01:00
Maciej Suminski 25c3798248 vhdlpp: Elaborate and emit functions work with ScopeBase instead of Architecture. 2015-02-04 16:57:43 +01:00
Maciej Suminski 90293d8e0a vhdlpp: VTypeArray::is_variable_length() uses ScopeBase to determine if variable has constant length. 2015-02-04 16:57:43 +01:00
Maciej Suminski 621cf37339 vhdlpp: Added ScopeBase::find_param() method. 2015-02-04 16:57:43 +01:00
Maciej Suminski 6d75af86e6 vhdlpp: Added Subprogram::fix_variables() method. 2015-02-04 16:57:43 +01:00
Maciej Suminski 5d26f0e28d vhdlpp: Added VTypeArray::is_variable_length() method. 2015-02-04 16:57:43 +01:00
Maciej Suminski 774609fbbb vhdlpp: VTypeArray stores parent type, in case it is a subtype. 2015-02-04 16:57:43 +01:00
Maciej Suminski 9ba7694484 vhdlpp: Minor assert. 2015-02-04 16:57:43 +01:00
Maciej Suminski 870a826225 vhdlpp: Corrected VTypeDef::emit_def() to allow typedefed names in function headers. 2015-02-04 16:57:43 +01:00
Maciej Suminski 2ecfed0baa vhdlpp: Moved part of check_unb_vector() to fix_logic_darray(). 2015-02-04 16:57:43 +01:00
Maciej Suminski 56e410f386 vhdlpp: SigVarBase::peek_name_() method made public. 2015-02-04 16:57:43 +01:00
Maciej Suminski d4dd635bf6 vhdlpp: Added ExpNew class. 2015-02-04 16:57:43 +01:00
Maciej Suminski c287281bbe vhdlpp: Tries to determine if function return type is fixed size.
Added Subprogram::fixed_return_type() method.
2015-02-04 16:57:43 +01:00
Maciej Suminski 962330f20a vhdlpp: Functions support unbounded vectors as return type and parameters. 2015-02-04 16:57:43 +01:00
Maciej Suminski 777e7e0a3d vhdlpp: Added ExpFunc::func_ret_type() method. 2015-02-04 16:57:43 +01:00
Maciej Suminski 839f9cd7ae vhdlpp: Added ReturnStmt::cast_to() method. 2015-02-04 16:57:43 +01:00
Maciej Suminski b8b2f53027 vhdlpp: Added VType::get_generic_typename() method. 2015-02-04 16:57:43 +01:00
Maciej Suminski 9b3bd039bb vhdlpp: Added ExpCast class. 2015-02-04 16:57:42 +01:00
Maciej Suminski 51b9191021 vhdlpp: Added VType::is_unbounded() method. 2015-02-04 16:57:42 +01:00
Maciej Suminski 756c9ceccf ivl: Functions returning a dynamic array may be casted to vector. 2015-02-04 16:02:38 +01:00
Maciej Suminski 8b3667f76e ivl: Casting vectors to dynamic arrays. 2015-02-04 16:02:38 +01:00
Maciej Suminski a52242745a ivl: Casting dynamic arrays to vectors. 2015-02-04 16:02:38 +01:00
Maciej Suminski ff5b696569 vhdlpp: Improved SequentialStmt visitor. 2015-02-04 16:02:38 +01:00
Maciej Suminski b05a19dffc vhdlpp: VTypeArray emits dimensions in a bit smarter way. 2015-02-04 16:02:38 +01:00
Maciej Suminski e6b22a2bea vhdlpp: Visitor for SequentialStmt. 2015-02-04 16:02:38 +01:00
Maciej Suminski a02ebc3114 $ivl_darray_method$[from/to]_vec works with constants. 2015-02-04 16:02:38 +01:00
Maciej Suminski 0592ba042e vhdlpp: For-loop emission rewritten to handle 'range in subprograms. 2015-02-04 16:02:38 +01:00
Maciej Suminski bcca3cf395 ivl: Unpacked array typedefs are correctly recognized when used in function parameters. 2015-02-04 15:58:12 +01:00
Cary R 01ba41afd8 Only skip zero repeat expressions in a concatenation. 2015-02-02 18:15:12 -08:00
Cary R 84c592b068 Fix white space issue 2015-02-02 15:29:25 -08:00
Cary R bb93a585b6 Generate correct vvp code for zero replication cases 2015-02-02 15:27:57 -08:00
Cary R 47688d234b Assert if an unsupported dynamic array type is given. 2015-01-16 18:54:43 -08:00
Cary R b3425d6cf3 Report that 4-state dynamic arrays are not currently supported in vvp
Also fix some error code propagation issues.
2015-01-16 18:22:16 -08:00
Cary R 40ae1051d4 Report the vvp only supports a dynamic array of size 8, 16, 32 or 64 2015-01-15 18:18:14 -08:00
Cary R 21c60b38e1 Fix space issues in the code. 2015-01-15 17:47:39 -08:00
Cary R 78c6b3cad2 More updates for sys_darray.c (fix 32-bit crash and optimize) 2015-01-15 17:44:13 -08:00
Cary R a04104077f Update top level cppcheck suppression file 2015-01-15 17:37:26 -08:00
Cary R 0e3a758894 Some cleanup of the calltf functions in sys_darray.c 2015-01-14 22:22:02 -08:00
Cary R d682029240 Update compiletf routines in sys_darray to be more exact 2015-01-14 19:58:42 -08:00
Cary R 1ffcd40336 Fix a clear word to be after it has been used 2015-01-14 19:48:24 -08:00
Cary R 09439c55ab Add new object to the vpi_get_str(vpiType, handle) code. 2015-01-14 19:08:00 -08:00
Cary R c858dea2d5 Fix compile warning (remainder is a global) 2015-01-14 17:22:27 -08:00
Cary R 228a3f123a For some local nets fix the local flag and file/line information 2015-01-14 16:40:30 -08:00
Cary R 074f7a7a49 Fix undefined access in for loop synthesis 2015-01-14 15:11:36 -08:00
Stephen Williams f642313e1b Merge pull request #50 from orsonmmz/darray
Unpacked arrays extension
2015-01-12 14:08:22 -08:00
Stephen Williams dd9d96eb07 Merge branch 'master' of github.com:steveicarus/iverilog 2015-01-12 09:24:07 -08:00
Maciej Suminski 35401f0e2c ivl: Functions may return dynamic arrays. 2015-01-12 11:08:31 +01:00
Maciej Suminski b6e16aea6b ivl: Typedefs may use unpacked arrays. 2015-01-12 11:08:31 +01:00
Maciej Suminski eeaf23041b vvp: Support for dynamic arrays of logic type. 2015-01-12 11:08:31 +01:00
Maciej Suminski e8096eda80 ivl: Support for unpacked arrays of structures. 2015-01-12 11:08:31 +01:00
Maciej Suminski 961d6a8f3b vpi: $left and $right functions for arrays and strings. 2015-01-12 11:08:31 +01:00
Maciej Suminski 288ebf011c vpi: Moved $ivl_darray_method$[from/to]_vec to sys_darray.c 2015-01-12 11:08:31 +01:00
Maciej Suminski 0ae304b6a8 vpi: Added $ivl_darray_method$from_vec.
Converts a vector to dynamic array of vectors.
2015-01-12 11:08:31 +01:00
Maciej Suminski 5e61bb64b7 vpi: Added $ivl_darray_method$to_vec.
Converts a dynamic array of vectors to a single vector.
2015-01-12 11:08:31 +01:00
Cary R 3f847fd927 Fix a compile warning 2015-01-10 16:28:55 -08:00
Cary R 4a41a53b42 For valgrind clean up the class definitions at the end. 2015-01-10 16:18:59 -08:00
Martin Whitaker a1630e1d30 Fix for br968.
__vpiVThrVec4Stack::vpi_get_value_int_ was always treating the thread variable
as unsigned, rather than observing the value of __vpiVThrVec4Stack::signed_flag_.
Not sure why this was done - none of the regression tests broke when I changed
this.
2015-01-10 17:24:50 +00:00
Martin Whitaker bca84d9dbb Added parser support for SV modport declarations. 2015-01-10 11:10:41 +00:00
Cary R e61ed48914 Clean up vals_words when a dynamic array is accessed using the vpi 2015-01-09 17:38:39 -08:00
Cary R d29a6d134f Fix valgrind cleanup of dynamic and queue arrays 2015-01-09 15:05:48 -08:00
Cary R 6310b47538 Fix a memory leak when searching for an element by name 2015-01-08 16:14:20 -08:00
Cary R 9c75a4b96b Fix a memory leak when the dump file cannot be opened 2015-01-08 16:14:08 -08:00
Cary R c57e68292c Fix undefined value problem in compiler (found with valgrind) 2015-01-08 10:05:32 -08:00
Stephen Williams 0fecdcbeda Icarus Verilog snapshot 2015-01-05 2015-01-05 10:34:18 -08:00
Cary R 23ad62f317 Update cppcheck results 2014-12-28 09:27:14 -08:00
Cary R ac20008606 Update lz4 files from GTKWave 2014-12-28 09:25:54 -08:00
Stephen Williams 96d181efed Support vpiStrengthVal for vec4 stack objects. 2014-12-23 14:42:45 -08:00
Stephen Williams 18bfe7d497 Merge branch 'master' of github.com:steveicarus/iverilog 2014-12-23 13:52:48 -08:00
Stephen Williams 86562e60ba Work towards nested packed struct member vectors. 2014-12-23 13:52:38 -08:00
Martin Whitaker b400532169 Added support for interface declaration and instantiation.
modport and extern tf declarations are not yet supported.
2014-12-19 23:10:14 +00:00
Stephen Williams 6fd10dedb6 Add some implicit support for std and textio libraries
Patch submitted by Fabrizio Ferrandi.
2014-12-18 08:20:19 -08:00
Cary R c8255952a3 Update cppcheck supprression file 2014-12-16 16:47:00 -08:00
Martin Whitaker 71c4ea36e8 Pass -v compiler option to vvp in the output file shebang line.
Slightly modified version of the patch contributed by Stephan
Böttcheron iverilog-devel.
2014-12-16 21:22:19 +00:00
Martin Whitaker 5df179cd5f Implement feature request #47.
This causes vvp to evaluate all the input expressions for a user
function call before assigning any of them to the function input
variables. This stops the input variables being overwritten if
the same (non-automatic) function is used in one of the input
expressions.
2014-12-14 21:46:28 +00:00
Martin Whitaker ce5c4ca8ba Fix for br967 - allow real value for repeat statement loop length. 2014-12-13 19:50:33 +00:00
Martin Whitaker 6aa8e49b09 Add sorry message for unsupported arrays of named events. 2014-12-13 17:46:56 +00:00
Martin Whitaker f29f4ff4e3 Fix for br965.
When performing constant propagation, we need to take into account
values driven through a tran object. For now, be pessimistic, and
assume that all tran objects connect to a variable driver.
2014-12-13 12:49:13 +00:00
Cary R 3ccc59eaa3 Fix compile with valgrind hooks after vec4-stack changes 2014-12-12 14:28:07 -08:00
Martin Whitaker 0282b8450c Fix potential memory leak when a thread is disabled.
A disable statement can terminate a thread whilst it still has
local variables on the stack (e.g. the loop counter for a repeat
statement). We need to clear the thread stacks when this happens.
2014-12-11 20:10:17 +00:00
Cary R 43841af2f3 Fix a cppcheck warning and fix code style a bit 2014-12-11 09:59:15 -08:00
Cary R b2d8d41e3f Fix some cppcheck warnings in tgt-vvp 2014-12-10 16:30:55 -08:00
Cary R 0e38843ae9 Make verinum output match for either 32-bit or 64-bit systems 2014-12-10 15:11:45 -08:00
Cary R 96472e5537 For a signed R-value we can use the full width when converting to long
When trying to get the value we can use the full width of a long if the
expression is signed.
2014-12-10 14:41:27 -08:00
Cary R 48b0fed29e Use uint64_t casting of constants since UL does not work on 32-bit machines
Using a UL constant in a unit64_t context does not work on a 32-bit
machine since UL is 32-bits. Instead create uint64_t constants using
static casts and the appropriate bit operators.
2014-12-10 14:41:18 -08:00
Cary R 1efa220773 Fix non-blocking assignment to an array error state handling
If either the index or part offset expressions generate an undefined
value then the assignment is skipped. This patch reworks the code that
handles the flags used to detect this. For some simple cases a global
flag is not needed, but for other cases one is needed since there are
two expressions that can generate an error and even when there is only
a variable expression this error state needs to be preserved if there
is a variable delay. An undefined delay value defaults to zero and is
not an error.
2014-12-09 17:29:18 -08:00
Cary R 2d6622e543 vlog95: for a 32-bit width we can generate a signed undefined value 2014-12-08 21:09:36 -08:00
Cary R edf112b900 Update all the vvp examples to work correctly 2014-12-08 20:55:19 -08:00
Cary R f0a0ab100f vlog95: trim binary constants to save space and emit size of undef. consts.
This should not change the functionality, but to save space trim any
unneeded bits from a binary constant. Also for the case of emitting
a signed undefined value when the allow signed flag is not set add
the width to the constant.
2014-12-08 13:08:30 -08:00
Cary R c28188618b File example vvp code so make check passes. 2014-12-08 10:43:46 -08:00
Martin Whitaker 0d7daf5862 Fix vvp memory leak for user function calls in a continuous assignment. 2014-12-07 13:47:50 +00:00
Martin Whitaker 60ab1daa1f Restore some master branch fixes lost in the vec4-stack merge. 2014-12-07 12:10:15 +00:00
153 changed files with 6717 additions and 3559 deletions
+2
View File
@@ -0,0 +1,2 @@
# gperf in MSYS chokes on DOS line endings
*.gperf text eol=lf
+3 -3
View File
@@ -118,8 +118,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
Statement.o AStatement.o $M $(FF) $(TT)
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
PFunction.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@@ -292,7 +292,7 @@ endif
version_tag.h version:
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
echo "Using git-describe for VERSION_TAG"; \
tmp=`$(GIT) --git-dir $(srcdir)/.git describe --always --dirty \
tmp=`(cd $(srcdir) && $(GIT) describe --always --dirty) \
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
elif test -r $(srcdir)/version_tag.h; then \
+17 -2
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -35,6 +35,7 @@ class PExpr;
class PEIdent;
class PGate;
class PGenerate;
class PModport;
class PSpecPath;
class PTask;
class PFunction;
@@ -47,6 +48,10 @@ class NetScope;
* A module is a named container and scope. A module holds a bunch of
* semantic quantities such as wires and gates. The module is
* therefore the handle for grasping the described circuit.
*
* SystemVerilog introduces program blocks and interfaces. These have
* much in common with modules, so the Module class is used to represent
* these containers as well.
*/
class Module : public PScopeExtra, public LineInfo {
@@ -64,7 +69,7 @@ class Module : public PScopeExtra, public LineInfo {
public:
/* The name passed here is the module name, not the instance
name. This make must be a permallocated string. */
name. This name must be a permallocated string. */
explicit Module(LexicalScope*parent, perm_string name);
~Module();
@@ -81,6 +86,11 @@ class Module : public PScopeExtra, public LineInfo {
restrictions and slightly modify scheduling semantics. */
bool program_block;
/* This is true if the module represents a interface
instead of a module/cell. Interfaces have different
content restrictions and some extra allowed items. */
bool is_interface;
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
UCDriveType uc_drive;
@@ -125,6 +135,11 @@ class Module : public PScopeExtra, public LineInfo {
unless they are instantiated, implicitly or explicitly. */
std::map<perm_string,Module*> nested_modules;
/* An interface can contain one or more named modport lists.
The parser will ensure these don't appear in modules or
program blocks. */
map<perm_string,PModport*> modports;
list<PSpecPath*> specify_paths;
// The mod_name() is the name of the module type.
+8 -3
View File
@@ -436,7 +436,7 @@ class PEIdent : public PExpr {
const perm_string&) const;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
const name_component_t&) const;
bool elaborate_lval_darray_bit_(Design*, NetScope*,
NetAssign_*) const;
@@ -917,8 +917,10 @@ class PECallFunction : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
@@ -997,6 +999,9 @@ class PECastType : public PExpr {
void dump(ostream &out) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include "PModport.h"
PModport::PModport(perm_string n)
: name_(n)
{
}
PModport::~PModport()
{
}
+52
View File
@@ -0,0 +1,52 @@
#ifndef IVL_PModport_H
#define IVL_PModport_H
/*
* Copyright (c) 2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PScope.h"
# include "StringHeap.h"
# include "netlist.h"
# include <vector>
/*
* The PModport class represents a parsed SystemVerilog modport list.
*/
class PModport : public LineInfo {
public:
// The name is a perm-allocated string. It is the simple name
// of the modport, without any scope.
explicit PModport(perm_string name);
~PModport();
perm_string name() const { return name_; }
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
map<perm_string,simple_port_t> simple_ports;
private:
perm_string name_;
private: // not implemented
PModport(const PModport&);
PModport& operator= (const PModport&);
};
#endif /* IVL_PModport_H */
Vendored
+2 -1
View File
@@ -223,8 +223,9 @@ AC_SUBST(strip_dynamic)
# -------------
AC_DEFUN([AX_C99_STRTOD],
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
case "${host}" in
*-*-mingw*)
*-*-mingw32)
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
;;
esac
+324 -447
View File
File diff suppressed because it is too large Load Diff
Vendored
+225 -101
View File
@@ -1,44 +1,40 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
# Copyright 1992-2015 Free Software Foundation, Inc.
timestamp='2009-04-17'
timestamp='2015-03-08'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to <[email protected]>. Submit a context
# diff and a properly formatted ChangeLog entry.
# Please send patches to <[email protected]>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -72,8 +68,7 @@ Report bugs and patches to <[email protected]>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -120,13 +115,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -149,10 +149,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray)
-apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -167,10 +170,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
;;
-hiux*)
os=-hiuxwe2
;;
@@ -215,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
@@ -239,20 +248,28 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | clipper \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| fido | fr30 | frv \
| e2k | epiphany \
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep | metag \
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -266,36 +283,55 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nios | nios2 \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| or32 \
| open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| visium \
| we32k \
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
leon|leon[3-9])
basic_machine=sparc-$basic_machine
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -305,6 +341,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -319,25 +370,31 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| e2k-* | elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -351,32 +408,42 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| romp-* | rs6000-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| visium-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
@@ -401,7 +468,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -451,6 +518,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-aros
;;
asmjs)
basic_machine=asmjs-unknown
;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -467,11 +537,24 @@ case $basic_machine in
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
@@ -503,7 +586,7 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
cr16)
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
@@ -661,7 +744,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -700,6 +782,9 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
leon-*|leon[3-9]-*)
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
@@ -719,8 +804,15 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
mingw64)
basic_machine=x86_64-pc
os=-mingw64
;;
mingw32)
basic_machine=i386-pc
basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
@@ -748,6 +840,10 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
moxiebox)
basic_machine=moxie-unknown
os=-moxiebox
;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -755,10 +851,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i686-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -823,6 +927,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -905,9 +1015,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -932,7 +1043,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
rdos | rdos64)
basic_machine=x86_64-pc
os=-rdos
;;
rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -1001,6 +1116,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
@@ -1057,20 +1175,8 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tic55x | c55x*)
basic_machine=tic55x-unknown
os=-coff
;;
tic6x | c6x*)
basic_machine=tic6x-unknown
os=-coff
;;
tile*)
basic_machine=tile-unknown
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
@@ -1140,6 +1246,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1237,9 +1346,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1260,30 +1372,31 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -kopensolaris* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -aos* | -aros* | -cloudabi* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1322,7 +1435,7 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
-os400*)
os=-os400
;;
-wince*)
@@ -1371,7 +1484,7 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
-tpf*)
os=-tpf
;;
-triton*)
@@ -1407,15 +1520,14 @@ case $os in
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
@@ -1438,10 +1550,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
score-*)
score-*)
os=-elf
;;
spu-*)
spu-*)
os=-elf
;;
*-acorn)
@@ -1453,8 +1565,23 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
c4x-* | tic4x-*)
os=-coff
;;
c8051-*)
os=-elf
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1474,14 +1601,11 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
m68*-cisco)
os=-aout
;;
mep-*)
mep-*)
os=-elf
;;
mips*-cisco)
@@ -1508,7 +1632,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-knuth)
*-knuth)
os=-mmixware
;;
*-wec)
@@ -1613,7 +1737,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
-aix*)
-cnk*|-aix*)
vendor=ibm
;;
-beos*)
+5 -1
View File
@@ -82,7 +82,7 @@ CFLAGS="$iverilog_temp_cflags"
AC_SUBST(DEPENDENCY_FLAG, [-MD])
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
AC_SUBST(WARNING_FLAGS_CC, [""])
AC_SUBST(WARNING_FLAGS_CC, ["-Wstrict-prototypes"])
AC_SUBST(WARNING_FLAGS_CXX, [""])
fi
@@ -223,6 +223,10 @@ case "${host}" in
CPPFLAGS="-mieee $CPPFLAGS"
CFLAGS="-mieee $CFLAGS"
;;
*-*-mingw*)
CXXFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CXXFLAGS"
CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CFLAGS"
;;
esac
# Do some more operating system specific setup. We put the file64_support
+2 -2
View File
@@ -1,3 +1,3 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:4938
thisSubtraction:netlist.h:4947
thisSubtraction:netlist.h:4976
thisSubtraction:netlist.h:4985
+1
View File
@@ -1375,6 +1375,7 @@ void NetScope::dump(ostream&o) const
if (is_cell()) o << " (cell)";
if (nested_module()) o << " (nested)";
if (program_block()) o << " (program)";
if (is_interface()) o << " (interface)";
o << " " << children_.size() << " children, "
<< classes_.size() << " classes" << endl;
+2
View File
@@ -49,6 +49,7 @@ endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
LDFLAGS = @LDFLAGS@
O = main.o res.o
@@ -80,6 +81,7 @@ config.h: $(srcdir)/config.h.in Makefile
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
-e 's;@SUFFIX@;$(suffix);g' \
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
-e 's;@IVLCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@SHARED@;@shared@;' $< > $@
# Windows specific...
+1
View File
@@ -4,6 +4,7 @@
#define IVERILOG_VPI_CC "@IVLCC@"
#define IVERILOG_VPI_CXX "@IVLCXX@"
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@"
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
#define IVERILOG_SUFFIX "@SUFFIX@"
+169 -164
View File
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2002 Gus Baldauf ([email protected])
* Copyright (c) 2015 Martin Whitaker
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,7 +21,7 @@
/*
* iverilog-vpi.c
*
* this program provides the functionality of iverilog-vpi.sh under Win32
* this program provides the functionality of iverilog-vpi.sh under Windows
*/
#include <stdio.h>
@@ -32,7 +33,7 @@
#include <windows.h>
static void setup_ivl_environment();
static void setup_ivl_environment(void);
static void assign(char **ptr, char *str);
/* The compile options: compiler, flags, etc. are in here */
@@ -43,16 +44,17 @@ static void assign(char **ptr, char *str);
static struct global_strings {
char *pCCSRC; /* list of C source files (*.c) */
char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
char *pOBJ; /* list of object files */
char *pLIB; /* list of library files */
char *pINCS; /* list of include directories */
char *pDEFS; /* list of definitions */
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
char *pOBJ; /* list of object files */
char *pLIB; /* list of library files */
char *pINCS; /* list of include directories */
char *pDEFS; /* list of definitions */
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
char *pMINGW; /* path to MinGW directory */
char *pIVL; /* path to IVL directory */
char *pCFLAGS; /* CFLAGS option */
char *pLDLIBS; /* LDLIBS option */
char *pNewPath; /* new PATH environment variable setting */
char *pIVL; /* path to IVL directory */
char *pCCFLAGS; /* compiler flags for compiling C source files */
char *pCXFLAGS; /* compiler flags for compiling C++ source files */
char *pLDLIBS; /* linker flags for final linking stage */
char *pCCNAME; /* base name of compiler */
char *pLD; /* what to use for a linker */
} gstr;
@@ -75,21 +77,21 @@ static void myExit(int exitVal)
deInitDynString(gstr.pOUT);
deInitDynString(gstr.pMINGW);
deInitDynString(gstr.pIVL);
deInitDynString(gstr.pCFLAGS);
deInitDynString(gstr.pCCFLAGS);
deInitDynString(gstr.pCXFLAGS);
deInitDynString(gstr.pLDLIBS);
deInitDynString(gstr.pNewPath);
free(gstr.pLD);
deInitDynString(gstr.pCCNAME);
deInitDynString(gstr.pLD);
exit(exitVal);
}
/* display usage summary and exit */
static void usage()
static void usage(void)
{
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
fprintf(stderr, "usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n");
fprintf(stderr, " or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
myExit(1);
}
@@ -98,7 +100,7 @@ static void initDynString(char **str)
*str = (char *) malloc(1);
if (!*str) {
fprintf(stderr,"error: out of memory\n");
fprintf(stderr, "error: out of memory\n");
myExit(4);
}
@@ -107,8 +109,10 @@ static void initDynString(char **str)
/* initialize dynamic memory buffers */
static void init()
static void init(void)
{
char *ptr;
initDynString(&gstr.pCCSRC);
initDynString(&gstr.pCXSRC);
initDynString(&gstr.pOBJ);
@@ -118,9 +122,17 @@ static void init()
initDynString(&gstr.pOUT);
initDynString(&gstr.pMINGW);
initDynString(&gstr.pIVL);
initDynString(&gstr.pCFLAGS);
initDynString(&gstr.pCCFLAGS);
initDynString(&gstr.pCXFLAGS);
initDynString(&gstr.pLDLIBS);
initDynString(&gstr.pNewPath);
initDynString(&gstr.pCCNAME);
initDynString(&gstr.pLD);
/* Get the base name of the C compiler. */
assign(&gstr.pCCNAME, IVERILOG_VPI_CC);
ptr = strchr(gstr.pCCNAME, ' ');
if (ptr != NULL) *ptr = '\0';
/* By default use the C compiler to link the programs. */
assign(&gstr.pLD, IVERILOG_VPI_CC);
}
@@ -136,7 +148,7 @@ static int endsIn (char *end, char *str)
ext = str + (strlen(str) - strlen(end));
return stricmp(end,ext) ? 0 : 1;
return stricmp(end, ext) ? 0 : 1;
}
/* return true if "str" begins with "prefix", case insensitive */
@@ -146,35 +158,35 @@ static int startsWith (char *prefix, char *str)
if (strlen(prefix) >= strlen(str))
return 0;
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
return strnicmp(prefix, str, strlen(prefix)) ? 0 : 1;
}
/* append "app" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "app" */
static void appendn (char **ptr, char *app, int count)
static void appendn (char **ptr, char *app, size_t count)
{
char *nptr = (char *) realloc(*ptr, strlen(*ptr) +
(count?count:strlen(app)) + 1);
(count ? count : strlen(app)) + 1);
if (nptr == NULL) {
fprintf(stderr,"error: out of memory\n");
fprintf(stderr, "error: out of memory\n");
free(*ptr);
myExit(4);
}
*ptr = nptr;
if (count)
strncat(*ptr,app,count);
strncat(*ptr, app, count);
else
strcat(*ptr,app);
strcat(*ptr, app);
}
/* append "app" to "ptr", allocating memory as needed */
static void append (char **ptr, char *app)
{
appendn(ptr,app,0);
appendn(ptr, app, 0);
}
/* if the string does not end with a backslash, add one */
@@ -182,36 +194,36 @@ static void append (char **ptr, char *app)
static void appendBackSlash(char **str)
{
if ((*str)[strlen(*str)-1] != '\\')
append(str,"\\");
append(str, "\\");
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "str" */
static void assignn (char **ptr, char *str, int count)
static void assignn (char **ptr, char *str, size_t count)
{
char *nptr = (char *) realloc(*ptr, (count?count:strlen(str)) + 1);
char *nptr = (char *) realloc(*ptr, (count ? count : strlen(str)) + 1);
if (nptr == NULL) {
fprintf(stderr,"error: out of memory\n");
fprintf(stderr, "error: out of memory\n");
free(*ptr);
myExit(4);
}
*ptr = nptr;
if (count) {
strncpy(*ptr,str,count);
strncpy(*ptr, str, count);
(*ptr)[count] = 0;
}
else
strcpy(*ptr,str);
strcpy(*ptr, str);
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
static void assign (char **ptr, char *str)
{
assignn(ptr,str,0);
assignn(ptr, str, 0);
}
/* get a copy of a Icarus Verilog registry string key */
@@ -223,11 +235,11 @@ static int GetRegistryKey(char *key, char **value)
char *regKeyBuffer;
DWORD regKeyType, regKeySize;
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, KEY_QUERY_VALUE, &hkKey);
if (lrv != ERROR_SUCCESS)
return 0;
lrv = RegQueryValueEx(hkKey,key,NULL,&regKeyType,NULL,&regKeySize);
lrv = RegQueryValueEx(hkKey, key, NULL, &regKeyType, NULL, &regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
return 0;
@@ -236,7 +248,7 @@ static int GetRegistryKey(char *key, char **value)
regKeyBuffer = (char *) malloc(regKeySize+1);
if (!regKeyBuffer) {
lrv = RegCloseKey(hkKey);
fprintf(stderr,"error: out of memory\n");
fprintf(stderr, "error: out of memory\n");
myExit(4);
}
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
@@ -252,7 +264,7 @@ static int GetRegistryKey(char *key, char **value)
RegCloseKey(hkKey);
assign(value,regKeyBuffer);
assign(value, regKeyBuffer);
free(regKeyBuffer);
return 1;
@@ -262,27 +274,30 @@ static int GetRegistryKey(char *key, char **value)
static void SetRegistryKey(char *key, char *value)
{
long lrv;
HKEY hkKey;
DWORD res;
if (RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
"Software\\Icarus Verilog",
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,NULL,
&hkKey,
&res) != ERROR_SUCCESS)
return;
lrv = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, "",
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, &res);
if (lrv != ERROR_SUCCESS) {
char message[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lrv, LANG_USER_DEFAULT,
message, sizeof(message), NULL);
fprintf(stderr, "error: couldn't write to registry - %s\n", message);
if (lrv == ERROR_ACCESS_DENIED) {
fprintf(stderr, " try running as administrator\n");
}
return;
}
/* This needs an unsigned char *, but for MinGW the char is signed. */
RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value,
strlen(value)+1);
RegCloseKey(hkKey);
printf("info: storing %s in Windows' registry entry\n",value);
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
printf("info: storing %s in Windows' registry entry\n", value);
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n", key);
}
/* parse the command line, assign results to global variable strings */
@@ -299,7 +314,6 @@ static int parse(int argc, char *argv[])
char lib_option[] = "-l";
char inc_option[] = "-I";
char mingw_option[] = "-mingw=";
char ivl_option[] = "-ivl=";
char def_option[] = "-D";
if (argc == 1) return 0;
@@ -339,7 +353,7 @@ static int parse(int argc, char *argv[])
/* Check for compiled object files */
else if (endsIn(dot_o_ext, argv[idx])) {
++srcFileCnt;
append(&gstr.pOBJ," ");
append(&gstr.pOBJ, " ");
append(&gstr.pOBJ, argv[idx]);
if (!*gstr.pOUT)
assignn(&gstr.pOUT, argv[idx],
@@ -349,10 +363,6 @@ static int parse(int argc, char *argv[])
else if (startsWith(mingw_option, argv[idx]))
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
strlen(argv[idx])-(sizeof(mingw_option)-1));
/* Check for the -ivl option */
else if (startsWith(ivl_option, argv[idx]))
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
strlen(argv[idx])-(sizeof(ivl_option)-1));
/* Check for the --name option */
else if (startsWith(name_option, argv[idx])) {
assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1,
@@ -376,7 +386,7 @@ static int parse(int argc, char *argv[])
/* Check for the --cflags option */
else if (stricmp("--cflags", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\n", gstr.pCFLAGS);
printf("%s\n", gstr.pCCFLAGS);
myExit(0);
}
/* Check for the --ldflags option */
@@ -393,7 +403,7 @@ static int parse(int argc, char *argv[])
/* Check for the --install-dir option */
else if (stricmp("--install-dir", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
printf("%s\\lib\\ivl" IVERILOG_SUFFIX "\\.\n", gstr.pIVL);
myExit(0);
}
/* This is different than iverilog-vpi.sh, we don't
@@ -402,15 +412,16 @@ static int parse(int argc, char *argv[])
}
/* In case there is a --name without source/object files */
if (0 == srcFileCnt) assign(&gstr.pOUT,"");
if (0 == srcFileCnt) assign(&gstr.pOUT, "");
/* Normally it's an error if there are no source or object files */
/* Unless we are setting the IVL or MinGW registry entries */
if (!*gstr.pOUT) {
if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
} else
if (*gstr.pOUT) {
/* We have a valid result file so add the .vpi extension */
append(&gstr.pOUT, ".vpi");
} else {
/* Unless we are setting the MinGW registry entry, it's
an error if there are no source or object files */
if (!*gstr.pMINGW) return 0;
}
return 1;
}
@@ -421,58 +432,27 @@ static void checkMingwDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path, *comp, *cp;
initDynString(&path);
assign(&path,gstr.pMINGW);
appendBackSlash(&path);
append(&path,"bin\\");
/* Get just the compiler name (the first word) */
comp = strdup(IVERILOG_VPI_CC);
cp = strchr(comp, ' ');
if (cp != NULL) *cp = '\0';
append(&path, comp);
append(&path,".exe");
free(comp);
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\\\mingw\n");
myExit(5);
}
}
/* do minimal check that the Icarus Verilog root directory looks valid */
static void checkIvlDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path;
initDynString(&path);
assign(&path,gstr.pIVL);
assign(&path, gstr.pMINGW);
appendBackSlash(&path);
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
append(&path, "bin\\");
append(&path, gstr.pCCNAME);
append(&path, ".exe");
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\\\iverilog\n");
myExit(6);
fprintf(stderr, "error: %s\n", root);
fprintf(stderr, " does not appear to be the valid root directory of\n");
fprintf(stderr, " MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
fprintf(stderr, " point to the MinGW root directory. For a Windows command\n");
fprintf(stderr, " shell the option would be something like -mingw=c:\\mingw\n");
fprintf(stderr, " For a Cygwin shell the option would be something like\n");
fprintf(stderr, " -mingw=c:\\\\mingw\n");
myExit(5);
}
}
@@ -480,68 +460,98 @@ static void checkIvlDir(char *root)
#define IVL_REGKEY_MINGW "MingwDir"
static void setup_mingw_environment()
static void setup_mingw_environment(void)
{
char *pOldPATH = getenv("PATH"); /* get current path */
char buffer[1]; /* doesn't matter how big this is, as we don't use the result */
char *path;
if (*gstr.pMINGW) {
checkMingwDir(gstr.pMINGW);
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
} else if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
fprintf(stderr," a Windows command shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
myExit(5);
}
if (!*gstr.pOUT) SetRegistryKey(IVL_REGKEY_MINGW, gstr.pMINGW);
} else if (GetRegistryKey(IVL_REGKEY_MINGW, &gstr.pMINGW)) {
checkMingwDir(gstr.pMINGW);
} else if (SearchPath(NULL, gstr.pCCNAME, ".exe", sizeof(buffer), buffer, NULL)) {
return;
} else {
fprintf(stderr, "error: cannot locate the MinGW C compiler - either add its location\n");
fprintf(stderr, " to the PATH environment variable or use the -mingw option of\n");
fprintf(stderr, " iverilog-vpi.exe to point to the MinGW root directory. For\n");
fprintf(stderr, " a Windows command shell the option would be something like\n");
fprintf(stderr, " -mingw=c:\\mingw For a Cygwin shell the option would be\n");
fprintf(stderr, " something like -mingw=c:\\\\mingw\n");
myExit(5);
}
/* Create new path with MinGW in it */
assign(&gstr.pNewPath,"PATH=");
append(&gstr.pNewPath,gstr.pMINGW);
appendBackSlash(&gstr.pNewPath);
append(&gstr.pNewPath, "\\");
append(&gstr.pNewPath,"bin;");
append(&gstr.pNewPath,pOldPATH);
initDynString(&path);
assign(&path, "PATH=");
append(&path, gstr.pMINGW);
appendBackSlash(&path);
append(&path, "bin;");
append(&path, getenv("PATH"));
/* Place new path in environment */
_putenv(gstr.pNewPath);
_putenv(path);
deInitDynString(path);
}
/* see if we can find iverilog root */
/* find the iverilog root and initialise the compiler options */
#define IVL_REGKEY_IVL "InstallDir"
static void setup_ivl_environment()
static void setup_ivl_environment(void)
{
if (*gstr.pIVL) {
checkIvlDir(gstr.pIVL);
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
fprintf(stderr," For a Windows command shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
myExit(6);
}
char path[4096];
char *ptr;
/* Build up the CFLAGS option string */
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I\"");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX);
/* Extract the Icarus Verilog root directory from the path to the
command. The command path will look something like this:
C:\iverilog\bin\iverilog-vpi.exe
The corresponding root directory is
C:\iverilog
so we chop off the file name and the last directory. */
GetModuleFileName(NULL, path, sizeof(path));
ptr = strrchr(path, '\\');
if (!ptr) {
fprintf(stderr, "error: couldn't find start of program name in command path '%s'\n", path);
myExit(6);
}
*ptr = 0;
ptr = strrchr(path, '\\');
if (!ptr) {
fprintf(stderr, "error: couldn't find start of bin directory in command path '%s'\n", path);
myExit(6);
}
*ptr = 0;
assign(&gstr.pIVL, path);
/* Build up the CCFLAGS option string */
assign(&gstr.pCCFLAGS, IVERILOG_VPI_CFLAGS " -I\"");
append(&gstr.pCCFLAGS, gstr.pIVL);
appendBackSlash(&gstr.pCCFLAGS);
append(&gstr.pCCFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
/* Build up the CXFLAGS option string */
assign(&gstr.pCXFLAGS, IVERILOG_VPI_CXXFLAGS " -I\"");
append(&gstr.pCXFLAGS, gstr.pIVL);
appendBackSlash(&gstr.pCXFLAGS);
append(&gstr.pCXFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
/* Build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L\"");
append(&gstr.pLDLIBS,gstr.pIVL);
assign(&gstr.pLDLIBS, "-L\"");
append(&gstr.pLDLIBS, gstr.pIVL);
appendBackSlash(&gstr.pLDLIBS);
append(&gstr.pLDLIBS,"\\lib\" " IVERILOG_VPI_LDLIBS);
append(&gstr.pLDLIBS, "lib\" " IVERILOG_VPI_LDLIBS);
}
/* compile source modules */
static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
static void compile(char *pSource, char *pFlags, char **pObject, int *compile_errors, char *compiler)
{
char *ptr1 = pSource;
char *ptr2 = strchr(ptr1, ' ');
@@ -568,7 +578,7 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
append(&buf, " ");
append(&buf, gstr.pDEFS);
append(&buf, " ");
append(&buf, gstr.pCFLAGS);
append(&buf, pFlags);
append(&buf, " ");
append(&buf, gstr.pINCS);
append(&buf, " ");
@@ -593,27 +603,22 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
/* using the global strings, compile and link */
static void compile_and_link()
static void compile_and_link(void)
{
char *buf=0;
int iRet, compile_errors = 0;
/* To make the output match iverilog-vpi.sh do not print out the
* root directories */
// printf("MinGW root directory: %s.\n", gstr.pMINGW);
checkMingwDir(gstr.pMINGW);
// printf("Icarus Verilog root directory: %s.\n", gstr.pIVL);
checkIvlDir(gstr.pIVL);
/* compile the C source files (*.c) */
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
compile(gstr.pCCSRC, gstr.pCCFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
/* compile the C++ source files (*.cc, *.cpp) */
compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
compile(gstr.pCXSRC, gstr.pCXFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
if (compile_errors) {
fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
fprintf(stderr, "iverilog-vpi: %d file(s) failed to compile.\n",
compile_errors);
myExit(2);
}
@@ -644,7 +649,7 @@ int main(int argc, char *argv[])
{
init();
if (!parse(argc,argv)) usage();
if (!parse(argc, argv)) usage();
setup_mingw_environment();
setup_ivl_environment();
+9 -3
View File
@@ -1,4 +1,4 @@
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
.TH iverilog 1 "May 10th, 2015" "" "Version %M.%m.%n %E"
.SH NAME
iverilog - Icarus Verilog compiler
@@ -213,6 +213,12 @@ a reference to a key temporary file that passes information to the
compiler proper. To keep that file from being deleted at the end
of the process, provide a file name of your own in the environment
variable \fBIVERILOG_ICONFIG\fP.
If the selected target is \fIvvp\fP, the \fB\-v\fP switch is appended
to the shebang line in the compiler output file, so directly executing
the compiler output file will turn on verbose messages in \fIvvp\fP.
This extra verbosity can be avoided by using the \fIvvp\fP command to
indirectly execute the compiler output file.
.TP 8
.B -V
Print the version of the compiler, and exit.
@@ -514,14 +520,14 @@ Steve Williams ([email protected])
.SH SEE ALSO
vvp(1),
.BR "<http://www.icarus.com/eda/verilog/>"
.BR "<http://iverilog.icarus.com/>"
Tips on using, debugging, and developing the compiler can be found at
.BR "<http://iverilog.wikia.com/>"
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2014 Stephen Williams
Copyright \(co 2002\-2015 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+4 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
* Copyright (c) 2000-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -568,6 +568,9 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else {
fprintf(stderr, "Ignoring unknown warning class "
"%s\n", name);
}
}
+90 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
* Copyright (c) 1999-2015 Stephen Williams ([email protected])
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -657,10 +657,13 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
case 'E': /* === */
case 'N': /* !== */
if (lp->expr_type() == IVL_VT_REAL ||
rp->expr_type() == IVL_VT_REAL) {
lp->expr_type() == IVL_VT_STRING ||
rp->expr_type() == IVL_VT_REAL ||
rp->expr_type() == IVL_VT_STRING) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< " operator may not have REAL operands." << endl;
<< " operator may not have REAL or STRING operands."
<< endl;
des->errors += 1;
return 0;
}
@@ -785,8 +788,11 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
right_ = tmp;
}
NetEConst*rc = dynamic_cast<NetEConst*> (rp);
if (rc && (r_width < sizeof(long)*8))
r_val = rc->value().as_long();
// Adjust the expression width that can be converter depending
// on if the R-value is signed or not.
unsigned c_width = sizeof(long)*8;
if (! right_->has_sign()) c_width -= 1;
if (rc && (r_width <= c_width)) r_val = rc->value().as_long();
if (debug_elaborate && rc) {
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
@@ -1072,7 +1078,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
if (name=="$ivlh_to_unsigned") {
ivl_assert(*this, parms_.size() == 2);
// The Icarus Verilog specific $ivl_unsigned() system
// The Icarus Verilog specific $ivlh_to_unsigned() system
// task takes a second argument which is the output
// size. This can be an arbitrary constant function.
PExpr*pexpr = parms_[1];
@@ -1094,6 +1100,11 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
bool rc = eval_as_long(value, nexpr);
ivl_assert(*this, rc && value>=0);
// The argument type/width is self-determined and doesn't
// affect the result type/width.
width_mode_t arg_mode = SIZED;
parms_[0]->test_width(des, scope, arg_mode);
expr_width_ = value;
signed_flag_= false;
return expr_width_;
@@ -1443,7 +1454,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
PExpr*expr = parms_[0];
ivl_assert(*this, expr);
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
NetExpr*sub = expr->elaborate_expr(des, scope, expr->expr_width(), flags);
return cast_to_width_(sub, expr_wid);
}
@@ -2178,6 +2189,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return elaborate_base_(des, scope, dscope, expr_wid, flags);
}
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const
{
const netdarray_t*darray = dynamic_cast<const netdarray_t*>(type);
assert(darray);
return elaborate_expr(des, scope, darray->element_type()->packed_width(), flags);
}
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
unsigned expr_wid, unsigned flags) const
{
@@ -2259,6 +2278,9 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
func->set_line(*this);
if(res->darray_type())
return func;
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
tmp->cast_signed(signed_flag_);
@@ -2522,11 +2544,44 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
expr_width_ = t->packed_width();
}
signed_flag_= t->get_signed();
signed_flag_ = t->get_signed();
min_width_ = expr_width_;
return expr_width_;
}
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned) const
{
const netdarray_t*darray = NULL;
const netvector_t*vector = NULL;
// Casting array of vectors to dynamic array type
if((darray = dynamic_cast<const netdarray_t*>(type)) &&
(vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
PExpr::width_mode_t mode = PExpr::SIZED;
unsigned use_wid = base_->test_width(des, scope, mode);
NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
assert(vector->packed_width() > 0);
assert(base->expr_width() > 0);
// Find rounded up length that can fit the whole casted array of vectors
int len = base->expr_width() + vector->packed_width() - 1;
if(base->expr_width() > vector->packed_width()) {
len /= vector->packed_width();
} else {
len /= base->expr_width();
}
// Number of words in the created dynamic array
NetEConst*len_expr = new NetEConst(verinum(len));
return new NetENew(type, len_expr, base);
}
// Fallback
return elaborate_expr(des, scope, (unsigned) 0, 0);
}
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned) const
{
@@ -2822,6 +2877,25 @@ NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
list<long>&prefix_indices) const
{
unsigned dimensions = net->unpacked_dimensions() + net->packed_dimensions();
switch (net->data_type()) {
case IVL_VT_STRING:
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
dimensions += 1;
default:
break;
}
if (path_.back().index.size() > dimensions) {
cerr << get_fileline() << ": error: the number of indices ("
<< path_.back().index.size()
<< ") is greater than the number of dimensions ("
<< dimensions
<< ")." << endl;
des->errors += 1;
return false;
}
list<index_component_t> index;
index = path_.back().index;
ivl_assert(*this, index.size() >= net->unpacked_dimensions());
@@ -4578,7 +4652,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
{
list<long> prefix_indices;
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
ivl_assert(*this, rc);
if (!rc)
return 0;
long msv, lsv;
bool parts_defined_flag;
@@ -4718,7 +4793,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
{
list<long>prefix_indices;
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
ivl_assert(*this, rc);
if (!rc)
return 0;
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
@@ -4820,7 +4896,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
{
list<long>prefix_indices;
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
ivl_assert(*this, rc);
if (!rc)
return 0;
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
@@ -4908,7 +4985,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
{
list<long>prefix_indices;
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
ivl_assert(*this, rc);
if (!rc)
return 0;
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
+23 -7
View File
@@ -157,7 +157,7 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
return 0;
pform_name_t use_path = cur_path;
perm_string tmp_name = peek_tail_name(use_path);
name_component_t tail = use_path.back();
use_path.pop_back();
NetNet* reg = 0;
@@ -171,18 +171,32 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
return 0;
tmp = new NetAssign_(tmp);
tmp->set_property(tmp_name);
tmp->set_property(tail.name);
return tmp;
}
if (reg->struct_type()) {
if (reg->struct_type() && reg->struct_type()->packed()) {
NetAssign_*tmp = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, scope, tmp, tail);
return tmp;
}
#if 0
if (reg->struct_type() && reg->struct_type()->packed()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with struct " << use_path << endl;
<< "I don't know what to do with packed struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
#endif
if (reg->struct_type() && !reg->struct_type()->packed()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with unpacked struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
if (reg->class_type()) {
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
}
return 0;
@@ -316,7 +330,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (reg->struct_type() && !method_name.nil()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, use_scope, lv, method_name);
name_component_t tmp_name (method_name);
elaborate_lval_net_packed_member_(des, use_scope, lv, tmp_name);
return lv;
}
@@ -1117,8 +1132,9 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetAssign_*lv,
const perm_string&member_name) const
const name_component_t&member_comp) const
{
const perm_string&member_name = member_comp.name;
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
+9 -22
View File
@@ -201,16 +201,15 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
verinum one_value ((uint64_t)1, enum_width);
one_value.has_sign(enum_type->signed_flag);
// Find the maximum allowed enumeration value.
verinum min_value (0);
verinum max_value (0);
if (enum_type->signed_flag) {
min_value = -pow(verinum(2), verinum(enum_width-1));
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
} else {
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
}
min_value.has_sign(true);
max_value.has_sign(enum_type->signed_flag);
// Variable to indicate when a defined value wraps.
bool implicit_wrapped = false;
// Process the enumeration definition.
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
@@ -229,6 +228,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
continue;
}
cur_value = val_const->value();
// Clear the implicit wrapped flag if a parameter is given.
implicit_wrapped = false;
// A 2-state value can not have a constant with X/Z bits.
if (enum_type->base_type==IVL_VT_BOOL &&
@@ -335,24 +336,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
continue;
}
// Cast any undefined bits to zero so the comparisons below
// return just true (1) or false (0).
verinum two_state_value = cur_value;
two_state_value.cast_to_int2();
// The enumeration value must fit into the enumeration bits.
if (!cur_value.is_defined()) {
if (cur_value.len() > (unsigned long)use_enum->packed_width()) {
cerr << use_enum->get_fileline()
<< ": error: Enumeration name " << cur->name
<< " value=" << cur_value
<< " is too wide for enumeration base type." << endl;
des->errors += 1;
}
} else if ((two_state_value > max_value) ||
(cur_value.has_sign() && (two_state_value < min_value))) {
// Check to see if an implicitly wrapped value is used.
if (implicit_wrapped) {
cerr << use_enum->get_fileline()
<< ": error: Enumeration name " << cur->name
<< " has an inferred value that overflowed." << endl;
@@ -385,6 +370,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
// In case the next name has an implicit value,
// increment the current value by one.
if (cur_value.is_defined()) {
if (cur_value == max_value) implicit_wrapped = true;
cur_value = cur_value + one_value;
}
}
@@ -1756,7 +1742,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
bound_type_? true : false,
mod->program_block);
mod->program_block,
mod->is_interface);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
+19 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -909,6 +909,11 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
*/
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
{
// This sets the vector or array dimension size that will
// cause a warning. For now, these warnings are permanently
// enabled.
const long warn_dimension_size = 1 << 30;
NetNet::Type wtype = type_;
bool is_implicit_scalar = false;
if (wtype == NetNet::IMPLICIT) {
@@ -1042,7 +1047,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
packed_dimensions = nlist;
wid = netrange_width(packed_dimensions);
if (wid > warn_dimension_size) {
cerr << get_fileline() << ": warning: Vector size "
"is greater than " << warn_dimension_size
<< "." << endl;
}
}
unsigned nattrib = 0;
@@ -1063,6 +1072,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// put all the packed dimensions there.
if (use_lidx==0 && use_ridx==0) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
vec->set_signed(get_signed());
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netdarray_t(vec);
@@ -1073,6 +1083,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// declaration, which is the dimensions [null:<nil>].
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
vec->set_signed(get_signed());
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netqueue_t(vec);
@@ -1114,6 +1125,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
index_l = lval.as_long();
index_r = rval.as_long();
}
if (abs(index_r - index_l) > warn_dimension_size) {
cerr << get_fileline() << ": warning: Array dimension "
"is greater than " << warn_dimension_size
<< "." << endl;
}
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
}
@@ -1194,7 +1210,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
cerr << " in scope " << scope_path(scope) << endl;
}
sig = new NetNet(scope, name_, wtype, use_type);
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
+46 -33
View File
@@ -32,6 +32,44 @@
using namespace std;
/*
* Some types have a list of ranges that need to be elaborated. This
* function elaborates the ranges referenced by "dims" into the vector
* "ranges".
*/
static void elaborate_array_ranges(Design*des, NetScope*scope,
vector<netrange_t>&ranges,
const list<pform_range_t>*dims)
{
if (dims == 0)
return;
for (list<pform_range_t>::const_iterator cur = dims->begin()
; cur != dims->end() ; ++ cur) {
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
/* If elaboration failed for either expression, we
should have already reported the error, so just
skip the following evaluation to recover. */
long mnum = 0, lnum = 0;
if ( me && ! eval_as_long(mnum, me) ) {
assert(0);
des->errors += 1;
}
if ( le && ! eval_as_long(lnum, le) ) {
assert(0);
des->errors += 1;
}
ranges.push_back(netrange_t(mnum, lnum));
}
}
/*
* Elaborations of types may vary depending on the scope that it is
* done in, so keep a per-scope cache of the results.
@@ -120,33 +158,7 @@ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
vector<netrange_t> packed;
if (pdims.get()) {
for (list<pform_range_t>::const_iterator cur = pdims->begin()
; cur != pdims->end() ; ++ cur) {
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
/* If elaboration failed for either expression, we
should have already reported the error, so just
skip the following evaluation to recover. */
long mnum = 0, lnum = 0;
if ( me && ! eval_as_long(mnum, me) ) {
assert(0);
des->errors += 1;
}
if ( le && ! eval_as_long(lnum, le) ) {
assert(0);
des->errors += 1;
}
packed.push_back(netrange_t(mnum, lnum));
}
}
elaborate_array_ranges(des, scope, packed, pdims.get());
netvector_t*tmp = new netvector_t(packed, base_type);
tmp->set_signed(signed_flag);
@@ -171,13 +183,14 @@ ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
return &netstring_t::type_string;
}
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*) const
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
cerr << get_fileline() << " : sorry: "
<< "Packed arrays are not currently supported in this context."
<< endl;
des->errors += 1;
return 0;
vector<netrange_t>packed;
elaborate_array_ranges(des, scope, packed, dims.get());
ivl_type_t etype = base_type->elaborate_type(des, scope);
return new netparray_t(packed, etype);
}
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
+34 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -2282,11 +2282,18 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
PExpr::width_mode_t mode = PExpr::SIZED;
rval_->test_width(des, scope, mode);
// Create a L-value that matches the function return type.
NetNet*tmp;
netvector_t*tmp_vec = new netvector_t(rval_->expr_type(),
rval_->expr_width()-1, 0,
rval_->has_sign());
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::REG, tmp_vec);
if(rval_->expr_type() == IVL_VT_DARRAY) {
netdarray_t*darray = new netdarray_t(tmp_vec);
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, darray);
} else {
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, tmp_vec);
}
tmp->set_file(rval_->get_file());
tmp->set_lineno(rval_->get_lineno());
NetAssign_*lv = new NetAssign_(tmp);
@@ -4882,7 +4889,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
sig->data_type(), sig->vector_width(),
expr1_);
if (debug_elaborate) {
if (debug_elaborate && initial_expr) {
cerr << get_fileline() << ": debug: FOR initial assign: "
<< sig->name() << " = " << *initial_expr << endl;
}
@@ -4893,34 +4900,29 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
reported so it's OK that the netlist is bogus. */
NetProc*sub = statement_->elaborate(des, scope);
/* Now elaborate the for_step statement. I really should do
some error checking here to make sure the step statement
really does step the variable. */
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate for_step statement "
<< sig->name() << " = " << *initial_expr << endl;
}
NetProc*step = step_->elaborate(des, scope);
/* Elaborate the condition expression. Try to evaluate it too,
in case it is a constant. This is an interesting case
worthy of a warning. */
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
if (ce == 0) {
delete sub;
delete step;
return 0;
}
if (dynamic_cast<NetEConst*>(ce)) {
cerr << get_fileline() << ": warning: condition expression "
"of for-loop is constant." << endl;
}
/* Error recovery - if we failed to elaborate any of the loop
expressions, give up now. */
if (initial_expr == 0 || ce == 0 || step == 0 || sub == 0) {
delete initial_expr;
delete ce;
delete step;
delete sub;
return 0;
}
/* All done, build up the loop. */
NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step);
@@ -5013,6 +5015,10 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
des->errors += 1;
return 0;
}
// If the expression is real, convert to an integer. 64 bits
// should be more enough for any real use case.
if (expr->expr_type() == IVL_VT_REAL)
expr = cast_to_int4(expr, 64);
NetProc*stat = statement_->elaborate(des, scope);
if (stat == 0) return 0;
@@ -5193,9 +5199,14 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
*/
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
{
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
tmp->set_line(*this);
NetWhile*loop = new NetWhile(tmp, statement_->elaborate(des, scope));
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
NetProc*sub = statement_->elaborate(des, scope);
if (ce == 0 || sub == 0) {
delete ce;
delete sub;
return 0;
}
NetWhile*loop = new NetWhile(ce, sub);
loop->set_line(*this);
return loop;
}
@@ -6086,7 +6097,8 @@ Design* elaborate(list<perm_string>roots)
// Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design.
NetScope*scope = des->make_root_scope(*root, rmod->program_block);
NetScope*scope = des->make_root_scope(*root, rmod->program_block,
rmod->is_interface);
// Collect some basic properties of this scope from the
// Module definition.
+20 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -1138,18 +1138,29 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
if (sub->vector_width() == expr_width())
return sub;
// The vector_width is not exactly right, so the source is
// probably asking for padding. Create nodes to do sign
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
net_vec->set_signed(has_sign());
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_vec);
net->set_line(*this);
net->local_flag(true);
if (has_sign()) {
// It may still happen that the expression is wider than the selection,
// and there was no part select created earlier (size casting).
if(expr_width() < sub->vector_width()) {
NetPartSelect*sel = new NetPartSelect(sub, 0, expr_width(),
NetPartSelect::VP, has_sign());
sel->set_line(*this);
des->add_node(sel);
connect(net->pin(0), sel->pin(0));
// The vector_width is not exactly right, so the source is
// probably asking for padding. Create nodes to do sign
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
} else if (has_sign()) {
NetSignExtend*pad = new NetSignExtend(scope,
scope->local_symbol(),
expr_width());
@@ -1166,7 +1177,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
cat->set_line(*this);
des->add_node(cat);
assert(expr_width() > sub->vector_width());
unsigned pad_width = expr_width() - sub->vector_width();
verinum pad((uint64_t)0, pad_width);
NetConst*con = new NetConst(scope, scope->local_symbol(),
@@ -1278,6 +1288,8 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
net_->vector_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
tmp->local_flag(true);
verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width());
NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val);
tmp_const->set_line(*this);
+34 -47
View File
@@ -1,10 +1,10 @@
.TH iverilog-vpi 1 "April 17th, 2009" "" "Version %M.%m.%n %E"
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%m.%n %E"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
.SH SYNOPSIS
.B iverilog-vpi
[\-\-name=\fIname\fP]
[options]
\fIsourcefile\fP...
.SH DESCRIPTION
@@ -15,9 +15,9 @@ list of C or C++ source files, and generates as output a linked VPI
module. See the \fBvvp\fP(1) man page for a description of how the
linked module is loaded by a simulation.
The output is named after the first source file. For example, if the
first source file is named \fIfoo.c\fP, the output becomes
\fIfoo.vpi\fP.
By default the output is named after the first source file. For
example, if the first source file is named \fIfoo.c\fP, the output
becomes \fIfoo.vpi\fP.
.SH OPTIONS
\fIiverilog\-vpi\fP accepts the following options:
@@ -28,8 +28,8 @@ VPI modules to further reference external libraries.
.TP 8
.B -I\fIdirectory\fP
Add \fIdirectory\fP to the list of directories that will be search for
header files.
Add \fIdirectory\fP to the list of directories that will be searched
for header files.
.TP 8
.B -D\fIdefine\fP
@@ -41,46 +41,38 @@ Normally, the output VPI module will be named after the first source
file passed to the command. This flag sets the name (without the .vpi
suffix) of the output vpi module.
.TP 8
.B --install-dir
This flag causes the program to print the install directory for VPI
modules, then exit. It is a convenience for makefiles or automated
plug-in installers.
.TP 8
.B --cflags, --ldflags and --ldlibs
These flags provide compile time information.
.SH "PC-ONLY OPTIONS"
The PC port of \fIiverilog\-vpi\fP includes two special flags needed to
support the more intractable development environment. These flags help
the program locate parts that it needs.
When built as a native Windows program (using the MinGW toolchain),
by default \fIiverilog\-vpi\fP will attempt to locate the MinGW tools
needed to compile a VPI module on the system path (as set by the PATH
environment variable). As an alternative, the user may specify the
location of the MinGW tools via the following option.
.TP 8
.B -mingw=\fIpath\fP
Tell the program the root of the Mingw compiler tool suite. The
Tell the program the root of the MinGW compiler tool suite. The
\fBvvp\fP runtime is compiled with this compiler, and this is the
compiler that \fIiverilog\-vpi\fP expects to use to compile your source
code. This is normally not needed, and if you do use it, it is only
needed once. The compiler will save the \fIpath\fP in the registry for
use later.
compiler that \fIiverilog\-vpi\fP expects to use to compile your
source code. If this option accompanies a list of files, it will
apply to the current build only. If this option is provided on its
own, \fIiverilog\-vpi\fP will save the \fIpath\fP in the registry
and use that path in preference to the system path for subsequent
operations, avoiding the need to specify it on the command line
every time.
.SH "INFORMATIONAL OPTIONS"
\fIiverilog\-vpi\fP includes additional flags to let Makefile gurus
peek at the configuration of the \fIiverilog\fP installation. This way,
Makefiles can be written that handle complex VPI builds natively, and
without hard-coding values that depend on the system and installation.
If used at all, these options must be used one at a time, and without
any other options or directives.
.TP 8
.B -ivl=\fIpath\fP
Set for the use during compilation the root if the Icarus Verilog
install. This is the place where you installed Icarus Verilog when you
ran the installer. This flag is also only needed once, and the path is
stored in the registry for future use.
.SH "UNIX-ONLY OPTIONS"
The UNIX version of \fIiverilog\-vpi\fP includes additional flags to
let Makefile gurus peek at the configuration of the \fIiverilog\fP
installation. This way, Makefiles can be written that handle complex VPI
builds natively, and without hard-coding values that depend on the
system and installation. If used at all, these options must be
used one at a time, and without any other options or directives.
.B --install-dir
Print the install directory for VPI modules.
.TP 8
.B --cflags
@@ -95,11 +87,6 @@ Print the linker flags (LDFLAGS) needed to link a VPI module.
.B --ldlibs
Print the libraries (LDLIBS) needed to link a VPI module.
.TP 8
.B -m32
On 64bit systems that support it (and support vvp32) this flag
requests a 32bit vpi binary instead of the default 64bit binary.
.P
Example GNU makefile that takes advantage of these flags:
.IP "" 4
@@ -123,12 +110,12 @@ Steve Williams ([email protected])
.SH SEE ALSO
iverilog(1), vvp(1),
.BR "<http://www.icarus.com/eda/verilog/>",
.BR "<http://www.mingw.org>",
.BR "<http://iverilog.icarus.com/>",
.BR "<http://mingw-w64.yaxm.org/>",
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2009 Stephen Williams
Copyright \(co 2002\-2015 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+140 -305
View File
@@ -136,21 +136,11 @@ static void ifdef_leave(void)
* we assume that the non-file part is from this file. */
if (istack->path != NULL && cur->path != NULL &&
strcmp(istack->path,cur->path) != 0) {
fprintf
(
stderr,
"%s:%u: warning: This `endif matches an ifdef in another file.\n",
istack->path,
istack->lineno+1
);
fprintf(stderr, "%s:%u: warning: This `endif matches an ifdef "
"in another file.\n", istack->path, istack->lineno+1);
fprintf
(
stderr,
"%s:%u: This is the odd matched `ifdef.\n",
cur->path,
cur->lineno+1
);
fprintf(stderr, "%s:%u: This is the odd matched `ifdef.\n",
cur->path, cur->lineno+1);
}
free(cur->path);
@@ -243,12 +233,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<PCOMENT>`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
fprintf(stderr, "error: macro names cannot be directive keywords "
"('%s'); replaced with nothing.\n", yytext);
}
<PCOMENT>`[a-zA-Z][a-zA-Z0-9_$]* {
@@ -285,12 +271,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<PPINCLUDE>`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
fprintf(stderr, "error: macro names cannot be directive keywords "
"('%s'); replaced with nothing.\n", yytext);
}
<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* {
@@ -342,11 +324,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
emit_pathline(istack);
error_count += 1;
BEGIN(ERROR_LINE);
fprintf
(
stderr,
"error: malformed `define directive: macro names cannot be directive keywords\n"
);
fprintf(stderr, "error: malformed `define directive: macro names "
"cannot be directive keywords\n");
}
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
@@ -483,73 +462,45 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
`ifdef {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
}
`ifndef {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
}
`elsif {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1);
}
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
}
`else {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `else without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
}
`endif {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `endif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
}
`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
fprintf(stderr, "error: macro names cannot be directive keywords "
"('%s'); replaced with nothing.\n", yytext);
}
/* This pattern notices macros and arranges for them to be replaced. */
@@ -722,17 +673,14 @@ static struct define_t* magic_table = &def_LINE;
*/
static struct define_t* def_lookup_internal(const char*name, struct define_t*cur)
{
if (cur == 0)
return 0;
if (cur == 0) return 0;
assert(cur->up == 0);
while (cur)
{
while (cur) {
int cmp = strcmp(name, cur->name);
if (cmp == 0)
return cur;
if (cmp == 0) return cur;
cur = (cmp < 0) ? cur->left : cur->right;
}
@@ -743,11 +691,9 @@ static struct define_t* def_lookup_internal(const char*name, struct define_t*cur
static struct define_t* def_lookup(const char*name)
{
// first, try a magic macro
if(name[0] == '_' && name[1] == '_' && name[2] != '\0')
{
if(name[0] == '_' && name[1] == '_' && name[2] != '\0') {
struct define_t* result = def_lookup_internal(name, magic_table);
if(result)
{
if(result) {
return result;
}
}
@@ -806,8 +752,7 @@ static /* inline */ char* def_argv(int arg)
static void check_for_max_args(void)
{
if (def_argc == MAX_DEF_ARG)
{
if (def_argc == MAX_DEF_ARG) {
emit_pathline(istack);
fprintf(stderr, "error: too many macro arguments - aborting\n");
exit(1);
@@ -839,14 +784,12 @@ static void def_add_arg(void)
check_for_max_args();
/* Remove trailing white space and, if necessary, opening brace. */
while (isspace((int)yytext[length - 1]))
length--;
while (isspace((int)yytext[length - 1])) length--;
/* This can happen because we are also processing "argv[0]", the
macro name, as a pseudo-argument. The lexor will match that
as name(, so chop off the ( here. */
if (yytext[length - 1] == '(')
length--;
if (yytext[length - 1] == '(') length--;
yytext[length] = 0;
@@ -921,41 +864,32 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
}
}
if (def_table == 0)
if (def_table == 0) {
def_table = def;
else
{
} else {
struct define_t* cur = def_table;
while (1)
{
while (1) {
int cmp = strcmp(def->name, cur->name);
if (cmp == 0)
{
if (cmp == 0) {
free(cur->value);
cur->value = def->value;
free(def->name);
free(def);
break;
}
else if (cmp < 0)
{
if (cur->left != 0)
} else if (cmp < 0) {
if (cur->left != 0) {
cur = cur->left;
else
{
} else {
cur->left = def;
def->up = cur;
break;
}
}
else
{
if (cur->right != 0)
} else {
if (cur->right != 0) {
cur = cur->right;
else
{
} else {
cur->right = def;
def->up = cur;
break;
@@ -973,8 +907,7 @@ static void free_macro(struct define_t* def)
free_macro(def->right);
free(def->name);
free(def->value);
for (idx = 0 ; idx < def->argc ; idx += 1)
free(def->defaults[idx]);
for (idx = 0 ; idx < def->argc ; idx += 1) free(def->defaults[idx]);
free(def->defaults);
free(def);
}
@@ -1069,25 +1002,19 @@ static void do_define(void)
*/
cp = strchr(yytext, '/');
while (cp && *cp)
{
while (cp && *cp) {
if (cp[1] == '/') {
*cp = 0;
break;
}
if (cp[1] == '*')
{
if (cp[1] == '*') {
tail = strstr(cp+2, "*/");
if (tail == 0)
{
if (tail == 0) {
*cp = 0;
fprintf
(
stderr,
"%s:%u: Unterminated comment in define\n",
istack->path, istack->lineno+1
fprintf(stderr, "%s:%u: Unterminated comment in define\n",
istack->path, istack->lineno+1
);
break;
}
@@ -1101,10 +1028,8 @@ static void do_define(void)
/* Trim trailing white space. */
cp = yytext + strlen(yytext);
while (cp > yytext)
{
if (!isspace((int)cp[-1]))
break;
while (cp > yytext) {
if (!isspace((int)cp[-1])) break;
cp -= 1;
*cp = 0;
@@ -1114,8 +1039,7 @@ static void do_define(void)
* and the white space that precedes it, then replace all that
* with a single newline.
*/
if ((cp > yytext) && (cp[-1] == '\\'))
{
if ((cp > yytext) && (cp[-1] == '\\')) {
cp -= 1;
cp[0] = 0;
@@ -1143,18 +1067,13 @@ static void do_define(void)
/* If the text for a macro with arguments contains occurrences
* of ARG_MARK, issue an error message and suppress the macro.
*/
if ((def_argc > 1) && strchr(head, ARG_MARK))
{
if ((def_argc > 1) && strchr(head, ARG_MARK)) {
emit_pathline(istack);
error_count += 1;
def_argc = 0;
fprintf
(
stderr,
"error: implementation restriction - macro text may not contain a %s character\n",
_STR2(ARG_MARK)
);
fprintf(stderr, "error: implementation restriction - "
"macro text may not contain a %s character\n", _STR2(ARG_MARK));
}
/* Look for formal argument names in the definition, and replace
@@ -1162,18 +1081,15 @@ static void do_define(void)
* the formal argument index number.
*/
added_cnt = 0;
for (arg = 1; arg < def_argc; arg++)
{
for (arg = 1; arg < def_argc; arg++) {
int argl = def_argl[arg];
cp = find_arg(head, head, def_argv(arg));
while (cp && *cp)
{
while (cp && *cp) {
added_cnt += 2 - argl;
if (added_cnt > 0)
{
if (added_cnt > 0) {
char* base = define_text;
define_cnt += added_cnt;
@@ -1216,13 +1132,11 @@ static void def_finish(void)
{
define_continue_flag = 0;
if (def_argc <= 0)
return;
if (def_argc <= 0) return;
if (!define_text)
if (!define_text) {
define_macro(def_argv(0), "", 0, def_argc);
else
{
} else {
define_macro(def_argv(0), define_text, 0, def_argc);
free(define_text);
@@ -1251,24 +1165,18 @@ static void def_undefine(void)
if (cur == 0) return;
if (cur->magic) return;
if (cur->up == 0)
{
if ((cur->left == 0) && (cur->right == 0))
if (cur->up == 0) {
if ((cur->left == 0) && (cur->right == 0)) {
def_table = 0;
else if (cur->left == 0)
{
} else if (cur->left == 0) {
def_table = cur->right;
if (cur->right)
cur->right->up = 0;
}
else if (cur->right == 0)
{
} else if (cur->right == 0) {
assert(cur->left);
def_table = cur->left;
def_table->up = 0;
}
else
{
} else {
tail = cur->left;
while (tail->right)
tail = tail->right;
@@ -1279,50 +1187,40 @@ static void def_undefine(void)
def_table = cur->left;
def_table->up = 0;
}
}
else if (cur->left == 0)
{
if (cur->up->left == cur)
} else if (cur->left == 0) {
if (cur->up->left == cur) {
cur->up->left = cur->right;
else
{
} else {
assert(cur->up->right == cur);
cur->up->right = cur->right;
}
if (cur->right)
cur->right->up = cur->up;
if (cur->right) cur->right->up = cur->up;
}
else if (cur->right == 0)
{
else if (cur->right == 0) {
assert(cur->left);
if (cur->up->left == cur)
if (cur->up->left == cur) {
cur->up->left = cur->left;
else
{
} else {
assert(cur->up->right == cur);
cur->up->right = cur->left;
}
cur->left->up = cur->up;
}
else
{
} else {
tail = cur->left;
assert(cur->left && cur->right);
while (tail->right)
tail = tail->right;
while (tail->right) tail = tail->right;
tail->right = cur->right;
tail->right->up = tail;
if (cur->up->left == cur)
if (cur->up->left == cur) {
cur->up->left = cur->left;
else
{
} else {
assert(cur->up->right == cur);
cur->up->right = cur->left;
}
@@ -1332,8 +1230,7 @@ static void def_undefine(void)
free(cur->name);
free(cur->value);
for (idx = 0 ; idx < cur->argc ; idx += 1)
free(cur->defaults[idx]);
for (idx = 0 ; idx < cur->argc ; idx += 1) free(cur->defaults[idx]);
free(cur->defaults);
free(cur);
}
@@ -1350,10 +1247,9 @@ static int macro_needs_args(const char*text)
{
cur_macro = def_lookup(text);
if (cur_macro)
if (cur_macro) {
return (cur_macro->argc > 1);
else
{
} else {
emit_pathline(istack);
fprintf(stderr, "warning: macro %s undefined (and assumed null) at this point.\n", text);
return 0;
@@ -1386,8 +1282,7 @@ static void macro_add_to_arg(int is_white_space)
check_for_max_args();
/* Replace any run of white space with a single space */
if (is_white_space)
{
if (is_white_space) {
yytext[0] = ' ';
yytext[1] = 0;
length = 1;
@@ -1435,8 +1330,7 @@ static int exp_buf_free = 0;
static void exp_buf_grow_to_fit(int length)
{
while (length >= exp_buf_free)
{
while (length >= exp_buf_free) {
exp_buf_size += EXP_BUF_CHUNK;
exp_buf_free += EXP_BUF_CHUNK;
exp_buf = realloc(exp_buf, exp_buf_size);
@@ -1451,8 +1345,7 @@ static void expand_using_args(void)
int arg;
int length;
if (def_argc != cur_macro->argc)
{
if (def_argc != cur_macro->argc) {
emit_pathline(istack);
fprintf(stderr, "error: wrong number of arguments for `%s\n", cur_macro->name);
return;
@@ -1461,12 +1354,10 @@ static void expand_using_args(void)
head = cur_macro->value;
tail = head;
while (*tail)
{
if (*tail != ARG_MARK)
while (*tail) {
if (*tail != ARG_MARK) {
tail++;
else
{
} else {
arg = tail[1]; assert(arg < def_argc);
char*use_argv;
@@ -1508,17 +1399,14 @@ static void expand_using_args(void)
*/
static void do_expand(int use_args)
{
if (cur_macro)
{
if (cur_macro) {
struct include_stack_t*isp;
int head = 0;
int tail = 0;
const char *cp;
unsigned escapes = 0;
char *str_buf = 0;
if (cur_macro->keyword)
{
if (cur_macro->keyword) {
fprintf(yyout, "%s", cur_macro->value);
if (do_expand_stringify_flag) {
do_expand_stringify_flag = 0;
@@ -1527,33 +1415,27 @@ static void do_expand(int use_args)
return;
}
if (use_args)
{
if (use_args) {
int tail = 0;
head = exp_buf_size - exp_buf_free;
expand_using_args();
tail = exp_buf_size - exp_buf_free;
exp_buf_free += tail - head;
if (tail == head)
return;
if (tail == head) return;
}
isp = (struct include_stack_t*) calloc(1, sizeof(struct include_stack_t));
isp->stringify_flag = do_expand_stringify_flag;
do_expand_stringify_flag = 0;
if (use_args)
{
if (use_args) {
isp->str = &exp_buf[head];
}
else if(cur_macro->magic)
{
} else if(cur_macro->magic) {
// cast const char * to char * to suppress warning, since we won't
// be modifying isp->str in place.
isp->str = (char*)do_magic(cur_macro->name);
}
else
{
} else {
isp->str = cur_macro->value;
}
@@ -1588,8 +1470,7 @@ static void do_expand(int use_args)
exp_buf_free -= idx;
isp->str = str_buf;
} else
isp->str = strdup(isp->str);
} else isp->str = strdup(isp->str);
isp->orig_str = isp->str;
isp->next = istack;
@@ -1612,21 +1493,16 @@ static const char* do_magic(const char*name)
{
size_t desired_cnt = 0;
if(!magic_text)
{
magic_text = malloc(24); // unimportant initial size
}
if(!magic_text) magic_text = malloc(24); // unimportant initial size
if(!strcmp(name, "__LINE__"))
{
if(!strcmp(name, "__LINE__")) {
// istack->lineno is unsigned. the largest it could be is 64 bits.
// 2^64 is between 10^19 and 10^20. So the decimal representation of
// lineno can't possibly be longer than 23 bytes. I'm generous but
// bytes are cheap and this is nobody's critical path.
desired_cnt = 24;
if(magic_cnt < desired_cnt)
{
if(magic_cnt < desired_cnt) {
magic_text = realloc(magic_text, desired_cnt);
assert(magic_text);
magic_cnt = desired_cnt;
@@ -1637,17 +1513,12 @@ static const char* do_magic(const char*name)
assert(actual_len >= 0);
assert((unsigned) actual_len < desired_cnt);
return magic_text;
}
else if(!strcmp(name, "__FILE__"))
{
} else if(!strcmp(name, "__FILE__")) {
const char *path = get_path(istack);
if(path)
{
if(path) {
desired_cnt = strlen(path)+2+1; // two quotes and a null
if(magic_cnt < desired_cnt)
{
if(magic_cnt < desired_cnt) {
magic_text = realloc(magic_text, desired_cnt);
assert(magic_text);
magic_cnt = desired_cnt;
@@ -1689,19 +1560,17 @@ static const char* do_magic(const char*name)
static void output_init(void)
{
if (line_direct_flag)
if (line_direct_flag) {
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
}
}
static void include_filename(void)
{
if(standby) {
emit_pathline(istack);
fprintf
(
stderr,
"error: malformed `include directive. Extra junk on line?\n"
);
fprintf(stderr,
"error: malformed `include directive. Extra junk on line?\n");
exit(1);
}
@@ -1728,8 +1597,7 @@ static void do_include(void)
/* Add the current path to the start of the include_dir list. */
isp = istack;
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1775,8 +1643,9 @@ code_that_switches_buffers:
}
}
if (line_direct_flag)
if (line_direct_flag) {
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
}
standby->next = istack;
standby->stringify_flag = 0;
@@ -1796,8 +1665,7 @@ code_that_switches_buffers:
*/
static unsigned get_line(struct include_stack_t* isp)
{
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1811,8 +1679,7 @@ static unsigned get_line(struct include_stack_t* isp)
*/
static const char* get_path(struct include_stack_t* isp)
{
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1827,8 +1694,7 @@ static const char* get_path(struct include_stack_t* isp)
*/
static void emit_pathline(struct include_stack_t* isp)
{
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1837,17 +1703,12 @@ static void emit_pathline(struct include_stack_t* isp)
static void lexor_done(void)
{
while (ifdef_stack)
{
while (ifdef_stack) {
struct ifdef_stack_t*cur = ifdef_stack;
ifdef_stack = cur->next;
fprintf
(
stderr,
"%s:%u: error: This `ifdef lacks an `endif.\n",
cur->path, cur->lineno+1
);
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
cur->path, cur->lineno+1);
free(cur->path);
free(cur);
@@ -1904,8 +1765,7 @@ static void open_input_file(struct include_stack_t*isp)
char*cmd = malloc(cmdlen);
snprintf(cmd, cmdlen, "%s -w\"%s\"%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
if (verbose_flag)
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
if (verbose_flag) fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
isp->file = popen(cmd, "r");
isp->file_close = pclose;
@@ -1943,29 +1803,23 @@ static int load_next_input(void)
isp->comment = NULL;
}
if (isp->file)
{
if (isp->file) {
free(isp->path);
assert(isp->file_close);
isp->file_close(isp->file);
}
else
{
} else {
/* If I am printing line directives and I just finished
* macro substitution, I should terminate the line and
* arrange for a new directive to be printed.
*/
if (line_direct_flag && istack && istack->path && isp->lineno)
if (line_direct_flag && istack && istack->path && isp->lineno) {
fprintf(yyout, "\n");
else
line_mask_flag = 1;
} else line_mask_flag = 1;
free(isp->orig_str);
}
if (isp->stringify_flag) {
fputc('"', yyout);
}
if (isp->stringify_flag) fputc('"', yyout);
free(isp);
@@ -1974,10 +1828,8 @@ static int load_next_input(void)
* queue. If none are there, give up. Otherwise, open the file
* and continue parsing.
*/
if (istack == 0)
{
if (file_queue == 0)
{
if (istack == 0) {
if (file_queue == 0) {
lexor_done();
return 0;
}
@@ -1989,15 +1841,15 @@ static int load_next_input(void)
istack->lineno = 0;
open_input_file(istack);
if (istack->file == 0)
{
if (istack->file == 0) {
perror(istack->path);
error_count += 1;
return 0;
}
if (line_direct_flag)
if (line_direct_flag) {
fprintf(yyout, "\n`line 1 \"%s\" 0\n", istack->path);
}
if (depend_file) {
if (dep_mode == 'p') {
@@ -2022,8 +1874,9 @@ static int load_next_input(void)
*/
yy_switch_to_buffer(istack->yybs);
if (line_direct_flag && istack->path && !line_mask_flag)
if (line_direct_flag && istack->path && !line_mask_flag) {
fprintf(yyout, "\n`line %u \"%s\" 2\n", istack->lineno+1, istack->path);
}
return 1;
}
@@ -2045,23 +1898,16 @@ static int load_next_input(void)
static void do_dump_precompiled_defines(FILE* out, struct define_t* table)
{
if (!table->keyword)
#ifdef __MINGW32__ /* MinGW does not know about z. */
fprintf(out, "%s:%d:%d:%s\n", table->name, table->argc, strlen(table->value), table->value);
#else
fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value);
#endif
if (table->left)
do_dump_precompiled_defines(out, table->left);
if (table->left) do_dump_precompiled_defines(out, table->left);
if (table->right)
do_dump_precompiled_defines(out, table->right);
if (table->right) do_dump_precompiled_defines(out, table->right);
}
void dump_precompiled_defines(FILE* out)
{
if (def_table)
do_dump_precompiled_defines(out, def_table);
if (def_table) do_dump_precompiled_defines(out, def_table);
}
void load_precompiled_defines(FILE* src)
@@ -2070,8 +1916,7 @@ void load_precompiled_defines(FILE* src)
size_t buf_len = 4096;
int ch;
while ((ch = fgetc(src)) != EOF)
{
while ((ch = fgetc(src)) != EOF) {
char* cp = buf;
char* name = 0;
@@ -2086,26 +1931,21 @@ void load_precompiled_defines(FILE* src)
assert( (size_t)(cp-buf) < buf_len );
}
if (ch != ':')
return;
if (ch != ':') return;
/* Terminate the name string. */
*cp++ = 0;
assert( (size_t)(cp-buf) < buf_len );
/* Read the argc number. (this doesn't need buffer space) */
while (isdigit(ch = fgetc(src)))
argc = 10*argc + ch-'0';
while (isdigit(ch = fgetc(src))) argc = 10*argc + ch-'0';
if (ch != ':')
return;
if (ch != ':') return;
/* Read the value len (this doesn't need buffer space) */
while (isdigit(ch = fgetc(src)))
len = 10*len + ch-'0';
while (isdigit(ch = fgetc(src))) len = 10*len + ch-'0';
if (ch != ':')
return;
if (ch != ':') return;
/* Save the name, and start the buffer over. */
name = strdup(buf);
@@ -2119,8 +1959,7 @@ void load_precompiled_defines(FILE* src)
cp = buf;
while (len > 0)
{
while (len > 0) {
ch = fgetc(src);
if (ch == EOF) {
free(name);
@@ -2165,8 +2004,7 @@ void reset_lexor(FILE* out, char* paths[])
isp->stringify_flag = 0;
isp->comment = NULL;
if (isp->file == 0)
{
if (isp->file == 0) {
perror(paths[0]);
exit(1);
}
@@ -2189,8 +2027,7 @@ void reset_lexor(FILE* out, char* paths[])
/* Now build up a queue of all the remaining file names, so
* that load_next_input() can pull them when needed.
*/
for (idx = 1 ; paths[idx] ; idx += 1)
{
for (idx = 1 ; paths[idx] ; idx += 1) {
isp = malloc(sizeof(struct include_stack_t));
isp->path = strdup(paths[idx]);
isp->file = 0;
@@ -2200,10 +2037,8 @@ void reset_lexor(FILE* out, char* paths[])
isp->stringify_flag = 0;
isp->comment = NULL;
if (tail)
tail->next = isp;
else
file_queue = isp;
if (tail) tail->next = isp;
else file_queue = isp;
tail = isp;
}
+1 -1
View File
@@ -36,7 +36,7 @@ double acc_fetch_paramval(handle object)
fprintf(pli_trace, "acc_fetch_paramval(%s) --> \"%s\"\n",
vpi_get_str(vpiName, object), val.value.str);
}
return (double) (long)val.value.str;
return (double) (intptr_t)val.value.str;
default:
vpi_printf("XXXX: parameter %s has type %d\n",
+20 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -45,6 +45,14 @@ bool Nexus::drivers_constant() const
return false;
}
/* If we are connected to a tran, there may be a driver
on the other side of the tran. We could try checking
for this, but for now, be pessimistic. */
if (dynamic_cast<const NetTran*>(cur->get_obj())) {
driven_ = VAR;
return false;
}
Link::DIR cur_dir = cur->get_dir();
if (cur_dir == Link::INPUT)
continue;
@@ -267,11 +275,17 @@ vector<bool> Nexus::driven_mask(void) const
}
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
continue;
if (obj_ps && cur->get_pin()!=1)
continue;
if (obj_ps) {
if(obj_ps) {
if (obj_ps->dir()==NetPartSelect::VP) {
if(cur->get_pin() != 0)
continue;
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
mask[idx] = true;
return mask;
} else {
if (cur->get_pin() != 1)
continue;
}
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
size_t bit = idx + obj_ps->base();
ivl_assert(*obj, bit < mask.size());
+1
View File
@@ -859,6 +859,7 @@ int main(int argc, char*argv[])
# if defined(HAVE_TIMES)
times_flag = true;
# endif
flags["VVP_EXTRA_ARGS"] = strdup(" -v");
break;
case 'V':
version_flag = true;
+3 -281
View File
@@ -1,282 +1,4 @@
Please NOTE:
Please see the Icarus Verilog Wiki for instruction on building and installing
Icarus Verilog as a native Windows application using the MinGW tools:
These directions are slightly outdated and need to be updated.
The plan is to rewrite all this using the latest MinGW at
some time in the not too distant future (CR Aug. 2009)
MINGW PORT OF ICARUS VERILOG
Copyright 2006 Stephen Williams <[email protected]>
Icarus Verilog source can be compiled with the mingw C/C++ compilers
to get a Windows binary that does not require the POSIX compatibility
cruft of the Cygwin.dll library. The resulting program can be run with
or without Cygwin, so this is the preferred Windows distribution form.
The configure scripts automatically detect that the compilers in use
are the mingw compilers and will configure the Makefiles appropriately.
The mingw patch doesn't contain tools beyond the compiler, but there
is the "msys" package that the makers of Mingw publish that has enough
extra tools to get most everything else working. There are a few extra
packages needed beyond mingw and msys, and the following instructions
explain how to get them and install them.
* Some Preliminary Comments -- PLEASE READ ME --
The Windows port of Icarus Verilog is the most difficult of all the
ports. The Windows system off the shelf is completely stripped, devoid
of any support for software development. Everything needed to compile
Icarus Verilog must be collected from various sources and stitched
together by hand. Normal human beings with a basic understanding of
software development can do this, but some patience (and access to the
Internet) is required. You may choose to print these instructions. FOR
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
NOTE that if you have Cygwin installed, it is best to not use a cygwin
window to do the build, as the Cygwin tools will intermix with the
mingw tools such that it is hard to be sure you are using the right
compiler. Thus, it is recommended that these steps be *not* done in a
Cygwin window. Use an MSYS window instead, and be careful that your
msys/mingw tools are not masked by paths that point to Cygwin binaries.
I have no plans to intentionally support MSVC++ compilation. Don't ask.
* Summary of Prerequisites
This is a brief list of prerequisite packages, along with the URL
where each can be found. In most cases, the specific version is not
critical, but these are the versions I use.
msys-1.0 <http://www.mingw/org>
msysDTK-1.0 <http://www.mingw.org>
Mingw32-5.x <http://www.mingw.org>
... including the sub-packages binutils, gcc-core and gcc-g++
if you are given the option.
readline-5.0-1 <http://gnuwin32.sourceforge.net>
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
bison-2.1 <http://gnuwin32.sourceforge.net>
flex-2.5.4a <http://gnuwin32.sourceforge.net>
The above table lists the packages required. It is convenient to
install them in the above order. Many of these packages are also
collected into the directory:
<ftp://icarus.com/pub/eda/verilog/win32-build-parts>
Incidentally, besides Mingw32, none of these packages are needed after
installation of Icarus Verilog is complete. These are only needed to
build the compiler. The Mingw32 package can be used to compile VPI
modules if you choose.
* Install MSYS and msysDTK
The msys package is available from the mingw download site. This is
not the compiler but a collection of *nix tools ported to Windows and
wrapped in a convenient installer. The msys package is all the various
basic tools (shells, file utils, etc) and the msysDTK is extra
developer tools other than the compiler.
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most
likely, you want to install them in c:/msys. (The msysDTK is installed
in the same location, as it is an add-on.)
This install should be easy and reliable.
The installation will leave an "msys" icon on your desktop and in the
mingw sub-menu of your Start menu. This icon brings up a shell window
(a command line) that has paths all set up for executing msys and
mingw commands. This is what you will want to use while executing
commands below.
* Install Mingw32
The obvious step 2, then, is install the mingw compilers. These can be
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
is a convenient remote installer. Download this program and run
it. The installer will ask which components you want to install. You
need only the base C compiler and the C++ compiler. (You may install
other languages if you wish.)
When I install Mingw32 (using the installer) I typically set a
destination directory of d:\mingw or the like. You will be using
that path later.
NOTES:
If you intend to compile VPI modules for Icarus Verilog, you
need Mingw32, even if you are using a precompiled binary. VPI
modules only require Mingw32, and none of the other libraries.
Finally, as part of installing the mingw32 compilers, remember to add
the mingw/bin directory to your path. You will need that to be able to
find the compilers later.
* Install GnuWin32 Packages
The GnuWin32 project is a collections of open source programs and
libraries ported to Windows. These also work well with the Mingw
compiler, and in fact Icarus Verilog uses a few pieces from this
collection.
You will need these gnuwin32 packages to compile Icarus Verilog:
<http://gnuwin32.sourceforge.net>
bzip2-1.0.3.exe
zlib-1.2.3.exe
gperf-3.0.1.exe
bison-2.1.exe
flex-2.5.4a.exe
readline-5.0-1.exe
I suggest creating a common directory for holding all your gnuwin32
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
has a "setup" link for each of these packages. Click the setup to
download the installer for each of the desired programs, then execute
the downloaded .exe files to invoke the installer. Install into the
c:\gunwin32 directory.
NOTES:
You need the binaries and the developer files, but you do not
need the source to these packages. The installer gives you the
choice.
After you are done installing the gnuwin32 tools, you should add the
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
your Windows path. The msys shell will pick up your Windows path.
* Unpack Icarus Verilog source
Unpack the compressed tar file (.tar.gz) of the source with a command
like this:
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
This will create a directory "verilog-xxxxxxxx" that contains all the
source for Icarus Verilog. Descend into that directory, as that is
where we will work from now on.
$ cd verilog-xxxxxxxx
NOTES:
The exact name of the file will vary according to the
snapshot. The 20030303 name is only an example.
Unpack the source into a directory that has no spaces. The
makefiles included in the source get confused by white space in
directory names.
* Preconfigure Icarus Verilog (Not normally needed)
Under certain cases, you may need to "preconfigure" the Icarus Verilog
source tree. You should only need to do this if you are getting the
Icarus Verilog source tree from git, or you are using an existing
source tree that you've patched to cause configure.in files to change.
NOTE: If you are building from a fresh, bundled source tree that
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
the "Configure Icarus Verilog" step below.
First, remove any autom4te.cache directories that may exist in your
source tree. These can make a mess of autoconf runs. Then, generate
configure scripts with this command:
$ sh autoconf.sh
This script will run the "autoconf" command (part of the msysDTK) to
generate all the necessary "configure" scripts. This will take a few
minutes. This should go smoothly.
* Configure Icarus Verilog
Now we are all set to configure and compile Icarus Verilog. Choose a
destination path where you will want to install the binaries. I chose
on my system the directory "D:\iverilog". This choice is not
permanent, so don't get too much angst over it. Just choose a name
without white space.
Now, configure the source to make the makefiles and configuration
details. Run these commands:
$ CPPFLAGS="-Ic:/gnuwin32/include
$ LDFLAGS="-Lc:/gnuwin32/lib
$ export CPPFLAGS LDFLAGS
$ ./configure --prefix=c:/iverilog
NOTES:
The CPPFLAGS and LDFLAGS variables tell configure where
the gnuwin32 packages are. The configure program will
write these values into the Makefiles, so you only need to
keep these variables long enough for the configure program
to work.
Your PATH variable was set in the previous step.
Use forward slashes as directory characters. All the various
tools prefer the forward slash.
Substitute your chosen directory for the prefix. This will cause the
makefiles to build and the source code to configure. The configure
program will detect that this is a mingw environment and set things up
to build properly.
(For a prefix, use the drive letter notation; the mingw compiled parts
require it, and the Cygwin tools should be able to handle it. You may
need to check or upgrade your Cygwin installation if this causes
problems for you.)
* Compile Icarus Verilog
This, believe it or not, should be the easy part:
$ make
It could take a while. Now is a good time to go get some coffee or
take a tea break.
* Install Icarus Verilog
If the compile ran OK, then next you install Icarus Verilog in the
directory you have chosen. When you are ready, install like this:
$ make install
This is part of what the configure program did for you. The Makefiles
now know to put the files under the D:\iverilog directory (or whatever
directory you chose) and away you go.
You may find that you need to put some of the prerequisite DLLs into
the d:\iverilog\bin directory. These include:
c:\mingw\bin\mingw10.dll
c:\gnuwin32\bin\readline.dll
c:\gnuwin32\bin\history.dll
c:\gnuwin32\bin\bzip2.dll
c:\gnuwin32\bin\zlib.dll
If you already have these in your Windows path (i.e. your system32
directory) then you do not need to copy them into the iverilog
directory. However, prepackaged Icarus Verilog binaries include these
files.
* Running Icarus Verilog
Finally, put the C:\iverilog\bin directory in your Windows path, and
you should be able to run the iverilog and vvp commands to your
heart's content.
Currently, the iverilog.exe uses the path to itself to locate the
libraries and modules associated with itself. In other words, if you
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
subparts in the C:\iverilog directory and subdirectories below
that. This means you can move the Icarus Verilog installation by
simply moving the root directory and all its contents.
The vvp.pdf and iverilog.pdf files document the main commands. View
these with Acrobat reader, or any other viewer capable of displaying
PDF format files.
http://iverilog.wikia.com/wiki/Installation_Guide#Compiling_on_MS_Windows_.28MinGW.29
+3 -2
View File
@@ -101,11 +101,12 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val;
}
NetScope* Design::make_root_scope(perm_string root, bool program_block)
NetScope* Design::make_root_scope(perm_string root, bool program_block,
bool is_interface)
{
NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
false, program_block);
false, program_block, is_interface);
/* This relies on the fact that the basename return value is
permallocated. */
root_scope_->set_module_name(root_scope_->basename());
+6 -2
View File
@@ -110,8 +110,10 @@ void Definitions::add_class(netclass_t*net_class)
* in question.
*/
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bool prog)
: type_(t), name_(n), nested_module_(nest), program_block_(prog), up_(up)
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
bool program, bool interface)
: type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), up_(up)
{
events_ = 0;
lcounter_ = 0;
@@ -372,6 +374,8 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
// To get here the parameter must already exist, so we should
// never get here.
assert(0);
// But return something to avoid a compiler warning.
return idx;
}
NetScope::TYPE NetScope::type() const
+4 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL_netdarray_H
#define IVL_netdarray_H
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -33,6 +33,9 @@ class netdarray_t : public netarray_t {
// IVL_VT_DARRAY for dynamic arrays?
ivl_variable_type_t base_type() const;
// A dynamic array may have a type that is signed.
inline bool get_signed() const { return element_type()->get_signed(); }
// This is the base_type() of the element of the array. We
// need this in some cases in order to get the base type of
// the element, and not the IVL_VT_DARRAY of the array itself.
+8 -3
View File
@@ -918,7 +918,8 @@ class NetScope : public Definitions, public Attrib {
/* Create a new scope, and attach it to the given parent. The
name is expected to have been permallocated. */
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, bool prog=false);
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false,
bool program=false, bool interface=false);
~NetScope();
/* Rename the scope using the name generated by inserting as
@@ -1008,8 +1009,9 @@ class NetScope : public Definitions, public Attrib {
// Nested modules have slightly different scope search rules.
inline bool nested_module() const { return nested_module_; }
// Program blocks have elaboration constraints.
// Program blocks and interfaces have elaboration constraints.
inline bool program_block() const { return program_block_; }
inline bool is_interface() const { return is_interface_; }
TYPE type() const;
void print_type(ostream&) const;
@@ -1221,6 +1223,8 @@ class NetScope : public Definitions, public Attrib {
bool nested_module_;
// True if the scope is a program block
bool program_block_;
// True if the scope is an interface
bool is_interface_;
perm_string file_;
perm_string def_file_;
@@ -4747,7 +4751,8 @@ class Design : public Definitions {
const char* get_flag(const string&key) const;
NetScope* make_root_scope(perm_string name, bool program_block);
NetScope* make_root_scope(perm_string name, bool program_block,
bool is_interface);
NetScope* find_root_scope();
std::list<NetScope*> find_root_scopes() const;
+6
View File
@@ -34,6 +34,12 @@ netparray_t::~netparray_t()
* The packed width of a packed array is the packed width of the
* element times the dimension width of the array itself.
*/
bool netparray_t::packed(void) const
{
return true;
}
long netparray_t::packed_width(void) const
{
long cur_width = element_type()->packed_width();
+1
View File
@@ -64,6 +64,7 @@ class netparray_t : public netsarray_t {
public:
// Virtual methods from the ivl_type_s type...
bool packed(void) const;
long packed_width(void) const;
std::vector<netrange_t> slice_dimensions() const;
+4 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL__netqueue_H
#define IVL__netqueue_H
/*
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -38,6 +38,9 @@ class netqueue_t : public netdarray_t {
// IVL_VT_QUEUE for queues.
ivl_variable_type_t base_type() const;
// A queue may have a type that is signed.
inline bool get_signed() const { return element_type()->get_signed(); }
std::ostream& debug_dump(std::ostream&) const;
private:
+1 -1
View File
@@ -94,7 +94,7 @@ class netrange_t {
inline netrange_t() : msb_(LONG_MAX), lsb_(LONG_MAX) { }
// Create a properly defined netrange
inline netrange_t(long m, long l) : msb_(m), lsb_(l) { }
// Copy constructure.
// Copy constructor.
inline netrange_t(const netrange_t&that)
: msb_(that.msb_), lsb_(that.lsb_) { }
+211 -42
View File
@@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
* Copyright CERN 2012-2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -49,6 +49,16 @@ static struct {
data_type_t* data_type;
} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT, 0};
/* Modport port declaration lists use this structure for context. */
enum modport_port_type_t { MP_NONE, MP_SIMPLE, MP_TF, MP_CLOCKING };
static struct {
modport_port_type_t type;
union {
NetNet::PortType direction;
bool is_import;
};
} last_modport_port = { MP_NONE, {NetNet::NOT_A_PORT}};
/* The task and function rules need to briefly hold the pointer to the
task/function that is currently in progress. */
static PTask* current_task = 0;
@@ -549,6 +559,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <flag> from_exclude block_item_decls_opt
%type <number> number pos_neg_number
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
%type <flag> import_export
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
%type <flag> udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
@@ -562,8 +573,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt
%type <text> register_variable net_variable endlabel_opt class_declaration_endlabel_opt
%type <perm_strings> register_variable_list net_variable_list
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
%type <perm_strings> register_variable_list net_variable_list event_variable_list
%type <perm_strings> list_of_identifiers loop_variables
%type <port_list> list_of_port_identifiers
@@ -583,7 +594,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <tf_ports> task_item task_item_list task_item_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
%type <named_pexpr> port_name parameter_value_byname
%type <named_pexpr> modport_simple_port port_name parameter_value_byname
%type <named_pexprs> port_name_list parameter_value_byname_list
%type <named_pexpr> attribute
@@ -739,7 +750,7 @@ class_identifier
perm_string name = lex_strings.make($1);
class_type_t*tmp = new class_type_t(name);
FILE_NAME(tmp, @1);
pform_set_typedef(name, tmp);
pform_set_typedef(name, tmp, NULL);
delete[]$1;
$$ = tmp;
}
@@ -1117,8 +1128,8 @@ data_type_or_implicit_or_void
statements may go. This may be a bad idea, but it is legacy now. */
/* NOTE 2: The "module" rule of the description combines the
module_declaration and program_declaration rules from the
standard description. */
module_declaration, program_declaration, and interface_declaration
rules from the standard description. */
description /* IEEE1800-2005: A.1.2 */
: module
@@ -1142,7 +1153,7 @@ description_list
;
/* This implements the [ : INDENTIFIER ] part of the constructure
/* This implements the [ : IDENTIFIER ] part of the constructor
rule documented in IEEE1800-2005: A.1.8 */
endnew_opt : ':' K_new | ;
@@ -1270,6 +1281,11 @@ function_declaration /* IEEE1800-2005: A.2.6 */
;
import_export /* IEEE1800-2012: A.2.9 */
: K_import { $$ = true; }
| K_export { $$ = false; }
;
implicit_class_handle /* IEEE1800-2005: A.8.4 */
: K_this { $$ = pform_create_this(); }
| K_super { $$ = pform_create_super(); }
@@ -1546,6 +1562,115 @@ method_qualifier_opt
|
;
modport_declaration /* IEEE1800-2012: A.2.9 */
: K_modport
{ if (!pform_in_interface())
yyerror(@1, "error: modport declarations are only allowed "
"in interfaces.");
}
modport_item_list ';'
modport_item_list
: modport_item
| modport_item_list ',' modport_item
;
modport_item
: IDENTIFIER
{ pform_start_modport_item(@1, $1); }
'(' modport_ports_list ')'
{ pform_end_modport_item(@1); }
;
/* The modport_ports_list is a LALR(2) grammar. When the parser sees a
',' it needs to look ahead to the next token to decide whether it is
a continuation of the preceding modport_ports_declaration, or the
start of a new modport_ports_declaration. bison only supports LALR(1),
so we have to handcraft a mini parser for this part of the syntax.
last_modport_port holds the state for this mini parser.*/
modport_ports_list
: modport_ports_declaration
| modport_ports_list ',' modport_ports_declaration
| modport_ports_list ',' modport_simple_port
{ if (last_modport_port.type == MP_SIMPLE) {
pform_add_modport_port(@3, last_modport_port.direction,
$3->name, $3->parm);
} else {
yyerror(@3, "error: modport expression not allowed here.");
}
delete $3;
}
| modport_ports_list ',' modport_tf_port
{ if (last_modport_port.type != MP_TF)
yyerror(@3, "error: task/function declaration not allowed here.");
}
| modport_ports_list ',' IDENTIFIER
{ if (last_modport_port.type == MP_SIMPLE) {
pform_add_modport_port(@3, last_modport_port.direction,
lex_strings.make($3), 0);
} else if (last_modport_port.type != MP_TF) {
yyerror(@3, "error: list of identifiers not allowed here.");
}
delete[] $3;
}
| modport_ports_list ','
{ yyerror(@2, "error: NULL port declarations are not allowed"); }
;
modport_ports_declaration
: attribute_list_opt port_direction IDENTIFIER
{ last_modport_port.type = MP_SIMPLE;
last_modport_port.direction = $2;
pform_add_modport_port(@3, $2, lex_strings.make($3), 0);
delete[] $3;
delete $1;
}
| attribute_list_opt port_direction modport_simple_port
{ last_modport_port.type = MP_SIMPLE;
last_modport_port.direction = $2;
pform_add_modport_port(@3, $2, $3->name, $3->parm);
delete $3;
delete $1;
}
| attribute_list_opt import_export IDENTIFIER
{ last_modport_port.type = MP_TF;
last_modport_port.is_import = $2;
yyerror(@3, "sorry: modport task/function ports are not yet supported.");
delete[] $3;
delete $1;
}
| attribute_list_opt import_export modport_tf_port
{ last_modport_port.type = MP_TF;
last_modport_port.is_import = $2;
yyerror(@3, "sorry: modport task/function ports are not yet supported.");
delete $1;
}
| attribute_list_opt K_clocking IDENTIFIER
{ last_modport_port.type = MP_CLOCKING;
last_modport_port.direction = NetNet::NOT_A_PORT;
yyerror(@3, "sorry: modport clocking declaration is not yet supported.");
delete[] $3;
delete $1;
}
;
modport_simple_port
: '.' IDENTIFIER '(' expression ')'
{ named_pexpr_t*tmp = new named_pexpr_t;
tmp->name = lex_strings.make($2);
tmp->parm = $4;
delete[]$2;
$$ = tmp;
}
;
modport_tf_port
: K_task IDENTIFIER
| K_task IDENTIFIER '(' tf_port_list_opt ')'
| K_function data_type_or_implicit_or_void IDENTIFIER
| K_function data_type_or_implicit_or_void IDENTIFIER '(' tf_port_list_opt ')'
;
non_integer_type /* IEEE1800-2005: A.2.2.1 */
: K_real { $$ = real_type_t::REAL; }
@@ -2186,8 +2311,8 @@ block_item_decl
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
}
| K_event list_of_identifiers ';'
{ pform_make_events($2, @1.text, @1.first_line);
| K_event event_variable_list ';'
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
}
| K_parameter param_type parameter_assign_list ';'
@@ -2233,9 +2358,9 @@ block_item_decls_opt
/* Type declarations are parsed here. The rule actions call pform
functions that add the declaration to the current lexical scope. */
type_declaration
: K_typedef data_type IDENTIFIER ';'
: K_typedef data_type IDENTIFIER dimensions_opt ';'
{ perm_string name = lex_strings.make($3);
pform_set_typedef(name, $2);
pform_set_typedef(name, $2, $4);
delete[]$3;
}
@@ -2248,7 +2373,7 @@ type_declaration
yyerror(@3, "error: Typedef identifier \"%s\" is already a type name.", $3.text);
} else {
pform_set_typedef(name, $2);
pform_set_typedef(name, $2, NULL);
}
delete[]$3.text;
}
@@ -2261,7 +2386,7 @@ type_declaration
perm_string name = lex_strings.make($3);
class_type_t*tmp = new class_type_t(name);
FILE_NAME(tmp, @3);
pform_set_typedef(name, tmp);
pform_set_typedef(name, tmp, NULL);
delete[]$3;
}
| K_typedef K_enum IDENTIFIER ';'
@@ -2276,7 +2401,7 @@ type_declaration
perm_string name = lex_strings.make($2);
class_type_t*tmp = new class_type_t(name);
FILE_NAME(tmp, @2);
pform_set_typedef(name, tmp);
pform_set_typedef(name, tmp, NULL);
delete[]$2;
}
@@ -2323,34 +2448,34 @@ enum_data_type
enum_type->range.reset(make_range_from_width(integer_width));
$$ = enum_type;
}
| K_enum K_logic unsigned_signed_opt dimensions '{' enum_name_list '}'
| K_enum K_logic unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
{ enum_type_t*enum_type = new enum_type_t;
FILE_NAME(enum_type, @1);
enum_type->names .reset($6);
enum_type->base_type = IVL_VT_LOGIC;
enum_type->signed_flag = $3;
enum_type->integer_flag = false;
enum_type->range.reset($4);
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
$$ = enum_type;
}
| K_enum K_reg unsigned_signed_opt dimensions '{' enum_name_list '}'
| K_enum K_reg unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
{ enum_type_t*enum_type = new enum_type_t;
FILE_NAME(enum_type, @1);
enum_type->names .reset($6);
enum_type->base_type = IVL_VT_LOGIC;
enum_type->signed_flag = $3;
enum_type->integer_flag = false;
enum_type->range.reset($4);
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
$$ = enum_type;
}
| K_enum K_bit unsigned_signed_opt dimensions '{' enum_name_list '}'
| K_enum K_bit unsigned_signed_opt dimensions_opt '{' enum_name_list '}'
{ enum_type_t*enum_type = new enum_type_t;
FILE_NAME(enum_type, @1);
enum_type->names .reset($6);
enum_type->base_type = IVL_VT_BOOL;
enum_type->signed_flag = $3;
enum_type->integer_flag = false;
enum_type->range.reset($4);
enum_type->range.reset($4 ? $4 : make_range_from_width(1));
$$ = enum_type;
}
;
@@ -4213,13 +4338,13 @@ local_timeunit_prec_decl2
}
;
/* This is the global structure of a module. A module in a start
/* This is the global structure of a module. A module is a start
section, with optional ports, then an optional list of module
items, and finally an end marker. */
module
: attribute_list_opt module_start IDENTIFIER
{ pform_startmodule(@2, $3, $2==K_program, $1); }
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
module_package_import_list_opt
module_parameter_port_list_opt
module_port_list_opt
@@ -4258,6 +4383,9 @@ module
case K_program:
yyerror(@14, "error: program not closed by endprogram.");
break;
case K_interface:
yyerror(@14, "error: interface not closed by endinterface.");
break;
default:
break;
}
@@ -4283,6 +4411,10 @@ module
yyerror(@16, "error: End label doesn't match "
"program name.");
break;
case K_interface:
yyerror(@16, "error: End label doesn't match "
"interface name.");
break;
default:
break;
}
@@ -4297,19 +4429,21 @@ module
}
;
/* Modules start with module/macromodule or program keyword, and end
with the endmodule or endprogram keyword. The syntax for modules
and programs is almost identical, so let semantics sort out the
differences. */
/* Modules start with a module/macromodule, program, or interface
keyword, and end with a endmodule, endprogram, or endinterface
keyword. The syntax for modules programs, and interfaces is
almost identical, so let semantics sort out the differences. */
module_start
: K_module { $$ = K_module; }
| K_macromodule { $$ = K_module; }
| K_program { $$ = K_program; }
| K_interface { $$ = K_interface; }
;
module_end
: K_endmodule { $$ = K_module; }
| K_endprogram { $$ = K_program; }
: K_endmodule { $$ = K_module; }
| K_endprogram { $$ = K_program; }
| K_endinterface { $$ = K_interface; }
;
endlabel_opt
@@ -4505,7 +4639,12 @@ module_item
/* */
| K_defparam defparam_assign_list ';'
| K_defparam
{ if (pform_in_interface())
yyerror(@1, "error: Parameter overrides are not allowed "
"in interfaces.");
}
defparam_assign_list ';'
/* Most gate types have an optional drive strength and optional
two/three-value delay. These rules handle the different cases.
@@ -4670,25 +4809,32 @@ module_item
pform_endgenerate();
}
| modport_declaration
| package_import_declaration
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
| attribute_list_opt K_specparam specparam_decl ';'
| attribute_list_opt K_specparam
{ if (pform_in_interface())
yyerror(@1, "error: specparam declarations are not allowed "
"in interfaces.");
}
specparam_decl ';'
/* specify blocks are parsed but ignored. */
| K_specify K_endspecify
{ /* empty lists are legal syntax. */ }
| K_specify
{ if (pform_in_interface())
yyerror(@1, "error: specify blocks are not allowed "
"in interfaces.");
}
specify_item_list_opt K_endspecify
| K_specify specify_item_list K_endspecify
{
}
| K_specify error K_endspecify
{ yyerror(@1, "error: syntax error in specify block");
yyerrok;
}
| K_specify error K_endspecify
{ yyerror(@1, "error: syntax error in specify block");
yyerrok;
}
/* These rules match various errors that the user can type into
module items. These rules try to catch them at a point where a
@@ -5338,6 +5484,23 @@ net_variable_list
}
;
event_variable
: IDENTIFIER dimensions_opt
{ if ($2) {
yyerror(@2, "sorry: event arrays are not supported.");
delete $2;
}
$$ = $1;
}
;
event_variable_list
: event_variable
{ $$ = list_from_identifier($1); }
| event_variable_list ',' event_variable
{ $$ = list_from_identifier($1, $3); }
;
specify_item
: K_specparam specparam_decl ';'
| specify_simple_path_decl ';'
@@ -5450,6 +5613,12 @@ specify_item_list
| specify_item_list specify_item
;
specify_item_list_opt
: /* empty */
{ }
| specify_item_list
{ }
specify_edge_path_decl
: specify_edge_path '=' '(' delay_value_list ')'
{ $$ = pform_assign_path_delay($1, $4); }
@@ -6566,7 +6735,7 @@ udp_primitive
presence is significant. This is a fairly common pattern so
collect those rules here. */
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false;} ;
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
+152 -39
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -29,6 +29,7 @@
# include "PPackage.h"
# include "PUdp.h"
# include "PGenerate.h"
# include "PModport.h"
# include "PSpec.h"
# include "discipline.h"
# include <list>
@@ -265,6 +266,10 @@ static unsigned scope_generate_counter = 1;
always within a module. */
static PGenerate*pform_cur_generate = 0;
/* This tracks the current modport list being processed. This is
always within an interface. */
static PModport*pform_cur_modport = 0;
static NetNet::Type pform_default_nettype = NetNet::WIRE;
/*
@@ -534,6 +539,15 @@ bool pform_in_program_block()
return false;
}
bool pform_in_interface()
{
if (pform_cur_module.empty())
return false;
if (pform_cur_module.front()->is_interface)
return true;
return false;
}
static bool pform_at_module_level()
{
return (lexical_scope == pform_cur_module.front())
@@ -579,8 +593,11 @@ PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetN
return cur;
}
void pform_set_typedef(perm_string name, data_type_t*data_type)
void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_range_t>*unp_ranges)
{
if(unp_ranges)
data_type = new uarray_type_t(data_type, unp_ranges);
// If we are in a lexical scope (i.e. a package or module)
// then put the typedef into that scope. Otherwise, put it
// into the $root scope.
@@ -1062,6 +1079,12 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
assert(siz->is_defined());
unsigned long size = siz->as_ulong();
if (size == 0) {
cerr << file << ":" << lineno << ": error: Sized numeric constant "
"must have a size greater than zero." << endl;
error_count += 1;
}
verinum::V pad;
switch (val->get(val->len()-1)) {
@@ -1107,7 +1130,8 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
}
void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, list<named_pexpr_t>*attr)
bool program_block, bool is_interface,
list<named_pexpr_t>*attr)
{
if (! pform_cur_module.empty() && !gn_system_verilog()) {
cerr << loc << ": error: Module definition " << name
@@ -1115,15 +1139,25 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
error_count += 1;
}
if (gn_system_verilog() && ! pform_cur_module.empty() &&
pform_cur_module.front()->program_block) {
cerr << loc << ": error: Program blocks cannot contain nested modules/program blocks." << endl;
error_count += 1;
if (gn_system_verilog() && ! pform_cur_module.empty()) {
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: module, program, or interface "
"declarations are not allowed in program "
"blocks." << endl;
error_count += 1;
}
if (pform_cur_module.front()->is_interface
&& !(program_block || is_interface)) {
cerr << loc << ": error: module declarations are not "
"allowed in interfaces." << endl;
error_count += 1;
}
}
perm_string lex_name = lex_strings.make(name);
Module*cur_module = new Module(lexical_scope, lex_name);
cur_module->program_block = program_block;
cur_module->is_interface = is_interface;
/* Set the local time unit/precision to the global value. */
cur_module->time_unit = pform_time_unit;
cur_module->time_precision = pform_time_prec;
@@ -1914,7 +1948,6 @@ static void pform_set_net_range(list<perm_string>*names,
pform_set_net_range(txt, net_type, range, signed_flag, dt, SR_NET, attr);
}
delete names;
}
/*
@@ -2001,8 +2034,13 @@ void pform_makegates(const struct vlltype&loc,
{
assert(! pform_cur_module.empty());
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: Gates and switches may not be instantiated"
<< " in program blocks." << endl;
cerr << loc << ": error: Gates and switches may not be instantiated in "
<< "program blocks." << endl;
error_count += 1;
}
if (pform_cur_module.front()->is_interface) {
cerr << loc << ": error: Gates and switches may not be instantiated in "
<< "interfaces." << endl;
error_count += 1;
}
@@ -2117,8 +2155,13 @@ void pform_make_modgates(const struct vlltype&loc,
{
assert(! pform_cur_module.empty());
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: Module instantiations are not allowed"
<< " in program blocks." << endl;
cerr << loc << ": error: Module instantiations are not allowed in "
<< "program blocks." << endl;
error_count += 1;
}
if (pform_cur_module.front()->is_interface) {
cerr << loc << ": error: Module instantiations are not allowed in "
<< "interfaces." << endl;
error_count += 1;
}
@@ -2317,6 +2360,11 @@ void pform_module_define_port(const struct vlltype&li,
signed_flag = false;
prange = 0;
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(vtype)) {
data_type = enum_type->base_type;
signed_flag = enum_type->signed_flag;
prange = enum_type->range.get();
} else if (vtype) {
VLerror(li, "sorry: Given type %s not supported here (%s:%d).",
typeid(*vtype).name(), __FILE__, __LINE__);
@@ -2624,7 +2672,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
}
delete range;
delete names;
return res;
}
@@ -2653,7 +2700,6 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
res->push_back(pform_tf_port_t(curw));
}
delete names;
return res;
}
@@ -2662,35 +2708,54 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
data_type_t*vtype,
list<perm_string>*names)
{
vector<pform_tf_port_t>*ret = NULL;
std::list<pform_range_t>*unpacked_dims = NULL;
if (uarray_type_t*uarray = dynamic_cast<uarray_type_t*> (vtype)) {
unpacked_dims = uarray->dims.get();
vtype = uarray->base_type;
}
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code);
return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL,
atype->signed_flag,
range_tmp, names);
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, vec_type->base_type,
ret = pform_make_task_ports(loc, pt, vec_type->base_type,
vec_type->signed_flag,
copy_range(vec_type->pdims.get()),
names, vec_type->integer_flag);
}
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_REAL,
ret = pform_make_task_ports(loc, pt, IVL_VT_REAL,
true, 0, names);
}
if (dynamic_cast<string_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_STRING,
ret = pform_make_task_ports(loc, pt, IVL_VT_STRING,
false, 0, names);
}
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
return do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
}
return do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
if (unpacked_dims) {
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
PWire*wire = pform_get_wire_in_scope(*cur);
wire->set_unpacked_idx(*unpacked_dims);
}
}
delete names;
return ret;
}
/*
@@ -3136,7 +3201,6 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_
perm_string txt = *cur;
pform_set_integer_2atom(width, signed_flag, txt, net_type, attr);
}
delete names;
}
template <class T> static void pform_set2_data_type(const struct vlltype&li, T*data_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
@@ -3212,7 +3276,6 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
pform_set_enum(li, enum_type, txt, net_type, attr);
}
delete names;
}
/*
@@ -3221,58 +3284,68 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
*/
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
const std::list<pform_range_t>*unpacked_dims = NULL;
if (data_type == 0) {
VLerror(li, "internal error: data_type==0.");
assert(0);
}
if(uarray_type_t*uarray_type = dynamic_cast<uarray_type_t*> (data_type)) {
unpacked_dims = uarray_type->dims.get();
data_type = uarray_type->base_type;
}
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr);
return;
}
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
pform_set_struct_type(struct_type, names, net_type, attr);
return;
}
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
pform_set_enum(li, enum_type, names, net_type, attr);
return;
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
else if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
if (net_type==NetNet::REG && vec_type->integer_flag)
net_type=NetNet::INTEGER;
pform_set_net_range(names, vec_type->pdims.get(),
vec_type->signed_flag,
vec_type->base_type, net_type, attr);
return;
}
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
else if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
pform_set_net_range(names, 0, true, IVL_VT_REAL, net_type, attr);
return;
}
if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
else if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
pform_set_class_type(class_type, names, net_type, attr);
return;
}
if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
else if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
pform_set2_data_type(li, array_type, names, net_type, attr);
return;
}
if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
else if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
pform_set_string_type(string_type, names, net_type, attr);
return;
} else {
VLerror(li, "internal error: Unexpected data_type.");
assert(0);
}
VLerror(li, "internal error: Unexpected data_type.");
assert(0);
if(unpacked_dims) {
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
PWire*wire = pform_get_wire_in_scope(*cur);
wire->set_unpacked_idx(*unpacked_dims);
}
}
delete names;
}
vector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
@@ -3326,6 +3399,46 @@ PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
return pp;
}
void pform_start_modport_item(const struct vlltype&loc, const char*name)
{
Module*scope = pform_cur_module.front();
ivl_assert(loc, scope && scope->is_interface);
ivl_assert(loc, pform_cur_modport == 0);
perm_string use_name = lex_strings.make(name);
pform_cur_modport = new PModport(use_name);
FILE_NAME(pform_cur_modport, loc);
if (scope->modports.find(use_name) != scope->modports.end()) {
cerr << loc << ": error: duplicate declaration for modport '"
<< name << "' in '" << scope->mod_name() << "'." << endl;
error_count += 1;
}
scope->modports[use_name] = pform_cur_modport;
delete[] name;
}
void pform_end_modport_item(const struct vlltype&loc)
{
ivl_assert(loc, pform_cur_modport);
pform_cur_modport = 0;
}
void pform_add_modport_port(const struct vlltype&loc,
NetNet::PortType port_type,
perm_string name, PExpr*expr)
{
ivl_assert(loc, pform_cur_modport);
if (pform_cur_modport->simple_ports.find(name)
!= pform_cur_modport->simple_ports.end()) {
cerr << loc << ": error: duplicate declaration of port '"
<< name << "' in modport list '"
<< pform_cur_modport->name() << "'." << endl;
error_count += 1;
}
pform_cur_modport->simple_ports[name] = make_pair(port_type, expr);
}
FILE*vl_input = 0;
extern void reset_lexor();
+21 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_pform_H
#define IVL_pform_H
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -136,6 +136,10 @@ extern void pform_set_default_nettype(NetNet::Type net,
used to reject statements that cannot exist in program blocks. */
extern bool pform_in_program_block(void);
/* Return true if currently processing an interface. This can be
used to reject statements that cannot exist in interfaces. */
extern bool pform_in_interface(void);
/*
* Look for the given wire in the current lexical scope. If the wire
* (including variables of any type) cannot be found in the current
@@ -152,12 +156,14 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
* are to apply to the scope of that module. The endmodule causes the
* pform to close up and finish the named module.
*
* The program_flag indicates that the module is actually a program
* block. This has implications during parse and during
* The program_block flag indicates that the module is actually a program
* block. The is_interface flag indicates that the module is actually
* an interface. These flags have implications during parse and during
* elaboration/code generation.
*/
extern void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, list<named_pexpr_t>*attr);
bool program_block, bool is_interface,
list<named_pexpr_t>*attr);
extern void pform_check_timeunit_prec();
extern void pform_module_set_ports(vector<Module::port_t*>*);
@@ -213,6 +219,15 @@ extern void pform_package_import(const struct vlltype&loc,
extern PExpr* pform_package_ident(const struct vlltype&loc,
PPackage*pkg, pform_name_t*ident);
/*
* Interface related functions.
*/
extern void pform_start_modport_item(const struct vlltype&loc, const char*name);
extern void pform_end_modport_item(const struct vlltype&loc);
extern void pform_add_modport_port(const struct vlltype&loc,
NetNet::PortType port_type,
perm_string name, PExpr*expr);
/*
* This creates an identifier aware of names that may have been
* imported from other packages.
@@ -272,7 +287,8 @@ extern void pform_endgenerate();
*/
extern PGenerate* pform_parent_generate(void);
extern void pform_set_typedef(perm_string name, data_type_t*data_type);
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
std::list<pform_range_t>*unp_ranges);
/*
* This function makes a PECallFunction of the named function. Decide
+1 -1
View File
@@ -88,7 +88,7 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
return false;
// The prefix is found to be a scope, so switch to that
// scope, set the hier_path to turn of upwards searches,
// scope, set the hier_path to turn off upwards searches,
// and continue our search for the tail.
if (recurse.is_scope()) {
scope = recurse.scope;
+107 -25
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -82,15 +82,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
des->errors += 1;
return false;
}
if (lval_->more) {
cerr << get_fileline() << ": sorry: "
<< "NetAssignBase::synth_async does not support an "
<< "L-value concatenation ";
dump_lval(cerr);
cerr << endl;
des->errors += 1;
return false;
}
if (debug_synth2) {
cerr << get_fileline() << ": NetAssignBase::synth_async: "
@@ -109,6 +100,34 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
<< ", nex_out.pin_count()==" << nex_out.pin_count() << endl;
}
if (lval_->more ) {
unsigned base = 0, width = 1;
unsigned i = 0;
NetAssign_ *lval = lval_;
while (lval) {
NetNet *llsig = lval->sig();
width = lval->lwidth();
ivl_variable_type_t tmp_data_type = llsig->data_type();
netvector_t *tmp_type = new netvector_t(tmp_data_type, llsig->vector_width()-1, 0);
NetNet *tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
tmp->local_flag(true);
NetPartSelect *ps = new NetPartSelect(rsig, base, width, NetPartSelect::VP);
ps->set_line(*this);
des->add_node(ps);
connect(tmp->pin(0), ps->pin(0));
connect(nex_out.pin(i), tmp->pin(0));
base += width;
i++;
lval->turn_sig_to_wire_on_release();
lval = lval->more;
}
return true;
}
// Here we note if the l-value is actually a bit/part
// select. If so, generate a NetPartSelect to perform the select.
if ((lval_->lwidth()!=lsig->vector_width()) && !scope->loop_index_tmp.empty()) {
@@ -136,6 +155,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
NetPartSelect*ps = new NetPartSelect(tmp, base_off, lval_->lwidth(), NetPartSelect::PV);
ps->set_line(*this);
@@ -166,7 +186,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
//tmp->local_flag(true);
tmp->local_flag(true);
tmp->set_line(*this);
ivl_assert(*this, accumulated_nex_out.pin_count()==1);
NetNet*use_lsig = lsig;
@@ -185,7 +206,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
<< " Found no use_sig, resorting to lsig." << endl;
}
}
NetSubstitute*ps = new NetSubstitute(use_lsig, rsig,
tmp->vector_width(),
base_off);
@@ -531,18 +551,24 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
statement_map[sel_idx] = items_[item].statement;
}
// The mux_size is the number of inputs that are selected.
unsigned mux_size = max_guard_value + 1;
unsigned sel_need = ceil(log2(mux_size));
// The minimum selector width is the number of inputs that
// are selected, rounded up to the nearest power of 2.
unsigned sel_need = ceil(log2(max_guard_value + 1));
// If the sel_width can select more than just the explicit
// guard values, and there is a default statement, then adjust
// the mux size to allow for the implicit selections.
if (statement_default && (sel_width > sel_need)) {
// the sel_need to allow for the implicit selections.
if (statement_default && (sel_width > sel_need))
sel_need += 1;
ivl_assert(*this, sel_need < sizeof mux_size);
mux_size = 1<<sel_need;
// The mux size is always an exact power of 2.
if (sel_need >= 8*sizeof(unsigned)) {
cerr << get_fileline() << ": sorry: mux select width of "
<< sel_need << " bits is too large for synthesis." << endl;
des->errors += 1;
return false;
}
unsigned mux_size = 1U << sel_need;
if (debug_synth2) {
cerr << get_fileline() << ": NetCase::synth_async: "
@@ -746,7 +772,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
netvector_t*condit_type = new netvector_t(IVL_VT_LOGIC, 0, 0);
NetCaseCmp::kind_t case_kind;
NetCaseCmp::kind_t case_kind = NetCaseCmp::EEQ;
switch (type()) {
case NetCase::EQ:
case_kind = NetCaseCmp::EEQ;
@@ -829,6 +855,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, tmp_vec);
tmp->local_flag(true);
tmp->set_line(*this);
ivl_assert(*this, tmp->vector_width() != 0);
connect(mux_cur->pin_Result(), tmp->pin(0));
@@ -1105,6 +1132,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
NetNet*otmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
otmp->local_flag(true);
otmp->set_line(*this);
connect(mux->pin_Result(),otmp->pin(0));
connect(mux->pin_Sel(), ssig->pin(0));
@@ -1115,6 +1143,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
connect(mux->pin_Data(1), tmp->pin(0));
}
@@ -1122,6 +1152,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
connect(mux->pin_Data(0), tmp->pin(0));
}
@@ -1132,6 +1164,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
tmp_type = new netvector_t(mux_data_type, mux_lwidth-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
NetPartSelect*ps = new NetPartSelect(tmp, mux_off, mux_width, NetPartSelect::PV);
des->add_node(ps);
connect(ps->pin(0), otmp->pin(0));
@@ -1159,8 +1193,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
<< endl;
}
vector<bool>mask = statement_input.pin(idx).nexus()->driven_mask();
for (size_t bit = mux_off ; bit < mux_off+mux_width ; bit += 1) {
ivl_assert(*this, mask[bit]==false);
// If the mask is empty then there are no bits in the
// nexus to check yet.
if (! mask.empty()) {
for (size_t bit = mux_off;
bit < mux_off+mux_width;
bit += 1) {
ivl_assert(*this, mask[bit]==false);
}
}
connect(nex_out.pin(idx), statement_input.pin(idx));
}
@@ -1308,6 +1348,7 @@ bool NetProcTop::synth_async(Design*des)
NetNet*tmp_sig = new NetNet(scope(), scope()->local_symbol(),
NetNet::WIRE, NetNet::not_an_array, tmp_type);
tmp_sig->local_flag(true);
tmp_sig->set_line(*this);
NetPartSelect*tmp = new NetPartSelect(tmp_sig, item.base,
item.wid, NetPartSelect::PV);
@@ -1508,9 +1549,49 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
connect(ff_aset.pin(pin), rst->pin(0));
} else {
cerr << get_fileline() << ": sorry: "
<< "Forgot how to implement asynchronous scramble (set to x/z)." << endl;
return false;
NetConcat *set_cc = new NetConcat(scope,
scope->local_symbol(),
rst_nex->vector_width(),
rst_drv.len(), true);
NetConcat *rst_cc = new NetConcat(scope,
scope->local_symbol(),
rst_nex->vector_width(),
rst_drv.len(), true);
ivl_variable_type_t oosig_data_type = IVL_VT_LOGIC;
netvector_t *oosig_vec = new netvector_t(oosig_data_type, 0, 0);
NetNet *oosig[2] = {new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, oosig_vec),
new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, oosig_vec)};
set_cc->set_line(*this);
des->add_node(set_cc);
connect(set_cc->pin(0), oosig[0]->pin(0));
rst_cc->set_line(*this);
des->add_node(rst_cc);
connect(rst_cc->pin(0), oosig[1]->pin(0));
for (int i = 0; i < (int)rst_drv.len(); i += 1) {
// This is the output signal f const, osig.
ivl_variable_type_t osig_data_type = IVL_VT_LOGIC;
netvector_t*osig_vec = new netvector_t(osig_data_type, 0, 0);
NetNet *osig = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, osig_vec);
NetConst *nc = new NetConst(scope, scope->local_symbol(),
verinum(verinum::V0, 1));
connect(nc->pin(0), osig->pin(0));
nc->set_line(*this);
des->add_node(nc);
if (rst_drv[i] == verinum::V1) {
connect(set_cc->pin(i+1), rst->pin(0));
connect(rst_cc->pin(i+1), nc->pin(0));
} else {
connect(set_cc->pin(i+1), nc->pin(0));
connect(rst_cc->pin(i+1), rst->pin(0));
}
}
connect(ff_aset.pin(pin), set_cc->pin(0));
connect(ff_aclr.pin(pin), rst_cc->pin(0));
}
}
@@ -1789,6 +1870,7 @@ bool NetProcTop::synth_sync(Design*des)
NetNet*clock = new NetNet(scope(), scope()->local_symbol(),
NetNet::TRI, &netvector_t::scalar_logic);
clock->local_flag(true);
clock->set_line(*this);
#if 0
NetNet*ce = new NetNet(scope(), scope()->local_symbol(),
+2 -1
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
@@ -364,6 +364,7 @@ void dll_target::expr_last(const NetELast*net)
esig->value_ = IVL_VT_DARRAY;
esig->net_type= sig->net_type;
esig->width_ = 1;
esig->signed_ = sig->net_type->get_signed()? 1 : 0;
FILE_NAME(esig, net);
esig->u_.signal_.word = 0;
esig->u_.signal_.sig = sig;
+5 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -1057,20 +1057,17 @@ void dll_target::logic(const NetLogic*net)
obj->npins_ = net->pin_count();
obj->pins_ = new ivl_nexus_t[obj->npins_];
ivl_nexus_ptr_t out_ptr = 0;
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus();
assert(nex->t_cookie());
obj->pins_[idx] = nex->t_cookie();
ivl_nexus_ptr_t tmp = nexus_log_add(obj->pins_[idx], obj, idx);
if (idx == 0)
out_ptr = tmp;
if (idx == 0) {
tmp->drive0 = net->pin(0).drive0();
tmp->drive1 = net->pin(0).drive1();
}
}
out_ptr->drive0 = net->pin(0).drive0();
out_ptr->drive1 = net->pin(0).drive1();
assert(net->scope());
ivl_scope_t scop = find_scope(des_, net->scope());
assert(scop);
+6 -3
View File
@@ -82,12 +82,15 @@ pcb_config.h: stamp-pcb_config-h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep
fp_lex.o: fp_lex.cc fp.h
fp_lex.cc: $(srcdir)/fp.lex
$(LEX) -s -ofp_lex.cc $(srcdir)/fp.lex
fp.cc fp.h: $(srcdir)/fp.y
$(YACC) --verbose -t -d -o fp.cc $(srcdir)/fp.y
mv fp.cc.h fp.h 2>/dev/null || mv fp.hh fp.h
fp.cc: $(srcdir)/fp.y
$(YACC) --verbose -t -p fp -d -o $@ $<
fp.h: fp.cc
mv fp.cc.h $@ 2>/dev/null || mv fp.hh $@
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
-1
View File
@@ -1,5 +1,4 @@
%name-prefix="fp"
%pure-parser
%parse-param {const char*file_path}
+2 -2
View File
@@ -2,7 +2,7 @@
// are not used here.
// target_design()
unusedFunction:stub.c:1770
unusedFunction:stub.c:1773
// target_query()
unusedFunction:stub.c:1834
unusedFunction:stub.c:1843
+1 -1
View File
@@ -380,7 +380,7 @@ static void show_lpm_divide(ivl_lpm_t net)
*/
static void show_lpm_cmp_eeq(ivl_lpm_t net)
{
const char*str;
const char*str = 0;
switch (ivl_lpm_type(net)) {
case IVL_LPM_CMP_EEQ:
str = "EEQ";
+2 -2
View File
@@ -1900,7 +1900,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
{
ivl_nexus_t nex = ivl_signal_nex(sig, 0);
unsigned idx, count = ivl_nexus_ptrs(nex);
unsigned long emitted = (unsigned long) ivl_nexus_get_private(nex);
unsigned long emitted = (uintptr_t) ivl_nexus_get_private(nex);
for (idx = 0; idx < count; idx += 1) {
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
@@ -1930,7 +1930,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
fprintf(vlog_out, "\n");
/* Increment the emitted constant count by one. */
ivl_nexus_set_private(nex,
(void *) ((unsigned long) ivl_nexus_get_private(nex) + 1U));
(void *) ((uintptr_t) ivl_nexus_get_private(nex) + 1U));
return;
}
/* We must find the constant in the nexus. */
+13 -3
View File
@@ -78,6 +78,7 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
{
unsigned has_undef = 0;
assert(nbits > 0);
/* Check for an undefined bit. */
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
if ((bits[idx] != '0') && (bits[idx] != '1')) {
@@ -91,8 +92,14 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
/* Emit as a binary constant. */
if (has_undef || (nbits < 2)) {
int start = nbits - 1;
char sbit = bits[start];
/* Trim extra leading bits. */
if (! is_signed && (sbit == '1')) sbit = ' ';
while (start && (sbit == bits[start-1])) start -= 1;
/* Print the trimmed value. */
fprintf(vlog_out, "b");
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
for (int idx = start; idx >= 0; idx -= 1) {
fprintf(vlog_out, "%c", bits[idx]);
}
/* Emit as a hex constant. */
@@ -152,9 +159,12 @@ void emit_number(const char *bits, unsigned nbits, unsigned is_signed,
vlog_errors += 1;
return;
} else if (rtype == -2) {
fprintf(vlog_out, "'bz");
fprintf(vlog_out, "%u'bz", nbits);
} else if (rtype == -3) {
fprintf(vlog_out, "'bx");
/* If this is a 32-bit wide constant then generate the
* undefined with integers to get a signed value. */
if (nbits == 32) fprintf(vlog_out, "1/0");
else fprintf(vlog_out, "%u'bx", nbits);
} else {
fprintf(vlog_out, "%"PRId32, value);
}
+1 -1
View File
@@ -942,7 +942,7 @@ static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt)
static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
{
const char *case_type;
const char *case_type = 0;
unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
switch (ivl_statement_type(stmt)) {
case IVL_ST_CASE:
+2 -2
View File
@@ -2,7 +2,7 @@
// are not used here.
// target_design()
unusedFunction:vvp.c:89
unusedFunction:vvp.c:149
// target_query()
unusedFunction:vvp.c:184
unusedFunction:vvp.c:246
-4
View File
@@ -26,10 +26,6 @@
# include <assert.h>
# include "ivl_alloc.h"
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
{
unsigned idx;
+46 -37
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -36,7 +36,6 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
if (ewidth < pwidth)
fprintf(vvp_out, " %%pad/u %u;\n", pwidth);
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", port, pwidth);
}
static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
@@ -45,54 +44,57 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
assert(ivl_signal_dimensions(port) == 0);
draw_eval_real(expr);
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
}
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
{
/* For now, treat bit2 variables as bit4 variables. */
function_argument_logic(port, expr);
}
static void function_argument_class(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_object(expr);
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
}
static void function_argument_darray(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_object(expr);
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
}
static void function_argument_string(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_string(expr);
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
}
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
static void draw_eval_function_argument(ivl_signal_t port, ivl_expr_t expr)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
switch (dtype) {
case IVL_VT_BOOL:
/* For now, treat bit2 variables as bit4 variables. */
case IVL_VT_LOGIC:
function_argument_logic(port, expr);
break;
case IVL_VT_REAL:
function_argument_real(port, expr);
break;
case IVL_VT_BOOL:
function_argument_bool(port, expr);
break;
case IVL_VT_CLASS:
function_argument_class(port, expr);
vvp_errors += draw_eval_object(expr);
break;
case IVL_VT_STRING:
function_argument_string(port, expr);
draw_eval_string(expr);
break;
case IVL_VT_DARRAY:
function_argument_darray(port, expr);
vvp_errors += draw_eval_object(expr);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
ivl_signal_basename(port), dtype);
assert(0);
}
}
static void draw_send_function_argument(ivl_signal_t port)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
switch (dtype) {
case IVL_VT_BOOL:
/* For now, treat bit2 variables as bit4 variables. */
case IVL_VT_LOGIC:
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n",
port, ivl_signal_width(port));
break;
case IVL_VT_REAL:
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
break;
case IVL_VT_CLASS:
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
break;
case IVL_VT_STRING:
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
break;
case IVL_VT_DARRAY:
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
@@ -111,13 +113,20 @@ static void draw_ufunc_preamble(ivl_expr_t expr)
fprintf(vvp_out, " %%alloc S_%p;\n", def);
}
/* evaluate the expressions and send the results to the
function ports. */
/* Evaluate the expressions and send the results to the
function ports. Do this in two passes - evaluate,
then send - this avoids the function input variables
being overwritten if the same (non-automatic) function
is called in one of the expressions. */
assert(ivl_expr_parms(expr) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(expr) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
draw_function_argument(port, ivl_expr_parm(expr, idx));
draw_eval_function_argument(port, ivl_expr_parm(expr, idx));
}
for (idx = ivl_expr_parms(expr) ; idx > 0 ; idx -= 1) {
ivl_signal_t port = ivl_scope_port(def, idx);
draw_send_function_argument(port);
}
/* Call the function */
-4
View File
@@ -23,10 +23,6 @@
# include <assert.h>
# include "ivl_alloc.h"
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
struct args_info {
char*text;
/* True ('s' or 'u' if this argument is a calculated vec4. */
+27 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,7 +28,6 @@ static int eval_darray_new(ivl_expr_t ex)
ivl_expr_t size_expr = ivl_expr_oper1(ex);
ivl_expr_t init_expr = ivl_expr_oper2(ex);
draw_eval_expr_into_integer(size_expr, size_reg);
clr_word(size_reg);
// The new function has a net_type that contains the details
// of the type.
@@ -39,6 +38,7 @@ static int eval_darray_new(ivl_expr_t ex)
assert(element_type);
switch (ivl_type_base(element_type)) {
int msb, lsb, wid;
case IVL_VT_REAL:
// REAL objects are not packable.
assert(ivl_type_packed_dimensions(element_type) == 0);
@@ -53,19 +53,30 @@ static int eval_darray_new(ivl_expr_t ex)
// bool objects are vectorable, but for now only support
// a single dimensions.
assert(ivl_type_packed_dimensions(element_type) == 1);
int msb = ivl_type_packed_msb(element_type, 0);
int lsb = ivl_type_packed_lsb(element_type, 0);
int wid = msb>=lsb? msb - lsb : lsb - msb;
msb = ivl_type_packed_msb(element_type, 0);
lsb = ivl_type_packed_lsb(element_type, 0);
wid = msb>=lsb? msb - lsb : lsb - msb;
wid += 1;
fprintf(vvp_out, " %%new/darray %u, \"%sb%d\";\n", size_reg,
ivl_type_signed(element_type) ? "s" : "", wid);
break;
case IVL_VT_LOGIC:
// logic objects are vectorable, but for now only support
// a single dimensions.
assert(ivl_type_packed_dimensions(element_type) == 1);
msb = ivl_type_packed_msb(element_type, 0);
lsb = ivl_type_packed_lsb(element_type, 0);
wid = msb>=lsb? msb - lsb : lsb - msb;
wid += 1;
fprintf(vvp_out, " %%new/darray %u, \"%sv%d\";\n", size_reg,
ivl_type_signed(element_type) ? "s" : "", wid);
break;
default:
assert(0);
break;
}
clr_word(size_reg);
if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) {
unsigned idx;
@@ -109,12 +120,15 @@ static int eval_darray_new(ivl_expr_t ex)
unsigned wid;
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
wid = width_of_packed_type(element_type);
draw_eval_vec4(init_expr);
resize_vec4_wid(init_expr, wid);
for (idx = 0 ; idx < cnt ; idx += 1) {
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
draw_eval_vec4(init_expr);
fprintf(vvp_out, " %%parti/%c %u, %ld, 6;\n",
ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid);
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1);
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
fprintf(vvp_out, " %%pop/vec4 1;\n");
}
break;
case IVL_VT_REAL:
@@ -187,11 +201,12 @@ static int eval_object_property(ivl_expr_t expr)
static int eval_object_shallowcopy(ivl_expr_t ex)
{
int errors = 0;
ivl_expr_t dest = ivl_expr_oper1(ex);
ivl_expr_t src = ivl_expr_oper2(ex);
draw_eval_object(dest);
draw_eval_object(src);
errors += draw_eval_object(dest);
errors += draw_eval_object(src);
/* The %scopy opcode pops the top of the object stack as the
source object, and shallow-copies it to the new top, the
@@ -199,7 +214,7 @@ static int eval_object_shallowcopy(ivl_expr_t ex)
the stack. */
fprintf(vvp_out, " %%scopy;\n");
return 0;
return errors;
}
static int eval_object_signal(ivl_expr_t expr)
+29 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2013-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -643,16 +643,16 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr)
// the stack and replace it with the result of the shift.
switch (ivl_expr_opcode(expr)) {
case 'l': /* << */
fprintf(vvp_out, " %%shiftl %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftl %d;\n", use_index_reg);
break;
case 'r': /* >> */
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
break;
case 'R': /* >>> */
if (ivl_expr_signed(le))
fprintf(vvp_out, " %%shiftr/s %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftr/s %d;\n", use_index_reg);
else
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
break;
default:
assert(0);
@@ -790,10 +790,10 @@ static void draw_concat_number_vec4(ivl_expr_t expr, int as_concati)
if (accum) {
if (count_pushi) {
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %u;\n",
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %d;\n",
val0, valx, accum);
} else {
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %u;\n",
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %d;\n",
val0, valx, accum);
}
}
@@ -807,16 +807,27 @@ static void draw_concat_vec4(ivl_expr_t expr)
/* This is the number of expressions that go into the
concatenation. */
unsigned num_sube = ivl_expr_parms(expr);
unsigned sub_idx;
unsigned sub_idx = 0;
ivl_expr_t sube;
assert(num_sube > 0);
/* Start with the most-significant bits. */
draw_eval_vec4(ivl_expr_parm(expr, 0));
sube = ivl_expr_parm(expr, sub_idx);
draw_eval_vec4(sube);
/* Evaluate, but skip any zero replication expressions at the
* head of this concatenation. */
while ((ivl_expr_type(sube) == IVL_EX_CONCAT) &&
(ivl_expr_repeat(sube) == 0)) {
fprintf(vvp_out, " %%pop/vec4 1; skip zero replication\n");
sub_idx += 1;
sube = ivl_expr_parm(expr, sub_idx);
draw_eval_vec4(sube);
}
for (sub_idx = 1 ; sub_idx < num_sube ; sub_idx += 1) {
for ( sub_idx += 1 ; sub_idx < num_sube ; sub_idx += 1) {
/* Concatenate progressively lower parts. */
ivl_expr_t sube = ivl_expr_parm(expr, sub_idx);
sube = ivl_expr_parm(expr, sub_idx);
/* Special case: The next expression is a NUMBER that
can be concatenated using %concati/vec4
@@ -827,6 +838,13 @@ static void draw_concat_vec4(ivl_expr_t expr)
}
draw_eval_vec4(sube);
/* Evaluate, but skip any zero replication expressions in the
* rest of this concatenation. */
if ((ivl_expr_type(sube) == IVL_EX_CONCAT) &&
(ivl_expr_repeat(sube) == 0)) {
fprintf(vvp_out, " %%pop/vec4 1; skip zero replication\n");
continue;
}
fprintf(vvp_out, " %%concat/vec4; draw_concat_vec4\n");
}
-4
View File
@@ -23,10 +23,6 @@
# include <assert.h>
# include "ivl_alloc.h"
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
static ivl_signal_t find_path_source_port(ivl_delaypath_t path)
{
unsigned idx;
+33 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,11 +22,6 @@
# include <assert.h>
# include <stdlib.h>
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
/*
* These functions handle the blocking assignment. Use the %set
* instruction to perform the actual assignment, and calculate any
@@ -143,7 +138,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
draw_eval_vec4(part_off_ex);
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.part_select_dynamic.x_flag);
fprintf(vvp_out, " %%dup/vec4;\n");
fprintf(vvp_out, " %%ix/vec4 %u;\n", slice->u_.part_select_dynamic.word_idx_reg);
fprintf(vvp_out, " %%ix/vec4 %d;\n", slice->u_.part_select_dynamic.word_idx_reg);
fprintf(vvp_out, " %%part/u %u;\n", wid);
} else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {
@@ -167,7 +162,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
slice->u_.memory_word_dynamic.x_flag = allocate_flag();
draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg);
fprintf(vvp_out, " %%flag_mov %d, 4;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%load/vec4a v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
} else {
@@ -263,7 +258,7 @@ static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
break;
case SLICE_MEMORY_WORD_DYNAMIC:
fprintf(vvp_out, " %%flag_mov 4, %d;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%flag_mov 4, %u;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%store/vec4a v%p, %d, 0;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
clr_flag(slice->u_.memory_word_dynamic.x_flag);
@@ -381,7 +376,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
/* Note that flag4 is set by the eval above. */
assert(lsig);
if (ivl_signal_type(lsig)==IVL_SIT_UWIRE) {
fprintf(vvp_out, " %%force/vec4/off v%p_0, %u;\n",
fprintf(vvp_out, " %%force/vec4/off v%p_0, %d;\n",
lsig, offset_index);
} else {
fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n",
@@ -397,7 +392,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
assert(!lsig);
ivl_type_t sub_type = draw_lval_expr(nest);
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
fprintf(vvp_out, " %%store/prop/v %u, %u;\n",
fprintf(vvp_out, " %%store/prop/v %d, %u;\n",
ivl_lval_property_idx(lval), lwid);
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
@@ -444,11 +439,34 @@ static int show_stmt_assign_vector(ivl_statement_t net)
fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
} else if (ivl_expr_value(rval) == IVL_VT_STRING) {
/* Special case: vector to string casting */
/* Special case: string to vector casting */
ivl_lval_t lval = ivl_stmt_lval(net, 0);
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
ivl_expr_signal(rval), ivl_lval_sig(lval));
if (slices) free(slices);
return 0;
} else if (ivl_expr_value(rval) == IVL_VT_DARRAY) {
/* Special case: dynamic array to vector casting */
ivl_lval_t lval = ivl_stmt_lval(net, 0);
void*rval_addr = NULL;
/* Even more special case: function call returning dynamic array */
if(ivl_expr_type(rval) == IVL_EX_UFUNC) {
rval_addr = ivl_scope_port(ivl_expr_def(rval), 0);
draw_ufunc_object(rval);
/* We do not need to store the result, it is going to be
converted to vector quite soon. */
fprintf(vvp_out, " %%pop/obj 1, 0; drop the result\n");
} else {
rval_addr = ivl_expr_signal(rval);
}
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
rval_addr, ivl_lval_sig(lval));
if (slices) free(slices);
return 0;
} else {
@@ -532,8 +550,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
break;
}
if (slices)
free(slices);
if (slices) free(slices);
return 0;
}
@@ -868,7 +885,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
expression to the assignment is of an entire
array object. */
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
draw_eval_object(rval);
errors += draw_eval_object(rval);
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
@@ -882,7 +899,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
/* The property is a class object. */
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
draw_eval_object(rval);
errors += draw_eval_object(rval);
if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
+5 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -59,7 +59,10 @@ __inline__ static void draw_execute_header(ivl_design_t des)
{
const char*cp = ivl_design_flag(des, "VVP_EXECUTABLE");
if (cp) {
fprintf(vvp_out, "#! %s\n", cp);
const char *extra_args = ivl_design_flag(des, "VVP_EXTRA_ARGS");
if (!extra_args)
extra_args = "";
fprintf(vvp_out, "#! %s%s\n", cp, extra_args);
#if !defined(__MINGW32__)
fchmod(fileno(vvp_out), 0755);
#endif
-5
View File
@@ -23,11 +23,6 @@
# include "ivl_target.h"
# include <stdio.h>
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
extern int debug_draw;
/*
+44 -31
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -21,10 +21,7 @@
# include <string.h>
# include <assert.h>
# include <stdlib.h>
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
# include <stdbool.h>
static int show_statement(ivl_statement_t net, ivl_scope_t sscope);
@@ -114,14 +111,12 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
ivl_expr_t part_off_ex,
unsigned nevents)
{
unsigned skip_assign = transient_id++;
int word_ix_reg = 3;
int part_off_reg = 0;
int delay_index;
unsigned long part_off = 0;
int error_flag = allocate_flag();
fprintf(vvp_out, " %%flag_set/imm %d, 0;\n", error_flag);
/* Figure the constant part offset, if possible. If we can do
so, then forget about the expression and use the calculated
@@ -143,11 +138,13 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
/* Calculate array word index into word index register */
draw_eval_expr_into_integer(word_ix, word_ix_reg);
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
if (part_off_ex) {
part_off_reg = allocate_word();
/* Save the index calculation error flag to a global. */
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
/* Add the error state of the part select to the global. */
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
} else if (part_off != 0) {
@@ -158,26 +155,35 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
part_off_reg, part_off);
}
/* Calculated delay... */
if (dexp != 0) {
/* Calculated delay... */
delay_index = allocate_word();
/* If needed save the index calculation error flag. */
if (! part_off_ex) {
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
}
draw_eval_expr_into_integer(dexp, delay_index);
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
if (word_ix_reg != 3) {
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
clr_word(word_ix_reg);
}
/* Restore the error state since an undefined delay is okay. */
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
lsig, part_off_reg, delay_index);
clr_word(delay_index);
/* Event control delay... */
} else if (nevents != 0) {
/* Event control delay... */
/* If needed use the global error state. */
if (part_off_ex) {
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
}
fprintf(vvp_out, " %%assign/vec4/a/e v%p, %d;\n", lsig, part_off_reg);
/* Constant delay... */
} else {
/* Constant delay... */
unsigned long low_d = delay % UINT64_C(0x100000000);
unsigned long hig_d = delay / UINT64_C(0x100000000);
@@ -185,15 +191,18 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
fprintf(vvp_out, " %%ix/load %d, %lu, %lu; Constant delay\n",
delay_index, low_d, hig_d);
if (word_ix_reg != 3) {
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
clr_word(word_ix_reg);
}
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %u;\n",
/* If needed use the global error state. */
if (part_off_ex) {
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
}
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
lsig, part_off_reg, delay_index);
clr_word(delay_index);
}
fprintf(vvp_out, "t_%u ;\n", skip_assign);
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
clr_flag(error_flag);
@@ -1043,7 +1052,14 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
assert(ivl_signal_dimensions(rsig) != 0);
assert(number_is_immediate(rword_idx, IMM_WID, 0));
if (!number_is_immediate(rword_idx, IMM_WID, 0)) {
fprintf(stderr, "%s:%u: tgt-vvp sorry: procedural continuous "
"assignments are not yet fully supported. The RHS of "
"this assignment will only be evaluated once, at the "
"time the assignment statement is executed.\n",
ivl_stmt_file(net), ivl_stmt_lineno(net));
return;
}
/* An out-of-range or undefined index will have been
converted to a canonical offset of 1'bx. Skip the
assignment in this case. */
@@ -1321,7 +1337,7 @@ static int show_stmt_do_while(ivl_statement_t net, ivl_scope_t sscope)
the result. If the expression evaluates to true, then
branch to the top label. */
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u;\n",
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %d;\n",
thread_count, top_label, use_flag);
clr_flag(use_flag);
@@ -1665,7 +1681,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
the result. If the expression evaluates to false, then
branch to the out label. */
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %u;\n",
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %d;\n",
thread_count, out_label, use_flag);
clr_flag(use_flag);
@@ -1696,19 +1712,16 @@ static int show_delete_method(ivl_statement_t net)
return 0;
}
static int show_push_frontback_method(ivl_statement_t net)
static int show_push_frontback_method(ivl_statement_t net, bool is_front)
{
const char*stmt_name = ivl_stmt_name(net);
show_stmt_file_line(net, "queue: push_back");
const char*type_code = "?";
if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0)
const char*type_code;
if (is_front) {
show_stmt_file_line(net, "queue: push_front");
type_code = "qf";
else if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0)
} else {
show_stmt_file_line(net, "queue: push_back");
type_code = "qb";
else
type_code = "??";
}
unsigned parm_count = ivl_stmt_parm_count(net);
if (parm_count != 2)
@@ -1750,10 +1763,10 @@ static int show_system_task_call(ivl_statement_t net)
return show_delete_method(net);
if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0)
return show_push_frontback_method(net);
return show_push_frontback_method(net, true);
if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0)
return show_push_frontback_method(net);
return show_push_frontback_method(net, false);
show_stmt_file_line(net, "System task call.");
+8 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -1737,10 +1737,14 @@ static void draw_lpm_ff(ivl_lpm_t net)
assert(ivl_lpm_sync_set(net) == 0);
if (ivl_lpm_async_clr(net)) {
assert(! ivl_lpm_async_set(net));
if (ivl_lpm_async_set(net)) {
fprintf(stderr, "%s:%u:vvp.tgt: sorry: No support for a D-ff "
"with both an async. set and clear.\n",
ivl_lpm_file(net), ivl_lpm_lineno(net));
vvp_errors += 1;
}
fprintf(vvp_out, "L_%p .dff/aclr ", net);
} else if (ivl_lpm_async_set(net)) {
assert(! ivl_lpm_async_clr(net));
fprintf(vvp_out, "L_%p .dff/aset ", net);
} else {
fprintf(vvp_out, "L_%p .dff ", net);
@@ -2328,7 +2332,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
draw_task_definition(net);
if (ivl_scope_type(net) == IVL_SCT_FUNCTION)
draw_func_definition(net);
vvp_errors += draw_func_definition(net);
ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
return 0;
+1 -1
View File
@@ -1,6 +1,6 @@
#norootforbuild
#
%define rev_date 20141205
%define rev_date 20150513
# Normally, the suff-ix is %nil, meaning the suffix is to not be used.
# But if the builder wants to make a suffixed package, he may set this
# to a value (i.e. -test) to cause suffixes to be put in all the right
+3 -1
View File
@@ -780,7 +780,9 @@ ostream& operator<< (ostream&o, const verinum&v)
/* If the number is fully defined (no x or z) then print it
out as a decimal number. */
if (v.is_defined() && v.len() <= 8*sizeof(long)) {
unsigned dec_len = 8*sizeof(int); /* avoid 32/64 bit differences. */
if (! v.has_sign()) dec_len -= 1; /* an unsigned number. */
if (v.is_defined() && v.len() <= dec_len) {
if (v.has_sign())
o << "'sd" << v.as_long();
else
+40 -1
View File
@@ -28,7 +28,7 @@ using namespace std;
Architecture::Architecture(perm_string name, const ActiveScope&ref,
list<Architecture::Statement*>&s)
: Scope(ref), name_(name)
: Scope(ref), name_(name), cur_component_(NULL)
{
statements_.splice(statements_.end(), s);
}
@@ -39,6 +39,34 @@ Architecture::~Architecture()
ScopeBase::cleanup();
}
bool Architecture::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const
{
if(Scope::find_constant(by_name, typ, exp))
return true;
// Check generics in components
if(cur_component_) {
std::map<perm_string,ComponentBase*>::const_iterator c = new_components_.find(cur_component_->component_name());
if(c == new_components_.end())
c = old_components_.find(cur_component_->component_name());
assert(c != old_components_.end());
ComponentBase*base = c->second;
const InterfacePort*generic = base->find_generic(by_name);
if(!generic)
return false; // apparently there is no such generic in the component
Expression*e = cur_component_->find_generic_map(by_name);
typ = generic->type;
exp = e ? e : generic->expr;
return true;
}
return false;
}
void Architecture::push_genvar_type(perm_string gname, const VType*gtype)
{
genvar_type_t tmp;
@@ -191,6 +219,17 @@ ComponentInstantiation::~ComponentInstantiation()
}
}
Expression*ComponentInstantiation::find_generic_map(perm_string by_name) const
{
map<perm_string,Expression*>::const_iterator p = generic_map_.find(by_name);
if(p == generic_map_.end())
return NULL;
return p->second;
}
ProcessStatement::ProcessStatement(perm_string iname,
std::list<Expression*>*sensitivity_list,
std::list<SequentialStmt*>*statements_list)
+14 -5
View File
@@ -25,7 +25,7 @@
# include <list>
# include <map>
class ComponentBase;
class ComponentInstantiation;
class Entity;
class Expression;
class ExpName;
@@ -54,10 +54,6 @@ class Architecture : public Scope, public LineInfo {
virtual int elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, Entity*ent, Architecture*arc);
virtual void dump(ostream&out, int indent = 0) const;
private:
private: // Not implemented
};
public:
@@ -69,6 +65,10 @@ class Architecture : public Scope, public LineInfo {
perm_string get_name() const { return name_; }
// Sets the currently processed component (to be able to reach its parameters).
void set_cur_component(ComponentInstantiation*component) { cur_component_ = component; }
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const;
// Elaborate this architecture in the context of the given entity.
int elaborate(Entity*entity);
@@ -110,6 +110,9 @@ class Architecture : public Scope, public LineInfo {
};
std::list<genvar_emit_t> genvar_emit_stack_;
// Currently processed component (or NULL if none).
ComponentInstantiation*cur_component_;
private: // Not implemented
};
@@ -198,6 +201,12 @@ class ComponentInstantiation : public Architecture::Statement {
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
virtual void dump(ostream&out, int indent =0) const;
// Returns the expression that initializes a generic (or NULL if not found).
Expression*find_generic_map(perm_string by_name) const;
inline perm_string instance_name() const { return iname_; }
inline perm_string component_name() const { return cname_; }
private:
perm_string iname_;
perm_string cname_;
+7 -4
View File
@@ -92,15 +92,16 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
return 1;
}
arc->set_cur_component(this);
for (map<perm_string,Expression*>::const_iterator cur = generic_map_.begin()
; cur != generic_map_.end() ; ++cur) {
// check if generic from component instantiation
// exists in the component declaration
const InterfacePort*iparm = base->find_generic(cur->first);
if (iparm == 0) {
cerr << get_fileline() << ": error: No generic " << cur->first
cerr << get_fileline() << ": warning: No generic " << cur->first
<< " in component " << cname_ << "." << endl;
errors += 1;
continue;
}
@@ -134,6 +135,8 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
cur->second->elaborate_expr(ent, arc, iport->type);
}
arc->set_cur_component(NULL);
return errors;
}
@@ -368,9 +371,9 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
return errors;
}
for (list<Expression*>::const_iterator cur = rval_.begin()
for (list<Expression*>::iterator cur = rval_.begin()
; cur != rval_.end() ; ++cur) {
(*cur)->elaborate_expr(ent, arc, lval_type);
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
}
return errors;
+12 -6
View File
@@ -70,12 +70,12 @@ int Architecture::emit(ostream&out, Entity*entity)
// of the full definition.
typedef_context_t typedef_ctx;
for (map<perm_string,const VType*>::iterator cur = use_types_.begin()
; cur != use_types_.end() ; ++cur) {
//for (map<perm_string,const VType*>::iterator cur = use_types_.begin()
//; cur != use_types_.end() ; ++cur) {
if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
errors += def->emit_typedef(out, typedef_ctx);
}
//if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
//errors += def->emit_typedef(out, typedef_ctx);
//}
for (map<perm_string,const VType*>::iterator cur = cur_types_.begin()
; cur != cur_types_.end() ; ++cur) {
@@ -103,7 +103,9 @@ int Architecture::emit(ostream&out, Entity*entity)
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) {
errors += cur->second->emit_package(out);
// Do not emit unbounded functions, we will just need fixed instances later
if(!cur->second->unbounded())
errors += cur->second->emit_package(out);
}
for (list<Architecture::Statement*>::iterator cur = statements_.begin()
@@ -146,6 +148,8 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
const char*comma = "";
int errors = 0;
arc->set_cur_component(this);
out << cname_;
if (! generic_map_.empty()) {
out << " #(";
@@ -175,6 +179,8 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
}
out << ");" << endl;
arc->set_cur_component(NULL);
return errors;
}
+2 -1
View File
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014 CERN / Maciej Suminski (maciej.suminski@cern.ch)
* Copyright (c) 2014 CERN
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
+2 -1
View File
@@ -92,7 +92,8 @@ int Entity::elaborate_generic_exprs_()
for (vector<InterfacePort*>::const_iterator cur = parms_.begin()
; cur != parms_.end() ; ++cur) {
InterfacePort*curp = *cur;
curp->expr->elaborate_expr(this, 0, curp->type);
if(curp->expr)
curp->expr->elaborate_expr(this, 0, curp->type);
}
return errors;
}
+5 -3
View File
@@ -50,9 +50,11 @@ int Entity::emit(ostream&out)
const InterfacePort*curp = *cur;
if (cur != parms_.begin())
out << ", ";
out << "parameter \\" << curp->name << " = ";
ivl_assert(*this, curp->expr);
errors += curp->expr->emit(out, this, 0);
out << "parameter \\" << curp->name << " ";
if(curp->expr) {
out << "= ";
errors += curp->expr->emit(out, this, 0);
}
}
out << ") ";
}
+51 -23
View File
@@ -18,40 +18,68 @@
*/
# include "entity.h"
# include "expression.h"
using namespace std;
void ComponentBase::write_to_stream(ostream&fd) const
{
fd << " component " << name_ << " is" << endl;
fd << " port(" << endl;
vector<InterfacePort*>::const_iterator cur = ports_.begin();
while (cur != ports_.end()) {
InterfacePort*item = *cur;
++cur;
if(!parms_.empty()) {
fd << " generic(" << endl;
fd << " " << item->name << " : ";
switch (item->mode) {
case PORT_NONE:
fd << "???? ";
break;
case PORT_IN:
fd << "in ";
break;
case PORT_OUT:
fd << "out ";
break;
}
for(vector<InterfacePort*>::const_iterator it = parms_.begin();
it != parms_.end(); ++it) {
const InterfacePort*parm = *it;
item->type->write_to_stream(fd);
if(it != parms_.begin())
fd << ";";
if (cur != ports_.end())
fd << ";" << endl;
else
fd << endl;
fd << " " << parm->name << " : ";
parm->type->write_to_stream(fd);
if(parm->expr) {
fd << " := ";
parm->expr->write_to_stream(fd);
}
fd << endl;
}
fd << " );" << endl;
}
fd << " );" << endl;
if(!ports_.empty()) {
fd << " port(" << endl;
vector<InterfacePort*>::const_iterator cur = ports_.begin();
while (cur != ports_.end()) {
InterfacePort*item = *cur;
++cur;
fd << " " << item->name << " : ";
switch (item->mode) {
case PORT_NONE:
fd << "???? ";
break;
case PORT_IN:
fd << "in ";
break;
case PORT_OUT:
fd << "out ";
break;
}
item->type->write_to_stream(fd);
if (cur != ports_.end())
fd << ";" << endl;
else
fd << endl;
}
fd << " );" << endl;
}
fd << " end component;" << endl;
}
+147 -7
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2014 / Stephen Williams (steve@icarus.com),
* Maciej Suminski (maciej.suminski@cern.ch)
* Copyright CERN 2012-2015 / Stephen Williams (steve@icarus.com),
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,6 +20,7 @@
*/
# include "expression.h"
# include "subprogram.h"
# include "parse_types.h"
# include "scope.h"
# include <iostream>
@@ -63,6 +64,11 @@ ExpAttribute::~ExpAttribute()
delete base_;
}
Expression*ExpAttribute::clone() const
{
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
}
ExpBinary::ExpBinary(Expression*op1, Expression*op2)
: operand1_(op1), operand2_(op2)
{
@@ -112,6 +118,23 @@ ExpAggregate::~ExpAggregate()
delete elements_[idx];
}
Expression* ExpAggregate::clone() const
{
std::list<element_t*>*new_elements = NULL;
if(!elements_.empty()) {
new_elements = new std::list<element_t*>();
for(std::vector<element_t*>::const_iterator it = elements_.begin();
it != elements_.end(); ++it) {
new_elements->push_back(new element_t(**it));
}
}
assert(aggregate_.empty()); // cloning should not happen after elab
return new ExpAggregate(new_elements);
}
ExpAggregate::choice_t::choice_t(Expression*exp)
: expr_(exp)
{
@@ -126,6 +149,15 @@ ExpAggregate::choice_t::choice_t(prange_t*rang)
{
}
ExpAggregate::choice_t::choice_t(const choice_t&other)
{
if(Expression*e = other.expr_.get())
expr_.reset(e->clone());
if(other.range_.get())
range_.reset(new prange_t(*other.range_.get()));
}
ExpAggregate::choice_t::~choice_t()
{
}
@@ -159,6 +191,18 @@ ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
}
}
ExpAggregate::element_t::element_t(const ExpAggregate::element_t&other)
{
fields_.reserve(other.fields_.size());
for(std::vector<choice_t*>::const_iterator it = other.fields_.begin();
it != other.fields_.end(); ++it) {
fields_.push_back(*it);
}
val_ = other.val_->clone();
}
ExpAggregate::element_t::~element_t()
{
for (size_t idx = 0 ; idx < fields_.size() ; idx += 1)
@@ -235,12 +279,46 @@ ExpConditional::~ExpConditional()
}
}
Expression*ExpConditional::clone() const
{
std::list<Expression*>*new_true_clause = NULL;
if(!true_clause_.empty()) {
new_true_clause = new std::list<Expression*>();
for(std::list<Expression*>::const_iterator it = true_clause_.begin();
it != true_clause_.end(); ++it) {
new_true_clause->push_back((*it)->clone());
}
}
std::list<else_t*>*new_else_clause = NULL;
if(!else_clause_.empty()) {
new_else_clause = new std::list<else_t*>();
for(std::list<else_t*>::const_iterator it = else_clause_.begin();
it != else_clause_.end(); ++it) {
new_else_clause->push_back(new else_t(**it));
}
}
return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause);
}
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
: cond_(cond)
{
if (tru) true_clause_.splice(true_clause_.end(), *tru);
}
ExpConditional::else_t::else_t(const else_t&other)
{
cond_ = other.cond_->clone();
for(std::list<Expression*>::const_iterator it = other.true_clause_.begin();
it != other.true_clause_.end(); ++it) {
true_clause_.push_back((*it)->clone());
}
}
ExpConditional::else_t::~else_t()
{
delete cond_;
@@ -283,6 +361,27 @@ ExpFunc::~ExpFunc()
delete argv_[idx];
}
Expression*ExpFunc::clone() const {
std::list<Expression*>*new_args = NULL;
if(!argv_.empty()) {
new_args = new std::list<Expression*>();
for(std::vector<Expression*>::const_iterator it = argv_.begin();
it != argv_.end(); ++it)
new_args->push_back((*it)->clone());
}
ExpFunc*f = new ExpFunc(name_, new_args);
f->def_ = def_;
return f;
}
const VType* ExpFunc::func_ret_type() const
{
return def_ ? def_->peek_return_type() : NULL;
}
ExpInteger::ExpInteger(int64_t val)
: value_(val)
{
@@ -351,11 +450,6 @@ ExpName::~ExpName()
delete index_;
}
const char* ExpName::name() const
{
return name_;
}
bool ExpName::symbolic_compare(const Expression*that) const
{
const ExpName*that_name = dynamic_cast<const ExpName*> (that);
@@ -386,6 +480,28 @@ void ExpName::set_range(Expression*msb, Expression*lsb)
lsb_ = lsb;
}
int ExpName::index_t::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "(";
if(idx_ && size_) {
errors += idx_->emit(out, ent, scope);
out << "*";
errors += size_->emit(out, ent, scope);
}
if(offset_) {
if(idx_ && size_)
out << "+";
errors += offset_->emit(out, ent, scope);
}
out << ")";
return errors;
}
ExpRelation::ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2)
: ExpBinary(op1, op2), fun_(ty)
{
@@ -395,6 +511,11 @@ ExpRelation::~ExpRelation()
{
}
ExpShift::ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2)
: ExpBinary(op1, op2), shift_(op)
{
}
ExpString::ExpString(const char* value)
: value_(strlen(value))
{
@@ -423,3 +544,22 @@ ExpUNot::ExpUNot(Expression*op1)
ExpUNot::~ExpUNot()
{
}
ExpCast::ExpCast(Expression*base, const VType*type) :
base_(base), type_(type)
{
}
ExpCast::~ExpCast()
{
}
ExpNew::ExpNew(Expression*size) :
size_(size)
{
}
ExpNew::~ExpNew()
{
delete size_;
}
+276 -112
View File
@@ -2,8 +2,8 @@
#define IVL_expression_H
/*
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2014 / Stephen Williams (steve@icarus.com),
* Maciej Suminski (maciej.suminski@cern.ch)
* Copyright CERN 2015 / Stephen Williams (steve@icarus.com),
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -31,13 +31,11 @@
class prange_t;
class Entity;
class Architecture;
class ScopeBase;
class Subprogram;
class VType;
class VTypeArray;
class VTypePrimitive;
class ExpName;
/*
@@ -51,18 +49,21 @@ class Expression : public LineInfo {
Expression();
virtual ~Expression() =0;
// Returns a deep copy of the expression.
virtual Expression*clone() const =0;
// This virtual method handles the special case of elaborating
// an expression that is the l-value of a sequential variable
// assignment. This generates an error for most cases, but
// expressions that are valid l-values return 0 and set any
// flags needed to indicate their status as writable variables.
virtual int elaborate_lval(Entity*ent, Architecture*arc,
virtual int elaborate_lval(Entity*ent, ScopeBase*scope,
bool is_sequ);
// This virtual method probes the expression to get the most
// constrained type for the expression. For a given instance,
// this may be called before the elaborate_expr method.
virtual const VType*probe_type(Entity*ent, Architecture*arc) const;
virtual const VType*probe_type(Entity*ent, ScopeBase*scope) const;
// The fit_type virtual method is used by the ExpConcat class
// to probe the type of operands. The atype argument is the
@@ -70,13 +71,13 @@ class Expression : public LineInfo {
// returns its type as interpreted in this context. Really,
// this is mostly about helping aggregate expressions within
// concatenations to figure out their type.
virtual const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
virtual const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
// This virtual method elaborates an expression. The ltype is
// the type of the lvalue expression, if known, and can be
// used to calculate the type for the expression being
// elaborated.
virtual int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
virtual int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
// Return the type that this expression would be if it were an
// l-value. This should only be called after elaborate_lval is
@@ -86,12 +87,12 @@ class Expression : public LineInfo {
// This virtual method writes a VHDL-accurate representation
// of this expression to the designated stream. This is used
// for writing parsed types to library files.
virtual void write_to_stream(std::ostream&fd) =0;
virtual void write_to_stream(std::ostream&fd) const =0;
// The emit virtual method is called by architecture emit to
// output the generated code for the expression. The derived
// class fills in the details of what exactly happened.
virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0;
virtual int emit(ostream&out, Entity*ent, ScopeBase*scope) =0;
// The emit_package virtual message is similar, but is called
// in a package context and to emit SV packages.
@@ -102,8 +103,7 @@ class Expression : public LineInfo {
// argument if the evaluation works, or return false if it
// cannot be done.
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const;
virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
// The symbolic compare returns true if the two expressions
// are equal without actually calculating the value.
@@ -134,6 +134,13 @@ class Expression : public LineInfo {
Expression& operator = (const Expression&);
};
/*
* Checks before cloning if the other expression actually exists (!=NULL).
*/
static inline Expression*safe_clone(const Expression*other) {
return (other ? other->clone() : NULL);
}
static inline void FILE_NAME(Expression*tgt, const LineInfo*src)
{
tgt->set_line(*src);
@@ -150,13 +157,15 @@ class ExpUnary : public Expression {
ExpUnary(Expression*op1);
virtual ~ExpUnary() =0;
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
inline const Expression*peek_operand() const { return operand1_; }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
protected:
inline void write_to_stream_operand1(std::ostream&fd)
inline void write_to_stream_operand1(std::ostream&fd) const
{ operand1_->write_to_stream(fd); }
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
void dump_operand1(ostream&out, int indent = 0) const;
private:
@@ -173,23 +182,23 @@ class ExpBinary : public Expression {
ExpBinary(Expression*op1, Expression*op2);
virtual ~ExpBinary() =0;
const Expression* peek_operand1(void) const { return operand1_; }
const Expression* peek_operand2(void) const { return operand2_; }
inline const Expression* peek_operand1(void) const { return operand1_; }
inline const Expression* peek_operand2(void) const { return operand2_; }
const VType*probe_type(Entity*ent, Architecture*arc) const;
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
protected:
int elaborate_exprs(Entity*, Architecture*, const VType*);
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
int elaborate_exprs(Entity*, ScopeBase*, const VType*);
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope);
bool eval_operand1(ScopeBase*scope, int64_t&val) const;
bool eval_operand2(ScopeBase*scope, int64_t&val) const;
inline void write_to_stream_operand1(std::ostream&out)
inline void write_to_stream_operand1(std::ostream&out) const
{ operand1_->write_to_stream(out); }
inline void write_to_stream_operand2(std::ostream&out)
inline void write_to_stream_operand2(std::ostream&out) const
{ operand2_->write_to_stream(out); }
void dump_operands(ostream&out, int indent = 0) const;
@@ -219,6 +228,9 @@ class ExpAggregate : public Expression {
explicit choice_t(perm_string name);
// discreate_range choice
explicit choice_t(prange_t*ran);
choice_t(const choice_t&other);
~choice_t();
// true if this represents an "others" choice
@@ -235,11 +247,17 @@ class ExpAggregate : public Expression {
std::auto_ptr<Expression>expr_;
std::auto_ptr<prange_t> range_;
private: // not implemented
choice_t(const choice_t&);
choice_t& operator= (const choice_t&);
};
struct choice_element {
choice_element() : choice(), expr() {}
choice_element(const choice_element&other) {
choice = other.choice ? new choice_t(*other.choice) : NULL;
expr = safe_clone(other.expr);
}
choice_t*choice;
Expression*expr;
bool alias_flag;
@@ -251,6 +269,7 @@ class ExpAggregate : public Expression {
class element_t {
public:
explicit element_t(std::list<choice_t*>*fields, Expression*val);
element_t(const element_t&other);
~element_t();
size_t count_choices() const { return fields_.size(); }
@@ -265,7 +284,6 @@ class ExpAggregate : public Expression {
std::vector<choice_t*>fields_;
Expression*val_;
private: // not implemented
element_t(const element_t&);
element_t& operator = (const element_t&);
};
@@ -273,19 +291,20 @@ class ExpAggregate : public Expression {
ExpAggregate(std::list<element_t*>*el);
~ExpAggregate();
Expression*clone() const;
const VType*probe_type(Entity*ent, Architecture*arc) const;
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype);
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype);
int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype);
int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
int elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
int emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
int emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
private:
// This is the elements as directly parsed.
@@ -305,9 +324,13 @@ class ExpArithmetic : public ExpBinary {
ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2);
~ExpArithmetic();
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const {
return new ExpArithmetic(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
@@ -324,16 +347,18 @@ class ExpAttribute : public Expression {
ExpAttribute(ExpName*base, perm_string name);
~ExpAttribute();
Expression*clone() const;
inline perm_string peek_attribute() const { return name_; }
inline const ExpName* peek_base() const { return base_; }
const VType*probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Some attributes can be evaluated at compile time
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
private:
@@ -345,12 +370,15 @@ class ExpBitstring : public Expression {
public:
explicit ExpBitstring(const char*);
ExpBitstring(const ExpBitstring&other) : Expression() { value_ = other.value_; }
~ExpBitstring();
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpBitstring(*this); }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
@@ -362,19 +390,22 @@ class ExpCharacter : public Expression {
public:
ExpCharacter(char val);
ExpCharacter(const ExpCharacter&other) : Expression() { value_ = other.value_; }
~ExpCharacter();
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpCharacter(*this); }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
char value() const { return value_; }
private:
int emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc,
int emit_primitive_bit_(ostream&out, Entity*ent, ScopeBase*scope,
const VTypePrimitive*etype);
private:
@@ -387,17 +418,21 @@ class ExpConcat : public Expression {
ExpConcat(Expression*op1, Expression*op2);
~ExpConcat();
const VType*probe_type(Entity*ent, Architecture*arc) const;
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const {
return new ExpConcat(operand1_->clone(), operand2_->clone());
}
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
private:
Expression*operand1_;
@@ -415,11 +450,12 @@ class ExpConditional : public Expression {
class else_t : public LineInfo {
public:
else_t(Expression*cond, std::list<Expression*>*tru);
else_t(const else_t&other);
~else_t();
int elaborate_expr(Entity*ent, Architecture*arc, const VType*lt);
int emit_when_else(ostream&out, Entity*ent, Architecture*arc);
int emit_else(ostream&out, Entity*ent, Architecture*arc);
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope);
int emit_else(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
@@ -432,10 +468,12 @@ class ExpConditional : public Expression {
std::list<else_t*>*fal);
~ExpConditional();
const VType*probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const;
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
@@ -457,10 +495,12 @@ class ExpEdge : public ExpUnary {
explicit ExpEdge(ExpEdge::fun_t ty, Expression*op);
~ExpEdge();
Expression*clone() const { return new ExpEdge(fun_, peek_operand()->clone()); }
inline fun_t edge_fun() const { return fun_; }
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
@@ -474,14 +514,19 @@ class ExpFunc : public Expression {
ExpFunc(perm_string nn, std::list<Expression*>*args);
~ExpFunc();
Expression*clone() const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
inline perm_string func_name() const { return name_; }
inline size_t func_args() const { return argv_.size(); }
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
const VType*func_ret_type() const;
public: // Base methods
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
@@ -494,14 +539,17 @@ class ExpInteger : public Expression {
public:
ExpInteger(int64_t val);
ExpInteger(const ExpInteger&other) : Expression(), value_(other.value_) {}
~ExpInteger();
const VType*probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpInteger(*this); }
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
int emit_package(std::ostream&out);
bool is_primary(void) const;
bool is_primary(void) const { return true; }
bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
virtual ostream& dump_inline(ostream&out) const;
@@ -514,12 +562,15 @@ class ExpReal : public Expression {
public:
ExpReal(double val);
ExpReal(const ExpReal&other) : Expression(), value_(other.value_) {}
~ExpReal();
const VType*probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpReal(*this); }
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
int emit_package(std::ostream&out);
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
@@ -538,11 +589,15 @@ class ExpLogical : public ExpBinary {
ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2);
~ExpLogical();
Expression*clone() const {
return new ExpLogical(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
inline fun_t logic_fun() const { return fun_; }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
@@ -565,31 +620,64 @@ class ExpName : public Expression {
~ExpName();
public: // Base methods
int elaborate_lval(Entity*ent, Architecture*arc, bool);
int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*);
const VType* probe_type(Entity*ent, Architecture*arc) const;
const VType* fit_type(Entity*ent, Architecture*arc, const VTypeArray*host) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const {
return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
name_, safe_clone(index_), safe_clone(lsb_));
}
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*);
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
const VType* fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*host) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const;
const char* name() const;
inline perm_string peek_name() const { return name_; }
inline const char* name() const { return name_; }
inline const perm_string& peek_name() const { return name_; }
void set_range(Expression*msb, Expression*lsb);
private:
const VType* elaborate_adjust_type_with_range_(Entity*ent, Architecture*arc, const VType*type);
class index_t {
public:
index_t(Expression*idx, Expression*size, Expression*offset = NULL) :
idx_(idx), size_(size), offset_(offset) {}
int elaborate_lval_(Entity*ent, Architecture*arc, bool, ExpName*suffix);
const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const;
const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
int emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc);
private:
Expression*idx_;
Expression*size_;
Expression*offset_;
};
const VType* elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*scope, const VType*type);
int elaborate_lval_(Entity*ent, ScopeBase*scope, bool, ExpName*suffix);
const VType* probe_prefix_type_(Entity*ent, ScopeBase*scope) const;
const VType* probe_prefixed_type_(Entity*ent, ScopeBase*scope) const;
int emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope);
// There are some workarounds required for constant arrays/records, as
// they are currently emitted as flat localparams (without any type
// information). The following workarounds adjust the access indices
// to select appropriate parts of the localparam.
bool try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
list<index_t*>&indices, int&data_size);
bool check_const_array_workaround_(const VTypeArray*arr, ScopeBase*scope,
list<index_t*>&indices, int&data_size) const;
bool check_const_record_workaround_(const VTypeRecord*rec, ScopeBase*scope,
list<index_t*>&indices, int&data_size) const;
int emit_workaround_(ostream&out, Entity*ent, ScopeBase*scope,
const list<index_t*>&indices, int field_size);
private:
std::auto_ptr<ExpName> prefix_;
@@ -604,8 +692,8 @@ class ExpNameALL : public ExpName {
ExpNameALL() : ExpName(perm_string()) { }
public:
int elaborate_lval(Entity*ent, Architecture*arc, bool);
const VType* probe_type(Entity*ent, Architecture*arc) const;
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
void dump(ostream&out, int indent =0) const;
};
@@ -620,32 +708,60 @@ class ExpRelation : public ExpBinary {
ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2);
~ExpRelation();
const VType* probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const {
return new ExpRelation(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
fun_t fun_;
};
class ExpShift : public ExpBinary {
public:
enum shift_t { SRL, SLL, SRA, SLA, ROL, ROR };
public:
ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2);
Expression*clone() const {
return new ExpShift(shift_, peek_operand1()->clone(), peek_operand2()->clone());
}
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
private:
shift_t shift_;
};
class ExpString : public Expression {
public:
explicit ExpString(const char*);
ExpString(const ExpString&other) : Expression(), value_(other.value_) {}
~ExpString();
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpString(*this); }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
const std::vector<char>& get_value() const { return value_; }
private:
int emit_as_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*arr);
int emit_as_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*arr);
private:
std::vector<char> value_;
@@ -657,8 +773,10 @@ class ExpUAbs : public ExpUnary {
ExpUAbs(Expression*op1);
~ExpUAbs();
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); }
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
};
@@ -668,10 +786,56 @@ class ExpUNot : public ExpUnary {
ExpUNot(Expression*op1);
~ExpUNot();
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc);
Expression*clone() const { return new ExpUNot(peek_operand()->clone()); }
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
};
/*
* Class that wraps other expressions to cast them to other types.
*/
class ExpCast : public Expression {
public:
ExpCast(Expression*base, const VType*type);
~ExpCast();
Expression*clone() const { return new ExpCast(base_->clone(), type_->clone()); }
inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) {
return base_->elaborate_expr(ent, scope, type_);
}
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
Expression*base_;
const VType*type_;
};
/*
* Class that handles 'new' statement. VHDL is not capable of dynamic memory
* allocation, but it is useful for emitting some cases.
*/
class ExpNew : public Expression {
public:
ExpNew(Expression*size);
~ExpNew();
Expression*clone() const { return new ExpNew(size_->clone()); }
// There is no 'new' in VHDL - do not emit anything
void write_to_stream(std::ostream&) const {};
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
Expression*size_;
};
#endif /* IVL_expression_H */
+44
View File
@@ -68,3 +68,47 @@ void ExpConcat::dump(ostream&out, int indent) const
operand1_->dump(out, indent);
operand2_->dump(out, indent);
}
void ExpCast::dump(ostream&out, int indent) const
{
out << "Casting ";
base_->dump(out, indent+4);
out << " to ";
type_->emit_def(out, empty_perm_string);
}
void ExpNew::dump(ostream&out, int indent) const
{
out << "New dynamic array size: ";
size_->dump(out, indent);
}
void ExpShift::dump(ostream&out, int indent) const
{
const char*fun_name = "?";
switch (shift_) {
case SRL:
fun_name = "srl";
break;
case SLL:
fun_name = "sll";
break;
case SLA:
fun_name = "sla";
break;
case SRA:
fun_name = "sra";
break;
case ROR:
fun_name = "ror";
break;
case ROL:
fun_name = "rol";
break;
}
out << setw(indent) << "" << "Shift " << fun_name
<< " at " << get_fileline() << endl;
dump_operands(out, indent+4);
}
+300 -137
View File
@@ -33,20 +33,20 @@
using namespace std;
int Expression::elaborate_lval(Entity*, Architecture*, bool)
int Expression::elaborate_lval(Entity*, ScopeBase*, bool)
{
cerr << get_fileline() << ": error: Expression is not a valid l-value." << endl;
return 1;
}
const VType* Expression::probe_type(Entity*, Architecture*) const
const VType* Expression::probe_type(Entity*, ScopeBase*) const
{
return 0;
}
const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray*) const
const VType* Expression::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
{
const VType*res = probe_type(ent,arc);
const VType*res = probe_type(ent,scope);
if (res == 0) {
cerr << get_fileline() << ": internal error: "
<< "fit_type for " << typeid(*this).name()
@@ -56,7 +56,7 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray
return res;
}
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type)
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope, const VType*type)
{
// Unfold typedefs
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) {
@@ -75,23 +75,19 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc
int64_t use_msb, use_lsb;
bool flag;
flag = index_->evaluate(arc, use_msb);
flag = index_->evaluate(scope, use_msb);
ivl_assert(*this, flag);
flag = lsb_->evaluate(arc, use_lsb);
flag = lsb_->evaluate(scope, use_lsb);
ivl_assert(*this, flag);
Expression*exp_msb = new ExpInteger(use_msb);
Expression*exp_lsb = new ExpInteger(use_lsb);
vector<VTypeArray::range_t> use_dims (1);
use_dims[0] = VTypeArray::range_t(exp_msb, exp_lsb);
type = new VTypeArray(array->element_type(), use_dims);
type = new VTypeArray(array->element_type(), use_msb, use_lsb);
}
}
return type;
}
int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName*suffix)
int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName*suffix)
{
int errors = 0;
@@ -134,13 +130,13 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
<< ent->get_name() << "." << endl;
return errors + 1;
} else if (Signal*sig = arc->find_signal(name_)) {
} else if (Signal*sig = scope->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
found_type = sig->peek_type();
} else if (Variable*var = arc->find_variable(name_)) {
} else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ();
@@ -201,7 +197,7 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
return errors;
}
suffix_type = suffix->elaborate_adjust_type_with_range_(ent, arc, suffix_type);
suffix_type = suffix->elaborate_adjust_type_with_range_(ent, scope, suffix_type);
ivl_assert(*this, suffix_type);
suffix->set_type(suffix_type);
@@ -209,12 +205,12 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
return errors;
}
int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
{
int errors = 0;
if (prefix_.get()) {
return prefix_->elaborate_lval_(ent, arc, is_sequ, this);
return prefix_->elaborate_lval_(ent, scope, is_sequ, this);
}
const VType*found_type = 0;
@@ -238,13 +234,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
<< ent->get_name() << "." << endl;
return 1;
} else if (Signal*sig = arc->find_signal(name_)) {
} else if (Signal*sig = scope->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
found_type = sig->peek_type();
} else if (Variable*var = arc->find_variable(name_)) {
} else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ();
@@ -257,13 +253,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
return errors + 1;
}
found_type = elaborate_adjust_type_with_range_(ent, arc, found_type);
found_type = elaborate_adjust_type_with_range_(ent, scope, found_type);
set_type(found_type);
return errors;
}
int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval)
int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lval)
{
int errors = 0;
@@ -273,6 +269,9 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
errors += 1;
}
const VType*dummy_type;
Expression*dummy_expr;
if (const InterfacePort*cur = ent->find_port(name_)) {
/* IEEE 1076-2008, p.80:
* For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER
@@ -295,14 +294,17 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
default:
break;
}
} else if (arc->find_signal(name_)) {
} else if (scope->find_signal(name_)) {
/* OK */
} else if (ent->find_generic(name_)) {
/* OK */
} else if (scope->find_constant(name_, dummy_type, dummy_expr)) {
/* OK */
} else {
cerr << get_fileline() << ": error: No port or signal " << name_
cerr << get_fileline() << ": error: No port, signal or constant " << name_
<< " to be used as r-value." << endl;
errors += 1;
}
@@ -310,21 +312,21 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
return errors;
}
int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
int ExpNameALL::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
{
return Expression::elaborate_lval(ent, arc, is_sequ);
return Expression::elaborate_lval(ent, scope, is_sequ);
}
int Expression::elaborate_expr(Entity*, Architecture*, const VType*)
int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*)
{
cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl;
return 1;
}
const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const
const VType* ExpBinary::probe_type(Entity*ent, ScopeBase*scope) const
{
const VType*t1 = operand1_->probe_type(ent, arc);
const VType*t2 = operand2_->probe_type(ent, arc);
const VType*t1 = operand1_->probe_type(ent, scope);
const VType*t2 = operand2_->probe_type(ent, scope);
if (t1 == 0)
return t2;
@@ -351,12 +353,12 @@ const VType*ExpBinary::resolve_operand_types_(const VType*, const VType*) const
return 0;
}
int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
int ExpBinary::elaborate_exprs(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
errors += operand1_->elaborate_expr(ent, arc, ltype);
errors += operand2_->elaborate_expr(ent, arc, ltype);
errors += operand1_->elaborate_expr(ent, scope, ltype);
errors += operand2_->elaborate_expr(ent, scope, ltype);
return errors;
}
@@ -365,17 +367,17 @@ int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
* return the fit_type for the operand. The assumption is that the
* operator doesn't change the type.
*/
const VType*ExpUnary::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const
const VType*ExpUnary::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const
{
return operand1_->fit_type(ent, arc, atype);
return operand1_->fit_type(ent, scope, atype);
}
const VType*ExpAggregate::probe_type(Entity*ent, Architecture*arc) const
const VType*ExpAggregate::probe_type(Entity*ent, ScopeBase*scope) const
{
return Expression::probe_type(ent, arc);
return Expression::probe_type(ent, scope);
}
const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host) const
const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) const
{
ivl_assert(*this, elements_.size() == 1);
size_t choice_count = elements_[0]->count_choices();
@@ -401,7 +403,7 @@ const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host
return res;
}
int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpAggregate::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
if (ltype == 0) {
cerr << get_fileline() << ": error: Elaboration of aggregate types needs well known type context?" << endl;
@@ -415,10 +417,10 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
}
if (const VTypeArray*larray = dynamic_cast<const VTypeArray*>(ltype)) {
return elaborate_expr_array_(ent, arc, larray);
return elaborate_expr_array_(ent, scope, larray);
}
else if(const VTypeRecord*lrecord = dynamic_cast<const VTypeRecord*>(ltype)) {
return elaborate_expr_record_(ent, arc, lrecord);
return elaborate_expr_record_(ent, scope, lrecord);
}
cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl;
@@ -430,7 +432,7 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
* expressions (the elements_ member) using the element type as the
* ltype for the subexpression.
*/
int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype)
int ExpAggregate::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype)
{
const VType*element_type = ltype->element_type();
int errors = 0;
@@ -476,7 +478,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
if (aggregate_[idx].alias_flag)
continue;
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, element_type);
errors += aggregate_[idx].expr->elaborate_expr(ent, scope, element_type);
}
// done with the obsolete elements_ vector.
@@ -485,7 +487,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
return errors;
}
int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype)
int ExpAggregate::elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype)
{
int errors = 0;
@@ -513,10 +515,12 @@ int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTy
ivl_assert(*this, field);
perm_string field_name = field->peek_name();
idx = -1;
const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx);
ivl_assert(*this, idx >= 0);
aggregate_[idx] = tmp;
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type());
errors += aggregate_[idx].expr->elaborate_expr(ent, scope, el->peek_type());
}
// done with the obsolete elements_ vector.
@@ -535,16 +539,16 @@ void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst)
}
}
int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpArithmetic::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
errors += elaborate_exprs(ent, arc, ltype);
errors += elaborate_exprs(ent, scope, ltype);
return errors;
}
@@ -563,53 +567,55 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
return 0;
}
const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const
const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const
{
base_->probe_type(ent, arc);
base_->probe_type(ent, scope);
if (name_ == "length" || name_ == "left" || name_ == "right") {
return &primitive_INTEGER;
return &primitive_NATURAL;
}
return 0;
}
int ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{
int errors = 0;
const VType*sub_type = base_->probe_type(ent, arc);
errors += base_->elaborate_expr(ent, arc, sub_type);
const VType*sub_type = base_->probe_type(ent, scope);
errors += base_->elaborate_expr(ent, scope, sub_type);
return errors;
}
const VType*ExpBitstring::fit_type(Entity*, Architecture*, const VTypeArray*atype) const
const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
{
// Really should check that this string can work with the
// array element type?
return atype->element_type();
}
int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*)
int ExpBitstring::elaborate_expr(Entity*, ScopeBase*, const VType*)
{
int errors = 0;
const VTypeArray*type = new VTypeArray(&primitive_STDLOGIC, value_.size() - 1, 0);
set_type(type);
return errors;
}
const VType*ExpCharacter::fit_type(Entity*, Architecture*, const VTypeArray*atype) const
const VType*ExpCharacter::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
{
// Really should check that this character can work with the
// array element type?
return atype->element_type();
}
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
int ExpCharacter::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{
ivl_assert(*this, ltype != 0);
set_type(ltype);
return 0;
}
const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const
const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const
{
Expression*operands[2] = {operand1_, operand2_};
const VType*types[2] = {NULL, NULL};
@@ -617,7 +623,7 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a
// determine the type and size of concatenated expressions
for(int i = 0; i < 2; ++i) {
types[i] = operands[i]->fit_type(ent, arc, atype);
types[i] = operands[i]->fit_type(ent, scope, atype);
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(types[i])) {
types[i] = arr->element_type();
@@ -645,62 +651,62 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a
/*
* I don't know how to probe the type of a concatenation, quite yet.
*/
const VType*ExpConcat::probe_type(Entity*, Architecture*) const
const VType*ExpConcat::probe_type(Entity*, ScopeBase*) const
{
ivl_assert(*this, 0);
return 0;
}
int ExpConcat::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpConcat::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*>(ltype)) {
errors += elaborate_expr_array_(ent, arc, atype);
errors += elaborate_expr_array_(ent, scope, atype);
} else {
errors += operand1_->elaborate_expr(ent, arc, ltype);
errors += operand2_->elaborate_expr(ent, arc, ltype);
errors += operand1_->elaborate_expr(ent, scope, ltype);
errors += operand2_->elaborate_expr(ent, scope, ltype);
}
return errors;
}
int ExpConcat::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*atype)
int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*atype)
{
int errors = 0;
// For now, only support single-dimension arrays here.
ivl_assert(*this, atype->dimensions() == 1);
const VType*type1 = operand1_->fit_type(ent, arc, atype);
const VType*type1 = operand1_->fit_type(ent, scope, atype);
ivl_assert(*this, type1);
const VType*type2 = operand2_->fit_type(ent, arc, atype);
const VType*type2 = operand2_->fit_type(ent, scope, atype);
ivl_assert(*this, type2);
errors += operand1_->elaborate_expr(ent, arc, type1);
errors += operand2_->elaborate_expr(ent, arc, type2);
errors += operand1_->elaborate_expr(ent, scope, type1);
errors += operand2_->elaborate_expr(ent, scope, type2);
return errors;
}
const VType* ExpConditional::probe_type(Entity*, Architecture*) const
const VType* ExpConditional::probe_type(Entity*, ScopeBase*) const
{
return 0;
}
int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0)
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
ivl_assert(*this, ltype);
@@ -708,42 +714,92 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
/* Note that the type for the condition expression need not
have anything to do with the type of this expression. */
errors += cond_->elaborate_expr(ent, arc, 0);
errors += cond_->elaborate_expr(ent, scope, 0);
for (list<Expression*>::const_iterator cur = true_clause_.begin()
; cur != true_clause_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, ltype);
errors += (*cur)->elaborate_expr(ent, scope, ltype);
}
for (list<else_t*>::const_iterator cur = else_clause_.begin()
; cur != else_clause_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, ltype);
errors += (*cur)->elaborate_expr(ent, scope, ltype);
}
return errors;
}
int ExpConditional::else_t::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (cond_)
errors += cond_->elaborate_expr(ent, arc, 0);
errors += cond_->elaborate_expr(ent, scope, 0);
for (list<Expression*>::const_iterator cur = true_clause_.begin()
; cur != true_clause_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, ltype);
errors += (*cur)->elaborate_expr(ent, scope, ltype);
}
return errors;
}
int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
{
if(name_ == "integer")
return &primitive_INTEGER;
if(name_ == "unsigned" || name_ == "resize") {
if(argv_.empty())
return NULL;
const VType*type = argv_[0]->probe_type(ent, scope);
if(!type)
return NULL;
int msb = type->get_width(scope) - 1;
ivl_assert(*this, msb >= 0);
// Determine the sign
bool sign = false;
if(name_ == "resize") {
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
sign = arr->signed_vector();
}
return new VTypeArray(&primitive_BIT, msb, 0, sign);
}
if(name_ == "std_logic_vector" || name_ == "conv_std_logic_vector") {
if(argv_.empty())
return NULL;
const VType*type = argv_[0]->probe_type(ent, scope);
if(!type)
return NULL;
int msb = type->get_width(scope) - 1;
return new VTypeArray(&primitive_STDLOGIC, msb, 0);
}
Subprogram*prog = scope->find_subprogram(name_);
if(!prog)
prog = library_find_subprogram(name_);
if(!prog)
return NULL;
return prog->peek_return_type();
}
int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{
int errors = 0;
ivl_assert(*this, arc);
Subprogram*prog = arc->find_subprogram(name_);
ivl_assert(*this, scope);
Subprogram*prog = scope->find_subprogram(name_);
if(!prog)
prog = library_find_subprogram(name_);
@@ -751,27 +807,110 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
ivl_assert(*this, def_==0);
def_ = prog;
// Elaborate arguments
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
const VType*tmp = argv_[idx]->probe_type(ent, arc);
if(!tmp && prog)
tmp = prog->peek_param_type(idx);
errors += argv_[idx]->elaborate_expr(ent, arc, tmp);
const VType*tmp = argv_[idx]->probe_type(ent, scope);
const VType*param_type = prog ? prog->peek_param_type(idx) : NULL;
if(!tmp && param_type)
tmp = param_type;
errors += argv_[idx]->elaborate_expr(ent, scope, tmp);
}
if(def_ && def_->unbounded()) {
def_ = prog->make_instance(argv_, scope);
name_ = def_->name();
}
return errors;
}
const VType* ExpInteger::probe_type(Entity*, Architecture*) const
const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
{
// Built-in functions
if(name_ == "to_integer" || name_ == "unsigned" || name_ == "integer") {
ivl_assert(*this, argv_.size() == 1);
const VType*type = argv_[0]->probe_type(ent, scope);
ivl_assert(*this, type);
// Determine the sign
bool sign = false;
if(name_ == "integer") {
sign = true;
} else if(name_ == "to_integer") {
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
sign = arr->signed_vector();
}
return new VTypeArray(&primitive_BIT, type->get_width(scope), 0, sign);
}
if(name_ == "to_unsigned" || name_ == "std_logic_vector" ||
name_ == "conv_std_logic_vector" || name_ == "resize")
{
ivl_assert(*this, argv_.size() == 2);
// Determine the sign
bool sign = false;
const VType*element = &primitive_STDLOGIC;
if(name_ == "resize") {
const VType*type = argv_[0]->probe_type(ent, scope);
ivl_assert(*this, type);
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
{
sign = arr->signed_vector();
element = arr->element_type();
}
} else if(name_ == "to_unsigned") {
element = &primitive_BIT;
}
int64_t width = 0;
bool evaluated = argv_[1]->evaluate(scope, width);
ivl_assert(*this, evaluated);
return new VTypeArray(element, width, 0, sign);
}
if(name_ == "and_reduce" || name_ == "or_reduce") {
ivl_assert(*this, argv_.size() == 1);
const VType*element = &primitive_STDLOGIC;
return new VTypeArray(element, 0, 0, false);
}
// Other cases
Subprogram*prog = def_;
if(!prog) {
ivl_assert(*this, scope);
prog = scope->find_subprogram(name_);
}
if(!prog)
prog = library_find_subprogram(name_);
cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl;
ivl_assert(*this, prog);
return def_->peek_return_type();
}
const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
{
return &primitive_INTEGER;
}
int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpInteger::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
@@ -779,17 +918,17 @@ int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
return errors;
}
const VType* ExpReal::probe_type(Entity*, Architecture*) const
const VType* ExpReal::probe_type(Entity*, ScopeBase*) const
{
return &primitive_REAL;
}
int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpReal::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
@@ -797,27 +936,27 @@ int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
return errors;
}
int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpLogical::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
errors += elaborate_exprs(ent, arc, ltype);
errors += elaborate_exprs(ent, scope, ltype);
return errors;
}
const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const
const VType* ExpName::probe_prefix_type_(Entity*ent, ScopeBase*scope) const
{
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl;
return 0;
}
const VType*type = probe_type(ent, arc);
const VType*type = probe_type(ent, scope);
return type;
}
@@ -826,10 +965,10 @@ const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const
* that have prefix parts. In this case we try to get the type of the
* prefix and interpret the name in that context.
*/
const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
const VType* ExpName::probe_prefixed_type_(Entity*ent, ScopeBase*scope) const
{
// First, get the type of the prefix.
const VType*prefix_type = prefix_->probe_prefix_type_(ent, arc);
const VType*prefix_type = prefix_->probe_prefix_type_(ent, scope);
if (prefix_type == 0) {
return 0;
}
@@ -850,6 +989,13 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
return element_type;
}
if (const VTypeArray*pref_array = dynamic_cast<const VTypeArray*> (prefix_type)) {
const VType*element_type = pref_array->element_type();
ivl_assert(*this, element_type);
return element_type;
}
cerr << get_fileline() << ": sorry: I don't know how to probe "
<< "prefix type " << typeid(*prefix_type).name()
<< " of " << name_ << "." << endl;
@@ -857,34 +1003,43 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
return 0;
}
const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
{
if (prefix_.get())
return probe_prefixed_type_(ent, arc);
return probe_prefixed_type_(ent, scope);
if (const InterfacePort*cur = ent->find_port(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
if(ent) {
if (const InterfacePort*cur = ent->find_port(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
}
if (const InterfacePort*cur = ent->find_generic(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
}
}
if (const InterfacePort*cur = ent->find_generic(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
}
if(scope) {
if (Signal*sig = scope->find_signal(name_))
return sig->peek_type();
if (Signal*sig = arc->find_signal(name_))
return sig->peek_type();
if (Variable*var = scope->find_variable(name_))
return var->peek_type();
if (Variable*var = arc->find_variable(name_))
return var->peek_type();
const VType*type = 0;
Expression*cval = 0;
if (scope->find_constant(name_, type, cval))
return type;
const VType*ctype = 0;
Expression*cval = 0;
if (arc->find_constant(name_, ctype, cval))
return ctype;
Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc && (type = arc->probe_genvar_type(name_))) {
return type;
}
if (const VType*gtype = arc->probe_genvar_type(name_)) {
return gtype;
if ((type = scope->is_enum_name(name_))) {
return type;
}
}
cerr << get_fileline() << ": error: Signal/variable " << name_
@@ -892,12 +1047,12 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
return 0;
}
const VType* ExpName::fit_type(Entity*ent, Architecture*arc, const VTypeArray*)const
const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)const
{
return probe_type(ent, arc);
return probe_type(ent, scope);
}
int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{
if (ltype) {
ivl_assert(*this, ltype != 0);
@@ -907,22 +1062,22 @@ int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
return 0;
}
const VType* ExpNameALL::probe_type(Entity*, Architecture*) const
const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const
{
return 0;
}
const VType* ExpRelation::probe_type(Entity*, Architecture*) const
const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const
{
return &primitive_BOOLEAN;
}
int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, arc);
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
@@ -930,41 +1085,49 @@ int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
// The type of the operands must match, but need not match the
// type for the ExpRelation itself. So get the operand type
// separately.
const VType*otype = ExpBinary::probe_type(ent, arc);
errors += elaborate_exprs(ent, arc, otype);
const VType*otype = ExpBinary::probe_type(ent, scope);
errors += elaborate_exprs(ent, scope, otype);
return errors;
}
int ExpShift::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
errors += elaborate_exprs(ent, scope, ltype);
return errors;
}
/*
* When a string appears in a concatenation, then the type of the
* string is an array with the same element type of the concatenation,
* but with elements for each character of the string.
*/
const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype) const
const VType*ExpString::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
{
vector<VTypeArray::range_t> range (atype->dimensions());
// Generate an array range for this string
ivl_assert(*this, range.size() == 1);
ExpInteger*use_msb = new ExpInteger(value_.size());
ExpInteger*use_lsb = new ExpInteger(0);
FILE_NAME(use_msb, this);
FILE_NAME(use_lsb, this);
range[0] = VTypeArray::range_t(use_msb, use_lsb);
VTypeArray*type = new VTypeArray(atype->element_type(), range);
VTypeArray*type = new VTypeArray(atype->element_type(), value_.size(), 0);
return type;
}
int ExpString::elaborate_expr(Entity*, Architecture*, const VType*ltype)
int ExpString::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{
ivl_assert(*this, ltype != 0);
set_type(ltype);
return 0;
}
int ExpUNot::elaborate_expr(Entity*, Architecture*, const VType*ltype)
int ExpUNot::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{
ivl_assert(*this, ltype != 0);
set_type(ltype);
+348 -140
View File
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2015 / Stephen Williams (steve@icarus.com)
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -33,7 +34,34 @@
using namespace std;
int Expression::emit(ostream&out, Entity*, Architecture*)
inline static int emit_logic(char val, ostream& out, const VTypePrimitive::type_t type)
{
// TODO case 'W': case 'L': case 'H':
switch (val) {
case '-': case 'U':
val = 'x';
/* fall through */
case 'X': case 'Z':
assert(type == VTypePrimitive::STDLOGIC);
/* fall through */
case '0':
case '1':
out << (char) tolower(val);
break;
default:
assert(false);
out << "x";
return 1;
}
return 0;
}
int Expression::emit(ostream&out, Entity*, ScopeBase*)
{
out << " /* " << get_fileline() << ": internal error: "
<< "I don't know how to emit this expression! "
@@ -54,34 +82,34 @@ bool Expression::is_primary(void) const
return false;
}
int ExpBinary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
int ExpBinary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
bool oper_primary = operand1_->is_primary();
if (! oper_primary) out << "(";
errors += operand1_->emit(out, ent, arc);
errors += operand1_->emit(out, ent, scope);
if (! oper_primary) out << ")";
return errors;
}
int ExpBinary::emit_operand2(ostream&out, Entity*ent, Architecture*arc)
int ExpBinary::emit_operand2(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
bool oper_primary = operand2_->is_primary();
if (! oper_primary) out << "(";
errors += operand2_->emit(out, ent, arc);
errors += operand2_->emit(out, ent, scope);
if (! oper_primary) out << ")";
return errors;
}
int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
int ExpUnary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += operand1_->emit(out, ent, arc);
errors += operand1_->emit(out, ent, scope);
return errors;
}
int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpAggregate::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
if (peek_type() == 0) {
out << "/* " << get_fileline() << ": internal error: "
@@ -95,9 +123,9 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
}
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (use_type))
return emit_array_(out, ent, arc, atype);
return emit_array_(out, ent, scope, atype);
else if (const VTypeRecord*arecord = dynamic_cast<const VTypeRecord*> (use_type))
return emit_record_(out, ent, arc, arecord);
return emit_record_(out, ent, scope, arecord);
out << "/* " << get_fileline() << ": internal error: "
<< "I don't know how to elab/emit aggregate in " << typeid(use_type).name()
@@ -105,7 +133,7 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
return 1;
}
int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype)
int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*atype)
{
int errors = 0;
@@ -119,14 +147,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
int64_t use_msb;
int64_t use_lsb;
bool rc_msb, rc_lsb;
rc_msb = rang.msb()->evaluate(ent, arc, use_msb);
rc_lsb = rang.lsb()->evaluate(ent, arc, use_lsb);
rc_msb = rang.msb()->evaluate(ent, scope, use_msb);
rc_lsb = rang.lsb()->evaluate(ent, scope, use_lsb);
if (rc_msb && rc_lsb) {
int asize = (use_msb >= use_lsb) ? (use_msb - use_lsb) + 1 :
(use_lsb - use_msb) + 1;
out << "{" << asize << "{";
errors += aggregate_[0].expr->emit(out, ent, arc);
errors += aggregate_[0].expr->emit(out, ent, scope);
out << "}}";
} else {
out << "{(";
@@ -134,7 +162,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
out << use_msb;
} else {
out << "(";
errors += rang.msb()->emit(out, ent, arc);
errors += rang.msb()->emit(out, ent, scope);
out << ")";
}
if (rc_lsb && use_lsb==0) {
@@ -142,11 +170,11 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
out << "-" << use_lsb;
} else {
out << "-(";
errors += rang.lsb()->emit(out, ent, arc);
errors += rang.lsb()->emit(out, ent, scope);
out << ")";
}
out << "+1){";
errors += aggregate_[0].expr->emit(out, ent, arc);
errors += aggregate_[0].expr->emit(out, ent, scope);
out << "}}";
}
return errors;
@@ -158,9 +186,9 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
// Fully calculate the range numbers.
int64_t use_msb, use_lsb;
bool rc;
rc = rang.msb()->evaluate(ent, arc, use_msb);
rc = rang.msb()->evaluate(ent, scope, use_msb);
ivl_assert(*this, rc);
rc = rang.lsb()->evaluate(ent, arc, use_lsb);
rc = rang.lsb()->evaluate(ent, scope, use_lsb);
ivl_assert(*this, rc);
if(use_msb < use_lsb)
swap(use_msb, use_lsb);
@@ -198,14 +226,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
if (prange_t*range = aggregate_[idx].choice->range_expressions()) {
int64_t begin_val, end_val;
if (! range->msb()->evaluate(ent, arc, begin_val)) {
if (! range->msb()->evaluate(ent, scope, begin_val)) {
cerr << range->msb()->get_fileline() << ": error: "
<< "Unable to evaluate aggregate choice expression." << endl;
errors += 1;
continue;
}
if (! range->lsb()->evaluate(ent, arc, end_val)) {
if (! range->lsb()->evaluate(ent, scope, end_val)) {
cerr << range->msb()->get_fileline() << ": error: "
<< "Unable to evaluate aggregate choice expression." << endl;
errors += 1;
@@ -235,7 +263,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
// elements so disable further positional
// processing.
positional_section = false;
if (! tmp->evaluate(ent, arc, tmp_val)) {
if (! tmp->evaluate(ent, scope, tmp_val)) {
cerr << tmp->get_fileline() << ": error: "
<< "Unable to evaluate aggregate choice expression." << endl;
errors += 1;
@@ -266,7 +294,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
<< "Missing element " << idx << "." << endl;
errors += 1;
} else {
errors += cur->expr->emit(out, ent, arc);
errors += cur->expr->emit(out, ent, scope);
}
}
out << "}";
@@ -274,7 +302,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
return errors;
}
int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*)
int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*)
{
int errors = 0;
@@ -292,9 +320,9 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
if(idx != 0)
out << ",";
//errors += name->emit(out, ent, arc);
//errors += name->emit(out, ent, scope);
//out << ": ";
errors += val->emit(out, ent, arc);
errors += val->emit(out, ent, scope);
}
out << "}";
@@ -302,13 +330,20 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
return errors;
}
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Try to evaluate first
int64_t val;
if(evaluate(scope, val)) {
out << val;
return 0;
}
if (name_ == "event") {
out << "$ivlh_attribute_event(";
errors += base_->emit(out, ent, arc);
errors += base_->emit(out, ent, scope);
out << ")";
return errors;
}
@@ -319,27 +354,27 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
expression doesn't even need to be evaluated.) */
if (name_=="length") {
out << "$bits(";
errors += base_->emit(out, ent, arc);
errors += base_->emit(out, ent, scope);
out << ")";
return errors;
} else if (name_=="left" || name_=="right") {
out << "$" << name_ << "(";
errors += base_->emit(out, ent, arc);
errors += base_->emit(out, ent, scope);
out << ")";
return errors;
}
out << "$ivl_attribute(";
errors += base_->emit(out, ent, arc);
errors += base_->emit(out, ent, scope);
out << ", \"" << name_ << "\")";
return errors;
}
int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += emit_operand1(out, ent, arc);
errors += emit_operand1(out, ent, scope);
switch (fun_) {
case PLUS:
@@ -369,12 +404,12 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
break;
}
errors += emit_operand2(out, ent, arc);
errors += emit_operand2(out, ent, scope);
return errors;
}
int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
int ExpBitstring::emit(ostream&out, Entity*, ScopeBase*)
{
int errors = 0;
@@ -385,39 +420,31 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
return errors;
}
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*,
const VTypePrimitive*etype)
{
switch (etype->type()) {
case VTypePrimitive::BOOLEAN:
case VTypePrimitive::BIT:
case VTypePrimitive::STDLOGIC:
switch (value_) {
case '0':
case '1':
out << "1'b" << value_;
return 0;
default:
break;
}
out << "1'b";
int res = emit_logic(value_, out, etype->type());
default:
return 1;
}
return 1;
if(res)
cerr << get_fileline() << ": internal error: "
<< "Don't know how to handle bit " << value_
<< " with etype==" << etype->type() << endl;
return res;
}
int ExpCharacter::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
const VType*etype = peek_type();
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) {
return emit_primitive_bit_(out, ent, arc, use_type);
return emit_primitive_bit_(out, ent, scope, use_type);
}
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(etype)) {
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(array->element_type())) {
return emit_primitive_bit_(out, ent, arc, use_type);
return emit_primitive_bit_(out, ent, scope, use_type);
}
}
@@ -439,22 +466,22 @@ bool ExpConcat::is_primary(void) const
return true;
}
int ExpConcat::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpConcat::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "{";
errors += operand1_->emit(out, ent, arc);
errors += operand1_->emit(out, ent, scope);
out << ", ";
errors += operand2_->emit(out, ent, arc);
errors += operand2_->emit(out, ent, scope);
out << "}";
return errors;
}
int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "(";
errors += cond_->emit(out, ent, arc);
errors += cond_->emit(out, ent, scope);
out << ")? (";
if (true_clause_.size() > 1) {
@@ -463,7 +490,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
}
Expression*tmp = true_clause_.front();
errors += tmp->emit(out, ent, arc);
errors += tmp->emit(out, ent, scope);
out << ") : (";
@@ -475,11 +502,11 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
for (list<else_t*>::iterator cur = else_clause_.begin()
; cur != last ; ++cur) {
errors += (*cur) ->emit_when_else(out, ent, arc);
errors += (*cur) ->emit_when_else(out, ent, scope);
}
}
errors += else_clause_.back()->emit_else(out, ent, arc);
errors += else_clause_.back()->emit_else(out, ent, scope);
out << ")";
// The emit_when_else() functions do not close the last
@@ -492,13 +519,13 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture*arc)
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
assert(cond_ != 0);
out << "(";
errors += cond_->emit(out, ent, arc);
errors += cond_->emit(out, ent, scope);
out << ")? (";
if (true_clause_.size() > 1) {
@@ -507,14 +534,14 @@ int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture
}
Expression*tmp = true_clause_.front();
errors += tmp->emit(out, ent, arc);
errors += tmp->emit(out, ent, scope);
out << ") : (";
return errors;
}
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc)
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Trailing else must have no condition.
@@ -526,12 +553,12 @@ int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc)
}
Expression*tmp = true_clause_.front();
errors += tmp->emit(out, ent, arc);
errors += tmp->emit(out, ent, scope);
return errors;
}
int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpEdge::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
switch (fun_) {
@@ -544,60 +571,90 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
case ANYEDGE:
break;
}
errors += emit_operand1(out, ent, arc);
errors += emit_operand1(out, ent, scope);
return errors;
}
int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
if (name_ == "unsigned" && argv_.size()==1) {
if (name_ == "unsigned" && argv_.size() == 1) {
// Handle the special case that this is a cast to
// unsigned. This function is brought in as part of the
// std numeric library, but we interpret it as the same
// as the $unsigned function.
out << "$unsigned(";
errors += argv_[0]->emit(out, ent, arc);
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "integer" && argv_.size() == 1) {
// Simply skip the function name, SystemVerilog takes care of
// rounding real numbers
errors += argv_[0]->emit(out, ent, arc);
out << "$signed(";
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "to_integer" && argv_.size() == 1) {
bool signed_flag = false;
// to_integer converts unsigned to natural
// signed to integer
// try to determine the converted type
const VType*type = argv_[0]->probe_type(ent, scope);
const VTypeArray*array = dynamic_cast<const VTypeArray*>(type);
if(array)
signed_flag = array->signed_vector();
else
cerr << get_fileline() << ": sorry: Could not determine the "
<< "expression sign. Output may be erroneous." << endl;
out << (signed_flag ? "$signed(" : "$unsigned(");
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "std_logic_vector" && argv_.size() == 1) {
// Special case: The std_logic_vector function casts its
// argument to std_logic_vector. Internally, we don't
// have to do anything for that to work.
out << "(";
errors += argv_[0]->emit(out, ent, arc);
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "to_unsigned" && argv_.size() == 2) {
out << "$ivlh_to_unsigned(";
errors += argv_[0]->emit(out, ent, arc);
errors += argv_[0]->emit(out, ent, scope);
out << ", ";
errors += argv_[1]->emit(out, ent, arc);
errors += argv_[1]->emit(out, ent, scope);
out << ")";
} else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) {
} else if ((name_ == "conv_std_logic_vector" || name_ == "resize") &&
argv_.size() == 2) {
int64_t use_size;
bool rc = argv_[1]->evaluate(ent, arc, use_size);
bool rc = argv_[1]->evaluate(ent, scope, use_size);
ivl_assert(*this, rc);
out << use_size << "'(";
errors += argv_[0]->emit(out, ent, arc);
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "rising_edge" && argv_.size()==1) {
} else if (name_ == "rising_edge" && argv_.size() == 1) {
out << "$ivlh_rising_edge(";
errors += argv_[0]->emit(out, ent, arc);
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "falling_edge" && argv_.size()==1) {
} else if (name_ == "falling_edge" && argv_.size() == 1) {
out << "$ivlh_falling_edge(";
errors += argv_[0]->emit(out, ent, arc);
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "and_reduce" && argv_.size() == 1) {
out << "&(";
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "or_reduce" && argv_.size() == 1) {
out << "|(";
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else {
@@ -615,7 +672,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
out << "\\" << name_ << " (";
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
if (idx > 0) out << ", ";
errors += argv_[idx]->emit(out, ent, arc);
errors += argv_[idx]->emit(out, ent, scope);
}
out << ")";
}
@@ -623,9 +680,9 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
int ExpInteger::emit(ostream&out, Entity*, ScopeBase*)
{
out << value_;
out << "32'd" << value_;
return 0;
}
@@ -635,12 +692,7 @@ int ExpInteger::emit_package(ostream&out)
return 0;
}
bool ExpInteger::is_primary(void) const
{
return true;
}
int ExpReal::emit(ostream&out, Entity*, Architecture*)
int ExpReal::emit(ostream&out, Entity*, ScopeBase*)
{
out << value_;
return 0;
@@ -657,11 +709,11 @@ bool ExpReal::is_primary(void) const
return true;
}
int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpLogical::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += emit_operand1(out, ent, arc);
errors += emit_operand1(out, ent, scope);
switch (fun_) {
case AND:
@@ -684,22 +736,22 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
break;
}
errors += emit_operand2(out, ent, arc);
errors += emit_operand2(out, ent, scope);
return errors;
}
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
if (prefix_.get()) {
errors += prefix_->emit_as_prefix_(out, ent, arc);
errors += prefix_->emit_as_prefix_(out, ent, scope);
}
out << "\\" << name_ << " ";
if (index_) {
out << "[";
errors += index_->emit(out, ent, arc);
errors += index_->emit(out, ent, scope);
out << "]";
ivl_assert(*this, lsb_ == 0);
}
@@ -707,27 +759,35 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
int field_size = 0;
list<index_t*> indices;
if(try_workarounds_(out, ent, scope, indices, field_size)) {
emit_workaround_(out, ent, scope, indices, field_size);
return 0;
}
if (prefix_.get()) {
errors += prefix_->emit_as_prefix_(out, ent, arc);
errors += prefix_->emit_as_prefix_(out, ent, scope);
}
const GenerateStatement*gs = 0;
Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc && (gs = arc->probe_genvar_emit(name_)))
out << "\\" << gs->get_name() << ":" << name_ << " ";
out << "\\" << gs->get_name() << ":" << name_ << " ";
else
out << "\\" << name_ << " ";
if (index_) {
out << "[";
errors += index_->emit(out, ent, arc);
errors += index_->emit(out, ent, scope);
if (lsb_) {
out << ":";
errors += lsb_->emit(out, ent, arc);
errors += lsb_->emit(out, ent, scope);
}
out << "]";
}
@@ -735,15 +795,130 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
bool ExpName::try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
list<index_t*>& indices, int& data_size)
{
Expression*exp = NULL;
bool wrkand_required = false;
const VType*type = NULL;
if(!scope)
return false;
if(prefix_.get())
prefix_->try_workarounds_(out, ent, scope, indices, data_size);
if(index_ && !lsb_ && scope->find_constant(name_, type, exp)) {
while(const VTypeDef*type_def = dynamic_cast<const VTypeDef*>(type)) {
type = type_def->peek_definition();
}
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
assert(arr);
wrkand_required |= check_const_array_workaround_(arr, scope, indices, data_size);
}
if(prefix_.get() && scope->find_constant(prefix_->name_, type, exp)) {
// Handle the case of array of records
if(prefix_->index_) {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
assert(arr);
type = arr->element_type();
data_size = type->get_width(scope);
}
while(const VTypeDef*type_def = dynamic_cast<const VTypeDef*>(type)) {
type = type_def->peek_definition();
}
const VTypeRecord*rec = dynamic_cast<const VTypeRecord*>(type);
assert(rec);
wrkand_required |= check_const_record_workaround_(rec, scope, indices, data_size);
}
return wrkand_required;
}
bool ExpName::check_const_array_workaround_(const VTypeArray*arr,
ScopeBase*scope, list<index_t*>&indices, int&data_size) const
{
const VType*element = arr->element_type();
data_size = element->get_width(scope);
if(data_size < 0)
return false;
indices.push_back(new index_t(index_, new ExpInteger(data_size)));
return true;
}
bool ExpName::check_const_record_workaround_(const VTypeRecord*rec,
ScopeBase*scope, list<index_t*>&indices, int&data_size) const
{
int tmp_offset = 0;
const vector<VTypeRecord::element_t*>& elements = rec->get_elements();
for(vector<VTypeRecord::element_t*>::const_reverse_iterator it = elements.rbegin();
it != elements.rend(); ++it) {
VTypeRecord::element_t* el = (*it);
if(el->peek_name() == name_) {
const VType*type = el->peek_type();
int tmp_field = type->get_width(scope);
if(tmp_field < 0)
return false;
data_size = tmp_field;
indices.push_back(new index_t(NULL, NULL, new ExpInteger(tmp_offset)));
if(index_) {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
assert(arr);
return check_const_array_workaround_(arr, scope, indices, data_size);
}
return true;
}
int w = el->peek_type()->get_width(scope);
if(w < 0)
return false;
tmp_offset += w;
}
return false;
}
int ExpName::emit_workaround_(ostream&out, Entity*ent, ScopeBase*scope,
const list<index_t*>& indices, int field_size)
{
int errors = 0;
out << "\\" << (prefix_.get() ? prefix_->name_ : name_) << " [";
for(list<index_t*>::const_iterator it = indices.begin();
it != indices.end(); ++it) {
errors += (*it)->emit(out, ent, scope);
out << "+";
}
out << ":" << field_size << "]";
return errors;
}
bool ExpName::is_primary(void) const
{
return true;
}
int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += emit_operand1(out, ent, arc);
errors += emit_operand1(out, ent, scope);
switch (fun_) {
case EQ:
@@ -766,7 +941,37 @@ int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
break;
}
errors += emit_operand2(out, ent, arc);
errors += emit_operand2(out, ent, scope);
return errors;
}
int ExpShift::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += emit_operand1(out, ent, scope);
switch (shift_) {
case SRL:
out << " >> ";
break;
case SLL:
out << " << ";
break;
case SRA:
out << " >>> ";
break;
case SLA:
out << " <<< ";
break;
case ROR:
case ROL:
out << " /* ?ror/rol? */ ";
break;
}
errors += emit_operand2(out, ent, scope);
return errors;
}
@@ -775,13 +980,13 @@ bool ExpString::is_primary(void) const
return true;
}
int ExpString::emit(ostream& out, Entity*ent, Architecture*arc)
int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope)
{
const VType*type = peek_type();
assert(type != 0);
if (const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type)) {
return emit_as_array_(out, ent, arc, arr);
return emit_as_array_(out, ent, scope, arr);
}
out << "\"";
@@ -792,7 +997,7 @@ int ExpString::emit(ostream& out, Entity*ent, Architecture*arc)
return 0;
}
int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeArray*arr)
int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr)
{
int errors = 0;
assert(arr->dimensions() == 1);
@@ -815,48 +1020,51 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA
assert(etype->type() != VTypePrimitive::INTEGER);
out << value_.size() << "'b";
for (size_t idx = 0 ; idx < value_.size() ; idx += 1) {
switch (value_[idx]) {
case '0':
out << "0";
break;
case '1':
out << "1";
break;
case 'z': case 'Z':
assert(etype->type() == VTypePrimitive::STDLOGIC);
out << "z";
break;
case '-':
assert(etype->type() == VTypePrimitive::STDLOGIC);
out << "x";
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Don't know how to handle bit " << value_[idx]
<< " with etype==" << etype->type() << endl;
assert(etype->type() == VTypePrimitive::STDLOGIC);
out << "x";
break;
}
int res = emit_logic(value_[idx], out, etype->type());
errors += res;
if(res)
cerr << get_fileline() << ": internal error: "
<< "Don't know how to handle bit " << value_[idx]
<< " with etype==" << etype->type() << endl;
}
return errors;
}
int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "abs(";
errors += emit_operand1(out, ent, arc);
errors += emit_operand1(out, ent, scope);
out << ")";
return errors;
}
int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc)
int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "~(";
errors += emit_operand1(out, ent, arc);
errors += emit_operand1(out, ent, scope);
out << ")";
return errors;
}
int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += type_->emit_def(out, empty_perm_string);
out << "'(";
errors += base_->emit(out, ent, scope);
out << ")";
return errors;
}
int ExpNew::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "new[";
errors += size_->emit(out, ent, scope);
out << "]";
return errors;
}
+91 -29
View File
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,12 +28,11 @@ bool Expression::evaluate(ScopeBase*, int64_t&) const
return false;
}
bool Expression::evaluate(Entity*, Architecture*arc, int64_t&val) const
bool Expression::evaluate(Entity*, ScopeBase*scope, int64_t&val) const
{
return evaluate(arc, val);
return evaluate(scope, val);
}
bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
{
int64_t val1, val2;
@@ -76,67 +77,92 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return true;
}
bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const
{
/* Special Case: The length attribute can be calculated all
/* Special Case: The array attributes can sometimes be calculated all
the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */
if (name_ == "length") {
if (name_ == "length" || name_ == "right" || name_ == "left") {
const VType*base_type = base_->peek_type();
//if (base_type == 0)
// base_type = base_->probe_type(ent,arc);
ivl_assert(*this, base_type);
if(!base_type) {
const ExpName*name = NULL;
if(scope && (name = dynamic_cast<const ExpName*>(base_))) {
const perm_string& n = name->peek_name();
if(const Variable*var = scope->find_variable(n))
base_type = var->peek_type();
else if(const Signal*sig = scope->find_signal(n))
base_type = sig->peek_type();
else if(const InterfacePort*port = scope->find_param(n))
base_type = port->type;
}
}
if(!base_type)
return false; // I tried really hard, sorry
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
cerr << get_fileline() << ": error: "
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the 'length attribute to non-array objects"
<< endl;
ivl_assert(*this, false);
return false;
}
int64_t size = 1;
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
const VTypeArray::range_t&dim = arr->dimension(idx);
ivl_assert(*this, ! dim.is_box());
size *= 1 + labs(dim.msb() - dim.lsb());
}
val = size;
if(name_ == "length") {
int64_t size = arr->get_width(scope);
if(size > 0)
val = size;
else
return false;
} else if(name_ == "left") {
arr->dimension(0).msb()->evaluate(scope, val);
} else if(name_ == "right") {
arr->dimension(0).lsb()->evaluate(scope, val);
} else ivl_assert(*this, false);
return true;
}
return false;
}
bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (!ent || !scope) { // it's impossible to evaluate, probably it is inside a subprogram
return false;
}
if (name_ == "left" || name_ == "right") {
const VType*base_type = base_->peek_type();
if (base_type == 0)
base_type = base_->probe_type(ent,arc);
base_type = base_->probe_type(ent, scope);
ivl_assert(*this, base_type);
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
cerr << get_fileline() << ": error: "
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to non-array objects" << endl;
ivl_assert(*this, false);
return false;
}
ivl_assert(*this, arr->dimensions() == 1);
if(name_ == "left")
arr->dimension(0).msb()->evaluate(ent, arc, val);
else
arr->dimension(0).lsb()->evaluate(ent, arc, val);
arr->dimension(0).msb()->evaluate(ent, scope, val);
else // "right"
arr->dimension(0).lsb()->evaluate(ent, scope, val);
return true;
}
return evaluate(arc, val);
return evaluate(scope, val);
}
/*
@@ -158,14 +184,16 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
return false;
}
bool rc = scope->find_constant(name_, type, exp);
if (rc == false)
if (!scope)
return false;
if (!scope->find_constant(name_, type, exp))
return false;
return exp->evaluate(scope, val);
}
bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
@@ -178,8 +206,42 @@ bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
// Evaluate the default expression and use that.
if (gen->expr)
return gen->expr->evaluate(ent, arc, val);
return gen->expr->evaluate(ent, scope, val);
}
return evaluate(arc, val);
return evaluate(scope, val);
}
bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
{
int64_t val1, val2;
bool rc;
rc = eval_operand1(scope, val1);
if (rc == false)
return false;
rc = eval_operand2(scope, val2);
if (rc == false)
return false;
switch (shift_) {
case SRL:
val = (uint64_t)val1 >> (uint64_t)val2;
break;
case SLL:
val = (uint64_t)val1 << (uint64_t)val2;
break;
case SRA:
val = (int64_t)val1 >> (int64_t)val2;
break;
case SLA:
val = (int64_t)val1 << (int64_t)val2;
break;
case ROR:
case ROL:
return false;
}
return true;
}
+89 -22
View File
@@ -24,7 +24,7 @@
using namespace std;
void ExpAggregate::write_to_stream(ostream&fd)
void ExpAggregate::write_to_stream(ostream&fd) const
{
fd << "(";
for (vector<element_t*>::const_iterator cur = elements_.begin()
@@ -73,7 +73,7 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd)
fd << "/* ERROR */";
}
void ExpArithmetic::write_to_stream(ostream&out)
void ExpArithmetic::write_to_stream(ostream&out) const
{
out << "(";
write_to_stream_operand1(out);
@@ -111,23 +111,23 @@ void ExpArithmetic::write_to_stream(ostream&out)
out << ")";
}
void ExpAttribute::write_to_stream(ostream&fd)
void ExpAttribute::write_to_stream(ostream&fd) const
{
base_->write_to_stream(fd);
fd << "'" << name_;
}
void ExpBitstring::write_to_stream(ostream&fd)
void ExpBitstring::write_to_stream(ostream&fd) const
{
fd << "\"";
for(vector<char>::const_iterator it = value_.begin();
it != value_.end(); ++it) {
fd << "B\"";
for(vector<char>::const_reverse_iterator it = value_.rbegin();
it != value_.rend(); ++it) {
fd << *it;
}
fd << "\"";
}
void ExpCharacter::write_to_stream(ostream&fd)
void ExpCharacter::write_to_stream(ostream&fd) const
{
char buf[4];
buf[0] = '\'';
@@ -137,7 +137,7 @@ void ExpCharacter::write_to_stream(ostream&fd)
fd << buf;
}
void ExpConcat::write_to_stream(ostream&fd)
void ExpConcat::write_to_stream(ostream&fd) const
{
fd << "(";
operand1_->write_to_stream(fd);
@@ -146,21 +146,21 @@ void ExpConcat::write_to_stream(ostream&fd)
fd << ")";
}
void ExpConditional::write_to_stream(ostream&)
void ExpConditional::write_to_stream(ostream&) const
{
ivl_assert(*this, !"Not supported");
}
void ExpEdge::write_to_stream(ostream&)
void ExpEdge::write_to_stream(ostream&) const
{
ivl_assert(*this, !"Not supported");
}
void ExpFunc::write_to_stream(ostream&fd)
void ExpFunc::write_to_stream(ostream&fd) const
{
const char*comma = "";
fd << name_ << "(";
for (vector<Expression*>::iterator cur = argv_.begin()
for (vector<Expression*>::const_iterator cur = argv_.begin()
; cur != argv_.end() ; ++cur) {
fd << comma;
(*cur)->write_to_stream(fd);
@@ -169,22 +169,22 @@ void ExpFunc::write_to_stream(ostream&fd)
fd << ")";
}
void ExpInteger::write_to_stream(ostream&fd)
void ExpInteger::write_to_stream(ostream&fd) const
{
fd << value_;
}
void ExpReal::write_to_stream(ostream&fd)
void ExpReal::write_to_stream(ostream&fd) const
{
fd << value_;
}
void ExpLogical::write_to_stream(ostream&)
void ExpLogical::write_to_stream(ostream&) const
{
ivl_assert(*this, !"Not supported");
}
void ExpName::write_to_stream(ostream&fd)
void ExpName::write_to_stream(ostream&fd) const
{
if (prefix_.get()) {
prefix_->write_to_stream(fd);
@@ -203,12 +203,73 @@ void ExpName::write_to_stream(ostream&fd)
}
}
void ExpRelation::write_to_stream(ostream&)
void ExpRelation::write_to_stream(ostream&fd) const
{
ivl_assert(*this, !"Not supported");
peek_operand1()->write_to_stream(fd);
switch(fun_) {
case EQ:
fd << " = ";
break;
case LT:
fd << " < ";
break;
case GT:
fd << " > ";
break;
case NEQ:
fd << " != ";
break;
case LE:
fd << " <= ";
break;
case GE:
fd << " >= ";
break;
}
peek_operand2()->write_to_stream(fd);
}
void ExpString::write_to_stream(ostream&fd)
void ExpShift::write_to_stream(ostream&out) const
{
out << "(";
write_to_stream_operand1(out);
out << ")";
switch (shift_) {
case SRL:
out << "srl";
break;
case SLL:
out << "sll";
break;
case SLA:
out << "sla";
break;
case SRA:
out << "sra";
break;
case ROR:
out << "ror";
break;
case ROL:
out << "rol";
break;
}
out << "(";
write_to_stream_operand2(out);
out << ")";
}
void ExpString::write_to_stream(ostream&fd) const
{
fd << "\"";
for(vector<char>::const_iterator it = value_.begin();
@@ -218,15 +279,21 @@ void ExpString::write_to_stream(ostream&fd)
fd << "\"";
}
void ExpUAbs::write_to_stream(ostream&fd)
void ExpUAbs::write_to_stream(ostream&fd) const
{
fd << "abs ";
write_to_stream_operand1(fd);
}
void ExpUNot::write_to_stream(ostream&fd)
void ExpUNot::write_to_stream(ostream&fd) const
{
fd << "not ";
write_to_stream_operand1(fd);
}
void ExpCast::write_to_stream(ostream&fd) const
{
// Type casting is introduced only for a few specific cases in
// SystemVerilog, so no need to use it here
base_->write_to_stream(fd);
}
+45 -8
View File
@@ -108,6 +108,7 @@ static string make_library_package_path(perm_string lib_name, perm_string name)
static void import_ieee(void);
static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name);
static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name);
static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack)
{
@@ -211,6 +212,9 @@ void library_import(const YYLTYPE&loc, const std::list<perm_string>*names)
// The ieee library is special and handled by an
// internal function.
import_ieee();
} else if (*cur == "std") {
// The std library is always implicitly imported.
} else if (*cur == "work") {
// The work library is always implicitly imported.
@@ -238,6 +242,11 @@ void library_use(const YYLTYPE&loc, ActiveScope*res,
import_ieee_use(res, use_package, use_name);
return;
}
// Special case handling for the STD library.
if (use_library == "std") {
import_std_use(loc, res, use_package, use_name);
return;
}
struct library_contents&lib = libraries[use_library];
Package*pack = lib.packages[use_package];
@@ -361,15 +370,28 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
}
}
static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string package, perm_string name)
{
if (package == "standard") {
// do nothing
return;
} else if (package == "textio") {
cerr << "warning: textio package not really supported" << endl;
return;
} else {
sorrymsg(loc, "package %s of library %s not yet supported", package.str(), name.str());
return;
}
}
const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true);
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL);
const VTypePrimitive primitive_REAL(VTypePrimitive::REAL);
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true);
const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER);
const VTypeRange primitive_NATURAL(&primitive_INTEGER, INT64_MAX, 0);
static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector<VTypeArray::range_t> (1));
static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));
static const VTypeArray primitive_STRING(&primitive_CHARACTER, vector<VTypeArray::range_t> (1));
@@ -382,11 +404,19 @@ void generate_global_types(ActiveScope*res)
res->use_name(perm_string::literal("real"), &primitive_REAL);
res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC);
res->use_name(perm_string::literal("character"), &primitive_CHARACTER);
res->use_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR);
res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR);
res->use_name(perm_string::literal("string"), &primitive_STRING);
res->use_name(perm_string::literal("natural"), &primitive_NATURAL);
}
void emit_std_types(ostream&out)
{
out << "`ifndef __VHDL_STD_TYPES" << endl;
out << "`define __VHDL_STD_TYPES" << endl;
out << "typedef enum bit { \\false , \\true } boolean ;" << endl;
out << "`endif" << endl;
}
bool is_global_type(perm_string name)
{
if (name == "boolean") return true;
@@ -394,10 +424,13 @@ bool is_global_type(perm_string name)
if (name == "integer") return true;
if (name == "real") return true;
if (name == "std_logic") return true;
if (name == "std_logic_vector") return true;
if (name == "character") return true;
if (name == "bit_vector") return true;
if (name == "string") return true;
if (name == "natural") return true;
if (name == "signed") return true;
if (name == "unsigned") return true;
return false;
}
@@ -407,13 +440,10 @@ void library_set_work_path(const char*path)
library_work_path = path;
}
list<const Package*> work_packages;
static void store_package_in_work(const Package*pack)
{
string path = make_work_package_path(pack->name());
ofstream file (path.c_str(), ios_base::out);
pack->write_to_stream(file);
work_packages.push_back(pack);
}
static int emit_packages(perm_string, const map<perm_string,Package*>&packages)
@@ -424,6 +454,13 @@ static int emit_packages(perm_string, const map<perm_string,Package*>&packages)
errors += cur->second->emit_package(cout);
}
for (list<const Package*>::const_iterator cur = work_packages.begin()
; cur != work_packages.end(); ++cur) {
string path = make_work_package_path((*cur)->name());
ofstream file (path.c_str(), ios_base::out);
(*cur)->write_to_stream(file);
}
return errors;
}
+1
View File
@@ -26,6 +26,7 @@ extern void library_add_directory(const char*directory);
extern Subprogram*library_find_subprogram(perm_string name);
extern void emit_std_types(ostream&out);
extern int emit_packages(void);
#endif /* IVL_library_H */
+2
View File
@@ -232,6 +232,8 @@ int main(int argc, char*argv[])
return 3;
}
emit_std_types(cout);
errors = emit_packages();
if (errors > 0) {
fprintf(stderr, "%d errors emitting packages.\n", errors);
+7 -8
View File
@@ -73,12 +73,6 @@ void Package::write_to_stream(ostream&fd) const
// Do not include global types in types dump
if (is_global_type(cur->first))
continue;
if (cur->first == "std_logic_vector")
continue;
if (cur->first == "signed")
continue;
if (cur->first == "unsigned")
continue;
fd << "type " << cur->first << " is ";
cur->second->write_type_to_stream(fd);
@@ -90,8 +84,6 @@ void Package::write_to_stream(ostream&fd) const
// Do not include global types in types dump
if (is_global_type(cur->first))
continue;
if (cur->first == "std_logic_vector")
continue;
fd << "type " << cur->first << " is ";
cur->second->write_type_to_stream(fd);
@@ -130,4 +122,11 @@ void Package::write_to_stream(ostream&fd) const
}
fd << "end package " << name_ << ";" << endl;
fd << "package body " << name_ << " is" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) {
cur->second->write_to_stream_body(fd);
}
fd << "end " << name_ << ";" << endl;
}
+18 -14
View File
@@ -32,25 +32,22 @@ int Package::emit_package(ostream&fd) const
if (cur_types_.empty() && cur_constants_.empty() && cur_subprograms_.empty())
return 0;
// If this package was imported from a library, then do not
// emit it again.
if (from_library_.str() != 0) {
fd << "/* Suppress package " << name()
<< " from library " << from_library_ << " */" << endl;
return 0;
}
int errors = 0;
fd << "package \\" << name() << " ;" << endl;
fd << "`ifndef package_" << name() << endl;
fd << "`define package_" << name() << endl;
// Only emit types that were defined within this package. Skip
// the types that were imported from elsewhere.
typedef_context_t typedef_ctx;
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
; cur != cur_types_.end() ; ++ cur) {
fd << "typedef ";
errors += cur->second->emit_def(fd, cur->first);
fd << " ;" << endl;
if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
errors += def->emit_typedef(fd, typedef_ctx);
//fd << "typedef ";
//errors += cur->second->emit_def(fd,
//dynamic_cast<const VTypeDef*>(cur->second) ? empty_perm_string : cur->first);
//fd << " ;" << endl;
}
//for (map<perm_string,struct const_t*>::const_iterator cur = use_constants_.begin()
@@ -66,12 +63,19 @@ int Package::emit_package(ostream&fd) const
//fd << ";" << endl;
//}
fd << "package \\" << name() << " ;" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) {
errors += cur->second->emit_package(fd);
// Do not emit unbounded functions, we will just need fixed instances later
if(!cur->second->unbounded())
errors += cur->second->emit_package(fd);
else
fd << "/* function " << cur->second->name() <<
" has to be instantiated, skipping */" << endl;
}
fd << "endpackage" << endl;
fd << "endpackage /* " << name() << " */" << endl;
fd << "`endif" << endl;
return errors;
}
+184 -46
View File
@@ -8,7 +8,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams ([email protected])
* Copyright CERN 2012-2014 / Stephen Williams ([email protected]),
* Maciej Suminski ([email protected])
* @author Maciej Suminski ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -260,6 +260,8 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
Architecture::Statement* arch_statement;
std::list<Architecture::Statement*>* arch_statement_list;
ReportStmt::severity_t severity;
Subprogram*subprogram;
};
@@ -314,7 +316,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <arch_statement> concurrent_statement component_instantiation_statement
%type <arch_statement> concurrent_conditional_signal_assignment
%type <arch_statement> concurrent_signal_assignment_statement
%type <arch_statement> concurrent_signal_assignment_statement concurrent_simple_signal_assignment
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
%type <arch_statement> process_statement
%type <arch_statement_list> architecture_statement_part generate_statement_body
@@ -348,15 +350,16 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <text> architecture_body_start package_declaration_start
%type <text> package_body_start
%type <text> identifier_opt identifier_colon_opt logical_name suffix
%type <text> identifier_opt identifier_colon_opt logical_name suffix instantiated_unit
%type <name_list> logical_name_list identifier_list
%type <name_list> enumeration_literal_list enumeration_literal
%type <sequ_list> if_statement_else sequence_of_statements subprogram_statement_part
%type <sequ> sequential_statement if_statement signal_assignment_statement
%type <sequ> sequential_statement if_statement signal_assignment signal_assignment_statement
%type <sequ> case_statement procedure_call procedure_call_statement
%type <sequ> loop_statement variable_assignment_statement
%type <sequ> return_statement
%type <sequ> loop_statement variable_assignment variable_assignment_statement
%type <sequ> assertion_statement report_statement return_statement
%type <range> range
%type <range_list> range_list index_constraint
@@ -371,6 +374,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <exp_else_list> else_when_waveforms
%type <subprogram> function_specification subprogram_specification subprogram_body_start
%type <severity> severity severity_opt
%%
@@ -433,6 +437,22 @@ architecture_statement_part
}
;
assertion_statement
: K_assert expression report_statement
{ ReportStmt*report = dynamic_cast<ReportStmt*>($3);
assert(report);
AssertStmt*tmp = new AssertStmt($2, report->message().c_str(), report->severity());
delete report;
FILE_NAME(tmp,@2);
$$ = tmp;
}
| K_assert expression severity_opt ';'
{ AssertStmt*tmp = new AssertStmt($2, NULL, $3);
FILE_NAME(tmp,@2);
$$ = tmp;
}
;
association_element
: IDENTIFIER ARROW expression
{ named_expr_t*tmp = new named_expr_t(lex_strings.make($1), $3);
@@ -573,20 +593,40 @@ case_statement_alternative_list
* statement alternative and pass that up instead.
*/
case_statement_alternative
: K_when choice ARROW sequence_of_statements
: K_when choices ARROW sequence_of_statements
{ CaseSeqStmt::CaseStmtAlternative* tmp;
if ($2->others()) {
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
} else if (Expression*ex = $2->simple_expression()) {
tmp = new CaseSeqStmt::CaseStmtAlternative(ex, $4);
} else {
errormsg(@2, "I don't know what to make of the case choice\n");
tmp = 0;
}
if (tmp) FILE_NAME(tmp, @1);
delete $2;
delete $4;
$$ = tmp;
std::list<ExpAggregate::choice_t*>*choices = $2;
std::list<Expression*>*exp_list = new std::list<Expression*>;
bool others = false;
for(std::list<ExpAggregate::choice_t*>::iterator it = choices->begin();
it != choices->end(); ++it) {
if((*it)->others() || others)
// If there is one "others", then it also covers all other alternatives
// Continue the loop to delete every choice_t, but do not
// bother to add the expressions to the exp_list (we are going to
// delete them very soon)
others = true;
else
exp_list->push_back((*it)->simple_expression());
delete (*it);
}
if(others) {
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
for(std::list<Expression*>::iterator it = exp_list->begin();
it != exp_list->end(); ++it) {
delete (*it);
}
} else {
tmp = new CaseSeqStmt::CaseStmtAlternative(exp_list, $4);
}
if (tmp) FILE_NAME(tmp, @1);
delete choices;
delete $4;
$$ = tmp;
}
;
@@ -657,22 +697,27 @@ component_declaration
}
;
instantiated_unit
: IDENTIFIER
| K_component IDENTIFIER { $$ = $2; }
;
component_instantiation_statement
: IDENTIFIER ':' K_component_opt IDENTIFIER generic_map_aspect_opt port_map_aspect_opt ';'
: IDENTIFIER ':' instantiated_unit generic_map_aspect_opt port_map_aspect_opt ';'
{ perm_string iname = lex_strings.make($1);
perm_string cname = lex_strings.make($4);
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5, $6);
perm_string cname = lex_strings.make($3);
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $4, $5);
delete $4;
delete $5;
delete $6;
FILE_NAME(tmp, @1);
delete[]$1;
delete[]$4;
delete[]$3;
$$ = tmp;
}
| IDENTIFIER ':' K_component_opt IDENTIFIER error ';'
| IDENTIFIER ':' instantiated_unit error ';'
{ errormsg(@4, "Errors in component instantiation.\n");
delete[]$1;
delete[]$4;
delete[]$3;
$$ = 0;
}
;
@@ -706,7 +751,6 @@ composite_type_definition
{ $$ = $1; }
;
/* The when...else..when...else syntax is not a general expression
in VHDL but a specific sort of assignment statement model. We
create Exppression objects for it, but the parser will only
@@ -743,6 +787,17 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
}
;
concurrent_simple_signal_assignment
: name LEQ waveform ';'
{ ExpName*name = dynamic_cast<ExpName*> ($1);
assert(name);
SignalAssignment*tmp = new SignalAssignment(name, *$3);
FILE_NAME(tmp, @1);
$$ = tmp;
delete $3;
}
else_when_waveforms
: else_when_waveforms else_when_waveform
{ list<ExpConditional::else_t*>*tmp = $1;
@@ -770,18 +825,14 @@ else_when_waveform
;
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
: name LEQ waveform ';'
{ ExpName*name = dynamic_cast<ExpName*> ($1);
assert(name);
SignalAssignment*tmp = new SignalAssignment(name, *$3);
FILE_NAME(tmp, @1);
: concurrent_simple_signal_assignment
$$ = tmp;
delete $3;
}
| IDENTIFIER ':' concurrent_simple_signal_assignment { $$ = $3; }
| concurrent_conditional_signal_assignment
| IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; }
| name LEQ error ';'
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
delete $1;
@@ -1539,10 +1590,17 @@ mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
name /* IEEE 1076-2008 P8.1 */
: IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */
{ ExpName*tmp = new ExpName(lex_strings.make($1));
FILE_NAME(tmp, @1);
delete[]$1;
$$ = tmp;
{ Expression*tmp;
if(!strcasecmp($1, "true"))
tmp = new ExpBitstring("1");
else if(!strcasecmp($1, "false"))
tmp = new ExpBitstring("0");
else
tmp = new ExpName(lex_strings.make($1));
FILE_NAME(tmp, @1);
delete[]$1;
$$ = tmp;
}
| selected_name
@@ -1570,11 +1628,16 @@ name /* IEEE 1076-2008 P8.1 */
delete[]$1;
$$ = tmp;
}
| selected_name '(' range ')'
| selected_name '(' range ')'
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
tmp->set_range($3->msb(), $3->lsb());
$$ = tmp;
}
| selected_name '(' expression ')'
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
tmp->set_range($3, NULL);
$$ = tmp;
}
;
/* Handle name lists as lists of expressions. */
@@ -1771,6 +1834,7 @@ primary
delete[]$1;
$$ = tmp;
}
/*XXXX Caught up in element_association_list?
| '(' expression ')'
{ $$ = $2; }
@@ -1993,6 +2057,14 @@ relation
}
;
report_statement
: K_report STRING_LITERAL severity_opt ';'
{ ReportStmt*tmp = new ReportStmt($2, $3);
FILE_NAME(tmp,@2);
delete[]$2;
$$ = tmp;
}
return_statement
: K_return expression ';'
{ ReturnStmt*tmp = new ReturnStmt($2);
@@ -2100,6 +2172,8 @@ sequential_statement
| procedure_call_statement { $$ = $1; }
| loop_statement { $$ = $1; }
| return_statement { $$ = $1; }
| report_statement { $$ = $1; }
| assertion_statement { $$ = $1; }
| K_null ';' { $$ = 0; }
| error ';'
{ errormsg(@1, "Syntax error in sequential statement.\n");
@@ -2108,7 +2182,61 @@ sequential_statement
}
;
shift_expression : simple_expression { $$ = $1; } ;
severity
: K_severity IDENTIFIER
{ if(!strcasecmp($2, "NOTE"))
$$ = ReportStmt::NOTE;
else if(!strcasecmp($2, "WARNING"))
$$ = ReportStmt::WARNING;
else if(!strcasecmp($2, "ERROR"))
$$ = ReportStmt::ERROR;
else if(!strcasecmp($2, "FAILURE"))
$$ = ReportStmt::FAILURE;
else {
errormsg(@1, "Invalid severity level (possible values: NOTE, WARNING, ERROR, FAILURE).\n");
$$ = ReportStmt::UNSPECIFIED;
}
}
severity_opt
: severity { $$ = $1; }
| { $$ = ReportStmt::UNSPECIFIED; }
shift_expression
: simple_expression
| simple_expression K_srl simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SRL, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_sll simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SLL, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_sra simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SRA, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_sla simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SLA, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_ror simple_expression
{ sorrymsg(@2, "ROR is not supported.\n");
ExpShift*tmp = new ExpShift(ExpShift::ROR, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_rol simple_expression
{ sorrymsg(@2, "ROL is not supported.\n");
ExpShift*tmp = new ExpShift(ExpShift::ROL, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
;
sign
: '+'
@@ -2186,7 +2314,7 @@ simple_expression_terms
}
;
signal_assignment_statement
signal_assignment
: name LEQ waveform ';'
{ SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
FILE_NAME(tmp, @1);
@@ -2201,6 +2329,10 @@ signal_assignment_statement
}
;
signal_assignment_statement
: signal_assignment
| IDENTIFIER ':' signal_assignment { $$ = $3; }
subprogram_body_start
: subprogram_specification K_is
{ assert(!active_sub);
@@ -2223,7 +2355,7 @@ subprogram_body /* IEEE 1076-2008 P4.3 */
} else if (tmp) {
errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str());
}
prog->transfer_from(*active_scope);
prog->transfer_from(*active_scope, ScopeBase::VARIABLES);
prog->set_program_body($4);
active_scope->bind_name(prog->name(), prog);
active_sub = NULL;
@@ -2373,6 +2505,9 @@ type_declaration
tmp->set_definition($4);
active_scope->incomplete_types.erase(cur);
}
if(const VTypeEnum*enum_type = dynamic_cast<const VTypeEnum*>($4)) {
active_scope->use_enum(enum_type);
}
}
delete[]$2;
}
@@ -2429,6 +2564,10 @@ use_clauses_opt
;
variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
: variable_assignment
| IDENTIFIER ':' variable_assignment { $$ = $3; }
variable_assignment
: name VASSIGN expression ';'
{ VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3);
FILE_NAME(tmp, @1);
@@ -2495,7 +2634,6 @@ waveform_element
/* Some keywords are optional in some contexts. In all such cases, a
similar rule is used, as described here. */
K_architecture_opt : K_architecture | ;
K_component_opt : K_component | ;
K_configuration_opt: K_configuration| ;
K_entity_opt : K_entity | ;
K_is_opt : K_is | ;
@@ -2504,9 +2642,9 @@ K_postponed_opt : K_postponed | ;
K_shared_opt : K_shared | ;
%%
static void yyerror(YYLTYPE*, yyscan_t, const char*, bool, const char* /*msg*/)
static void yyerror(YYLTYPE*loc, yyscan_t, const char*, bool, const char*msg)
{
//fprintf(stderr, "%s\n", msg);
fprintf(stderr, "%s:%u: %s\n", loc->text, loc->first_line, msg);
parse_errors += 1;
}
+1
View File
@@ -105,6 +105,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
VTypeArray*subtype = new VTypeArray(element, range,
base_array->signed_vector());
subtype->set_parent_type(base_array);
return subtype;
}
+3 -1
View File
@@ -72,6 +72,9 @@ class prange_t {
public:
prange_t(Expression* left, Expression* right, bool dir)
: left_(left), right_(right), direction_(dir), auto_dir_(false) {}
prange_t(const prange_t&other) :
left_(other.left_->clone()), right_(other.right_->clone()),
direction_(other.direction_), auto_dir_(other.auto_dir_) {}
~prange_t() { delete left_; delete right_; }
void dump(ostream&out, int indent) const;
@@ -91,7 +94,6 @@ class prange_t {
bool auto_dir_;
private: //not implemented
prange_t(const prange_t&);
prange_t operator=(const prange_t&);
};
+66 -17
View File
@@ -21,6 +21,7 @@
# include "scope.h"
# include "package.h"
# include "subprogram.h"
# include "entity.h"
# include <algorithm>
# include <iostream>
# include <iterator>
@@ -58,6 +59,8 @@ ScopeBase::ScopeBase(const ActiveScope&ref)
use_subprograms_ = ref.use_subprograms_;
cur_subprograms_ = ref.cur_subprograms_;
use_enums_ = ref.use_enums_;
// This constructor is invoked when the parser is finished with
// an active scope and is making the actual scope. At this point
// we know that "this" is the parent scope for the subprograms,
@@ -101,8 +104,11 @@ const VType*ScopeBase::find_type(perm_string by_name)
return cur->second;
}
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp)
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const
{
typ = NULL;
exp = NULL;
map<perm_string,struct const_t*>::const_iterator cur = cur_constants_.find(by_name);
if (cur == cur_constants_.end()) {
cur = use_constants_.find(by_name);
@@ -118,6 +124,8 @@ bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*
exp = cur->second->val;
return true;
}
return false;
}
Signal* ScopeBase::find_signal(perm_string by_name) const
@@ -148,6 +156,23 @@ Variable* ScopeBase::find_variable(perm_string by_name) const
}
}
const InterfacePort* ScopeBase::find_param(perm_string by_name) const
{
for(map<perm_string,Subprogram*>::const_iterator it = use_subprograms_.begin();
it != use_subprograms_.end(); ++it) {
if(const InterfacePort*port = it->second->find_param(by_name))
return port;
}
for(map<perm_string,Subprogram*>::const_iterator it = cur_subprograms_.begin();
it != cur_subprograms_.end(); ++it) {
if(const InterfacePort*port = it->second->find_param(by_name))
return port;
}
return NULL;
}
Subprogram* ScopeBase::find_subprogram(perm_string name) const
{
map<perm_string,Subprogram*>::const_iterator cur;
@@ -163,6 +188,17 @@ Subprogram* ScopeBase::find_subprogram(perm_string name) const
return 0;
}
const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const
{
for(list<const VTypeEnum*>::const_iterator it = use_enums_.begin();
it != use_enums_.end(); ++it) {
if((*it)->has_name(name))
return *it;
}
return NULL;
}
/*
* This method is only used by the ActiveScope derived class to import
* definition from another scope.
@@ -201,27 +237,35 @@ void ScopeBase::do_use_from(const ScopeBase*that)
; cur != that->cur_constants_.end() ; ++ cur) {
use_constants_[cur->first] = cur->second;
}
use_enums_ = that->use_enums_;
}
void ScopeBase::transfer_from(ScopeBase&ref)
void ScopeBase::transfer_from(ScopeBase&ref, transfer_type_t what)
{
std::copy(ref.new_signals_.begin(), ref.new_signals_.end(),
insert_iterator<map<perm_string, Signal*> >(
new_signals_, new_signals_.end())
);
ref.new_signals_.clear();
if(what & SIGNALS) {
std::copy(ref.new_signals_.begin(), ref.new_signals_.end(),
insert_iterator<map<perm_string, Signal*> >(
new_signals_, new_signals_.end())
);
ref.new_signals_.clear();
}
std::copy(ref.new_variables_.begin(), ref.new_variables_.end(),
insert_iterator<map<perm_string, Variable*> >(
new_variables_, new_variables_.end())
);
ref.new_variables_.clear();
if(what & VARIABLES) {
std::copy(ref.new_variables_.begin(), ref.new_variables_.end(),
insert_iterator<map<perm_string, Variable*> >(
new_variables_, new_variables_.end())
);
ref.new_variables_.clear();
}
std::copy(ref.new_components_.begin(), ref.new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
new_components_, new_components_.end())
);
ref.new_components_.clear();
if(what & COMPONENTS) {
std::copy(ref.new_components_.begin(), ref.new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
new_components_, new_components_.end())
);
ref.new_components_.clear();
}
}
void ActiveScope::set_package_header(Package*pkg)
@@ -248,6 +292,11 @@ bool ActiveScope::is_vector_name(perm_string name) const
if (find_variable(name))
return true;
const VType*dummy_type;
Expression*dummy_exp;
if (find_constant(name, dummy_type, dummy_exp))
return true;
if (context_entity_ && context_entity_->find_port(name))
return true;
+22 -4
View File
@@ -53,13 +53,26 @@ class ScopeBase {
virtual ~ScopeBase() =0;
const VType* find_type(perm_string by_name);
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
virtual bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const;
Signal* find_signal(perm_string by_name) const;
Variable* find_variable(perm_string by_name) const;
virtual const InterfacePort* find_param(perm_string by_name) const;
Subprogram* find_subprogram(perm_string by_name) const;
// Moves all signals, variables and components from another scope to
// this one. After the transfer new_* maps are emptied in the another scope.
void transfer_from(ScopeBase&ref);
// Checks if a string is one of possible enum values. If so, the enum
// type is returned, otherwise NULL.
const VTypeEnum* is_enum_name(perm_string name) const;
// Moves signals, variables and components from another scope to
// this one. After the transfer new_* maps are cleared in the source scope.
enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff };
void transfer_from(ScopeBase&ref, transfer_type_t what = ALL);
inline void bind_subprogram(perm_string name, Subprogram*obj)
{ map<perm_string, Subprogram*>::iterator it;
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
use_subprograms_.erase(it);
cur_subprograms_[name] = obj;
}
protected:
void cleanup();
@@ -106,6 +119,8 @@ class ScopeBase {
std::map<perm_string, Subprogram*> use_subprograms_; //imported
std::map<perm_string, Subprogram*> cur_subprograms_; //current
std::list<const VTypeEnum*> use_enums_;
void do_use_from(const ScopeBase*that);
};
@@ -191,6 +206,9 @@ class ActiveScope : public ScopeBase {
cur_types_[name] = t;
}
inline void use_enum(const VTypeEnum* t)
{ use_enums_.push_back(t); }
inline void use_name(perm_string name, const VType* t)
{ use_types_[name] = t; }
+68 -1
View File
@@ -19,6 +19,15 @@
# include "sequential.h"
# include "expression.h"
# include <cassert>
template<typename T>
inline static void visit_stmt_list(std::list<T*>& stmts, SeqStmtVisitor& func)
{
for(typename std::list<T*>::iterator it = stmts.begin(); it != stmts.end(); ++it) {
(*it)->visit(func);
}
}
SequentialStmt::SequentialStmt()
{
@@ -75,6 +84,14 @@ void IfSequential::extract_false(std::list<SequentialStmt*>&that)
}
}
void IfSequential::visit(SeqStmtVisitor& func)
{
visit_stmt_list(if_, func);
visit_stmt_list(elsif_, func);
visit_stmt_list(else_, func);
func(this);
}
IfSequential::Elsif::Elsif(Expression*cond, std::list<SequentialStmt*>*tr)
: cond_(cond)
{
@@ -91,6 +108,11 @@ IfSequential::Elsif::~Elsif()
}
}
void IfSequential::Elsif::visit(SeqStmtVisitor& func)
{
visit_stmt_list(if_, func);
}
SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav)
{
lval_ = sig;
@@ -118,7 +140,14 @@ CaseSeqStmt::~CaseSeqStmt()
}
}
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list<SequentialStmt*>* stmts)
void CaseSeqStmt::visit(SeqStmtVisitor& func)
{
visit_stmt_list(alt_, func);
func(this);
}
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(std::list<Expression*>*exp,
list<SequentialStmt*>*stmts)
: exp_(exp)
{
if (stmts) stmts_.splice(stmts_.end(), *stmts);
@@ -134,6 +163,11 @@ CaseSeqStmt::CaseStmtAlternative::~CaseStmtAlternative()
}
}
void CaseSeqStmt::CaseStmtAlternative::visit(SeqStmtVisitor& func)
{
visit_stmt_list(stmts_, func);
}
ProcedureCall::ProcedureCall(perm_string name)
: name_(name), param_list_(0)
{
@@ -163,6 +197,12 @@ ReturnStmt::~ReturnStmt()
delete val_;
}
void ReturnStmt::cast_to(const VType*type)
{
assert(val_);
val_ = new ExpCast(val_, type);
}
LoopStatement::LoopStatement(perm_string name, list<SequentialStmt*>* stmts)
: name_(name)
{
@@ -178,6 +218,12 @@ LoopStatement::~LoopStatement()
}
}
void LoopStatement::visit(SeqStmtVisitor& func)
{
visit_stmt_list(stmts_, func);
func(this);
}
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list<SequentialStmt*>* stmts)
: LoopStatement(scope_name, stmts), it_(it), range_(range)
{
@@ -217,3 +263,24 @@ BasicLoopStatement::BasicLoopStatement(perm_string lname, list<SequentialStmt*>*
BasicLoopStatement::~BasicLoopStatement()
{
}
ReportStmt::ReportStmt(const char*msg, severity_t sev)
: msg_(msg), severity_(sev)
{
if(sev == ReportStmt::UNSPECIFIED)
severity_ = ReportStmt::NOTE;
}
AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severity_t sev)
: ReportStmt("", sev), cond_(condition)
{
if(msg == NULL)
msg_ = default_msg_;
else
msg_ = std::string(msg);
if(sev == ReportStmt::UNSPECIFIED)
severity_ = ReportStmt::ERROR;
}
const std::string AssertStmt::default_msg_ = std::string("Assertion violation.");
+95 -30
View File
@@ -23,10 +23,17 @@
# include "LineInfo.h"
# include "parse_types.h"
# include <list>
# include <functional>
class Architecture;
class ScopeBase;
class Entity;
class Expression;
class SequentialStmt;
struct SeqStmtVisitor {
virtual ~SeqStmtVisitor() {};
virtual void operator() (SequentialStmt*s) = 0;
};
class SequentialStmt : public LineInfo {
@@ -35,9 +42,13 @@ class SequentialStmt : public LineInfo {
virtual ~SequentialStmt() =0;
public:
virtual int elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
virtual int elaborate(Entity*ent, ScopeBase*scope);
virtual int emit(ostream&out, Entity*entity, ScopeBase*scope);
virtual void dump(ostream&out, int indent) const;
virtual void write_to_stream(std::ostream&fd);
// Recursively visits a tree of sequential statements.
virtual void visit(SeqStmtVisitor& func) { func(this); }
};
/*
@@ -52,10 +63,12 @@ class LoopStatement : public SequentialStmt {
inline perm_string loop_name() const { return name_; }
void dump(ostream&out, int indent) const;
void visit(SeqStmtVisitor& func);
protected:
int elaborate_substatements(Entity*ent, Architecture*arc);
int emit_substatements(std::ostream&out, Entity*ent, Architecture*arc);
int elaborate_substatements(Entity*ent, ScopeBase*scope);
int emit_substatements(std::ostream&out, Entity*ent, ScopeBase*scope);
void write_to_stream_substatements(ostream&fd);
private:
perm_string name_;
@@ -70,11 +83,15 @@ class IfSequential : public SequentialStmt {
Elsif(Expression*cond, std::list<SequentialStmt*>*tr);
~Elsif();
int elaborate(Entity*entity, Architecture*arc);
int condition_emit(ostream&out, Entity*entity, Architecture*arc);
int statement_emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*entity, ScopeBase*scope);
int condition_emit(ostream&out, Entity*entity, ScopeBase*scope);
int statement_emit(ostream&out, Entity*entity, ScopeBase*scope);
void condition_write_to_stream(ostream&fd);
void statement_write_to_stream(ostream&fd);
void dump(ostream&out, int indent) const;
void visit(SeqStmtVisitor& func);
private:
Expression*cond_;
@@ -91,9 +108,11 @@ class IfSequential : public SequentialStmt {
~IfSequential();
public:
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const;
void visit(SeqStmtVisitor& func);
const Expression*peek_condition() const { return cond_; }
@@ -117,10 +136,12 @@ class ReturnStmt : public SequentialStmt {
~ReturnStmt();
public:
int emit(ostream&out, Entity*entity, Architecture*arc);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const;
const Expression*peek_expr() const { return val_; };
void cast_to(const VType*type);
private:
Expression*val_;
@@ -132,8 +153,9 @@ class SignalSeqAssignment : public SequentialStmt {
~SignalSeqAssignment();
public:
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const;
private:
@@ -145,15 +167,17 @@ class CaseSeqStmt : public SequentialStmt {
public:
class CaseStmtAlternative : public LineInfo {
public:
CaseStmtAlternative(Expression* exp, std::list<SequentialStmt*>* stmts);
CaseStmtAlternative(std::list<Expression*>*exp, std::list<SequentialStmt*>*stmts);
~CaseStmtAlternative();
void dump(std::ostream& out, int indent) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void visit(SeqStmtVisitor& func);
private:
Expression* exp_;
std::list<Expression*>*exp_;
std::list<SequentialStmt*> stmts_;
private: // not implemented
CaseStmtAlternative(const CaseStmtAlternative&);
@@ -166,8 +190,10 @@ class CaseSeqStmt : public SequentialStmt {
public:
void dump(ostream&out, int indent) const;
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void visit(SeqStmtVisitor& func);
private:
Expression* cond_;
@@ -180,8 +206,8 @@ class ProcedureCall : public SequentialStmt {
ProcedureCall(perm_string name, std::list<named_expr_t*>* param_list);
~ProcedureCall();
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void dump(ostream&out, int indent) const;
private:
@@ -195,8 +221,9 @@ class VariableSeqAssignment : public SequentialStmt {
~VariableSeqAssignment();
public:
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const;
private:
@@ -210,8 +237,7 @@ class WhileLoopStatement : public LoopStatement {
ExpLogical*, list<SequentialStmt*>*);
~WhileLoopStatement();
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent) const;
private:
@@ -224,11 +250,16 @@ class ForLoopStatement : public LoopStatement {
perm_string index, prange_t*, list<SequentialStmt*>*);
~ForLoopStatement();
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const;
private:
// Emits for-loop which direction is determined at run-time.
// It is used for 'range & 'reverse_range attributes.
int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope);
perm_string it_;
prange_t* range_;
};
@@ -238,9 +269,43 @@ class BasicLoopStatement : public LoopStatement {
BasicLoopStatement(perm_string lname, list<SequentialStmt*>*);
~BasicLoopStatement();
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
int elaborate(Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent) const;
};
class ReportStmt : public SequentialStmt {
public:
typedef enum { UNSPECIFIED, NOTE, WARNING, ERROR, FAILURE } severity_t;
ReportStmt(const char*message, severity_t severity = NOTE);
virtual ~ReportStmt() {}
void dump(ostream&out, int indent) const;
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
inline const std::string& message() const { return msg_; }
inline severity_t severity() const { return severity_; }
protected:
std::string msg_;
severity_t severity_;
};
class AssertStmt : public ReportStmt {
public:
AssertStmt(Expression*condition, const char*message, ReportStmt::severity_t severity = ReportStmt::ERROR);
void dump(ostream&out, int indent) const;
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
private:
Expression*cond_;
// Message displayed when there is no report assigned.
static const std::string default_msg_;
};
#endif /* IVL_sequential_H */
+18 -1
View File
@@ -105,7 +105,9 @@ void CaseSeqStmt::CaseStmtAlternative::dump(ostream& out, int indent) const
out << setw(indent) << "" << "when ";
if (exp_)
exp_->dump(out, 0);
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
(*it)->dump(out, 0);
}
else
out << "others" << endl;
@@ -163,3 +165,18 @@ void BasicLoopStatement::dump(ostream&out, int indent) const
out << setw(indent) << "" << "BasicLoopStatement at file=" << get_fileline() << endl;
LoopStatement::dump(out, indent+2);
}
void ReportStmt::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "ReportStmt at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "severity: " << severity_ << endl;
out << setw(indent+3) << "" << "message: " << msg_ << endl;
}
void AssertStmt::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "AssertStmt at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "condition: ";
cond_->dump(out, indent+3);
ReportStmt::dump(out, indent+3);
}
+41 -33
View File
@@ -20,35 +20,35 @@
# include "sequential.h"
# include "expression.h"
int SequentialStmt::elaborate(Entity*, Architecture*)
int SequentialStmt::elaborate(Entity*, ScopeBase*)
{
return 0;
}
int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc)
int LoopStatement::elaborate_substatements(Entity*ent, ScopeBase*scope)
{
int errors = 0;
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
errors += (*cur)->elaborate(ent, scope);
}
return errors;
}
int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
const VType*ctype = cond_->probe_type(ent, arc);
errors += cond_->elaborate_expr(ent, arc, ctype);
const VType*ctype = cond_->probe_type(ent, scope);
errors += cond_->elaborate_expr(ent, scope, ctype);
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
; cur != alt_.end() ; ++cur) {
CaseStmtAlternative*curp = *cur;
errors += curp->elaborate_expr(ent, arc, ctype);
errors += curp->elaborate(ent, arc);
errors += curp->elaborate_expr(ent, scope, ctype);
errors += curp->elaborate(ent, scope);
}
return errors;
@@ -59,79 +59,82 @@ int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
* ltype is the probed type for the main case condition. The
* expression needs to elaborate itself in that context.
*/
int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (exp_)
errors += exp_->elaborate_expr(ent, arc, ltype);
if (exp_) {
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end();
++it) {
errors += (*it)->elaborate_expr(ent, scope, ltype);
}
}
return errors;
}
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc)
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
SequentialStmt*curp = *cur;
errors += curp->elaborate(ent, arc);
errors += curp->elaborate(ent, scope);
}
return errors;
}
int ForLoopStatement::elaborate(Entity*ent, Architecture*arc)
int ForLoopStatement::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += elaborate_substatements(ent, arc);
errors += elaborate_substatements(ent, scope);
return errors;
}
int IfSequential::elaborate(Entity*ent, Architecture*arc)
int IfSequential::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += cond_->elaborate_expr(ent, arc, 0);
errors += cond_->elaborate_expr(ent, scope, 0);
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
errors += (*cur)->elaborate(ent, scope);
}
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
; cur != elsif_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
errors += (*cur)->elaborate(ent, scope);
}
for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
errors += (*cur)->elaborate(ent, scope);
}
return errors;
}
int IfSequential::Elsif::elaborate(Entity*ent, Architecture*arc)
int IfSequential::Elsif::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += cond_->elaborate_expr(ent, arc, 0);
errors += cond_->elaborate_expr(ent, scope, 0);
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
errors += (*cur)->elaborate(ent, scope);
}
return errors;
}
int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Elaborate the l-value expression.
errors += lval_->elaborate_lval(ent, arc, true);
errors += lval_->elaborate_lval(ent, scope, true);
// The elaborate_lval should have resolved the type of the
// l-value expression. We'll use that type to elaborate the
@@ -146,23 +149,23 @@ int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
for (list<Expression*>::iterator cur = waveform_.begin()
; cur != waveform_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
errors += (*cur)->elaborate_expr(ent, scope, lval_type);
}
return errors;
}
int ProcedureCall::elaborate(Entity*, Architecture*)
int ProcedureCall::elaborate(Entity*, ScopeBase*)
{
return 0;
}
int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Elaborate the l-value expression.
errors += lval_->elaborate_lval(ent, arc, true);
errors += lval_->elaborate_lval(ent, scope, true);
// The elaborate_lval should have resolved the type of the
// l-value expression. We'll use that type to elaborate the
@@ -174,18 +177,23 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
}
// Elaborate the r-value expression.
errors += rval_->elaborate_expr(ent, arc, lval_type);
errors += rval_->elaborate_expr(ent, scope, lval_type);
return errors;
}
int WhileLoopStatement::elaborate(Entity*, Architecture*)
int WhileLoopStatement::elaborate(Entity*, ScopeBase*)
{
//TODO:check whether there is any wait statement in the statements (there should be)
return 0;
}
int BasicLoopStatement::elaborate(Entity*, Architecture*)
int BasicLoopStatement::elaborate(Entity*, ScopeBase*)
{
return 0;
}
int AssertStmt::elaborate(Entity*ent, ScopeBase*scope)
{
return cond_->elaborate_expr(ent, scope, 0);
}
+333 -108
View File
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -27,7 +29,7 @@
# include <typeinfo>
# include <ivl_assert.h>
int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
int SequentialStmt::emit(ostream&out, Entity*, ScopeBase*)
{
out << " // " << get_fileline() << ": internal error: "
<< "I don't know how to emit this sequential statement! "
@@ -35,23 +37,30 @@ int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
return 1;
}
int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
void SequentialStmt::write_to_stream(std::ostream&fd)
{
fd << " // " << get_fileline() << ": internal error: "
<< "I don't know how to write_to_stream this sequential statement! "
<< "type=" << typeid(*this).name() << endl;
}
int IfSequential::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "if (";
errors += cond_->emit(out, ent, arc);
errors += cond_->emit(out, ent, scope);
out << ") begin" << endl;
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur)
errors += (*cur)->emit(out, ent, arc);
errors += (*cur)->emit(out, ent, scope);
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
; cur != elsif_.end() ; ++cur) {
out << "end else if (";
errors += (*cur)->condition_emit(out, ent, arc);
errors += (*cur)->condition_emit(out, ent, scope);
out << ") begin" << endl;
errors += (*cur)->statement_emit(out, ent, arc);
errors += (*cur)->statement_emit(out, ent, scope);
}
if (! else_.empty()) {
@@ -59,7 +68,7 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur)
errors += (*cur)->emit(out, ent, arc);
errors += (*cur)->emit(out, ent, scope);
}
@@ -67,36 +76,84 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, Architecture*arc)
void IfSequential::write_to_stream(std::ostream&fd)
{
return cond_->emit(out, ent, arc);
fd << "if ";
cond_->write_to_stream(fd);
fd << " then " << endl;
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur)
(*cur)->write_to_stream(fd);
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
; cur != elsif_.end() ; ++cur) {
fd << "elsif ";
(*cur)->condition_write_to_stream(fd);
fd << " " << endl;
(*cur)->statement_write_to_stream(fd);
}
if (! else_.empty()) {
fd << " else " << endl;
for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur)
(*cur)->write_to_stream(fd);
}
fd << "end if;" << endl;
}
int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, Architecture*arc)
int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, ScopeBase*scope)
{
return cond_->emit(out, ent, scope);
}
int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur)
errors += (*cur)->emit(out, ent, arc);
errors += (*cur)->emit(out, ent, scope);
return errors;
}
int ReturnStmt::emit(ostream&out, Entity*ent, Architecture*arc)
void IfSequential::Elsif::condition_write_to_stream(ostream&fd)
{
cond_->write_to_stream(fd);
}
void IfSequential::Elsif::statement_write_to_stream(ostream&fd)
{
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur)
(*cur)->write_to_stream(fd);
}
int ReturnStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "return ";
errors += val_->emit(out, ent, arc);
errors += val_->emit(out, ent, scope);
out << ";" << endl;
return errors;
}
int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
void ReturnStmt::write_to_stream(ostream&fd)
{
fd << "return ";
val_->write_to_stream(fd);
fd << ";" << endl;
}
int SignalSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += lval_->emit(out, ent, arc);
errors += lval_->emit(out, ent, scope);
if (waveform_.size() != 1) {
out << "/* Confusing waveform? */;" << endl;
@@ -105,27 +162,50 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
} else {
Expression*tmp = waveform_.front();
out << " <= ";
errors += tmp->emit(out, ent, arc);
errors += tmp->emit(out, ent, scope);
out << ";" << endl;
}
return errors;
}
int VariableSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
void SignalSeqAssignment::write_to_stream(ostream&fd)
{
lval_->write_to_stream(fd);
if (waveform_.size() != 1) {
fd << "-- Confusing waveform?" << endl;
} else {
Expression*tmp = waveform_.front();
fd << " <= ";
tmp->write_to_stream(fd);
fd << ";" << endl;
}
}
int VariableSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += lval_->emit(out, ent, arc);
errors += lval_->emit(out, ent, scope);
out << " = ";
errors += rval_->emit(out, ent, arc);
errors += rval_->emit(out, ent, scope);
out << ";" << endl;
return errors;
}
int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
void VariableSeqAssignment::write_to_stream(ostream&fd)
{
lval_->write_to_stream(fd);
fd << " := ";
rval_->write_to_stream(fd);
fd << ";" << endl;
}
int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*)
{
out << " // " << get_fileline() << ": internal error: "
<< "I don't know how to emit this sequential statement! "
@@ -133,29 +213,38 @@ int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
return 1;
}
int LoopStatement::emit_substatements(ostream&out, Entity*ent, Architecture*arc)
int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
SequentialStmt*tmp = *cur;
errors += tmp->emit(out, ent, arc);
errors += tmp->emit(out, ent, scope);
}
return errors;
}
int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc)
void LoopStatement::write_to_stream_substatements(ostream&fd)
{
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
SequentialStmt*tmp = *cur;
tmp->write_to_stream(fd);
}
}
int CaseSeqStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "case (";
errors += cond_->emit(out, ent, arc);
errors += cond_->emit(out, ent, scope);
out << ")" << endl;
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
; cur != alt_.end() ; ++cur) {
CaseStmtAlternative*curp = *cur;
errors += curp ->emit(out, ent, arc);
errors += curp ->emit(out, ent, scope);
}
out << "endcase" << endl;
@@ -163,16 +252,38 @@ int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture*arc)
void CaseSeqStmt::write_to_stream(ostream&fd)
{
fd << "case ";
cond_->write_to_stream(fd);
fd << " is" << endl;
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
; cur != alt_.end() ; ++cur) {
CaseStmtAlternative*curp = *cur;
curp ->write_to_stream(fd);
}
fd << "end case;" << endl;
}
int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
bool first = true;
if (exp_) {
errors += exp_->emit(out, ent, arc);
out << ":" << endl;
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
if(first)
first = false;
else
out << ",";
errors += (*it)->emit(out, ent, scope);
}
} else {
out << "default:" << endl;
out << "default";
}
out << ":" << endl;
SequentialStmt*curp;
@@ -182,14 +293,14 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
break;
case 1:
curp = stmts_.front();
errors += curp->emit(out, ent, arc);
errors += curp->emit(out, ent, scope);
break;
default:
out << "begin" << endl;
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
curp = *cur;
errors += curp->emit(out, ent, arc);
errors += curp->emit(out, ent, scope);
}
out << "end" << endl;
break;
@@ -198,92 +309,206 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
return errors;
}
int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc)
void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd)
{
int errors = 0;
ivl_assert(*this, range_);
fd << "when ";
if (exp_) {
bool first = true;
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
if(first)
first = false;
else
fd << "|";
int64_t start_val;
bool start_rc = range_->msb()->evaluate(ent, arc, start_val);
int64_t finish_val;
bool finish_rc = range_->lsb()->evaluate(ent, arc, finish_val);
ivl_assert(*this, start_rc);
ivl_assert(*this, finish_rc);
bool dir = range_->is_downto();
if (!dir) {
int64_t tmp = start_val;
start_val = finish_val;
finish_val = tmp;
(*it)->write_to_stream(fd);
}
} else {
fd << "others" << endl;
}
fd << "=>" << endl;
if (dir && (start_val < finish_val)) {
if(range_->is_auto_dir()) {
dir = false;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " downto " << finish_val << " */ end" << endl;
return errors;
}
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
(*cur)->write_to_stream(fd);
}
else if (!dir && start_val > finish_val) {
if(range_->is_auto_dir()) {
dir = true;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " to " << finish_val << " */ end" << endl;
return errors;
}
}
perm_string scope_name = loop_name();
if (scope_name.nil()) {
char buf[80];
snprintf(buf, sizeof buf, "__%p", this);
scope_name = lex_strings.make(buf);
}
out << "begin : " << scope_name << endl;
out << "longint \\" << it_ << " ;" << endl;
out << "for (\\" << it_ << " = " << start_val << " ; ";
if (dir)
out << "\\" << it_ << " >= " << finish_val;
else
out << "\\" << it_ << " <= " << finish_val;
out << "; \\" << it_ << " = \\" << it_;
if (dir)
out << " - 1";
else
out << " + 1";
out << ") begin" << endl;
errors += emit_substatements(out, ent, arc);
out << "end" << endl;
out << "end /* " << scope_name << " */" << endl;
return errors;
}
int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*)
int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
out << " // " << get_fileline() << ": internal error: "
<< "I don't know how to emit this sequential statement! "
<< "type=" << typeid(*this).name() << endl;
return 1;
int errors = 0;
ivl_assert(*this, range_);
int64_t start_val;
bool start_rc = range_->msb()->evaluate(ent, scope, start_val);
int64_t finish_val;
bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val);
perm_string scope_name = loop_name();
if (scope_name.nil()) {
char buf[80];
snprintf(buf, sizeof buf, "__%p", this);
scope_name = lex_strings.make(buf);
}
out << "begin : " << scope_name << endl;
out << "longint \\" << it_ << " ;" << endl;
if(!start_rc || !finish_rc) {
// Could not evaluate one of the loop boundaries, it has to be
// determined during the run-time
errors += emit_runtime_(out, ent, scope);
} else {
bool dir = range_->is_downto();
if (!dir) {
int64_t tmp = start_val;
start_val = finish_val;
finish_val = tmp;
}
if (dir && (start_val < finish_val)) {
if(range_->is_auto_dir()) {
dir = false;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " downto " << finish_val << " */ end" << endl
<< "end" << endl;
return errors;
}
}
else if (!dir && start_val > finish_val) {
if(range_->is_auto_dir()) {
dir = true;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " to " << finish_val << " */ end" << endl
<< "end" << endl;
return errors;
}
}
out << "for (\\" << it_ << " = " << start_val << " ; ";
if (dir)
out << "\\" << it_ << " >= " << finish_val;
else
out << "\\" << it_ << " <= " << finish_val;
out << "; \\" << it_ << " = \\" << it_;
if (dir)
out << " - 1)";
else
out << " + 1)";
}
out << " begin" << endl;
errors += emit_substatements(out, ent, scope);
out << "end" << endl;
out << "end /* " << scope_name << " */" << endl;
return errors;
}
int BasicLoopStatement::emit(ostream&out, Entity*, Architecture*)
void ForLoopStatement::write_to_stream(ostream&fd)
{
out << " // " << get_fileline() << ": internal error: "
<< "I don't know how to emit this sequential statement! "
<< "type=" << typeid(*this).name() << endl;
return 1;
fd << "for " << it_ << " in ";
range_->expr_left()->write_to_stream(fd);
fd << " to ";
range_->expr_right()->write_to_stream(fd);
fd << " loop" << endl;
write_to_stream_substatements(fd);
fd << "end loop;" << endl;
}
int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "for (\\" << it_ << " = ";
errors += range_->expr_left()->emit(out, ent, scope);
// Twisted way of determining the loop direction at runtime
out << " ;\n(";
errors += range_->expr_left()->emit(out, ent, scope);
out << " < ";
errors += range_->expr_right()->emit(out, ent, scope);
out << " ? \\" << it_ << " <= ";
errors += range_->expr_right()->emit(out, ent, scope);
out << " : \\" << it_ << " >= ";
errors += range_->expr_right()->emit(out, ent, scope);
out << ");\n\\" << it_ << " = \\" << it_ << " + (";
errors += range_->expr_left()->emit(out, ent, scope);
out << " < ";
errors += range_->expr_right()->emit(out, ent, scope);
out << " ? 1 : -1))";
return errors;
}
int ReportStmt::emit(ostream&out, Entity*, ScopeBase*)
{
out << "$display(\"";
switch(severity_)
{
case NOTE: out << "** Note: "; break;
case WARNING: out << "** Warning: "; break;
case ERROR: out << "** Error: "; break;
case FAILURE: out << "** Failure: "; break;
case UNSPECIFIED: ivl_assert(*this, false); break;
}
out << msg_;
out << " (" << get_fileline() << ")\");";
if(severity_ == FAILURE)
out << "$finish();";
out << std::endl;
return 0;
}
void ReportStmt::write_to_stream(std::ostream&fd)
{
fd << "report \"" << msg_ << "\"" << std::endl;
fd << "severity ";
switch(severity_)
{
case NOTE: fd << "NOTE"; break;
case WARNING: fd << "WARNING"; break;
case ERROR: fd << "ERROR"; break;
case FAILURE: fd << "FAILURE"; break;
case UNSPECIFIED: break;
}
fd << ";" << std::endl;
}
int AssertStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "if(!(";
errors += cond_->emit(out, ent, scope);
out << ")) begin" << std::endl;
errors += ReportStmt::emit(out, ent, scope);
out << "end" << std::endl;
return errors;
}
void AssertStmt::write_to_stream(std::ostream&fd)
{
fd << "assert ";
cond_->write_to_stream(fd);
fd << std::endl;
ReportStmt::write_to_stream(fd);
}
+141 -13
View File
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -23,6 +25,8 @@
# include "vtype.h"
# include "sequential.h"
# include "ivl_assert.h"
# include "compiler.h"
# include <cassert>
using namespace std;
@@ -46,7 +50,21 @@ void Subprogram::set_program_body(list<SequentialStmt*>*stmt)
{
ivl_assert(*this, statements_==0);
statements_ = stmt;
fix_return_type();
}
bool Subprogram::unbounded() const {
if(return_type_->is_unbounded())
return true;
if(ports_) {
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
it != ports_->end(); ++it) {
if((*it)->type->is_unbounded())
return true;
}
}
return false;
}
bool Subprogram::compare_specification(Subprogram*that) const
@@ -105,30 +123,104 @@ const VType*Subprogram::peek_param_type(int idx) const
return (*p)->type;
}
void Subprogram::fix_return_type(void)
{
if(!statements_)
return;
Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBase*scope) {
assert(arguments.size() == ports_->size());
const ReturnStmt*ret = NULL;
const VType*t = NULL;
std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
int i = 0;
for (std::list<SequentialStmt*>::const_iterator s = statements_->begin()
; s != statements_->end(); ++s) {
if((ret = dynamic_cast<const ReturnStmt*>(*s))) {
// Change the argument types to match the ones that were used during
// the function call
for(std::list<InterfacePort*>::iterator it = ports_->begin();
it != ports_->end(); ++it) {
InterfacePort*p = new InterfacePort(**it);
p->type = arguments[i++]->peek_type()->clone();
assert(p->type);
ports->push_back(p);
}
char buf[80];
snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports);
perm_string new_name = lex_strings.make(buf);
Subprogram*instance = new Subprogram(new_name, ports, return_type_);
// Copy variables
for(std::map<perm_string,Variable*>::iterator it = new_variables_.begin();
it != new_variables_.end(); ++it) {
Variable*v = new Variable(it->first, it->second->peek_type()->clone());
instance->new_variables_[it->first] = v;
}
instance->set_parent(scope);
instance->set_program_body(statements_);
instance->fix_return_type();
scope->bind_subprogram(new_name, instance);
return instance;
}
struct check_return_type : public SeqStmtVisitor {
check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {}
void operator() (SequentialStmt*s)
{
ReturnStmt*ret;
if((ret = dynamic_cast<ReturnStmt*>(s))) {
const Expression*expr = ret->peek_expr();
const VType*t = NULL;
if(const ExpName*n = dynamic_cast<const ExpName*>(expr)) {
if(Variable*v = find_variable(n->peek_name()))
if(Variable*v = subp_->find_variable(n->peek_name()))
t = v->peek_type();
} else {
t = expr->peek_type();
}
if(t)
return_type_ = t;
if(!t) { // cannot determine the type at least in one case
ret_type_ = NULL;
return;
}
if(!ret_type_) { // this is first processed return statement
ret_type_ = t;
} else if(!t->type_match(ret_type_)) {
// the function can return different types,
// we cannot have fixed width
ret_type_ = NULL;
return;
}
}
}
const VType*get_type() const { return ret_type_; }
private:
const Subprogram*subp_;
const VType*ret_type_;
};
void Subprogram::fix_return_type()
{
if(!statements_)
return;
check_return_type r(this);
for (std::list<SequentialStmt*>::iterator s = statements_->begin()
; s != statements_->end(); ++s) {
(*s)->visit(r);
}
VType*return_type = const_cast<VType*>(r.get_type());
if(return_type && !return_type->is_unbounded()) {
// Let's check if the variable length can be evaluated without any scope.
// If not, then it is depends on information about e.g. function params
if(return_type->is_variable_length(NULL)) {
if(VTypeArray*arr = dynamic_cast<VTypeArray*>(return_type))
arr->evaluate_ranges(this);
}
return_type_ = return_type;
}
}
void Subprogram::write_to_stream(ostream&fd) const
@@ -149,3 +241,39 @@ void Subprogram::write_to_stream(ostream&fd) const
return_type_->write_to_stream(fd);
fd << ";" << endl;
}
void Subprogram::write_to_stream_body(ostream&fd) const
{
fd << "function " << name_ << "(";
if (ports_ && ! ports_->empty()) {
list<InterfacePort*>::const_iterator cur = ports_->begin();
InterfacePort*curp = *cur;
fd << curp->name << " : ";
curp->type->write_to_stream(fd);
for (++cur ; cur != ports_->end() ; ++cur) {
curp = *cur;
fd << "; " << curp->name << " : ";
curp->type->write_to_stream(fd);
}
}
fd << ") return ";
return_type_->write_to_stream(fd);
fd << " is" << endl;
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}
fd << "begin" << endl;
if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
(*cur)->write_to_stream(fd);
}
} else {
fd << "--empty body" << endl;
}
fd << "end function;" << endl;
}
+19 -4
View File
@@ -3,6 +3,8 @@
/*
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -43,6 +45,7 @@ class Subprogram : public LineInfo, public ScopeBase {
inline const perm_string&name() const { return name_; }
void set_program_body(std::list<SequentialStmt*>*statements);
inline bool empty_program_body() const { return !statements_ || statements_->empty(); }
// Return true if the specification (name, types, ports)
// matches this subprogram and that subprogram.
@@ -50,19 +53,31 @@ class Subprogram : public LineInfo, public ScopeBase {
const InterfacePort*find_param(perm_string nam) const;
const VType*peek_param_type(int idx) const;
const VType*peek_return_type() const { return return_type_; }
int emit(ostream&out, Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Emit a definition as it would show up in a package.
int emit_package(std::ostream&fd) const;
void write_to_stream(std::ostream&fd) const;
void write_to_stream_body(std::ostream&fd) const;
void dump(std::ostream&fd) const;
// Creates a new instance of the function that takes arguments of
// a different type. It is used to allow VHDL functions that work with
// unbounded std_logic_vectors, so there can be a separate instance
// for limited length logic vector.
Subprogram*make_instance(std::vector<Expression*> arguments, ScopeBase*scope);
// Checks if either return type or parameters are unbounded vectors.
bool unbounded() const;
private:
// Determines appropriate return type. Un case of std_logic_vector
// VHDL requires skipping its size in contrary to Verilog
void fix_return_type(void);
// Tries to set the return type to a fixed type. VHDL functions that
// return std_logic_vectors do not specify its length, as SystemVerilog
// demands.
void fix_return_type();
perm_string name_;
const ScopeBase*parent_;
+1 -1
View File
@@ -70,7 +70,7 @@ int Subprogram::emit_package(ostream&fd) const
if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
errors += (*cur)->emit(fd, NULL, NULL);
errors += (*cur)->emit(fd, NULL, const_cast<Subprogram*>(this));
}
} else {
fd << " begin /* empty body */ end" << endl;
+16 -8
View File
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
* Copyright CERN 2014 / Maciej Suminski (maciej.suminski@cern.ch)
* Copyright CERN 2014
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -34,10 +35,10 @@ SigVarBase::~SigVarBase()
{
}
void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc)
void SigVarBase::elaborate_init_expr(Entity*ent, ScopeBase*scope)
{
if(init_expr_) {
init_expr_->elaborate_expr(ent, arc, peek_type());
init_expr_->elaborate_expr(ent, scope, peek_type());
}
}
@@ -46,7 +47,7 @@ void SigVarBase::type_elaborate_(VType::decl_t&decl)
decl.type = type_;
}
int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
@@ -54,18 +55,18 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
decl.reg_flag = true;
errors += decl.emit(out, peek_name_());
errors += decl.emit(out, peek_name());
Expression*init_expr = peek_init_expr();
if (init_expr) {
out << " = ";
init_expr->emit(out, ent, arc);
init_expr->emit(out, ent, scope);
}
out << ";" << endl;
return errors;
}
int Variable::emit(ostream&out, Entity*, Architecture*)
int Variable::emit(ostream&out, Entity*, ScopeBase*)
{
int errors = 0;
@@ -73,7 +74,14 @@ int Variable::emit(ostream&out, Entity*, Architecture*)
type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
decl.reg_flag = true;
errors += decl.emit(out, peek_name_());
errors += decl.emit(out, peek_name());
out << ";" << endl;
return errors;
}
void Variable::write_to_stream(std::ostream&fd)
{
fd << "variable " << peek_name() << " : ";
peek_type()->write_to_stream(fd);
fd << ";" << endl;
}

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