Compare commits

...

240 Commits

Author SHA1 Message Date
Cary R 27be6e88bc V0.8: backport of check primitive port count code.
This patch backports from multiple places checks that verify
that the various primitives are given the correct number of
port expressions.
2008-12-09 19:21:48 -08:00
Cary R 918b0a410f V0.8: backport $random fix.
Back port a $random fix from development.
2008-12-09 15:43:28 -08:00
Stephen Williams ec85377d13 Prepare for 0.8.7 release. 2008-12-09 09:47:42 -08:00
Cary R a22124a198 V0.8: Mostly back port the version checking code from development.
This is a back port from development of the code to put and check
that the vvp input file is the right version. It also adds the -V
flag to vvp. It does not add the VERSION_TAG information so will
only produce the single string ivl_version tag. The runtime will
read both forms since if it is feed a V0.9 file we want it to
complain nicely (no syntax error). To change the displayed version
for the various programs and checks change version.h.
2008-12-05 22:01:13 -08:00
Cary R e8bc5aefb4 V0.8: Get arrayed instance ports correct.
This is a back port from development of the code to get the
arrayed instance port order correct (MSB to LSB).
2008-12-05 21:57:57 -08:00
Cary R ca5d265350 V0.8: left shift of integer value needs to use integer size
This is a back port from development of the code to resize an
unsized constant value to 32 bits. Development used integer_width,
but that is not supported in V0.8. Development also supports using
the expression width which V0.8 does not.
2008-12-05 21:54:59 -08:00
Cary R 113312a0c1 V0.8: do not schedule function calls.
This patch mirrors what was done in development to force a function
call to be run immediately.
2008-11-28 10:16:23 -08:00
Cary R 12d5aa08e2 V0.8: A $signed can make a concat signed.
This patch mirrors what was done in development to fix the
signed concat problem.
2008-11-28 10:12:11 -08:00
Stephen Williams 15702f1b87 Fix bad memory reference.
The expression for the repeat expression was deleted before the
tests for expression sanity.
2008-11-28 10:00:57 -08:00
Stephen Williams 9b5ef0bbb9 Checkin some developer convenience scripts. 2008-11-28 09:32:22 -08:00
Cary R b8d9f19eb0 Use MOS instead of bufif devices for mux optimization.
This patch mirrors what was done in development to fix the mux
with one input as Z optimization. It should use a MOS device
instead of a bufif device.
2008-11-28 09:16:21 -08:00
Cary R 8d9f7e2e26 Include directory should be 0.8 not 0.0.
The include directory had the wrong version.
2008-11-28 09:11:58 -08:00
Stephen Williams 65326fd6a9 Put header files in include/iverilog dir.
The include/verilog directory is a bit too
generic. Use the include/iverilog dir instead.
2008-11-25 16:29:30 -08:00
Cary R bb92974839 V0.8: Fail on a zero width repeat
This patch mirrors what was done in development to fail for zero
width repeats. Actually development supports them in some contexts,
this is allowed in 1364-2005, but V0.8 doesn't support them at all.
2008-11-24 21:07:51 -08:00
Cary R 7dc473db8d V0.8: fix signed parameter multiply
This patch mirrors what was done in development to fix the
multiplication of signed values.
2008-11-24 21:03:11 -08:00
Cary R abc2aa17d2 V0.8: complain about a negative repeat value.
This patch mirrors what was done in development to complain
about a negative repeat value.
2008-11-24 21:00:58 -08:00
Cary R c8bffe728a V0.8: fix verinum XOR with z input
This patch mirrors what was done in development to fix the XOR
of a z bit in verinum.
2008-11-24 20:56:48 -08:00
Cary R d134f6f074 V0.8: fix $ungetc argument order.
This patch mirrors what was done in development to fix $ungetc.
2008-11-24 20:52:38 -08:00
Cary R 8deb2c0b60 V0.8: only return a real time value for $realtime.
This patch mirrors what was done in development to only return a
real value when realtime is called.
2008-11-24 20:49:53 -08:00
Cary R 451783056d V0.8: Can not have and undefined repeat.
This patch mirrors what was done in development to fail when the
repeat has an undefined value.
2008-11-24 20:44:28 -08:00
Cary R 322bbed7c7 V0.8: Don't crash on invalid input.
This patch mirrors what was done in development to prevent a crash
when given invalid input.
2008-11-24 20:42:48 -08:00
Cary R e8bb9b1f76 V0.8: `timescale can not be inside module definition.
This patch mirrors what was done in development to complain
about a `timescale inside of a module definition.
2008-11-24 20:39:49 -08:00
Cary R f112b77d3b V0.8: Fix single bit reductions with 1'bz input.
This patch mirrors what was done in development to support single
bit reductions correctly.
2008-11-20 20:25:39 -08:00
Cary R ddf68ca14c Don't let -I block -ivl!
When -I was added it was blocking -ivl since the string comparison
is case insensitive.
(cherry picked from commit a412149e2c)
2008-11-20 20:23:52 -08:00
Cary R d8fdcd5a38 Add verilog<suffix> to MinGW iverilog-vpi tool
When changing where the include files were located the MinGW
iverilog-vpi tool was missed.
(cherry picked from commit 45f2d68d33)
2008-11-20 20:12:45 -08:00
Stephen Williams 408e25f6bc Make the 0.8 series use --enable-suffix by default
This we are working on closing out this release series,
install with the 0.8 suffix enabled by default from
now on.
2008-11-20 09:53:52 -08:00
Cary R 3dd2c74ebe V0.8: For scheduled put values save the string and free it after the put.
Users expect that vpi_put_value() will keep a copy of the string
that is passed to it. This patch implements this buy copying the
string and then freeing it after the actual put_value call.
2008-11-20 09:31:52 -08:00
Cary R d260052940 Fix MinGW suffix configuration.
In the driver-vpi file we need to use g for the suffix replacement
so that both libraries get changed.

Also added an end line to the config.h.in file.
2008-11-20 07:35:30 -08:00
Stephen Williams 146f64992c Create support for the --enable-suffix configuration option.
This configure option causes the installed commands to have
a suffix string that makes them distinct from other versions
that also have a suffix string. This allows for multiple
installed versions of Icarus Verilog.

Also, move installed C/C++ header files into a subdirectory of
their own under the target include directory, to make clearer
the purpose and source of those files.

(cherry picked from commit 4bc90f7cfd)
2008-11-19 22:39:10 -08:00
Cary R 74e2343e52 V0.8: fix shifting of 0 or signed constant.
This patch matches the one from development. If just returns the
L-value if the shift is a NOP.
2008-11-16 11:07:58 -08:00
Cary R b4b9667def Fix signed divide for words that match the machine word.
There was an error when calculating the negative of a value that
was the same width as the native machine word. This patch is similar
to what was done in 0.9 to fix the problem there.
2008-11-16 11:05:04 -08:00
Cary R 5e401055e8 V0.8: do signed comparisons and fix verinum < and <=
This patch fixes the verinum < and <= operators to directly
compare the long result not the difference. Because of overflow
the difference can give an incorrect value. Using a long value
is technically wrong, but that will need to be a different
patch. It also fixes the eval_leeq_() routine to correctly build
the largest value in a signed comparison.
2008-08-23 09:30:37 -07:00
Cary R e89bce48ed Error message for missing system tasks/functions.
This patch adds an error message for the standard system
tasks and functions that are not currently implemented.
2008-08-23 09:23:49 -07:00
Cary R cf01d1a75f V0.8: Remork previous patch to use the correct method 2008-06-25 15:38:20 -07:00
Cary R 6df10a082b V0.8: fix memory leak in recent patch. 2008-06-25 12:52:04 -07:00
Cary R 22ad8c42bc V0.8: Copy file and line info during a macro expansion.
The file and line number information needs to be copied when
doing a macro expansion. This prevents a macro that expands to
an `ifdef of other construct that needs to push the stack
from core dumping because the file is NULL.
2008-06-25 11:26:02 -07:00
Cary R f418bea775 MinGW fixes (system return and vsnprintf)
The MinGW system() implementation appears to return the straight
return value instead of the waitpid() like result that more
normal systems return. Because of this just return the system()
result without processing for MinGW compilations.

Older version of the MinGW runtime (pre 3.14) just used the
underlying vsnprintf(). Which has some problems. The 3.14 version
has some nice improvements, but it has a sever bug when processing
"%*.*f", -1, -1, <some_real_value>.  Because of this we need to use
the underlying version without the enhancements for now.
2008-05-22 20:20:29 -07:00
Stephen Williams 568e601212 Do not use "synthesize" to elaborate nets if not necessary.
The synthesize was causing memories to be exploded, whis was then causing
memory word addresses to turn into bit index statements, causing bugs.
So don't synthesize if we are not actually synthesizing.
2008-05-22 09:37:19 -07:00
Cary R b7e7d3cb04 User tasks have empty nex_output().
This patch matches what is done in the development branch and
fixes the reported bug.
2008-05-13 11:09:12 -07:00
Cary R 8a1543aaaf V0.8: pad user function port in synthesize().
This patch removes the assert in synthesize() for user functions and
replaces it with a pad to width.
2008-02-25 16:07:29 -08:00
Cary R c6ba9269bc Fix some problems in driver-vpi/main.c
Fixed a few problems in driver-vpi/main.c that were preventing
the Verilog-A math library from compiling.
2008-02-25 16:02:40 -08:00
Michael Witten 3af373667a [PATCH] Removed #include asm/page.h on GNU/Linux
vvp/main.cc was including asm/page.h on GNU/Linux
systems, though that file does not often exist and
is not necessary.

Signed-off-by: Michael Witten <mfwitten@mit.edu>
2008-02-04 13:20:57 -08:00
Stephen Williams d49e44594b Fix reported build errors with gcc 4.3
Add missing includes to cstring et al.
2008-01-21 18:04:30 -08:00
Cary R 4d3f592b5f V0.8 add check target to {tgt-*,vpi}/Makefile.in
Add missing Makefile check targets to the tgt-* and vpi directories.
2008-01-16 11:07:47 -08:00
Cary R d1e82d3d12 V0.8: ignore edge-control specifiers
Update the specify code in V0.8 to ignore edge-control specifiers.
2008-01-15 15:57:40 -08:00
Cary R d70ccb6895 V0.8: update driver-vpi/* to match iverilog-vpi.sh
This patch updates the MinGW C version of iverilog-vpi to match the
shell version. This allows the vpi tests in the test suite to be run.
2008-01-09 08:10:39 -08:00
Cary R e34647f79c V0.8: Add vvp flag that allows $stop to act like $finish.
This patch adds a new flag to vvp "-n" that can be used to make
$stop and hence <Control-C> act like $finish. This may be desired
when using vvp in a non-interactive environment.
2008-01-09 08:08:19 -08:00
Cary R 24b097ce89 V0.8 fix for shift/reduce warning
This patch fixes the oversight in the previous patch and eliminated
the shift/reduce warning. Apply it after the previous one.
2007-12-31 17:52:27 -08:00
Cary R 83ee7e7988 V0.8: allow NULL ports in task calls.
This is a direct back port from development that allows tasks to
be called with no ports. This fixes one failure in the test suite.
2007-12-31 17:52:09 -08:00
Cary R f33d477166 V0.8: allow vthr_vector to be converted to real.
This is a direct back port from development that allows vthread
vectors to be converted to real values. This is the first step
in fixing two more failures in the test suite.
2007-12-29 15:02:11 -08:00
Cary R 3f16d3402a V0.8: add `elsif add some conditional directive syntax checks.
This is a direct back port from the development branch. It adds
the `elsif directive and adds check that the conditional
directives are used correctly.
2007-12-29 14:54:29 -08:00
Cary R 304a63d8e3 Fix protect/endprotect
This patch makes stable match the development branch. `protect/`endprotect
are not required to be on their own line.
2007-12-29 14:49:13 -08:00
Cary R 23d56d8198 V0.8: fix a few more specify block problems.
This patch fixes a few more specify block problems in the stable
branch.
2007-12-29 14:44:13 -08:00
Cary R a8f68fe416 V0.8: ignore ifnone in specify block
In specify blocks ignore the ifnone command.
2007-12-29 14:37:48 -08:00
Cary R 5dc4202929 V0.8: Back port development patch for pr1716276
This is a straight back port of the development patch for the
problem reported in pr1716276. This was causing the test case
to core dump under stable.
2007-12-29 14:29:27 -08:00
Cary R 281b4edbab v0.8: Do not run the first time step if the compilation failed.
This patch fixes another minor problem introduced by the process
end of simulation events. Specifically if the compilation has
indicated we should not run do not even start the main event loop.
2007-12-10 16:26:06 -08:00
Cary R 3eb86a2376 Process end of simulation events.
This is copied from the development branch. It allows the processing
of events that happen at the simulation finish time.
2007-12-06 18:54:15 -08:00
Cary R 1fb93c0565 Fix call back free problem.
This is copied from the development branch. The issue is that calling
vpi_free_object should not really free a call back handle since it is
the real call back object and doing so will invalidate it. This will
likely end with a core dump.
2007-12-06 18:50:31 -08:00
Holger Waechtler bdb900b25f Fix compile error on some gcc versions 2007-12-03 14:27:53 -08:00
Cary R 28da79dcc3 V0.8: Add the enhancements in iverilog-vpi from devel
Back port all the enhancements to iverilog-vpi made in the
development branch to the stable branch.
2007-11-29 18:05:06 -08:00
Cary R bbd61823b9 Update vpi/etc. files to correctly use PLI_INT32
This patch fixes the various PLI code that was incorrectly
using int for PLI_INT32 for functions that are used with the
vpi_systf_data and cd_data data structures.
2007-11-29 18:01:51 -08:00
Stephen Williams 0f716d6dca Prepare for 0.8.6 release. 2007-11-26 10:55:13 -08:00
Cary R a44236f8cb v0_8: A leading underscore is valid for macro substitutions.
For text macro substitutions the lexor did not allow leading underscores.
This patch fixes that omission. All other places that text macros may be
used appear to be correct.
2007-11-16 15:48:25 -08:00
Cary R 4be2ccb3fa Add error message for pr1489570.
This patch does not add the functionality needed to fix pr1489570, but
it does give an error message that is a bit more descriptive of the
current limitation (cannot do division or modulus with wide value).
2007-11-14 13:52:19 -08:00
Cary R 9f4dc5411f v0_8: make patch for pr1792108 synth aware.
This patch makes the behavior selection for pr1792108 depend on the
synth* functors.
2007-11-14 13:38:43 -08:00
Stephen Williams 545d20eba5 Error message for inconnected primitive ports.
Error message (instead of a seg fault) when a primitive port
is left unconnected.

Signed-off-by: Stephen Williams <steve@icarus.com>
2007-10-31 11:41:04 -07:00
Stephen Williams b2159d1e64 Unary minus size assertion
Fix errors with unary subtraction producing logic gates with
inconsistent widths.

Signed-off-by: Stephen Williams <steve@wing.icarus.com>
2007-10-31 11:40:45 -07:00
Stephen Williams 4c8df2a370 No system functions in continuous assignments.
Do not support (in 0.8) system functions in continuous assignments.
Make a better error message.

Signed-off-by: Stephen Williams <steve@wing.icarus.com>
2007-10-31 11:40:35 -07:00
Stephen Williams eed0885dd0 Fix comparison of two negative numbers
Pairs of negative numbers that are equal do not set
the LT flag correctly at runtime.
2007-10-31 11:39:45 -07:00
Cary R 0fc10d0262 v0_8: fix @* to correctly handle non-input nets.
This is a slightly modified version of the patch from the development
branch. Specifically it only allows outputs in the sensitivity list for
non-synthesis back ends. The text from the development patch follows.

@* was only expanding to input nets. nex_input() for blocks was removing
any output net that was also an input. There was also a bug in how output
nets were removed. Only outputs currently defined were removed from the
input list.

always @(*) begin
  y = a;
  z = y;
end

would report "a" as an input. While

always @(*) begin
  z = y;
  y = a;
end

would report both "a" and "y" as inputs.

To fix this all nex_inputs now take a flag that when true (the default)
correctly removes any output from the input list. Both the above cases
will now return "a". If the flag is false outputs which are also inputs
will be included in the input list. This is what the @* elaboration code
uses to get the correct sensitivity list.
2007-10-30 17:49:35 -07:00
Cary R 1775c78aa9 v0_8: clear expression look aside for transient thread.
This is a back port of code from the development branch. The problem is
that for named blocks (which create a transient thread) the look aside
was not being cleared for the new thread. This resulted in an invalid
variable reference optimization.
2007-10-30 17:33:06 -07:00
Cary R 85652e24e0 v0_8: explicitly state the V0.8 cannot evaluate constant real expressions.
V0.8 does not have the code to evaluate constant real expressions. This
patch adds a line to the normal error message that says this explicitly.
2007-10-29 16:28:36 -07:00
Cary R eb4fc8fb7b Warn that bit based signals cannot be converted to real.
V0.8 does not have the code to covert bit based signals to a real value,
so print a more descriptive error message before quiting.
2007-10-29 16:24:55 -07:00
Cary R 043b7ae684 v0_8: warn about unused variable in for loop.
This patch back ports from the development branch a warning when
an undefined variable is used in a for loop.
2007-10-29 16:20:58 -07:00
Cary R 2946f30ffc v0_8: fix comparison in previous patch for pr1745132
If I had remembered to test the passing case I would have noticed
the comparison was wrong.
2007-10-29 16:15:07 -07:00
Cary R 5530aea6a3 v0_8: print an error message for an invalid bit selection.
This code may be used for more than just a bit select so the error message
is fairly generic. Though it should help in tracking down the real problem
(invalid Verilog code).
2007-10-29 16:14:49 -07:00
Cary R 40e09cd719 v0_8-add min_typ_max to expressions.
This patch adds min_typ_max to expressions. Remember when using a
min_typ_max triplet in an expression they must be enclosed with
parenthesis (1364-2001 section 4.3 page 58).
2007-10-29 16:08:34 -07:00
Cary R c67f3b0081 v0_8: implement $printtimescale.
This patch implements the $printtimescale system task. It is a back port
from the development branch. One thing to note is that the precision is
the global precision not the local precision. The patch to fix that could
also be back ported if needed, but it is significantly more work.
2007-10-29 16:02:08 -07:00
Cary R 95254aa27e v0_8: disable lxt support if libbzip2 is not found.
Configure was checking for libbzip2, but it was not doing anything with
the result. This patch disables lxt support if libbzip2 is not found.
2007-10-29 15:58:35 -07:00
Cary R 468e3bb702 v0_8 make C style comments work in false/suppressed ifdef/etc. blocks.
C style comments were not recognized as comments in false or
suppressed sections of ifdef/etc. blocks. This prohibited an
unneeded endif/else/etc. from being commented out with this
style of comment.
2007-10-29 15:50:29 -07:00
Alan M. Feldstein be8c8a8eb7 Removed UML not for publication.
Removed UML not for publication.
2007-10-24 16:18:02 -07:00
Alan M. Feldstein 5cae6b64af Fixed dangling latch gate inputs.
With -tfnf, observed
(latch  43020 1 43022 43021)
in the output file. That 3rd number is the ID of the gate nexus. However, it was only found as
(dangle 43022)
The purpose of this patch is to fix that in the common code.
2007-10-24 16:16:23 -07:00
steve f600e774d5 Add support for NAND gates. (Chris H) 2007-06-06 15:46:22 +00:00
steve d16dd26660 Support Latch synthesis (Alan Feldstein) 2007-05-30 17:48:53 +00:00
steve 8c04d669f9 DEBUG aids. (Alan Feldstein) 2007-05-30 17:48:26 +00:00
steve 5d2dcfd7f7 Fix uninitilized line number. 2007-05-25 18:35:45 +00:00
steve 0b3f1e4119 Better configuration messages (Alan Feldstein) 2007-05-16 23:51:42 +00:00
steve 8bd9fc7128 Supress error about types for default rule. 2007-04-26 00:50:54 +00:00
steve 1b551aaf94 Update to v0.8.4 release. 2007-03-23 23:26:51 +00:00
steve a3dda80fb2 Properly support signed task/function arguments. 2007-03-23 23:22:57 +00:00
steve 9e9d5ccfdd Fix compile time eval of <= comparison. 2007-03-23 23:02:31 +00:00
steve 07daee9438 Fix compile time evaluation of < operator. 2007-03-23 20:59:25 +00:00
steve 82808d8b5d Parse attribute attached to block items. 2007-03-23 19:31:22 +00:00
steve c045f51a7f Spelling fixes (larry doolittle) 2007-02-26 19:51:38 +00:00
steve d72eadb885 Get page size from sysconf. 2007-02-16 23:29:17 +00:00
steve e99f0a8f51 Comment about 10.3. 2007-02-09 05:30:22 +00:00
steve ed2cb380cd fix lexical handling of slashes in strings. 2007-02-09 05:29:24 +00:00
steve dc8e941260 Fix parse of bit select in notifier expression, 2006-12-03 04:58:20 +00:00
steve d486b81f23 Fix crash handling constant true conditional. 2006-11-27 01:47:14 +00:00
steve 59c2f16a5f Fix evaluate of constant condition expressions. 2006-11-27 01:32:24 +00:00
steve 1470a061fd Add synthesis of user defined functions. 2006-11-26 01:54:05 +00:00
steve c1333a21ef Prevent constant mux outputs from confusing itself. 2006-11-12 01:20:45 +00:00
steve 04ef0b7d80 Fix async blocks to take accumulated input. 2006-11-11 23:10:20 +00:00
steve 2fc9413d1f More detailed BuildRequires settings. 2006-11-11 21:21:50 +00:00
steve c94bdbcdb0 Make signal lookup use extended names. 2006-11-11 21:21:21 +00:00
steve 1820cd0244 Fix compile on Mac OS X 2006-11-02 17:47:52 +00:00
steve aa3cbbdf99 Error message for condit expression not synthesized. 2006-11-02 02:13:15 +00:00
steve 0a9b6f34ae Detect and synthesize enables using condit false. 2006-10-30 02:03:30 +00:00
steve 5c2c5453ac Fix code generation for signed numbers in real expressions. 2006-10-11 00:19:04 +00:00
steve 0c6bb476ea Get rounding of conversion correct. 2006-10-11 00:17:35 +00:00
steve 568924dcb5 Version stamp update 2006-10-04 17:08:59 +00:00
steve 33b3f7bdda Detect delay precision overflow. 2006-10-04 00:37:03 +00:00
steve 3a04e0a051 Fix a dangling reference to NetEParam objects in defparams. 2006-10-04 00:34:45 +00:00
steve 66ae377801 Snapshot v0.8.3 2006-10-03 21:34:40 +00:00
steve 898db57405 Describe the preconfigure steps. 2006-09-28 23:42:14 +00:00
steve 0fe45b5046 Fix host type detection in some configure scripts. 2006-09-22 03:29:02 +00:00
steve 20cfe99457 Fix left shift of small unsized constants. 2006-09-20 20:27:02 +00:00
steve 4ec8b38a5c Special handling of exploded memory arguments. 2006-09-15 23:56:05 +00:00
steve 79add47002 Build instruction typos and minor corrections. 2006-09-15 23:53:24 +00:00
steve c429f4c9a7 missing sig diagnostics. 2006-08-23 04:09:14 +00:00
steve 7f6a0b652a Do not count self as signifincant in nodangle. 2006-08-23 04:08:55 +00:00
steve 9f3f9154eb Fix missing sig on certain mux outputs.
Ignore condit statements (for synthesis) with no outputs.
2006-08-23 04:08:19 +00:00
steve 498fd06412 Add synthesis for casez statements. 2006-08-22 04:22:45 +00:00
steve 6d3b780791 Improve performance of unlink of heavily connected nexa. 2006-08-15 03:41:24 +00:00
steve a0ec981c50 Improved nexus management performance. 2006-08-08 02:17:48 +00:00
steve 930cd598a0 Typo clearing an event cell. 2006-08-06 18:09:42 +00:00
steve 77adab0f33 Remove excess PEString:: prefix for stubborn compilers. 2006-07-28 16:26:17 +00:00
steve 0e3768f829 Handle statement output override better in blocks. 2006-07-23 19:42:33 +00:00
steve 22884f2e64 Add support for full_case attribute. 2006-07-10 00:21:49 +00:00
steve 62da6aca28 Root dir variable does not include lib/ivl components. 2006-07-07 21:31:50 +00:00
steve 525ebddb0c Properly synthesize casex statements. 2006-07-02 00:50:15 +00:00
steve 521750c007 Fix ambiguity warnings. 2006-06-27 01:47:25 +00:00
steve 85d2833a62 Fix const/non-const warnings. 2006-06-27 01:37:14 +00:00
steve e2cc258283 Cure exit from main warning. 2006-06-27 01:33:17 +00:00
steve f09cf85c76 Fix unused var warning for mingw32 build. 2006-06-27 01:30:20 +00:00
steve c32de1dba0 Handle case where case output appears to be internal. 2006-06-26 00:05:46 +00:00
steve 628b866c36 Change Copyright tag to License. 2006-06-24 05:22:55 +00:00
steve 08dbe801c1 synthesis of NetCondit handles partial resets. 2006-06-23 03:49:46 +00:00
steve 101810df21 Handle simple memory addressing in expression synthesis. 2006-06-15 01:57:26 +00:00
steve 3877b636df synthesis for NetEBitSel. 2006-06-14 03:02:54 +00:00
steve 9d028a63f2 Remove redundant call to get_root_dir. 2006-06-14 03:01:49 +00:00
steve 35e5cea9df Add support for -Wunused warnings. 2006-06-12 00:16:50 +00:00
steve ec510071f1 Fix partial use of NetMux in sync condit statements. 2006-06-07 03:17:39 +00:00
steve 7413c533f6 Compilation warnings. 2006-06-02 23:42:48 +00:00
steve dde69cebb6 Handle condit clauses with unassigned outputs. 2006-06-01 03:01:48 +00:00
steve f942657ad5 NetESignal input is only selected bits. 2006-05-21 21:58:46 +00:00
steve fad1620828 Replace assertions with error messages. 2006-05-20 16:06:48 +00:00
steve a9931e7a58 Fix synthesis of l-value bit select in block. 2006-05-18 01:47:12 +00:00
steve 6cd4adb135 Fix synthesis of expressions with land of vectors. 2006-05-15 03:55:22 +00:00
steve 9643b86ab3 Update to use only Mingw for build. 2006-05-08 04:33:35 +00:00
steve 452eaeaea8 Handle memory assignments out of range during synthesis 2006-05-05 01:56:36 +00:00
steve 3a6e2df958 Fix uninitialized mem_lref_ member. 2006-05-02 02:00:15 +00:00
steve e73b7e2656 parse.cc and parse.h are made by the same steps. 2006-05-01 20:11:56 +00:00
steve 469ec11190 Merge fixes from devel tree. 2006-04-25 05:11:14 +00:00
steve e0bbfa512c Constant propagate addresses through NetRamDq read ports. 2006-04-23 04:26:13 +00:00
steve 94c9af2a5d Add cprop debugging. 2006-04-23 04:25:45 +00:00
steve 9f2e7df0ff vpp.conf is generated, so add it to cvsignore. 2006-04-23 02:44:29 +00:00
steve f02b2c9d7a Fix handling of exploded memories with partial or missing resets. 2006-04-16 19:26:37 +00:00
steve 058dac4290 Exploded memories accessed by constant indices. 2006-04-10 03:43:39 +00:00
steve ce4e21a962 Punt on set/reset if some sources are unconnected. 2006-04-01 01:37:58 +00:00
steve 065d6bc1e3 Add synth debug flag 2006-04-01 01:37:24 +00:00
steve 312d09dc1d Handle asynchronous demux/bit replacements. 2006-03-26 23:09:21 +00:00
steve faf7f30283 Add the .demux device. 2006-03-26 23:09:00 +00:00
steve 5d41e98c1f More installation directory flexibility. 2006-03-26 21:47:26 +00:00
steve 5e8330a4ff Better error messages when synthesis fails. 2006-03-18 18:43:21 +00:00
steve ef8964c65a Fix crash when memory exploding doesnot work 2006-03-16 05:40:18 +00:00
steve aa42ec381c Fix a spelling error in an error message. 2006-03-16 05:39:43 +00:00
steve c9d4aab9cb Right shifts really are allowed. 2006-03-16 05:39:20 +00:00
steve b8bc531f05 Fix the memsynth1 case. 2006-03-12 07:34:16 +00:00
steve 79cb8c883a Add support for negedge FFs by using attributes. 2006-02-25 05:03:28 +00:00
steve 27e633410c Add change callback to vpiMemory objects. 2006-02-19 16:57:31 +00:00
steve 7527c466ed Handle synthesis of FF vectors with l-value decoder. 2006-02-19 00:11:31 +00:00
steve 3ea1214160 More robust test for concat constant-ness. 2006-02-07 22:46:23 +00:00
steve 782542922d Detect nul arguments to concat expressions. 2006-02-07 22:45:54 +00:00
steve 1f8102c4dc Speed up processing of connect when one side is empty. 2006-01-27 02:05:46 +00:00
steve c4b34e8720 Document how the default statement handling works. 2006-01-27 01:58:53 +00:00
steve e494be7cbf Fix pin_Sel overrun. 2006-01-22 00:13:59 +00:00
steve eb0a78e9ce When mux has wide select but sparse choices, use 1hot translation. 2006-01-21 21:42:31 +00:00
steve e80138ec8c Restrict DFF to only one of Sset and Sclr. 2006-01-18 06:16:11 +00:00
steve 943316c6f6 Support DFF with synchronous inputs. 2006-01-18 06:15:45 +00:00
steve 52b8ed9077 Rework l-value handling to allow for more l-value type flexibility. 2006-01-18 01:23:23 +00:00
steve fc227aa3e1 Remember to set DLL= flag. 2006-01-14 20:13:38 +00:00
steve 41993815e9 Show synchronous set/clr of FF. 2006-01-14 20:13:22 +00:00
steve c5063f5d2f Case statement handles partial outputs. 2006-01-01 02:25:07 +00:00
steve f28aa11936 Allow for implicit case default in synchronous processes. 2006-01-01 01:30:39 +00:00
steve 3131fa68b7 Fix crashes caused bu synthesis of sqrt32.v. 2005-12-31 04:28:14 +00:00
steve def3809b3f Handle DFF definitions spread out within a block. 2005-12-19 01:13:47 +00:00
steve 3429c24a6a Properly fail when concat is not actually constant. 2005-12-18 21:06:01 +00:00
steve f47627d752 Fix missing outputs from synchronous conditionals to get out from in. 2005-12-15 02:38:51 +00:00
steve 9468f3d06f Handle both asynchronous set and reset. 2005-12-14 01:53:39 +00:00
steve b997de63a5 Account for sync vs async muxes. 2005-12-14 00:54:29 +00:00
steve f50f06ab4e Handle concatenations in l-values. 2005-12-10 04:26:32 +00:00
steve d5d03812cd Fix crash on block with assignments that assign lval to self. 2005-12-10 03:30:50 +00:00
steve b6d5a0675e Support constant concatenation of constants. 2005-12-07 03:28:44 +00:00
steve e63e830d62 Error messages for missing else clauses. 2005-12-07 02:14:37 +00:00
steve 74ca34bd82 Handle partial sets of conditional clauses. 2005-11-16 00:38:26 +00:00
steve c9d480028e Allow for block output to be set throughout the statements. 2005-11-13 22:28:48 +00:00
steve cc89ba66af Do not panic if case statement is nul. 2005-11-13 22:28:14 +00:00
steve 05e6d51004 Snapshot 0.8.2 2005-09-30 15:13:37 +00:00
steve ae583204e3 Snapshot 0.8.2 2005-09-30 15:01:44 +00:00
steve 018476f7cd More predictable ordering of items in NexusSet. 2005-09-25 23:30:31 +00:00
steve bfabeab6b9 Add Xilinx virtex as a reference EDIF device. 2005-09-25 16:35:36 +00:00
steve 4a3f1a3641 Attach line numbers to NetMux devices. 2005-09-11 02:56:37 +00:00
steve d97560caa7 Fix overly agressive constant propagation through MUX causing lost Z bits. 2005-09-11 02:50:51 +00:00
steve 393102d43a Evaluate magnitude compare with real operands. 2005-09-09 02:17:08 +00:00
steve 8e97a0e4d4 Support b1 edge in primitive tables. 2005-09-09 02:13:15 +00:00
steve 4ea789a2d7 More explicit internal error message. 2005-09-04 15:41:54 +00:00
steve 354f7ad920 More explicit internal error message. 2005-09-04 15:39:19 +00:00
steve f4a6206790 Handle b0 edges in primitives. 2005-09-04 15:33:19 +00:00
steve fd29ba3398 Reduce mux slices that are constant throughout range. 2005-08-28 22:00:39 +00:00
steve 44fbf60885 More thorough constant propagation through MUX devices. 2005-08-28 19:51:02 +00:00
steve a0d69113c3 More thorough constant propagation through MUX devices. 2005-08-28 19:50:03 +00:00
steve 86942ac592 Dump CMP_GE devices. 2005-08-28 17:37:28 +00:00
steve 075f9cbc4b Back-port edif_nexus_to_joint from tgt-edif. 2005-08-27 22:29:30 +00:00
steve 9dab368880 fix configure and build instructions for mingw build. 2005-08-27 22:19:37 +00:00
steve 5f6027fb66 Join cell0 and cell1 instances in LPM target. 2005-08-25 18:52:32 +00:00
steve 53156793fe Add support for implicit defaults in case and conditions. 2005-08-22 01:00:41 +00:00
steve 4644c220e8 Handle statements in blocks overriding previous statement outputs. 2005-08-21 22:49:54 +00:00
steve c30cd9afea Display NOR gates. 2005-08-21 22:27:57 +00:00
steve a8f45a18f0 Fix the comment in the EDIT header. 2005-08-21 22:25:51 +00:00
steve 6828e3e2ea Generate LPM for the CMP_EQ device. 2005-08-21 14:39:33 +00:00
steve 75eb372adf configure tgt-edif subdir. 2005-08-21 02:20:16 +00:00
steve 3b753fe52b Add the tgt-edif target. 2005-08-17 01:17:28 +00:00
steve 8c73fa7840 Fix compilation warnings/errors with newer compilers. 2005-08-13 00:45:53 +00:00
steve d310e656c7 Fix parse errors related to pr766. 2005-07-27 14:48:34 +00:00
steve 0510367b70 Fix compile errors with g++-4. 2005-07-06 22:41:34 +00:00
steve 3e11207a56 Fix gcc4 build issues. 2005-06-14 15:33:54 +00:00
steve 665f31271f popen must be matched by pclose. 2005-03-22 15:53:12 +00:00
steve 9a2b56675c Fix set_width to allow binary logical operands to be self determined. 2005-03-05 01:36:16 +00:00
steve c9f38f5ffa Improve distclean targets. 2005-02-23 18:40:23 +00:00
steve 5ea4152162 Spelling fixes from Larry. 2005-02-23 18:37:52 +00:00
steve 327c897d7e Spellig fixes. 2005-02-19 16:39:30 +00:00
steve 29ebe486b7 Fix multiple delete of an expression. 2005-02-19 16:38:14 +00:00
steve 4af0acb3be Fix (from Tony) for clock compression detection 2005-02-11 17:04:22 +00:00
steve 8435774c26 Fix evaluate of constants in netlist concatenation repeats. 2005-01-29 00:18:23 +00:00
steve 6172748c65 Add stub config files to CVS. 2005-01-28 18:30:11 +00:00
steve ca0ae9040a Add ability to compile real values into index registers. 2005-01-28 18:29:29 +00:00
steve d9cdbde3f6 More robust handling of file name argument to $fopen. 2005-01-01 20:07:41 +00:00
steve 307a97116f Fix leak of word registers in code generator. 2004-12-12 04:25:10 +00:00
steve 83d2c6dfd1 Update for 0.8 files. 2004-10-14 01:12:41 +00:00
203 changed files with 13875 additions and 1867 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $" #ident "$Id: LineInfo.cc,v 1.4.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -34,12 +34,12 @@ LineInfo::~LineInfo()
{ {
} }
string LineInfo::get_line() const std::string LineInfo::get_line() const
{ {
ostringstream buf; std::ostringstream buf;
buf << (file_? file_ : "") << ":" << lineno_; buf << (file_? file_ : "") << ":" << lineno_;
string res = buf.str(); std::string res = buf.str();
return res; return res;
} }
@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
/* /*
* $Log: LineInfo.cc,v $ * $Log: LineInfo.cc,v $
* Revision 1.4.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.4 2003/01/17 05:49:03 steve * Revision 1.4 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf. * Use stringstream in place of sprintf.
* *

View File

@ -19,11 +19,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $" #ident "$Id: LineInfo.h,v 1.7.2.2 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include <string> # include <string>
using namespace std;
/* /*
* This class holds line information for an internal object. * This class holds line information for an internal object.
* *
@ -38,7 +40,7 @@ class LineInfo {
LineInfo(); LineInfo();
~LineInfo(); ~LineInfo();
string get_line() const; std::string get_line() const;
void set_line(const LineInfo&that); void set_line(const LineInfo&that);
@ -52,6 +54,12 @@ class LineInfo {
/* /*
* $Log: LineInfo.h,v $ * $Log: LineInfo.h,v $
* Revision 1.7.2.2 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.7.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.7 2003/01/17 05:49:03 steve * Revision 1.7 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf. * Use stringstream in place of sprintf.
* *

View File

@ -16,16 +16,16 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $" #ident "$Id: Makefile.in,v 1.169.2.7 2007/05/30 17:48:53 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
# This version string is only used in the version message printed # This string is used as an installation suffix. It modifies certain
# by the compiler. It reflects the assigned version number for the # key install paths/files such that a build and install of Icarus Verilog
# product as a whole. Most components also print the CVS Name: token # with the same $(prefix) but a different $(suffix) will not interfere.
# in order to get a more automatic version stamp as well. # The normal configuratin leaves suffix empty
VERSION = 0.8 suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -37,7 +37,9 @@ VPATH = $(srcdir)
bindir = @bindir@ bindir = @bindir@
libdir = @libdir@ libdir = @libdir@
includedir = @includedir@ # This is actually the directory where we install our own header files.
# It is a little different from the generic includedir.
includedir = @includedir@/iverilog$(suffix)
mandir = @mandir@ mandir = @mandir@
libdir64 = @libdir64@ libdir64 = @libdir64@
@ -54,6 +56,8 @@ INSTALL_DATA = @INSTALL_DATA@
STRIP = @STRIP@ STRIP = @STRIP@
LEX = @LEX@ LEX = @LEX@
YACC = @YACC@ YACC = @YACC@
MAN = @MAN@
PS2PDF = @PS2PDF@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@ CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
CXXFLAGS = -Wall @CXXFLAGS@ CXXFLAGS = -Wall @CXXFLAGS@
@ -70,7 +74,7 @@ all: dep ivl@EXEEXT@
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in ivlpp tgt-verilog tgt-stub; \ for dir in ivlpp tgt-verilog tgt-stub; \
do (cd $$dir ; $(MAKE) $@); done do (cd $$dir ; $(MAKE) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@ cd driver ; $(MAKE) $@
# In the windows world, the installer will need a dosify program to # In the windows world, the installer will need a dosify program to
# dosify text files. # dosify text files.
@ -103,6 +107,7 @@ distclean: clean
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \ for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
do (cd $$dir ; $(MAKE) $@); done do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h rm -f Makefile config.status config.log config.cache config.h
rm -rf autom4te.cache
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
@ -111,7 +116,7 @@ O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \ elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
elab_sig.o emit.o eval.o eval_attrib.o \ elab_sig.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_assign.o \ load_module.o netlist.o NetLatch.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \ net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \ net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \ net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
@ -136,7 +141,7 @@ ivl@EXEEXT@: $O ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@ $(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
dlltool --dllname ivl@EXEEXT@ --def ivl.def \ dlltool --dllname ivl@EXEEXT@ --def ivl.def \
--output-lib libivl.a --output-exp ivl.exp --output-lib libivl.a --output-exp ivl.exp
$(CXX) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@ $(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
else else
ivl@EXEEXT@: $O ivl@EXEEXT@: $O
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib) $(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
@ -150,9 +155,13 @@ all: dep iverilog-vpi
iverilog-vpi: iverilog-vpi.sh iverilog-vpi: iverilog-vpi.sh
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \ sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@INCLUDEDIR@;@includedir@;' \ -e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
-e 's;@LIBDIR64@;@libdir64@;' \ -e 's;@LIBDIR64@;@libdir64@;' \
-e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \ -e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \
-e 's;@INCLUDEDIR@;$(includedir);' \
-e 's;@LIBDIR@;@libdir@;' $< > $@ -e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@ chmod +x $@
endif endif
@ -161,7 +170,7 @@ dep:
mkdir dep mkdir dep
%.o: %.cc %.o: %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o $(DEBUGFLAGS)
mv $*.d dep/$*.d mv $*.d dep/$*.d
@ -169,10 +178,8 @@ lexor.o: lexor.cc parse.h
parse.o: parse.cc parse.o: parse.cc
parse.cc: $(srcdir)/parse.y parse.cc parse.h: $(srcdir)/parse.y
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y $(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
parse.h: parse.cc
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
syn-rules.cc: $(srcdir)/syn-rules.y syn-rules.cc: $(srcdir)/syn-rules.y
@ -187,46 +194,55 @@ lexor_keyword.cc: lexor_keyword.gperf
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps $(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
iverilog-vpi.pdf: iverilog-vpi.ps iverilog-vpi.pdf: iverilog-vpi.ps
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf $(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
# Build and install the iverilog-vpi.pdf only if there is a man
# program *and* a ps2pdf program.
ifeq (@WIN32@,yes) ifeq (@WIN32@,yes)
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1 ifeq ($(MAN),none)
INSTALL_DOCDIR = $(mandir)/man1 INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
all: dep iverilog-vpi.pdf
else else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1 ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
else
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOCDIR = $(mandir)/man1 INSTALL_DOCDIR = $(mandir)/man1
endif endif
ifeq (@MINGW32@,yes) ifeq (@MINGW32@,yes)
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt WIN32_INSTALL =
else else
WIN32_INSTALL = $(bindir)/iverilog-vpi WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
endif endif
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf XNF_INSTALL = $(libdir)/ivl$(suffix)/xnf.conf $(libdir)/ivl$(suffix)/xnf-s.conf
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL) install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL)
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \ for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done do (cd $$dir ; $(MAKE) $@); done
$(bindir)/iverilog-vpi: ./iverilog-vpi $(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi $(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@ $(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@ $(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf $(libdir)/ivl$(suffix)/xnf-s.conf: $(srcdir)/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf $(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl$(suffix)/xnf-s.conf
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf $(libdir)/ivl$(suffix)/xnf.conf: $(srcdir)/xnf.conf
$(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl/xnf.conf $(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl$(suffix)/xnf.conf
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h $(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h $(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h
@ -243,49 +259,32 @@ $(includedir)/acc_user.h: $(srcdir)/acc_user.h
$(includedir)/veriuser.h: $(srcdir)/veriuser.h $(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h $(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man $(mandir)/man1/iverilog-vpi$(suffix).1: $(srcdir)/iverilog-vpi.man
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(mandir)/man1/iverilog-vpi.1 $(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf $(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf $(prefix)/iverilog-vpi.pdf $(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
# In windows installations, put a few examples and the quick_start
# into the destination directory.
ifeq (@MINGW32@,yes)
$(prefix)/hello.vl: $(srcdir)/examples/hello.vl
./dosify.exe $(srcdir)/examples/hello.vl tmp.vl
mv tmp.vl $(prefix)/hello.vl
$(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
mv tmp.vl $(prefix)/sqrt.vl
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
mv tmp.vl $(prefix)/sqrt-virtex.v
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
mv tmp.txt $(prefix)/QUICK_START.txt
endif
installdirs: mkinstalldirs installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl \ $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl$(suffix) \
$(mandir) $(mandir)/man1 $(DESTDIR)$(libdir)/ivl$(suffix)/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
uninstall: uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \ for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done do (cd $$dir ; $(MAKE) $@); done
for f in xnf.conf xnf-s.conf ivl; \ for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
do rm -f $(libdir)/ivl/$$f; done do rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/$$f; done
-rmdir $(libdir)/ivl -rmdir $(DESTDIR)$(libdir)/ivl$(suffix)/include
for f in verilog iverilog-vpi gverilog@EXEEXT@; \ -rmdir $(DESTDIR)$(libdir)/ivl$(suffix)
do rm -f $(bindir)/$$f; done for f in verilog$(suffix) iverilog-vpi$(suffix); \
do rm -f $(DESTDIR)$(bindir)/$$f; done
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \ for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
do rm -f $(includedir)/$$f; done do rm -f $(DESTDIR)$(includedir)/$$f; done
rm -f $(mandir)/man1/iverilog-vpi.1 -test X$(suffix) = X || rmdir $(DESTDIR)/$(includedir)
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1 $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
-include $(patsubst %.o, dep/%.d, $O) -include $(patsubst %.o, dep/%.d, $O)

48
NetLatch.cc Normal file
View File

@ -0,0 +1,48 @@
// NetLatch.cc
// Author: Alan M. Feldstein
// Class NetLatch member-function definitions
#include "NetLatch.h" // NetLatch class definition
#include "target.h" // target_t structure definition
// constructor
NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
// explicitly call base-class constructor
: NetNode( scope, name, 2U * width + 1U )
{
} // end NetLatch constructor
unsigned NetLatch::width() const
{
return ( pin_count() - 1U ) / 2U;
} // end function width
Link &NetLatch::pin_Data( unsigned w )
{
unsigned pn = 1 + 2 * w;
assert( pn < pin_count() );
return pin( pn );
} // end function pin_Data
Link &NetLatch::pin_Q( unsigned w )
{
unsigned pn = 2 + 2 * w;
assert( pn < pin_count() );
return pin( pn );
} // end function pin_Q
Link &NetLatch::pin_Gate()
{
return pin( 0 );
} // end function pin_Gate
const Link &NetLatch::pin_Gate() const
{
return pin( 0 );
} // end function pin_Gate
bool NetLatch::emit_node( target_t *driverPtr ) const
{
driverPtr->lpm_latch( this );
return true;
} // end function emit_node

34
NetLatch.h Normal file
View File

@ -0,0 +1,34 @@
// NetLatch.h
// Author: Alan M. Feldstein
// This class represents an LPM_LATCH device. In Verilog, storage components of this type can be inferred.
// The pinout is assigned like so:
// 0 -- Gate
//
// 1 -- Data[0]
// 2 -- Q[0]
// ...
#ifndef NETLATCH_H
#define NETLATCH_H
#include "netlist.h" // NetNode, NetScope, Link class definitions
#include "StringHeap.h" // perm_string class definition
class NetLatch : public NetNode
{
public:
NetLatch( NetScope *, perm_string, unsigned );
unsigned width() const;
Link &pin_Data( unsigned );
Link &pin_Q( unsigned );
Link &pin_Gate();
const Link &pin_Data( unsigned ) const;
const Link &pin_Q( unsigned ) const;
const Link &pin_Gate() const;
virtual bool emit_node( target_t * ) const;
}; // end class NetLatch
#endif

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PDelays.cc,v 1.11 2003/06/21 01:21:42 steve Exp $" #ident "$Id: PDelays.cc,v 1.11.2.1 2006/10/04 00:37:03 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -72,6 +72,20 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
dex = tmp; dex = tmp;
} }
int shift = scope->time_unit() - des->get_precision();
if (sizeof(unsigned) <= 4 && shift > 9) {
cerr << expr->get_line() << ": error: Precision overflow"
<< " in scope " << scope->name() << "." << endl;
cerr << expr->get_line() << ": :"
<< " Units are 10e" << scope->time_unit()
<< " minus precision 10e" << des->get_precision()
<< " is 10e" << shift << "." << endl;
cerr << expr->get_line() << ": : Perhaps a timescale "
<< "is missing or incorrect?" << endl;
des->errors += 1;
return 0;
}
/* If the delay expression is a real constant or vector /* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time constant, then evaluate it, scale it to the local time
units, and return an adjusted value. */ units, and return an adjusted value. */
@ -79,7 +93,6 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) { if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
verireal fn = tmp->value(); verireal fn = tmp->value();
int shift = scope->time_unit() - des->get_precision();
long delay = fn.as_long(shift); long delay = fn.as_long(shift);
if (delay < 0) if (delay < 0)
delay = 0; delay = 0;
@ -146,6 +159,9 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
/* /*
* $Log: PDelays.cc,v $ * $Log: PDelays.cc,v $
* Revision 1.11.2.1 2006/10/04 00:37:03 steve
* Detect delay precision overflow.
*
* Revision 1.11 2003/06/21 01:21:42 steve * Revision 1.11 2003/06/21 01:21:42 steve
* Harmless fixup of warnings. * Harmless fixup of warnings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.cc,v 1.35 2004/10/04 01:10:51 steve Exp $" #ident "$Id: PExpr.cc,v 1.35.2.1 2006/02/07 22:46:23 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -90,6 +90,8 @@ bool PEConcat::is_constant(Module *mod) const
{ {
bool constant = repeat_? repeat_->is_constant(mod) : true; bool constant = repeat_? repeat_->is_constant(mod) : true;
for (unsigned i = 0; constant && i < parms_.count(); ++i) { for (unsigned i = 0; constant && i < parms_.count(); ++i) {
if (parms_[i] == 0)
continue;
constant = constant && parms_[i]->is_constant(mod); constant = constant && parms_[i]->is_constant(mod);
} }
return constant; return constant;
@ -262,6 +264,9 @@ bool PEUnary::is_constant(Module*m) const
/* /*
* $Log: PExpr.cc,v $ * $Log: PExpr.cc,v $
* Revision 1.35.2.1 2006/02/07 22:46:23 steve
* More robust test for concat constant-ness.
*
* Revision 1.35 2004/10/04 01:10:51 steve * Revision 1.35 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

16
PExpr.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.66 2004/10/04 01:10:51 steve Exp $" #ident "$Id: PExpr.h,v 1.66.2.2 2006/07/28 16:26:17 steve Exp $"
#endif #endif
# include <string> # include <string>
@ -115,6 +115,8 @@ class PEConcat : public PExpr {
PEConcat(const svector<PExpr*>&p, PExpr*r =0); PEConcat(const svector<PExpr*>&p, PExpr*r =0);
~PEConcat(); ~PEConcat();
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
// Concatenated Regs can be on the left of procedural // Concatenated Regs can be on the left of procedural
@ -324,7 +326,7 @@ class PEString : public PExpr {
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const; bool sys_task_arg =false) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const; virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* PEString::eval_const(const Design*, const NetScope*) const; verinum* eval_const(const Design*, const NetScope*) const;
virtual bool is_constant(Module*) const; virtual bool is_constant(Module*) const;
@ -374,7 +376,7 @@ class PEBinary : public PExpr {
unsigned long decay, unsigned long decay,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const; Link::strength_t drive1) const;
virtual NetEBinary*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const; bool sys_task_arg =false) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const; virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
@ -384,7 +386,7 @@ class PEBinary : public PExpr {
PExpr*left_; PExpr*left_;
PExpr*right_; PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const; NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
NetNet* elaborate_net_add_(Design*des, NetScope*scope, NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth, unsigned lwidth,
@ -492,6 +494,12 @@ class PECallFunction : public PExpr {
/* /*
* $Log: PExpr.h,v $ * $Log: PExpr.h,v $
* Revision 1.66.2.2 2006/07/28 16:26:17 steve
* Remove excess PEString:: prefix for stubborn compilers.
*
* Revision 1.66.2.1 2005/12/07 03:28:44 steve
* Support constant concatenation of constants.
*
* Revision 1.66 2004/10/04 01:10:51 steve * Revision 1.66 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PTask.h,v 1.13 2004/05/31 23:34:36 steve Exp $" #ident "$Id: PTask.h,v 1.13.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "LineInfo.h" # include "LineInfo.h"
@ -70,7 +70,7 @@ class PTask : public LineInfo {
// Elaborate the statement to finish off the task definition. // Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const; void elaborate(Design*des, NetScope*scope) const;
void dump(ostream&, unsigned) const; void dump(std::ostream&, unsigned) const;
private: private:
svector<PWire*>*ports_; svector<PWire*>*ports_;
@ -106,7 +106,7 @@ class PFunction : public LineInfo {
/* Elaborate the behavioral statement. */ /* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const; void elaborate(Design *des, NetScope*) const;
void dump(ostream&, unsigned) const; void dump(std::ostream&, unsigned) const;
private: private:
perm_string name_; perm_string name_;
@ -117,6 +117,9 @@ class PFunction : public LineInfo {
/* /*
* $Log: PTask.h,v $ * $Log: PTask.h,v $
* Revision 1.13.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.13 2004/05/31 23:34:36 steve * Revision 1.13 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * function return values to allow for better

13
PUdp.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $" #ident "$Id: PUdp.h,v 1.12.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include <map> # include <map>
@ -55,20 +55,20 @@ class PUdp {
public: public:
explicit PUdp(perm_string n, unsigned nports); explicit PUdp(perm_string n, unsigned nports);
svector<string>ports; svector<std::string>ports;
unsigned find_port(const char*name); unsigned find_port(const char*name);
bool sequential; bool sequential;
svector<string>tinput; svector<std::string>tinput;
svector<char> tcurrent; svector<char> tcurrent;
svector<char> toutput; svector<char> toutput;
verinum::V initial; verinum::V initial;
map<string,PExpr*> attributes; std::map<std::string,PExpr*> attributes;
void dump(ostream&out) const; void dump(std::ostream&out) const;
perm_string name_; perm_string name_;
private: private:
@ -80,6 +80,9 @@ class PUdp {
/* /*
* $Log: PUdp.h,v $ * $Log: PUdp.h,v $
* Revision 1.12.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.12 2004/03/08 00:47:44 steve * Revision 1.12 2004/03/08 00:47:44 steve
* primitive ports can bind bi name. * primitive ports can bind bi name.
* *

View File

@ -88,10 +88,6 @@ Normally, this command automatically figures out everything it needs
to know. It generally works pretty well. There are a few flags to the to know. It generally works pretty well. There are a few flags to the
configure script that modify its behavior: configure script that modify its behavior:
--without-ipal
This turns off support for Icarus PAL, whether ipal
libraries are installed or not.
--prefix=<root> --prefix=<root>
The default is /usr/local, which causes the tool suite to The default is /usr/local, which causes the tool suite to
be compiled for install in /usr/local/bin, be compiled for install in /usr/local/bin,
@ -107,6 +103,17 @@ configure script that modify its behavior:
compilation of 32bit compatible vvp (vvp32) and the vpi compilation of 32bit compatible vvp (vvp32) and the vpi
modules that match. modules that match.
--enable-suffix
--enable-suffix=<your-suffix>
--disable-suffix
Enable/disable changing the names of install files to use
a suffix string so that this version or install can co-
exist with other versions. This renames the installed
commands (iverilog, iverilog-vpi, vvp) and the installed
library files and include directory so that installations
with the same prefix but different suffix are guaranteed
to not interfere with each other.
2.2.1 Special AMD64 Instructions 2.2.1 Special AMD64 Instructions
(The Icarus Verilog RPM for x86_64 is build using these instructions.) (The Icarus Verilog RPM for x86_64 is build using these instructions.)
@ -114,7 +121,7 @@ configure script that modify its behavior:
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
most out of your install, first make sure you have both 64bit and most out of your install, first make sure you have both 64bit and
32bit development libraries installed. Then configure with this 32bit development libraries installed. Then configure with this
somewhat more compilcated command: somewhat more complex command:
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32 ./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $" #ident "$Id: Statement.h,v 1.40.2.1 2006/07/10 00:21:49 steve Exp $"
#endif #endif
# include <string> # include <string>
@ -71,12 +71,15 @@ class PProcess : public LineInfo {
* fact, the Statement class is abstract and represents all the * fact, the Statement class is abstract and represents all the
* possible kinds of statements that exist in Verilog. * possible kinds of statements that exist in Verilog.
*/ */
class Statement : public LineInfo { class Statement : public LineInfo, public Attrib {
public: public:
Statement() { } Statement() { }
virtual ~Statement() =0; virtual ~Statement() =0;
map<perm_string,PExpr*> attributes;
void dump_attributes(ostream&out, unsigned ind) const;
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const;
@ -456,6 +459,9 @@ class PWhile : public Statement {
/* /*
* $Log: Statement.h,v $ * $Log: Statement.h,v $
* Revision 1.40.2.1 2006/07/10 00:21:49 steve
* Add support for full_case attribute.
*
* Revision 1.40 2004/02/20 18:53:33 steve * Revision 1.40 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $" #ident "$Id: StringHeap.cc,v 1.6.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "StringHeap.h" # include "StringHeap.h"
@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*text)
return perm_string(add(text)); return perm_string(add(text));
} }
perm_string StringHeapLex::make(const string&text) perm_string StringHeapLex::make(const std::string&text)
{ {
return perm_string(add(text.c_str())); return perm_string(add(text.c_str()));
} }
@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
/* /*
* $Log: StringHeap.cc,v $ * $Log: StringHeap.cc,v $
* Revision 1.6.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.6 2004/02/18 17:11:54 steve * Revision 1.6 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

View File

@ -19,12 +19,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.h,v 1.5 2004/02/18 17:11:54 steve Exp $" #ident "$Id: StringHeap.h,v 1.5.2.2 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include <string> # include <string>
using namespace std;
class perm_string { class perm_string {
public: public:
@ -101,7 +103,7 @@ class StringHeapLex : private StringHeap {
const char*add(const char*); const char*add(const char*);
perm_string make(const char*); perm_string make(const char*);
perm_string make(const string&); perm_string make(const std::string&);
unsigned add_count() const; unsigned add_count() const;
unsigned add_hit_count() const; unsigned add_hit_count() const;
@ -120,6 +122,12 @@ class StringHeapLex : private StringHeap {
/* /*
* $Log: StringHeap.h,v $ * $Log: StringHeap.h,v $
* Revision 1.5.2.2 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.5.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.5 2004/02/18 17:11:54 steve * Revision 1.5 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

39
aclocal.m4 vendored
View File

@ -14,7 +14,7 @@
AC_DEFUN([AX_CPP_IDENT], AC_DEFUN([AX_CPP_IDENT],
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident, [AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
[AC_TRY_COMPILE([ [AC_TRY_COMPILE([
#ident "$Id: aclocal.m4,v 1.6 2004/10/04 01:10:52 steve Exp $" #ident "$Id: aclocal.m4,v 1.6.2.2 2007/05/16 23:51:42 steve Exp $"
],[while (0) {}], ],[while (0) {}],
[AS_VAR_SET(ax_cv_cpp_ident, yes)], [AS_VAR_SET(ax_cv_cpp_ident, yes)],
[AS_VAR_SET(ax_cv_cpp_ident, no)])]) [AS_VAR_SET(ax_cv_cpp_ident, no)])])
@ -24,6 +24,23 @@ fi
AC_SUBST(ident_support) AC_SUBST(ident_support)
])# AC_CPP_IDENT ])# AC_CPP_IDENT
# AX_ENABLE_SUFFIX
# ----------------
# Create the configure option --enable-suffix[=suffix] to generate suffix
# strings for the installed commands. This allows for shared installs of
# different builds. Remember to change the default suffix string to some
# value appropriate for the current version.
AC_DEFUN([AX_ENABLE_SUFFIX],
[AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=yes])
if test X$enable_suffix = Xyes; then
install_suffix='-0.8'
elif test X$enable_suffix = Xno; then
install_suffix=''
else
install_suffix="$enable_suffix"
fi
AC_SUBST(install_suffix)
])# AX_ENABLE_SUFFIX
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH) # _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
# ------------------------------ # ------------------------------
@ -48,7 +65,7 @@ AC_DEFUN([AX_C_UNDERSCORES_LEADING],
[AS_VAR_SET(ax_cv_c_underscores_leading, yes)], [AS_VAR_SET(ax_cv_c_underscores_leading, yes)],
[AS_VAR_SET(ax_cv_c_underscores_leading, no)])]) [AS_VAR_SET(ax_cv_c_underscores_leading, no)])])
if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
AC_DEFINE(NEED_LU) AC_DEFINE([NEED_LU], [1], [Symbol names in object files produced by C compiler have leading underscores.])
fi fi
])# AX_C_UNDERSCORES_LEADING ])# AX_C_UNDERSCORES_LEADING
@ -63,7 +80,7 @@ AC_DEFUN([AX_C_UNDERSCORES_TRAILING],
[AS_VAR_SET(ax_cv_c_underscores_trailing, yes)], [AS_VAR_SET(ax_cv_c_underscores_trailing, yes)],
[AS_VAR_SET(ax_cv_c_underscores_trailing, no)])]) [AS_VAR_SET(ax_cv_c_underscores_trailing, no)])])
if test $ax_cv_c_underscores_trailing = yes; then if test $ax_cv_c_underscores_trailing = yes; then
AC_DEFINE(NEED_TU) AC_DEFINE([NEED_TU], [1], [Symbol names in object files produced by C compiler have trailing underscores.])
fi fi
])# AX_C_UNDERSCORES_TRAILING ])# AX_C_UNDERSCORES_TRAILING
@ -91,13 +108,9 @@ AC_MSG_RESULT($WIN32)
AC_DEFUN([AX_LD_EXTRALIBS], AC_DEFUN([AX_LD_EXTRALIBS],
[AC_MSG_CHECKING([for extra libs needed]) [AC_MSG_CHECKING([for extra libs needed])
EXTRALIBS= EXTRALIBS=
case "${host}" in if test "$MINGW32" = "yes"; then
*-*-cygwin* ) EXTRALIBS="-liberty"
if test "$MINGW32" = "yes"; then fi
EXTRALIBS="-liberty"
fi
;;
esac
AC_SUBST(EXTRALIBS) AC_SUBST(EXTRALIBS)
AC_MSG_RESULT($EXTRALIBS) AC_MSG_RESULT($EXTRALIBS)
])# AX_LD_EXTRALIBS ])# AX_LD_EXTRALIBS
@ -109,7 +122,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
[AC_MSG_CHECKING([for shared library link flag]) [AC_MSG_CHECKING([for shared library link flag])
shared=-shared shared=-shared
case "${host}" in case "${host}" in
*-*-cygwin*) *-*-cygwin* | *-*-mingw32*)
shared="-shared -Wl,--enable-auto-image-base" shared="-shared -Wl,--enable-auto-image-base"
;; ;;
@ -138,7 +151,7 @@ AC_DEFUN([AX_C_PICFLAG],
PICFLAG=-fPIC PICFLAG=-fPIC
case "${host}" in case "${host}" in
*-*-cygwin*) *-*-cygwin* | *-*-mingw32*)
PICFLAG= PICFLAG=
;; ;;
@ -173,7 +186,7 @@ case "${host}" in
rdynamic="" rdynamic=""
;; ;;
*-*-cygwin*) *-*-cygwin* | *-*-mingw32*)
rdynamic="" rdynamic=""
;; ;;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $" #ident "$Id: async.cc,v 1.7.2.2 2007/05/30 17:48:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -66,6 +66,10 @@ bool NetEvWait::is_asynchronous()
NexusSet*inputs = statement_->nex_input(); NexusSet*inputs = statement_->nex_input();
/* All the inputs of the statement must be accounted for in
the sensitivity list. Otherwise, there are inputs that can
change without the event being triggered, and that implies
a latch, not a combinational circuit. */
if (! sense->contains(*inputs)) { if (! sense->contains(*inputs)) {
delete sense; delete sense;
delete inputs; delete inputs;
@ -85,7 +89,7 @@ bool NetProc::is_asynchronous()
return false; return false;
} }
bool NetProcTop::is_asynchronous() bool NetProcTop::is_asynchronous() const
{ {
if (type_ == NetProcTop::KINITIAL) if (type_ == NetProcTop::KINITIAL)
return false; return false;
@ -95,6 +99,12 @@ bool NetProcTop::is_asynchronous()
/* /*
* $Log: async.cc,v $ * $Log: async.cc,v $
* Revision 1.7.2.2 2007/05/30 17:48:53 steve
* Support Latch synthesis (Alan Feldstein)
*
* Revision 1.7.2.1 2006/05/21 21:58:46 steve
* NetESignal input is only selected bits.
*
* Revision 1.7 2004/01/18 23:26:54 steve * Revision 1.7 2004/01/18 23:26:54 steve
* The is_combinational function really need not recurse. * The is_combinational function really need not recurse.
* *

View File

@ -70,6 +70,14 @@ warning.)
* Other Attributes * Other Attributes
(* ivl_full_case *)
This attribute only has meaning when attached to case statements,
and only when doing synthesis. The statement means to ignore the
possibility that some cases are not defined. Presume that the
device really is fully specified and do not emit any warnings
about missing guards.
[ none defined yet ] [ none defined yet ]

View File

@ -9,10 +9,10 @@
echo "Autoconf in root..." echo "Autoconf in root..."
autoconf autoconf
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli for dir in vpip vpi vvp tgt-vvp tgt-edif tgt-fpga libveriuser cadpli
do do
echo "Autoconf in $dir..." echo "Autoconf in $dir..."
( cd ./$dir ; autoconf --include=.. ) ( cd ./$dir ; autoconf -f --include=.. )
done done
echo "Precompiling lexor_keyword.gperf" echo "Precompiling lexor_keyword.gperf"

View File

@ -16,12 +16,12 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.11 2004/10/04 01:09:07 steve Exp $" #ident "$Id: Makefile.in,v 1.11.2.1 2005/02/23 18:40:23 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
VERSION = 0.0 suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -33,7 +33,7 @@ bindir = @bindir@
libdir = @libdir@ libdir = @libdir@
includedir = $(prefix)/include includedir = $(prefix)/include
vpidir = @libdir@/ivl/@vpidir1@ vpidir = @libdir@/ivl$(suffix)/@vpidir1@
strip_dynamic=@strip_dynamic@ strip_dynamic=@strip_dynamic@
@ -52,7 +52,7 @@ SHARED = @shared@
all: all:
ifeq (@enable_vvp32@,yes) ifeq (@enable_vvp32@,yes)
vpidir32 = $(libdir)/ivl/@vpidir2@ vpidir32 = $(libdir)/ivl$(suffix)/@vpidir2@
ALL32 = all32 ALL32 = all32
INSTALL32 = install32 INSTALL32 = install32
UNINSTALL32 = uninistall32 UNINSTALL32 = uninistall32
@ -86,6 +86,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32) install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)

View File

@ -10,6 +10,8 @@ AC_SUBST(EXEEXT)
# Combined check for Microsoft-related bogosities; sets WIN32 if found # Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32 AX_WIN32
AX_ENABLE_SUFFIX
AC_PROG_INSTALL AC_PROG_INSTALL
# vvp32 is by default disabled # vvp32 is by default disabled
@ -37,7 +39,7 @@ AC_SUBST(DLLIB)
AX_CPP_PRECOMP AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects. # Compiler option for position independent code, needed when making shared objects.
AX_C_PICFLAG AX_C_PICFLAG
# Linker option used when compiling the target # Linker option used when compiling the target

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: compiler.h,v 1.26 2004/10/04 01:10:52 steve Exp $" #ident "$Id: compiler.h,v 1.26.2.3 2006/06/12 00:16:50 steve Exp $"
#endif #endif
# include <list> # include <list>
@ -78,12 +78,17 @@ extern bool warn_timescale;
/* Warn about legal but questionable module port bindings. */ /* Warn about legal but questionable module port bindings. */
extern bool warn_portbinding; extern bool warn_portbinding;
/* Warn about unused or unassigned variables. */
extern bool warn_unused;
/* This is true if verbose output is requested. */ /* This is true if verbose output is requested. */
extern bool verbose_flag; extern bool verbose_flag;
extern bool debug_scopes; extern bool debug_scopes;
extern bool debug_eval_tree; extern bool debug_eval_tree;
extern bool debug_elaborate; extern bool debug_elaborate;
extern bool debug_synth;
extern bool debug_cprop;
/* Path to a directory useful for finding subcomponents. */ /* Path to a directory useful for finding subcomponents. */
extern const char*basedir; extern const char*basedir;
@ -136,6 +141,15 @@ extern int load_sys_func_table(const char*path);
/* /*
* $Log: compiler.h,v $ * $Log: compiler.h,v $
* Revision 1.26.2.3 2006/06/12 00:16:50 steve
* Add support for -Wunused warnings.
*
* Revision 1.26.2.2 2006/04/23 04:25:45 steve
* Add cprop debugging.
*
* Revision 1.26.2.1 2006/04/01 01:37:24 steve
* Add synth debug flag
*
* Revision 1.26 2004/10/04 01:10:52 steve * Revision 1.26 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -9,6 +9,9 @@ AC_PROG_CC
AC_PROG_CXX AC_PROG_CXX
AC_CHECK_TOOL(STRIP, strip, true) AC_CHECK_TOOL(STRIP, strip, true)
AC_CHECK_PROGS(XGPERF,gperf,none) AC_CHECK_PROGS(XGPERF,gperf,none)
AC_CHECK_PROGS(MAN,man,none)
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
if test "$XGPERF" = "none" if test "$XGPERF" = "none"
then then
echo "" echo ""
@ -56,9 +59,12 @@ AC_CHECK_LIB(z, gzwrite, HAVE_LIBZ=yes, HAVE_LIBZ=no)
AC_SUBST(HAVE_LIBZ) AC_SUBST(HAVE_LIBZ)
if test "$WIN32" = "yes"; then if test "$WIN32" = "yes"; then
AC_CHECK_LIB(bz2, main) AC_CHECK_LIB(bz2, main)
AC_CHECK_LIB(bz2, main, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
else else
AC_CHECK_LIB(bz2, BZ2_bzdopen) AC_CHECK_LIB(bz2, BZ2_bzdopen)
AC_CHECK_LIB(bz2, BZ2_bzdopen, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
fi fi
AC_SUBST(HAVE_LIBBZ2)
AC_MSG_CHECKING(for sys/times) AC_MSG_CHECKING(for sys/times)
AC_TRY_LINK( AC_TRY_LINK(
@ -66,7 +72,7 @@ AC_TRY_LINK(
#include <sys/times.h> #include <sys/times.h>
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);}, ,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
do_times=yes do_times=yes
AC_DEFINE(HAVE_TIMES,1), AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
do_times=no do_times=no
) )
AC_MSG_RESULT($do_times) AC_MSG_RESULT($do_times)
@ -91,9 +97,11 @@ AC_C_BIGENDIAN
# $host # $host
AX_ENABLE_SUFFIX
AX_LD_EXTRALIBS AX_LD_EXTRALIBS
# Compiler option for position independent code, needed whan making shared objects. # Compiler option for position independent code, needed when making shared objects.
# CFLAGS inherited by cadpli/Makefile? # CFLAGS inherited by cadpli/Makefile?
AX_C_PICFLAG AX_C_PICFLAG
@ -141,6 +149,6 @@ AC_SUBST(vpidir1)
AC_SUBST(vpidir2) AC_SUBST(vpidir2)
AC_MSG_RESULT(${vpidir1} ${vpidir2}) AC_MSG_RESULT(${vpidir1} ${vpidir2})
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-fpga libveriuser cadpli) AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-edif tgt-fpga libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile) AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)

414
cprop.cc
View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $" #ident "$Id: cprop.cc,v 1.47.2.7 2007/02/26 19:51:38 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -25,6 +25,7 @@
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
# include "functor.h" # include "functor.h"
# include "compiler.h"
# include <assert.h> # include <assert.h>
@ -47,6 +48,9 @@ struct cprop_functor : public functor_t {
virtual void lpm_ff(Design*des, NetFF*obj); virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj); virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj); virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_mux_large(Design*des, NetMux*obj);
virtual void lpm_ram_dq(Design*des, NetRamDq*obj);
bool lpm_ram_dq_const_address_(Design*des, NetRamDq*obj);
}; };
void cprop_functor::signal(Design*des, NetNet*obj) void cprop_functor::signal(Design*des, NetNet*obj)
@ -842,84 +846,378 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
/* /*
* This detects the case where the mux selects between a value and * This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a bufif with the sel * Vz. In this case, replace the device with a MOS with the sel
* input used to enable the output. * input used to enable the output.
*/ */
void cprop_functor::lpm_mux(Design*des, NetMux*obj) void cprop_functor::lpm_mux(Design*des, NetMux*obj)
{ {
if (obj->size() > 2) {
lpm_mux_large(des, obj);
return;
}
if (obj->size() != 2) if (obj->size() != 2)
return; return;
if (obj->sel_width() != 1) if (obj->sel_width() != 1)
return; return;
/* If the first input is all constant Vz, then replace the NetScope*scope = obj->scope();
NetMux with an array of BUFIF1 devices, with the enable
connected to the select input. */
bool flag = true; bool flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) { for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) { bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
flag = false; bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
break;
}
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) { /* If both data inputs are constant, we'll be able to do
flag = false; a substitution. */
break; if (cflag_a && cflag_b)
} continue;
verinum::V va = cflag_a
? obj->pin_Data(idx, 0).nexus()->driven_value()
: verinum::Vx;
verinum::V vb = cflag_b
? obj->pin_Data(idx, 1).nexus()->driven_value()
: verinum::Vx;
/* If only one Data input is constant, but a constant
HiZ, then we will be able to do a MOS
substitution. */
if (cflag_a && va==verinum::Vz)
continue;
if (cflag_b && vb==verinum::Vz)
continue;
/* Otherwise, we cannot accurately do a substitution. If
one input is non-constant, then that input may have a
HiZ value, and there is no Verilog logic other then a
MUX that can pass a HiZ value. */
flag = false;
} }
if (flag) { if (! flag) {
NetScope*scope = obj->scope(); return;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) { }
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF1);
connect(obj->pin_Result(idx), tmp->pin(0)); /* Create a temporary net to hold the result value that we
build up. When we are done, we will connect this to the
Result pins of the mux, then delete the mux *and* this
net. That will cause all the proper connectivity to
happen. */
NetNet result_tmp(scope, scope->local_symbol(),
NetNet::WIRE, obj->width());
/* We know that every slice has at least one constant. Run
through the slices again, creating boolean devices to
replace the MUX slice. */
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
/* If the Sel==0 input is constant Z, make a NMOS. */
if (obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 0).nexus()->driven_value()==verinum::Vz) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::NMOS);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1)); connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2)); connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp); des->add_node(tmp);
continue;
} }
count += 1; /* If the Sel==1 input is constant Z, make a PMOS. */
delete obj; if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
return; && obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
}
/* If instead the second input is all constant Vz, replace the NetLogic*tmp = new NetLogic(scope,
NetMux with an array of BUFIF0 devices. */
flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (! obj->pin_Data(idx, 1).nexus()->drivers_constant()) {
flag = false;
break;
}
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
flag = false;
break;
}
}
if (flag) {
NetScope*scope = obj->scope();
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(), scope->local_symbol(),
3, NetLogic::BUFIF0); 3, NetLogic::PMOS);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1)); connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2)); connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp); des->add_node(tmp);
continue;
} }
count += 1; /* At this point, the only cases that are left are where
delete obj; the data inputs are both constant, and neither are
HiZ. From this we know how to generate the output
from only the S input. */
if (! (obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 1).nexus()->drivers_constant())) {
cerr << obj->get_line() << ": internal error: "
<< "Drivers not constant where expected?"
<< " obj->width()=" << obj->width()
<< " idx=" << idx
<< endl;
obj->dump_node(cerr, 4);
}
assert(obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 1).nexus()->drivers_constant());
verinum::V a = obj->pin_Data(idx, 0).nexus()->driven_value();
verinum::V b = obj->pin_Data(idx, 1).nexus()->driven_value();
if (a == b) {
connect(result_tmp.pin(idx), obj->pin_Data(idx,0));
continue;
}
if (a == verinum::V0 && b == verinum::V1) {
connect(result_tmp.pin(idx), obj->pin_Sel(0));
continue;
}
if (a == verinum::V1 && b == verinum::V0) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Sel(0), tmp->pin(1));
des->add_node(tmp);
continue;
}
/* A==0: Q = B & S */
if (a == verinum::V0) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::AND);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* B==1: Q = A | S */
if (b == verinum::V1) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::OR);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* A==1: Q = B | ~S */
if (a == verinum::V1) {
NetLogic*inv = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
NetNet*invs = new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, 1);
invs->local_flag(true);
connect(inv->pin(0), invs->pin(0));
connect(inv->pin(1), obj->pin_Sel(0));
des->add_node(inv);
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::OR);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(inv->pin(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* B==0: Q = A & ~S */
if (b == verinum::V0) {
NetLogic*inv = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
NetNet*invs = new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, 1);
invs->local_flag(true);
connect(inv->pin(0), invs->pin(0));
connect(inv->pin(1), obj->pin_Sel(0));
des->add_node(inv);
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::AND);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(inv->pin(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
assert(0);
}
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
connect(result_tmp.pin(idx), obj->pin_Result(idx));
delete obj;
count += 1;
}
void cprop_functor::lpm_mux_large(Design*des, NetMux*obj)
{
NetScope*scope = obj->scope();
unsigned width = obj->width();
unsigned size = obj->size();
/* This test looks for bit slices that are constant
throughout. If we find any, we can reduce the width of the
MUX to eliminate the fixed value. */
/* After the following for loop, this array of bools will
contain "true" for each bit slice that is constant and
identical, and "false" otherwise. The reduce_width will
count the number of true entries in the flags array. */
bool*flags = new bool[width];
unsigned reduce_width = 0;
for (unsigned bit = 0 ; bit < width ; bit += 1) {
flags[bit] = true;
/* If not even the first selection is constant, then the
slice cannot be reduced. */
if (! obj->pin_Data(bit, 0).nexus()->drivers_constant()) {
flags[bit] = false;
continue;
}
/* If any of the remaining selections in non-consant, or
constant with a different value, then this slice
cannot be reduced. */
verinum::V val = obj->pin_Data(bit, 0).nexus()->driven_value();
for (unsigned idx = 1; flags[bit] && idx < size ; idx += 1) {
if (!obj->pin_Data(bit,idx).nexus()->drivers_constant()) {
flags[bit] = false;
break;
}
if (val != obj->pin_Data(bit,idx).nexus()->driven_value()) {
flags[bit] = false;
break;
}
}
if (! flags[bit]) {
/* This bit slice is too complex. Go on. */
continue;
}
reduce_width += 1;
}
/* If no slices can be reduced, then we are finished. */
if (reduce_width == 0) {
delete[]flags;
return; return;
} }
/* Handle the very special case that all the slices can be
reduced. We don't need a MUX at all! */
if (reduce_width == width) {
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
delete obj;
count += 1;
delete[]flags;
return;
}
/* Create a reduced mux with the same name and size, but fewer
slices. Connect all the slices that we are keeping. */
NetMux*tmp = new NetMux(scope, obj->name(),
width-reduce_width, size, obj->sel_width());
tmp->set_line(*obj);
for (unsigned idx = 0 ; idx < obj->sel_width() ; idx += 1)
connect(obj->pin_Sel(idx), tmp->pin_Sel(idx));
unsigned dst_bit = 0;
for (unsigned bit = 0 ; bit < width ; bit += 1) {
if (flags[bit]) {
connect(obj->pin_Result(bit), obj->pin_Data(bit,0));
continue;
}
connect(obj->pin_Result(bit), tmp->pin_Result(dst_bit));
for (unsigned idx = 0 ; idx < size ; idx += 1)
connect(obj->pin_Data(bit,idx), tmp->pin_Data(dst_bit,idx));
dst_bit += 1;
}
/* Add the new node. Delete the old node. Signal that we
change the design and may use a rescan. */
des->add_node(tmp);
delete obj;
delete[]flags;
count += 1;
} }
void cprop_functor::lpm_ram_dq(Design*des, NetRamDq*obj)
{
if (lpm_ram_dq_const_address_(des,obj))
return;
}
/*
* Try to evaluate a constant address input. If we find it, then
* replace the NetRamDq with a direct link to the addressed word.
*/
bool cprop_functor::lpm_ram_dq_const_address_(Design*des, NetRamDq*obj)
{
NetMemory*mem = obj->mem();
NetNet* reg = mem->reg_from_explode();
/* I only know how to do this on exploded memories. */
if (reg == 0)
return false;
verinum sel (0UL, obj->awidth());
for (unsigned idx = 0 ; idx < obj->awidth() ; idx += 1) {
if (! obj->pin_Address(idx).nexus()->drivers_constant())
return false;
sel.set(idx, obj->pin_Address(idx).nexus()->driven_value());
}
unsigned long address = sel.as_ulong();
/* If the address is outside the ram, then leave this to the
code generator to figure out. */
if (address >= obj->size())
return false;
unsigned base = address * obj->width();
assert(base+obj->width() <= reg->pin_count());
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
connect(reg->pin(base+idx), obj->pin_Q(idx));
if (debug_cprop) {
cerr << obj->get_line() << ": debug: Replace read port with"
<< " fixed link to word " << address << "." << endl;
}
delete obj;
count += 1;
return true;
}
/* /*
* This functor looks to see if the constant is connected to nothing * This functor looks to see if the constant is connected to nothing
* but signals. If that is the case, delete the dangling constant and * but signals. If that is the case, delete the dangling constant and
@ -1038,6 +1336,24 @@ void cprop(Design*des)
/* /*
* $Log: cprop.cc,v $ * $Log: cprop.cc,v $
* Revision 1.47.2.7 2007/02/26 19:51:38 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.47.2.6 2006/11/12 01:20:45 steve
* Prevent constant mux outputs from confusing itself.
*
* Revision 1.47.2.5 2006/04/23 04:26:13 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.47.2.4 2005/09/11 02:50:51 steve
* Fix overly agressive constant propagation through MUX causing lost Z bits.
*
* Revision 1.47.2.3 2005/08/28 22:00:39 steve
* Reduce mux slices that are constant throughout range.
*
* Revision 1.47.2.2 2005/08/28 19:51:02 steve
* More thorough constant propagation through MUX devices.
*
* Revision 1.47 2004/02/20 18:53:34 steve * Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.149 2004/10/04 01:10:52 steve Exp $" #ident "$Id: design_dump.cc,v 1.149.2.7 2006/08/23 04:09:14 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -77,6 +77,8 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " (local)"; o << " (local)";
if (signed_) if (signed_)
o << " signed"; o << " signed";
if (mref_)
o << " mref_=" << mref_->name();
switch (port_type_) { switch (port_type_) {
case NetNet::NOT_A_PORT: case NetNet::NOT_A_PORT:
break; break;
@ -171,7 +173,8 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
if (pin(idx).is_linked()) { if (pin(idx).is_linked()) {
const Nexus*nex = pin(idx).nexus(); const Nexus*nex = pin(idx).nexus();
o << nex << " " << nex->name(); const char*nex_name = nex->name();
o << nex << " " << (nex_name? nex_name : "????");
} }
o << endl; o << endl;
@ -216,6 +219,23 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4); dump_obj_attr(o, ind+4);
} }
void NetDecode::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
<< " ff=" << ff_->name() << ", word width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetDemux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
<< " bus width=" << width() << ", address width=" << awidth()
<< ", word count=" << size() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetDivide::dump_node(ostream&o, unsigned ind) const void NetDivide::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl; o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl;
@ -240,6 +260,7 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "Multiplexer (NetMux): " << name() o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
<< " scope=" << scope()->name() << endl; << " scope=" << scope()->name() << endl;
o << setw(ind+6) << "" << "source=" << get_line() << endl;
dump_node_pins(o, ind+4); dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4); dump_obj_attr(o, ind+4);
} }
@ -272,7 +293,12 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "LPM_FF: " << name() o << setw(ind) << "" << "LPM_FF: " << name()
<< " scope=" << (scope()? scope()->name() : "") << " scope=" << (scope()? scope()->name() : "")
<< " aset_value=" << aset_value_ << endl; << " aset_value=" << aset_value_
<< " sset_value=" << sset_value_;
if (demux_) o << " demux=" << demux_->name();
o << endl;
dump_node_pins(o, ind+4); dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4); dump_obj_attr(o, ind+4);
@ -355,8 +381,16 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
void NetRamDq::dump_node(ostream&o, unsigned ind) const void NetRamDq::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): " o << setw(ind) << "" << "LPM_RAM_DQ (";
<< name() << endl;
if (mem_)
if (NetNet*tmp = mem_->reg_from_explode())
o << "exploded mem=" << tmp->name();
else
o << "mem=" << mem_->name();
o << "): " << name() << endl;
dump_node_pins(o, ind+4); dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4); dump_obj_attr(o, ind+4);
} }
@ -432,7 +466,7 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
void NetAssign_::dump_lval(ostream&o) const void NetAssign_::dump_lval(ostream&o) const
{ {
if (sig_) { if (sig_) {
o << sig_->name(); o << "sig=" << sig_->name();
if (bmux_) { if (bmux_) {
o << "[" << *bmux_ << "]"; o << "[" << *bmux_ << "]";
@ -443,7 +477,7 @@ void NetAssign_::dump_lval(ostream&o) const
// Is there an obvious way to flag memories in the dump // Is there an obvious way to flag memories in the dump
// as different from the _real_ bit mux case? // as different from the _real_ bit mux case?
// o << "**memory**"; // o << "**memory**";
o << mem_->name() << "["; o << "mem=" << mem_->name() << "[";
if (bmux_) o << *bmux_; if (bmux_) o << *bmux_;
else o << "**oops**"; else o << "**oops**";
o << "]"; o << "]";
@ -537,6 +571,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
break; break;
} }
dump_proc_attr(o, ind+2);
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
o << setw(ind+2) << ""; o << setw(ind+2) << "";
if (items_[idx].guard) if (items_[idx].guard)
@ -842,6 +878,15 @@ void NetProc::dump(ostream&o, unsigned ind) const
o << setw(ind) << "" << "// " << typeid(*this).name() << endl; o << setw(ind) << "" << "// " << typeid(*this).name() << endl;
} }
void NetProc::dump_proc_attr(ostream&o, unsigned ind) const
{
unsigned idx;
for (idx = 0 ; idx < attr_cnt() ; idx += 1) {
o << setw(ind) << "" << "(* " << attr_key(idx) << " = "
<< attr_value(idx) << " *)" << endl;
}
}
/* Dump an expression that no one wrote a dump method for. */ /* Dump an expression that no one wrote a dump method for. */
void NetExpr::dump(ostream&o) const void NetExpr::dump(ostream&o) const
{ {
@ -1089,6 +1134,27 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $Log: design_dump.cc,v $
* Revision 1.149.2.7 2006/08/23 04:09:14 steve
* missing sig diagnostics.
*
* Revision 1.149.2.6 2006/07/10 00:21:50 steve
* Add support for full_case attribute.
*
* Revision 1.149.2.5 2006/04/16 19:26:37 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
* Fix the memsynth1 case.
*
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
* Rework l-value handling to allow for more l-value type flexibility.
*
* Revision 1.149 2004/10/04 01:10:52 steve * Revision 1.149 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -16,12 +16,12 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.7 2004/10/13 22:01:34 steve Exp $" #ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
VERSION = 0.8 suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -29,6 +29,8 @@ srcdir = @srcdir@
VPATH = $(srcdir) VPATH = $(srcdir)
suffix = @install_suffix@
bindir = $(exec_prefix)/bin bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib libdir = $(exec_prefix)/lib
includedir = $(prefix)/include includedir = $(prefix)/include
@ -41,14 +43,14 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@ CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
all: iverilog-vpi@EXEEXT@ all: iverilog-vpi@EXEEXT@
clean: clean:
rm -f *.o rm -f *.o config.h
rm -f iverilog-vpi@EXEEXT@ rm -f iverilog-vpi@EXEEXT@
distclean: clean distclean: clean
@ -60,21 +62,27 @@ iverilog-vpi@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@ $(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
main.o: main.c main.o: main.c config.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/main.c $(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/main.c
config.h: config.h.in
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
-e 's;@SUFFIX@;$(suffix);g' \
-e 's;@IVLCFLAGS@;@CXXFLAGS@;' \
-e 's;@SHARED@;@shared@;' $< > $@
# Windows specific... # Windows specific...
res.o: res.rc res.o: res.rc
windres -i res.rc -o res.o windres -i res.rc -o res.o
# #
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@ install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@ $(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
installdirs: ../mkinstalldirs installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(bindir) $(srcdir)/../mkinstalldirs $(bindir)
uninstall: uninstall:
rm -f $(bindir)/iverilog-vpi@EXEEXT@ rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@

9
driver-vpi/config.h.in Normal file
View File

@ -0,0 +1,9 @@
/* For now do not put the Icarus Verilog include or library paths here.
* They are generated from a registry entry the user must set (-ivl=).
* This may change in the future once I have thought about it more. */
#define IVERILOG_VPI_CC "@IVLCC@"
#define IVERILOG_VPI_CXX "@IVLCXX@"
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
#define IVERILOG_SUFFIX "@SUFFIX@"

View File

@ -32,28 +32,28 @@
#include <windows.h> #include <windows.h>
/* Macros used for compiling and linking */ static void setup_ivl_environment();
static void assign(char **ptr, char *str);
#define IVERILOG_VPI_CC "gcc" /* no .exe extension */ /* The compile options: compiler, flags, etc. are in here */
#define IVERILOG_VPI_CXX "gcc" /* no .exe extension */ #include "config.h"
#define IVERILOG_VPI_CFLAGS "-O" /* -I appended later */
#define IVERILOG_VPI_LD "gcc" /* no .exe extension */
#define IVERILOG_VPI_LDFLAGS "-shared -Wl,--enable-auto-image-base"
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi" /* -L prepended later */
/* pointers to global strings */ /* pointers to global strings */
static struct global_strings { static struct global_strings {
char *pCCSRC; /* list of C source files */ char *pCCSRC; /* list of C source files (*.c) */
char *pCXSRC; /* list of C++ source files */ char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
char *pOBJ; /* list of object files */ char *pOBJ; /* list of object files */
char *pLIB; /* list of library 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 *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
char *pMINGW; /* path to MinGW directory */ char *pMINGW; /* path to MinGW directory */
char *pIVL; /* path to IVL directory */ char *pIVL; /* path to IVL directory */
char *pCFLAGS; /* CFLAGS option */ char *pCFLAGS; /* CFLAGS option */
char *pLDLIBS; /* LDLIBS option */ char *pLDLIBS; /* LDLIBS option */
char *pNewPath; /* new PATH environment variable setting */ char *pNewPath; /* new PATH environment variable setting */
char *pLD; /* what to use for a linker */
} gstr; } gstr;
@ -70,12 +70,15 @@ static void myExit(int exitVal)
deInitDynString(gstr.pCXSRC); deInitDynString(gstr.pCXSRC);
deInitDynString(gstr.pOBJ); deInitDynString(gstr.pOBJ);
deInitDynString(gstr.pLIB); deInitDynString(gstr.pLIB);
deInitDynString(gstr.pINCS);
deInitDynString(gstr.pDEFS);
deInitDynString(gstr.pOUT); deInitDynString(gstr.pOUT);
deInitDynString(gstr.pMINGW); deInitDynString(gstr.pMINGW);
deInitDynString(gstr.pIVL); deInitDynString(gstr.pIVL);
deInitDynString(gstr.pCFLAGS); deInitDynString(gstr.pCFLAGS);
deInitDynString(gstr.pLDLIBS); deInitDynString(gstr.pLDLIBS);
deInitDynString(gstr.pNewPath); deInitDynString(gstr.pNewPath);
free(gstr.pLD);
exit(exitVal); exit(exitVal);
} }
@ -84,9 +87,9 @@ static void myExit(int exitVal)
static void usage() static void usage()
{ {
fprintf(stderr,"usage: iverilog-vpi [--name=name] [-llibrary] [-mingw=dir] [-ivl=dir] sourcefile...\n"); fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
fprintf(stderr," or iverilog-vpi -mingw=dir\n"); fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
fprintf(stderr," or iverilog-vpi -ivl=dir\n"); fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
myExit(1); myExit(1);
} }
@ -110,12 +113,16 @@ static void init()
initDynString(&gstr.pCXSRC); initDynString(&gstr.pCXSRC);
initDynString(&gstr.pOBJ); initDynString(&gstr.pOBJ);
initDynString(&gstr.pLIB); initDynString(&gstr.pLIB);
initDynString(&gstr.pINCS);
initDynString(&gstr.pDEFS);
initDynString(&gstr.pOUT); initDynString(&gstr.pOUT);
initDynString(&gstr.pMINGW); initDynString(&gstr.pMINGW);
initDynString(&gstr.pIVL); initDynString(&gstr.pIVL);
initDynString(&gstr.pCFLAGS); initDynString(&gstr.pCFLAGS);
initDynString(&gstr.pLDLIBS); initDynString(&gstr.pLDLIBS);
initDynString(&gstr.pNewPath); initDynString(&gstr.pNewPath);
/* By default use the C compiler to link the programs. */
assign(&gstr.pLD, IVERILOG_VPI_CC);
} }
/* return true if "str" is terminated with with "end", case insensitive */ /* return true if "str" is terminated with with "end", case insensitive */
@ -277,63 +284,124 @@ static int parse(int argc, char *argv[])
char dot_c_ext[] = ".c"; char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc"; char dot_cc_ext[] = ".cc";
char dot_cpp_ext[] = ".cpp";
char dot_o_ext[] = ".o"; char dot_o_ext[] = ".o";
char name_option[] = "--name="; char name_option[] = "--name=";
char lib_option[] = "-l"; char lib_option[] = "-l";
char inc_option[] = "-I";
char mingw_option[] = "-mingw="; char mingw_option[] = "-mingw=";
char ivl_option[] = "-ivl="; char ivl_option[] = "-ivl=";
char def_option[] = "-D";
if (argc == 1) if (argc == 1) return 0;
return 0;
for (idx=1; idx<argc; ++idx) { for (idx=1; idx<argc; ++idx) {
if (endsIn(dot_c_ext,argv[idx])) { /* check for C source files */ /* Check for C source files (*.c) */
if (endsIn(dot_c_ext, argv[idx])) {
++srcFileCnt; ++srcFileCnt;
append(&gstr.pCCSRC,argv[idx]); append(&gstr.pCCSRC, argv[idx]);
append(&gstr.pCCSRC," "); append(&gstr.pCCSRC, " ");
if (!*gstr.pOUT) if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_c_ext)); assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_c_ext));
} }
else if (endsIn(dot_cc_ext,argv[idx])) { /* check for C++ source files */ /* Check for C++ source files (*.cc) */
else if (endsIn(dot_cc_ext, argv[idx])) {
/* We need to link with the C++ compiler. */
assign(&gstr.pLD, IVERILOG_VPI_CXX);
++srcFileCnt; ++srcFileCnt;
append(&gstr.pCXSRC,argv[idx]); append(&gstr.pCXSRC, argv[idx]);
append(&gstr.pCXSRC," "); append(&gstr.pCXSRC, " ");
if (!*gstr.pOUT) if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext)); assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_cc_ext));
} }
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */ /* Check for C++ source files (*.cpp) */
else if (endsIn(dot_cpp_ext, argv[idx])) {
/* We need to link with the C++ compiler. */
assign(&gstr.pLD, IVERILOG_VPI_CXX);
++srcFileCnt;
append(&gstr.pCXSRC, argv[idx]);
append(&gstr.pCXSRC, " ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_cpp_ext));
}
/* Check for compiled object files */
else if (endsIn(dot_o_ext, argv[idx])) {
++srcFileCnt; ++srcFileCnt;
append(&gstr.pOBJ,argv[idx]);
append(&gstr.pOBJ," "); append(&gstr.pOBJ," ");
append(&gstr.pOBJ, argv[idx]);
if (!*gstr.pOUT) if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_o_ext)); assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_o_ext));
} }
else if (startsWith(name_option,argv[idx])) { /* check for --name option */ /* Check for the -mingw option */
assignn(&gstr.pOUT,argv[idx]+sizeof(name_option)-1,strlen(argv[idx])-(sizeof(name_option)-1)); 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,
strlen(argv[idx])-(sizeof(name_option)-1));
} }
else if (startsWith(lib_option,argv[idx])) { /* check for -l option */ /* Check for the -l option */
append(&gstr.pLIB,argv[idx]); else if (startsWith(lib_option, argv[idx])) {
append(&gstr.pLIB," "); append(&gstr.pLIB, " ");
append(&gstr.pLIB, argv[idx]);
} }
else if (startsWith(mingw_option,argv[idx])) /* check for -mingw option */ /* Check for the -I option */
assignn(&gstr.pMINGW,argv[idx]+sizeof(mingw_option)-1,strlen(argv[idx])-(sizeof(mingw_option)-1)); else if (startsWith(inc_option, argv[idx])) {
else if (startsWith(ivl_option,argv[idx])) /* check for -ivl option */ append(&gstr.pINCS, " ");
assignn(&gstr.pIVL,argv[idx]+sizeof(ivl_option)-1,strlen(argv[idx])-(sizeof(ivl_option)-1)); append(&gstr.pINCS, argv[idx]);
else }
return 0; /* different from iverilog-vpi.sh, we don't ignore accept arguments */ /* Check for the -D option */
else if (startsWith(def_option, argv[idx])) {
append(&gstr.pDEFS, " ");
append(&gstr.pDEFS, argv[idx]);
}
/* Check for the --cflags option */
else if (stricmp("--cflags", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\n", gstr.pCFLAGS);
myExit(0);
}
/* Check for the --ldflags option */
else if (stricmp("--ldflags", argv[idx]) == 0) {
printf("%s\n", IVERILOG_VPI_LDFLAGS);
myExit(0);
}
/* Check for the --ldlibs option */
else if (stricmp("--ldlibs", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\n", gstr.pLDLIBS);
myExit(0);
}
/* 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);
myExit(0);
}
/* This is different than iverilog-vpi.sh, we don't
* ignore unknown arguments */
else return 0;
} }
if (0 == srcFileCnt) /* In case there is a --name without source/object files */
assign(&gstr.pOUT,""); /* in case they used --name with no source files */ if (0 == srcFileCnt) assign(&gstr.pOUT,"");
if (!*gstr.pOUT) { /* normally it's an error if there are no *.c,*.cc,*.o files */ /* Normally it's an error if there are no source or object files */
if (!*gstr.pMINGW && !*gstr.pIVL) /* unless they are just setting the IVL or MinGW registry entries */ /* Unless we are setting the IVL or MinGW registry entries */
usage(); if (!*gstr.pOUT) {
} if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
else { } else
append(&gstr.pOUT,".vpi"); /* the result file should have a .vpi extension */ /* We have a valid result file so add the .vpi extension */
append(&gstr.pOUT," "); append(&gstr.pOUT, ".vpi");
}
return 1; return 1;
} }
@ -376,14 +444,14 @@ static void checkIvlDir(char *root)
initDynString(&path); initDynString(&path);
assign(&path,gstr.pIVL); assign(&path,gstr.pIVL);
appendBackSlash(&path); appendBackSlash(&path);
append(&path,"bin\\vvp.exe"); append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
irv = _stat(path,&stat_buf); irv = _stat(path,&stat_buf);
deInitDynString(path); deInitDynString(path);
if (irv) { if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root); 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.exe to\n"); 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," 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," 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," For a Cygwin shell the option would be something like\n");
@ -403,9 +471,7 @@ static void setup_mingw_environment()
if (*gstr.pMINGW) { if (*gstr.pMINGW) {
checkMingwDir(gstr.pMINGW); checkMingwDir(gstr.pMINGW);
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW); SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
} } else if (!GetRegistryKey(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,"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," 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," a Windows command shell the option would be something like\n");
@ -414,13 +480,16 @@ static void setup_mingw_environment()
myExit(5); myExit(5);
} }
assign(&gstr.pNewPath,"PATH="); /* create new path */ /* Create new path with MinGW in it */
assign(&gstr.pNewPath,"PATH=");
append(&gstr.pNewPath,gstr.pMINGW); append(&gstr.pNewPath,gstr.pMINGW);
appendBackSlash(&gstr.pNewPath); appendBackSlash(&gstr.pNewPath);
append(&gstr.pNewPath, "\\");
append(&gstr.pNewPath,"bin;"); append(&gstr.pNewPath,"bin;");
append(&gstr.pNewPath,pOldPATH); append(&gstr.pNewPath,pOldPATH);
_putenv(gstr.pNewPath); /* place new path in environment variable */ /* Place new path in environment */
_putenv(gstr.pNewPath);
} }
/* see if we can find iverilog root */ /* see if we can find iverilog root */
@ -432,67 +501,73 @@ static void setup_ivl_environment()
if (*gstr.pIVL) { if (*gstr.pIVL) {
checkIvlDir(gstr.pIVL); checkIvlDir(gstr.pIVL);
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL); SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
} } else if (!GetRegistryKey(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,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\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," 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," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
fprintf(stderr," like -ivl=c:\\\\iverilog\n"); fprintf(stderr," like -ivl=c:\\\\iverilog\n");
myExit(6); myExit(6);
} }
/* build up the CFLAGS option string */ /* Build up the CFLAGS option string */
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I");
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS);
append(&gstr.pCFLAGS," -I");
append(&gstr.pCFLAGS,gstr.pIVL); append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS); appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"include"); append(&gstr.pCFLAGS,"\\include\\\\iverilog" IVERILOG_SUFFIX);
/* build up the LDFLAGS option string */
/* Build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L"); assign(&gstr.pLDLIBS,"-L");
append(&gstr.pLDLIBS,gstr.pIVL); append(&gstr.pLDLIBS,gstr.pIVL);
appendBackSlash(&gstr.pLDLIBS); appendBackSlash(&gstr.pLDLIBS);
append(&gstr.pLDLIBS,"lib "); append(&gstr.pLDLIBS,"\\lib " IVERILOG_VPI_LDLIBS);
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
} }
/* compile source modules */ /* compile source modules */
static void compile(char *pSource, char **pObject, char *ext, int *compile_errors, char *compiler) static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
{ {
char *ptr1 = pSource; char *ptr1 = pSource;
char *ptr2 = strchr(pSource,' '); char *ptr2 = strchr(ptr1, ' ');
char *buf=0,*src=0,*obj=0; char *buf=0, *src=0, *obj=0;
while (ptr2) { while (ptr2) {
int len = ptr2 - ptr1; int len = ptr2 - ptr1;
assignn(&src,ptr1,len); char *ostart;
int olen;
assignn(&src, ptr1, len);
assignn(&obj,ptr1,len-strlen(ext)); /* strip off the extension */ /* Build the object file name */
append (&obj,".o"); ostart = strrchr(ptr1, '/');
if (ostart == NULL) ostart = ptr1;
else ostart += 1;
olen = strrchr(ptr1, '.') - ostart;
assignn(&obj, ostart, olen);
append(&obj, ".o");
assign (&buf,compiler); /* Build the compile line */
append (&buf," -c -o "); assign(&buf, compiler);
append (&buf,obj); append(&buf, " -c -o ");
append (&buf," "); append(&buf, obj);
append (&buf,gstr.pCFLAGS); append(&buf, " ");
append (&buf," "); append(&buf, gstr.pDEFS);
append (&buf,src); append(&buf, " ");
append(&buf, gstr.pCFLAGS);
append(&buf, " ");
append(&buf, gstr.pINCS);
append(&buf, " ");
append(&buf, src);
append (pObject,obj); append (pObject, " ");
append (pObject," "); append (pObject, obj);
printf("%s\n",buf); printf("Compiling %s...\n", src);
if (system(buf)) if (system(buf)) ++*compile_errors;
++*compile_errors;
ptr1 = ptr2 + 1; /* advance to next token */ /* advance to next token */
ptr2 = strchr(ptr1,' '); ptr1 = ptr2 + 1;
ptr2 = strchr(ptr1, ' ');
} }
free(buf); free(buf);
@ -507,43 +582,44 @@ static void compile_and_link()
char *buf=0; char *buf=0;
int iRet, compile_errors = 0; int iRet, compile_errors = 0;
/* print out the mingw and ivl directories to help the user debug problems */ /* To make the output match iverilog-vpi.sh do not print out the
* root directories */
printf("info: %s will be used as the MinGW root directory.\n",gstr.pMINGW); // printf("MinGW root directory: %s.\n", gstr.pMINGW);
checkMingwDir(gstr.pMINGW); checkMingwDir(gstr.pMINGW);
printf("info: %s will be used as the Icarus Verilog root directory.\n",gstr.pIVL); // printf("Icarus Verilog root directory: %s.\n", gstr.pIVL);
checkIvlDir(gstr.pIVL); checkIvlDir(gstr.pIVL);
/* compile */ /* compile the C source files (*.c) */
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
compile(gstr.pCCSRC,&gstr.pOBJ,".c" ,&compile_errors,IVERILOG_VPI_CC ); /* compile the C source files */ /* compile the C++ source files (*.cc, *.cpp) */
compile(gstr.pCXSRC,&gstr.pOBJ,".cc",&compile_errors,IVERILOG_VPI_CXX); /* compile the C++ source files */ compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
if (compile_errors) { if (compile_errors) {
fprintf(stderr,"iverilog-vpi: Some %d files failed to compile.\n",compile_errors); fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
compile_errors);
myExit(2); myExit(2);
} }
/* link */ /* link */
assign(&buf, gstr.pLD);
append(&buf, " -o ");
append(&buf, gstr.pOUT);
append(&buf, " ");
append(&buf, IVERILOG_VPI_LDFLAGS);
append(&buf, " ");
append(&buf, gstr.pOBJ);
append(&buf, " ");
append(&buf, gstr.pLIB);
append(&buf, " ");
append(&buf, gstr.pLDLIBS);
assign(&buf,IVERILOG_VPI_LD); printf("Making %s from %s...\n", gstr.pOUT,gstr.pOBJ);
append(&buf," -o ");
append(&buf,gstr.pOUT); /* has a trailing space */
append(&buf,IVERILOG_VPI_LDFLAGS);
append(&buf," ");
append(&buf,gstr.pOBJ) /* has a trailing space */;
append(&buf,gstr.pLIB); /* has a trailing space */
append(&buf,gstr.pLDLIBS);
printf("%s\n",buf);
iRet = system(buf); iRet = system(buf);
free(buf); free(buf);
if (iRet) myExit(3);
if (iRet)
myExit(3);
} }
/* program execution starts here */ /* program execution starts here */
@ -552,14 +628,14 @@ int main(int argc, char *argv[])
{ {
init(); init();
if (!parse(argc,argv)) if (!parse(argc,argv)) usage();
usage();
setup_mingw_environment(); setup_mingw_environment();
setup_ivl_environment(); setup_ivl_environment();
if (*gstr.pOUT) /* are there any *.c,*.cc,*.o files specified */ /* are there any source or object files specified */
compile_and_link(); if (*gstr.pOUT) compile_and_link();
myExit(0); myExit(0);
return 0; // eliminate warnings.
} }

View File

@ -16,12 +16,12 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.24 2004/10/13 22:01:34 steve Exp $" #ident "$Id: Makefile.in,v 1.24.2.3 2007/05/30 17:48:26 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
VERSION = 0.8 suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -40,8 +40,10 @@ CC = @CC@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
MAN = @MAN@
PS2PDF = @PS2PDF@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@ CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
@ -54,6 +56,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile rm -f Makefile
rm -rf autom4te.cache
O = main.o substit.o cflexor.o cfparse.o O = main.o substit.o cflexor.o cfparse.o
@ -68,41 +71,49 @@ cfparse.h cfparse.c: cfparse.y
main.o: main.c globals.h main.o: main.c globals.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(DEBUGFLAGS) $(srcdir)/main.c
build_string.o: build_string.c globals.h build_string.o: build_string.c globals.h
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
cfparse.o: cfparse.c globals.h cfparse_misc.h cfparse.o: cfparse.c globals.h cfparse_misc.h
iverilog.ps: $(srcdir)/iverilog.man iverilog.ps: $(srcdir)/iverilog.man
man -t $(srcdir)/iverilog.man > iverilog.ps $(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
iverilog.pdf: iverilog.ps iverilog.pdf: iverilog.ps
ps2pdf iverilog.ps iverilog.pdf $(PS2PDF) iverilog.ps iverilog.pdf
ifeq (@WIN32@,yes) ifeq (@WIN32@,yes)
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1 ifeq ($(MAN),none)
INSTALL_DOCDIR = $(mandir)/man1 INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
all: iverilog.pdf
else else
INSTALL_DOC = $(mandir)/man1/iverilog.1 ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
else
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOCDIR = $(mandir)/man1 INSTALL_DOCDIR = $(mandir)/man1
endif endif
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC) install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@ $(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@ $(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog$(suffix)@EXEEXT@
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man $(mandir)/man1/iverilog$(suffix).1: $(srcdir)/iverilog.man
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1 $(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog$(suffix).1
$(prefix)/iverilog.pdf: iverilog.pdf $(prefix)/iverilog$(suffix).pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf $(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog$(suffix).pdf
installdirs: ../mkinstalldirs installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR) $(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
uninstall: uninstall:
rm -f $(bindir)/iverilog@EXEEXT@ rm -f $(bindir)/iverilog$(suffix)@EXEEXT@
rm -f $(mandir)/man1/iverilog.1 rm -f $(mandir)/man1/iverilog$(suffix).1

View File

@ -1,4 +1,4 @@
.TH iverilog 1 "$Date: 2004/10/04 01:10:56 $" Version "$Date: 2004/10/04 01:10:56 $" .TH iverilog 1 "$Date: 2006/06/12 00:16:53 $" Version "$Date: 2006/06/12 00:16:53 $"
.SH NAME .SH NAME
iverilog - Icarus Verilog compiler iverilog - Icarus Verilog compiler
@ -212,6 +212,12 @@ inherit timescale from another file. Both probably mean that
timescales are inconsistent, and simulation timing can be confusing timescales are inconsistent, and simulation timing can be confusing
and dependent on compilation order. and dependent on compilation order.
.TP 8
.B unused
This enables warnings for unused variables. This may detect variables
that are not assigned, or variables and nets that are not used, or
similar possible misuses of variables and nets.
.SH "SYSTEM FUNCTION TABLE FILES" .SH "SYSTEM FUNCTION TABLE FILES"
If the source file name as a \fB.sft\fP suffix, then it is taken to be If the source file name as a \fB.sft\fP suffix, then it is taken to be
a system function table file. A System function table file is used to a system function table file. A System function table file is used to

View File

@ -17,10 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.65 2004/06/17 14:47:22 steve Exp $" #ident "$Id: main.c,v 1.65.2.6 2007/05/30 17:48:26 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include "version.h"
const char NOTICE[] = const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n" " This program is free software; you can redistribute it and/or modify\n"
@ -88,6 +89,10 @@ extern const char*optarg;
# define IVL_ROOT "." # define IVL_ROOT "."
#endif #endif
#ifndef IVL_ROOT_VARIABLE
# define IVL_ROOT_VARIABLE "IVERILOG_ROOT"
#endif
# include "globals.h" # include "globals.h"
#include "cfparse_misc.h" /* cfparse() */ #include "cfparse_misc.h" /* cfparse() */
@ -262,15 +267,72 @@ static int t_default(char*cmd, unsigned ncmd)
} }
#endif #endif
#ifdef DEBUG
char *original_cmd = malloc( strlen( cmd ) + (size_t)1 );
strcpy( original_cmd, cmd );
cmd = realloc( cmd, strlen( original_cmd ) + (size_t)19 ); /* more than enough memory for the ivlpp command and ">/tmp/ivlpp_stdout" */
if( cmd == NULL ){
exit( EXIT_FAILURE );
}
char *debug_ivl = malloc( strlen( original_cmd ) + (size_t)5 ); /* more than enough memory for "gdb " and ivl program_name */
strcpy( debug_ivl, "gdb " );
static char whitespace[] = " \t\f\r\v\n";
char *token;
int found_pipe = 0;
unsigned long token_counter = 0UL;
strcpy( cmd, "" );
for( token = strtok( original_cmd, whitespace ); token != NULL; token = strtok( NULL, whitespace ) ){
if( strcmp( token, "|" ) == 0 ){
found_pipe = 1;
}
if( found_pipe ){
token_counter++;
}
if( token_counter == 0UL ){
strcat( cmd, token );
strcat( cmd, " " ); /* harmless space after last token, and it was already there anyway */
}
if( token_counter == 2UL ){
strcat( debug_ivl, token );
}
if( token_counter > 2UL ){
printf( "%s\n", token );
}
}
free( original_cmd );
strcat( cmd, ">/tmp/ivlpp_stdout" );
#endif
if (verbose_flag) if (verbose_flag)
printf("translate: %s\n", cmd); printf("translate: %s\n", cmd);
rc = system(cmd); rc = system(cmd);
#ifdef DEBUG
if( verbose_flag ){
printf( "%s\n", debug_ivl );
}
system( debug_ivl ); /* For simplicity, ignore any return value, which is implementation dependent anyway. */
free( debug_ivl );
#endif
remove(source_path); remove(source_path);
if ( ! getenv("IVERILOG_ICONFIG")) if ( ! getenv("IVERILOG_ICONFIG"))
remove(iconfig_path); remove(iconfig_path);
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
return rc;
#else
if (rc != 0) { if (rc != 0) {
if (rc == 127) { if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd); fprintf(stderr, "Failed to execute: %s\n", cmd);
@ -285,13 +347,14 @@ static int t_default(char*cmd, unsigned ncmd)
} }
return 0; return 0;
#endif
} }
static void process_warning_switch(const char*name) static void process_warning_switch(const char*name)
{ {
if (strcmp(name,"all") == 0) { if (strcmp(name,"all") == 0) {
strcat(warning_flags, "ipt"); strcat(warning_flags, "iptu");
} else if (strcmp(name,"implicit") == 0) { } else if (strcmp(name,"implicit") == 0) {
if (! strchr(warning_flags+2, 'i')) if (! strchr(warning_flags+2, 'i'))
@ -302,6 +365,9 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"timescale") == 0) { } else if (strcmp(name,"timescale") == 0) {
if (! strchr(warning_flags+2, 't')) if (! strchr(warning_flags+2, 't'))
strcat(warning_flags, "t"); strcat(warning_flags, "t");
} else if (strcmp(name,"unused") == 0) {
if (! strchr(warning_flags+2, 'u'))
strcat(warning_flags, "u");
} else if (strcmp(name,"no-implicit") == 0) { } else if (strcmp(name,"no-implicit") == 0) {
char*cp = strchr(warning_flags+2, 'i'); char*cp = strchr(warning_flags+2, 'i');
if (cp) while (*cp) { if (cp) while (*cp) {
@ -320,6 +386,12 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1]; cp[0] = cp[1];
cp += 1; cp += 1;
} }
} else if (strcmp(name,"no-unused") == 0) {
char*cp = strchr(warning_flags+2, 'u');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
} }
} }
@ -409,14 +481,13 @@ int process_generation(const char*name)
return 0; return 0;
} }
int main(int argc, char **argv) /*
* This function fills in th ivl_root directory with the appropriate
* path, based on operating system, build time configuration, and
* environment.
*/
static char* get_root_dir()
{ {
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
#ifdef __MINGW32__ #ifdef __MINGW32__
{ char * s; { char * s;
char basepath[1024]; char basepath[1024];
@ -443,16 +514,56 @@ int main(int argc, char **argv)
s = strrchr(ivl_root, sep); s = strrchr(ivl_root, sep);
if (s) *s = 0; if (s) *s = 0;
strcat(ivl_root, "\\lib\\ivl"); strcat(ivl_root, "\\lib\\ivl");
base = ivl_root;
} }
#else #else
/* In a UNIX environment, the IVL_ROOT from the Makefile is
dependable. It points to the $prefix/lib/ivl directory, { char*var = 0;
where the sub-parts are installed. */
strcpy(ivl_root, IVL_ROOT); /* In other systems, use the configured root. */
base = ivl_root; strcpy(ivl_root, IVL_ROOT);
/* In any case, the IVL_ROOT variable can be used to override
the install location at run time. If it is set, use that
value instead. */
if ( (var = getenv(IVL_ROOT_VARIABLE)) ) {
strncpy(ivl_root, var, MAXSIZE);
strcat(ivl_root, "/lib/ivl");
}
}
#endif
return ivl_root;
}
int main(int argc, char **argv)
{
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
base = get_root_dir();
#ifdef __MINGW32__
/* Under Windows, there is no point checking the root
directory. */
#else
/* On other systems, check that the root directory seems
reasonable. */
{ size_t tmp_len = strlen(base) + 16;
char* tmp = malloc(tmp_len);
snprintf(tmp, tmp_len, "%s%civl", base, sep);
if (0 != access(tmp, F_OK)) {
fprintf(stderr, "%s: INSTALLATION ERROR: Directory %s"
" does not contain ivl files.\n", argv[0], base);
fprintf(stderr, "%s: : Check installation"
" or set " IVL_ROOT_VARIABLE " correctly.\n", argv[0]);
return 1;
}
free(tmp);
}
#endif #endif
/* Create a temporary file for communicating input parameters /* Create a temporary file for communicating input parameters
@ -594,7 +705,7 @@ int main(int argc, char **argv)
pbase = base; pbase = base;
if (version_flag || verbose_flag) { if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " ($Name: $)\n"); printf("Icarus Verilog version " VERSION "\n\n");
printf("Copyright 1998-2003 Stephen Williams\n"); printf("Copyright 1998-2003 Stephen Williams\n");
puts(NOTICE); puts(NOTICE);
@ -735,6 +846,24 @@ int main(int argc, char **argv)
/* /*
* $Log: main.c,v $ * $Log: main.c,v $
* Revision 1.65.2.6 2007/05/30 17:48:26 steve
* DEBUG aids. (Alan Feldstein)
*
* Revision 1.65.2.5 2006/07/07 21:31:50 steve
* Root dir variable does not include lib/ivl components.
*
* Revision 1.65.2.4 2006/06/27 01:30:20 steve
* Fix unused var warning for mingw32 build.
*
* Revision 1.65.2.3 2006/06/14 03:01:49 steve
* Remove redundant call to get_root_dir.
*
* Revision 1.65.2.2 2006/06/12 00:16:53 steve
* Add support for -Wunused warnings.
*
* Revision 1.65.2.1 2006/03/26 21:47:26 steve
* More installation directory flexibility.
*
* Revision 1.65 2004/06/17 14:47:22 steve * Revision 1.65 2004/06/17 14:47:22 steve
* Add a .sft file for the system functions. * Add a .sft file for the system functions.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.18 2004/06/17 16:06:18 steve Exp $" #ident "$Id: dup_expr.cc,v 1.18.2.2 2006/11/02 02:13:15 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -29,6 +29,7 @@ NetEBComp* NetEBComp::dup_expr() const
{ {
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(), NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
right_->dup_expr()); right_->dup_expr());
result->set_line(*this);
return result; return result;
} }
@ -90,6 +91,7 @@ NetESignal* NetESignal::dup_expr() const
NetESignal*tmp = new NetESignal(net_, msi_, lsi_); NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
assert(tmp); assert(tmp);
tmp->expr_width(expr_width()); tmp->expr_width(expr_width());
tmp->set_line(*this);
return tmp; return tmp;
} }
@ -118,6 +120,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms); tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
assert(tmp); assert(tmp);
tmp->set_line(*this);
return tmp; return tmp;
} }
@ -143,6 +146,12 @@ NetEVariable* NetEVariable::dup_expr() const
/* /*
* $Log: dup_expr.cc,v $ * $Log: dup_expr.cc,v $
* Revision 1.18.2.2 2006/11/02 02:13:15 steve
* Error message for condit expression not synthesized.
*
* Revision 1.18.2.1 2006/06/12 00:16:50 steve
* Add support for -Wunused warnings.
*
* Revision 1.18 2004/06/17 16:06:18 steve * Revision 1.18 2004/06/17 16:06:18 steve
* Help system function signedness survive elaboration. * Help system function signedness survive elaboration.
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2006 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.91 2004/10/04 01:10:52 steve Exp $" #ident "$Id: elab_expr.cc,v 1.91.2.2 2006/11/02 02:13:15 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -43,7 +43,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, bool) const
* and right sides, and creating one of a variety of different NetExpr * and right sides, and creating one of a variety of different NetExpr
* types. * types.
*/ */
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
{ {
assert(left_); assert(left_);
assert(right_); assert(right_);
@ -73,7 +73,7 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
} }
} }
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp); NetExpr*tmp = elaborate_expr_base_(des, lp, rp);
return tmp; return tmp;
} }
@ -82,11 +82,11 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
* operands are elaborated as necessary, and all I need to do is make * operands are elaborated as necessary, and all I need to do is make
* the correct NetEBinary object and connect the parameters. * the correct NetEBinary object and connect the parameters.
*/ */
NetEBinary* PEBinary::elaborate_expr_base_(Design*des, NetExpr* PEBinary::elaborate_expr_base_(Design*des,
NetExpr*lp, NetExpr*rp) const NetExpr*lp, NetExpr*rp) const
{ {
bool flag; bool flag;
NetEBinary*tmp; NetExpr*tmp;
switch (op_) { switch (op_) {
default: default:
@ -112,6 +112,51 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
break; break;
case 'l': // << case 'l': // <<
if (NetEConst*lpc = dynamic_cast<NetEConst*> (lp)) {
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
// Handle the super-special case that both
// operands are constants. Precalculate the
// entire value here.
verinum lpval = lpc->value();
unsigned shift = rpc->value().as_ulong();
verinum result = lpc->value() << shift;
// If the l-value has explicit size, use that.
if (lpval.has_len()) {
result = verinum(result, lpval.len());
}
tmp = new NetEConst(result);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Precalculate " << *this
<< " to constant " << *tmp << endl;
} else {
// Handle the special case that the left
// operand is constant. If it is unsized, we
// may have to expand it to an integer width.
verinum lpval = lpc->value();
if (lpval.len() < 32 && !lpval.has_len()) {
lpval = verinum(lpval, 32);
lpc = new NetEConst(lpval);
lpc->set_line(*lp);
}
tmp = new NetEBShift(op_, lpc, rp);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Adjust " << *this
<< " to this " << *tmp
<< " to allow for integer widths." << endl;
}
} else {
// Left side is not constant, so handle it the
// default way.
tmp = new NetEBShift(op_, lp, rp);
}
tmp->set_line(*this);
break;
case 'r': // >> case 'r': // >>
case 'R': // >>> case 'R': // >>>
tmp = new NetEBShift(op_, lp, rp); tmp = new NetEBShift(op_, lp, rp);
@ -387,13 +432,16 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
if (NetNet*res = dscope->find_signal(dscope->basename())) { if (NetNet*res = dscope->find_signal(dscope->basename())) {
NetESignal*eres = new NetESignal(res); NetESignal*eres = new NetESignal(res);
NetEUFunc*func = new NetEUFunc(dscope, eres, parms); NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
eres->set_line(*this);
func->set_line(*this);
return func; return func;
} }
if (NetVariable*res = dscope->find_variable(dscope->basename())) { if (NetVariable*res = dscope->find_variable(dscope->basename())) {
NetEVariable*eres = new NetEVariable(res); NetEVariable*eres = new NetEVariable(res);
eres->set_line(*res);
NetEUFunc*func = new NetEUFunc(dscope, eres, parms); NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
eres->set_line(*res);
func->set_line(*this);
return func; return func;
} }
@ -425,6 +473,29 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
des->errors += 1; des->errors += 1;
} }
if (!rep->value().is_defined()) {
cerr << get_line() << ": error: Concatenation repeat "
<< "may not be undefined (" << rep->value()
<< ")." << endl;
des->errors += 1;
return 0;
}
if (rep->value().is_negative()) {
cerr << get_line() << ": error: Concatenation repeat "
<< "may not be negative (" << rep->value().as_long()
<< ")." << endl;
des->errors += 1;
return 0;
}
if (rep->value().is_zero()) {
cerr << get_line() << ": error: Concatenation repeat "
<< "may not be zero." << endl;
des->errors += 1;
return 0;
}
repeat = rep; repeat = rep;
} }
@ -497,6 +568,17 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetScope*found_in = symbol_search(des, scope, path_, NetScope*found_in = symbol_search(des, scope, path_,
net, mem, var, par, eve); net, mem, var, par, eve);
if (net && mem) {
assert(net == mem->reg_from_explode());
net = 0;
}
if (net && net->mref()) {
mem = net->mref();
assert(net == mem->reg_from_explode());
net = 0;
}
// If the identifier name is a parameter name, then return // If the identifier name is a parameter name, then return
// a reference to the parameter expression. // a reference to the parameter expression.
if (par != 0) { if (par != 0) {
@ -742,6 +824,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
} }
NetESignal*node = new NetESignal(net); NetESignal*node = new NetESignal(net);
node->set_line(*this);
assert(idx_ == 0); assert(idx_ == 0);
// Non-constant bit select? punt and make a subsignal // Non-constant bit select? punt and make a subsignal
@ -1005,6 +1088,12 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/* /*
* $Log: elab_expr.cc,v $ * $Log: elab_expr.cc,v $
* Revision 1.91.2.2 2006/11/02 02:13:15 steve
* Error message for condit expression not synthesized.
*
* Revision 1.91.2.1 2006/06/12 00:16:50 steve
* Add support for -Wunused warnings.
*
* Revision 1.91 2004/10/04 01:10:52 steve * Revision 1.91 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.138 2004/10/04 03:09:38 steve Exp $" #ident "$Id: elab_net.cc,v 1.138.2.3 2005/09/11 02:56:37 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -28,6 +28,7 @@
# include "compiler.h" # include "compiler.h"
# include <iostream> # include <iostream>
# include <cstring>
/* /*
* This is a state flag that determines whether an elaborate_net must * This is a state flag that determines whether an elaborate_net must
@ -498,7 +499,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
use of the situation, or 0 if it cannot. */ use of the situation, or 0 if it cannot. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) { if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
lsig = lexp->synthesize(des); lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
if (lsig == 0) { if (lsig == 0) {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
"Cannot elaborate net for " << *lexp << endl; "Cannot elaborate net for " << *lexp << endl;
@ -518,7 +519,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) { if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
rsig = rexp->synthesize(des); rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
assert(rsig); assert(rsig);
delete rexp; delete rexp;
@ -532,13 +533,13 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
} }
if (lsig == 0) { if (lsig == 0) {
lsig = lexp->synthesize(des); lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
assert(lsig); assert(lsig);
delete lexp; delete lexp;
} }
if (rsig == 0) { if (rsig == 0) {
rsig = rexp->synthesize(des); rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
assert(rsig); assert(rsig);
delete rexp; delete rexp;
} }
@ -1216,6 +1217,13 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
return sub; return sub;
} }
if (path_.peek_name(0)[0] == '$') {
cerr << get_line() << ": sorry: System functions " << path_ <<
" not supported in continuous assignments." << endl;
des->errors += 1;
return 0;
}
/* Look up the function definition. */ /* Look up the function definition. */
NetFuncDef*def = des->find_function(scope, path_); NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) { if (def == 0) {
@ -1312,21 +1320,47 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
unsigned repeat = 1; unsigned repeat = 1;
if (repeat_) { if (repeat_) {
verinum*rep = repeat_->eval_const(des, scope); auto_ptr<NetExpr> etmp (elab_and_eval(des, scope, repeat_));
if (rep == 0) { assert(etmp.get());
NetEConst*erep = dynamic_cast<NetEConst*>(etmp.get());
if (erep == 0) {
cerr << get_line() << ": internal error: Unable to " cerr << get_line() << ": internal error: Unable to "
<< "evaluate constant repeat expression." << endl; << "evaluate constant repeat expression." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
repeat = rep->as_ulong(); repeat = erep->value().as_ulong();
if (repeat == 0) { if (repeat == 0) {
cerr << get_line() << ": error: Invalid repeat value." cerr << get_line() << ": error: Concatenation repeat "
"may not be 0."
<< endl; << endl;
des->errors += 1; des->errors += 1;
delete rep; return 0;
}
if (!erep->value().is_defined()) {
cerr << get_line() << ": error: Concatenation repeat "
<< "may not be undefined (" << erep->value()
<< ")." << endl;
des->errors += 1;
return 0;
}
if (erep->value().is_negative()) {
cerr << get_line() << ": error: Concatenation repeat "
<< "may not be negative (" << erep->value().as_long()
<< ")." << endl;
des->errors += 1;
return 0;
}
if (erep->value().is_zero()) {
cerr << get_line() << ": error: Concatenation repeat "
<< "may not be zero." << endl;
des->errors += 1;
return 0; return 0;
} }
} }
@ -1435,6 +1469,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
NetMux*mux = new NetMux(scope, scope->local_symbol(), 1, NetMux*mux = new NetMux(scope, scope->local_symbol(), 1,
sig_width, sel->pin_count()); sig_width, sel->pin_count());
mux->set_line(*this);
/* Connect the signal bits to the mux. Account for the /* Connect the signal bits to the mux. Account for the
direction of the numbering (lsb to msb vs. msb to lsb) by direction of the numbering (lsb to msb vs. msb to lsb) by
@ -2268,6 +2303,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
(true) connected to tru_sig. */ (true) connected to tru_sig. */
NetMux*mux = new NetMux(scope, scope->local_symbol(), dwidth, 2, 1); NetMux*mux = new NetMux(scope, scope->local_symbol(), dwidth, 2, 1);
mux->set_line(*this);
connect(mux->pin_Sel(0), expr_sig->pin(0)); connect(mux->pin_Sel(0), expr_sig->pin(0));
/* Connect the data inputs. */ /* Connect the data inputs. */
@ -2413,6 +2449,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
reduction=true; gtype = NetLogic::XNOR; break; reduction=true; gtype = NetLogic::XNOR; break;
case '-': // Unary 2's complement. case '-': // Unary 2's complement.
if (owidth == 0)
owidth = sub_sig->pin_count();
sig = new NetNet(scope, scope->local_symbol(), sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, owidth); NetNet::WIRE, owidth);
sig->local_flag(true); sig->local_flag(true);
@ -2459,15 +2498,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
default: default:
NetAddSub*sub = new NetAddSub(scope, scope->local_symbol(), NetAddSub*sub = new NetAddSub(scope, scope->local_symbol(),
sig->pin_count()); owidth);
sub->attribute(perm_string::literal("LPM_Direction"), verinum("SUB")); sub->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
des->add_node(sub); des->add_node(sub);
for (unsigned idx = 0 ; idx < sig->pin_count(); idx += 1) for (unsigned idx = 0 ; idx < owidth ; idx += 1)
connect(sig->pin(idx), sub->pin_Result(idx)); connect(sig->pin(idx), sub->pin_Result(idx));
for (unsigned idx = 0; idx < sub_sig->pin_count(); idx += 1) for (unsigned idx = 0; idx < owidth; idx += 1)
connect(sub_sig->pin(idx), sub->pin_DataB(idx)); connect(sub_sig->pin(idx), sub->pin_DataB(idx));
verinum tmp_num (verinum::V0, sub->width(), true); verinum tmp_num (verinum::V0, sub->width(), true);
@ -2477,8 +2516,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
des->add_node(tmp_con); des->add_node(tmp_con);
NetNet*tmp_sig = new NetNet(scope, scope->local_symbol(), NetNet*tmp_sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::WIRE, owidth);
sub_sig->pin_count());
tmp_sig->local_flag(true); tmp_sig->local_flag(true);
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) { for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
@ -2513,6 +2551,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $Log: elab_net.cc,v $
* Revision 1.138.2.3 2005/09/11 02:56:37 steve
* Attach line numbers to NetMux devices.
*
* Revision 1.138.2.2 2005/02/19 16:39:30 steve
* Spellig fixes.
*
* Revision 1.138.2.1 2005/01/29 00:18:23 steve
* Fix evaluate of constants in netlist concatenation repeats.
*
* Revision 1.138 2004/10/04 03:09:38 steve * Revision 1.138 2004/10/04 03:09:38 steve
* Fix excessive error message. * Fix excessive error message.
* *

View File

@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0; return 0;
} }
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp); NetExpr*tmp = elaborate_expr_base_(des, lp, rp);
return tmp; return tmp;
} }

View File

@ -24,6 +24,7 @@
# include "compiler.h" # include "compiler.h"
# include <iostream> # include <iostream>
# include <stdio.h> # include <stdio.h>
# include <cstring>
/* /*
* Elaboration happens in two passes, generally. The first scans the * Elaboration happens in two passes, generally. The first scans the
@ -432,6 +433,9 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
; cur != replace.end() ; cur ++ ) { ; cur != replace.end() ; cur ++ ) {
PExpr*tmp = (*cur).second; PExpr*tmp = (*cur).second;
// No expression means that the parameter is not
// replaced at all.
if (tmp == 0) continue;
NetExpr*val = tmp->elaborate_pexpr(des, sc); NetExpr*val = tmp->elaborate_pexpr(des, sc);
bool flag = my_scope->replace_parameter((*cur).first, val); bool flag = my_scope->replace_parameter((*cur).first, val);
if (! flag) { if (! flag) {
@ -444,7 +448,11 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
/* Stash the instance array of scopes into the parent /* Stash the instance array of scopes into the parent
scope. Later elaboration passes will use this vector to scope. Later elaboration passes will use this vector to
further elaborate the array. */ further elaborate the array.
Note that the array is ordered from LSB to MSB. We will use
that fact in the main elaborate to connect things in the
correct order. */
sc->instance_arrays[get_name()] = instances; sc->instance_arrays[get_name()] = instances;
} }

View File

@ -23,6 +23,7 @@
# include "config.h" # include "config.h"
# include <iostream> # include <iostream>
# include <cstdlib>
# include "Module.h" # include "Module.h"
# include "PExpr.h" # include "PExpr.h"

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.308 2004/10/04 01:10:52 steve Exp $" #ident "$Id: elaborate.cc,v 1.308.2.6 2006/11/27 01:47:14 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -67,6 +67,21 @@ void PGate::elaborate(Design*des, NetScope*scope) const
typeid(*this).name() << endl; typeid(*this).name() << endl;
} }
void process_attributes(Design*des, NetScope*scope,
Attrib*dest, const map<perm_string,PExpr*>&table)
{
struct attrib_list_t*attrib_list = 0;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(table, attrib_list_n,
des, scope);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
dest->attribute(attrib_list[adx].key,
attrib_list[adx].val);
delete[]attrib_list;
}
/* /*
* Elaborate the continuous assign. (This is *not* the procedural * Elaborate the continuous assign. (This is *not* the procedural
* assign.) Elaborate the lvalue and rvalue, and do the assignment. * assign.) Elaborate the lvalue and rvalue, and do the assignment.
@ -354,76 +369,212 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
switch (type()) { switch (type()) {
case AND: case AND:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::AND); cerr << get_line() << ": error: the AND "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::AND);
}
break; break;
case BUF: case BUF:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::BUF); cerr << get_line() << ": error: the BUF "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else if (pin_count() > 2) {
cerr << get_line() << ": sorry: the BUF "
"primitive may only have one output in V0.8." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUF);
}
break; break;
case BUFIF0: case BUFIF0:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::BUFIF0); cerr << get_line() << ": error: the BUFIF0 "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUFIF0);
}
break; break;
case BUFIF1: case BUFIF1:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::BUFIF1); cerr << get_line() << ": error: the BUFIF1 "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUFIF1);
}
break; break;
case NAND: case NAND:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::NAND); cerr << get_line() << ": error: the NAND "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NAND);
}
break; break;
case NMOS: case NMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::NMOS); cerr << get_line() << ": error: the NMOS "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NMOS);
}
break; break;
case NOR: case NOR:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::NOR); cerr << get_line() << ": error: the NOR "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOR);
}
break; break;
case NOT: case NOT:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::NOT); cerr << get_line() << ": error: the NOT "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else if (pin_count() > 2) {
cerr << get_line() << ": sorry: the NOT "
"primitive may only have one output in V0.8." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOT);
}
break; break;
case NOTIF0: case NOTIF0:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::NOTIF0); cerr << get_line() << ": error: the NOTIF0 "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOTIF0);
}
break; break;
case NOTIF1: case NOTIF1:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::NOTIF1); cerr << get_line() << ": error: the NOTIF1 "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOTIF1);
}
break; break;
case OR: case OR:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::OR); cerr << get_line() << ": error: the OR "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::OR);
}
break; break;
case RNMOS: case RNMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::RNMOS); cerr << get_line() << ": error: the RNMOS "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::RNMOS);
}
break; break;
case RPMOS: case RPMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::RPMOS); cerr << get_line() << ": error: the RPMOS "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::RPMOS);
}
break; break;
case PMOS: case PMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 3) {
NetLogic::PMOS); cerr << get_line() << ": error: the PMOS "
"primitive must have three arguments." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PMOS);
}
break; break;
case PULLDOWN: case PULLDOWN:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 1) {
NetLogic::PULLDOWN); cerr << get_line() << ": sorry: the PULLDOWN "
"primitive may only have one output in V0.8." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PULLDOWN);
}
break; break;
case PULLUP: case PULLUP:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() != 1) {
NetLogic::PULLUP); cerr << get_line() << ": sorry: the PULLUP "
"primitive may only have one output in V0.8." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PULLUP);
}
break; break;
case XNOR: case XNOR:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::XNOR); cerr << get_line() << ": error: the XNOR "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XNOR);
}
break; break;
case XOR: case XOR:
cur[idx] = new NetLogic(scope, inm, pin_count(), if (pin_count() < 2) {
NetLogic::XOR); cerr << get_line() << ": error: the XOR "
"primitive must have an input." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XOR);
}
break; break;
default: default:
cerr << get_line() << ": internal error: unhandled " cerr << get_line() << ": internal error: unhandled "
@ -454,6 +605,12 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
const PExpr*ex = pin(idx); const PExpr*ex = pin(idx);
if (ex == 0) {
cerr << get_line() << ": error: Logic gate port "
"expressions are not optional." << endl;
des->errors += 1;
return;
}
NetNet*sig = (idx == 0) NetNet*sig = (idx == 0)
? ex->elaborate_lnet(des, scope, true) ? ex->elaborate_lnet(des, scope, true)
: ex->elaborate_net(des, scope, 0, 0, 0, 0); : ex->elaborate_net(des, scope, 0, 0, 0, 0);
@ -642,7 +799,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
unsigned prts_pin_count = 0; unsigned prts_pin_count = 0;
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) { for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
NetScope*inst_scope = instance[inst]; // Scan the instances from MSB to LSB. The port
// will be assembled in that order as well.
NetScope*inst_scope = instance[instance.count()-inst-1];
// Scan the module sub-ports for this instance... // Scan the module sub-ports for this instance...
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) { for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
@ -1179,6 +1338,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
tmp->set_line(*this); tmp->set_line(*this);
NetESignal*sig = new NetESignal(tmp); NetESignal*sig = new NetESignal(tmp);
sig->set_line(*this);
/* Generate an assignment of the l-value to the temporary... */ /* Generate an assignment of the l-value to the temporary... */
string n = scope->local_hsymbol(); string n = scope->local_hsymbol();
@ -1215,6 +1375,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
/* And build up the complex statement. */ /* And build up the complex statement. */
NetBlock*bl = new NetBlock(NetBlock::SEQU, 0); NetBlock*bl = new NetBlock(NetBlock::SEQU, 0);
bl->set_line(*this);
bl->append(a1); bl->append(a1);
bl->append(st); bl->append(st);
@ -1318,6 +1479,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
} }
NetBlock*cur = new NetBlock(type, nscope); NetBlock*cur = new NetBlock(type, nscope);
cur->set_line(*this);
bool fail_flag = false; bool fail_flag = false;
if (nscope == 0) if (nscope == 0)
@ -1388,6 +1550,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
NetCase*res = new NetCase(type_, expr, icount); NetCase*res = new NetCase(type_, expr, icount);
res->set_line(*this); res->set_line(*this);
process_attributes(des, scope, res, attributes);
/* Iterate over all the case items (guard/statement pairs) /* Iterate over all the case items (guard/statement pairs)
elaborating them. If the guard has no expression, then this elaborating them. If the guard has no expression, then this
@ -1403,8 +1566,12 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
/* If there are no expressions, then this is the /* If there are no expressions, then this is the
default case. */ default case. */
NetProc*st = 0; NetProc*st = 0;
if (cur->stat) if (cur->stat) {
st = cur->stat->elaborate(des, scope); st = cur->stat->elaborate(des, scope);
} else {
st = new NetBlock(NetBlock::SEQU, scope);
st->set_line(*this);
}
res->set_case(inum, 0, st); res->set_case(inum, 0, st);
inum += 1; inum += 1;
@ -1413,16 +1580,19 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
/* If there are one or more expressions, then /* If there are one or more expressions, then
iterate over the guard expressions, elaborating iterate over the guard expressions, elaborating
a separate case for each. (Yes, the statement a separate case for each. If the statement is
will be elaborated again for each.) */ nul, then put an appropriate stub in place. */
NetExpr*gu = 0; NetExpr*gu = 0;
NetProc*st = 0; NetProc*st = 0;
assert(cur->expr[e]); assert(cur->expr[e]);
gu = elab_and_eval(des, scope, cur->expr[e]); gu = elab_and_eval(des, scope, cur->expr[e]);
if (cur->stat) if (cur->stat) {
st = cur->stat->elaborate(des, scope); st = cur->stat->elaborate(des, scope);
} else {
st = new NetBlock(NetBlock::SEQU, scope);
st->set_line(*this);
}
res->set_case(inum, gu, st); res->set_case(inum, gu, st);
inum += 1; inum += 1;
} }
@ -1451,12 +1621,26 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) { if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) {
verinum val = ce->value(); verinum val = ce->value();
delete expr; delete expr;
if (val[0] == verinum::V1)
return if_->elaborate(des, scope); verinum::V val_reduced = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
val_reduced = val_reduced | val[idx];
if (val_reduced == verinum::V1)
if (if_) {
return if_->elaborate(des, scope);
} else {
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
tmp->set_line(*this);
return tmp;
}
else if (else_) else if (else_)
return else_->elaborate(des, scope); return else_->elaborate(des, scope);
else else {
return new NetBlock(NetBlock::SEQU, 0); NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
tmp->set_line(*this);
return tmp;
}
} }
// If the condition expression is more then 1 bits, then // If the condition expression is more then 1 bits, then
@ -1625,6 +1809,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
} }
NetBlock*block = new NetBlock(NetBlock::SEQU, 0); NetBlock*block = new NetBlock(NetBlock::SEQU, 0);
block->set_line(*this);
/* Detect the case where the definition of the task is known /* Detect the case where the definition of the task is known
@ -1702,6 +1887,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
continue; continue;
NetESignal*sig = new NetESignal(port); NetESignal*sig = new NetESignal(port);
sig->set_line(*this);
/* Generate the assignment statement. */ /* Generate the assignment statement. */
NetAssign*ass = new NetAssign(lv, sig); NetAssign*ass = new NetAssign(lv, sig);
@ -1922,10 +2108,15 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
if (expr_.count() == 0) { if (expr_.count() == 0) {
assert(enet); assert(enet);
NexusSet*nset = enet->nex_input(); /* For synthesis we want just the inputs, but for the rest we
* want inputs and outputs that may cause a value to change. */
extern bool synthesis; /* Synthesis flag from main.cc */
bool rem_out = false;
if (synthesis) rem_out = true;
NexusSet*nset = enet->nex_input(rem_out);
if (nset == 0) { if (nset == 0) {
cerr << get_line() << ": internal error: No NexusSet" cerr << get_line() << ": error: Unable to elaborate:"
<< " from statement." << endl; << endl;
enet->dump(cerr, 6); enet->dump(cerr, 6);
des->errors += 1; des->errors += 1;
return enet; return enet;
@ -2314,6 +2505,13 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
the for loop. This is also a very specific assignment the for loop. This is also a very specific assignment
statement. Put this into the "body" block. */ statement. Put this into the "body" block. */
sig = des->find_signal(scope, id2->path()); sig = des->find_signal(scope, id2->path());
if (sig == 0) {
cerr << get_line() << ": error: Unable to find variable "
<< id2->path() << " in for-loop increment expression." << endl;
des->errors += 1;
return body;
}
assert(sig); assert(sig);
lv = new NetAssign_(sig); lv = new NetAssign_(sig);
@ -2481,6 +2679,7 @@ void PTask::elaborate(Design*des, NetScope*task) const
NetProc*st; NetProc*st;
if (statement_ == 0) { if (statement_ == 0) {
st = new NetBlock(NetBlock::SEQU, 0); st = new NetBlock(NetBlock::SEQU, 0);
st->set_line(*this);
} else { } else {
@ -2769,6 +2968,24 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.308.2.6 2006/11/27 01:47:14 steve
* Fix crash handling constant true conditional.
*
* Revision 1.308.2.5 2006/11/27 01:32:24 steve
* Fix evaluate of constant condition expressions.
*
* Revision 1.308.2.4 2006/07/10 00:21:50 steve
* Add support for full_case attribute.
*
* Revision 1.308.2.3 2006/06/12 00:16:51 steve
* Add support for -Wunused warnings.
*
* Revision 1.308.2.2 2005/12/10 03:30:50 steve
* Fix crash on block with assignments that assign lval to self.
*
* Revision 1.308.2.1 2005/11/13 22:28:14 steve
* Do not panic if case statement is nul.
*
* Revision 1.308 2004/10/04 01:10:52 steve * Revision 1.308 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

19
emit.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: emit.cc,v 1.77 2004/10/04 01:10:53 steve Exp $" #ident "$Id: emit.cc,v 1.77.2.2 2006/03/26 23:09:21 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -32,6 +32,7 @@
# include "netlist.h" # include "netlist.h"
# include <typeinfo> # include <typeinfo>
# include <cassert> # include <cassert>
# include <cstring>
bool NetNode::emit_node(struct target_t*tgt) const bool NetNode::emit_node(struct target_t*tgt) const
{ {
@ -86,6 +87,16 @@ bool NetConst::emit_node(struct target_t*tgt) const
return tgt->net_const(this); return tgt->net_const(this);
} }
bool NetDecode::emit_node(struct target_t*tgt) const
{
return tgt->lpm_decode(this);
}
bool NetDemux::emit_node(struct target_t*tgt) const
{
return tgt->lpm_demux(this);
}
bool NetDivide::emit_node(struct target_t*tgt) const bool NetDivide::emit_node(struct target_t*tgt) const
{ {
tgt->lpm_divide(this); tgt->lpm_divide(this);
@ -511,6 +522,12 @@ bool emit(const Design*des, const char*type)
/* /*
* $Log: emit.cc,v $ * $Log: emit.cc,v $
* Revision 1.77.2.2 2006/03/26 23:09:21 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.77 2004/10/04 01:10:53 steve * Revision 1.77 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

37
eval.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: eval.cc,v 1.36 2003/06/21 01:21:43 steve Exp $" #ident "$Id: eval.cc,v 1.36.2.3 2006/09/20 20:27:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -112,7 +112,10 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
case 'l': { // left shift (<<) case 'l': { // left shift (<<)
assert(r->is_defined()); assert(r->is_defined());
unsigned long rv = r->as_ulong(); unsigned long rv = r->as_ulong();
res = new verinum(verinum::V0, l->len()); unsigned use_wid = l->len();
if (! l->has_len())
use_wid += rv;
res = new verinum(verinum::V0, use_wid);
if (rv < res->len()) { if (rv < res->len()) {
unsigned cnt = res->len() - rv; unsigned cnt = res->len() - rv;
for (unsigned idx = 0 ; idx < cnt ; idx += 1) for (unsigned idx = 0 ; idx < cnt ; idx += 1)
@ -143,6 +146,27 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
return res; return res;
} }
verinum* PEConcat::eval_const(const Design*des, const NetScope*scope) const
{
verinum*accum = parms_[0]->eval_const(des, scope);
if (accum == 0)
return 0;
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
verinum*tmp = parms_[idx]->eval_const(des, scope);
/* Oops, found an argument that is not constant. Give up. */
if (tmp == 0) {
delete accum;
return 0;
}
assert(tmp);
*accum = concat(*accum, *tmp);
delete tmp;
}
return accum;
}
/* /*
* Evaluate an identifier as a constant expression. This is only * Evaluate an identifier as a constant expression. This is only
@ -240,6 +264,15 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
/* /*
* $Log: eval.cc,v $ * $Log: eval.cc,v $
* Revision 1.36.2.3 2006/09/20 20:27:02 steve
* Fix left shift of small unsized constants.
*
* Revision 1.36.2.2 2005/12/18 21:06:01 steve
* Properly fail when concat is not actually constant.
*
* Revision 1.36.2.1 2005/12/07 03:28:44 steve
* Support constant concatenation of constants.
*
* Revision 1.36 2003/06/21 01:21:43 steve * Revision 1.36 2003/06/21 01:21:43 steve
* Harmless fixup of warnings. * Harmless fixup of warnings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: eval_tree.cc,v 1.62 2004/10/04 01:10:53 steve Exp $" #ident "$Id: eval_tree.cc,v 1.62.2.5 2007/03/23 23:02:31 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -215,6 +215,11 @@ NetEConst* NetEBComp::eval_eqeq_()
NetEConst* NetEBComp::eval_less_() NetEConst* NetEBComp::eval_less_()
{ {
if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(false, false);
if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(false, false);
NetEConst*r = dynamic_cast<NetEConst*>(right_); NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0; if (r == 0) return 0;
@ -224,12 +229,24 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result); return new NetEConst(result);
} }
if (left_->expr_width() == 0) {
cerr << get_line() << ": internal error: "
<< "Having trouble evaluating left expression of < op."
<< endl;
cerr << get_line() << ": : "
<< "Expression is: "
<< *this << endl;
return 0;
}
/* Detect the case where the right side is greater that or /* Detect the case where the right side is greater that or
equal to the largest value the left side can possibly equal to the largest value the left side can possibly
have. */ have. */
assert(left_->expr_width() > 0); assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width()); verinum lv (verinum::V1, left_->expr_width() + 1);
if (lv < rv) { lv.set(left_->expr_width(), verinum::V0);
lv.has_sign( left_->has_sign() );
if ((lv < rv) == verinum::V1) {
verinum result(verinum::V1, 1); verinum result(verinum::V1, 1);
return new NetEConst(result); return new NetEConst(result);
} }
@ -259,7 +276,7 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result); return new NetEConst(result);
} }
NetEConst* NetEBComp::eval_leeq_real_() NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
{ {
NetEConst*vtmp; NetEConst*vtmp;
NetECReal*rtmp; NetECReal*rtmp;
@ -308,7 +325,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
assert(0); assert(0);
} }
verinum result((lv <= rv)? verinum::V1 : verinum::V0, 1); /* This function supports < and <=. If the eq_flag is true,
then include <=. Otherwise, include only <. */
bool flag;
if (gt_flag)
flag = include_eq_flag? (lv >= rv) : (lv > rv);
else
flag = include_eq_flag? (lv <= rv) : (lv < rv);
verinum result(flag? verinum::V1 : verinum::V0, 1);
vtmp = new NetEConst(result); vtmp = new NetEConst(result);
vtmp->set_line(*this); vtmp->set_line(*this);
@ -318,9 +344,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
NetEConst* NetEBComp::eval_leeq_() NetEConst* NetEBComp::eval_leeq_()
{ {
if (right_->expr_type() == ET_REAL) if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(); return eval_leeq_real_(false, true);
if (left_->expr_type() == ET_REAL) if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(); return eval_leeq_real_(false, true);
NetEConst*r = dynamic_cast<NetEConst*>(right_); NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0; if (r == 0) return 0;
@ -337,11 +363,17 @@ NetEConst* NetEBComp::eval_leeq_()
cerr << get_line() << ": : " << *this << endl; cerr << get_line() << ": : " << *this << endl;
} }
/* Detect the case where the right side is greater that or /* Detect the case where the right side is greater than or
equal to the largest value the left side can possibly equal to the largest value the left side can possibly
have. */ have. */
assert(left_->expr_width() > 0); assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width()); verinum lv (verinum::V1, left_->expr_width() + 1);
if (left_->has_sign() && rv.has_sign()) {
lv.set(lv.len()-1, verinum::V0);
lv.has_sign(true);
}
lv.set(left_->expr_width(), verinum::V0);
lv.has_sign( left_->has_sign() );
if (lv <= rv) { if (lv <= rv) {
verinum result(verinum::V1, 1); verinum result(verinum::V1, 1);
return new NetEConst(result); return new NetEConst(result);
@ -374,23 +406,10 @@ NetEConst* NetEBComp::eval_leeq_()
NetEConst* NetEBComp::eval_gt_() NetEConst* NetEBComp::eval_gt_()
{ {
if ((left_->expr_type() == NetExpr::ET_REAL) if (right_->expr_type() == ET_REAL)
&& (right_->expr_type() == NetExpr::ET_REAL)) { return eval_leeq_real_(true, false);
if (left_->expr_type() == ET_REAL)
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_); return eval_leeq_real_(true, false);
if (tmpl == 0)
return 0;
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
if (tmpr == 0)
return 0;
double ll = tmpl->value().as_double();
double rr = tmpr->value().as_double();
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
NetEConst*l = dynamic_cast<NetEConst*>(left_); NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0; if (l == 0) return 0;
@ -450,23 +469,10 @@ NetEConst* NetEBComp::eval_gt_()
NetEConst* NetEBComp::eval_gteq_() NetEConst* NetEBComp::eval_gteq_()
{ {
if ((left_->expr_type() == NetExpr::ET_REAL) if (right_->expr_type() == ET_REAL)
&& (right_->expr_type() == NetExpr::ET_REAL)) { return eval_leeq_real_(true, true);
if (left_->expr_type() == ET_REAL)
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_); return eval_leeq_real_(true, true);
if (tmpl == 0)
return 0;
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
if (tmpr == 0)
return 0;
double ll = tmpl->value().as_double();
double rr = tmpr->value().as_double();
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
NetEConst*l = dynamic_cast<NetEConst*>(left_); NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0; if (l == 0) return 0;
@ -1069,6 +1075,12 @@ NetEConst* NetEConcat::eval_tree()
val = verinum(val.as_string()); val = verinum(val.as_string());
} }
// Normally, concatenations are unsigned. However, the
// $signed() function works by marking the expression as
// signed, so we really have to check.
val.has_sign( this->has_sign() );
NetEConst*res = new NetEConst(val); NetEConst*res = new NetEConst(val);
res->set_width(val.len()); res->set_width(val.len());
return res; return res;
@ -1477,6 +1489,7 @@ NetEConst* NetEUReduce::eval_tree()
verinum val = rval->value(); verinum val = rval->value();
verinum::V res; verinum::V res;
bool invert = false;
switch (op_) { switch (op_) {
@ -1505,6 +1518,8 @@ NetEConst* NetEUReduce::eval_tree()
break; break;
} }
case 'A':
invert = true;
case '&': { case '&': {
res = verinum::V1; res = verinum::V1;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1) for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@ -1512,6 +1527,8 @@ NetEConst* NetEUReduce::eval_tree()
break; break;
} }
case 'N':
invert = true;
case '|': { case '|': {
res = verinum::V0; res = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1) for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@ -1519,6 +1536,8 @@ NetEConst* NetEUReduce::eval_tree()
break; break;
} }
case 'X':
invert = true;
case '^': { case '^': {
/* Reduction XOR. */ /* Reduction XOR. */
unsigned ones = 0, unknown = 0; unsigned ones = 0, unknown = 0;
@ -1534,23 +1553,38 @@ NetEConst* NetEUReduce::eval_tree()
break; break;
} }
if (unknown) if (unknown) res = verinum::Vx;
return new NetEConst(verinum(verinum::Vx,1,true)); else if (ones%2) res = verinum::V1;
if (ones%2) else res = verinum::V0;
return new NetEConst(verinum(verinum::V1,1,true)); break;
return new NetEConst(verinum(verinum::V0,1,true));
} }
default: default:
return 0; return 0;
} }
if (invert) res = ~res;
return new NetEConst(verinum(res, 1)); return new NetEConst(verinum(res, 1));
} }
/* /*
* $Log: eval_tree.cc,v $ * $Log: eval_tree.cc,v $
* Revision 1.62.2.5 2007/03/23 23:02:31 steve
* Fix compile time eval of <= comparison.
*
* Revision 1.62.2.4 2007/03/23 20:59:25 steve
* Fix compile time evaluation of < operator.
*
* Revision 1.62.2.3 2005/09/09 02:17:08 steve
* Evaluate magnitude compare with real operands.
*
* Revision 1.62.2.2 2005/09/04 15:41:54 steve
* More explicit internal error message.
*
* Revision 1.62.2.1 2005/09/04 15:39:19 steve
* More explicit internal error message.
*
* Revision 1.62 2004/10/04 01:10:53 steve * Revision 1.62 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -16,13 +16,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
* $Id: sqrt-virtex.v,v 1.4 2003/11/25 18:35:31 steve Exp $" * $Id: sqrt-virtex.v,v 1.4.2.2 2005/02/23 18:37:52 steve Exp $"
*/ */
/* /*
* This module is a synthesizeable square-root function. It is also a * This module is a synthesizeable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using * detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other then to * Icarus Verilog. In fact, for no particular reason other than to
* be excessively specific, I will step through the process of * be excessively specific, I will step through the process of
* generating a design for a Spartan-II XC2S15-VQ100, and also how to * generating a design for a Spartan-II XC2S15-VQ100, and also how to
* generate a generic library part for larger Virtex designs. * generate a generic library part for larger Virtex designs.
@ -129,8 +129,8 @@
* This command creates from the chip.ngd the file "chip_root.v" that * This command creates from the chip.ngd the file "chip_root.v" that
* contains Verilog code that simulates the mapped design. This output * contains Verilog code that simulates the mapped design. This output
* Verilog has the single root module "chip_root", which came from the * Verilog has the single root module "chip_root", which came from the
* name of the root module when we were making hte EDIF file in the * name of the root module when we were making the EDIF file in the
* first place. The module has ports named just line the ports of the * first place. The module has ports named just like the ports of the
* chip_root module below. * chip_root module below.
* *
* The generated Verilog uses the library in the directory * The generated Verilog uses the library in the directory

View File

@ -17,24 +17,65 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $" #ident "$Id: expr_synth.cc,v 1.59.2.11 2007/02/26 19:51:38 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include <iostream> # include <iostream>
# include <typeinfo>
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
# include "compiler.h"
NetNet* NetExpr::synthesize(Design*des) NetNet* NetExpr::synthesize(Design*des)
{ {
cerr << get_line() << ": internal error: cannot synthesize expression: " cerr << get_line() << ": internal error: cannot synthesize expression: "
<< *this << endl; << *this << endl;
cerr << get_line() << ": : typeid="
<< typeid(*this).name() << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
/*
* For the NetEBitSel expression, create a NetMux node that selects a
* bit from the input.
*/
NetNet* NetEBitSel::synthesize(Design*des)
{
NetNet*net = sig_->synthesize(des);
assert(net);
NetNet*adr = idx_->synthesize(des);
if (adr == 0)
return 0;
NetScope*scope = adr->scope();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
osig->set_line(*this);
osig->local_flag(true);
NetMux*mux = new NetMux(scope, scope->local_symbol(),
1, net->pin_count(), adr->pin_count());
mux->set_line(*this);
des->add_node(mux);
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
connect(mux->pin_Data(0, idx), net->pin(idx));
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
connect(mux->pin_Sel(idx), adr->pin(idx));
connect(mux->pin_Result(0), osig->pin(0));
return osig;
}
/* /*
* Make an LPM_ADD_SUB device from addition operators. * Make an LPM_ADD_SUB device from addition operators.
*/ */
@ -408,7 +449,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
default: { default: {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
<< "NetEBDiv has unexpeced op() code: " << "NetEBDiv has unexpected op() code: "
<< op() << endl; << op() << endl;
des->errors += 1; des->errors += 1;
@ -472,13 +513,18 @@ NetNet* NetEBLogic::synthesize(Design*des)
perm_string oname = scope->local_symbol(); perm_string oname = scope->local_symbol();
olog = new NetLogic(scope, oname, 3, NetLogic::AND); olog = new NetLogic(scope, oname, 3, NetLogic::AND);
olog->set_line(*this);
connect(osig->pin(0), olog->pin(0)); connect(osig->pin(0), olog->pin(0));
des->add_node(olog); des->add_node(olog);
/* XXXX Here, I need to reduce the parameters with /* Here, I need to reduce the parameters with
reduction or. */ reduction or. Only do this if we must. */
if (lsig->pin_count() > 1)
lsig = reduction_or(des, lsig);
if (rsig->pin_count() > 1)
rsig = reduction_or(des, rsig);
/* By this point, the left and right parameters have been /* By this point, the left and right parameters have been
reduced to single bit values. Now we just connect them to reduced to single bit values. Now we just connect them to
@ -486,6 +532,11 @@ NetNet* NetEBLogic::synthesize(Design*des)
assert(lsig->pin_count() == 1); assert(lsig->pin_count() == 1);
connect(lsig->pin(0), olog->pin(1)); connect(lsig->pin(0), olog->pin(1));
if (rsig->pin_count() != 1) {
cerr << olog->get_line() << ": internal error: "
<< "right argument not reduced. expr=" << *this << endl;
}
assert(rsig->pin_count() == 1); assert(rsig->pin_count() == 1);
connect(rsig->pin(0), olog->pin(2)); connect(rsig->pin(0), olog->pin(2));
} }
@ -566,7 +617,6 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet::IMPLICIT, expr_width()); NetNet::IMPLICIT, expr_width());
osig->local_flag(true); osig->local_flag(true);
assert(op() == 'l');
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(), NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
osig->pin_count(), osig->pin_count(),
rsig->pin_count(), rsig->pin_count(),
@ -640,6 +690,71 @@ NetNet* NetEConst::synthesize(Design*des)
return osig; return osig;
} }
NetNet* NetEMemory::synthesize(Design*des)
{
NetScope*scope = mem_->scope();
NetNet*explode = mem_->explode_to_reg();
unsigned width = expr_width();
assert(idx_);
NetNet*addr = idx_->synthesize(des);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT,
width);
osig->set_line(*this);
if (explode) {
if (debug_synth)
cerr << get_line() << ": debug: synthesize read of "
<< explode->pin_count() << " bit exploded memory." << endl;
/* Only make a mux big enough to address the words that
the address can generate. (If the address is
0-extended, then only the low words are addressable.) */
unsigned use_count = mem_->count();
if (use_count > (1U << addr->pin_count())) {
use_count = 1 << addr->pin_count();
if (debug_synth)
cerr << get_line() << ": debug: "
<< "Index expression can only address "
<< use_count << " of "
<< mem_->count() << " words." << endl;
}
/* This is a reference to an exploded memory. So locate
the reg vector and use the addr expression as a
select into a MUX. */
NetMux*mux = new NetMux(scope, scope->local_symbol(),
width, use_count, addr->pin_count());
des->add_node(mux);
mux->set_line(*this);
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(mux->pin_Result(idx), osig->pin(idx));
for (unsigned idx = 0 ; idx < mux->sel_width() ; idx += 1)
connect(mux->pin_Sel(idx), addr->pin(idx));
for (unsigned wrd = 0 ; wrd < use_count ; wrd += 1)
for (unsigned idx = 0 ; idx < width ; idx += 1) {
unsigned bit = wrd*width + idx;
connect(mux->pin_Data(idx, wrd), explode->pin(bit));
}
if (debug_synth)
cerr << get_line() << ": debug: synthesis done." << endl;
} else {
cerr << get_line() << ": internal error: Synthesize memory "
<< "expression that is not exploded?" << endl;
des->errors += 1;
}
return osig;
}
NetNet* NetECReal::synthesize(Design*des) NetNet* NetECReal::synthesize(Design*des)
{ {
cerr << get_line() << ": error: Real constants are " cerr << get_line() << ": error: Real constants are "
@ -684,6 +799,97 @@ NetNet* NetEUBits::synthesize(Design*des)
return osig; return osig;
} }
NetNet* NetEUFunc::synthesize(Design*des)
{
assert(func_);
NetFuncDef* def = func_->func_def();
assert(def);
assert(parms_.count() == def->port_count());
svector<NetNet*> inports (parms_.count());
unsigned errors = 0;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
inports[idx] = parms_[idx]->synthesize(des);
if (inports[idx] == 0)
errors += 1;
}
if (errors > 0) {
cerr << get_line() << ": error: "
<< "Cannot continue with function instance synthesis."
<< endl;
return 0;
}
NetNet*out = def->synthesize(des, inports);
if (! out) {
cerr << get_line() << ": error: "
<< "User defined functions do not synthesize." << endl;
def->dump(cerr, 4);
des->errors += 1;
return 0;
}
return out;
}
NetNet* NetFuncDef::synthesize(Design*des, const svector<NetNet*>&inports_)
{
/* First run synthesis for the function definition as if this
where a toplevel process. This will create the logic that
the function represents, but connected to the port nets for
the function definition. We will detach those common ports
later. */
NexusSet nex_set;
statement_->nex_output(nex_set);
const perm_string tmp1 = scope()->local_symbol();
NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE,
nex_set.count());
for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1)
connect(nex_set[idx], nex_out->pin(idx));
bool flag = statement_->synth_async_noaccum(des, scope(), false, 0,
nex_out, nex_out);
if (!flag) {
delete nex_out;
return 0;
}
/* Connect the inports_ vectors to the input ports and detach
the static arg ports themselves. This moves the input from
the synthesized device from the static ports to the actual
ports from the instance context. */
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
NetNet*in = inports_[idx];
NetNet*arg = ports_[idx];
in = pad_to_width(des, in, arg->pin_count());
for (unsigned pin = 0 ; pin < arg->pin_count() ; pin += 1) {
connect(in->pin(pin), arg->pin(pin));
arg->pin(pin).unlink();
}
}
/* Detach the output signal from the synthesized result. We
use instead the nex_out that was returned from the
synthesis of the function. This is how we account for the
fact that the function may be synthesized multiple times to
go into multiple expression. Each synthesis needs a unique
output. */
for (unsigned idx = 0 ; idx < result_sig_->pin_count() ; idx += 1)
result_sig_->pin(idx).unlink();
return nex_out;
}
NetNet* NetEUReduce::synthesize(Design*des) NetNet* NetEUReduce::synthesize(Design*des)
{ {
NetNet*isig = expr_->synthesize(des); NetNet*isig = expr_->synthesize(des);
@ -811,6 +1017,7 @@ NetNet* NetETernary::synthesize(Design *des)
perm_string oname = csig->scope()->local_symbol(); perm_string oname = csig->scope()->local_symbol();
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1); NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
mux->set_line(*this);
for (unsigned idx = 0 ; idx < width; idx += 1) { for (unsigned idx = 0 ; idx < width; idx += 1) {
connect(tsig->pin(idx), mux->pin_Data(idx, 1)); connect(tsig->pin(idx), mux->pin_Data(idx, 1));
connect(fsig->pin(idx), mux->pin_Data(idx, 0)); connect(fsig->pin(idx), mux->pin_Data(idx, 0));
@ -854,6 +1061,21 @@ NetNet* NetETernary::synthesize(Design *des)
*/ */
NetNet* NetESignal::synthesize(Design*des) NetNet* NetESignal::synthesize(Design*des)
{ {
if (warn_unused) {
if (net_->peek_lref() == 0 && net_->type()==NetNet::REG) {
cerr << get_line() << ": warning: "
<< "reg " << net_->name()
<< " is used by logic but never assigned." << endl;
}
if (net_->peek_lref() == 0 && net_->type()==NetNet::INTEGER) {
cerr << get_line() << ": warning: "
<< "reg " << net_->name()
<< " is used by logic but never assigned." << endl;
}
}
/* If there is no part select, then the synthesis is trivial. */
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1))) if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
return net_; return net_;
@ -866,6 +1088,7 @@ NetNet* NetESignal::synthesize(Design*des)
perm_string name = scope->local_symbol(); perm_string name = scope->local_symbol();
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid); NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
tmp->local_flag(true); tmp->local_flag(true);
tmp->set_line(*this);
for (unsigned idx = 0 ; idx < wid ; idx += 1) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(tmp->pin(idx), net_->pin(idx+lsi_)); connect(tmp->pin(idx), net_->pin(idx+lsi_));
@ -875,6 +1098,39 @@ NetNet* NetESignal::synthesize(Design*des)
/* /*
* $Log: expr_synth.cc,v $ * $Log: expr_synth.cc,v $
* Revision 1.59.2.11 2007/02/26 19:51:38 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.59.2.10 2006/11/26 01:54:05 steve
* Add synthesis of user defined functions.
*
* Revision 1.59.2.9 2006/08/08 02:17:48 steve
* Improved nexus management performance.
*
* Revision 1.59.2.8 2006/06/15 01:57:26 steve
* Handle simple memory addressing in expression synthesis.
*
* Revision 1.59.2.7 2006/06/14 03:02:54 steve
* synthesis for NetEBitSel.
*
* Revision 1.59.2.6 2006/06/12 00:16:52 steve
* Add support for -Wunused warnings.
*
* Revision 1.59.2.5 2006/05/15 03:55:22 steve
* Fix synthesis of expressions with land of vectors.
*
* Revision 1.59.2.4 2006/04/10 03:43:39 steve
* Exploded memories accessed by constant indices.
*
* Revision 1.59.2.3 2006/03/16 05:39:20 steve
* Right shifts really are allowed.
*
* Revision 1.59.2.2 2005/09/11 02:56:37 steve
* Attach line numbers to NetMux devices.
*
* Revision 1.59.2.1 2005/02/19 16:39:31 steve
* Spellig fixes.
*
* Revision 1.59 2004/06/30 02:16:26 steve * Revision 1.59 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets. * Implement signed divide and signed right shift in nets.
* *
@ -883,82 +1139,5 @@ NetNet* NetESignal::synthesize(Design*des)
* *
* Revision 1.57 2004/06/12 15:00:02 steve * Revision 1.57 2004/06/12 15:00:02 steve
* Support / and % in synthesized contexts. * Support / and % in synthesized contexts.
*
* Revision 1.56 2004/06/01 01:04:57 steve
* Fix synthesis method for logical and/or
*
* Revision 1.55 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.54 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.53 2004/02/15 04:23:48 steve
* Fix evaluation of compare to constant expression.
*
* Revision 1.52 2003/11/10 19:39:20 steve
* Remove redundant scope tokens.
*
* Revision 1.51 2003/10/27 06:04:21 steve
* More flexible width handling for synthesized add.
*
* Revision 1.50 2003/09/26 02:44:27 steve
* Assure ternary arguments are wide enough.
*
* Revision 1.49 2003/09/03 23:31:36 steve
* Support synthesis of constant downshifts.
*
* Revision 1.48 2003/08/28 04:11:18 steve
* Spelling patch.
*
* Revision 1.47 2003/08/09 03:23:40 steve
* Add support for IVL_LPM_MULT device.
*
* Revision 1.46 2003/07/26 03:34:42 steve
* Start handling pad of expressions in code generators.
*
* Revision 1.45 2003/06/24 01:38:02 steve
* Various warnings fixed.
*
* Revision 1.44 2003/04/19 04:52:56 steve
* Less picky about expression widths while synthesizing ternary.
*
* Revision 1.43 2003/04/08 05:07:15 steve
* Detect constant shift distances in synthesis.
*
* Revision 1.42 2003/04/08 04:33:55 steve
* Synthesize shift expressions.
*
* Revision 1.41 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.40 2003/02/26 01:29:24 steve
* LPM objects store only their base names.
*
* Revision 1.39 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.38 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.37 2002/11/17 23:37:55 steve
* Magnitude compare to 0.
*
* Revision 1.36 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.35 2002/07/07 22:31:39 steve
* Smart synthesis of binary AND expressions.
*
* Revision 1.34 2002/07/05 21:26:17 steve
* Avoid emitting to vvp local net symbols.
*
* Revision 1.33 2002/05/26 01:39:02 steve
* Carry Verilog 2001 attributes with processes,
* all the way through to the ivl_target API.
*
* Divide signal reference counts between rval
* and lval references.
*/ */

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: functor.cc,v 1.32 2004/10/04 01:10:53 steve Exp $" #ident "$Id: functor.cc,v 1.32.2.1 2006/04/23 04:26:14 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -79,6 +79,9 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
{ {
} }
void functor_t::lpm_ram_dq(class Design*, class NetRamDq*)
{
}
void NetScope::run_functor(Design*des, functor_t*fun) void NetScope::run_functor(Design*des, functor_t*fun)
{ {
@ -206,6 +209,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
fun->lpm_mux(des, this); fun->lpm_mux(des, this);
} }
void NetRamDq::functor_node(Design*des, functor_t*fun)
{
fun->lpm_ram_dq(des, this);
}
proc_match_t::~proc_match_t() proc_match_t::~proc_match_t()
{ {
} }
@ -267,6 +275,9 @@ int proc_match_t::event_wait(NetEvWait*)
/* /*
* $Log: functor.cc,v $ * $Log: functor.cc,v $
* Revision 1.32.2.1 2006/04/23 04:26:14 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.32 2004/10/04 01:10:53 steve * Revision 1.32 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: functor.h,v 1.20 2002/08/12 01:34:59 steve Exp $" #ident "$Id: functor.h,v 1.20.2.1 2006/04/23 04:26:14 steve Exp $"
#endif #endif
/* /*
@ -77,6 +77,9 @@ struct functor_t {
/* This method is called for each MUX. */ /* This method is called for each MUX. */
virtual void lpm_mux(class Design*des, class NetMux*); virtual void lpm_mux(class Design*des, class NetMux*);
/* This is called for eacm RamDq device. */
virtual void lpm_ram_dq(class Design*des, class NetRamDq*);
}; };
struct proc_match_t { struct proc_match_t {
@ -92,6 +95,9 @@ struct proc_match_t {
/* /*
* $Log: functor.h,v $ * $Log: functor.h,v $
* Revision 1.20.2.1 2006/04/23 04:26:14 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.20 2002/08/12 01:34:59 steve * Revision 1.20 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig. * conditional ident string using autoconfig.
* *

View File

@ -27,6 +27,15 @@ first source file is named \fIfoo.c\fP, the output becomes
Include the named library in the link of the VPI module. This allows Include the named library in the link of the VPI module. This allows
VPI modules to further reference external libraries. 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.
.TP 8
.B -D\fIdefine\fP
Define a macro named \fIdefine\fP.
.TP 8 .TP 8
.B --name=\fIname\fP .B --name=\fIname\fP
Normally, the output VPI module will be named after the first source Normally, the output VPI module will be named after the first source
@ -39,6 +48,10 @@ This flag causes the program to print the install directory for VPI
modules, then exit. It is a convenience for makefiles or automated modules, then exit. It is a convenience for makefiles or automated
plug-in installers. plug-in installers.
.TP 8
.B --cflags, --ldflags and -ldlibs
These flags provide compile time information.
.SH "PC-ONLY OPTIONS" .SH "PC-ONLY OPTIONS"
The PC port of \fIiverilog-vpi\fP includes two special flags needed to The PC port of \fIiverilog-vpi\fP includes two special flags needed to

View File

@ -17,19 +17,20 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: iverilog-vpi.sh,v 1.14 2004/05/20 00:40:34 steve Exp $"
# These are the variables used for compiling files # These are the variables used for compiling files
CC=gcc CC=@IVCC@
CXX=gcc CXX=@IVCXX@
CFLAGS="@PIC@ -O -I@INCLUDEDIR@" CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
SUFFIX=@SUFFIX@
# These are used for linking... # These are used for linking...
LD=gcc LD=$CC
LDFLAGS32="@SHARED@ -L@LIBDIR@" LDFLAGS32="@SHARED@ -L@LIBDIR@"
LDFLAGS64="@SHARED@ -L@LIBDIR64@" LDFLAGS64="@SHARED@ -L@LIBDIR64@"
LDFLAGS="$LDFLAGS64" LDFLAGS="$LDFLAGS64"
LDLIBS="-lveriuser -lvpi" LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
INSTDIR64="@VPIDIR1@" INSTDIR64="@VPIDIR1@"
INSTDIR32="@VPIDIR2@" INSTDIR32="@VPIDIR2@"
@ -46,6 +47,7 @@ OBJ=
LIB= LIB=
OUT= OUT=
INCOPT= INCOPT=
DEFS=
# -- # --
# parse the command line switches. This collects the source files # parse the command line switches. This collects the source files
@ -63,11 +65,19 @@ do
;; ;;
*.cc) CXSRC="$CXSRC $parm" *.cc) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then if [ x$OUT = x ]; then
OUT=`basename $parm .cc` OUT=`basename $parm .cc`
fi fi
;; ;;
*.cpp) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cpp`
fi
;;
*.o) OBJ="$OBJ $parm" *.o) OBJ="$OBJ $parm"
if [ x$OUT = x ]; then if [ x$OUT = x ]; then
OUT=`basename $parm .o` OUT=`basename $parm .o`
@ -82,7 +92,9 @@ do
;; ;;
-I*) INCOPT="$INCOPT $parm" -I*) INCOPT="$INCOPT $parm"
echo "$parm" ;;
-D*) DEFS="$DEFS $parm"
;; ;;
-m32) LDFLAGS="-m32 $LDFLAGS32" -m32) LDFLAGS="-m32 $LDFLAGS32"
@ -106,7 +118,7 @@ do
;; ;;
--install-dir) --install-dir)
echo "@LIBDIR@/ivl/$INSTDIR" echo "@LIBDIR@/ivl$SUFFIX/$INSTDIR"
exit exit
;; ;;
esac esac
@ -130,7 +142,7 @@ do
obj=$base".o" obj=$base".o"
echo "Compiling $src..." echo "Compiling $src..."
$CC -c -o $obj $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1` $CC -c -o $obj $DEFS $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1`
OBJ="$OBJ $obj" OBJ="$OBJ $obj"
done done
@ -140,13 +152,13 @@ do
obj=$base".o" obj=$base".o"
echo "Compiling $src..." echo "Compiling $src..."
$CXX -c -o $obj $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1` $CXX -c -o $obj $DEFS $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1`
OBJ="$OBJ $obj" OBJ="$OBJ $obj"
done done
if test $compile_errors -gt 0 if test $compile_errors -gt 0
then then
echo "Some ($compile_errors) files failed to compile." echo "$0: $compile_errors file(s) failed to compile."
exit $compile_errors exit $compile_errors
fi fi

View File

@ -62,12 +62,15 @@ ivl_logic_udp
ivl_lpm_aset_value ivl_lpm_aset_value
ivl_lpm_async_clr ivl_lpm_async_clr
ivl_lpm_async_set ivl_lpm_async_set
ivl_lpm_attr_cnt
ivl_lpm_attr_val
ivl_lpm_basename ivl_lpm_basename
ivl_lpm_clk ivl_lpm_clk
ivl_lpm_data ivl_lpm_data
ivl_lpm_datab ivl_lpm_datab
ivl_lpm_data2 ivl_lpm_data2
ivl_lpm_data2_width ivl_lpm_data2_width
ivl_lpm_decode
ivl_lpm_define ivl_lpm_define
ivl_lpm_enable ivl_lpm_enable
ivl_lpm_memory ivl_lpm_memory

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.126 2004/10/04 01:10:53 steve Exp $" #ident "$Id: ivl_target.h,v 1.126.2.5 2006/04/16 19:26:37 steve Exp $"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -226,8 +226,11 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CMP_GE = 1, IVL_LPM_CMP_GE = 1,
IVL_LPM_CMP_GT = 2, IVL_LPM_CMP_GT = 2,
IVL_LPM_CMP_NE = 11, IVL_LPM_CMP_NE = 11,
IVL_LPM_DECODE = 15,
IVL_LPM_DEMUX = 16,
IVL_LPM_DIVIDE = 12, IVL_LPM_DIVIDE = 12,
IVL_LPM_FF = 3, IVL_LPM_FF = 3,
IVL_LPM_LATCH = 17,
IVL_LPM_MOD = 13, IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4, IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5, IVL_LPM_MUX = 5,
@ -629,6 +632,11 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* the LPM type, but it generally has to do with the width of the * the LPM type, but it generally has to do with the width of the
* output data path. * output data path.
* *
* ivl_lpm_attr_cnt
* ivl_lpm_attr_val
* These functions access attributes attached to LPM devices. These
* attributes may be explicit attributes collected from the Verilog
* source, or implicit attributes generated by the compiler.
* *
* These functions apply to a subset of the LPM devices, or may have * These functions apply to a subset of the LPM devices, or may have
* varying meaning depending on the device: * varying meaning depending on the device:
@ -642,13 +650,18 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* Return the input data nexus for device types that have a second * Return the input data nexus for device types that have a second
* input vector. For example, arithmetic devices are like this. * input vector. For example, arithmetic devices are like this.
* *
* ivl_lpm_decode
* Return the DECODER associated with this LPM_FF device. The
* decoder for a FF takes an input address and generates an enable
* input for no more then 1 bit (can be none) of the FF device.
*
* ivl_lpm_q * ivl_lpm_q
* Return the output data nexus for device types that have a single * Return the output data nexus for device types that have a single
* output vector. This is most devices, it turns out. * output vector. This is most devices, it turns out.
* *
* ivl_lpm_selects * ivl_lpm_selects
* This is the size of the select input for a LPM_MUX device, or the * This is the size of the select input for a LPM_MUX or LPM_DECODE
* address bus width of an LPM_RAM. * device, or the address bus width of an LPM_RAM.
* *
* ivl_lpm_signed * ivl_lpm_signed
* Arithmetic LPM devices may be signed or unsigned if there is a * Arithmetic LPM devices may be signed or unsigned if there is a
@ -658,6 +671,64 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* In addition to a width, some devices have a size. The size is * In addition to a width, some devices have a size. The size is
* often the number of inputs per out, i.e., the number of inputs * often the number of inputs per out, i.e., the number of inputs
* per bit for a MUX. * per bit for a MUX.
*
* SEMANTIC NOTES:
*
* - IVL_LPM_FF
* The IVL_LPM_FF and IVL_LPM_DECODE devices are closely related. If
* the ivl_lpm_decode function returns a non-nil value, then the
* decoder represents an extra ENABLE-like input, where exactly <N>
* bits of the width of the FF is enabled. The ivl_lpm_width of the
* decoder defines <N>.
*
* The decoder inputs are the address that selects the FF to be
* enabled, and the ivl_lpm_selects for the decoder gives the width of
* the address. The address of the LSB of the memory, then, is the
* word width times the input address. For a simple l-value bit
* select, the word width <N> will be 1, and the address goes directly
* to the bit. Otherwise, <N>*address gets to the first bit of the word.
*
* The core compiler generates these attributes in certain cases:
*
* - ivl:clock_polarity
* If present, the string value can be "INVERT". That indicates
* that the clock is negedge sensitive instead of the default
* posedge sensitive.
*
* - IVL_LPM_RAM
* The IVL_LPM_RAM may also appear as a READ port for a FF array. In
* this case, the IVL_LPM_RAM device has an ivl_lpm_width that is the
* width of the word, and an ivl_lpm_size that is the number of words
* in the array. In effect, the IVL_LPM_RAM reorganizes a vector into
* an array of words. If this is happening, then the ivl_lpm_memory
* will return 0.
*
* The ivl_lpm_q function gets the output nexa of the read port. The
* "q" port has as many bits as the width. The ivl_lpm_data2 function
* gets the nexa of the input, with the sdx the word address and the
* idx the bit within the word.
*
* - IVL_LPM_DEMUX
* This device is a form of bit replacement. The device has a data bus
* width (ivl_lpm_width) and an address width. The Data outputs are
* ivl_lpm_q and have the data bus width. The ivl_lpm_data functions are
* inputs to the device. Normally, the device passes the data inputs
* through to the Q output.
*
* The IVL_LPM_DEMUX also has a size (ivl_lpm_size) which is the
* number of addressable units in the device. If the device is bit-
* addressable, then the size is the same as the width. I.e. if
* ivl_lpm_width == ivl_lpm_size, then the address selects a single
* bit. If ivl_lpm_width/ivl_lpm_size == 8, then the address selects
* words of 8 bits and there are ivl_lpm_size of them. The
* ivl_lpm_width will always be an exact multiple of
* ivl_lpm_size. This is slightly different from the meaning of width
* in memory ports, but reflects that the DEMUX manipulates fixed
* width ranges within a single vector.
*
* The ivl_lpm_select inputs address a bit of the device. The
* addressed bit is substituted by the replacement bit. This
* replacement bit comes from the ivl_lpm_datab(net,0) nexus.
*/ */
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
@ -667,6 +738,9 @@ extern int ivl_lpm_signed(ivl_lpm_t net);
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net); extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
extern unsigned ivl_lpm_width(ivl_lpm_t net); extern unsigned ivl_lpm_width(ivl_lpm_t net);
extern unsigned ivl_lpm_attr_cnt(ivl_lpm_t net);
extern ivl_attribute_t ivl_lpm_attr_val(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_FF */ /* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net);
@ -676,26 +750,31 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net); extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */ /* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_gate( ivl_lpm_t netPtr );
/* IVL_LPM_FF */
extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net);
/* IVL_LPM_UFUNC */ /* IVL_LPM_UFUNC */
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net); extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */ /* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */ /* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT */
/* IVL_LPM_RAM IVL_LPM_SUB IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */ /* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_MULT IVL_LPM_SUB */
/* IVL_LPM_MUX IVL_LPM_UFUNC */ /* IVL_LPM_MUX IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx); extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
/* IVL_LPM_UFUNC */ /* IVL_LPM_UFUNC */
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx); extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB /* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
IVL_LPM_UFUNC */ IVL_LPM_UFUNC IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX IVL_LPM_RAM */ /* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
extern unsigned ivl_lpm_selects(ivl_lpm_t net); extern unsigned ivl_lpm_selects(ivl_lpm_t net);
/* IVL_LPM_MUX IVL_LPM_RAM */ /* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX */ /* IVL_LPM_DEMUX, IVL_LPM_MUX, IVL_LPM_RAM */
extern unsigned ivl_lpm_size(ivl_lpm_t net); extern unsigned ivl_lpm_size(ivl_lpm_t net);
/* IVL_LPM_RAM */ /* IVL_LPM_RAM */
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
@ -1236,6 +1315,21 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $Log: ivl_target.h,v $
* Revision 1.126.2.5 2006/04/16 19:26:37 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.126.2.4 2006/03/26 23:09:22 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.126.2.3 2006/03/12 07:34:16 steve
* Fix the memsynth1 case.
*
* Revision 1.126.2.2 2006/02/25 05:03:28 steve
* Add support for negedge FFs by using attributes.
*
* Revision 1.126.2.1 2006/02/19 00:11:31 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.126 2004/10/04 01:10:53 steve * Revision 1.126 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -23,7 +23,7 @@
# #
SHELL = /bin/sh SHELL = /bin/sh
VERSION = 0.0 suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -63,16 +63,16 @@ lexor.c: lexor.lex
parse.h parse.c: parse.y parse.h parse.c: parse.y
bison --verbose -t -d -o parse.c $(srcdir)/parse.y bison --verbose -t -d -o parse.c $(srcdir)/parse.y
install: all installdirs $(libdir)/ivl/ivlpp install: all installdirs $(libdir)/ivl$(suffix)/ivlpp
$(libdir)/ivl/ivlpp: ivlpp $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp $(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
installdirs: ../mkinstalldirs installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl $(srcdir)/../mkinstalldirs $(libdir)/ivl$(suffix)
uninstall: uninstall:
rm -f $(libdir)/ivl/ivlpp rm -f $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
lexor.o: lexor.c parse.h globals.h lexor.o: lexor.c parse.h globals.h
main.o: main.c globals.h main.o: main.c globals.h

View File

@ -37,7 +37,7 @@ valid options include:
Predefine the symbol ``name'' to have the specified Predefine the symbol ``name'' to have the specified
value. If the value is not specified, then ``1'' is value. If the value is not specified, then ``1'' is
used. This is mostly of use for controlling conditional used. This is mostly of use for controlling conditional
compilaiton. compilation.
This option does *not* override existing `define This option does *not* override existing `define
directives in the source file. directives in the source file.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.46 2004/09/10 00:15:45 steve Exp $" #ident "$Id: lexor.lex,v 1.46.2.1 2007/05/25 18:35:45 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -93,7 +93,7 @@ static void ifdef_enter(void)
cur = (struct ifdef_stack_t*) cur = (struct ifdef_stack_t*)
calloc(1, sizeof(struct ifdef_stack_t)); calloc(1, sizeof(struct ifdef_stack_t));
cur->path = strdup(istack->path); if (istack->path) cur->path = strdup(istack->path);
cur->lineno = istack->lineno; cur->lineno = istack->lineno;
cur->next = ifdef_stack; cur->next = ifdef_stack;
ifdef_stack = cur; ifdef_stack = cur;
@ -108,7 +108,10 @@ static void ifdef_leave(void)
cur = ifdef_stack; cur = ifdef_stack;
ifdef_stack = cur->next; ifdef_stack = cur->next;
if (strcmp(istack->path,cur->path) != 0) { /* If either path is from a non-file context e.g.(macro expansion)
* 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: " fprintf(stderr, "%s:%u: warning: "
"This `endif matches an ifdef in another file.\n", "This `endif matches an ifdef in another file.\n",
istack->path, istack->lineno); istack->path, istack->lineno);
@ -142,6 +145,7 @@ static int comment_enter = 0;
%x PPINCLUDE %x PPINCLUDE
%x PPDEFINE %x PPDEFINE
%x CCOMMENT %x CCOMMENT
%x IFCCOMMENT
%x PCOMENT %x PCOMENT
%x CSTRING %x CSTRING
%x ERROR_LINE %x ERROR_LINE
@ -309,11 +313,37 @@ W [ \t\b\f]+
yy_push_state(IFDEF_SUPR); yy_push_state(IFDEF_SUPR);
} }
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
BEGIN(IFDEF_SUPR);
}
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char*name = strchr(yytext, '`');
assert(name);
name += 6;
name += strspn(name, " \t\b\f");
if (is_defined(name)) {
BEGIN(IFDEF_TRUE);
} else {
BEGIN(IFDEF_FALSE);
}
}
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); } <IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); } <IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else { } <IFDEF_SUPR>`else { }
<IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* { } <IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* { }
<IFDEF_FALSE,IFDEF_SUPR>"/*" { comment_enter = YY_START; BEGIN(IFCCOMMENT); }
<IFCCOMMENT>[^\r\n] { }
<IFCCOMMENT>\n\r { istack->lineno += 1; }
<IFCCOMMENT>\r\n { istack->lineno += 1; }
<IFCCOMMENT>\n { istack->lineno += 1; }
<IFCCOMMENT>\r { istack->lineno += 1; }
<IFCCOMMENT>"*/" { BEGIN(comment_enter); }
<IFDEF_FALSE,IFDEF_SUPR>[^\r\n] { } <IFDEF_FALSE,IFDEF_SUPR>[^\r\n] { }
<IFDEF_FALSE,IFDEF_SUPR>\n\r { istack->lineno += 1; fputc('\n', yyout); } <IFDEF_FALSE,IFDEF_SUPR>\n\r { istack->lineno += 1; fputc('\n', yyout); }
<IFDEF_FALSE,IFDEF_SUPR>\r\n { istack->lineno += 1; fputc('\n', yyout); } <IFDEF_FALSE,IFDEF_SUPR>\r\n { istack->lineno += 1; fputc('\n', yyout); }
@ -322,8 +352,44 @@ W [ \t\b\f]+
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); } <IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
`ifdef {
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`ifndef {
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`elsif {
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`else {
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`endif {
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
/* This pattern notices macros and arranges for them to be replaced. */ /* This pattern notices macros and arranges for them to be replaced. */
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); } `[a-zA-Z_][a-zA-Z0-9_$]* { def_match(); }
/* Any text that is not a directive just gets passed through to the /* Any text that is not a directive just gets passed through to the
output. Very easy. */ output. Very easy. */
@ -854,6 +920,7 @@ void reset_lexor(FILE*out, char*paths[])
isp->path = strdup(paths[0]); isp->path = strdup(paths[0]);
isp->file = fopen(paths[0], "r"); isp->file = fopen(paths[0], "r");
isp->str = 0; isp->str = 0;
isp->lineno = 0;
if (isp->file == 0) { if (isp->file == 0) {
perror(paths[0]); perror(paths[0]);
exit(1); exit(1);
@ -876,8 +943,10 @@ void reset_lexor(FILE*out, char*paths[])
for (idx = 1 ; paths[idx] ; idx += 1) { for (idx = 1 ; paths[idx] ; idx += 1) {
isp = malloc(sizeof(struct include_stack_t)); isp = malloc(sizeof(struct include_stack_t));
isp->path = strdup(paths[idx]); isp->path = strdup(paths[idx]);
isp->file = 0;
isp->str = 0; isp->str = 0;
isp->next = 0; isp->next = 0;
isp->lineno = 0;
if (tail) if (tail)
tail->next = isp; tail->next = isp;
else else

View File

@ -17,10 +17,11 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.20 2004/09/10 00:15:45 steve Exp $" #ident "$Id: main.c,v 1.20.2.1 2006/06/27 01:37:14 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include "version.h"
const char NOTICE[] = const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n" " This program is free software; you can redistribute it and/or modify\n"
@ -38,8 +39,6 @@ const char NOTICE[] =
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n" " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
; ;
const char VERSION[] = "$Name: $ $State: Exp $";
# include <stdio.h> # include <stdio.h>
# include <stdlib.h> # include <stdlib.h>
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
@ -126,8 +125,8 @@ int main(int argc, char*argv[])
int opt, idx; int opt, idx;
const char*flist_path = 0; const char*flist_path = 0;
unsigned flag_errors = 0; unsigned flag_errors = 0;
char*out_path = 0; const char*out_path = 0;
char *dep_path = NULL; const char*dep_path = NULL;
FILE*out; FILE*out;
/* Define preprocessor keywords that I plan to just pass. */ /* Define preprocessor keywords that I plan to just pass. */
@ -213,7 +212,7 @@ int main(int argc, char*argv[])
break; break;
case 'v': case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n", fprintf(stderr, "Icarus Verilog Preprocessor version %s\n\n",
VERSION); VERSION);
fprintf(stderr, "%s\n", COPYRIGHT); fprintf(stderr, "%s\n", COPYRIGHT);
fputs(NOTICE, stderr); fputs(NOTICE, stderr);
@ -290,6 +289,9 @@ int main(int argc, char*argv[])
/* /*
* $Log: main.c,v $ * $Log: main.c,v $
* Revision 1.20.2.1 2006/06/27 01:37:14 steve
* Fix const/non-const warnings.
*
* Revision 1.20 2004/09/10 00:15:45 steve * Revision 1.20 2004/09/10 00:15:45 steve
* Remove bad casts. * Remove bad casts.
* *

View File

@ -1,4 +1,6 @@
%option never-interactive
%{ %{
/* /*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
@ -19,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.86 2004/06/13 04:56:54 steve Exp $" #ident "$Id: lexor.lex,v 1.86.2.4 2007/02/09 05:29:24 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -90,6 +92,7 @@ static int dec_buf_div2(char *buf);
static void process_timescale(const char*txt); static void process_timescale(const char*txt);
static int comment_enter; static int comment_enter;
static bool in_module = false;
%} %}
%x CCOMMENT %x CCOMMENT
@ -99,6 +102,7 @@ static int comment_enter;
%s UDPTABLE %s UDPTABLE
%x PPTIMESCALE %x PPTIMESCALE
%x PPDEFAULT_NETTYPE %x PPDEFAULT_NETTYPE
%s EDGES
W [ \t\b\f\r]+ W [ \t\b\f\r]+
@ -156,11 +160,12 @@ W [ \t\b\f\r]+
with "*" and return that. */ with "*" and return that. */
"(*"{W}*")" { return '*'; } "(*"{W}*")" { return '*'; }
<EDGES>"]" { BEGIN(0); return yytext[0]; }
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; } [}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
\" { BEGIN(CSTRING); } \" { BEGIN(CSTRING); }
<CSTRING>\\\" { yymore(); } <CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
<CSTRING>\n { BEGIN(0); <CSTRING>\n { BEGIN(0);
yylval.text = strdup(yytext); yylval.text = strdup(yytext);
VLerror(yylloc, "Missing close quote of string."); VLerror(yylloc, "Missing close quote of string.");
@ -179,6 +184,8 @@ W [ \t\b\f\r]+
<UDPTABLE>\(01\) { return 'r'; } <UDPTABLE>\(01\) { return 'r'; }
<UDPTABLE>\(0[xX]\) { return 'Q'; } <UDPTABLE>\(0[xX]\) { return 'Q'; }
<UDPTABLE>\(b[xX]\) { return 'q'; } <UDPTABLE>\(b[xX]\) { return 'q'; }
<UDPTABLE>\(b0\) { return 'f'; /* b0 is 10|00, but only 10 is meaningful */}
<UDPTABLE>\(b1\) { return 'r'; /* b1 is 11|01, but only 01 is meaningful */}
<UDPTABLE>\(0\?\) { return 'P'; } <UDPTABLE>\(0\?\) { return 'P'; }
<UDPTABLE>\(10\) { return 'f'; } <UDPTABLE>\(10\) { return 'f'; }
<UDPTABLE>\(1[xX]\) { return 'M'; } <UDPTABLE>\(1[xX]\) { return 'M'; }
@ -196,14 +203,42 @@ W [ \t\b\f\r]+
<UDPTABLE>[pP] { return 'p'; } <UDPTABLE>[pP] { return 'p'; }
<UDPTABLE>[01\?\*\-] { return yytext[0]; } <UDPTABLE>[01\?\*\-] { return yytext[0]; }
<EDGES>"01" { return K_edge_descriptor; }
<EDGES>"0x" { return K_edge_descriptor; }
<EDGES>"0z" { return K_edge_descriptor; }
<EDGES>"10" { return K_edge_descriptor; }
<EDGES>"1x" { return K_edge_descriptor; }
<EDGES>"1z" { return K_edge_descriptor; }
<EDGES>"x0" { return K_edge_descriptor; }
<EDGES>"x1" { return K_edge_descriptor; }
<EDGES>"z0" { return K_edge_descriptor; }
<EDGES>"z1" { return K_edge_descriptor; }
[a-zA-Z_][a-zA-Z0-9$_]* { [a-zA-Z_][a-zA-Z0-9$_]* {
int rc = lexor_keyword_code(yytext, yyleng); int rc = lexor_keyword_code(yytext, yyleng);
if (rc == IDENTIFIER) { switch (rc) {
case IDENTIFIER:
yylval.text = strdup(yytext); yylval.text = strdup(yytext);
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0) if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
rc = PATHPULSE_IDENTIFIER; rc = PATHPULSE_IDENTIFIER;
} else { break;
case K_edge:
BEGIN(EDGES);
break;
case K_module:
case K_macromodule:
in_module = true;
break;
case K_endmodule:
in_module = false;
break;
default:
yylval.text = 0; yylval.text = 0;
break;
} }
return rc; return rc;
@ -262,6 +297,12 @@ W [ \t\b\f\r]+
^{W}?`timescale { BEGIN(PPTIMESCALE); } ^{W}?`timescale { BEGIN(PPTIMESCALE); }
<PPTIMESCALE>.* { process_timescale(yytext); } <PPTIMESCALE>.* { process_timescale(yytext); }
<PPTIMESCALE>\n { <PPTIMESCALE>\n {
if (in_module) {
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
"`timescale directive can not be inside a module "
"definition." << endl;
error_count += 1;
}
yylloc.first_line += 1; yylloc.first_line += 1;
BEGIN(0); } BEGIN(0); }
@ -276,10 +317,10 @@ W [ \t\b\f\r]+
^{W}?`disable_portfaults{W}?.* { } ^{W}?`disable_portfaults{W}?.* { }
^{W}?`enable_portfaults{W}?.* { } ^{W}?`enable_portfaults{W}?.* { }
^{W}?`endcelldefine{W}?.* { } ^{W}?`endcelldefine{W}?.* { }
^{W}?`endprotect{W}?.* { } `endprotect { }
^{W}?`nosuppress_faults{W}?.* { } ^{W}?`nosuppress_faults{W}?.* { }
^{W}?`nounconnected_drive{W}?.* { } ^{W}?`nounconnected_drive{W}?.* { }
^{W}?`protect{W}?.* { } `protect { }
^{W}?`resetall{W}?.* { } ^{W}?`resetall{W}?.* { }
^{W}?`suppress_faults{W}?.* { } ^{W}?`suppress_faults{W}?.* { }
^{W}?`unconnected_drive{W}?.* { } ^{W}?`unconnected_drive{W}?.* { }

View File

@ -44,6 +44,7 @@ function, K_function
highz0, K_highz0 highz0, K_highz0
highz1, K_highz1 highz1, K_highz1
if, K_if if, K_if
ifnone, K_ifnone
initial, K_initial initial, K_initial
inout, K_inout inout, K_inout
input, K_input input, K_input

View File

@ -16,11 +16,12 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.34 2004/10/04 01:10:07 steve Exp $" #ident "$Id: Makefile.in,v 1.34.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -93,17 +94,18 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32) install:: all installdirs $(libdir64)/libveriuser$(suffix).a $(INSTALL32)
$(libdir64)/libveriuser.a: ./libveriuser.a $(libdir64)/libveriuser$(suffix).a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(libdir64)/libveriuser.a $(INSTALL_DATA) ./libveriuser.a $(libdir64)/libveriuser$(suffix).a
installdirs: mkinstalldirs installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(libdir64) $(srcdir)/mkinstalldirs $(includedir) $(libdir64)
uninstall:: uninstall::
rm -f $(libdir64)/libveriuser.a rm -f $(libdir64)/libveriuser$(suffix).a
ifeq (@enable_vvp32@,yes) ifeq (@enable_vvp32@,yes)
all32: bin32 bin32/libveriuser.a all32: bin32 bin32/libveriuser.a
@ -122,10 +124,13 @@ bin32/libveriuser.a: bin32/libveriuser.o
ar cvq $@ bin32/libveriuser.o ar cvq $@ bin32/libveriuser.o
$(RANLIB) $@ $(RANLIB) $@
install32: $(libdir)/libveriuser.a install32: $(libdir)/libveriuser$(suffix).a
$(libdir)/libveriuser.a: bin32/libveriuser.a $(libdir)/libveriuser$(suffix).a: bin32/libveriuser.a
$(INSTALL_DATA) bin32/libveriuser.a $(libdir)/libveriuser.a $(INSTALL_DATA) bin32/libveriuser.a $(libdir)/libveriuser$(suffix).a
uninstall::
rm -f $(DESTDIR)$(libdir)/libveriuser$(suffix).a
-include $(patsubst bin32/%.o, bin32/%.d, $(addprefix bin32/,$O)) -include $(patsubst bin32/%.o, bin32/%.d, $(addprefix bin32/,$O))
endif endif

View File

@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
/* trace */ /* trace */
if (pli_trace) { if (pli_trace) {
int *ip; PLI_INT32 *ip;
fprintf(pli_trace, "acc_next(%p <", type); fprintf(pli_trace, "acc_next(%p <", type);
for (ip = type; *ip; ip++) { for (ip = type; *ip; ip++) {
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip); fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);

View File

@ -1,6 +1,8 @@
AC_INIT(Makefile.in) AC_INIT(Makefile.in)
AC_CONFIG_HEADER(config.h) AC_CONFIG_HEADER(config.h)
AC_CANONICAL_HOST
AC_PROG_CC AC_PROG_CC
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_RANLIB AC_PROG_RANLIB
@ -12,6 +14,8 @@ AX_CPP_IDENT
#enable_vvp32=no #enable_vvp32=no
AC_SUBST(enable_vvp32) AC_SUBST(enable_vvp32)
AX_ENABLE_SUFFIX
AC_CHECK_HEADERS(malloc.h) AC_CHECK_HEADERS(malloc.h)
AC_CHECK_SIZEOF(unsigned long long) AC_CHECK_SIZEOF(unsigned long long)
@ -21,7 +25,7 @@ AC_CHECK_SIZEOF(unsigned)
# may modify CPPFLAGS and CFLAGS # may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects. # Compiler option for position independent code, needed when making shared objects.
AX_C_PICFLAG AX_C_PICFLAG
AC_SUBST(EXEEXT) AC_SUBST(EXEEXT)

View File

@ -44,9 +44,9 @@ typedef struct t_pli_data {
int paramvc; /* parameter number for misctf */ int paramvc; /* parameter number for misctf */
} s_pli_data, *p_pli_data; } s_pli_data, *p_pli_data;
static int compiletf(char *); static PLI_INT32 compiletf(char *);
static int calltf(char *); static PLI_INT32 calltf(char *);
static int callback(p_cb_data); static PLI_INT32 callback(p_cb_data);
/* /*
* Register veriusertfs routines/wrappers. Iterate over the tfcell * Register veriusertfs routines/wrappers. Iterate over the tfcell
@ -109,7 +109,7 @@ void veriusertfs_register_table(p_tfcell vtable)
tf_data.tfname = tf->tfname; tf_data.tfname = tf->tfname;
tf_data.compiletf = compiletf; tf_data.compiletf = compiletf;
tf_data.calltf = calltf; tf_data.calltf = calltf;
tf_data.sizetf = tf->sizetf; tf_data.sizetf = (PLI_INT32 (*)(char *))tf->sizetf;
tf_data.user_data = (char *)data; tf_data.user_data = (char *)data;
if (pli_trace) { if (pli_trace) {
@ -139,7 +139,7 @@ void veriusertfs_register_table(p_tfcell vtable)
* This function calls the veriusertfs checktf and sets up all the * This function calls the veriusertfs checktf and sets up all the
* callbacks misctf requires. * callbacks misctf requires.
*/ */
static int compiletf(char *data) static PLI_INT32 compiletf(char *data)
{ {
p_pli_data pli; p_pli_data pli;
p_tfcell tf; p_tfcell tf;
@ -221,7 +221,7 @@ static int compiletf(char *data)
/* /*
* This function is the wrapper for the veriusertfs calltf routine. * This function is the wrapper for the veriusertfs calltf routine.
*/ */
static int calltf(char *data) static PLI_INT32 calltf(char *data)
{ {
int rc = 0; int rc = 0;
p_pli_data pli; p_pli_data pli;
@ -249,7 +249,7 @@ static int calltf(char *data)
*/ */
extern int async_misctf_enable; extern int async_misctf_enable;
static int callback(p_cb_data data) static PLI_INT32 callback(p_cb_data data)
{ {
p_pli_data pli; p_pli_data pli;
p_tfcell tf; p_tfcell tf;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: load_module.cc,v 1.12 2003/06/05 04:31:09 steve Exp $" #ident "$Id: load_module.cc,v 1.12.2.1 2005/03/22 15:53:12 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -31,6 +31,8 @@
# include <dirent.h> # include <dirent.h>
# include <ctype.h> # include <ctype.h>
# include <assert.h> # include <assert.h>
# include <cstdlib>
# include <cstring>
/* /*
* The module library items are maps of key names to file name within * The module library items are maps of key names to file name within
@ -88,7 +90,7 @@ bool load_module(const char*type)
cerr << "Executing: " << cmdline << endl; cerr << "Executing: " << cmdline << endl;
pform_parse(path, file); pform_parse(path, file);
fclose(file); pclose(file);
free(cmdline); free(cmdline);
} else { } else {
@ -193,6 +195,9 @@ int build_library_index(const char*path, bool key_case_sensitive)
/* /*
* $Log: load_module.cc,v $ * $Log: load_module.cc,v $
* Revision 1.12.2.1 2005/03/22 15:53:12 steve
* popen must be matched by pclose.
*
* Revision 1.12 2003/06/05 04:31:09 steve * Revision 1.12 2003/06/05 04:31:09 steve
* INclude missing assert.h in load_module. * INclude missing assert.h in load_module.
* *

View File

@ -1,4 +1,11 @@
Icarus Verilog for Mac OS X
NOTE: Icarus Verilog version 0.8 is known to compile "out of the
box" on MacOSX 10.3. OSX 10.3 users need only the developer tools
included with new systems or available for free download from
Apple. Install Xcode and skip directly to step #3.
This file describes the procedure to build and install Icarus Verilog This file describes the procedure to build and install Icarus Verilog
on Mac OS X. I assume that you have experience with Unix and on Mac OS X. I assume that you have experience with Unix and
Terminal.app and a basic knowledge of how to download, compile and Terminal.app and a basic knowledge of how to download, compile and

41
main.cc
View File

@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.86 2004/10/04 01:10:53 steve Exp $" #ident "$Id: main.cc,v 1.86.2.3 2006/06/12 00:16:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -59,6 +59,7 @@ const char NOTICE[] =
# include "netlist.h" # include "netlist.h"
# include "target.h" # include "target.h"
# include "compiler.h" # include "compiler.h"
# include "version.h"
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H) #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt); extern "C" int getopt(int argc, char*argv[], const char*fmt);
@ -75,8 +76,6 @@ extern "C" const char*optarg;
/* Count errors detected in flag processing. */ /* Count errors detected in flag processing. */
unsigned flag_errors = 0; unsigned flag_errors = 0;
const char VERSION[] = "$Name: $";
const char*basedir = "."; const char*basedir = ".";
const char*target = "null"; const char*target = "null";
@ -103,6 +102,7 @@ FILE *depend_file = NULL;
bool warn_implicit = false; bool warn_implicit = false;
bool warn_timescale = false; bool warn_timescale = false;
bool warn_portbinding = false; bool warn_portbinding = false;
bool warn_unused = false;
bool error_implicit = false; bool error_implicit = false;
@ -112,6 +112,9 @@ bool error_implicit = false;
bool debug_scopes = false; bool debug_scopes = false;
bool debug_eval_tree = false; bool debug_eval_tree = false;
bool debug_elaborate = false; bool debug_elaborate = false;
bool debug_synth = false;
bool debug_cprop = false;
/* /*
* Verbose messages enabled. * Verbose messages enabled.
*/ */
@ -132,6 +135,11 @@ const bool CASE_SENSITIVE = false;
const bool CASE_SENSITIVE = true; const bool CASE_SENSITIVE = true;
#endif #endif
/*
* Are we doing synthesis?
*/
bool synthesis = false;
extern void cprop(Design*des); extern void cprop(Design*des);
extern void synth(Design*des); extern void synth(Design*des);
extern void synth2(Design*des); extern void synth2(Design*des);
@ -314,6 +322,12 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(cp,"elaborate") == 0) { } else if (strcmp(cp,"elaborate") == 0) {
debug_elaborate = true; debug_elaborate = true;
cerr << "debug: Enable elaborate debug" << endl; cerr << "debug: Enable elaborate debug" << endl;
} else if (strcmp(cp,"synth") == 0) {
debug_synth = true;
cerr << "debug: Enable synthesis debug" << endl;
} else if (strcmp(cp,"cprop") == 0) {
debug_cprop = true;
cerr << "debug: Enable cprop debug" << endl;
} else { } else {
} }
@ -325,6 +339,9 @@ static void read_iconfig_file(const char*ipath)
parm_to_flagmap(parm); parm_to_flagmap(parm);
} else if (strcmp(buf,"functor") == 0) { } else if (strcmp(buf,"functor") == 0) {
if (strncmp(cp, "synth", 5) == 0) {
synthesis = true; // We are doing synthesis.
}
net_func tmp = name_to_net_func(cp); net_func tmp = name_to_net_func(cp);
if (tmp == 0) { if (tmp == 0) {
cerr << "No such design transform function ``" cerr << "No such design transform function ``"
@ -376,6 +393,9 @@ static void read_iconfig_file(const char*ipath)
case 't': case 't':
warn_timescale = true; warn_timescale = true;
break; break;
case 'u':
warn_unused = true;
break;
default: default:
break; break;
} }
@ -483,7 +503,7 @@ int main(int argc, char*argv[])
# endif # endif
break; break;
case 'V': case 'V':
cout << "Icarus Verilog version " << VERSION << endl; cout << "Icarus Verilog version " << VERSION << endl << endl;
cout << COPYRIGHT << endl; cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl; cout << endl << NOTICE << endl;
return 0; return 0;
@ -496,8 +516,8 @@ int main(int argc, char*argv[])
return flag_errors; return flag_errors;
if (help_flag) { if (help_flag) {
cout << "Icarus Verilog version " << VERSION << endl << cout << "Icarus Verilog version " << VERSION << endl << endl <<
"usage: ivl <options> <file>\n" "Usage: ivl <options> <file>\n"
"options:\n" "options:\n"
"\t-C <name> Config file from driver.\n" "\t-C <name> Config file from driver.\n"
"\t-h Print usage information, and exit.\n" "\t-h Print usage information, and exit.\n"
@ -744,6 +764,15 @@ int main(int argc, char*argv[])
/* /*
* $Log: main.cc,v $ * $Log: main.cc,v $
* Revision 1.86.2.3 2006/06/12 00:16:53 steve
* Add support for -Wunused warnings.
*
* Revision 1.86.2.2 2006/04/23 04:25:45 steve
* Add cprop debugging.
*
* Revision 1.86.2.1 2006/04/01 01:37:24 steve
* Add synth debug flag
*
* Revision 1.86 2004/10/04 01:10:53 steve * Revision 1.86 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

217
mingw.txt
View File

@ -2,7 +2,7 @@
MINGW PORT OF ICARUS VERILOG MINGW PORT OF ICARUS VERILOG
Copyright 2003 Stephen Williams <steve@icarus.com> Copyright 2006 Stephen Williams <steve@icarus.com>
Icarus Verilog source can be compiled with the mingw C/C++ compilers Icarus Verilog source can be compiled with the mingw C/C++ compilers
@ -12,13 +12,13 @@ or without Cygwin, so this is the preferred Windows distribution form.
The configure scripts automatically detect that the compilers in use The configure scripts automatically detect that the compilers in use
are the mingw compilers and will configure the Makefiles appropriately. are the mingw compilers and will configure the Makefiles appropriately.
However, the mingw tools do not include all the other tools around the The mingw patch doesn't contain tools beyond the compiler, but there
compiler, including the shell interpreter for the configure script, is the "msys" package that the makers of Mingw publish that has enough
bison, flex, gperf, etc. Therefore, you still need Cygwin to compile extra tools to get most everything else working. There are a few extra
Icarus Verilog, even if you don't need the Cygwin compilers. There are packages needed beyond mingw and msys, and the following instructions
also a few precompiled library prerequisites that you need. explain how to get them and install them.
* Some Preliminary Comments * Some Preliminary Comments -- PLEASE READ ME --
The Windows port of Icarus Verilog is the most difficult of all the The Windows port of Icarus Verilog is the most difficult of all the
ports. The Windows system off the shelf is completely stripped, devoid ports. The Windows system off the shelf is completely stripped, devoid
@ -26,7 +26,15 @@ of any support for software development. Everything needed to compile
Icarus Verilog must be collected from various sources and stitched Icarus Verilog must be collected from various sources and stitched
together by hand. Normal human beings with a basic understanding of together by hand. Normal human beings with a basic understanding of
software development can do this, but some patience (and access to the software development can do this, but some patience (and access to the
Internet) is required. You may choose to print these instructions. 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. I have no plans to intentionally support MSVC++ compilation. Don't ask.
@ -36,13 +44,15 @@ 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 where each can be found. In most cases, the specific version is not
critical, but these are the versions I use. critical, but these are the versions I use.
Cygwin <http://cygwin.com> msys-1.0 <http://www.mingw/org>
Mingw32-2.0.0 <http://www.mingw.org> msysDTK-1.0 <http://www.mingw.org>
Mingw32-5.x <http://www.mingw.org>
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net> readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net> bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net> zlib-1.2.3 <http://gnuwin32.sourceforge.net>
bzip2-1.0.2-lib.zip <http://gnuwin32.sourceforge.net> gperf-3.0.1 <http://gnuwin32.sourceforge.net>
zlib-1.1.4-lib.zip <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 The above table lists the packages required. It is convenient to
install them in the above order. Many of these packages are also install them in the above order. Many of these packages are also
@ -55,59 +65,38 @@ installation of Icarus Verilog is complete. These are only needed to
build the compiler. The Mingw32 package can be used to compile VPI build the compiler. The Mingw32 package can be used to compile VPI
modules if you choose. modules if you choose.
* Install Cygwin * Install MSYS and msysDTK
So, step 1 is "Download and Install Cygwin." See the web page The msys package is available from the mingw download site. This is
http://www.cygwin.com for instructions and the files to do not the compiler but a collection of *nix tools ported to Windows and
this. Cygwin *is* a kool package, and is worth having anyhow. There is wrapped in a convenient installer. The msys package is all the various
a convenient setup program that you download first. You execute the basic tools (shells, file utils, etc) and the msysDTK is extra
setup program, and that prompts you to select the package you want. developer tools other then the compiler.
You need in particular the Cygwin base, bison (see notes) flex, make Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
and gperf. If you are compiling from CVS, you also need cvs, rcs and self-installing packages. Install msys first, and then msysDTC. Most
automake packages. You will also need tar and gunzip, but these are likely, you want to install them in c:/msys. (The msysDTK is installed
hard to not install. I recommend installing the "which" package as in the same location, as it is an add-on.)
well. Beyond the basics, be sure to install these Cygwin packages:
bison (*not* 1.875. See Notes.) This install should be easy and reliable.
flex
ghostscript (makes the documentation)
gperf
gzip
make
strip
tar (tar and gunzip for unpacking the source)
unzip (For unpacking zip compressed packages.)
which
NOTES: The installation will leave an "msys" icon on your desktop and in the
bison-1.875 is broken, it generates invalid C/C++ code. You mingw sub-menu of your Start menu. This icon brings up a shell window
don't want that version for anything you do. If you have that (a command line) that has paths all set up for executing msys and
version (use "bison -V" to check the version) then use the mingw commands. This is what you will want to use while executing
Cygwin setup program to get a different version. I've downgraded commands below.
to 1.75 and couldn't be happier. In fact, a whole host of insane
bison bugs can be avoided that way.
There is a mingw32 runtime package included in the Cygwin
distribution. You do *not* need that, as you will be getting
everything from the mingw32 distribution itself.
Other then the install of mingw32, most of the remaining steps are
best done in a Cygwin window. When you installed Cygwin, a start menu
entry was created to allow you to start up the Cygwin window. I'll use
the string "$ " to represent a command prompt in this window, because
that is the usual bash prompt.
* Install Mingw32 * Install Mingw32
The obvious step 2, then, is install the mingw compilers. These can be The obvious step 2, then, is install the mingw compilers. These can be
found at the web page <http://www.mingw.org>. The Mingw-2.x.x version found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
comes prepackaged in a convenient, Windows style, installer. I is a convenient remote installer. Download this program and run
recommend you download this package instead of picking and choosing it. The installer will ask wich components you want to install. You
bits. 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 When I install Mingw32 (using the installer) I typically set a
destination directory of d:\mingw-2.0.0 or the like. You will be using destination directory of d:\mingw or the like. You will be using
that path later. that path later.
NOTES: NOTES:
@ -115,6 +104,10 @@ that path later.
need Mingw32, even if you are using a precompiled binary. VPI need Mingw32, even if you are using a precompiled binary. VPI
modules only require Mingw32, and none of the other libraries. 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 Mingw32 Packages * Install Mingw32 Packages
There is a collection of precompiled libraries and add-on packages There is a collection of precompiled libraries and add-on packages
@ -123,86 +116,94 @@ with simplified Windows installers, but they are pretty easy to
install by hand. Icarus Verilog uses the readline-4.2 package from install by hand. Icarus Verilog uses the readline-4.2 package from
that collection. that collection.
Since I installed Mingw32 in d:\mingw-2.0.0, I also created a Since I installed Mingw32 in c:\mingw, I also created a
Mingw-packages directory called d:\mingw-packages. The install, then, Mingw-packages directory called c:\mingw-packages. The install, then,
is as easy as this: is as easy as this:
<cygwin shell> <msys shell>
$ cd d:/mingw-packages $ cd c:/mingw-packages
$ unzip readline-4.2-20010727.zip $ unzip readline-4.2-20010727.zip
[lots of inflating...] [lots of inflating...]
There is no need to adjust your execution path for this package as we
are only using a library out of here. However, do remember the
directory name, as you will need it later.
Done. On to the next packages. Done. On to the next packages.
* Install GnuWin32 Packages * Install GnuWin32 Packages
The GnuWin32 project is a collections of open source programs and The GnuWin32 project is a collections of open source programs and
libraries ported to Windows. These also work well with the Mingw libraries ported to Windows. These also work well with the Mingw
compiler, and in fact Icarus Verilog uses a few libraries from this compiler, and in fact Icarus Verilog uses a few pieces from this
collection. collection.
You will need these gnuwin32 packages to compile Icarus Verilog: You will need these gnuwin32 packages to compile Icarus Verilog:
<http://gnuwin32.sourceforge.net> <http://gnuwin32.sourceforge.net>
bzip2-1.0.2-lib.zip bzip2-1.0.3.exe
bzip2-1.0.2-bin.zip zlib-1.2.3.exe
zlib-1.1.4-lib.zip gperf-3.0.1.exe
zlib-1.1.4-bin.zip bison-2.1.exe
flex-2.5.4a.exe
I suggest creating a common directory for holding all your gnuwin32 I suggest creating a common directory for holding all your gnuwin32
packages. I use D:\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 programes, then execute
the downloaded .exe files to invoke the installer. Install into the
c:\gunwin32 directory.
After downloading these packages, put the .zip files in your gnuwin32 NOTES:
directory and install them like so: You need the binaries and the developer files, but you do not
need the source to these packages. The installer gives you the
choice.
<cygwin shell> After you are done installing the gnuwin32 tools, you should add the
$ cd d:/gnuwin32 c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
$ unzip bzip2-1.0.2-bin.zip your Windows path. The msys shell will pick up your Windows path.
[lots of inflating...]
$ unzip bzip2-1.0.2-lib.zip
[lots of inflating...]
$ unzip zlib-1.1.4-bin.zip
[lots of inflating...]
$ unzip zlib-1.1.4-lib.zip
[lots of inflating...]
Done.
* Unpack Icarus Verilog source * Unpack Icarus Verilog source
Unpack the compressed tar file (.tar.gz) of the source with a command Unpack the compressed tar file (.tar.gz) of the source with a command
like this: like this:
$ gunzip -d verilog-20030303.tar.gz | tar xvf - $ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
This will create a directory "verilog-20030303" that contains all the This will create a directory "verilog-xxxxxxxx" that contains all the
source for Icarus Verilog. Descend into that directory, as that is source for Icarus Verilog. Descend into that directory, as that is
where we will work from now on. where we will work from now on.
$ cd verilog-20030303 $ cd verilog-xxxxxxxx
NOTE: NOTES:
The exact name of the file will vary according to the The exact name of the file will vary according to the
snapshot. The 20030303 name is only an example. snapshot. The 20030303 name is only an example.
* Select the mingw compilers Unpack the source into a directory that has no spaces. The
makefiles included in the source get confused by white space in
directory names.
In your cygwin window, if you type "which c++" you might get the * Preconfigure Icarus Verilog (Not normally needed)
response path "/usr/bin/c++" which is the cygwin compiler. This is not
the one we want to use, however. Tell the shell where the mingw
compilers are by setting the search path like so:
$ PATH=/cygdrive/d/mingw-2.0.0/bin:$PATH 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 CVS, or you are using an existing
source tree that you've patched to cause configure.in files to change.
This assumes that you installed mingw in D:\mingw-2.0.0. The actual NOTE: If you are building from a fresh, bundled source tree that
programs are in the bin directory under the root. After this command, you downloaded from an FTP site, then SKIP THIS STEP. Go on to
check that you are now getting the right compilers with this "which" the "Configure Icarus Verilog" step below.
command:
$ which c++ First, remove any autom4te.cache directories that may exist in your
/cygdrive/d/mingw-2.0.0/bin/c++ source tree. These can make a mess of autoconf runs. Then, generate
configure scripts with this command:
Good! $ 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 * Configure Icarus Verilog
@ -215,10 +216,10 @@ without white space.
Now, configure the source to make the makefiles and configuration Now, configure the source to make the makefiles and configuration
details. Run these commands: details. Run these commands:
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include" $ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include" $ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
$ export CPPFLAGS LDFLAGS $ export CPPFLAGS LDFLAGS
$ ./configure --prefix=d:/iverilog $ ./configure --prefix=c:/iverilog
NOTES: NOTES:
The CPPFLAGS and LDFLAGS variables tell configure where The CPPFLAGS and LDFLAGS variables tell configure where
@ -267,10 +268,10 @@ directory you chose) and away you go.
You may find that you need to put some of the prerequisite DLLs into You may find that you need to put some of the prerequisite DLLs into
the d:\iverilog\bin directory. These include: the d:\iverilog\bin directory. These include:
d:\mingw-2.0.0\bin\mingw10.dll c:\mingw\bin\mingw10.dll
d:\mingw-packages\bin\libreadline.dll c:\mingw-packages\bin\libreadline.dll
d:\gnuwin32\bin\bzip2.dll c:\gnuwin32\bin\bzip2.dll
d:\gnuwin32\bin\zlib.dll c:\gnuwin32\bin\zlib.dll
If you already have these in your Windows path (i.e. your system32 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) then you do not need to copy them into the iverilog
@ -279,14 +280,14 @@ files.
* Running Icarus Verilog * Running Icarus Verilog
Finally, put the D:\iverilog\bin directory in your Windows path, and 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 you should be able to run the iverilog and vvp commands to your
heart's content. heart's content.
Currently, the iverilog.exe uses the path to itself to locate the Currently, the iverilog.exe uses the path to itself to locate the
libraries and modules associated with itself. In other words, if you libraries and modules associated with itself. In other words, if you
execute the D:\iverilog\bin\iverilog.exe program, it will locate its execute the C:\iverilog\bin\iverilog.exe program, it will locate its
subparts in the D:\iverilog directory and subdirectories below subparts in the C:\iverilog directory and subdirectories below
that. This means you can move the Icarus Verilog installation by that. This means you can move the Icarus Verilog installation by
simply moving the root directory and all its contents. simply moving the root directory and all its contents.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.18 2004/08/28 15:08:31 steve Exp $" #ident "$Id: net_assign.cc,v 1.18.2.3 2006/05/02 02:00:15 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -45,6 +45,7 @@ NetAssign_::NetAssign_(NetNet*s)
lwid_ = sig_->pin_count(); lwid_ = sig_->pin_count();
sig_->incr_lref(); sig_->incr_lref();
more = 0; more = 0;
mem_lref_ = false;
} }
NetAssign_::NetAssign_(NetMemory*s) NetAssign_::NetAssign_(NetMemory*s)
@ -53,6 +54,7 @@ NetAssign_::NetAssign_(NetMemory*s)
loff_ = 0; loff_ = 0;
lwid_ = mem_->width(); lwid_ = mem_->width();
more = 0; more = 0;
mem_lref_ = false;
} }
NetAssign_::NetAssign_(NetVariable*s) NetAssign_::NetAssign_(NetVariable*s)
@ -61,6 +63,7 @@ NetAssign_::NetAssign_(NetVariable*s)
loff_ = 0; loff_ = 0;
lwid_ = 0; lwid_ = 0;
more = 0; more = 0;
mem_lref_ = false;
} }
NetAssign_::~NetAssign_() NetAssign_::~NetAssign_()
@ -71,6 +74,14 @@ NetAssign_::~NetAssign_()
sig_->type(NetNet::WIRE); sig_->type(NetNet::WIRE);
} }
if (mem_) {
NetNet*exp = mem_->reg_from_explode();
if (exp && mem_lref_) {
exp->decr_lref();
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
exp->type(NetNet::WIRE);
}
}
assert( more == 0 ); assert( more == 0 );
if (bmux_) delete bmux_; if (bmux_) delete bmux_;
} }
@ -111,7 +122,10 @@ perm_string NetAssign_::name() const
NetNet* NetAssign_::sig() const NetNet* NetAssign_::sig() const
{ {
return sig_; if (mem_)
return 0;
else
return sig_;
} }
NetMemory* NetAssign_::mem() const NetMemory* NetAssign_::mem() const
@ -124,6 +138,16 @@ NetVariable* NetAssign_::var() const
return var_; return var_;
} }
void NetAssign_::incr_mem_lref()
{
if (! mem_lref_) {
assert(mem_);
NetNet*exp = mem_->reg_from_explode();
assert(exp);
exp->incr_lref();
mem_lref_ = true;
}
}
void NetAssign_::set_part(unsigned lo, unsigned lw) void NetAssign_::set_part(unsigned lo, unsigned lw)
{ {
@ -261,6 +285,15 @@ NetAssignNB::~NetAssignNB()
/* /*
* $Log: net_assign.cc,v $ * $Log: net_assign.cc,v $
* Revision 1.18.2.3 2006/05/02 02:00:15 steve
* Fix uninitialized mem_lref_ member.
*
* Revision 1.18.2.2 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.18 2004/08/28 15:08:31 steve * Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing. * Do not change reg to wire in NetAssign_ unless synthesizing.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_design.cc,v 1.45 2004/10/04 01:10:54 steve Exp $" #ident "$Id: net_design.cc,v 1.45.2.1 2006/10/04 00:34:45 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -33,6 +33,7 @@
# include "util.h" # include "util.h"
# include "compiler.h" # include "compiler.h"
# include <sstream> # include <sstream>
# include <cstring>
Design:: Design() Design:: Design()
: errors(0), nodes_(0), procs_(0), lcounter_(0) : errors(0), nodes_(0), procs_(0), lcounter_(0)
@ -279,7 +280,7 @@ void NetScope::run_defparams(Design*des)
continue; continue;
} }
bool flag = targ_scope->replace_parameter(perm_name, val); bool flag = targ_scope->replace_parameter(perm_name, val->dup_expr());
if (! flag) { if (! flag) {
cerr << val->get_line() << ": warning: parameter " cerr << val->get_line() << ": warning: parameter "
<< perm_name << " not found in " << perm_name << " not found in "
@ -396,6 +397,7 @@ void NetScope::evaluate_parameters(Design*des)
<< ": internal error: " << ": internal error: "
"unable to evaluate real parameter values: " << "unable to evaluate real parameter values: " <<
*expr << endl; *expr << endl;
cerr << "FYI: V0.8 cannot evaluate constant real expressions." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
} }
@ -422,10 +424,6 @@ void NetScope::evaluate_parameters(Design*des)
assert(nexpr); assert(nexpr);
delete expr; delete expr;
(*cur).second.expr = nexpr; (*cur).second.expr = nexpr;
// Set the signedness flag.
(*cur).second.expr
->cast_signed( (*cur).second.signed_flag );
} }
break; break;
@ -438,7 +436,9 @@ void NetScope::evaluate_parameters(Design*des)
} }
/* If the parameter has range information, then make /* If the parameter has range information, then make
sure the value is set right. */ sure the value is set right. Note that if the
parameter doesn't have an explicit range, then it
will get the signedness from the expression itself. */
if (range_flag) { if (range_flag) {
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb; unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1; wid += 1;
@ -618,6 +618,9 @@ void Design::delete_process(NetProcTop*top)
/* /*
* $Log: net_design.cc,v $ * $Log: net_design.cc,v $
* Revision 1.45.2.1 2006/10/04 00:34:45 steve
* Fix a dangling reference to NetEParam objects in defparams.
*
* Revision 1.45 2004/10/04 01:10:54 steve * Revision 1.45 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.14 2004/02/18 17:11:56 steve Exp $" #ident "$Id: net_link.cc,v 1.14.2.6 2006/08/23 04:09:14 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -27,6 +27,7 @@
# include "netlist.h" # include "netlist.h"
# include <sstream> # include <sstream>
# include <string> # include <string>
# include <cstring>
# include <typeinfo> # include <typeinfo>
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
# include <malloc.h> # include <malloc.h>
@ -40,30 +41,33 @@ void connect(Nexus*l, Link&r)
if (l == r.nexus_) if (l == r.nexus_)
return; return;
Nexus*tmp = r.nexus_; Nexus*tmp = r.nexus_;
while (Link*cur = tmp->list_) { while (Link*cur = tmp->list_) {
tmp->list_ = cur->next_; tmp->list_ = cur->next_;
cur->nexus_ = 0; cur->nexus_ = 0;
cur->next_ = 0; cur->next_ = 0;
cur->prev_ = 0;
l->relink(cur); l->relink(cur);
} }
l->driven_ = Nexus::NO_GUESS;
assert(tmp->list_ == 0);
delete tmp; delete tmp;
} }
void connect(Link&l, Link&r) void connect(Link&l, Link&r)
{ {
assert(&l != &r); assert(&l != &r);
connect(l.nexus_, r); if (r.is_linked() && !l.is_linked())
connect(r.nexus_, l);
else if (r.nexus_->list_len_ > l.nexus_->list_len_)
connect(r.nexus_, l);
else
connect(l.nexus_, r);
} }
Link::Link() Link::Link()
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx), : dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
inst_(0), next_(0), nexus_(0) inst_(0), next_(0), prev_(0), nexus_(0)
{ {
(new Nexus()) -> relink(this); (new Nexus()) -> relink(this);
} }
@ -215,6 +219,7 @@ Nexus::Nexus()
{ {
name_ = 0; name_ = 0;
list_ = 0; list_ = 0;
list_len_ = 0;
driven_ = NO_GUESS; driven_ = NO_GUESS;
t_cookie_ = 0; t_cookie_ = 0;
} }
@ -241,6 +246,18 @@ verinum::V Nexus::get_init() const
return verinum::Vz; return verinum::Vz;
} }
int Nexus::is_driven() const
{
int count = 0;
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() == Link::OUTPUT)
count += 1;
}
return count;
}
void Nexus::unlink(Link*that) void Nexus::unlink(Link*that)
{ {
if (name_) { if (name_) {
@ -254,22 +271,32 @@ void Nexus::unlink(Link*that)
driven_ = NO_GUESS; driven_ = NO_GUESS;
assert(that); assert(that);
assert(that->nexus_ == this);
if (list_ == that) { if (list_ == that) {
assert(that->prev_ == 0);
// Move the second item the front of the list.
list_ = that->next_; list_ = that->next_;
if (list_)
list_->prev_ = 0;
list_len_ -= 1;
// Clear the pointers for the link.
that->next_ = 0; that->next_ = 0;
that->prev_ = 0;
that->nexus_ = 0; that->nexus_ = 0;
return; return;
} }
Link*cur = list_;
while (cur->next_ != that) { Link*cur = that->prev_;
assert(cur->next_); assert(cur->nexus_ == this);
cur = cur->next_;
}
cur->next_ = that->next_; cur->next_ = that->next_;
if (cur->next_)
cur->next_->prev_ = cur;
that->nexus_ = 0; that->nexus_ = 0;
that->next_ = 0; that->next_ = 0;
that->prev_ = 0;
list_len_ -= 1;
} }
void Nexus::relink(Link*that) void Nexus::relink(Link*that)
@ -287,8 +314,13 @@ void Nexus::relink(Link*that)
assert(that->nexus_ == 0); assert(that->nexus_ == 0);
assert(that->next_ == 0); assert(that->next_ == 0);
that->next_ = list_; that->next_ = list_;
that->prev_ = 0;
if (that->next_)
that->next_->prev_ = that;
that->nexus_ = this; that->nexus_ = this;
list_ = that; list_ = that;
list_len_ += 1;
} }
Link* Nexus::first_nlink() Link* Nexus::first_nlink()
@ -360,8 +392,9 @@ const char* Nexus::name() const
obj->name() << " pin " << pin << "(" << obj->name() << " pin " << pin << "(" <<
lnk->get_name() << "<" << lnk->get_inst() << ">)" lnk->get_name() << "<" << lnk->get_inst() << ">)"
" type=" << typeid(*obj).name() << "?" << endl; " type=" << typeid(*obj).name() << "?" << endl;
return 0;
} }
assert(sig); assert(sig);
ostringstream tmp; ostringstream tmp;
tmp << sig->name(); tmp << sig->name();
@ -378,6 +411,7 @@ const char* Nexus::name() const
NexusSet::NexusSet() NexusSet::NexusSet()
{ {
items_ = 0; items_ = 0;
index_ = 0;
nitems_ = 0; nitems_ = 0;
} }
@ -386,8 +420,11 @@ NexusSet::~NexusSet()
if (nitems_ > 0) { if (nitems_ > 0) {
assert(items_ != 0); assert(items_ != 0);
delete[] items_; delete[] items_;
assert(index_ != 0);
delete[] index_;
} else { } else {
assert(items_ == 0); assert(items_ == 0);
assert(index_ == 0);
} }
} }
@ -396,25 +433,44 @@ unsigned NexusSet::count() const
return nitems_; return nitems_;
} }
/*
* Add the Nexus to the nexus set at the *end* of the array. This
* preserves order, which is used in a few cases by the
* synthesizer. But for efficiency, also create a sorted index.
*/
void NexusSet::add(Nexus*that) void NexusSet::add(Nexus*that)
{ {
/* Handle the special case that the set is empty. */
if (nitems_ == 0) { if (nitems_ == 0) {
assert(items_ == 0); assert(items_ == 0);
assert(index_ == 0);
items_ = (Nexus**)malloc(sizeof(Nexus*)); items_ = (Nexus**)malloc(sizeof(Nexus*));
items_[0] = that; items_[0] = that;
index_ = (unsigned*)malloc(sizeof(unsigned));
index_[0] = 0;
nitems_ = 1; nitems_ = 1;
return; return;
} }
unsigned ptr = bsearch_(that); unsigned ptr = bsearch_(that);
if ((ptr < nitems_) && (items_[ptr] == that)) if (ptr < nitems_ && items_[index_[ptr]] == that) {
assert(items_[index_[ptr]] == that);
return; return;
}
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*)); items_ = (Nexus**) realloc(items_, (nitems_+1) * sizeof(Nexus*));
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1) index_ = (unsigned*)realloc(index_, (nitems_+1) * sizeof(unsigned));
items_[idx] = items_[idx-1];
items_[nitems_] = that;
unsigned dest = nitems_;
for (unsigned idx = ptr ; idx < nitems_ ; idx += 1) {
unsigned tmp = index_[idx];
index_[idx] = dest;
dest = tmp;
}
index_[nitems_] = dest;
items_[ptr] = that;
nitems_ += 1; nitems_ += 1;
} }
@ -430,20 +486,31 @@ void NexusSet::rem(Nexus*that)
return; return;
unsigned ptr = bsearch_(that); unsigned ptr = bsearch_(that);
if ((ptr >= nitems_) || (items_[ptr] != that)) if (ptr >= nitems_ || items_[index_[ptr]] != that)
return; return;
if (nitems_ == 1) { if (nitems_ == 1) {
free(items_); free(items_);
free(index_);
items_ = 0; items_ = 0;
index_ = 0;
nitems_ = 0; nitems_ = 0;
return; return;
} }
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1) unsigned index_ptr = index_[ptr];
for (unsigned idx = index_ptr ; idx < (nitems_-1) ; idx += 1)
items_[idx] = items_[idx+1]; items_[idx] = items_[idx+1];
items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*)); for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
index_[idx] = index_[idx+1];
for (unsigned idx = 0 ; idx < (nitems_-1) ; idx += 1)
if (index_[idx] > index_ptr)
index_[idx] -= 1;
items_ = (Nexus**) realloc(items_, (nitems_-1) * sizeof(Nexus*));
index_ = (unsigned*)realloc(index_, (nitems_-1) * sizeof(unsigned));
nitems_ -= 1; nitems_ -= 1;
} }
@ -459,16 +526,37 @@ Nexus* NexusSet::operator[] (unsigned idx) const
return items_[idx]; return items_[idx];
} }
/*
* This method uses binary search to locate the item in the list of
* nexus pointers. If the item is in the set, then this method returns
* the index where it exists in the *index* array. If the item is not
* in the set, the index points to where in the array the item should go.
*/
unsigned NexusSet::bsearch_(Nexus*that) const unsigned NexusSet::bsearch_(Nexus*that) const
{ {
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
if (items_[idx] < that)
continue;
return idx; unsigned low = 0, hig = nitems_;
while (low < hig) {
unsigned mid = (low + hig) / 2;
if (mid == hig) mid -= 1;
assert(mid >= low);
assert(mid < hig);
if (items_[index_[mid]] == that) {
return mid;
} else if (items_[index_[mid]] > that) {
hig = mid;
} else {
low = mid+1;
}
} }
return nitems_; assert(low == hig);
assert(low == nitems_ || items_[index_[low]] >= that);
return low;
} }
bool NexusSet::contains(const NexusSet&that) const bool NexusSet::contains(const NexusSet&that) const
@ -477,7 +565,7 @@ bool NexusSet::contains(const NexusSet&that) const
unsigned where = bsearch_(that[idx]); unsigned where = bsearch_(that[idx]);
if (where == nitems_) if (where == nitems_)
return false; return false;
if (items_[where] != that[idx]) if (items_[index_[where]] != that[idx])
return false; return false;
} }
@ -490,7 +578,7 @@ bool NexusSet::intersect(const NexusSet&that) const
unsigned where = bsearch_(that[idx]); unsigned where = bsearch_(that[idx]);
if (where == nitems_) if (where == nitems_)
continue; continue;
if (items_[where] == that[idx]) if (items_[index_[where]] == that[idx])
return true; return true;
} }
@ -499,6 +587,24 @@ bool NexusSet::intersect(const NexusSet&that) const
/* /*
* $Log: net_link.cc,v $ * $Log: net_link.cc,v $
* Revision 1.14.2.6 2006/08/23 04:09:14 steve
* missing sig diagnostics.
*
* Revision 1.14.2.5 2006/08/15 03:41:24 steve
* Improve performance of unlink of heavily connected nexa.
*
* Revision 1.14.2.4 2006/08/08 02:17:48 steve
* Improved nexus management performance.
*
* Revision 1.14.2.3 2006/07/23 19:42:33 steve
* Handle statement output override better in blocks.
*
* Revision 1.14.2.2 2006/01/27 02:05:46 steve
* Speed up processing of connect when one side is empty.
*
* Revision 1.14.2.1 2005/09/25 23:30:31 steve
* More predictable ordering of items in NexusSet.
*
* Revision 1.14 2004/02/18 17:11:56 steve * Revision 1.14 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *
@ -523,35 +629,5 @@ bool NexusSet::intersect(const NexusSet&that) const
* Revision 1.7 2002/06/24 01:49:39 steve * Revision 1.7 2002/06/24 01:49:39 steve
* Make link_drive_constant cache its results in * Make link_drive_constant cache its results in
* the Nexus, to improve cprop performance. * the Nexus, to improve cprop performance.
*
* Revision 1.6 2002/04/21 04:59:08 steve
* Add support for conbinational events by finding
* the inputs to expressions and some statements.
* Get case and assignment statements working.
*
* Revision 1.5 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2000/10/06 23:46:50 steve
* ivl_target updates, including more complete
* handling of ivl_nexus_t objects. Much reduced
* dependencies on pointers to netlist objects.
*
* Revision 1.3 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.2 2000/07/14 06:12:57 steve
* Move inital value handling from NetNet to Nexus
* objects. This allows better propogation of inital
* values.
*
* Clean up constant propagation a bit to account
* for regs that are not really values.
*
* Revision 1.1 2000/06/25 19:59:42 steve
* Redesign Links to include the Nexus class that
* carries properties of the connected set of links.
*
*/ */

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_input.cc,v 1.12 2004/09/04 04:24:15 steve Exp $" #ident "$Id: net_nex_input.cc,v 1.12.2.1 2006/05/21 21:58:47 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -29,7 +29,7 @@
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
NexusSet* NetExpr::nex_input() NexusSet* NetExpr::nex_input(bool rem_out)
{ {
cerr << get_line() cerr << get_line()
<< ": internal error: nex_input not implemented: " << ": internal error: nex_input not implemented: "
@ -37,7 +37,7 @@ NexusSet* NetExpr::nex_input()
return 0; return 0;
} }
NexusSet* NetProc::nex_input() NexusSet* NetProc::nex_input(bool rem_out)
{ {
cerr << get_line() cerr << get_line()
<< ": internal error: NetProc::nex_input not implemented" << ": internal error: NetProc::nex_input not implemented"
@ -45,29 +45,34 @@ NexusSet* NetProc::nex_input()
return 0; return 0;
} }
NexusSet* NetEBinary::nex_input() NexusSet* NetEBinary::nex_input(bool rem_out)
{ {
NexusSet*result = left_->nex_input(); NexusSet*result = left_->nex_input(rem_out);
NexusSet*tmp = right_->nex_input(); NexusSet*tmp = right_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
return result; return result;
} }
NexusSet* NetEBitSel::nex_input() NexusSet* NetEBitSel::nex_input(bool rem_out)
{ {
NexusSet*result = sig_->nex_input(); NexusSet*result = sig_->nex_input(rem_out);
NexusSet*tmp = idx_->nex_input(); NexusSet*tmp = idx_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
return result; return result;
} }
NexusSet* NetEConcat::nex_input() NexusSet* NetEConcat::nex_input(bool rem_out)
{ {
NexusSet*result = parms_[0]->nex_input(); if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(); NexusSet*tmp = parms_[idx]->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
}
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
@ -77,19 +82,19 @@ NexusSet* NetEConcat::nex_input()
/* /*
* A constant has not inputs, so always return an empty set. * A constant has not inputs, so always return an empty set.
*/ */
NexusSet* NetEConst::nex_input() NexusSet* NetEConst::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetECReal::nex_input() NexusSet* NetECReal::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetEMemory::nex_input() NexusSet* NetEMemory::nex_input(bool rem_out)
{ {
NexusSet*result = idx_->nex_input(); NexusSet*result = idx_->nex_input(rem_out);
return result; return result;
} }
@ -97,74 +102,79 @@ NexusSet* NetEMemory::nex_input()
* A parameter by definition has no inputs. It represents a constant * A parameter by definition has no inputs. It represents a constant
* value, even if that value is a constant expression. * value, even if that value is a constant expression.
*/ */
NexusSet* NetEParam::nex_input() NexusSet* NetEParam::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetEEvent::nex_input() NexusSet* NetEEvent::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetEScope::nex_input() NexusSet* NetEScope::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetESelect::nex_input() NexusSet* NetESelect::nex_input(bool rem_out)
{ {
NexusSet*result = base_? base_->nex_input() : new NexusSet(); NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
NexusSet*tmp = expr_->nex_input(); NexusSet*tmp = expr_->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
}
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
return result; return result;
} }
NexusSet* NetESFunc::nex_input() NexusSet* NetESFunc::nex_input(bool rem_out)
{ {
if (nparms_ == 0) if (nparms_ == 0)
return new NexusSet; return new NexusSet;
NexusSet*result = parms_[0]->nex_input(); NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) { for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(); NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
return result; return result;
} }
NexusSet* NetESignal::nex_input() NexusSet* NetESignal::nex_input(bool rem_out)
{ {
NexusSet*result = new NexusSet; NexusSet*result = new NexusSet;
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1) assert(msi_ <= net_->pin_count());
for (unsigned idx = lsi_ ; idx <= msi_ ; idx += 1)
result->add(net_->pin(idx).nexus()); result->add(net_->pin(idx).nexus());
return result; return result;
} }
NexusSet* NetETernary::nex_input() NexusSet* NetETernary::nex_input(bool rem_out)
{ {
NexusSet*tmp; NexusSet*tmp;
NexusSet*result = cond_->nex_input(); NexusSet*result = cond_->nex_input(rem_out);
tmp = true_val_->nex_input(); tmp = true_val_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
tmp = false_val_->nex_input(); tmp = false_val_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
return result; return result;
} }
NexusSet* NetEUFunc::nex_input() NexusSet* NetEUFunc::nex_input(bool rem_out)
{ {
NexusSet*result = new NexusSet; NexusSet*result = new NexusSet;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(); NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
@ -172,33 +182,33 @@ NexusSet* NetEUFunc::nex_input()
return result; return result;
} }
NexusSet* NetEUnary::nex_input() NexusSet* NetEUnary::nex_input(bool rem_out)
{ {
return expr_->nex_input(); return expr_->nex_input(rem_out);
} }
NexusSet* NetEVariable::nex_input() NexusSet* NetEVariable::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetAssign_::nex_input() NexusSet* NetAssign_::nex_input(bool rem_out)
{ {
if (bmux_ == 0) if (bmux_ == 0)
return new NexusSet; return new NexusSet;
else else
return bmux_->nex_input(); return bmux_->nex_input(rem_out);
} }
NexusSet* NetAssignBase::nex_input() NexusSet* NetAssignBase::nex_input(bool rem_out)
{ {
NexusSet*result = rval_->nex_input(); NexusSet*result = rval_->nex_input(rem_out);
/* It is possible that the lval_ can hav nex_input values. In /* It is possible that the lval_ can hav nex_input values. In
particular, index expressions are statement inputs as well, particular, index expressions are statement inputs as well,
so should be addressed here. */ so should be addressed here. */
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
NexusSet*tmp = cur->nex_input(); NexusSet*tmp = cur->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
@ -223,7 +233,7 @@ NexusSet* NetAssignBase::nex_input()
* In this example, "t" should not be in the input set because it is * In this example, "t" should not be in the input set because it is
* used by the sequence as a temporary value. * used by the sequence as a temporary value.
*/ */
NexusSet* NetBlock::nex_input() NexusSet* NetBlock::nex_input(bool rem_out)
{ {
if (last_ == 0) if (last_ == 0)
return new NexusSet; return new NexusSet;
@ -243,24 +253,24 @@ NexusSet* NetBlock::nex_input()
do { do {
/* Get the inputs for the current statement. */ /* Get the inputs for the current statement. */
NexusSet*tmp = cur->nex_input(); NexusSet*tmp = cur->nex_input(rem_out);
/* Remove from the input set those bits that are outputs /* Add the current input set to the accumulated input set. */
from previous statements. They aren't really inputs
to the block, just internal intermediate values. */
tmp->rem(*prev);
/* Add the corrected set to the accumulated input set. */
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
/* Add the current outputs to the accumulated output /* Add the current outputs to the accumulated output set,
set, for processing of later statements. */ so they can be removed from the input set below. */
cur->nex_output(*prev); cur->nex_output(*prev);
cur = cur->next_; cur = cur->next_;
} while (cur != last_->next_); } while (cur != last_->next_);
/* Remove from the input set those bits that are outputs
from other statements. They aren't really inputs
to the block, just internal intermediate values. */
if (rem_out) result->rem(*prev);
return result; return result;
} }
@ -269,9 +279,9 @@ NexusSet* NetBlock::nex_input()
* the inputs to all the guards, and the inputs to all the guarded * the inputs to all the guards, and the inputs to all the guarded
* statements. * statements.
*/ */
NexusSet* NetCase::nex_input() NexusSet* NetCase::nex_input(bool rem_out)
{ {
NexusSet*result = expr_->nex_input(); NexusSet*result = expr_->nex_input(rem_out);
if (result == 0) if (result == 0)
return 0; return 0;
@ -281,7 +291,7 @@ NexusSet* NetCase::nex_input()
if (items_[idx].statement == 0) if (items_[idx].statement == 0)
continue; continue;
NexusSet*tmp = items_[idx].statement->nex_input(); NexusSet*tmp = items_[idx].statement->nex_input(rem_out);
assert(tmp); assert(tmp);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
@ -290,7 +300,7 @@ NexusSet* NetCase::nex_input()
case is special and is identified by a null case is special and is identified by a null
guard. The default guard obviously has no input. */ guard. The default guard obviously has no input. */
if (items_[idx].guard) { if (items_[idx].guard) {
tmp = items_[idx].guard->nex_input(); tmp = items_[idx].guard->nex_input(rem_out);
assert(tmp); assert(tmp);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
@ -300,24 +310,24 @@ NexusSet* NetCase::nex_input()
return result; return result;
} }
NexusSet* NetCAssign::nex_input() NexusSet* NetCAssign::nex_input(bool rem_out)
{ {
cerr << get_line() << ": internal warning: NetCAssign::nex_input()" cerr << get_line() << ": internal warning: NetCAssign::nex_input()"
<< " not implemented." << endl; << " not implemented." << endl;
return new NexusSet; return new NexusSet;
} }
NexusSet* NetCondit::nex_input() NexusSet* NetCondit::nex_input(bool rem_out)
{ {
NexusSet*result = expr_->nex_input(); NexusSet*result = expr_->nex_input(rem_out);
if (if_ != 0) { if (if_ != 0) {
NexusSet*tmp = if_->nex_input(); NexusSet*tmp = if_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
if (else_ != 0) { if (else_ != 0) {
NexusSet*tmp = else_->nex_input(); NexusSet*tmp = else_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
@ -325,16 +335,16 @@ NexusSet* NetCondit::nex_input()
return result; return result;
} }
NexusSet* NetForce::nex_input() NexusSet* NetForce::nex_input(bool rem_out)
{ {
cerr << get_line() << ": internal warning: NetForce::nex_input()" cerr << get_line() << ": internal warning: NetForce::nex_input()"
<< " not implemented." << endl; << " not implemented." << endl;
return new NexusSet; return new NexusSet;
} }
NexusSet* NetForever::nex_input() NexusSet* NetForever::nex_input(bool rem_out)
{ {
NexusSet*result = statement_->nex_input(); NexusSet*result = statement_->nex_input(rem_out);
return result; return result;
} }
@ -347,29 +357,29 @@ NexusSet* NetForever::nex_input()
* include the input set of the <expr> because it does not affect the * include the input set of the <expr> because it does not affect the
* result. * result.
*/ */
NexusSet* NetPDelay::nex_input() NexusSet* NetPDelay::nex_input(bool rem_out)
{ {
NexusSet*result = statement_->nex_input(); NexusSet*result = statement_->nex_input(rem_out);
return result; return result;
} }
NexusSet* NetRepeat::nex_input() NexusSet* NetRepeat::nex_input(bool rem_out)
{ {
NexusSet*result = statement_->nex_input(); NexusSet*result = statement_->nex_input(rem_out);
NexusSet*tmp = expr_->nex_input(); NexusSet*tmp = expr_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
return result; return result;
} }
NexusSet* NetSTask::nex_input() NexusSet* NetSTask::nex_input(bool rem_out)
{ {
if (parms_.count() == 0) if (parms_.count() == 0)
return new NexusSet; return new NexusSet;
NexusSet*result = parms_[0]->nex_input(); NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(); NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
} }
@ -382,15 +392,15 @@ NexusSet* NetSTask::nex_input()
* parameters to consider, because the compiler already removed them * parameters to consider, because the compiler already removed them
* and converted them to blocking assignments. * and converted them to blocking assignments.
*/ */
NexusSet* NetUTask::nex_input() NexusSet* NetUTask::nex_input(bool rem_out)
{ {
return new NexusSet; return new NexusSet;
} }
NexusSet* NetWhile::nex_input() NexusSet* NetWhile::nex_input(bool rem_out)
{ {
NexusSet*result = proc_->nex_input(); NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(); NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;
return result; return result;
@ -398,6 +408,9 @@ NexusSet* NetWhile::nex_input()
/* /*
* $Log: net_nex_input.cc,v $ * $Log: net_nex_input.cc,v $
* Revision 1.12.2.1 2006/05/21 21:58:47 steve
* NetESignal input is only selected bits.
*
* Revision 1.12 2004/09/04 04:24:15 steve * Revision 1.12 2004/09/04 04:24:15 steve
* PR1026: assignment statements can have sensitivities in the l-values. * PR1026: assignment statements can have sensitivities in the l-values.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_output.cc,v 1.11 2004/09/16 03:17:33 steve Exp $" #ident "$Id: net_nex_output.cc,v 1.11.2.8 2006/08/08 02:17:48 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -47,10 +47,55 @@ void NetAssignBase::nex_output(NexusSet&out)
{ {
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
if (NetNet*lsig = cur->sig()) { if (NetNet*lsig = cur->sig()) {
if (cur->bmux()) {
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) {
out.add(lsig->pin(idx).nexus());
}
continue;
}
/* Handle l-value signals. We don't need to worry
here about whether there is a bmux, because the
synthesizer will detect that mux and create a
decoder between the expression and the signal. */
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) { for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
unsigned off = cur->get_loff() + idx; unsigned off = cur->get_loff() + idx;
out.add(lsig->pin(off).nexus()); out.add(lsig->pin(off).nexus());
} }
} else if (NetMemory*lmem = cur->mem()) {
/* Memories here are treated as a bunch of reg
devices. Use the explode_to_reg method to get
access to the FF version of the memory and use
that in our l-value management. */
NetNet*tmp = lmem->explode_to_reg();
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
/* The address is constant, so simply
connect to the right pins and we are
done. */
long adr_s = ae->value().as_long();
unsigned adr = lmem->index_to_address(adr_s) * lmem->width();
if (adr >= lmem->count()*lmem->width()) {
/* Skip assignments with constant
addresses that are outside the
range of memories. */
} else {
for (unsigned idx=0; idx<cur->lwidth(); idx += 1)
out.add(tmp->pin(adr+idx).nexus());
}
} else {
/* Put all the bits of the memory into the
set. The synthesis will generate a
decoder to handle this. */
for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1)
out.add(tmp->pin(idx).nexus());
}
} else { } else {
/* Quoting from netlist.h comments for class NetMemory: /* Quoting from netlist.h comments for class NetMemory:
* "This is not a node because memory objects can only be * "This is not a node because memory objects can only be
@ -69,11 +114,11 @@ void NetBlock::nex_output(NexusSet&out)
if (last_ == 0) if (last_ == 0)
return; return;
NetProc*cur = last_; NetProc*cur = last_->next_;
do { do {
cur = cur->next_;
cur->nex_output(out); cur->nex_output(out);
} while (cur != last_); cur = cur->next_;
} while (cur != last_->next_);
} }
void NetCase::nex_output(NexusSet&out) void NetCase::nex_output(NexusSet&out)
@ -114,6 +159,15 @@ void NetSTask::nex_output(NexusSet&out)
{ {
} }
/*
* Consider a task call to not have any outputs. This is not quite
* right, we should be listing as outputs all the output ports, but for
* the purposes that this method is used, this will do for now.
*/
void NetUTask::nex_output(NexusSet&out)
{
}
void NetWhile::nex_output(NexusSet&out) void NetWhile::nex_output(NexusSet&out)
{ {
if (proc_ != 0) if (proc_ != 0)
@ -122,6 +176,30 @@ void NetWhile::nex_output(NexusSet&out)
/* /*
* $Log: net_nex_output.cc,v $ * $Log: net_nex_output.cc,v $
* Revision 1.11.2.8 2006/08/08 02:17:48 steve
* Improved nexus management performance.
*
* Revision 1.11.2.7 2006/06/02 23:42:48 steve
* Compilation warnings.
*
* Revision 1.11.2.6 2006/06/01 03:01:48 steve
* Handle condit clauses with unassigned outputs.
*
* Revision 1.11.2.5 2006/05/18 01:47:12 steve
* Fix synthesis of l-value bit select in block.
*
* Revision 1.11.2.4 2006/05/05 01:56:36 steve
* Handle memory assignments out of range during synthesis
*
* Revision 1.11.2.3 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
* Rework l-value handling to allow for more l-value type flexibility.
*
* Revision 1.11 2004/09/16 03:17:33 steve * Revision 1.11 2004/09/16 03:17:33 steve
* net_output handles l-value concatenations. * net_output handles l-value concatenations.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.33 2004/10/04 01:10:54 steve Exp $" #ident "$Id: net_scope.cc,v 1.33.2.1 2005/02/19 16:39:31 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -25,6 +25,7 @@
# include "netlist.h" # include "netlist.h"
# include <sstream> # include <sstream>
# include <cstring>
/* /*
* The NetScope class keeps a scope tree organized. Each node of the * The NetScope class keeps a scope tree organized. Each node of the
@ -194,7 +195,7 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n) void NetScope::set_module_name(perm_string n)
{ {
assert(type_ == MODULE); assert(type_ == MODULE);
module_name_ = n; /* NOTE: n mus have been permallocated. */ module_name_ = n; /* NOTE: n must have been permallocated. */
} }
perm_string NetScope::module_name() const perm_string NetScope::module_name() const
@ -467,6 +468,9 @@ string NetScope::local_hsymbol()
/* /*
* $Log: net_scope.cc,v $ * $Log: net_scope.cc,v $
* Revision 1.33.2.1 2005/02/19 16:39:31 steve
* Spellig fixes.
*
* Revision 1.33 2004/10/04 01:10:54 steve * Revision 1.33 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.226 2004/10/04 01:10:54 steve Exp $" #ident "$Id: netlist.cc,v 1.226.2.7 2006/04/23 04:26:14 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -229,7 +229,7 @@ NetNode::~NetNode()
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, npins), sig_next_(0), sig_prev_(0), : NetObj(s, n, npins), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0), type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
local_flag_(false), eref_count_(0), lref_count_(0) local_flag_(false), eref_count_(0), lref_count_(0), mref_(0)
{ {
assert(s); assert(s);
@ -270,7 +270,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
: NetObj(s, n, ((ms>ls)?ms-ls:ls-ms) + 1), : NetObj(s, n, ((ms>ls)?ms-ls:ls-ms) + 1),
sig_next_(0), sig_prev_(0), type_(t), sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls), port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls),
local_flag_(false), eref_count_(0), lref_count_(0) local_flag_(false), eref_count_(0), lref_count_(0), mref_(0)
{ {
assert(s); assert(s);
@ -322,6 +322,14 @@ NetNet::~NetNet()
dump_net(cerr, 4); dump_net(cerr, 4);
} }
assert(lref_count_ == 0); assert(lref_count_ == 0);
if (mref_ != 0) {
cerr << get_line() << ": internal error: attempt to delete "
<< "signal ``" << name() << "'' which has "
<< "memory explode references." << endl;
dump_net(cerr, 4);
}
assert(mref_ == 0);
if (scope()) if (scope())
scope()->rem_signal(this); scope()->rem_signal(this);
@ -462,6 +470,23 @@ unsigned NetNet::get_refs() const
return lref_count_ + eref_count_; return lref_count_ + eref_count_;
} }
void NetNet::mref(NetMemory*mem)
{
assert(mref_ == 0);
assert(mem != 0);
mref_ = mem;
}
NetMemory*NetNet::mref()
{
return mref_;
}
const NetMemory* NetNet::mref() const
{
return mref_;
}
NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid) NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid) : NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid)
@ -533,6 +558,8 @@ const NetScope* NetProcTop::scope() const
NetFF::NetFF(NetScope*s, perm_string n, unsigned wid) NetFF::NetFF(NetScope*s, perm_string n, unsigned wid)
: NetNode(s, n, 8 + 2*wid) : NetNode(s, n, 8 + 2*wid)
{ {
demux_ = 0;
pin_Clock().set_dir(Link::INPUT); pin_Clock().set_dir(Link::INPUT);
pin_Clock().set_name(perm_string::literal("Clock"), 0); pin_Clock().set_name(perm_string::literal("Clock"), 0);
pin_Enable().set_dir(Link::INPUT); pin_Enable().set_dir(Link::INPUT);
@ -684,6 +711,118 @@ const verinum& NetFF::sset_value() const
return sset_value_; return sset_value_;
} }
unsigned NetDecode::width() const
{
return width_;
}
unsigned NetDecode::awidth() const
{
return pin_count();
}
NetDemux::NetDemux(NetScope*s, perm_string name,
unsigned bus_width, unsigned address_width, unsigned size)
: NetNode(s, name, bus_width*2+address_width+bus_width/size)
{
width_ = bus_width;
awidth_ = address_width;
size_ = size;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
pin_Q(idx).set_dir(Link::OUTPUT);
pin_Q(idx).set_name(perm_string::literal("Q"), idx);
}
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
pin_Data(idx).set_dir(Link::INPUT);
pin_Data(idx).set_name(perm_string::literal("Data"), idx);
}
for (unsigned idx = 0 ; idx < awidth_ ; idx += 1) {
pin_Address(idx).set_dir(Link::INPUT);
pin_Address(idx).set_name(perm_string::literal("Address"), idx);
}
for (unsigned idx = 0 ; idx < width_/size_ ; idx += 1) {
pin_WriteData(idx).set_dir(Link::INPUT);
pin_WriteData(idx).set_name(perm_string::literal("Writedata"), idx);
}
}
NetDemux::~NetDemux()
{
}
unsigned NetDemux::width() const
{
return width_;
}
unsigned NetDemux::awidth() const
{
return awidth_;
}
unsigned NetDemux::size() const
{
return size_;
}
Link& NetDemux::pin_Q(unsigned idx)
{
assert(idx < width_);
return pin(idx);
}
const Link& NetDemux::pin_Q(unsigned idx) const
{
assert(idx < width_);
return pin(idx);
}
Link& NetDemux::pin_Data(unsigned idx)
{
assert(idx < width_);
return pin(width_+idx);
}
const Link& NetDemux::pin_Data(unsigned idx) const
{
assert(idx < width_);
return pin(width_+idx);
}
Link& NetDemux::pin_Address(unsigned idx)
{
assert(idx < awidth_);
return pin(width_+width_+idx);
}
const Link& NetDemux::pin_Address(unsigned idx) const
{
assert(idx < awidth_);
return pin(width_+width_+idx);
}
Link& NetDemux::pin_WriteData(unsigned idx)
{
assert(idx < width_/size_);
return pin(width_+width_+awidth_+idx);
}
const Link& NetDemux::pin_WriteData(unsigned idx) const
{
assert(idx < width_/size_);
return pin(width_+width_+awidth_+idx);
}
NetDecode* NetFF::get_demux()
{
return demux_;
}
const NetDecode* NetFF::get_demux() const
{
return demux_;
}
/* /*
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is * The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
@ -1060,6 +1199,40 @@ const Link& NetCompare::pin_DataB(unsigned idx) const
return pin(8+width_+idx); return pin(8+width_+idx);
} }
NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem,
unsigned awid, unsigned word_width)
: NetNode(s, name, awid)
{
width_ = word_width;
assert( mem->width() % width_ == 0 );
ff_ = mem;
ff_->demux_ = this;
make_pins_(awid);
}
NetDecode::~NetDecode()
{
}
void NetDecode::make_pins_(unsigned awid)
{
for (unsigned idx = 0 ; idx < awid ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("Address"), idx);
}
}
Link& NetDecode::pin_Address(unsigned idx)
{
return pin(idx);
}
const Link& NetDecode::pin_Address(unsigned idx) const
{
return pin(idx);
}
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr, NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
unsigned wa, unsigned wb) unsigned wa, unsigned wb)
: NetNode(sc, n, wr+wa+wb), : NetNode(sc, n, wr+wa+wb),
@ -1385,10 +1558,7 @@ const Link& NetMux::pin_Data(unsigned w, unsigned s) const
return pin(2+width_+swidth_+s*width_+w); return pin(2+width_+swidth_+s*width_+w);
} }
void NetRamDq::make_pins_(unsigned wid)
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
: NetNode(s, n, 3+2*mem->width()+awid),
mem_(mem), awidth_(awid)
{ {
pin(0).set_dir(Link::INPUT); pin(0).set_name(perm_string::literal("InClock"), 0); pin(0).set_dir(Link::INPUT); pin(0).set_name(perm_string::literal("InClock"), 0);
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("OutClock"), 0); pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("OutClock"), 0);
@ -1399,39 +1569,49 @@ NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
pin(3+idx).set_name(perm_string::literal("Address"), idx); pin(3+idx).set_name(perm_string::literal("Address"), idx);
} }
for (unsigned idx = 0 ; idx < width() ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
pin(3+awidth_+idx).set_dir(Link::INPUT); pin(3+awidth_+idx).set_dir(Link::INPUT);
pin(3+awidth_+idx).set_name(perm_string::literal("Data"), idx); pin(3+awidth_+idx).set_name(perm_string::literal("Data"), idx);
} }
for (unsigned idx = 0 ; idx < width() ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
pin(3+awidth_+width()+idx).set_dir(Link::OUTPUT); pin(3+awidth_+wid+idx).set_dir(Link::OUTPUT);
pin(3+awidth_+width()+idx).set_name(perm_string::literal("Q"), idx); pin(3+awidth_+wid+idx).set_name(perm_string::literal("Q"), idx);
} }
}
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
: NetNode(s, n, 3+2*mem->width()+awid),
mem_(mem), awidth_(awid)
{
make_pins_(mem->width());
next_ = mem_->ram_list_; next_ = mem_->ram_list_;
mem_->ram_list_ = this; mem_->ram_list_ = this;
} }
NetRamDq::~NetRamDq() NetRamDq::~NetRamDq()
{ {
if (mem_->ram_list_ == this) { if (mem_) {
mem_->ram_list_ = next_; if (mem_->ram_list_ == this) {
mem_->ram_list_ = next_;
} else { } else {
NetRamDq*cur = mem_->ram_list_; NetRamDq*cur = mem_->ram_list_;
while (cur->next_ != this) { while (cur->next_ != this) {
assert(cur->next_); assert(cur->next_);
cur = cur->next_; cur = cur->next_;
}
assert(cur->next_ == this);
cur->next_ = next_;
} }
assert(cur->next_ == this);
cur->next_ = next_;
} }
} }
unsigned NetRamDq::width() const unsigned NetRamDq::width() const
{ {
return mem_->width(); if (mem_) return mem_->width();
return 0;
} }
unsigned NetRamDq::awidth() const unsigned NetRamDq::awidth() const
@ -1441,7 +1621,13 @@ unsigned NetRamDq::awidth() const
unsigned NetRamDq::size() const unsigned NetRamDq::size() const
{ {
return mem_->count(); if (mem_) return mem_->count();
return 0;
}
NetMemory* NetRamDq::mem()
{
return mem_;
} }
const NetMemory* NetRamDq::mem() const const NetMemory* NetRamDq::mem() const
@ -2003,6 +2189,7 @@ NetMemory::NetMemory(NetScope*sc, perm_string n, long w, long s, long e)
: width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc) : width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
{ {
name_ = n; name_ = n;
explode_ = 0;
scope_->add_memory(this); scope_->add_memory(this);
} }
@ -2033,7 +2220,26 @@ unsigned NetMemory::index_to_address(long idx) const
return idx - idxl_; return idx - idxl_;
} }
NetNet* NetMemory::explode_to_reg()
{
if (explode_)
return explode_;
explode_ = new NetNet(scope_, name_, NetNet::REG, count()*width_);
explode_->mref(this);
//explode_->incr_lref();
return explode_;
}
NetNet* NetMemory::reg_from_explode()
{
return explode_;
}
const NetNet* NetMemory::reg_from_explode() const
{
return explode_;
}
NetEMemory* NetEMemory::dup_expr() const NetEMemory* NetEMemory::dup_expr() const
{ {
@ -2281,6 +2487,27 @@ const NetProc*NetTaskDef::proc() const
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.226.2.7 2006/04/23 04:26:14 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.226.2.6 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.226.2.5 2006/03/26 23:09:22 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.226.2.4 2006/03/16 05:40:18 steve
* Fix crash when memory exploding doesnot work
*
* Revision 1.226.2.3 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.226.2.2 2006/02/19 00:11:32 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.226.2.1 2006/01/18 01:23:23 steve
* Rework l-value handling to allow for more l-value type flexibility.
*
* Revision 1.226 2004/10/04 01:10:54 steve * Revision 1.226 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

390
netlist.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.321 2004/10/04 01:10:54 steve Exp $" #ident "$Id: netlist.h,v 1.321.2.25 2007/05/30 17:48:53 steve Exp $"
#endif #endif
/* /*
@ -48,6 +48,7 @@ class ostream;
class Design; class Design;
class Link; class Link;
class Nexus; class Nexus;
class NetMemory;
class NetNode; class NetNode;
class NetProc; class NetProc;
class NetProcTop; class NetProcTop;
@ -58,12 +59,22 @@ class NetEvProbe;
class NetExpr; class NetExpr;
class NetESignal; class NetESignal;
class NetEVariable; class NetEVariable;
class NetFF;
class NetFuncDef; class NetFuncDef;
class NetRamDq;
class NetEvTrig;
class NetEvWait;
struct target; struct target;
struct functor_t; struct functor_t;
struct sync_accounting_cell {
NetProc*proc;
NetFF*ff;
unsigned pin;
};
/* ========= /* =========
* A NetObj is anything that has any kind of behavior in the * A NetObj is anything that has any kind of behavior in the
* netlist. Nodes can be gates, registers, etc. and are linked * netlist. Nodes can be gates, registers, etc. and are linked
@ -86,7 +97,6 @@ struct functor_t;
*/ */
class NetObj : public Attrib, public virtual LineInfo { class NetObj : public Attrib, public virtual LineInfo {
public:
public: public:
// The name of the object must be a permallocated string. A // The name of the object must be a permallocated string. A
// lex_strings string, for example. // lex_strings string, for example.
@ -215,7 +225,7 @@ class Link {
unsigned inst_; unsigned inst_;
private: private:
Link *next_; Link *next_, *prev_;
Nexus*nexus_; Nexus*nexus_;
private: // not implemented private: // not implemented
@ -253,6 +263,9 @@ class Nexus {
Link*first_nlink(); Link*first_nlink();
const Link* first_nlink()const; const Link* first_nlink()const;
/* Return the number of drivers, or 0 if undriven. */
int is_driven() const;
/* This method returns true if all the possible drivers of /* This method returns true if all the possible drivers of
this nexus are constant. It will also return true if there this nexus are constant. It will also return true if there
are no drivers at all. */ are no drivers at all. */
@ -267,6 +280,7 @@ class Nexus {
private: private:
Link*list_; Link*list_;
int list_len_;
void unlink(Link*); void unlink(Link*);
void relink(Link*); void relink(Link*);
@ -307,6 +321,7 @@ class NexusSet {
private: private:
Nexus**items_; Nexus**items_;
unsigned*index_;
unsigned nitems_; unsigned nitems_;
unsigned bsearch_(Nexus*that) const; unsigned bsearch_(Nexus*that) const;
@ -424,6 +439,11 @@ class NetNet : public NetObj {
unsigned get_refs() const; unsigned get_refs() const;
/* This may be and explode of a memory. */
void mref(NetMemory*ref);
NetMemory*mref();
const NetMemory*mref() const;
virtual void dump_net(ostream&, unsigned) const; virtual void dump_net(ostream&, unsigned) const;
private: private:
@ -448,6 +468,7 @@ class NetNet : public NetObj {
bool local_flag_; bool local_flag_;
unsigned eref_count_; unsigned eref_count_;
unsigned lref_count_; unsigned lref_count_;
NetMemory*mref_;
}; };
/* /*
@ -581,6 +602,87 @@ class NetCompare : public NetNode {
bool signed_flag_; bool signed_flag_;
}; };
/*
* A decoder takes an address input and activates (high) the single
* Q bit that is addressed. This can be used, for example, to
* generate an enable for a FF from an array of FFs.
*/
class NetDecode : public NetNode {
public:
NetDecode(NetScope*s, perm_string name, NetFF*mem,
unsigned awid, unsigned word_width);
~NetDecode();
// This is the width of the word. The width of the NetFF mem
// is an even multiple of this.
unsigned width() const;
// This is the width of the address. The address value for the
// base of a word is the address * width().
unsigned awidth() const;
const NetFF*ff() const;
Link& pin_Address(unsigned idx);
const Link& pin_Address(unsigned idx) const;
const Link& pin_Q(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
NetFF* ff_;
private:
void make_pins_(unsigned awid);
};
/*
* The NetDemux is similar to the NetDecode, except that it is
* combinational. The inputs are an address, Data, and WriteData.
* The Q output is the same as the Data input, except for the bit that
* is addressed by the address input, which gets WriteData instead.
*/
class NetDemux : public NetNode {
public:
NetDemux(NetScope*s, perm_string name,
unsigned bus_width, unsigned address_width,
unsigned size);
~NetDemux();
// This is the width of the bus that passes through the
// device. The address addresses into this width.
unsigned width() const;
// This is the width of the address. The address value for the
// base of a word is the address * width().
unsigned awidth() const;
// This is the number of words in the width that can be
// addressed. This implies (by division) the width of a word.
unsigned size() const;
Link& pin_Address(unsigned idx);
Link& pin_Data(unsigned idx);
Link& pin_Q(unsigned idx);
Link& pin_WriteData(unsigned idx);
const Link& pin_Address(unsigned idx) const;
const Link& pin_Data(unsigned idx) const;
const Link& pin_Q(unsigned idx) const;
const Link& pin_WriteData(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_, awidth_, size_;
private:
void make_pins_(unsigned wid, unsigned awid);
};
/* /*
* This class represents a theoretical (though not necessarily * This class represents a theoretical (though not necessarily
* practical) integer divider gate. This is not to represent any real * practical) integer divider gate. This is not to represent any real
@ -703,10 +805,19 @@ class NetFF : public NetNode {
void sset_value(const verinum&val); void sset_value(const verinum&val);
const verinum& sset_value() const; const verinum& sset_value() const;
NetDecode* get_demux();
const NetDecode* get_demux() const;
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const; virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun); virtual void functor_node(Design*des, functor_t*fun);
private:
// If there is a demux associated with this gate, the demux_
// member will point to the decoder.
friend class NetDecode;
NetDecode*demux_;
private: private:
verinum aset_value_; verinum aset_value_;
verinum sset_value_; verinum sset_value_;
@ -735,6 +846,7 @@ class NetMemory {
// NetScope*scope(); // NetScope*scope();
const NetScope*scope() const { return scope_; }; const NetScope*scope() const { return scope_; };
NetScope*scope() { return scope_; };
// This is the number of memory positions. // This is the number of memory positions.
unsigned count() const; unsigned count() const;
@ -744,6 +856,13 @@ class NetMemory {
// that are not zero based. // that are not zero based.
unsigned index_to_address(long idx) const; unsigned index_to_address(long idx) const;
// This method returns a NetNet::REG that has the same number
// of bits as the memory as a whole. This is used to represent
// memories that are synthesized to individual bits.
NetNet* explode_to_reg();
NetNet* reg_from_explode();
const NetNet* reg_from_explode() const;
void dump(ostream&o, unsigned lm) const; void dump(ostream&o, unsigned lm) const;
private: private:
@ -753,12 +872,14 @@ class NetMemory {
long idxl_; long idxl_;
friend class NetRamDq; friend class NetRamDq;
NetRamDq* ram_list_; class NetRamDq* ram_list_;
friend class NetScope; friend class NetScope;
NetMemory*snext_, *sprev_; NetMemory*snext_, *sprev_;
NetScope*scope_; NetScope*scope_;
NetNet*explode_;
private: // not implemented private: // not implemented
NetMemory(const NetMemory&); NetMemory(const NetMemory&);
NetMemory& operator= (const NetMemory&); NetMemory& operator= (const NetMemory&);
@ -878,6 +999,8 @@ class NetRamDq : public NetNode {
unsigned width() const; unsigned width() const;
unsigned awidth() const; unsigned awidth() const;
unsigned size() const; unsigned size() const;
NetMemory*mem();
const NetMemory*mem() const; const NetMemory*mem() const;
Link& pin_InClock(); Link& pin_InClock();
@ -908,11 +1031,15 @@ class NetRamDq : public NetNode {
// that are ports to the attached memory. // that are ports to the attached memory.
unsigned count_partners() const; unsigned count_partners() const;
void functor_node(Design*des, functor_t*fun);
private: private:
NetMemory*mem_; NetMemory*mem_;
NetRamDq*next_; NetRamDq*next_;
unsigned awidth_; unsigned awidth_;
private:
void make_pins_(unsigned wid);
}; };
/* /*
@ -1003,7 +1130,7 @@ class NetExpr : public LineInfo {
// Get the Nexus that are the input to this // Get the Nexus that are the input to this
// expression. Normally this descends down to the reference to // expression. Normally this descends down to the reference to
// a signal that reads from its input. // a signal that reads from its input.
virtual NexusSet* nex_input() =0; virtual NexusSet* nex_input(bool rem_out = true) =0;
// Return a version of myself that is structural. This is used // Return a version of myself that is structural. This is used
// for converting expressions to gates. // for converting expressions to gates.
@ -1044,7 +1171,7 @@ class NetEConst : public NetExpr {
virtual NetEConst* dup_expr() const; virtual NetEConst* dup_expr() const;
virtual NetNet*synthesize(Design*); virtual NetNet*synthesize(Design*);
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
private: private:
verinum value_; verinum value_;
@ -1096,7 +1223,7 @@ class NetECReal : public NetExpr {
virtual NetECReal* dup_expr() const; virtual NetECReal* dup_expr() const;
virtual NetNet*synthesize(Design*); virtual NetNet*synthesize(Design*);
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
private: private:
verireal value_; verireal value_;
@ -1315,7 +1442,7 @@ class NetUDP : public NetNode {
* linked into the netlist. However, elaborating a process may cause * linked into the netlist. However, elaborating a process may cause
* special nodes to be created to handle things like events. * special nodes to be created to handle things like events.
*/ */
class NetProc : public virtual LineInfo { class NetProc : public virtual LineInfo, public Attrib {
public: public:
explicit NetProc(); explicit NetProc();
@ -1324,7 +1451,7 @@ class NetProc : public virtual LineInfo {
// Find the Nexa that are input by the statement. This is used // Find the Nexa that are input by the statement. This is used
// for example by @* to find the inputs to the process for the // for example by @* to find the inputs to the process for the
// sensitivity list. // sensitivity list.
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
// Find the nexa that are set by the statement. Add the output // Find the nexa that are set by the statement. Add the output
// values to the set passed as a parameter. // values to the set passed as a parameter.
@ -1346,15 +1473,33 @@ class NetProc : public virtual LineInfo {
// process. Most process types are not. // process. Most process types are not.
virtual bool is_synchronous(); virtual bool is_synchronous();
// synthesize as asynchronous logic, and return true. // synthesize as asynchronous logic, and return true. The
virtual bool synth_async(Design*des, NetScope*scope, // sync_flag is used to tell the async synthesizer that the
const NetNet*nex_map, NetNet*nex_out); // output nex_map is ultimately connected to a DFF Q
// output. This can affect how cycles are handled.
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff, bool synth_async_noaccum(Design*des, NetScope*scope, bool sync_flag,
const NetNet*nex_map, NetNet*nex_out, struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out);
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
// Synthesize synchronous logic, and return true. The nex_out
// is where outputs are actually connected, and the nex_map
// maps nexa to bit positions. The ff is the initial DFF that
// was created to receive the Data inputs. The method *may*
// delete that DFF in favor of multiple smaller devices, but
// in that case it will set the ff argument to nil.
virtual bool synth_sync(Design*des, NetScope*scope,
struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
void dump_proc_attr(ostream&, unsigned ind) const;
private: private:
friend class NetBlock; friend class NetBlock;
@ -1432,11 +1577,13 @@ class NetAssign_ {
// into a wire. // into a wire.
void turn_sig_to_wire_on_release(); void turn_sig_to_wire_on_release();
void incr_mem_lref();
// It is possible that l-values can have *inputs*, as well as // It is possible that l-values can have *inputs*, as well as
// being outputs. For example foo[idx] = ... is the l-value // being outputs. For example foo[idx] = ... is the l-value
// (NetAssign_ object) with a foo l-value and the input // (NetAssign_ object) with a foo l-value and the input
// expression idx. // expression idx.
NexusSet* nex_input(); NexusSet* nex_input(bool rem_out = true);
// This pointer is for keeping simple lists. // This pointer is for keeping simple lists.
NetAssign_* more; NetAssign_* more;
@ -1452,6 +1599,7 @@ class NetAssign_ {
bool turn_sig_to_wire_on_release_; bool turn_sig_to_wire_on_release_;
unsigned loff_; unsigned loff_;
unsigned lwid_; unsigned lwid_;
bool mem_lref_;
}; };
class NetAssignBase : public NetProc { class NetAssignBase : public NetProc {
@ -1474,7 +1622,7 @@ class NetAssignBase : public NetProc {
void set_delay(NetExpr*); void set_delay(NetExpr*);
const NetExpr* get_delay() const; const NetExpr* get_delay() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&o); virtual void nex_output(NexusSet&o);
@ -1482,13 +1630,24 @@ class NetAssignBase : public NetProc {
// accounts for any grouping of NetAssign_ objects that might happen. // accounts for any grouping of NetAssign_ objects that might happen.
unsigned lwidth() const; unsigned lwidth() const;
bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
const NetNet*nex_map, NetNet*nex_out); struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
bool synth_sync(Design*des, NetScope*scope,
struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
// This dumps all the lval structures. // This dumps all the lval structures.
void dump_lval(ostream&) const; void dump_lval(ostream&) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private:
bool synth_async_mem_sync_(Design*des, NetScope*scope,
NetAssign_*cur, NetNet*rsig, unsigned&roff,
NetNet*nex_map, NetNet*nex_out);
private: private:
NetAssign_*lval_; NetAssign_*lval_;
NetExpr *rval_; NetExpr *rval_;
@ -1549,11 +1708,13 @@ class NetBlock : public NetProc {
// synthesize as asynchronous logic, and return true. // synthesize as asynchronous logic, and return true.
bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
const NetNet*nex_map, NetNet*nex_out); struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff, bool synth_sync(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out, struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
// This version of emit_recurse scans all the statements of // This version of emit_recurse scans all the statements of
@ -1561,7 +1722,7 @@ class NetBlock : public NetProc {
// for sequential blocks. // for sequential blocks.
void emit_recurse(struct target_t*) const; void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&); virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*); virtual int match_proc(struct proc_match_t*);
@ -1601,15 +1762,21 @@ class NetCase : public NetProc {
const NetExpr*expr(unsigned idx) const { return items_[idx].guard;} const NetExpr*expr(unsigned idx) const { return items_[idx].guard;}
const NetProc*stat(unsigned idx) const { return items_[idx].statement; } const NetProc*stat(unsigned idx) const { return items_[idx].statement; }
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&out); virtual void nex_output(NexusSet&out);
bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
const NetNet*nex_map, NetNet*nex_out); struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private:
bool synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in,
NetNet*esig, unsigned hot_items);
private: private:
TYPE type_; TYPE type_;
@ -1642,7 +1809,7 @@ class NetCAssign : public NetProc, public NetNode {
const Link& lval_pin(unsigned) const; const Link& lval_pin(unsigned) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
@ -1682,21 +1849,30 @@ class NetCondit : public NetProc {
bool emit_recurse_if(struct target_t*) const; bool emit_recurse_if(struct target_t*) const;
bool emit_recurse_else(struct target_t*) const; bool emit_recurse_else(struct target_t*) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&o); virtual void nex_output(NexusSet&o);
bool is_asynchronous(); bool is_asynchronous();
bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
const NetNet*nex_map, NetNet*nex_out); struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out, NetNet*accum, bool latch_inferred = false, NetNet *gsig = 0);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff, bool synth_sync(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out, struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*); virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private:
int connect_set_clr_range_( struct sync_accounting_cell*nex_ff,
unsigned bits, NetNet*rst,
const verinum&val);
int connect_enable_range_(Design*des, NetScope*scope,
struct sync_accounting_cell*nex_ff,
unsigned bits, NetNet*ce);
private: private:
NetExpr* expr_; NetExpr* expr_;
NetProc*if_; NetProc*if_;
@ -1845,12 +2021,12 @@ class NetEvent : public LineInfo {
NetEvProbe*probes_; NetEvProbe*probes_;
// Use these methods to list the triggers attached to me. // Use these methods to list the triggers attached to me.
NetEvTrig* trig_; class NetEvTrig* trig_;
// Use This member to count references by NetEvWait objects. // Use This member to count references by NetEvWait objects.
unsigned waitref_; unsigned waitref_;
struct wcell_ { struct wcell_ {
NetEvWait*obj; class NetEvWait*obj;
struct wcell_*next; struct wcell_*next;
}; };
struct wcell_ *wlist_; struct wcell_ *wlist_;
@ -1911,11 +2087,14 @@ class NetEvWait : public NetProc {
virtual void nex_output(NexusSet&out); virtual void nex_output(NexusSet&out);
virtual bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
const NetNet*nex_map, NetNet*nex_out); struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff, virtual bool synth_sync(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out, struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -1974,7 +2153,7 @@ class NetForce : public NetProc, public NetNode {
const NetNet*lval() const; const NetNet*lval() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
@ -1997,7 +2176,7 @@ class NetForever : public NetProc {
void emit_recurse(struct target_t*) const; void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -2035,6 +2214,8 @@ class NetFuncDef {
const NetNet*return_sig() const; const NetNet*return_sig() const;
const NetVariable*return_var() const; const NetVariable*return_var() const;
NetNet* synthesize(Design*des, const svector<NetNet*>&inports_);
void dump(ostream&, unsigned ind) const; void dump(ostream&, unsigned ind) const;
private: private:
@ -2069,7 +2250,7 @@ class NetPDelay : public NetProc {
unsigned long delay() const; unsigned long delay() const;
const NetExpr*expr() const; const NetExpr*expr() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&); virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
@ -2095,7 +2276,7 @@ class NetRepeat : public NetProc {
const NetExpr*expr() const; const NetExpr*expr() const;
void emit_recurse(struct target_t*) const; void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -2147,7 +2328,7 @@ class NetSTask : public NetProc {
const NetExpr* parm(unsigned idx) const; const NetExpr* parm(unsigned idx) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&); virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -2253,7 +2434,9 @@ class NetEUFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEUFunc*dup_expr() const; virtual NetEUFunc*dup_expr() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual NetNet* synthesize(Design*);
private: private:
NetScope*func_; NetScope*func_;
@ -2281,7 +2464,8 @@ class NetUTask : public NetProc {
const NetScope* task() const; const NetScope* task() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -2304,11 +2488,15 @@ class NetWhile : public NetProc {
void emit_proc_recurse(struct target_t*) const; void emit_proc_recurse(struct target_t*) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void nex_output(NexusSet&); virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
struct sync_accounting_cell*nex_ff,
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
private: private:
NetExpr* cond_; NetExpr* cond_;
NetProc*proc_; NetProc*proc_;
@ -2336,14 +2524,14 @@ class NetProcTop : public LineInfo, public Attrib {
const NetScope*scope() const; const NetScope*scope() const;
/* Return true if this process represents combinational logic. */ /* Return true if this process represents combinational logic. */
bool is_asynchronous(); bool is_asynchronous() const;
/* Create asynchronous logic from this thread and return true, /* Create asynchronous logic from this thread and return true,
or return false if that cannot be done. */ or return false if that cannot be done. */
bool synth_async(Design*des); bool synth_async(Design*des);
/* Return true if this process represents synchronous logic. */ /* Return true if this process represents synchronous logic. */
bool is_synchronous(); bool is_synchronous() const;
/* Create synchronous logic from this thread and return true, /* Create synchronous logic from this thread and return true,
or return false if that cannot be done. */ or return false if that cannot be done. */
@ -2410,7 +2598,7 @@ class NetEBinary : public NetExpr {
virtual bool has_width() const; virtual bool has_width() const;
virtual NetEBinary* dup_expr() const; virtual NetEBinary* dup_expr() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -2523,7 +2711,7 @@ class NetEBComp : public NetEBinary {
NetEConst*eval_eqeq_(); NetEConst*eval_eqeq_();
NetEConst*eval_less_(); NetEConst*eval_less_();
NetEConst*eval_leeq_(); NetEConst*eval_leeq_();
NetEConst*eval_leeq_real_(); NetEConst*eval_leeq_real_(bool gt_flag, bool include_eq_flag);
NetEConst*eval_gt_(); NetEConst*eval_gt_();
NetEConst*eval_gteq_(); NetEConst*eval_gteq_();
NetEConst*eval_neeq_(); NetEConst*eval_neeq_();
@ -2628,7 +2816,7 @@ class NetEConcat : public NetExpr {
unsigned nparms() const { return parms_.count() ; } unsigned nparms() const { return parms_.count() ; }
NetExpr* parm(unsigned idx) const { return parms_[idx]; } NetExpr* parm(unsigned idx) const { return parms_[idx]; }
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool has_width() const; virtual bool has_width() const;
virtual bool set_width(unsigned w); virtual bool set_width(unsigned w);
virtual NetEConcat* dup_expr() const; virtual NetEConcat* dup_expr() const;
@ -2661,7 +2849,7 @@ class NetEVariable : public NetExpr {
void dump(ostream&) const; void dump(ostream&) const;
NetEVariable*dup_expr() const; NetEVariable*dup_expr() const;
NexusSet* nex_input(); NexusSet* nex_input(bool rem_out = true);
private: private:
NetVariable*var_; NetVariable*var_;
@ -2682,7 +2870,7 @@ class NetEParam : public NetExpr {
NetEParam(class Design*des, NetScope*scope, perm_string name); NetEParam(class Design*des, NetScope*scope, perm_string name);
~NetEParam(); ~NetEParam();
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool set_width(unsigned w); virtual bool set_width(unsigned w);
virtual bool has_width() const; virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
@ -2718,7 +2906,7 @@ class NetESelect : public NetExpr {
const NetExpr*sub_expr() const; const NetExpr*sub_expr() const;
const NetExpr*select() const; const NetExpr*select() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool set_width(unsigned w); virtual bool set_width(unsigned w);
virtual bool has_width() const; virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
@ -2745,7 +2933,7 @@ class NetEEvent : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEEvent* dup_expr() const; virtual NetEEvent* dup_expr() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&os) const; virtual void dump(ostream&os) const;
@ -2768,7 +2956,7 @@ class NetEScope : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEScope* dup_expr() const; virtual NetEScope* dup_expr() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&os) const; virtual void dump(ostream&os) const;
@ -2796,7 +2984,7 @@ class NetESFunc : public NetExpr {
const NetExpr* parm(unsigned idx) const; const NetExpr* parm(unsigned idx) const;
virtual TYPE expr_type() const; virtual TYPE expr_type() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool set_width(unsigned); virtual bool set_width(unsigned);
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -2834,7 +3022,7 @@ class NetETernary : public NetExpr {
virtual NetETernary* dup_expr() const; virtual NetETernary* dup_expr() const;
virtual NetExpr* eval_tree(); virtual NetExpr* eval_tree();
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual NetNet*synthesize(Design*); virtual NetNet*synthesize(Design*);
@ -2874,7 +3062,7 @@ class NetEUnary : public NetExpr {
virtual NetEUnary* dup_expr() const; virtual NetEUnary* dup_expr() const;
virtual NetEConst* eval_tree(); virtual NetEConst* eval_tree();
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -2924,11 +3112,11 @@ class NetEMemory : public NetExpr {
const NetExpr* index() const; const NetExpr* index() const;
virtual bool set_width(unsigned); virtual bool set_width(unsigned);
virtual NetNet* synthesize(Design*);
NetExpr* eval_tree(); NetExpr* eval_tree();
virtual NetEMemory*dup_expr() const; virtual NetEMemory*dup_expr() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -2962,7 +3150,7 @@ class NetESignal : public NetExpr {
virtual NetESignal* dup_expr() const; virtual NetESignal* dup_expr() const;
NetNet* synthesize(Design*des); NetNet* synthesize(Design*des);
NexusSet* nex_input(); NexusSet* nex_input(bool rem_out = true);
// These methods actually reference the properties of the // These methods actually reference the properties of the
// NetNet object that I point to. // NetNet object that I point to.
@ -3004,8 +3192,9 @@ class NetEBitSel : public NetExpr {
const NetNet* sig() const; const NetNet* sig() const;
NetEBitSel* dup_expr() const; NetEBitSel* dup_expr() const;
NetNet* synthesize(Design*des);
virtual NexusSet* nex_input(); virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -3357,6 +3546,81 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.321.2.25 2007/05/30 17:48:53 steve
* Support Latch synthesis (Alan Feldstein)
*
* Revision 1.321.2.24 2006/11/26 01:54:05 steve
* Add synthesis of user defined functions.
*
* Revision 1.321.2.23 2006/08/15 03:41:24 steve
* Improve performance of unlink of heavily connected nexa.
*
* Revision 1.321.2.22 2006/08/08 02:17:48 steve
* Improved nexus management performance.
*
* Revision 1.321.2.21 2006/07/23 19:42:33 steve
* Handle statement output override better in blocks.
*
* Revision 1.321.2.20 2006/07/10 00:21:51 steve
* Add support for full_case attribute.
*
* Revision 1.321.2.19 2006/06/23 03:49:46 steve
* synthesis of NetCondit handles partial resets.
*
* Revision 1.321.2.18 2006/06/14 03:02:54 steve
* synthesis for NetEBitSel.
*
* Revision 1.321.2.17 2006/04/23 04:26:14 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.321.2.16 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.321.2.15 2006/04/10 03:43:39 steve
* Exploded memories accessed by constant indices.
*
* Revision 1.321.2.14 2006/03/26 23:09:23 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.321.2.13 2006/03/18 18:43:21 steve
* Better error messages when synthesis fails.
*
* Revision 1.321.2.12 2006/03/16 05:40:18 steve
* Fix crash when memory exploding doesnot work
*
* Revision 1.321.2.11 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.321.2.10 2006/02/19 00:11:32 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.321.2.9 2006/01/21 21:42:31 steve
* When mux has wide select but sparse choices, use 1hot translation.
*
* Revision 1.321.2.8 2006/01/18 01:23:24 steve
* Rework l-value handling to allow for more l-value type flexibility.
*
* Revision 1.321.2.7 2005/12/31 04:28:14 steve
* Fix crashes caused bu synthesis of sqrt32.v.
*
* Revision 1.321.2.6 2005/12/14 00:54:29 steve
* Account for sync vs async muxes.
*
* Revision 1.321.2.5 2005/11/13 22:28:48 steve
* Allow for block output to be set throughout the statements.
*
* Revision 1.321.2.4 2005/09/09 02:17:08 steve
* Evaluate magnitude compare with real operands.
*
* Revision 1.321.2.3 2005/08/22 01:00:41 steve
* Add support for implicit defaults in case and conditions.
*
* Revision 1.321.2.2 2005/08/13 00:45:54 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.321.2.1 2005/07/06 22:41:34 steve
* Fix compile errors with g++-4.
*
* Revision 1.321 2004/10/04 01:10:54 steve * Revision 1.321 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $" #ident "$Id: netmisc.cc,v 1.8.2.1 2006/05/15 03:55:23 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -72,6 +72,26 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
return res; return res;
} }
NetNet* reduction_or(Design*des, NetNet*isig)
{
NetScope*scope = isig->scope();
NetLogic*olog = new NetLogic(scope, scope->local_symbol(),
isig->pin_count()+1, NetLogic::OR);
olog->set_line(*isig);
des->add_node(olog);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->local_flag(true);
osig->set_line(*isig);
connect(olog->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < isig->pin_count() ; idx += 1)
connect(olog->pin(1+idx), isig->pin(idx));
return osig;
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe) NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
{ {
@ -90,6 +110,9 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/* /*
* $Log: netmisc.cc,v $ * $Log: netmisc.cc,v $
* Revision 1.8.2.1 2006/05/15 03:55:23 steve
* Fix synthesis of expressions with land of vectors.
*
* Revision 1.8 2004/02/20 18:53:35 steve * Revision 1.8 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.h,v 1.19 2004/03/07 20:04:11 steve Exp $" #ident "$Id: netmisc.h,v 1.19.2.1 2006/05/15 03:55:23 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -57,6 +57,11 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
*/ */
extern NetNet*add_to_net(Design*des, NetNet*sig, long val); extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
/*
* Calculate the reduction OR from the input signal.
*/
extern NetNet*reduction_or(Design*des, NetNet*sig);
/* /*
* In some cases the lval is accessible as a pointer to the head of * In some cases the lval is accessible as a pointer to the head of
* a list of NetAssign_ objects. This function returns the width of * a list of NetAssign_ objects. This function returns the width of
@ -75,6 +80,9 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
/* /*
* $Log: netmisc.h,v $ * $Log: netmisc.h,v $
* Revision 1.19.2.1 2006/05/15 03:55:23 steve
* Fix synthesis of expressions with land of vectors.
*
* Revision 1.19 2004/03/07 20:04:11 steve * Revision 1.19 2004/03/07 20:04:11 steve
* MOre thorough use of elab_and_eval function. * MOre thorough use of elab_and_eval function.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: nodangle.cc,v 1.21 2004/02/20 18:53:35 steve Exp $" #ident "$Id: nodangle.cc,v 1.21.2.2 2006/08/23 04:08:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -109,6 +109,9 @@ void nodangle_f::signal(Design*des, NetNet*sig)
if (sig->get_refs() > 0) if (sig->get_refs() > 0)
return; return;
if (sig->mref())
return;
/* Cannot delete the ports of tasks or functions. There are /* Cannot delete the ports of tasks or functions. There are
too many places where they are referenced. */ too many places where they are referenced. */
if ((sig->port_type() != NetNet::NOT_A_PORT) if ((sig->port_type() != NetNet::NOT_A_PORT)
@ -160,6 +163,9 @@ void nodangle_f::signal(Design*des, NetNet*sig)
if (cursig == 0) if (cursig == 0)
continue; continue;
if (cursig == sig)
continue;
if (cursig->local_flag()) if (cursig->local_flag())
continue; continue;
@ -205,6 +211,12 @@ void nodangle(Design*des)
/* /*
* $Log: nodangle.cc,v $ * $Log: nodangle.cc,v $
* Revision 1.21.2.2 2006/08/23 04:08:55 steve
* Do not count self as signifincant in nodangle.
*
* Revision 1.21.2.1 2006/03/16 05:40:19 steve
* Fix crash when memory exploding doesnot work
*
* Revision 1.21 2004/02/20 18:53:35 steve * Revision 1.21 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

234
parse.y
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.201 2004/10/04 01:10:54 steve Exp $" #ident "$Id: parse.y,v 1.201.2.8 2007/04/26 00:50:54 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -134,9 +134,10 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER %token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
%token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case %token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable %token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
%token K_edge K_else K_end K_endcase K_endfunction K_endmodule %token K_edge K_edge_descriptor
%token K_else K_end K_endcase K_endfunction K_endmodule
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for %token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
%token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if %token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if K_ifnone
%token K_initial K_inout K_input K_integer K_join K_large K_localparam %token K_initial K_inout K_input K_integer K_join K_large K_localparam
%token K_macromodule %token K_macromodule
%token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0 %token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0
@ -191,11 +192,11 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%type <gate> gate_instance %type <gate> gate_instance
%type <gates> gate_instance_list %type <gates> gate_instance_list
%type <expr> expression expr_primary %type <expr> expression expr_primary expr_mintypmax
%type <expr> lavalue lpvalue %type <expr> lavalue lpvalue
%type <expr> delay_value delay_value_simple %type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt %type <exprs> delay1 delay3 delay3_opt
%type <exprs> expression_list %type <exprs> expression_list expression_list_proper
%type <exprs> assign assign_list %type <exprs> assign assign_list
%type <exprs> range range_opt %type <exprs> range range_opt
@ -287,7 +288,7 @@ attribute
} }
| IDENTIFIER '=' expression | IDENTIFIER '=' expression
{ PExpr*tmp = $3; { PExpr*tmp = $3;
if (!pform_expression_is_constant(tmp)) { if (tmp && !pform_expression_is_constant(tmp)) {
yyerror(@3, "error: attribute value " yyerror(@3, "error: attribute value "
"expression must be constant."); "expression must be constant.");
delete tmp; delete tmp;
@ -308,17 +309,14 @@ attribute
integers. This rule matches those declarations. The containing integers. This rule matches those declarations. The containing
rule has presumably set up the scope. */ rule has presumably set up the scope. */
block_item_decl block_item_decl
: attribute_list_opt K_reg signed_opt range register_variable_list ';' : K_reg signed_opt range register_variable_list ';'
{ pform_set_net_range($5, $4, $3); { pform_set_net_range($4, $3, $2);
if ($1) delete $1;
} }
| attribute_list_opt K_reg signed_opt register_variable_list ';' | K_reg signed_opt register_variable_list ';'
{ pform_set_net_range($4, 0, $3); { pform_set_net_range($3, 0, $2);
if ($1) delete $1;
} }
| attribute_list_opt K_integer register_variable_list ';' | K_integer register_variable_list ';'
{ pform_set_reg_integer($3); { pform_set_reg_integer($2);
if ($1) delete $1;
} }
| K_time register_variable_list ';' | K_time register_variable_list ';'
{ pform_set_reg_time($2); { pform_set_reg_time($2);
@ -335,15 +333,13 @@ block_item_decl
/* Recover from errors that happen within variable lists. Use the /* Recover from errors that happen within variable lists. Use the
trailing semi-colon to resync the parser. */ trailing semi-colon to resync the parser. */
| attribute_list_opt K_reg error ';' | K_reg error ';'
{ yyerror(@2, "error: syntax error in reg variable list."); { yyerror(@1, "error: syntax error in reg variable list.");
yyerrok; yyerrok;
if ($1) delete $1;
} }
| attribute_list_opt K_integer error ';' | K_integer error ';'
{ yyerror(@2, "error: syntax error in integer variable list."); { yyerror(@1, "error: syntax error in integer variable list.");
yyerrok; yyerrok;
if ($1) delete $1;
} }
| K_time error ';' | K_time error ';'
{ yyerror(@1, "error: syntax error in time variable list."); { yyerror(@1, "error: syntax error in time variable list.");
@ -882,6 +878,30 @@ expression
} }
; ;
expr_mintypmax
: expression
{ $$ = $1; }
| expression ':' expression ':' expression
{ switch (min_typ_max_flag) {
case MIN:
$$ = $1;
delete $3;
delete $5;
break;
case TYP:
delete $1;
$$ = $3;
delete $5;
break;
case MAX:
delete $1;
delete $3;
$$ = $5;
break;
}
}
;
/* Many contexts take a comma separated list of expressions. Null /* Many contexts take a comma separated list of expressions. Null
expressions can happen anywhere in the list, so there are two expressions can happen anywhere in the list, so there are two
@ -910,6 +930,19 @@ expression_list
} }
; ;
expression_list_proper
: expression_list_proper ',' expression
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
delete $1;
$$ = tmp;
}
| expression
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
(*tmp)[0] = $1;
$$ = tmp;
}
;
expr_primary expr_primary
: number : number
@ -975,12 +1008,20 @@ expr_primary
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| '(' expression ')' | '(' expr_mintypmax ')'
{ $$ = $2; } { $$ = $2; }
| '{' expression_list '}' | '{' expression_list '}'
{ PEConcat*tmp = new PEConcat(*$2); { PEConcat*tmp = new PEConcat(*$2);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
for (unsigned idx = 0 ; idx < (*$2).count() ; idx += 1) {
PExpr*ex = (*$2)[idx];
if (ex == 0) {
yyerror(@1, "error: Null arguments not allowed"
" in repeat expressions.");
break;
}
}
delete $2; delete $2;
$$ = tmp; $$ = tmp;
} }
@ -990,7 +1031,6 @@ expr_primary
yyerror(@2, "error: Repeat expression " yyerror(@2, "error: Repeat expression "
"must be constant."); "must be constant.");
delete rep; delete rep;
delete $2;
rep = 0; rep = 0;
} }
PEConcat*tmp = new PEConcat(*$4, rep); PEConcat*tmp = new PEConcat(*$4, rep);
@ -1028,6 +1068,14 @@ function_item
$$ = tmp; $$ = tmp;
yyerror(@1, "Functions may not have output ports."); yyerror(@1, "Functions may not have output ports.");
} }
| K_output K_signed range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, true,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
yyerror(@1, "Functions may not have output ports.");
}
| K_inout range_opt list_of_identifiers ';' | K_inout range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, false, = pform_make_task_ports(NetNet::PINPUT, false,
@ -1036,7 +1084,15 @@ function_item
$$ = tmp; $$ = tmp;
yyerror(@1, "Functions may not have inout ports."); yyerror(@1, "Functions may not have inout ports.");
} }
| block_item_decl | K_inout K_signed range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, true,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
yyerror(@1, "Functions may not have inout ports.");
}
| attribute_list_opt block_item_decl
{ $$ = 0; } { $$ = 0; }
; ;
@ -1583,7 +1639,8 @@ module_item
/* block_item_decl rule is shared with task blocks and named /* block_item_decl rule is shared with task blocks and named
begin/end. */ begin/end. */
| block_item_decl | attribute_list_opt block_item_decl
{ ; }
/* */ /* */
@ -2265,8 +2322,11 @@ specify_item
| K_if '(' expression ')' specify_edge_path_decl ';' | K_if '(' expression ')' specify_edge_path_decl ';'
{ {
} }
| K_ifnone specify_simple_path_decl ';'
{
}
| K_Shold '(' spec_reference_event ',' spec_reference_event | K_Shold '(' spec_reference_event ',' spec_reference_event
',' expression spec_notifier_opt ')' ';' ',' delay_value spec_notifier_opt ')' ';'
{ delete $7; { delete $7;
} }
| K_Speriod '(' spec_reference_event ',' delay_value | K_Speriod '(' spec_reference_event ',' delay_value
@ -2274,11 +2334,11 @@ specify_item
{ delete $5; { delete $5;
} }
| K_Srecovery '(' spec_reference_event ',' spec_reference_event | K_Srecovery '(' spec_reference_event ',' spec_reference_event
',' expression spec_notifier_opt ')' ';' ',' delay_value spec_notifier_opt ')' ';'
{ delete $7; { delete $7;
} }
| K_Ssetup '(' spec_reference_event ',' spec_reference_event | K_Ssetup '(' spec_reference_event ',' spec_reference_event
',' expression spec_notifier_opt ')' ';' ',' delay_value spec_notifier_opt ')' ';'
{ delete $7; { delete $7;
} }
| K_Ssetuphold '(' spec_reference_event ',' spec_reference_event | K_Ssetuphold '(' spec_reference_event ',' spec_reference_event
@ -2296,14 +2356,18 @@ specify_item
{ delete $5; { delete $5;
delete $7; delete $7;
} }
| K_Swidth '(' spec_reference_event ',' expression ')' ';' | K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
{ delete $5; { delete $5;
} }
; ;
specify_delay_value_list specify_delay_value_list
: delay_value { } : delay_value
| specify_delay_value_list ',' delay_value { } { delete $1;
}
| specify_delay_value_list ',' delay_value
{ delete $3;
}
; ;
specify_item_list specify_item_list
@ -2316,15 +2380,19 @@ specify_edge_path_decl
| specify_edge_path '=' delay_value_simple | specify_edge_path '=' delay_value_simple
; ;
specify_edge_operator
: K_posedge
| K_negedge
;
/* The first two rules are not in development. */
specify_edge_path specify_edge_path
: '(' K_posedge specify_path_identifiers spec_polarity K_EG IDENTIFIER ')' : '(' specify_edge_operator specify_path_identifiers spec_polarity K_EG IDENTIFIER ')'
| '(' K_posedge specify_path_identifiers spec_polarity K_EG '(' expr_primary polarity_operator expression ')' ')' | '(' specify_edge_operator specify_path_identifiers spec_polarity K_SG IDENTIFIER ')'
| '(' K_posedge specify_path_identifiers spec_polarity K_SG IDENTIFIER ')' | '(' specify_path_identifiers spec_polarity K_EG '(' specify_path_identifiers polarity_operator expression ')' ')'
| '(' K_posedge specify_path_identifiers spec_polarity K_SG '(' expr_primary polarity_operator expression ')' ')' | '(' specify_edge_operator specify_path_identifiers spec_polarity K_EG '(' specify_path_identifiers polarity_operator expression ')' ')'
| '(' K_negedge specify_path_identifiers spec_polarity K_EG IDENTIFIER ')' | '(' specify_path_identifiers spec_polarity K_SG '(' specify_path_identifiers polarity_operator expression ')' ')'
| '(' K_negedge specify_path_identifiers spec_polarity K_EG '(' expr_primary polarity_operator expression ')' ')' | '(' specify_edge_operator specify_path_identifiers spec_polarity K_SG '(' specify_path_identifiers polarity_operator expression ')' ')'
| '(' K_negedge specify_path_identifiers spec_polarity K_SG IDENTIFIER ')'
| '(' K_negedge specify_path_identifiers spec_polarity K_SG '(' expr_primary polarity_operator expression ')' ')'
; ;
polarity_operator polarity_operator
@ -2436,6 +2504,12 @@ spec_reference_event
{ delete $2; { delete $2;
delete $4; delete $4;
} }
| K_edge '[' edge_descriptor_list ']' expr_primary
{ delete $5; }
| K_edge '[' edge_descriptor_list ']' expr_primary K_TAND expression
{ delete $5;
delete $7;
}
| expr_primary K_TAND expression | expr_primary K_TAND expression
{ delete $1; { delete $1;
delete $3; delete $3;
@ -2444,6 +2518,11 @@ spec_reference_event
{ delete $1; } { delete $1; }
; ;
edge_descriptor_list
: edge_descriptor_list ',' K_edge_descriptor
| K_edge_descriptor
;
spec_notifier_opt spec_notifier_opt
: /* empty */ : /* empty */
{ } { }
@ -2458,7 +2537,10 @@ spec_notifier
| spec_notifier ',' | spec_notifier ','
{ } { }
| spec_notifier ',' identifier | spec_notifier ',' identifier
{ delete $3; { delete $3; }
| spec_notifier ',' identifier '[' expr_primary ']'
{ delete $3;
delete $5;
} }
| IDENTIFIER | IDENTIFIER
{ delete $1; } { delete $1; }
@ -2541,9 +2623,9 @@ statement
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_begin error K_end /* | K_begin error K_end
{ yyerrok; } { yyerrok; }
*/
/* fork-join blocks are very similar to begin-end blocks. In fact, /* fork-join blocks are very similar to begin-end blocks. In fact,
from the parser's perspective there is no real difference. All we from the parser's perspective there is no real difference. All we
need to do is remember that this is a parallel block so that the need to do is remember that this is a parallel block so that the
@ -2690,28 +2772,34 @@ statement
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| event_control statement_opt | event_control attribute_list_opt statement_opt
{ PEventStatement*tmp = $1; { PEventStatement*tmp = $1;
if (tmp == 0) { if (tmp == 0) {
yyerror(@1, "error: Invalid event control."); yyerror(@1, "error: Invalid event control.");
$$ = 0; $$ = 0;
} else { } else {
tmp->set_statement($2); pform_attach_attributes($3, $2);
tmp->set_statement($3);
$$ = tmp; $$ = tmp;
} }
if ($2) delete $2;
} }
| '@' '*' statement_opt | '@' '*' attribute_list_opt statement_opt
{ PEventStatement*tmp = new PEventStatement; { PEventStatement*tmp = new PEventStatement;
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
tmp->set_statement($3); pform_attach_attributes($4, $3);
tmp->set_statement($4);
if ($3) delete $3;
$$ = tmp; $$ = tmp;
} }
| '@' '(' '*' ')' statement_opt | '@' '(' '*' ')' attribute_list_opt statement_opt
{ PEventStatement*tmp = new PEventStatement; { PEventStatement*tmp = new PEventStatement;
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
tmp->set_statement($5); pform_attach_attributes($6, $5);
tmp->set_statement($6);
if ($5) delete $5;
$$ = tmp; $$ = tmp;
} }
| lpvalue '=' expression ';' | lpvalue '=' expression ';'
@ -2796,7 +2884,7 @@ statement
delete $1; delete $1;
$$ = tmp; $$ = tmp;
} }
| identifier '(' expression_list ')' ';' | identifier '(' expression_list_proper ')' ';'
{ PCallTask*tmp = new PCallTask(*$1, *$3); { PCallTask*tmp = new PCallTask(*$1, *$3);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
@ -2804,6 +2892,19 @@ statement
delete $3; delete $3;
$$ = tmp; $$ = tmp;
} }
/* NOTE: The standard doesn't really support an empty argument list
between parentheses, but it seems natural, and people commonly
want it. So accept it explicitly. */
| identifier '(' ')' ';'
{ svector<PExpr*>pt (0);
PCallTask*tmp = new PCallTask(*$1, pt);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
| identifier ';' | identifier ';'
{ svector<PExpr*>pt (0); { svector<PExpr*>pt (0);
PCallTask*tmp = new PCallTask(*$1, pt); PCallTask*tmp = new PCallTask(*$1, pt);
@ -2820,14 +2921,18 @@ statement
; ;
statement_list statement_list
: statement_list statement : statement_list attribute_list_opt statement
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2); { pform_attach_attributes($3, $2);
svector<Statement*>*tmp = new svector<Statement*>(*$1, $3);
delete $1; delete $1;
if ($2) delete $2;
$$ = tmp; $$ = tmp;
} }
| statement | attribute_list_opt statement
{ svector<Statement*>*tmp = new svector<Statement*>(1); { pform_attach_attributes($2, $1);
(*tmp)[0] = $1; svector<Statement*>*tmp = new svector<Statement*>(1);
(*tmp)[0] = $2;
if ($1) delete $1;
$$ = tmp; $$ = tmp;
} }
; ;
@ -2848,6 +2953,13 @@ task_item
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_input K_signed range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, true,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
}
| K_output range_opt list_of_identifiers ';' | K_output range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT, false, = pform_make_task_ports(NetNet::POUTPUT, false,
@ -2855,6 +2967,13 @@ task_item
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_output K_signed range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT, true,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout range_opt list_of_identifiers ';' | K_inout range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT, false, = pform_make_task_ports(NetNet::PINOUT, false,
@ -2862,6 +2981,13 @@ task_item
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_inout K_signed range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT, true,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
}
; ;
task_item_list task_item_list

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: parse_api.h,v 1.3 2004/02/18 17:11:57 steve Exp $" #ident "$Id: parse_api.h,v 1.3.2.1 2005/08/13 00:45:54 steve Exp $"
#endif #endif
# include <stdio.h> # include <stdio.h>
@ -35,8 +35,8 @@ class PUdp;
* Verilog source into pform for elaboration. The parser adds modules * Verilog source into pform for elaboration. The parser adds modules
* to these maps as it compiles modules in the verilog source. * to these maps as it compiles modules in the verilog source.
*/ */
extern map<perm_string,Module*> pform_modules; extern std::map<perm_string,Module*> pform_modules;
extern map<perm_string,PUdp*> pform_primitives; extern std::map<perm_string,PUdp*> pform_primitives;
/* /*
* This code actually invokes the parser to make modules. The first * This code actually invokes the parser to make modules. The first
@ -47,10 +47,13 @@ extern map<perm_string,PUdp*> pform_primitives;
*/ */
extern int pform_parse(const char*path, FILE*file =0); extern int pform_parse(const char*path, FILE*file =0);
extern string vl_file; extern std::string vl_file;
/* /*
* $Log: parse_api.h,v $ * $Log: parse_api.h,v $
* Revision 1.3.2.1 2005/08/13 00:45:54 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.3 2004/02/18 17:11:57 steve * Revision 1.3 2004/02/18 17:11:57 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.129 2004/10/04 01:10:55 steve Exp $" #ident "$Id: pform.cc,v 1.129.2.1 2006/07/10 00:21:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -203,6 +203,19 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
return res; return res;
} }
void pform_attach_attributes(Statement*obj, svector<named_pexpr_t*>*attr)
{
if (obj == 0)
return;
if (attr == 0)
return;
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
named_pexpr_t*tmp = (*attr)[idx];
obj->attributes[tmp->name] = tmp->parm;
}
}
void pform_startmodule(const char*name, const char*file, unsigned lineno, void pform_startmodule(const char*name, const char*file, unsigned lineno,
svector<named_pexpr_t*>*attr) svector<named_pexpr_t*>*attr)
{ {
@ -1597,6 +1610,9 @@ int pform_parse(const char*path, FILE*file)
/* /*
* $Log: pform.cc,v $ * $Log: pform.cc,v $
* Revision 1.129.2.1 2006/07/10 00:21:53 steve
* Add support for full_case attribute.
*
* Revision 1.129 2004/10/04 01:10:55 steve * Revision 1.129 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $" #ident "$Id: pform.h,v 1.81.2.1 2006/07/10 00:21:53 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -37,6 +37,8 @@
# include <string> # include <string>
# include <list> # include <list>
# include <stdio.h> # include <stdio.h>
# include <cstring>
# include <cstdlib>
/* /*
* These classes implement the parsed form (P-form for short) of the * These classes implement the parsed form (P-form for short) of the
@ -219,6 +221,8 @@ extern void pform_set_attrib(perm_string name, perm_string key,
extern void pform_set_type_attrib(perm_string name, const string&key, extern void pform_set_type_attrib(perm_string name, const string&key,
char*value); char*value);
extern void pform_attach_attributes(Statement*obj, svector<named_pexpr_t*>*attr);
extern void pform_set_parameter(perm_string name, extern void pform_set_parameter(perm_string name,
bool signed_flag, bool signed_flag,
svector<PExpr*>*range, svector<PExpr*>*range,
@ -298,6 +302,9 @@ extern void pform_dump(ostream&out, Module*mod);
/* /*
* $Log: pform.h,v $ * $Log: pform.h,v $
* Revision 1.81.2.1 2006/07/10 00:21:53 steve
* Add support for full_case attribute.
*
* Revision 1.81 2004/08/26 04:02:04 steve * Revision 1.81 2004/08/26 04:02:04 steve
* Add support for localparam ranges. * Add support for localparam ranges.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.88 2004/10/04 01:10:55 steve Exp $" #ident "$Id: pform_dump.cc,v 1.88.2.1 2006/07/10 00:21:54 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -360,10 +360,14 @@ void PGModule::dump(ostream&out) const
out << " " << type_ << " "; out << " " << type_ << " ";
// If parameters are overridden by order, dump them. // If parameters are overridden by order, dump them.
if (overrides_) { if (overrides_ && overrides_->count() > 0) {
assert(parms_ == 0); assert(parms_ == 0);
out << "#("; out << "#(";
out << *((*overrides_)[0]);
if ((*overrides_)[0] == 0)
out << "<nil>";
else
out << *((*overrides_)[0]);
for (unsigned idx = 1 ; idx < overrides_->count() ; idx += 1) { for (unsigned idx = 1 ; idx < overrides_->count() ; idx += 1) {
out << "," << *((*overrides_)[idx]); out << "," << *((*overrides_)[idx]);
} }
@ -418,6 +422,19 @@ void Statement::dump(ostream&out, unsigned ind) const
out << setw(ind) << ""; out << setw(ind) << "";
out << "/* " << get_line() << ": " << typeid(*this).name() out << "/* " << get_line() << ": " << typeid(*this).name()
<< " */ ;" << endl; << " */ ;" << endl;
dump_attributes(out, ind+2);
}
void Statement::dump_attributes(ostream&out, unsigned ind) const
{
for (map<perm_string,PExpr*>::const_iterator idx = attributes.begin()
; idx != attributes.end()
; idx ++) {
out << setw(ind) << "" << "(* " << (*idx).first;
if ((*idx).second)
out << " = " << *(*idx).second;
out << " *)" << endl;
}
} }
void PAssign::dump(ostream&out, unsigned ind) const void PAssign::dump(ostream&out, unsigned ind) const
@ -487,6 +504,8 @@ void PCase::dump(ostream&out, unsigned ind) const
} }
out << " (" << *expr_ << ") /* " << get_line() << " */" << endl; out << " (" << *expr_ << ") /* " << get_line() << " */" << endl;
dump_attributes(out, ind+2);
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) { for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
PCase::Item*cur = (*items_)[idx]; PCase::Item*cur = (*items_)[idx];
@ -909,6 +928,9 @@ void PUdp::dump(ostream&out) const
/* /*
* $Log: pform_dump.cc,v $ * $Log: pform_dump.cc,v $
* Revision 1.88.2.1 2006/07/10 00:21:54 steve
* Add support for full_case attribute.
*
* Revision 1.88 2004/10/04 01:10:55 steve * Revision 1.88 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

19
scripts/devel-stub.conf Normal file
View File

@ -0,0 +1,19 @@
#
# This is a debug conf file that the scripts/devel-stub.sh script uses
# to control the ivl core. The contents of this file are normally written
# to a temporary file by the driver program, but for devel purposes, where
# the driver program is not used, this config substitutes.
#
# NOTE: DO NOT INSTALL THIS FILE!
#
iwidth:32
sys_func:vpi/system.sft
warnings:implicit
debug:eval_tree
debug:elaborate
debug:scope
debug:synth
debug:cprop
out:a.out
ivlpp:./ivlpp/ivlpp -D__ICARUS__ -L -Pfoo.pp
sys_func:scripts/devel-stub.sft

5
scripts/devel-stub.sft Normal file
View File

@ -0,0 +1,5 @@
# This is an example function table.
$realtime vpiSysFuncReal
$verywide vpiSysFuncSized 128 signed

14
scripts/devel-stub.sh Normal file
View File

@ -0,0 +1,14 @@
# This is a little developer convenience script to run the ivl core program
# in place with the stub target. It runs the ivl core verbose, with diagnostic
# output files enable, and without the driver program or preprocessor.
# It is useful only for development of the ivl core program.
#
# Run this script in the source directory for the ivl core program so that
# the patch to the other components is correct.
#
# NOTE: DO NOT INSTALL THIS FILE.
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl
echo "*** ivl command completed, rc=$?"

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: set_width.cc,v 1.34 2003/08/28 04:11:19 steve Exp $" #ident "$Id: set_width.cc,v 1.34.2.1 2005/03/05 01:36:16 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -167,12 +167,13 @@ bool NetEBDiv::set_width(unsigned w)
return w == expr_width(); return w == expr_width();
} }
/*
* The logical binary operators do not care what the widths of their
* operands are, the output is always 1 bit. The operands are
* self-determined, so a set_width is stopped here.
*/
bool NetEBLogic::set_width(unsigned w) bool NetEBLogic::set_width(unsigned w)
{ {
bool flag;
flag = left_->set_width(right_->expr_width());
if (!flag)
flag = right_->set_width(left_->expr_width());
return (w == 1); return (w == 1);
} }
@ -411,6 +412,9 @@ bool NetEUReduce::set_width(unsigned w)
/* /*
* $Log: set_width.cc,v $ * $Log: set_width.cc,v $
* Revision 1.34.2.1 2005/03/05 01:36:16 steve
* Fix set_width to allow binary logical operands to be self determined.
*
* Revision 1.34 2003/08/28 04:11:19 steve * Revision 1.34 2003/08/28 04:11:19 steve
* Spelling patch. * Spelling patch.
* *

View File

@ -1,8 +1,8 @@
# $Id: README-solaris_pkg.txt,v 1.2 2004/10/04 01:10:56 steve Exp $ # $Id: README-solaris_pkg.txt,v 1.2.2.1 2007/02/26 19:51:39 steve Exp $
Notes about the solaris package. Notes about the solaris package.
I. Installing a prebuild solaris package I. Installing a prebuilt solaris package
----------------------------------------- -----------------------------------------
To install the solaris package do the following as root on your machine: To install the solaris package do the following as root on your machine:
@ -24,10 +24,10 @@ To install the solaris package do the following as root on your machine:
this will install the package. The package will be registered under the this will install the package. The package will be registered under the
name "IVLver" name "IVLver"
II. Deinstalling the solaris package II. Uninstalling the solaris package
------------------------------------- -------------------------------------
To deinstall an installed solaris package do the following as root on your machine: To uninstall an installed solaris package do the following as root on your machine:
pkgrm IVLver pkgrm IVLver

View File

@ -1,7 +1,7 @@
PKG="IVLver" PKG="IVLver"
NAME="verilog" NAME="verilog"
ARCH="sparc" ARCH="sparc"
VERSION="0.7" VERSION="0.8"
CATEGORY="application" CATEGORY="application"
VENDOR="Icarus.com" VENDOR="Icarus.com"
EMAIL="steve@icarus.com" EMAIL="steve@icarus.com"

View File

@ -4,6 +4,7 @@ f none bin/iverilog 0755 bin bin
f none bin/iverilog-vpi 0755 bin bin f none bin/iverilog-vpi 0755 bin bin
f none bin/vvp 0755 bin bin f none bin/vvp 0755 bin bin
d none include 0755 bin bin d none include 0755 bin bin
f none include/_pli_types.h 0644 bin bin
f none include/acc_user.h 0644 bin bin f none include/acc_user.h 0644 bin bin
f none include/ivl_target.h 0644 bin bin f none include/ivl_target.h 0644 bin bin
f none include/veriuser.h 0644 bin bin f none include/veriuser.h 0644 bin bin
@ -11,12 +12,21 @@ f none include/vpi_user.h 0644 bin bin
d none lib 0755 bin bin d none lib 0755 bin bin
d none lib/ivl 0755 bin bin d none lib/ivl 0755 bin bin
f none lib/ivl/fpga.tgt 0644 bin bin f none lib/ivl/fpga.tgt 0644 bin bin
f none lib/ivl/fpga.conf 0644 bin bin
f none lib/ivl/fpga-s.conf 0644 bin bin
f none lib/ivl/iverilog.conf 0644 bin bin f none lib/ivl/iverilog.conf 0644 bin bin
f none lib/ivl/ivl 0755 bin bin f none lib/ivl/ivl 0755 bin bin
f none lib/ivl/ivlpp 0755 bin bin f none lib/ivl/ivlpp 0755 bin bin
f none lib/ivl/null.tgt 0644 bin bin f none lib/ivl/null.tgt 0644 bin bin
f none lib/ivl/null.conf 0644 bin bin
f none lib/ivl/null-s.conf 0644 bin bin
f none lib/ivl/system.vpi 0644 bin bin f none lib/ivl/system.vpi 0644 bin bin
f none lib/ivl/system.sft 0644 bin bin
f none lib/ivl/vvp.tgt 0644 bin bin f none lib/ivl/vvp.tgt 0644 bin bin
f none lib/ivl/vvp.conf 0644 bin bin
f none lib/ivl/vvp-s.conf 0644 bin bin
f none lib/ivl/xnf.conf 0644 bin bin
f none lib/ivl/xnf-s.conf 0644 bin bin
f none lib/libveriuser.a 0644 bin bin f none lib/libveriuser.a 0644 bin bin
f none lib/libvpi.a 0644 bin bin f none lib/libvpi.a 0644 bin bin
d none man 0755 bin bin d none man 0755 bin bin

View File

@ -21,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: svector.h,v 1.9 2003/07/23 02:35:44 steve Exp $" #ident "$Id: svector.h,v 1.9.2.1 2005/06/14 15:33:54 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -101,14 +101,17 @@ template <class TYPE> class svector {
* Override the implementation of the above template for the string * Override the implementation of the above template for the string
* type parameter. The initialization to nil works different here. * type parameter. The initialization to nil works different here.
*/ */
inline svector<string>::svector<string>(unsigned size) template <> inline svector<std::string>::svector(unsigned size)
: nitems_(size), items_(new string[size]) : nitems_(size), items_(new std::string[size])
{ {
} }
/* /*
* $Log: svector.h,v $ * $Log: svector.h,v $
* Revision 1.9.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.9 2003/07/23 02:35:44 steve * Revision 1.9 2003/07/23 02:35:44 steve
* Inline the svector<string> constructor. * Inline the svector<string> constructor.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: sync.cc,v 1.3 2002/09/24 00:58:35 steve Exp $" #ident "$Id: sync.cc,v 1.3.2.1 2007/05/30 17:48:54 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -57,7 +57,7 @@ bool NetEvWait::is_synchronous()
return true; //statement_->is_asynchronous(); return true; //statement_->is_asynchronous();
} }
bool NetProcTop::is_synchronous() bool NetProcTop::is_synchronous() const
{ {
if (type_ == NetProcTop::KINITIAL) if (type_ == NetProcTop::KINITIAL)
return false; return false;
@ -67,6 +67,9 @@ bool NetProcTop::is_synchronous()
/* /*
* $Log: sync.cc,v $ * $Log: sync.cc,v $
* Revision 1.3.2.1 2007/05/30 17:48:54 steve
* Support Latch synthesis (Alan Feldstein)
*
* Revision 1.3 2002/09/24 00:58:35 steve * Revision 1.3 2002/09/24 00:58:35 steve
* More detailed check of process edge events. * More detailed check of process edge events.
* *

2349
synth2.cc

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@
# include "config.h" # include "config.h"
# include "compiler.h" # include "compiler.h"
# include <stdio.h> # include <stdio.h>
# include <cstdlib>
# include <cstring>
/* /*
* Manage the information about system functions. This information is * Manage the information about system functions. This information is

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.108 2004/10/04 01:10:55 steve Exp $" #ident "$Id: t-dll-api.cc,v 1.108.2.5 2006/04/16 19:26:40 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -28,6 +28,9 @@
# include <malloc.h> # include <malloc.h>
#endif #endif
#include <stdexcept>
using std::invalid_argument;
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */ /* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key) extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
@ -481,6 +484,7 @@ extern "C" unsigned long ivl_expr_uvalue(ivl_expr_t net)
default: default:
assert(0); assert(0);
return 0UL;
} }
} }
@ -620,6 +624,19 @@ extern "C" const char* ivl_udp_name(ivl_udp_t net)
return net->name; return net->name;
} }
extern "C" unsigned ivl_lpm_attr_cnt(ivl_lpm_t net)
{
return net->nattr;
}
extern "C" ivl_attribute_t ivl_lpm_attr_val(ivl_lpm_t net, unsigned idx)
{
if (idx >= net->nattr)
return 0;
else
return net->attr + idx;
}
extern "C" const char* ivl_lpm_basename(ivl_lpm_t net) extern "C" const char* ivl_lpm_basename(ivl_lpm_t net)
{ {
return net->name; return net->name;
@ -686,6 +703,21 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
} }
} }
extern "C" ivl_nexus_t ivl_lpm_gate( ivl_lpm_t netPtr )
{
assert( netPtr );
switch ( netPtr->type )
{
case IVL_LPM_LATCH:
return netPtr->u_.latch.gatePtr;
default:
assert( false );
return 0;
}
}
extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net) extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
{ {
assert(net); assert(net);
@ -752,6 +784,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(idx < net->u_.arith.width); assert(idx < net->u_.arith.width);
return net->u_.arith.a[idx]; return net->u_.arith.a[idx];
case IVL_LPM_DEMUX:
assert(idx < net->u_.demux.width);
return net->u_.demux.d[idx];
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.width); assert(idx < net->u_.shift.width);
@ -765,6 +801,20 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
else else
return net->u_.ff.d.pins[idx]; return net->u_.ff.d.pins[idx];
case IVL_LPM_LATCH:
if( idx >= net->u_.latch.width )
{
throw invalid_argument( "idx too high" );
}
if ( net->u_.latch.width != 1U )
{
throw invalid_argument( "Only 1-wide latches are currently supported." );
}
return net->u_.latch.dataPtr;
default: default:
assert(0); assert(0);
return 0; return 0;
@ -788,6 +838,10 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
assert(idx < net->u_.arith.width); assert(idx < net->u_.arith.width);
return net->u_.arith.b[idx]; return net->u_.arith.b[idx];
case IVL_LPM_DEMUX:
assert(idx < net->u_.demux.width/net->u_.demux.size);
return net->u_.demux.bit_in[idx];
default: default:
assert(0); assert(0);
return 0; return 0;
@ -813,6 +867,22 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
return net->u_.ufunc.pins[base+idx]; return net->u_.ufunc.pins[base+idx];
} }
case IVL_LPM_RAM:
if (net->u_.ff.a.mem == 0) {
// This is an exploded RAM, so we use sdx and idx
// to address a nexa into the exploded ram.
if (sdx >= net->u_.ff.scnt)
return 0;
if (idx >= net->u_.ff.width)
return 0;
unsigned adr = sdx * net->u_.ff.width + idx;
return net->u_.ff.d.pins[adr];
} else {
// Normal RAM port does not have data2 nexa
return 0;
}
default: default:
assert(0); assert(0);
return 0; return 0;
@ -833,6 +903,18 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
} }
} }
extern "C" ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_FF:
return net->u_.ff.a.decode;
default:
assert(0);
return 0;
}
}
/* /*
* This function returns the hierarchical name for the LPM device. The * This function returns the hierarchical name for the LPM device. The
* name needs to be built up from the scope name and the lpm base * name needs to be built up from the scope name and the lpm base
@ -891,6 +973,20 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
else else
return net->u_.ff.q.pins[idx]; return net->u_.ff.q.pins[idx];
case IVL_LPM_LATCH:
if ( idx >= net->u_.latch.width )
{
throw invalid_argument( "idx too high" );
}
if ( net->u_.latch.width != 1U )
{
throw invalid_argument( "Only 1-wide latches are currently supported." );
}
return net->u_.latch.qPtr;
case IVL_LPM_MUX: case IVL_LPM_MUX:
assert(idx < net->u_.mux.width); assert(idx < net->u_.mux.width);
if (net->u_.mux.width == 1) if (net->u_.mux.width == 1)
@ -898,6 +994,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
else else
return net->u_.mux.q.pins[idx]; return net->u_.mux.q.pins[idx];
case IVL_LPM_DEMUX:
assert(idx < net->u_.demux.width);
return net->u_.demux.q[idx];
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.width); assert(idx < net->u_.shift.width);
@ -929,6 +1029,7 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
else else
return net->u_.ff.s.pins[idx]; return net->u_.ff.s.pins[idx];
case IVL_LPM_DECODE:
case IVL_LPM_MUX: case IVL_LPM_MUX:
assert(idx < net->u_.mux.swid); assert(idx < net->u_.mux.swid);
if (net->u_.mux.swid == 1) if (net->u_.mux.swid == 1)
@ -936,6 +1037,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
else else
return net->u_.mux.s.pins[idx]; return net->u_.mux.s.pins[idx];
case IVL_LPM_DEMUX:
assert(idx < net->u_.demux.awid);
return net->u_.demux.a[idx];
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.select); assert(idx < net->u_.shift.select);
@ -952,8 +1057,11 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
switch (net->type) { switch (net->type) {
case IVL_LPM_RAM: case IVL_LPM_RAM:
return net->u_.ff.swid; return net->u_.ff.swid;
case IVL_LPM_DECODE:
case IVL_LPM_MUX: case IVL_LPM_MUX:
return net->u_.mux.swid; return net->u_.mux.swid;
case IVL_LPM_DEMUX:
return net->u_.demux.awid;
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
return net->u_.shift.select; return net->u_.shift.select;
@ -970,6 +1078,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_FF: case IVL_LPM_FF:
case IVL_LPM_RAM: case IVL_LPM_RAM:
case IVL_LPM_MUX: case IVL_LPM_MUX:
case IVL_LPM_DEMUX:
return 0; return 0;
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
@ -984,7 +1093,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
return net->u_.shift.signed_flag; return net->u_.shift.signed_flag;
return 0; case IVL_LPM_DECODE:
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
return 0; return 0;
default: default:
@ -996,8 +1105,12 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
extern "C" unsigned ivl_lpm_size(ivl_lpm_t net) extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
{ {
switch (net->type) { switch (net->type) {
case IVL_LPM_DEMUX:
return net->u_.demux.size;
case IVL_LPM_MUX: case IVL_LPM_MUX:
return net->u_.mux.size; return net->u_.mux.size;
case IVL_LPM_RAM:
return net->u_.ff.scnt;
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
return net->u_.ufunc.ports - 1; return net->u_.ufunc.ports - 1;
default: default:
@ -1018,8 +1131,13 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
case IVL_LPM_FF: case IVL_LPM_FF:
case IVL_LPM_RAM: case IVL_LPM_RAM:
return net->u_.ff.width; return net->u_.ff.width;
case IVL_LPM_LATCH:
return net->u_.latch.width;
case IVL_LPM_DECODE:
case IVL_LPM_MUX: case IVL_LPM_MUX:
return net->u_.mux.width; return net->u_.mux.width;
case IVL_LPM_DEMUX:
return net->u_.demux.width;
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
@ -1046,7 +1164,7 @@ extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
assert(net); assert(net);
switch (net->type) { switch (net->type) {
case IVL_LPM_RAM: case IVL_LPM_RAM:
return net->u_.ff.mem; return net->u_.ff.a.mem;
default: default:
assert(0); assert(0);
return 0; return 0;
@ -1935,6 +2053,21 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/* /*
* $Log: t-dll-api.cc,v $ * $Log: t-dll-api.cc,v $
* Revision 1.108.2.5 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.108.2.4 2006/03/26 23:09:24 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.108.2.3 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.108.2.2 2006/02/25 05:03:29 steve
* Add support for negedge FFs by using attributes.
*
* Revision 1.108.2.1 2006/02/19 00:11:33 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.108 2004/10/04 01:10:55 steve * Revision 1.108 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-expr.cc,v 1.39 2004/06/17 16:06:19 steve Exp $" #ident "$Id: t-dll-expr.cc,v 1.39.2.2 2006/09/15 23:56:05 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -30,7 +30,8 @@
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
# include <malloc.h> # include <malloc.h>
#endif #endif
# include <stdlib.h> # include <cstdlib>
# include <cstring>
/* /*
* This is a little convenience function for converting a NetExpr * This is a little convenience function for converting a NetExpr
@ -222,12 +223,73 @@ void dll_target::expr_memory(const NetEMemory*net)
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(cur); assert(cur);
cur->type_ = IVL_EX_MEMORY; const NetMemory*mem = net->memory();
cur->value_ = IVL_VT_VECTOR;
cur->width_= net->expr_width(); if (const NetNet*reg = mem->reg_from_explode()) {
cur->signed_ = net->has_sign()? 1 : 0;
cur->u_.memory_.mem_ = find_memory(des_, net->memory()); if (expr_ == 0) {
cur->u_.memory_.idx_ = expr_; // If there is no index expression for the
// exploded memory, then replace it with the
// entire exploded reg.
cur->type_ = IVL_EX_SIGNAL;
cur->value_ = IVL_VT_VECTOR;
cur->width_= reg->pin_count();
cur->signed_ = net->has_sign()? 1 : 0;
cur->u_.signal_.sig = find_signal(des_, reg);
cur->u_.signal_.lsi = 0;
cur->u_.signal_.msi = cur->width_ - 1;
} else {
cur->type_ = IVL_EX_SELECT;
cur->value_ = IVL_VT_VECTOR;
cur->width_ = net->expr_width();
cur->signed_ = net->has_sign()? 1 : 0;
// Create an expression form of the exploded
// memory. This is what the select will apply to.
ivl_expr_t sig = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
sig->type_ = IVL_EX_SIGNAL;
sig->value_ = IVL_VT_VECTOR;
sig->width_ = reg->pin_count();
sig->signed_ = 0;
sig->u_.signal_.sig = find_signal(des_, reg);
assert(sig->u_.signal_.sig);
sig->u_.signal_.lsi = 0;
sig->u_.signal_.msi = reg->pin_count()-1;
cur->u_.binary_.lef_ = sig;
// Create an expression of the address calculation.
cur->u_.binary_.rig_ = expr_;
if (cur->width_ > 1) {
ivl_expr_t mul = (ivl_expr_t)calloc(2, sizeof(struct ivl_expr_s));
ivl_expr_t fac = mul+1;
fac->type_ = IVL_EX_ULONG;
fac->value_ = IVL_VT_VECTOR;
fac->width_ = 8*sizeof(cur->width_);
fac->signed_= 0;
fac->u_.ulong_.value = cur->width_;
mul->type_ = IVL_EX_BINARY;
mul->value_ = IVL_VT_VECTOR;
mul->width_ = fac->width_;
mul->signed_= 0;
mul->u_.binary_.op_ = '*';
mul->u_.binary_.lef_ = cur->u_.binary_.rig_;
mul->u_.binary_.rig_ = fac;
cur->u_.binary_.rig_ = mul;
}
}
} else {
cur->type_ = IVL_EX_MEMORY;
cur->value_ = IVL_VT_VECTOR;
cur->width_= net->expr_width();
cur->signed_ = net->has_sign()? 1 : 0;
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
cur->u_.memory_.idx_ = expr_;
}
expr_ = cur; expr_ = cur;
} }
@ -604,6 +666,12 @@ void dll_target::expr_variable(const NetEVariable*net)
/* /*
* $Log: t-dll-expr.cc,v $ * $Log: t-dll-expr.cc,v $
* Revision 1.39.2.2 2006/09/15 23:56:05 steve
* Special handling of exploded memory arguments.
*
* Revision 1.39.2.1 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.39 2004/06/17 16:06:19 steve * Revision 1.39 2004/06/17 16:06:19 steve
* Help system function signedness survive elaboration. * Help system function signedness survive elaboration.
* *

View File

@ -32,7 +32,8 @@
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
# include <malloc.h> # include <malloc.h>
#endif #endif
# include <stdlib.h> # include <cstdlib>
# include <cstring>
bool dll_target::process(const NetProcTop*net) bool dll_target::process(const NetProcTop*net)

253
t-dll.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.131 2004/10/04 01:10:55 steve Exp $" #ident "$Id: t-dll.cc,v 1.131.2.8 2006/07/23 19:42:35 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -31,7 +31,11 @@
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
# include <malloc.h> # include <malloc.h>
#endif #endif
# include <stdlib.h> # include <cstdlib>
# include <cstring>
#include <new> // standard operator new
using std::bad_alloc;
#if defined(__WIN32__) #if defined(__WIN32__)
@ -940,6 +944,8 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
obj->delay[1] = net->fall_time(); obj->delay[1] = net->fall_time();
obj->delay[2] = net->decay_time(); obj->delay[2] = net->decay_time();
logic_attributes(obj,net);
scope_add_logic(scope, obj); scope_add_logic(scope, obj);
} }
@ -965,6 +971,8 @@ bool dll_target::net_function(const NetUserFunc*net)
obj->type = IVL_LPM_UFUNC; obj->type = IVL_LPM_UFUNC;
obj->name = net->name(); obj->name = net->name();
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
obj->attr = 0;
obj->nattr = 0;
assert(obj->scope); assert(obj->scope);
/* Get the definition of the function and save it. */ /* Get the definition of the function and save it. */
@ -1104,9 +1112,11 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
obj->type = IVL_LPM_SUB; obj->type = IVL_LPM_SUB;
else else
obj->type = IVL_LPM_ADD; obj->type = IVL_LPM_ADD;
obj->name = net->name(); // NetAddSub names are permallocated. obj->name = net->name(); // NetAddSub names are permallocated
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
obj->attr = 0;
obj->nattr = 0;
assert(obj->scope); assert(obj->scope);
obj->u_.arith.signed_flag = 0; obj->u_.arith.signed_flag = 0;
@ -1176,6 +1186,8 @@ void dll_target::lpm_clshift(const NetCLShift*net)
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_SHIFTL; obj->type = IVL_LPM_SHIFTL;
obj->name = net->name(); obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -1243,6 +1255,8 @@ void dll_target::lpm_clshift(const NetCLShift*net)
void dll_target::lpm_compare(const NetCompare*net) void dll_target::lpm_compare(const NetCompare*net)
{ {
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->attr = 0;
obj->nattr = 0;
obj->name = net->name(); // NetCompare names are permallocated obj->name = net->name(); // NetCompare names are permallocated
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
@ -1357,6 +1371,8 @@ void dll_target::lpm_divide(const NetDivide*net)
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_DIVIDE; obj->type = IVL_LPM_DIVIDE;
obj->name = net->name(); obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -1427,6 +1443,8 @@ void dll_target::lpm_modulo(const NetModulo*net)
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_MOD; obj->type = IVL_LPM_MOD;
obj->name = net->name(); obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -1489,16 +1507,131 @@ void dll_target::lpm_modulo(const NetModulo*net)
scope_add_lpm(obj->scope, obj); scope_add_lpm(obj->scope, obj);
} }
bool dll_target::lpm_decode(const NetDecode*net)
{
return true;
}
ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net)
{
if (net == 0)
return 0;
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_DECODE;
obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
obj->scope = find_scope(des_, net->scope());
obj->u_.mux.swid = net->awidth();
obj->u_.mux.size = 0;
obj->u_.mux.width = net->width();
obj->u_.mux.d = 0;
if (obj->u_.mux.swid > 1) {
obj->u_.mux.s.pins = new ivl_nexus_t[obj->u_.mux.swid];
for (unsigned idx = 0 ; idx < obj->u_.mux.swid ; idx += 1) {
const Nexus*nex = net->pin_Address(idx).nexus();
assert(nex->t_cookie());
obj->u_.mux.s.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.mux.s.pins[idx], obj, idx,
IVL_DR_HiZ, IVL_DR_HiZ);
}
} else {
assert(obj->u_.mux.swid == 1);
const Nexus*nex = net->pin_Address(0).nexus();
assert(nex->t_cookie());
obj->u_.mux.s.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.mux.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
}
scope_add_lpm(obj->scope, obj);
return obj;
}
bool dll_target::lpm_demux(const NetDemux*net)
{
unsigned idx;
unsigned width = net->width();
unsigned awid = net->awidth();
unsigned size = net->size();
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_DEMUX;
obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.demux.width = width;
obj->u_.demux.awid = awid;
obj->u_.demux.size = net->size();
ivl_nexus_t*tmp = new ivl_nexus_t [2*width + awid + width/size];
obj->u_.demux.q = tmp;
obj->u_.demux.d = tmp + width;
obj->u_.demux.a = tmp + 2*width;
obj->u_.demux.bit_in = tmp + 2*width + awid;
for (idx = 0 ; idx < width ; idx += 1) {
const Nexus*nex = net->pin_Q(idx).nexus();
obj->u_.demux.q[idx] = (ivl_nexus_t) nex->t_cookie();
/* It is possible, but unlikely, that the Q is unused. */
if (obj->u_.demux.q[idx])
nexus_lpm_add(obj->u_.demux.q[idx], obj, idx,
IVL_DR_STRONG, IVL_DR_STRONG);
}
for (idx = 0 ; idx < width ; idx += 1) {
const Nexus*nex = net->pin_Data(idx).nexus();
assert(nex->t_cookie());
obj->u_.demux.d[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.demux.d[idx], obj, idx,
IVL_DR_HiZ, IVL_DR_HiZ);
}
for (idx = 0 ; idx < awid ; idx += 1) {
const Nexus*nex = net->pin_Address(idx).nexus();
assert(nex->t_cookie());
obj->u_.demux.a[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.demux.a[idx], obj, idx,
IVL_DR_HiZ, IVL_DR_HiZ);
}
for (idx = 0 ; idx < width/size ; idx += 1) {
const Nexus*nex = net->pin_WriteData(idx).nexus();
assert(nex->t_cookie());
obj->u_.demux.bit_in[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.demux.bit_in[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
obj->nattr = net->attr_cnt();
obj->attr = fill_in_attributes(net);
scope_add_lpm(obj->scope, obj);
return true;
}
void dll_target::lpm_ff(const NetFF*net) void dll_target::lpm_ff(const NetFF*net)
{ {
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_FF; obj->type = IVL_LPM_FF;
obj->name = net->name(); obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
obj->u_.ff.a.decode = lpm_decode_ff_(net->get_demux());
assert(obj->scope); assert(obj->scope);
obj->u_.ff.width = net->width(); obj->u_.ff.width = net->width();
obj->nattr = net->attr_cnt();
obj->attr = fill_in_attributes(net);
scope_add_lpm(obj->scope, obj); scope_add_lpm(obj->scope, obj);
const Nexus*nex; const Nexus*nex;
@ -1605,18 +1738,52 @@ void dll_target::lpm_ff(const NetFF*net)
} }
} }
void dll_target::lpm_latch( const NetLatch *latchPtr )
{
try
{
ivl_lpm_s *objPtr = new ivl_lpm_s;
objPtr->type = IVL_LPM_LATCH;
objPtr->name = latchPtr->name();
objPtr->scope = find_scope( des_, latchPtr->scope() );
assert( objPtr->scope ); // C++ programmers prefer using exceptions rather than assertions.
objPtr->u_.latch.width = latchPtr->width();
objPtr->nattr = latchPtr->attr_cnt();
objPtr->attr = fill_in_attributes( latchPtr );
scope_add_lpm( objPtr->scope, objPtr );
// Set the gate signal to point to the nexus, and the nexus to point back to this device.
const Nexus *const nexPtr = latchPtr->pin_Gate().nexus();
}
catch ( bad_alloc &memoryAllocationException )
{
cerr << "Exception occurred: " << memoryAllocationException.what() << endl;
}
} // end function lpm_latch
void dll_target::lpm_ram_dq(const NetRamDq*net) void dll_target::lpm_ram_dq(const NetRamDq*net)
{ {
ivl_memory_t mem = find_memory(des_, net->mem());
assert(mem);
const NetNet*ereg = net->mem()->reg_from_explode();
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_RAM; obj->type = IVL_LPM_RAM;
obj->name = net->name(); obj->name = net->name();
obj->u_.ff.mem = find_memory(des_, net->mem()); obj->attr = 0;
assert(obj->u_.ff.mem); obj->nattr = 0;
obj->u_.ff.a.mem = ereg? 0 : mem;
obj->scope = find_scope(des_, net->mem()->scope()); obj->scope = find_scope(des_, net->mem()->scope());
assert(obj->scope); assert(obj->scope);
obj->u_.ff.width = net->width(); obj->u_.ff.width = net->width();
obj->u_.ff.swid = net->awidth(); obj->u_.ff.swid = net->awidth();
obj->u_.ff.scnt = net->mem()->count();
scope_add_lpm(obj->scope, obj); scope_add_lpm(obj->scope, obj);
@ -1626,6 +1793,7 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
// the clock input. // the clock input.
bool has_write_port = net->pin_InClock().is_linked(); bool has_write_port = net->pin_InClock().is_linked();
assert( ereg? !has_write_port : 1 );
// Connect the write clock and write enable // Connect the write clock and write enable
@ -1717,6 +1885,21 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
IVL_DR_STRONG, IVL_DR_STRONG); IVL_DR_STRONG, IVL_DR_STRONG);
} }
} }
if (ereg) {
unsigned count = obj->u_.ff.width * obj->u_.ff.scnt;
assert(ereg->pin_count() == count);
obj->u_.ff.d.pins = new ivl_nexus_t [count];
for (unsigned idx = 0 ; idx < count ; idx += 1) {
nex = ereg->pin(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
}
} }
void dll_target::lpm_mult(const NetMult*net) void dll_target::lpm_mult(const NetMult*net)
@ -1724,6 +1907,8 @@ void dll_target::lpm_mult(const NetMult*net)
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_MULT; obj->type = IVL_LPM_MULT;
obj->name = net->name(); obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -1803,7 +1988,9 @@ void dll_target::lpm_mux(const NetMux*net)
{ {
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_MUX; obj->type = IVL_LPM_MUX;
obj->name = net->name(); // The NetMux perallocates its name. obj->name = net->name(); // NetMux names are permallocated
obj->attr = 0;
obj->nattr = 0;
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -1828,10 +2015,34 @@ void dll_target::lpm_mux(const NetMux*net)
for (unsigned idx = 0 ; idx < obj->u_.mux.width ; idx += 1) { for (unsigned idx = 0 ; idx < obj->u_.mux.width ; idx += 1) {
nex = net->pin_Result(idx).nexus(); nex = net->pin_Result(idx).nexus();
assert(nex->t_cookie()); #if 0
if (! nex->t_cookie()) {
cerr << net->get_line() << ": internal error: "
<< "broken mux. name=" << net->name()
<< ", width=" << obj->u_.mux.width
<< ", swid=" << obj->u_.mux.swid << endl;
for (unsigned tmp = 0; tmp < obj->u_.mux.width; tmp += 1) {
const Nexus*tmpn = net->pin_Result(tmp).nexus();
if (tmpn->t_cookie() == 0)
continue;
cerr << net->get_line() << ": XXXX "
<< "Result(" << tmp << ") : "
<< tmpn->name() << endl;
}
}
#endif
obj->u_.mux.q.pins[idx] = (ivl_nexus_t) nex->t_cookie(); obj->u_.mux.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG); /* It is possible (although unlikely) that the
result bit of the mux is not used. This can
happen, for example, if the output is
overridden in the HDL. In that case, skip
it. But if the bit is used, then add it to the
nexus. */
if (obj->u_.mux.q.pins[idx])
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
} }
} }
@ -2180,6 +2391,30 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.131.2.8 2006/07/23 19:42:35 steve
* Handle statement output override better in blocks.
*
* Revision 1.131.2.7 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.131.2.6 2006/03/26 23:09:24 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.131.2.5 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.131.2.4 2006/02/25 05:03:29 steve
* Add support for negedge FFs by using attributes.
*
* Revision 1.131.2.3 2006/02/19 00:11:34 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.131.2.2 2006/01/21 21:42:33 steve
* When mux has wide select but sparse choices, use 1hot translation.
*
* Revision 1.131.2.1 2005/02/19 16:39:31 steve
* Spellig fixes.
*
* Revision 1.131 2004/10/04 01:10:55 steve * Revision 1.131 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

47
t-dll.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.115 2004/10/04 01:10:56 steve Exp $" #ident "$Id: t-dll.h,v 1.115.2.5 2006/04/16 19:26:40 steve Exp $"
#endif #endif
# include "target.h" # include "target.h"
@ -76,8 +76,11 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_add_sub(const NetAddSub*); void lpm_add_sub(const NetAddSub*);
void lpm_clshift(const NetCLShift*); void lpm_clshift(const NetCLShift*);
void lpm_compare(const NetCompare*); void lpm_compare(const NetCompare*);
bool lpm_decode(const NetDecode*);
bool lpm_demux(const NetDemux*);
void lpm_divide(const NetDivide*); void lpm_divide(const NetDivide*);
void lpm_ff(const NetFF*); void lpm_ff(const NetFF*);
void lpm_latch( const NetLatch * );
void lpm_modulo(const NetModulo*); void lpm_modulo(const NetModulo*);
void lpm_mult(const NetMult*); void lpm_mult(const NetMult*);
void lpm_mux(const NetMux*); void lpm_mux(const NetMux*);
@ -162,6 +165,8 @@ struct dll_target : public target_t, public expr_scan_t {
void add_root(ivl_design_s &des_, const NetScope *s); void add_root(ivl_design_s &des_, const NetScope *s);
ivl_lpm_t lpm_decode_ff_(const NetDecode*);
void sub_off_from_expr_(long); void sub_off_from_expr_(long);
void mul_expr_by_const_(long); void mul_expr_by_const_(long);
@ -290,10 +295,14 @@ struct ivl_lpm_s {
ivl_scope_t scope; ivl_scope_t scope;
perm_string name; perm_string name;
struct ivl_attribute_s*attr;
unsigned nattr;
union { union {
struct ivl_lpm_ff_s { struct ivl_lpm_ff_s {
unsigned width; unsigned width;
unsigned swid; // ram only unsigned swid; // ram only
unsigned scnt;
ivl_nexus_t clk; ivl_nexus_t clk;
ivl_nexus_t we; ivl_nexus_t we;
ivl_nexus_t aclr; ivl_nexus_t aclr;
@ -312,11 +321,22 @@ struct ivl_lpm_s {
ivl_nexus_t*pins; ivl_nexus_t*pins;
ivl_nexus_t pin; ivl_nexus_t pin;
} s; } s;
ivl_memory_t mem; // ram only union {
ivl_memory_t mem; // ram only
ivl_lpm_t decode; // FF only
} a;
ivl_expr_t aset_value; ivl_expr_t aset_value;
ivl_expr_t sset_value; ivl_expr_t sset_value;
} ff; } ff;
struct ivl_lpm_latch_s
{
unsigned width;
ivl_nexus_s *gatePtr;
ivl_nexus_s *qPtr;
ivl_nexus_s *dataPtr;
} latch;
struct ivl_lpm_mux_s { struct ivl_lpm_mux_s {
unsigned width; unsigned width;
unsigned size; unsigned size;
@ -332,6 +352,14 @@ struct ivl_lpm_s {
} s; } s;
} mux; } mux;
struct ivl_lpm_demux_s {
unsigned width;
unsigned awid;
unsigned size;
ivl_nexus_t*bit_in;
ivl_nexus_t *q,*d,*a;
} demux;
struct ivl_lpm_shift_s { struct ivl_lpm_shift_s {
unsigned width; unsigned width;
unsigned select; unsigned select;
@ -684,6 +712,21 @@ struct ivl_variable_s {
/* /*
* $Log: t-dll.h,v $ * $Log: t-dll.h,v $
* Revision 1.115.2.5 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.115.2.4 2006/03/26 23:09:25 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.115.2.3 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.115.2.2 2006/02/25 05:03:30 steve
* Add support for negedge FFs by using attributes.
*
* Revision 1.115.2.1 2006/02/19 00:11:34 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.115 2004/10/04 01:10:56 steve * Revision 1.115 2004/10/04 01:10:56 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $" #ident "$Id: target.cc,v 1.69.2.2 2006/03/26 23:09:25 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -101,6 +101,20 @@ void target_t::lpm_compare(const NetCompare*)
"Unhandled NetCompare." << endl; "Unhandled NetCompare." << endl;
} }
bool target_t::lpm_decode(const NetDecode*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetDecode." << endl;
return false;
}
bool target_t::lpm_demux(const NetDemux*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetDemux." << endl;
return false;
}
void target_t::lpm_divide(const NetDivide*) void target_t::lpm_divide(const NetDivide*)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
@ -119,6 +133,11 @@ void target_t::lpm_ff(const NetFF*)
"Unhandled NetFF." << endl; "Unhandled NetFF." << endl;
} }
void target_t::lpm_latch( const NetLatch * )
{
cerr << "target (" << typeid( *this ).name() << "): Unhandled NetLatch." << endl;
}
void target_t::lpm_mult(const NetMult*) void target_t::lpm_mult(const NetMult*)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
@ -420,6 +439,12 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/* /*
* $Log: target.cc,v $ * $Log: target.cc,v $
* Revision 1.69.2.2 2006/03/26 23:09:25 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.69.2.1 2006/02/19 00:11:34 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.69 2004/05/31 23:34:39 steve * Revision 1.69 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * function return values to allow for better

View File

@ -19,10 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $" #ident "$Id: target.h,v 1.65.2.2 2006/03/26 23:09:25 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
#include "NetLatch.h"
/* /*
* This header file describes the types and constants used to describe * This header file describes the types and constants used to describe
@ -79,9 +80,12 @@ struct target_t {
virtual void lpm_add_sub(const NetAddSub*); virtual void lpm_add_sub(const NetAddSub*);
virtual void lpm_clshift(const NetCLShift*); virtual void lpm_clshift(const NetCLShift*);
virtual void lpm_compare(const NetCompare*); virtual void lpm_compare(const NetCompare*);
virtual bool lpm_decode(const NetDecode*);
virtual bool lpm_demux(const NetDemux*);
virtual void lpm_divide(const NetDivide*); virtual void lpm_divide(const NetDivide*);
virtual void lpm_modulo(const NetModulo*); virtual void lpm_modulo(const NetModulo*);
virtual void lpm_ff(const NetFF*); virtual void lpm_ff(const NetFF*);
virtual void lpm_latch( const NetLatch * );
virtual void lpm_mult(const NetMult*); virtual void lpm_mult(const NetMult*);
virtual void lpm_mux(const NetMux*); virtual void lpm_mux(const NetMux*);
virtual void lpm_ram_dq(const NetRamDq*); virtual void lpm_ram_dq(const NetRamDq*);
@ -170,6 +174,12 @@ extern const struct target *target_table[];
/* /*
* $Log: target.h,v $ * $Log: target.h,v $
* Revision 1.65.2.2 2006/03/26 23:09:25 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.65.2.1 2006/02/19 00:11:34 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.65 2004/05/31 23:34:39 steve * Revision 1.65 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * function return values to allow for better

6
tgt-edif/.cvsignore Normal file
View File

@ -0,0 +1,6 @@
configure
Makefile
edif.tgt
dep
config.status
config.log

46
tgt-edif/LICENSE.txt Normal file
View File

@ -0,0 +1,46 @@
The tgt-edif files are licensed differently from the rest of Icarus
Verilog. These files are:
--
Copyright (c) 2005 Stephen Williams
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
The purpose of the different license here is to allow licensees to use
these files to make EDIF based code generators that use these common
functions without statically linking to GPL files from elsewhere
within Icarus Verilog.
As a reminder, while this more relaxed license is here to allow
entities to make closed source (binary) code generators, this is not
intended to effect the GPL standing of the rest of Icarus Verilog
source. THIS RELAXED LICENSE APPLIES ONLY TO FILES SPECIFICALLY MARKED
WITH THIS NEW LICENSE. Furthermore, all rights remain reserved. Note
specifically the requirement for you to reproduce notices in your
documentation.

148
tgt-edif/Makefile.in Normal file
View File

@ -0,0 +1,148 @@
#
# Copyright (c) 2005 Stephen Williams
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#ident "$Id: Makefile.in,v 1.1.2.3 2006/05/08 04:33:36 steve Exp $"
#
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
mandir = @mandir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
RANLIB = @RANLIB@
MAN = @MAN@
PS2pdf = @ps2pdf@
CPPFLAGS = @ident_support@ -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
all: dep edif.tgt
dep:
mkdir dep
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
D = d-lpm.o d-virtex.o xilinx.o
O = edif.o device.o target.o gates.o generic.o $D
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
TGTDEPLIBS=../libivl.a
else
TGTLDFLAGS=
TGTDEPLIBS=
endif
edif.tgt: tables.o libedif_tgt.a $(TGTDEPLIBS)
$(CC) @shared@ -o $@ tables.o libedif_tgt.a $(TGTLDFLAGS)
libedif_tgt.a: $O
rm -f libedif_tgt.a
ar cqv libedif_tgt.a $O
$(RANLIB) libedif_tgt.a
iverilog-edif.ps: $(srcdir)/iverilog-edif.man
$(MAN) -t $(srcdir)/iverilog-edif.man > iverilog-edif.ps
iverilog-edif.pdf: iverilog-edif.ps
$(PS2PDF) iverilog-edif.ps iverilog-edif.pdf
Makefile: Makefile.in config.status
./config.status
clean:
rm -rf *.o dep edif.tgt
distclean: clean
rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
check: all
ifeq (@WIN32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC =
else
ifeq ($(PS2PDF),none)
#INSTALL_DOC = $(mandir)/man1/iverilog-edif.1
else
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
#all: iverilog-edif.pdf
endif
endif
else
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
#INSTALL_DOCDIR = $(mandir)/man1
endif
install: all installdirs $(libdir)/ivl$(suffix)/edif.tgt $(INSTALL_DOC) $(libdir)/ivl$(suffix)/edif.conf $(libdir)/ivl$(suffix)/edif-s.conf
$(libdir)/ivl$(suffix)/edif.tgt: ./edif.tgt
$(INSTALL_PROGRAM) ./edif.tgt $(libdir)/ivl$(suffix)/edif.tgt
$(libdir)/ivl$(suffix)/edif.conf: $(srcdir)/edif.conf
$(INSTALL_DATA) $(srcdir)/edif.conf $(libdir)/ivl$(suffix)/edif.conf
$(libdir)/ivl$(suffix)/edif-s.conf: $(srcdir)/edif-s.conf
$(INSTALL_DATA) $(srcdir)/edif-s.conf $(libdir)/ivl$(suffix)/edif-s.conf
$(mandir)/man1/iverilog-edif$(suffix).1: $(srcdir)/iverilog-edif.man
$(INSTALL_DATA) $(srcdir)/iverilog-edif.man $(mandir)/man1/iverilog-edif$(suffix).1
$(prefix)/iverilog-edif$(suffix).pdf: iverilog-edif.pdf
$(INSTALL_DATA) iverilog-edif.pdf $(prefix)/iverilog-edif$(suffix).pdf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl$(suffix)
uninstall:
rm -f $(libdir)/ivl$(suffix)/edif.tgt
rm -f $(INSTALL_DOC)
rm -f $(libdir)/ivl$(suffix)/edif-s.conf
rm -f $(libdir)/ivl$(suffix)/edif.conf
-include $(patsubst %.o, dep/%.d, $O)

32
tgt-edif/configure.in Normal file
View File

@ -0,0 +1,32 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(edif.conf)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_CHECK_PROGS(MAN,man,none)
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
AC_CANONICAL_HOST
# $host
AX_ENABLE_SUFFIX
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
AC_CHECK_HEADERS(malloc.h)
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# Compiler option for position independent code, needed when making shared objects.
AX_C_PICFLAG
# linker options when building a shared library
AX_LD_SHAREDLIB_OPTS
AX_CPP_IDENT
AC_OUTPUT(Makefile)

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