Compare commits

..
371 Commits
Author SHA1 Message Date
Stephen Williams afa2478801 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-06-09 16:58:21 -07:00
Stephen Williams 79feb44f10 Turn of concat output scheduling.
We really want lazy processing of concatenation because it has multiple
inputs and lazy processing should (in theory) prevent redundant and
useless propagations through the net.

But enabling it seems to cause many tests in the regression test suite
to fail to compare their results. There are races in many tests that
are interacting badly with this feature. So for now, ifdef it out.
2008-06-09 16:57:51 -07:00
Stephen Williams c03d76a0d7 Do not do lazy processing of part selects.
It doesn't really make any sense to do lazy processing of part selects,
but it is possible to use the part select position to more toroughly
check for changes in output and suppress non-changes. In particular,
we only need to check that the output part actually changes, and by the
way we only need to save those bits for the next go-round.

We do want to make sure that the very first input causes an output,
though, so that time-0 values get propagated.
2008-06-09 16:46:06 -07:00
Stephen Williams a2dc1e0a29 Add means for &A<> to index using a calculated index.
This is not a solution to all the problems, but is a better catch-all
then what is currently there. Allow the index field to be a T<> that
accesses the thread to get the address index.

Note that the lexor.lex currently returns the T<> as a T_SYMBOL, and the
users of T_SYMBOL objects need to interpret the meaning. This is
probably not the best idea, in light of all the other *<> formats that
now exist.
2008-06-08 21:38:35 -07:00
Stephen Williams 6a1235ac28 Rework parameter indexed part select up.
Indexed part select reworked to be more compact and more like the
part select.
2008-06-08 19:29:00 -07:00
Stephen Williams 7aebff2a86 Fix up parameter name part select
Part select of parameter names is fixed up to be structurally similar
to part select of signals, and also to behave similarly. (Though not
identically, for reason.)
2008-06-08 07:34:45 -07:00
Stephen Williams b31124983a Allow part selects to fall off the ends of the selected identifier
Part selects to signals are allowed to be off the ends of the signal
itself. The bits that are beyond the vector return X. This may mean
creating constant X bits on one or both ends of the result.
2008-06-06 22:05:17 -07:00
Larry Doolittle f256dfe16e Add missing include to vvp_island.cc
Add # include <string.h>, needed for compilation with gcc-4.3
2008-06-06 20:48:23 -07:00
Cary R 7c152685dc Clean up more compiletf routines, etc.
This patch cleans up some of the code to use common compiletf
routines where appropriate. It also adds code to print the
number of extra arguments and cleans up the messages a bit.
2008-06-06 20:44:21 -07:00
Stephen Williams 5d86dd0bbd Merge branch 'verilog-ams' 2008-06-06 20:39:42 -07:00
Cary R 4f97321c75 Add more array word properties.
This patch adds more array word properties.
2008-06-06 20:36:55 -07:00
Stephen Williams d0f303463d ASSIGN transfer data to scheduler efficiently/permalloc vvp_net_t objects.
The vvp_net_t objects are never deleted, so overload the new operator
to do a more space efficient permanent allocation.

The %assign/v instruction copied the vvp_vector4_t object needlessly
on its way to the scheduler. Eliminate that duplication.
2008-06-06 19:50:44 -07:00
Stephen Williams 35fe8fae00 Have vvp_vector8_t avoid allocating tiny scalar arrays. 2008-06-06 16:36:43 -07:00
Stephen Williams 2e95a740da Rework scheduling of concat, part, buf/not and resolv for efficiency.
The concat and resolv functors are best evaluated lazily, because each
evaluation is costly and there is a high probability that an evaluation
will be invalidated when new input comes in.

Also optimization the recv_vec4_pv method of the resolver, which is
commonly used, and adjust the order of handling of vvp_fun_part to
work more efficiently.
2008-06-06 15:31:22 -07:00
Stephen Williams 2f4e5bf5b6 Obvious optimizations of vvp_vector8_t handling.
The vvp_vector8_t constructor and destructor involve memory allocation
so it is best to pass these objects by reference as much as possible.

Also rework the resolver functor to only perform resolution after inputs
are in so that it doesn't get needlessly repeated. This eliminates many
resolve function calls, as well as activations throughout the net.

Also have the islands take more care not to perform resolution if the
inputs aren't really different.
2008-06-06 11:12:07 -07:00
Stephen Williams 7e478cdeb8 Merge branch 'master' into verilog-ams 2008-06-05 21:52:12 -07:00
Stephen Williams 2576543bb5 Add support for exclude of a point
Parameter value ranges support the exclude of a point as well as
range, so add the syntax to support that case. Internally it is
handled as a degenerate range, but the parse and initial elaboration
need to know about it.
2008-06-05 21:49:49 -07:00
Cary R e453b347f4 Add missing functions to ivl.def
This patch adds ivl_island_flag_set and ivl_island_flag_test
to the ivl.def file. This is needed by both Cygwin and MinGW.
2008-06-05 14:41:49 -07:00
Stephen Williams f132e09475 Fix default parameter type if localparams are present.
localparam declarations were messing up the state of parser variables
so that the default types of following parameters got messed up.
2008-06-05 14:38:56 -07:00
Stephen Williams 2ee976d1c0 Compile problems after merge with verilog-ams
The NetPartSelect::BI enumeration value does not exist any more.
2008-06-05 11:06:54 -07:00
Stephen Williams 30570adf31 Merge branch 'master' into verilog-ams 2008-06-05 10:52:58 -07:00
Cary R 1c51ac4ac0 For undefined memory words (size == 0) return an X vector.
If a memory word was accessed before it was defined the
code was returning a zero width vector result. Now it
returns an appropriately sized vector of 'x'.
2008-06-05 10:34:18 -07:00
Cary R 17a1358eb6 Remove documentation for memory opcodes.
The memory opcodes %assign/mv, %load/mv and %set/mv
were removed by a previous patch. This one removes
the documentation from opcodes.txt. It also removes
the documentation for the .mem* statements for the
same reason.
2008-06-05 10:31:38 -07:00
Stephen Williams 04a7f7054a Fix problem linking a-side and b-side tran branches.
Tran devices linked in series were not getting properly joined up
due to a problem with the add_branch method.
2008-06-04 20:34:04 -07:00
Stephen Williams e97a1ad610 Try to eliminate excessive processing recursions.
After calculating the A side of a tran[if/vp], the B side is usually
fully specified, so make an effort to push the calculated value through.
2008-06-04 16:10:43 -07:00
Stephen Williams e872310e4b Optimize recursive branch resolution
Recursive branch resolution was scanning every branch end, even though
many branch ends share ports and need not be repeatedly scanned. Handle
marks and flags to cut off recursion where it is not needed so as to
save much run time.
2008-06-04 11:34:26 -07:00
Stephen Williams 95850ac112 Merge branch 'master' into verilog-ams
Conflicts:

	tgt-vvp/vvp_scope.c

Note that the draw_net_input.c takes in a lot of the codes that used
to be in vvp_scope.c, so some changes may have been lost.
2008-06-03 21:17:57 -07:00
Cary R d0e154b830 Clean up dump routines and support of MemoryWord dump.
This patch cleans up the dump routines and adds file and
line number information for errors. It also adds some of
the missing MemoryWord properties so they can now be
dumped and monitored correctly.
2008-06-03 21:04:22 -07:00
Cary R 4010f6e710 Add $simparam and other fixes.
This patch adds $simparam and $simparam$str from Verilog-A.
The analog simulator parameters return 0.0 or N/A. The
vvp_cpu_wordsize system function has been moved into the
$simparam call and is now named CPUWordSize.

This patch also starts the factoring of common code in the
vpi directory. Some routines were renamed.

The priv.c file was renamed to sys_priv.c to match the
include file.

System functions can now have strings put to their output.
2008-06-03 20:56:37 -07:00
Larry Doolittle d74f2fe38d Don't duplicate Makefile shell code
Smaller, and conceptually easier to keep in sync,
way of handling build machines with and without git.
2008-06-03 20:52:41 -07:00
Stephen Williams db642e3850 Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-06-03 20:51:04 -07:00
Larry Doolittle 523dff7ae7 Fix probable precedence bug
and at least get rid of a compiler warning
2008-06-03 20:50:36 -07:00
Stephen Williams db09f2fa7e More cost effective and reliable island joining algorithm.
Rather then join islands while branches are initially created, save the
island creating for the end. This way, the process is actually recursive
and greedy, reliably collecting branches into islands without conflict.
2008-06-03 20:21:39 -07:00
Stephen Williams c2061e8199 Island ports can accept vector parts. 2008-06-03 17:31:15 -07:00
Stephen Williams ff9166d4a5 Got sense of tranvp wrong in connections to module ports. 2008-06-03 17:23:01 -07:00
Stephen Williams 73e2b297df Replace the NetPartSelect:BI with NetTran(VP).
Fold the bi-directional part select into the pass switch (tran) support
so that it can be really bi-directional. This involves adding a new
tranvp device that does part select in tran islands, and reworking the
tran island resolution to handle non-identical nodes. This will be needed
for resistive tran devices anyhow.
2008-06-03 11:16:25 -07:00
Stephen Williams 6e5373c87e Add part select support to vvp_vector8_t
Need a convenient way to handle part selects of vvp_vector8_t objects.
2008-06-03 08:52:42 -07:00
Stephen Williams 782bfab29e Add support for tranif devices in the vvp code generator.
The draw_net_input function is modified to account for nexus that is
a port of an island. Draw the ports (and the islands if necessary)
to the island and use the port output for the nexus instead of the
port input. This allows the bi-directional behavior of the port to
interpose itself in the data flow.

In this process of these changes, the draw_net_input function was
reorganized, and all the considerable amount of code for it was
moved to a file of its own. (vvp_scope.c is pretty unruly.)
2008-06-01 21:08:31 -07:00
Stephen Williams df15a0368c Collect NetTran devices into islands.
NetTran devices must be collected into islands because they are all
a bi-directional mass. This is how vvp will process them and the code
generator will need a head start organizing them.
2008-06-01 19:45:12 -07:00
Stephen Williams 916f300448 Assert some island port constraints. 2008-06-01 19:42:44 -07:00
Stephen Williams 7898f4e402 Account for swithes linked to nexus in ivl_target.h API.
Switches can connect to a nexus too, so add the missing nexus support
for that in the ivl_target.h API.
2008-06-01 14:29:27 -07:00
Stephen Williams 6f8bf90dc4 Add basic the .tran device.
The .tran device is simply a .tranif0 without the enable. It is
always enabled.
2008-06-01 10:37:41 -07:00
Stephen Williams 052870c0e5 And the vvp_island infrastructure to the vvp runtime.
The vvp_island classes are added, as well as support for tranif nodes
that use this concept. The result is a working implementation for
tranif0 and tranif1.

In the process, the symbol table functions were cleaned up and made
into templates for better type safety, and the vvp_net_ptr_t was
generalized so that it can be used by the branches in the island
implementation.

Also fix up the array handling to use the better symbol table support,
and to remember to clear its own table when linking is done.
2008-05-31 21:45:55 -07:00
Stephen Williams 1be1f65f33 Merge branch 'master' into verilog-ams 2008-05-29 20:11:00 -07:00
Stephen Williams fd6f017435 Get very subtle handling of part select into ports correct.
The code generator was reading the wrong node of a bi-directional
part select. This happens exclusively with part selects passed to
bi-directional ports, so was rare. The result was that the non-part
selected part may get an incorrect value.
2008-05-29 17:28:12 -07:00
Stephen Williams dfa6471227 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-05-29 14:00:51 -07:00
Stephen Williams a8f492776a Check range of immediate value. 2008-05-29 14:00:32 -07:00
Stephen Williams 6f0d98cf18 Constrain multiply word to prevent overflow.
The multiply runs does not need to do all the combinations of digit
products, because the higher ones cannot add into the result. Fix the
iteration to limit the scan.
2008-05-29 14:00:03 -07:00
Stephen Williams 6f30813102 Prevent overflow when parsing 32bit values
The source can carry 32bit numbers. Watch out that they are handled
all the way through to the compiled results on 32bit systems.
2008-05-29 13:52:12 -07:00
Cary R 2fab3159dd Add smart part select for system functions &PV<>.
This patch adds a smart part select that allows system functions
to have full access to the real bits of the part select.
2008-05-29 09:40:12 -07:00
Cary R f04fb0fc45 System functions have a default return value.
If a system function does not call vpi_put_value it is
supposed to have a default return value of 0. This patch
adds this functionality.
2008-05-28 09:53:27 -07:00
Cary R 7a1180868a Remove definition for non-existent routines.
ivl_switch_scope, ivl_switch_attr_cnt and ivl_switch_attr_val
are non-existent routines and should not be in ivl.def. I also
removed them from ivl_target.h. Cygwin expects that if a routine
is listed in ivl.def that it will find a real implementation.
2008-05-28 09:45:27 -07:00
Cary R b2bdce98ab It is an error for the concatenation repeat to be undefined.
Print an error message if the concatenation repeat expression
is undefined.
2008-05-28 09:39:57 -07:00
Cary R 653e2661b2 The no git code also check for an existing version.h
My previous patch always used an empty file if git was not
available. This patch extends this to use the existing
version.h file if it exists (snapshot, etc.)
2008-05-28 09:09:33 -07:00
Stephen Williams 9aa610f489 Fix handling of 32bit IMM in %addi on 32bit machines
The handling of immediate add used to do 16bits at a time. When it went
up to 32bits, the need to work in chunks vanished, but the chunk handling
was still there, this time shifting by 32, which causes problems on 32bit
machines. Simplify the %addi handling to avoid this.
2008-05-28 08:47:28 -07:00
Stephen Williams de7fff8ac6 Elaborate tran devices (switches)
This takes the support for switch modeling to the code generator.
Add error messages in the vvp code generator for lack of support.
2008-05-27 20:06:58 -07:00
Stephen Williams 2179797763 Do not allow unknows to be handled as logic immediate. 2008-05-27 19:48:31 -07:00
Cary R b5e9e44e07 Fix error in of_SUBI with wide results.
This patch fixes an error in the recent rework of of_SUBI.
It was doing a double bit inversion.
2008-05-27 19:42:20 -07:00
Stephen Williams 5a0fe9ff83 Better use of immediate operands.
Clarify that operands are typically 32bits, and have the code generator
make better use of this.

Also improve the %movi implementation to work well with marger vectors.

Add the %andi instruction to use immediate operands.
2008-05-27 17:51:28 -07:00
Stephen Williams f6fede5aae Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-05-27 11:55:45 -07:00
Stephen Williams 0fa3099ded Optimize %div and %div/s
Use high radix long division to take advantage of the divide hardware
of the host computer. It looks brute force at first glance, but since
it is using the optimized arithmetic of the host processor, it is much
faster then implementing "fast" algorithms the hard way.
2008-05-27 11:54:39 -07:00
Stephen Williams 6987d16bd3 Optimize the %load/vp0 to use subarrays.
This instruction adds an integer value to the value being loaded. This
optimization uses subarrays instead of the += operator. This is faster
because the value is best loaded into the vector as a subarray anyhow.
2008-05-26 16:44:58 -07:00
Stephen Williams 5cc376ebd4 Optimize ADD and MUL instructions
Make better use of the CPU word in ADD and MUL instructions.
2008-05-26 16:00:16 -07:00
Stephen Williams 8190307dd3 Optimize/inline vvp_bit4_r AND, OR and vector set bit.
The AND and OR operators for vvp_bit4_t are slightly tweaked to be
lighter and inlinable.

The vvp_vector4_t::set_bit is optimized to do less silly mask fiddling.
2008-05-26 11:09:33 -07:00
Stephen Williams 3575f68c9f Merge branch 'master' into verilog-ams 2008-05-23 21:23:16 -07:00
Stephen Williams c1268d04fc Merge branch 'verilog-ams' of ssh://[email protected]/~steve-icarus/git/verilog into verilog-ams
Conflicts:

	ivl_target.h
	t-dll.h
2008-05-23 20:55:46 -07:00
Stephen Williams ca756f3ec3 Bring switch information out to the ivl_target API.
This involves defining the API for switches and cleaning up the
elaborated form to match the defined ivl_target API. Also add t-dll
code to support the ivl_switch_t functions, and add stub code that
checks the results.
2008-05-23 20:53:10 -07:00
Stephen Williams 9af459f95b Vectorize AND/OR/NAND/NOR/INV instructions when reasonable.
When processing wide vectors of these operations, it pays to process
them as vectors. This improves run-time performance. Have the run time
select vectorized or not based on the vector width.
2008-05-23 17:52:43 -07:00
Stephen Williams 492b240304 Optimize vvp_vector4 vector handling.
Improve vvp_vector4_t methods copy_bits and the part selecting constructor
to make better use of vector words. Eliminate bit-by-bit processing by
these methods to take advantage of host processor words.

Improve vthread_bits_to_vector to use these improved methods and Update
the %load/av and %set/v instructions to take advantage of these changes.
2008-05-23 14:30:32 -07:00
Stephen Williams d2106a3d3a Fix botched processing of MUX with constant select.
If the select input was constant, the code then tried to look at the
constant data input. Just plain wrong.
2008-05-23 10:29:44 -07:00
Stephen Williams cf2f4dd0af Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-05-22 20:36:18 -07:00
Cary R 608c2574bd Add $finish_and_return.
This new system task can be used to set the vvp return value
and finish the simulation.
2008-05-22 20:34:38 -07:00
Larry Doolittle f17db21bf0 Make sure stringify_flag is always initialized.
Put in one last initialization of stringify_flag,
that Cary missed in add84b153c
and Steve missed in 73dcace781.
Found the long, hard way.
2008-05-22 20:32:26 -07:00
Cary R b26bdd3c19 MinGW fixes (development)
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.

snprintf prints %p differently than the other printf routines
so use _snprintf to get consistent results.

Only build the PDF files if both man and ps2pdf exist.

MinGW does not know about the z modifier for %d, %u, etc.

Add some missing Makefile check targets.
2008-05-22 20:24:21 -07:00
Larry Doolittle 6a9c5d8f7e Use standard for printing uint64_t
Ugly, but pedantically correct according to c99 7.8.1.
Maybe not as ugly as the compile-time warning it replaces.
2008-05-22 18:42:56 -07:00
Stephen Williams e59f28d659 work interrupted 2008-05-22 18:40:29 -07:00
Stephen Williams 07ae300e0c Rework %cmpi/u, %cmp/u and %ix/get for speed
These instructions can take advantage of the much optimized
vector_to_array function to do their arithmetic work quickly and
punt on X very quickly if needed. This helps some benchmarks.
2008-05-22 18:19:40 -07:00
Stephen Williams 4c5f24c7a7 Simplify MUXZ if the select is constant.
If the select of a MUXZ is constant 0 or 1, then we can elide the MUX
in place of a simple BUFZ. This should allow the dead code on the
unused side to be removed as well.
2008-05-21 10:25:44 -07:00
Stephen Williams be810c5ba6 Merge branch 'var-array-rework' 2008-05-21 07:01:07 -07:00
Stephen Williams 5ec3b590bf Clear up some poor pointer management.
The expression for a paramter value was not well managed, given that
the eval_expr() function replaces pointers. Clear things up a bit.
2008-05-20 20:36:41 -07:00
Stephen Williams 88313670c0 Clear up some poor pointer management.
The expression for a paramter value was not well managed, given that
the eval_expr() function replaces pointers. Clear things up a bit.
2008-05-20 20:32:42 -07:00
Stephen Williams d1daf6733f Allow VPI callbacks to var array words.
Functions like $monitor need to attach callbacks to array words if
those words are to be monitored. Have the array hold all the callbacks
for words in the array, under the assumption that the monitored words
are sparse.
2008-05-20 18:30:56 -07:00
Stephen Williams 007056d671 Remove last vestiges of the the .mem structures.
Before the .array support, we had .mem nodes. These are long since
removed because the arrays to all the jobs of the .mem nodes.
2008-05-20 16:57:50 -07:00
Stephen Williams 2dcb1514a2 Add support for passing array words to system tasks.
Array words don't have a vpiHandle with a label, so the %vpi_call
needs a special syntac for arguments that reference array words.
This syntax creates an array word reference that persists and can
be used at a VPI object by system tasks.
2008-05-20 16:21:54 -07:00
Stephen Williams d71a1cb9c1 Fix non-blocking assign to part select of memory word.
Memory words may have part selects assigned, but the code messed up
the testing for the validity of the part select base. This fixes do
detect constant bases so that base validity tests are handled at
compile time.
2008-05-20 11:51:17 -07:00
Stephen Williams f9f68236bc Make sure expressions of value_ranges are initialized. 2008-05-20 10:46:08 -07:00
Stephen Williams dadb3a68d3 Fix possible error choosing default discipline domain.
Recent gcc warns about code that turns out to be incorrect.
2008-05-20 10:41:24 -07:00
Larry Doolittle 6121c06f15 Reconcile autoconf.sh to new gperf usage
gperf command line changed in Makefile.in as of
commit cde87ed4a3
this patch propagates that change to autoconf.sh
2008-05-20 10:36:26 -07:00
Larry Doolittle b289d740e2 Drop two unused variables
eval_tree.cc:eval_tree()'s expr_msb and expr_lsb became unused after
commit c76e88cad5
which triggered warnings from gcc-4.3
2008-05-20 10:32:18 -07:00
Stephen Williams ec266ff52e Make sure expressions of value_ranges are initialized. 2008-05-19 21:55:53 -07:00
Stephen Williams ec773fe8cf Elaborate tran devices
The tran devices include tran, rtran, tranif0/1 and rtranif0/1. These
are all elaborated as options on a NetTran device. It is still not
clear the best way to present tran devices via the ivl_target.h API.
2008-05-19 21:42:52 -07:00
Stephen Williams 4c3d764a86 Add support for array iterator scan.
With the array vals_words method of getting compact vpiHandles to words
of a var array, it becomes easy to support the array iterators.
2008-05-19 19:04:42 -07:00
Cary R a412149e2c Don't let -I block -ivl!
When -I was added it was blocking -ivl since the string comparison
is case insensitive.
2008-05-19 18:32:09 -07:00
Larry Doolittle deb7b01717 Compatibility with gcc-4.3
Add include statements (<cstdlib> for abort()) and a cast.
Necessary and sufficient for successful compilation with
gcc-4.3 (Debian 4.3.0-4) 4.3.1 20080501 (prerelease)
2008-05-19 18:31:08 -07:00
Stephen Williams 3189efacbc Fix memory word offset errors
Fix handling writing to a word part select,
Fix readmemb calculations for the word size.
2008-05-19 18:05:27 -07:00
Stephen Williams 96ec4b7eba Fix array inputs to mux devices.
The draw_input_from_net function was being used to access words of
a var array, which doesn't work. Have the draw_input_from_net punt
on that case, and by the way the mux inputs don't need to use that
function, instead they should use the general draw_net_input function
to get the input labels.
2008-05-19 17:37:23 -07:00
Stephen Williams 07c8fce530 Careful that select signal does not try to select reg words directly. 2008-05-19 11:44:03 -07:00
Stephen Williams 9a00829ee4 Use ivl_signal_dimensions to detect that signal is an array.
It is possible for an array to have 1 word in it, so using the array
count to detect an array is incorrect. Use the ivl_signal_dimensions
function, which is there exactly for that purpose.
2008-05-19 11:31:40 -07:00
Stephen Williams 680d3c8a3e Assign to variable array words using array indexing.
The non-array set statements no longer work on array words. Handle
the various cases properly.
2008-05-19 11:18:04 -07:00
Stephen Williams 6966c26f27 Merge branch 'master' into verilog-ams 2008-05-17 17:04:57 -07:00
Stephen Williams a5e3d06412 Skip value range processing for parameters with no value ranges.
Classing parameter declarations do not need value range processing,
and in fact it can get in the way.
2008-05-17 16:55:00 -07:00
Stephen Williams eb3dcc2786 Dump verinum value as decimal if possible, even if sized. 2008-05-17 16:26:32 -07:00
Stephen Williams c76e88cad5 Add support for explicit parameter types, including real.
Before this, the types of parameters were always logic, only the
width and signed-ness could be controlled. A parameter may take
on implicit real values if the expression were real.

With this patch, the type for the parameter can be explicitly set
to logic or real. This also means that the parameter real valued
expressions need to be more crefully treated, possibly with casting
integral expressions to real values, or real expressions to integral
values.
2008-05-17 16:25:58 -07:00
Stephen Williams 6632e4c33b Allow ports to be declared before arrays.
It is possible for the code generator to create .array/port objects
before the .array object that the port refereces, so use the resolv_list
to arrange for binding during cleanup.
2008-05-16 19:06:12 -07:00
Stephen Williams 42913e46b8 Fix non-blocking assign to variable arrays.
Non-blocking assignment with constant index was still trying to access
the vpi handle directly.
2008-05-16 16:33:04 -07:00
Stephen Williams e2ad59466a Create handles to access words of an array, if needed.
VPI code may need to access words of a variable array. If so, create
a compact handle format that gains that access with minimal pain.
2008-05-16 16:20:22 -07:00
Stephen Williams 0cd946a7af Remove a useless call to vpi_iterate. 2008-05-16 16:18:07 -07:00
Stephen Williams 102cbb67b4 Rework variable arrays to not have vpi handles for every word.
Save tons of space per memory word by not creating a vpi handle for
each and every word of a variable array. (Net arrays still get a
vpiHandle for every word.) The consequence of this is that all
accesses to a variable array need to go through the indexing.

This commit handles the most common places where this impacts, but
there are still problems.
2008-05-16 10:38:32 -07:00
Stephen Williams 3113392594 Minor improvement to mingw.txt 2008-05-15 16:59:08 -07:00
Cary R 72b4256872 Return 0 when vpi_handle_by_name() is called with an unsupported object.
vpi_handle_by_name() was assuming it was always given a valid scope
object. In the context of vpi_chk_error() this is not required and
some users use/abuse the interface by calling the function with invalid
objects expecting a 0 return value. This patch adds an explicit check
for the supported types vpiScope and as an extension vpiModule.
Anything else should be flagged as an error once we have vpi_chk_error()
implemented, but for now it just returns 0.
2008-05-15 10:46:53 -07:00
Cary R ca880c73fc Fix $ungetc() arguments to be in the correct order.
The arguments to $ungetc() were backwards! This patch fixes that
and adds a bit more checking to the compile_tf routine. It still
needs more work, but that can wait for the major system function
clean up I have planned when I can find the time.
2008-05-15 10:38:41 -07:00
Stephen Williams f588656dd5 Merge branch 'master' into verilog-ams 2008-05-14 20:21:08 -07:00
Stephen Williams cef0d0071b Handle declarations within scopes under while and repeat statements.
The PWile and PRepeat statements need elaborate_sig() methods to recurse
into the contained statements.
2008-05-14 20:19:51 -07:00
Stephen Williams 35e48fb7b7 Merge branch 'master' into verilog-ams 2008-05-14 20:12:41 -07:00
Cary R 2934ceb548 A constant thread vector is binary.
Thread vectors can be treated as constants the problem
was that they did not set a constant type. They now
return vpiBinaryConst.
2008-05-14 11:56:50 -07:00
Stephen Williams 6b908aeec3 Arithmetic operands can do unsigned work and have signed result.
It is a quirk of the $signed() system function that the argument
is converted to signed, but the operation that is performed is
not changed. So arithmetic operators on unsigned arguments inside
a $signed() expression still perform unsigned arithmetic.
2008-05-14 11:51:53 -07:00
Stephen Williams a069b6dbe1 Basic test of the range for logic/bool parameters.
If there is a value range for a logic/bool parameter, then test the
configured value with the range and report an error if the range is
out of bounds.
2008-05-13 21:56:57 -07:00
Stephen Williams 48f934abf7 Get parameter ranges as far as the netlist form.
The pform is now translated/elaborated into NetScope objects. All that
remains is to check the parameter values against the ranges. This is
to be done in the evaluate_parameters() method.
2008-05-13 21:22:52 -07:00
Cary R a6dd97a5a6 Fix comparisons that use sb_to_idx()
A recent change to sb_to_idx() made it return a signed value
where it previously returned an unsigned value. This patch adds
explicit casts to remove the two signed vs unsigned comparison
warning messages.
2008-05-13 11:04:56 -07:00
Stephen Williams 2b4f7f8aed Revert "One more signed vs unsigned comparison fix"
This reverts commit 3c5bf034ca.
A latter patch is more complete.
2008-05-13 10:58:33 -07:00
Cary R add84b153c Make sure stringify_flag is initialized.
stringify_flag should not be used uninitialized.
Found with valgrind.
2008-05-13 10:50:59 -07:00
Stephen Williams 2172c8a503 Parse parameter value ranges into pform.
Handle parameter value ranges as far as the pform. The +-inf expressions
are not handled yet, nor is the single value exclude, but the other
cases are handled.
2008-05-12 21:26:38 -07:00
Stephen Williams cbf96d73ee Make semi-colon after discipline/nature name optional.
The VAMS-2.2 LRM syntax does not include a semicolon after the nature/
discipline name, but the 2.3 LRM does. Effectively, that means that
the simicolon is option from now on.
2008-05-12 17:31:59 -07:00
Larry Doolittle 3c5bf034ca One more signed vs unsigned comparison fix
Fix
  elab_expr.cc:1561: warning: comparison between signed and unsigned integer expressions
caused by revised prototype of NetNet::sb_to_idx() in
 commit dfb7bf5211
2008-05-12 16:29:10 -07:00
Stephen Williams 7166aea1d7 Attach natures to disciplines
Pform parse enough of the natures that they can be mapped and the
disciplines can bind to them. Since Verilog-AMS expects natures to
be declared before use, we can do the binding early.
2008-05-11 18:52:27 -07:00
Stephen Williams 93b400c4d7 Attach disciplines to wires
Allow discipline declaration of nets that attaches the discipline to
a new wire or a wire that is already declared.
2008-05-11 17:30:33 -07:00
Stephen Williams a506a18970 Nature and discipline declarations syntax
The VAMS-2.3 specification says that discipline and nature declarations
have a semi-colon after the identifier, but the disciplines.vams in
the appendix does not. Initial guess what that the disciplines.vams
is correct, but I've been told that the syntax is correct and the
disciplines.vams file is not.
2008-05-11 12:13:58 -07:00
Stephen Williams 5b273178f5 Parse disciplines and contribution statements
Parse discipline declarations, net discipline declarations, and
analog contribution statements. Don't yet do anything useful with
these, just give a sorry message where they are encountered.
2008-05-11 12:00:11 -07:00
Stephen Williams cde87ed4a3 Add disciplines.vams and enough syntax to parse it.
This is part of the standard disciplines header file, with enough
syntax to part the natures and disciplines included. Don't do anything
with the parse results yet.
2008-05-10 10:37:33 -07:00
Stephen Williams 84a7efdb4f Merge branch 'verilog-ams' 2008-05-09 17:46:45 -07:00
Stephen Williams dfb7bf5211 Handle part selects of nets that fall of the ends of the identifier.
The Verilog LRM specifies that it is legal to give constant part
selects that are beyond the bounds of the identifier being selected.
But elaboration was flagging that as an error. This patch changes it
to a warning, and handles the cases by generating 'bx bits as needed.
2008-05-09 17:42:37 -07:00
Stephen Williams a33619a0f5 Properly pad results of function calls.
The elaborator improperly allowed user function call nodes to take on
the expression width requested of them. The result was that generated
code had junk pad bits in certain cases.
2008-05-09 15:25:42 -07:00
Stephen Williams a1495bb007 Unary minus of a constant does make the number signed.
It is wrong to assume that the result of a unary minus is signed.
Doing so can cause incorrect results in subsequent math.
2008-05-09 14:18:39 -07:00
Stephen Williams 8e1f22cd82 AC_CHECK_FUNCS_ONCE is a little too modern for many uses. 2008-05-09 09:55:41 -07:00
Stephen Williams db10de1a6a Fix calculation of XOR when z is present
When calculating 0^z with constant arguments, make sure the result is
x. This problem only happens when the arguments are constants and the
expression is calculated at compile time.
2008-05-09 09:16:11 -07:00
Stephen Williams bbed408d68 When padding logic constants, sign extend x/z properly.
If there is an x or z bin in the sign position of a logic number to
be padded, pad with the x or z, not zero.
2008-05-09 08:25:25 -07:00
Stephen Williams ba3660b948 Merge branch 'master' into verilog-ams 2008-05-08 19:56:11 -07:00
Stephen Williams 73dcace781 Prevent macro expand in strings, and add a stringify syntax
Verilog does not allow macro expansion in strings, and that's that.
But sometimes people want strings of a macro expansion, so add a
stringify syntax that does the trick.
2008-05-08 18:43:07 -07:00
Stephen Williams fd3ca037aa Document the __VAMS_ENABLE__ macro. 2008-05-08 10:28:22 -07:00
Stephen Williams 2d068ca89f Add support for scaled real numbers.
Verilog-AMS supports scaled real numbers, where the "e<N>" (scientific
notation) is replaced with engineering scales from "a" (atto-) to
m (milli-) and "K" (kilo-) to "T" (tera-). This syntax can be handled
way down in the lexor.
2008-05-07 22:11:19 -07:00
Stephen Williams dea1161c7e Merge branch 'verilog-ams' 2008-05-07 17:50:56 -07:00
Stephen Williams 3a61b94e98 Realign generation flags to correspond to IEEE1364 nomenclature.
IEEE1364 has specific names for the various generations of Verilog that
are supported. Icarus Verilog should stick to those names for selection
the language feature set.

In the process, the extensions that were tied to the 2x generations
are pulled out out and given their own enable flags. The makes all the
feature control more regular and understandable.
2008-05-07 17:46:56 -07:00
Cary R 3a8a6976e1 Add $vvp_cpu_wordsize function
This patch adds a new system function $vvp_cpu_wordsize. It returns
the size of the underlying CPU word (long) in bits. This function
can be used to write fully portable tests for the test suite. Other
functions will be added as needed.
2008-05-07 09:42:02 -07:00
Stephen Williams 6cc244766c Fix build error branching around initializations. 2008-05-07 07:31:01 -07:00
Stephen Williams 6e3ec755e2 Define __VAMS_ENABLE__ when verilog-amd i enabled. 2008-05-06 22:34:48 -07:00
Stephen Williams ca517b5519 Handle corner cases of abs(), min() and max()
The abs() function needs to be able to turn -0.0 into 0.0. This proved
to be too clunky (and perhaps impossible) to do with tests and jumps,
so add an %abs/wr opcode to do it using fabs().

The min/max functions need to take special care with the handling
of NaN operands. These matter, so generate the extra code to handle
them.
2008-05-06 22:19:59 -07:00
Stephen Williams 10ab5cf698 Merge branch 'verilog-ams' 2008-05-06 21:00:12 -07:00
Stephen Williams 523de1b69c Handle the abs() function in net context.
In net context we have to create a node that does the abs() function
for us. Elaborate that node and handle it all the way down to vvp.
2008-05-06 20:37:00 -07:00
Stephen Williams 3e591f730e sign extended expressions are signed.
Fix when sign extending an expression that the result is also signed.
This bug caused some arithmetic operations (with extended arguments)
to not notice that they are signed.

Also be more robust in noticing that comparisons are signed and should
generate the right code.
2008-05-06 13:27:04 -07:00
Cary R 34e90bb3a6 Allow genvars to also be constants.
This patch adds genvars to the list of constant values.
2008-05-06 07:35:23 -07:00
Cary R 4f8b91e65c Add file and line information for parameters, etc.
This patch adds file and line information for parameters and
local parameters. It also adds file/line stubs for signals in
the tgt-* files. It adds the pform code needed to eventually
do genvar checks and passing of genvar file/line information.
It verifies that a genvar does not have the same name as a
parameter/local parameter.
2008-05-06 07:14:27 -07:00
Stephen Williams e91243e1c6 Elaborate abs() is continuous assign expressions.
In continuous assign expressions, the abs() operator can't easily be
burried in generic unary handling, so add the IVL_LPM_ABS type and
generate it as needed.
2008-05-05 22:00:39 -07:00
Stephen Williams 5484ee1732 Include va_math if compiling Verilog-AMS
The va_math module implements functions that are optional in base
Verilog but included in Verilog-AMS. So automatically include the
module if -gverilog-ams is given.
2008-05-05 19:26:17 -07:00
Stephen Williams a43f336c6c Include va_math if compiling Verilog-AMS
The va_math module implements functions that are optional in base
Verilog but included in Verilog-AMS. So automatically include the
module if -gverilog-ams is given.
2008-05-04 22:10:54 -07:00
Stephen Williams cc7187c172 Add support for abs() in logic threads.
Add the code generator code to handle the abs() function in signed
logic. Handle some of the interesting special cases as well.
2008-05-04 22:00:01 -07:00
Stephen Williams d60df2d75b Implement abs/min/max operators for real values.
Implement in behavioral the abs/min/max operators for real values.
The parser treats these builtin functions as operators, unary or
binary, and elaborates them appropriately.

Also add enough code generator support to handle real valued expressions
in thread context.
2008-05-03 21:54:42 -07:00
Stephen Williams 6d433364ac Fix some bugs with passing -gverilog-ams to the ivl core. 2008-05-03 21:51:47 -07:00
Stephen Williams bbc80a84a6 Rename $log to $log10.
Verilog-2005 defines the base-10 log function to be $log10. This makes
sense because in C the log() function is the natural log. So add the
$log10 function.

Since there may be legacy code that uses the $log function, leave it
defined, but we should consider at least printing a warning when the
$log function is used.
2008-05-03 18:29:52 -07:00
Stephen Williams c993fb8325 Handle Traditional Verilog-A math functions
Verilog-AMS recommends that users use the system-function style
math functions, but supports traditional style math functions for
portability. Add the keywords and parse the traditional Verilog-A
functions, and handle them as calls to the equivilent system
function.
2008-05-03 18:05:51 -07:00
Stephen Williams f662d76b2e Add infrastructure for enabling Verilog-AMS
Add the -gverilog-ams flag to the driver, and the begin_keywords support
for VAMS-2.3 keywords. With this, the infrastructure is in place to
start pulling in features from Verilog-AMS.
2008-05-02 16:28:48 -07:00
Stephen Williams 0c29e540ea Check ketwords against active keyword subset mask.
The begin_keywords directives manage a mask of keyword sets that are
active at a given moment. This patch makes the lexor actually test
the given keyword against the mask. If it matches, return the keyword
id, if it is disabled then it is an IDENTIFIER.
2008-05-02 15:29:09 -07:00
Stephen Williams 1a8be6d28c Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-05-02 14:55:49 -07:00
Stephen Williams 6491c5d43c Sort changelog for SuSE
The RPM program for SUSE is picky about the order of entries in the
changelog section.
2008-05-02 14:55:26 -07:00
GuntherDannoritzer a319939573 Fix up verilog.spec and root Makefile.in for package managers.
Package builders/managers find the DESTDIR variable convenient for
installing into a temporary target for building a package. This adds
the DESTDIR varilable to the root makefile.

Also, clean up the verilog.spec file to reduce redundancy so that
maintence for releases is easier.
2008-05-01 21:54:34 -07:00
Cary R 9db9aa4ccb Allow zero width replications only in a concatenation.
1364-2001 does not allow a replication count of zero, but
1364-2005 allows them when the replication is enclosed in
a concatenation with other valid bits. This patch adds
code to perform these checks for procedural expressions.
Because of the NetNet object must have a width greater
than zero a replication used in a continuous assignment
can never have a count of zero.
2008-05-01 20:33:04 -07:00
Larry Doolittle cb5260b2ce minor improvements to scripts/MAKE_SNAPSHOT.sh
could still use more love setting defaults and handling errors
2008-05-01 20:23:30 -07:00
Cary R c0d3bb370f Clean up some VPI issues.
This patch makes sure that objects either support vpiFile
and vpiLineNo or adds dummy code so that a runtime error
will not occur when accessing these properties. It also
returns 1 for the size of real variables and adds a
simplified vpiIndex that matches the Memory interface.
2008-05-01 20:18:59 -07:00
Larry Doolittle b99206ac8e avoid two unnecesary compile-time warnings 2008-05-01 18:34:03 -07:00
Stephen Williams 149bfa05d8 Support for the begin_keywords directive.
The begin_keywords directive allows the source code to select keyword
subsets so that a bit of code that uses identifiers that class with a
newer version of the standard can still be compiled.
2008-04-30 22:07:09 -07:00
Cary R 86a4025b58 Push file and line information for scopes to the runtime.
This patch adds code to push the file and line information
for scope objects (modules, functions, tasks, etc.) to the
runtime. For modules, this includes the definition fields.
2008-04-29 21:51:34 -07:00
Stephen Williams 2a5948d704 Add va_math.txt based on the README from the va_math submission. 2008-04-29 21:34:35 -07:00
Stephen Williams f5263c9447 Add the va_math module and constants.vams include file.
The va_math.vpi module implements systen-function versions of the
Verilog-A math functions. This library was contributed by Cary R.

Also add the constants.vams include file. This is pretty much
direct from the Verilog-AMS LRM.
2008-04-29 21:20:39 -07:00
Stephen Williams f95a6fed14 Prepare for snapshot 20080429 2008-04-29 12:03:22 -07:00
Cary R 436e2fca13 Add ifnone functionality.
This patch adds ifnone functionality. It does not produce an
error when both an ifnone and an unconditional simple module
path are given. For this case the ifnone delays are ignored.
2008-04-29 11:55:32 -07:00
Stephen Williams 64c92f9fdd A script for making snapshots
Include in git a script for making snapshots. This script makes a
bundle that can compile outside of git.
2008-04-28 21:54:09 -07:00
Cary R 603ca0f2de Add better error recovery for failed task/function definition.
This patch does a better job of recovering from an error in a
task or function definition. This prevents the compiler from
printing many irrelevant error messages.
2008-04-27 21:30:23 -07:00
Cary R efba4bfd09 Allow multiple ports in single ANSI decl for tasks and functions
This patch adds the functionality to tasks/functions to handle the
declaration of multiple ports using a single ANSI declaration. It
also deletes the old range vector before it adds the new one. The
tasks and functions are different than modules so we need to copy
the range for them.
2008-04-27 21:26:17 -07:00
Cary R 785aad94c5 Ignore a few more compiler directives.
This patch adds `default_decay_time, `default_trireg_strength,
`delay_mode_zero and `line as ignored compiler directives.
2008-04-27 21:18:21 -07:00
Cary R ffbf37b06b Add vpiScalarVal to signal_put_value().
This patch adds functionality for vpiScalarVal to signal_put_value().
It also factors out the scalar to bit4 code from vpiVectorVal.
2008-04-27 21:11:12 -07:00
Stephen Williams c3ac01d31b Make casts from double to unsigned bits portable.
Several places in Icarus Verilog try to get the bits of the integer
part of a double by casting to unsigned or unsigned long. But that
causes some compilers to generate smart code that converts all values
less then 0 to 0, even though we are after the bits, not the math
value. So be careful to do this cast only to non-negative values and
uminus the bits if necessary to get exactly what we want.

Signed-off-by: Stephen Williams <[email protected]>
2008-04-27 18:21:32 -07:00
Stephen Williams 81e12bf7f6 Handle multiple active specify delays.
Fix handling of cases where multiple specified delays are activated
for a given output. Need to apply the standard selection criteria
that gets the minimum value.
2008-04-25 17:17:51 -07:00
Stephen Williams abaab602bc Fix >= compare not detecting right X bits.
Oops, never properly checking that the right value has XZ bits.
2008-04-24 11:05:11 -07:00
Stephen Williams bd170d05ad optimize vvp_vector4_t magnitude compare and bitwise not.
Update the magnitide compare and bitwise not operators to use
optimized methods where possible.
2008-04-23 16:50:22 -07:00
Stephen Williams 7b81eb3494 Optimize the SUB instruction
The %sub instruction didn't have the efficent implementation that
the %add instructions used. Update subtraction to use the array
method, so that it gets the same performance benefits.
2008-04-23 14:03:52 -07:00
Stephen Williams b775d178d2 More efficient way to set arithmetic results into vector4.
The vvp_vector4_t often receives the results of vector arithmetic.
Add an optimized method for setting that data into the vector. Take
into account that arithmetic results have no X/Z bits, etc.
2008-04-23 13:50:05 -07:00
Stephen Williams 10ea9904f1 Clean up more vvp_bit4_t encoding dependencies. 2008-04-23 11:16:24 -07:00
Stephen Williams e7d463704c The inputs to logical and/or are condition expressions.
Logical and/or take as inputs condition expressions, which are scalar
expressions. Be sure to reduce vectors using proper logic to get the
right condition value.
2008-04-22 21:03:18 -07:00
Cary R c38e8182c2 Add checks that verify an always statement has delay.
This patch adds check to determine if an always block has delay
in it or not. If there is no delay a runtime infinite loop will
occur. For the indeterminate case it will print a warning message
if the new -Winfloop flag is given. This flag is not part of the
-Wall check!
2008-04-22 19:53:23 -07:00
Cary R 7b705a0212 Generate mixed real/vector expressions when needed.
When generating a real expression you can have bits of the
expression that use vector only operands. When this happens
evaluate that part of the expression as a vector and then
convert it to a real value.
2008-04-22 19:42:57 -07:00
Stephen Williams 5ddd35565f Protect left shift from shifting too far.
On some systems, 1UL<<X will make a mess if X is the size of
an unsigned long. This especially seems to be a problem on i386
systems. Protect those shifts in the vvp_net.cc.
2008-04-22 17:31:08 -07:00
Stephen Williams a12a6d925a Fix left shift of unsized constants in sef-determined context.
When left-shifting unsized constants in self-determined contexts, the
constant value is normally pared down to its minimum required width.
But this practically guarantees loss of bits. Instead, detect this
special case and give the unsized constant a width of an integer.

Still allow for the super-special case that the shifted value and the
shift amount are constants. In that case, the result width (and value)
can be calculated precisely and there is no need to resort to default
widths.
2008-04-22 11:23:24 -07:00
Stephen Williams 5ab0c20a7d Merge branch 'vector4_format' 2008-04-20 21:46:02 -07:00
Cary R 35e511d0c0 Check delay expressions correctly and give a better message.
This patch uses the true delay expression count not the truncated
one to check that the number of delay expressions is correct.
It also prints the actual number of expressions it found when
printing the error message.
2008-04-20 21:39:17 -07:00
Stephen Williams 935c3dc02d Optimize some common vvp_bit4_t operators.
By slightly altering the vvp_bit4_t encoding, a few simple
optimizations become possible. By making Z==2 and X==3, the
conversion from X/Z to X is a simple shift-or, and this can
be used to reduce the size of some of the bit4 operators.
2008-04-20 21:36:53 -07:00
Stephen Williams 6d2ef15951 Remove dead code related to bit arrays/vectors
In previous incarnations of the vvp runtime, bit vectors were passed
around as arrays of unsigned char that charried bit4 vectors. That
is no longer used. Remove the last vestiges of that dead code.
2008-04-20 20:43:53 -07:00
Stephen Williams 40fd07d46e Remove most dependencies on vvp_bit4_t encoding.
Remove dependencies on vvp_bit4_encoding outside of the vvp_net
core types. The table_functor_s class was the worst offfender and
was barely used, so it is now removed completely. There are a few
opcodes in vhtread.cc that also make vvvp_bit4_t encoding
assumptions (and used casts) and those have been fixed. There
were also various VPI interface functions that are fixed.
2008-04-20 19:21:41 -07:00
Stephen Williams 5e30016910 Rework vvp_vector4_t to use planar a/b bits instead of interleaved.
The vvp_vector4_t holds 4-value logic. This patch changes the encoding
of 4-value bits in the vector to use separate A- and B bit vectors,
with the B- vector signaling the A- bits that are not 0/1. This
allows rapid conversion to 2-value logic, and rapid tests for X
and Z values.
2008-04-20 16:30:27 -07:00
thiede 33466250f5 Support localparam integer types.
Support localparam integer types exactly the same way that they
are handled for parameters. (This patch was submitted to pr1946144.)
2008-04-18 21:54:25 -07:00
Stephen Williams bdab7698d2 User defined functions can have ANSI-style ports
Update the rules for parsing user function definitions to allow
Verilog-2001 ANSI style port declarations. In the process, also
unify with the user task port declaration so that the types don't
diverge. The rules are the same for both, with the extra constraint
that function ports must all be input. This latter rule is checked
later, during elaboration, so that the task/function pform code
can be shared, and better error messages can be generated.
2008-04-18 21:33:03 -07:00
Cary R 54918cf5b9 Add unlink from driver to deassign and zero link pointer.
This patch fixes deassign to allow it to unlink from a driver.
It also zeros the cassign_link and force_link pointers after
they have been unlinked. Not doing this will cause an assert
if deassign/release are called multiple times (variable only).
2008-04-17 20:36:03 -07:00
Stephen Williams 844447b995 More reliably handle make install from read-only directory
commonly, the make install is run in a compiled directory by a
different user (i.e. an administrator) that doesn't necessarily
have write access to the build directory. This patch fixes it so
that the test that the version.h is up to date doesn't need to
write a temporary file in the build directory.

It also makes sure that if there is a real need to update the
verion.h, and it is not writable, then properly fail the build.
2008-04-17 20:33:39 -07:00
Cary R 6eb9825ab7 Add force/release and assign/deassign for real values.
This patch adds assign/deassign for real variables and force/release
for real variables and nets.
2008-04-17 20:18:20 -07:00
Stephen Williams 23e60aa381 Fix parsing of precompiled macro definitions
Passing preprocessor definitions forward into library cells was broken
by this bug in processing the precompiled macro values that were written
by the main preprocessor.
2008-04-17 11:52:51 -07:00
Stephen Williams 373123af6b Detect thread bit allocation failures
Detect thread bit allocation failures and fail gracefully. Print an
error message that points at the expression in question, and return
with an error code so that the compiler exits with an error.
2008-04-15 21:51:03 -07:00
Stephen Williams 54cf66d8b4 Merge branch 'master' of [email protected]:git/verilog 2008-04-15 19:19:38 -07:00
Stephen Williams dffe1be819 Trim results of unsized constant add to prevent width expansion
When constant values are added to get another constant value, and the
expression is not otherwise a fixed size, then trim the result to
prevent unbounded expansion of unsized expression with.

In the process, find and fix a bug in the vtrim function that caused
an assert if trimming were not possible for an unsigned value.
2008-04-15 19:18:03 -07:00
Cary R d41f8fe52b Only pad parameter constants out to their defined width.
This patch fixes the elaboration of parameters in a continuous
assignment to only pad the constants to their defined width.
Previously they were padded to the l-value width which resulted
in a vvp runtime error. This appears to be because the width
for padding is the defined width, but the constant is printed
using its internal width which previously could be larger than
its defined width.

These constants are local nets so I added that flag as well.
2008-04-15 18:05:53 -07:00
Larry Doolittle 6ca53c6810 Don't crash on duplicate module
Fix for pr1938138,
pform.cc:278: failed assertion lexical_scope == 0
2008-04-15 17:56:54 -07:00
Cary R 9bb8e8146f Add assign/deassign to bit/part selects and other fixes
This patch adds the ability to assign/deassign a bit or part select.
It also cleans up the code and fixes some problem in the forcing of
strength aware nets.
2008-04-15 17:46:44 -07:00
Cary R 321114e4db Add an underscore between multiple strength values.
When printing the strength information for a multi bit net this patch
adds an underscore between the individual bit strength values. This
makes it easier to see the individual bit values.
2008-04-15 17:31:35 -07:00
Cary R ef3aacfe36 Make %v print all the bits of a vector.
This patch reworks the %v code to print the strength information
for all the bits of a vector. The code previously only printed
the LSB information.
2008-04-15 17:23:58 -07:00
J Varshney bfb33230aa Revise handling of version.h to avoid build problems.
A patch to insert the version string from git broke compilation when
the source was not a git repository or when building in a read-only
source tree.  This patch avoids breaking compilation by using a
graceful failure mechanism for generating the version string and does
not write to the source tree.
2008-04-11 20:51:09 -07:00
Cary R 44767d8f70 Make MUXZ and MUXR use enum for select type.
Rework the MUXZ and MUXR code to use an enum instead of plain
integers for the select input state. This makes it more obvious
what is actually going on.
2008-04-09 21:47:47 -07:00
Cary R fecd941a28 Make sure MUXZ runs at time zero if needed.
This patch adds a flag to the MUXZ object to make sure that it will
run at time zero if needed. If this is not done the default Z result
may not be overridden by an X result.
2008-04-09 21:47:39 -07:00
Cary R 2be8534021 Add %assign/av/d opcode.
This patch adds a %assign/av/d opcode. This is a version of %assign/av
that allows a delay expression. Ultimately this allows a dynamically
indexed array to have a delay expression (non-constant delay value).
2008-04-09 21:24:37 -07:00
Cary R 8cece424d1 In the context of a force/assign you cannot reuse a saved signal value.
This patch removes the overly optimistic lookaside save for a signal
that has been set (%set/v). This is incorrect because if a force or
assign are active the value will not be set as expected.
2008-04-09 21:10:11 -07:00
Stephen Williams e2dfeac86c Part select from vectored parameters correct.
Make sure that constant bit selects of parameter names use the
proper vector range.
2008-04-08 21:20:49 -07:00
Stephen Williams a914eda5ef Get part select from vectored parameters correct.
Parameters with vector descriptions that are not zero based and
are used in net contexts should generate the properly ranged
temporary signals. This causes subsequent part selects to work
out properly.
2008-04-08 20:50:36 -07:00
Stephen Williams ba8a41ca28 Some elab_pexpr debug text. 2008-04-08 20:42:42 -07:00
Stephen Williams a67d573ae6 Eval_tree debug is controled by debug_eval_tree flag. 2008-04-08 20:42:08 -07:00
Cary R f5418fe337 Catch unsupported bit/part select lvalue for assign/deassign.
This patch adds code to print a message when an assign/deassign is used
to drive/release a bit/part select.
2008-04-07 20:52:54 -07:00
Stephen Williams 7035ded57a Do not replace explicit parameters with implicit wires.
During elaborate_sig, the code to detect implicit wires did not
properly account for the possibility that the name is that of an
explicitly declared parameter.
2008-04-06 19:26:22 -07:00
J Varshney ad3a73f74f Append last git tag and abbreviated commit-id to version string. 2008-04-06 09:30:55 -07:00
J Varshney 43e8a08c97 Tell make to find ivl.def and vvp.def in srcdir. 2008-04-06 09:22:50 -07:00
Cary R 208c6a349d Add <> to general T_SYMBOL RE and move it after the special cases.
This patch add (I believe back in) the < and > characters to the
general T_SYMBOL regular expression. The match was also moved after
the special T_SYMBOL cases so that flex would match them correctly.
Flex matching rules are longest or if a tie the first.
2008-04-04 21:59:13 -07:00
Cary R 640231bbfa Add code to prevent broken synthesis in devel. from core dumping.
This patch adds code to prevent the broken synthesis code in
the development branch from core dumping. Broken code here
refers to the Icarus code not a Verilog file.
2008-04-04 21:38:59 -07:00
Cary R bdc48135e5 Fix two comparisons in tgt-vvp/eval_expr.c to use correct variable.
This patch fixes two comparison that were using the wrong variable
to determine when the end of the object had been reached.
2008-04-04 21:31:14 -07:00
Cary R f7e840cd0a Fix another delete[]/free problem.
This patch fixes a delete[] vs free problem in the NexusSet
class. The items_ array was being allocated with malloc/realloc
and freed with delete[]. The quick fix was to replace delete[]
with a call to free(). A better fix would probably be to rework
the class to use a vector.
2008-04-04 21:31:14 -07:00
Cary R 3c1e7c4260 A NetScope will get a default nettype from a parent.
The default nettype was not always being set. This patch
modifies the NetScope constructor to get the default
nettype from a parent if it exists. It is set to NONE if
a parent does not exist.
2008-04-04 21:31:14 -07:00
Cary R 5a1ec9b958 A IVL_EX_CONCAT is always unsigned.
The signedness of an IVL_EX_CONCAT was not being set. This patch
forces it to always be unsigned as the standard specifies.
2008-04-04 21:31:13 -07:00
Michael 1bc56fcc93 Delete all temporary files even when using -E flag
The -E flag causes the driver to exit early. Be careful to delete
all the various temporary files even in this case.
2008-04-04 21:22:46 -07:00
Stephen Williams 13958cf374 Elaborate_sig skips ports that are missing on primitives
It is illegal for primitives to not have ports bound, but that
error will be taken care of later, during elaborate.
2008-03-28 21:34:18 -05:00
Cary R b5b5a9935c Fix malloc/free and new/delete problems, plus some initializations.
This patch fixes some allocation problems (mostly in the parser
and lexor relating to identifiers). It also fixes a couple places
where uninitialized variables were used. All found with valgrind.
There are still 100 tests that have problems. Many of these appear
to be related.
2008-03-27 20:58:16 -07:00
Cary R bb14ac1fe0 Add functionality to alias an individual word of an array.
This patch adds the functionality to alias an individual word
of an array.
2008-03-26 21:44:57 -07:00
Cary R 04e8623ed6 Make macro argument substitution more sane.
Macro argument substitution used to just use strstr() to
find an argument that needed to be substituted. This is too
aggressive. It would do argument substitution in the middle
of keywords and other identifiers. A new routine is used
that verifies the character preceding the match is not
a normal identifier character [a-zA-Z0-9_$].
2008-03-26 18:27:05 -07:00
Cary R 225fcf6bf0 Pad CA bit arguments and make reductions and ! self-determined.
Binary bit based operators were not padding arguments if they had
different widths. The reduction operators and ! were not correctly
evaluating their arguments in a self-determined context.
2008-03-26 18:23:19 -07:00
Cary R 8c1cca423d Check for a negative repeat value.
This patch adds checks for a negative repeat value and prints
an error message under this condition.
2008-03-26 18:12:38 -07:00
Cary R 7bc9742710 Pad the R-value of a for loop initial assign like other assigns.
The for loop initial value R-value was not being padded correctly.
This code is a copy of the code used in a regular assignment.
2008-03-26 18:09:03 -07:00
Cary R 12f8af645f Add support for real parameters in vvp.
vvp did not have the ability to handle real parameters.
This patch fixes that omission. Parameters are only used
by vpi calls to get compile time information.
2008-03-26 18:04:57 -07:00
Cary R 259e4294e3 Make of_ZOMBIE use scheduled thread deletion.
This patch modifies of_ZOMBIE() to use the same scheduled deletion
as vthread_reap().
2008-03-26 18:02:43 -07:00
Stephen Williams ea74eb771e Fix a couple problems with signed multiply
Problems with signed expressions that are set to parameters and
that include multipliciation exposed a few bugs in the calculation
of signed multiply. Fix this and add some improved diagnostics.
2008-03-25 21:35:08 -07:00
Stephen Williams 32b115d8fe Parameters get their types (signedness) from expressions.
Parameters get their signedness from the expression that is assigned
to them unless the type is explicitly expressed where the parameter
is declared.
2008-03-25 21:30:41 -07:00
Stephen Williams 14e3a886bd Find implicit nets in expressions passed to ports.
It is questionable, but probably legal, for expressions passed as
arguments to input ports of various kinds of gates to implicitly
declare nets. This patch allows the scan through different types
of expressions for implicit nets.

The elaborate_sig handling here does not test for the legality of
having a non-trivial expression as argument to a port. For example,
it is definitely NOT legal to have r-value expressions passed to
output or inout ports. But that will be checked for later when the
instance is elaborated for real.
2008-03-23 17:52:48 -07:00
Stephen Williams 140fd45460 Implicit declaration handling in ports to UDP.
Scan port expressions for implicit nets using elaborate_sig.
2008-03-20 21:44:35 -07:00
Cary R 5b2f249dcc Thread deletion is now scheduled after rosync.
Threads used to be deleted when they finished processing code.
The problem with this is that some of the code could be
rescheduled to run at rosync ($strobe, etc.). This allowed the
thread data the code depended on to be reaped too soon. This
patch uses a new queue to schedule thread deletion. The queue
is processed after rosync has finished.
2008-03-20 20:45:41 -07:00
Cary R 01eb298228 Make muxz and muxr functors use scheduled events.
This patch makes the muxz and muxr functors schedule events
instead of directly calling vvp_send_*(). This prevents the
code from going into an infinite loop when the output feeds
back to the select.
2008-03-20 20:26:45 -07:00
Cary R 48990d8e2d Implement CA - ternary short circuit for constant T/F expressions.
This patch only applies to the ternary operator when used in a
continuous assignment. It adds short circuiting when the expression
is a constant true or false. It does not optimize the special case of
a constant 'bx expression with constant T/F expressions.
2008-03-20 20:07:54 -07:00
Cary R 77722a62c2 Enhance dump() for function definitions.
This patch enhances dump() for function definitions, by indicating a
signed result with a prepended "+" and also printing the MSB and LSB.
This matches other dump() routines. It also prints the arguments with
the same information. The arguments also include their type "input",
"output" or "inout".
2008-03-20 19:42:11 -07:00
Stephen Williams a2ea980a7a Merge branch 'implicit-sig' 2008-03-18 21:44:34 -07:00
Cary R 86301be3d2 Remove unused return_event_flag.
This patch removes the unused return_event_flag variable.
2008-03-18 21:44:13 -07:00
Stephen Williams bbb488f730 Handle implicit nets in the named arguments of module instances. 2008-03-18 21:40:31 -07:00
Stephen Williams 13d4a7352c Elaborate implicit signals that are arguments to module instances.
Module instances are like gates, so the expressions pass in need
to be checked for implicit nets.
2008-03-18 21:25:13 -07:00
Stephen Williams d26ae866f8 Move implicit net creation from elaboration to elaborate_sig
If implicit nets are declared during elaboration, then the success
of binding during elaboration will depend on the order of the code
in the source file.
2008-03-18 20:50:40 -07:00
Stephen Williams 8e6c2652ab Merge branch 'master' of [email protected]:git/verilog 2008-03-14 21:06:27 -07:00
Stephen Williams 94818c19a0 Update to 20080314 snapshot 2008-03-14 15:58:51 -07:00
Stephen Williams 9b1baea6da Minor remove of unused vvp_net_t member. 2008-03-12 21:30:42 -07:00
Cary R ef9ee52e53 NetESignal::dup_expr() was not passing the word_ information.
The dup_expr() function for NetESignal was not copying the word_
expression. This would cause an individual array access to turn
into an entire array access. The file and line information was
also not being set correctly.

An assert() in tgt-vvp/eval_expr.c was also replaced with an
exit() since the appropriate information was already being
printed.
2008-03-12 20:55:12 -07:00
Cary R 377f5eaa23 Add \' as a string constant to block macro expansion.
This patch allows you to type "The \`define is `value" and not have
Icarus try to expand `define as a macro.
2008-03-11 20:14:32 -07:00
Cary R 234648231b Add bit/part select release for constants and add an error check.
This patch adds functionality to do a bit or part select release
when a constant value is forced to the net/register. It also adds an
error message when the user tries to force a signal to a bit/part
select. This is not currently handled by the run time, so is now
caught in the compiler (tgt-vvp). Where when this functionality is
needed, it will be easy to know what to do instead of trying to track
down some odd runtime functionality.

What this all means is that you can force a signal to an entire
signal or you can force a constant to any part of a signal (bit,
part or entire) and release any of the above. Technically the
release of a constant value does not have to match the force.
The runtime verifies that if you are releasing a signal driver
it is being done as a full release. I don't see an easy way to
check this in the compiler.

To fix the signal deficiencies we need to rework the force_link
code to allow multiple drivers and partial unlinking. Much of
this is in the runtime, but the %force/link operator may also
need to be changed like I did to the %release opcode.
2008-03-11 19:56:58 -07:00
Cary R cc28a9a734 Improve error message in tgt-vvp/eval_expr.c:draw_eval_expr_wid().
The IVL_EX_NONE type was not displaying any message and default did not
use the new ivl_expr_{file,lineno} functions to get the source location.
This patch remedies these problems.
2008-03-11 19:47:22 -07:00
Stephen Williams 6f1445ff9d Minor cleanup of vpi_put_value to wire
Comments to clarify the vpiForceFlag and vpiReleaseFlag behaviors.
2008-03-10 22:18:41 -07:00
Stephen Williams e0fbc15bd4 Support vpiForceFlag and vpiReleaseFlag for nets.
vpi_put_value can mimic force and release with vpiForceFlag and
vpiReleaseFlag flags to the vpi_put_value call. With this patch,
the infrastructure is added to allow the flags argument to be passed
to the dispatched put_value function, and for signals handle those
flags as force/release of a net.
2008-03-10 21:54:58 -07:00
Stephen Williams e141d2bb37 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-03-10 19:24:40 -07:00
Cary R fe72d02cf6 Major rework of the ternary operator elaboration code.
This patch reworks much of the ternary code to short circuit when
possible and supports real values better. It adds a blend operator
for real values that returns 0.0 when the values differ and the value
when they match. This deviates slightly from the standard which
specifies that the value for reals is always 0.0 when the conditional
is 'bx. There are also a couple bug fixes.

These fixes have not been ported to continuous assignments yet.
Ternary operators used at compile time and in procedural assignments
should be complete (short circuit and support real values).
2008-03-08 19:45:13 -08:00
Cary R c2bae1ad6c Fix a small bug in the extra digits warning.
There were a couple places where a normal decimal number was
accidentally setting the base for an unsized number. This is
only a warning problem.
2008-03-06 20:42:07 -08:00
Stephen Williams 692caca9dc Connect module instance arrays MSB to MSB.
When a bit port of a module instance is connected to a vector
argument, the MSB module instance should be connected to the MSB
of the vector argument. This matters only in the rare case that
the %m is used. It also makes wave dumps come out right.
2008-03-06 20:37:08 -08:00
Michael Witten 8b45797ccf ivlpp: Fixed handling of absolute paths
The updates to the do_include code destroyed the
handling of absolute paths; all of the code that
handles buffer-switching was erroneously placed
in just the relative-path branch. Thanks go to
Cary R. for pointing out the problem.

Now the common code has been extracted yet again,
and the notorious goto statement has been used
in favor redundancy.

The test vvp_reg.pl produces the same output as
before, so hopefully nothing new is broken.

Signed-off-by: Michael Witten <[email protected]>
2008-03-05 08:42:57 -08:00
Stephen Williams 8d3febff2b Keep processes in proper lexical scope
Normally processes are found in the lexical scope of a module, but
there are special cases where processes (other then task/function
definitions) are in other lexical scopes. The most likely case is
initilizations that are in the lexical scope where the assigned
variable is declared.

In the process, the behaviors list is kept in the base PScope class
instead of the Module or any other derived lexical scope class.
2008-03-03 20:49:52 -08:00
Cary R 3221f70bcb Add vvp_fun_part_var::recv_vec4_pv().
Add missing vvp_fun_part_var::recv_vec4_pv() function. This is mostly
a duplicate of the _pv() routine from vvp_fun_part.
2008-03-02 21:20:56 -08:00
Stephen Williams cb920bd864 Merge branch 'master' of [email protected]:git/verilog 2008-03-02 21:04:46 -08:00
Stephen Williams 32a2e7aa39 Fix lexical scopes within case-generate alternatives.
Case-generate alternatives create sub-scopes that need to be scanned
by the scope scanner in order to get function definitions etc. that
are defined lexically within generated scopes.
2008-03-02 21:04:04 -08:00
Stephen Williams 52ac96ca15 elaborate_sig for generated case items
Handle elaborate_sig for scopes that are within a case-generated
scheme.
2008-02-27 20:54:47 -08:00
Cary R f8caebd076 Convert real array index to integer.
This patch converts a constant real index to an integer value when
defining an array. This can happen when using 2**8 which returns a
real value since the operands are signed.
2008-02-27 18:00:21 -08:00
Cary R 70c5c9fe14 Propagate file and line information in more places.
There where a few places that were not propagating the file and
line information.
2008-02-27 17:31:20 -08:00
Stephen Williams 75df8fb6bb Remove index register restrictions on ix/arith instructions.
The %ix/<arith> instructions are currently not in use, but even so
it is just plain wrong to restrict their register argument to 0-3.
2008-02-27 17:01:53 -08:00
Cary R ec87c7f6de Fix %ix/load to work with all index registers.
draw_number_bool64() in tgt-vvp/eval_bool.c was using %ix/load to
load immediate values into registers greater than three. The problem
was that of_IX_LOAD() in vvp/vthread.cc was masking off the upper
bits. This was putting the results in the wrong register. This patch
removes the bit masking from of_IX_LOAD() and updates the %ix/load
documentation.
2008-02-27 16:54:38 -08:00
Cary R b5ef6d7a37 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:01:59 -08:00
Cary R 285ff2859f Add power operator synthesize().
This patch adds synthesize() for the power operator.
2008-02-25 15:57:56 -08:00
Michael Witten a01bc5e245 ivlpp: Cleanup: Formatting/Detabification
The file lexor.lex was beginning to suffer a catastrophic
increase in entropy due mainly to the mingling of spaces
and tabs--an age-old problem that often finds itself as
the subject of many a religious war.

The key rule: Make it consistent in as many editors as
possible; this was achieved by converting all hard tabs
into soft tabs (composed of spaces) of width 4.

I couldn't help but make modifications to the code as I
tabifified, but most of the changes are strictly style.

While maintainers generally treat large scale whitespace and
formatting changes with much caution, I believe that the code
is now much more maintainable; moreover, the test suite
produces the same results as before.

Signed-off-by: Michael Witten <[email protected]>
2008-02-25 15:52:41 -08:00
Michael Witten c6ce3f6f38 ivlpp: Error checking for macro names
Macro names cannot be compiler directive names.
Such trespasses are now recognized and reported:

    (1) Offending `define lines are skipped.

    (2) Offending macros meant to be expanded
        are replaced with nothing.

Signed-off-by: Michael Witten <[email protected]>
2008-02-25 15:51:34 -08:00
Cary R fac1cc5a1c Add user function synth and clean up expression code.
This patch adds synthesize() for user functions. It also cleans up a
number of inconsistencies and missing checks in the expression code.
2008-02-24 20:00:18 -08:00
Stephen Williams 11a33a0907 Merge branch 'pscope' 2008-02-24 19:45:21 -08:00
Stephen Williams 8e704cbf93 Rework handling of lexical scope
Move the storage of wires (signals) out of the Module class into
the PScope base class, and instead of putting the PWires all into
the Module object, distribute them into the various lexical scopes
(derived from PScope) so that the wire names do not need to carry
scope information.

This required some rewiring of elaboration of signals, and rewriting
of lexical scope handling.
2008-02-24 19:40:54 -08:00
Cary R 3716e972ec Add support for unary +/- in real parameter evaluation.
This patch adds support for unary + and - of real value constants
to the eval_tree() functionality.
2008-02-20 17:24:44 -08:00
Cary R 538d3d1f4d Print an error message if $fscanf() is called with a NULL fd.
If $fscanf() is called with a NULL file descriptor an appropriate
error message is printed and the program exits.
2008-02-20 17:16:52 -08:00
Cary R 528af27769 Fix a realloc size error and initialize enable_ in the dff.
The buffer reallocation in scan_format_string() was one character
too small. The enable_ pin to the dff primitive was not given an
initial value.
2008-02-19 10:06:44 -08:00
Michael Witten 2bd13964cd ivlpp: Slight rearrangement of do_include()
The ordering of the logic was a little strange before.
Also, there were unnecessary operations, like the assert
and the include_dir[0]=0 business.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:56:18 -08:00
Michael Witten 105885402f ivlpp: Fixed include_path inconsistency
Discussions online and "standards" documents are never
conclusive, but the code that was present suggests that
iverilog adopts the sane practice of resolving relative
paths against the directory of the file that is currently
being processed.

Unfortunately, when a relative path is made absolute, the
code forgot to update the necessary include_stack_t object.

This has now been fixed.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:56:18 -08:00
Michael Witten b512671643 ivlpp: Removed yywrap() to handle EOF more sanely
When the lexical analyzer encounters and EOF, the
analyzer invokes yywrap() to determine what to do
next. The function determines one of two paths of
execution:

	(1)	If yywrap() returns 0, then the analyzer
		assumes that yywrap() has setup a new input
		source, and so scanning continues.

	(2)	If yywrap() returns non-zero, then the analyzer
		assumes that yywrap() has not setup a new input
		source, and so the analyzer proceeds to run the
		matching EOF action (the default of which invokes
		yyterminate()).

	NOTE:	The analyzer does not touch the start condition.

The old implementation was using yywrap() to destroy the current
input source and setup the next one. However, this causes problems
when the analyzer is in the middle of parsing some directive:

	(1)	Because yywrap() is called before any EOF action,
		the include_stack_t structure is destroyed before
		being used in the EOF action; the result is a segfault.

	(2)	Because yywrap() does not change the start condition,
		any EOF action would occur completely out of context;
		however, because of (1), this problem never cropped
		up.

The new implementation simply:

	(1)	Employs "%option noyywrap", which effectively causes
		the analyzer to act as though yywrap() produces a non-zero.

	(2)	Renames yywrap "load_next_input".

	(3)	Calls load_next_input() explicitly in exhaustive EOF actions,
		so that control is more fine grained.

The added benefit is that the code that finishes parsing EOF terminated
directives now works properly; `include and `define directives previously
segfaulted in such situations.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:56:18 -08:00
Michael Witten c064451e15 ivlpp: Formatting/Simplification
Code is now shared among rules.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:31:02 -08:00
Michael Witten 73f8c2e68c ivlpp: Fixed incorrect lineno
Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:31:02 -08:00
Michael Witten 6103a72927 ivlpp: Removed delayed_close
This variable was used in yywrap purportedly to obviate
hidden access to a file that should be closable.

After investigating the code flex produces, it would
seem that these fears are unfounded.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:31:02 -08:00
Michael Witten 3bdf0a13d6 ivlpp: Clarification
A simple comment to clarify the use of standby for the inclusion stack.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:31:02 -08:00
Michael Witten 623073c722 ivlpp: Removed the unnecessary parser
The verilog preprocessing language is sufficiently simple
that the parser may be implemented by hand on top of the
lexical analyzer.

In fact, ivlpp was already implemented in this way; relevant
[bison] parser files specified no grammar, and the parser
entry-point (yyparse) was simply an indirect use of the lexical
analyzer (yylex).

Therefore, parse.y has been removed, invocations of yyparse()
have been replaced by yylex(), references to bison generated
files have been removed, and Makefile.in has been updated
accordingly.

Signed-off-by: Michael Witten <[email protected]>
2008-02-19 09:31:02 -08:00
Cary R e989f63192 Fix thread address check and wide vector unaligned copy.
This patch fixes two problems. The first is that thr_check_addr()
was being used inconsistently. It should be passed a real address,
but the resize of the vector should be at least one more than this
address. The extra and unneeded CPU_WORD_BITS was also removed
from the routine.

The second problem involved an invalid memory access in
vvp_vector4_t::set_vec() when the vector being copied was an integer
multiple of the machine word width. Under this condition there would
be no remaining bits that needed to be copied but the routine was always
trying to copying some remaining bits. This code is now only executed
when there is a remainder.

Neither of these appear to be causing runtime problems. The second one
was found with valgrind. The first were found while tracking down the
second problem.
2008-02-19 09:21:20 -08:00
Larry Doolittle 39dd22ace4 Adjust unusual spacing
minimal changes, nearly eliminates oddball/inconsistent
source code use of whitespace
2008-02-19 09:15:03 -08:00
Stephen Williams ceef77e15f Merge branch 'master' of [email protected]:git/verilog 2008-02-15 21:21:13 -08:00
Stephen Williams b0e4a6884a Objects of lexical scope use PScope base class.
All the pform objects that represent lexical scope now are derived
from the PScope class, and are kept in a lexical_scope table so that
the scope can be managed.
2008-02-15 21:20:24 -08:00
Cary R e7ea90c812 Explicitly initialize real values to 0.0.
This patch explicitly initializes real values to 0.0. Not doing
this was creating an intermittent time zero value problem.
2008-02-15 15:12:55 -08:00
Larry Doolittle f9bf502324 Correct format string
vvp_scope.c:1741: warning: format '%d' expects type 'int', but argument 5 has type 'long unsigned int'
introduced in commit
  331faa2217
2008-02-15 13:26:24 -08:00
Larry Doolittle d28fcb8941 Add missing consts
Fixes char usage introduced in commit
  331faa2217
2008-02-15 13:25:28 -08:00
Cary R 2b5560957a Force the L-value and R-value to match for real values.
Check that if either the L-value or the R-value are real then both
must be real. This prevents a runtime crash.
2008-02-13 20:44:16 -08:00
Cary R b6f26e62df Add support for delaying constants at T0.
This patch adds support for delaying constants at time zero. It also
cleans up the code in elab_net.cc to use this capability instead of
building it with an extra BUFZ to carry the delay information.
2008-02-13 20:10:55 -08:00
Stephen Williams 3f2fa29482 Factor compile-time scopes into PScope class
Modules, functions and tasks are named scopes so derive them all
from the PScope base class. These items all take scoped items, so
the eventual plan is to move these items into PScope.
2008-02-13 19:59:05 -08:00
Cary R 4d8db7b5bc Clean pulse events for real signals.
This patch cleans pulse events for real signals. Not doing this
can produce invalid results under some conditions.
2008-02-13 15:43:19 -08:00
Cary R 2bab415626 Add message for unsupported release of part/bit select.
This patch adds a real error message instead of an assert when
someone attempts to release a part or bit select. I plan to work
on the real functionality soon.
2008-02-13 15:37:53 -08:00
Stephen Williams 110bc2e6eb Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-02-13 15:27:39 -08:00
Cary R 331faa2217 Add signed bit based power to continuous assignments.
This patch adds the power operator for signed bit based values
in a continuous assignment. It also fixes a few other power
expression width problems. The expression width is still not
calculated correctly, since the correct method can produce huge
possible bit widths. The result is currently limited to the width
of the native long. This is because lround() is used to convert
from a double to an integer. A check in the code generator protects
the runtime from this limitation.
2008-02-11 20:06:41 -08:00
Stephen Williams f2ff25bfef Dump delays of constants. 2008-02-09 22:20:01 -08:00
Stephen Williams bc1d3eb7cd Add support for generate case
Generate case is a complex generate scheme where the items are
sub-schemes of the case generate itself. The parser handles them
something like nested generate statements, but storing the case
guards as the test expression. Then the elaborator notes the
case scheme and reaches into the case item schemes inside to make
up tests, select the generate item, and elaborate.
2008-02-09 22:19:42 -08:00
Larry Doolittle 63e2aa8d1a refine man page treatment of -d
also renames config file option from scope to scopes,
for consistency with the source code, and adds a
wiki reference to the man page.
2008-02-08 15:30:21 -08:00
Stephen Williams 0ac36dc5af Merge branch 'master' of [email protected]:git/verilog 2008-02-06 18:38:55 -08:00
Stephen Williams 3a300725de Output delays for part select nets.
Implement net delays for part select devices.
2008-02-06 18:37:42 -08:00
Cary R 85229a6cdc Add unsigned bit based power to continuous assignments.
This patch adds the power operator for unsigned bit based values
in a continuous assignment. It also refactors the power code for
normal expressions and continuous assignments.
2008-02-06 14:38:16 -08:00
Cary R 47d1d981d5 Mangle the scope for user functions in a continuous assignment.
User functions called in a continuous assignment were not getting
their scope mangled. This is needed to handle arrayed instances and
possibly other things.
2008-02-06 14:28:08 -08:00
Stephen Williams fb63bf7dba Compile portability issues. 2008-02-05 20:36:57 -08:00
Martin Whitaker 3d2e791e52 Fix for pr1887168.
This patch fixes some bugs in the implementation of signed integer
division with wide operands in constant expressions and adds support
for signed integer modulus with wide operands in constant expressions.
It also removes a few redundant lines of code.
2008-02-05 15:48:07 -08:00
Larry Doolittle aaf8908676 Document new -d flag to driver
followup to commit 6256dd8040
2008-02-05 15:44:14 -08:00
Cary R 4cf8920e48 Fix trimming of unsigned verinum values.
Incorrect trimming of unsigned verinum values was causing the
compilers unsigned constant verinum pow function to give
incorrect results. This patch restores the pow compile time
optimization and fixes the trimming to always leave a single
zero in the MSB.
2008-02-05 15:40:21 -08:00
Cary R e82293c981 Add unsigned bit based power support to normal expressions.
This patch adds bit based power support to normal expressions.
It also pushes the constant unsigned bit based calculation to
the runtime until the bit based method can be copied to the
compiler. Continuous assignments also need to use this type
of calculation.
2008-02-05 15:33:51 -08:00
Stephen Williams 1b410f0c7d Factor code for processing parameters and localparams
Replace some redundant code with a single function that handles the
elaboration and type management of parameters identically.
2008-02-05 13:37:33 -08:00
Martin Whitaker 51b1804660 Fix for pr1885847.
Currently, if a localparam declaration does not include a type or
range, the RHS expression is cast to an unsigned value. This patch
changes this to make the localparam inherit the type of the RHS
expression, as is done for parameter declarations and is specified
by the Verilog-2001 standard.
2008-02-05 13:06:42 -08:00
Cary R 40064b3181 Catch that we do not currently support unsigned bit based power.
This patch adds a check and prints a warning message when the power
operator is used with unsigned bit based values. It also fixes a couple
of typos and adds an asserts if the above power operator happens to
get to the tgt-vvp back end.
2008-02-04 13:35:44 -08:00
Larry Doolittle 0e6d6b7416 Fix typos in vpi/sys_display.c
Fallout from me trying to understand the origin of pr1780480
and pr1830834.  Too bad I don't understand c++ and vvp as
well as I understand English!

(Spelling and grammer fixes in comments. -ed.)
2008-02-04 13:33:24 -08:00
Larry Doolittle f4cf7b1799 Cleanup from yesterday's "Add more error checking" patch
Removes const char related compiler warnings,
tidies up mainline code by abstracting the human_readable_op() routine
2008-02-04 13:30:30 -08:00
Michael Witten 9c0d2c13c9 [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 <[email protected]>
2008-02-04 13:22:32 -08:00
Stephen Williams f1f2806e3c Get delays of signed extended continuous assignments right.
Padding and continuous assignment caused problems if the continuous
assignment includes a delay. The problem is that the padding was
not necessarily included in the delay. Rework the elaboration to
make sure the padding is indeed included in the delay.
2008-02-01 20:13:23 -08:00
Cary R db851c235f Add more error checking for operators that cannot use real values.
This patch adds some checks to verify that  shifts, the reduction
operators and the bit wise operators are not used with real values.
It also includes a few other cleanups.
2008-01-31 20:15:04 -08:00
Cary R 1595ae79fd Add support for real power (**) in normal expressions.
This patch adds support for the real power (**) operator in
normal expressions.
2008-01-31 19:54:37 -08:00
Cary R f049426f25 Add support for real % in a continuous assignment.
This patch adds conditional support (2001X) for the real modulus
operator in a continuous assignment.
2008-01-31 16:56:11 -08:00
Cary R 5e8a1bd8cc Add power operator (**) for real values in a continuous assignment.
This patch adds the power operator for real values in a continuous
assignment.
2008-01-31 16:48:52 -08:00
Cary R fa759c1802 Fix problem with delay at t0 when only some of the bits change.
This patch makes sure the delay is calculated correctly when only some
of the bits change and you are comparing against the initial (t0) value.
Basically you have to check the initial value against all the bits in
the new signal not just the first bit since the order that bits change
is not deterministic.
2008-01-31 16:42:51 -08:00
Cary R 4c5481f254 Add delays for shifts, concatenation and replication in a CA.
This patch add delays in continuous assignments for the shift operators,
concatenations and replications. It also reports an error if the user
attempts to take the modulus of a real value.

This patch uncovers a couple other problems in the system. I am trying
to fix one of them. I will report the other problem shortly.
2008-01-31 16:39:12 -08:00
Cary R 1609de6ed9 Fix some bit based delays in continuous assignments.
This patch fixes some of the delays in bit based continuous
assignments (unary -, unary +constants, string constants,
reduction operators and user functions).

Use draw_lpm_output_delay() in all functions that need it.
2008-01-29 20:27:53 -08:00
Larry Doolittle d9ac146b8f Spelling fixes
only comments and documentation
some punctuation and capitalization for good measure
Changelogs are purposefully untouched
2008-01-29 20:24:24 -08:00
Larry Doolittle 31afec57b1 Fix for pr1879226, large constant shift values
Addresses pr1879226 on a couple of levels.  Analysis:

NetNet* PEBinary::elaborate_net_shift_() didn't flag dist==lwidth
as a case where all bits of the input are shifted away, which made
it create a real concatenator for this case.  It attempted to create
NetNet*tmp with zero width, which doesn't work; (lsb,msb) ends up
as (0,-1), which is later interpreted as a 2-bit wide net.

Added an assert to the NetNet constructor to catch any other lurking
attempts to create zero-width nets.

Added short-circuit code to handle the case where all bits of the input
are shifted away.  This case used to be "handled" by an assert failure.
2008-01-29 09:31:16 -08:00
Stephen Williams 76039cf595 Merge branch 'master' of [email protected]:git/verilog 2008-01-28 21:33:14 -08:00
Stephen Williams 685095b229 Support delay of user function output
When used in continuous assignments, user defined functions may have
delayed output. Handle that by generating the proper .delay node when
needed to delay the output of a .ufunc node.
2008-01-28 21:29:03 -08:00
Stephen Williams abfccb65e9 User defined functions take real arguments
Allow user defined functions to take real value arguments and return
real value results in net contexts. Use the data type of the nets
attached to the ports to define the data types of the arguments and
return value.
2008-01-28 18:57:55 -08:00
Larry Doolittle 388bb93beb Spelling fixes
only comments and documentation
2008-01-28 09:15:39 -08:00
Stephen Williams 1eb581ab37 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-01-28 09:13:33 -08:00
Stephen Williams 2f9ad47890 Merge branch 'master' of [email protected]:git/verilog 2008-01-27 18:25:11 -08:00
Larry Doolittle 47d65034db Spelling fixes
mostly comments, but includes some identifiers and message text
2008-01-27 18:18:13 -08:00
Stephen Williams b297a0a9fe Remove support for vvp32 build
Remove configure and Makefile support for the vvp32 build. Remove
also the libdir64 support.
2008-01-25 17:33:32 -08:00
Larry Doolittle 6256dd8040 Add support for ivl debug flags. 2008-01-25 11:16:44 -08:00
Stephen Williams 5ec91ec914 Add datarootdir to makefiles
It seems that later versions of autoconf expect datarootdir to be
use and set.
2008-01-24 12:10:31 -08:00
Stephen Williams 76164d7711 Rework compile-time evaluation of LT and GT
There was much redundant code in the compile-tile handling of the
less-then and greater-then of constant expressions, and much of it
was buggy. Unify much of the code and squeeze out the bugs so that
compile-time evaluations come out correctly.
2008-01-23 20:43:13 -08:00
Stephen Williams 89bf16b21e Signed-ness of parameters
Propagate the signedness of named parameters when they are evaluated.
2008-01-22 20:16:43 -08:00
Stephen Williams 5b17f2039a Fix bug in eval of <= compare
The compiler attempts to precalculate the results of <= comparisons.
Fix a few corner cases where the arguments are signed. Also fix the
important test of constant against non-constant where we try to test
if the non-constant value can possibly make the test fail.
2008-01-21 22:05:50 -08:00
Stephen Williams db25bba0d0 Fix assertion fail handling certain conditional delays
When conditional delays are in use, it is sometimes possible for there
to be no delays available for a given input event. In that case, skip
the delay processing for that case instead of crashing.
2008-01-21 19:57:17 -08:00
Cary R 10d25d2b88 Support delays for all operators in a continuous assignments.
Previously only the logical operators (~, &, |, ^, etc.) supported a
delayed value in a continuous assignment. This patch should extend this
to all operators. An extensive check of real values was done. The same
will be done shortly for bit based nets.

Checks for constructs currently unsupported in continuous assignments
provide a more explicit message (** operator, real user functions,
{!, && and ||} operators with a real argument).
2008-01-21 18:21:31 -08:00
Stephen Williams 3ea72109f8 Read and include sign of scanned decimal.
Fix simple bug where negative values read from the source file were
not getting their sign. The fix was proposed in pr1876738.
2008-01-21 18:11:28 -08:00
Stephen Williams b6b7d704b2 Clean up lexing of net literals.
The matching of net literals (i.e. Cx<> and T<> symbols) should not get
in the way of properly matching other symbols.
2008-01-21 17:52:40 -08:00
Stephen Williams 32d3e5ac46 Better formatting of Cr<> label for real valued drivers.
Rework the encoding of a real value in the Cr<> label to be similar to
the format used by the %loadi/wr instruction. This mantissa-expoment
format better carries all the bits of the desired real value with
plenty of fidelity and range.
2008-01-19 16:27:09 -08:00
Cary R ea1f448300 Real multiply in a cont. assign. is always 1 bit wide.
The continuous assignment multiply expands vectors to the sum
of the two widths. This is correct for bit based vectors, but
for real variables it should always be one bit wide.
2008-01-17 12:52:30 -08:00
Stephen Williams d992ec4bd4 Declare $rtoi in system.sft instead of the sys_funcs table.
The sys_funcs table should be left to those functions that are handled
internally by the compiler. Really, the internal sys_funcs table is a
legacy from the days before the compiler supported system function
tables in the .sft format.
2008-01-17 12:48:02 -08:00
Cary R 592a303ce5 Add $rtoi to system func. table and add check for NULL name.
System functions used in a continuous assignment must be defined
in the system function table since the name of the system functions
is kept in this definition. The default name is NULL which causes
problems. This patch add $rtoi to the system table and adds a check
for a NULL name.
2008-01-17 12:42:05 -08:00
Cary R 52a346ab38 Print real constant value comment with %g
The comment that shows the intended value for real constants was
being printed with a %f. This is wrong for large or small values.
This patch changes the %f to a %g to get more consistent results.
2008-01-17 12:31:08 -08:00
Cary R 0fa223434e Add check target to tgt-verilog/Makefile.in
Add the missing check target to Makefile.in.
2008-01-17 12:29:15 -08:00
Stephen Williams e1bf2ec019 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-01-16 16:55:26 -08:00
Cary R ded0fbe5ef Fix user functions with right shift argument.
A right shift may generate extra bits to preserve the proper shift
characteristic. This patch replaces the assert that was forcing the
input vector to not be greater than the input port width with code
to only select the required lower bits from the vector if it is
larger than the input port.
2008-01-15 21:01:16 -08:00
Cary R 0370f30b20 Support variable delay of a variable selected assignment.
This patch adds support for the following statement:

<vector>[<i>] <= #<delay> <value>.

It is a copy with slight modification of code from the next
else/if clause.
2008-01-15 20:33:36 -08:00
Cary R eac6333d6c Add missing deletes for patch "Add real compar..."
Add two deletes that I missed in the previous patch.
2008-01-15 19:48:49 -08:00
Cary R 1ff31db2cc Add real comparisons in continuous assignments.
This patch adds real comparisons in continuous assignments.
It also converts bit based constants to real values when needed
by the comparisons.
2008-01-15 19:48:26 -08:00
Stephen Williams 59ee700634 Net arrays that are addressed are not dangling
The nodangle functor tries to delete NetNet objects that are not used.
But NetNet objects that are addressed by a NetArrayDq should never be
dangling. So make sure the NetArrayDq marks the target NetNet correctly.
2008-01-15 19:39:53 -08:00
Cary R e46f8220f3 Evaluate non-immediate signal selection.
This patch adds code to treat non-immediate signal selection the
same as the default logic evaluation
2008-01-14 19:55:14 -08:00
Cary R 7ff342f4da Fix type warning in tgt-vvp/eval_expr.c
In a previous patch I missed this type inconsistency.
2008-01-14 19:51:38 -08:00
Stephen Williams 190aefcf89 Use inttypes.h to get uint64_t print format string
Code generators should not include _pli_types.h to get standard int
types and strings. Use the inttypes.h header file instead.
2008-01-14 09:53:20 -08:00
Stephen Williams cdfe3a8289 Use inttypes.h to get uint64_t print format string
Code generators should not include _pli_types.h to get standard int
types and strings. Use the inttypes.h header file instead.
2008-01-14 09:47:48 -08:00
Cary R c899a6a52e Add %load/avp0 opcode and fix %load/vp0.
This patch adds a new opcode %load/avp0 that is used to load a
word from an array and add a value to it. %load/vp0 was
changed/fixed to do the summation at the result width not the
vector width. This allows small vectors to index large arrays with
an offset. A few errors in the opcodes.txt file were also fixed.
2008-01-13 19:47:49 -08:00
Cary R e18b64768e Add missing check target in some Makefile.in files.
This patch adds a check target to the Makefile.in files in the
tgt-null, tgt-stub and vpi directories.
2008-01-11 21:52:51 -08:00
237 changed files with 20095 additions and 12743 deletions
+2 -2
View File
@@ -72,11 +72,11 @@ reporting problems with. However, if you clearly explain what is right
and wrong about the generated netlist, I will probably be able to fix
the problem. It may take a few iterations.
In this case, if possible include not only the sample verilog program,
In this case, if possible include not only the sample Verilog program,
but the generated netlist file(s) and a clear indication of what went
wrong. If it is not clear to me, I will ask for clarification.
* The Output is Correct, But Less Then Ideal
* The Output is Correct, But Less Than Ideal
If the output is strictly correct, but just not good enough for
practical use, I would like to know. These sorts of problems are
+1 -1
View File
@@ -32,7 +32,7 @@ using namespace std;
/*
* This class represents a component of a Verilog hierarchical name. A
* hierarchical component contains a name string (prepresented here
* hierarchical component contains a name string (represented here
* with a perm_string) and an optional signed number. This signed
* number is used if the scope is part of an array, for example an
* array of module instances or a loop generated scope.
+76 -41
View File
@@ -16,9 +16,6 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
#
#
SHELL = /bin/sh
# This version string is only used in the version message printed
@@ -30,6 +27,7 @@ VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
SUBDIRS = @subdirs@
@@ -40,8 +38,6 @@ libdir = @libdir@
includedir = @includedir@
mandir = @mandir@
libdir64 = @libdir64@
dllib=@DLLIB@
CC = @CC@
@@ -52,13 +48,16 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
MAN = @MAN@
PS2PDF = @PS2PDF@
GIT = @GIT@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
CXXFLAGS = -Wall @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
all: dep ivl@EXEEXT@
all: dep version.h ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in ivlpp ; \
do (cd $$dir ; $(MAKE) $@); done
@@ -66,7 +65,7 @@ all: dep ivl@EXEEXT@
# In the windows world, the installer will need a dosify program to
# dosify text files.
ifeq (@MING32@,yes)
ifeq (@MINGW32@,yes)
all: dep dosify.exe
dosify.exe: dosify.c
$(CC) -o dosify.exe dosify.c
@@ -100,19 +99,19 @@ distclean: clean
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o elab_expr.o \
elab_lval.o elab_net.o elab_pexpr.o elab_scope.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 \
load_module.o netlist.o netmisc.o net_assign.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_proc.o net_scope.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o pform_types.o \
net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o PSpec.o \
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
@@ -125,9 +124,9 @@ ifeq (@WIN32@,yes)
# The first step makes an ivl.exe that dlltool can use to make an
# export and import library, and the last link makes a, ivl.exe
# that really exports the things that the import library imports.
ivl@EXEEXT@: $O ivl.def
ivl@EXEEXT@: $O $(srcdir)/ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
dlltool --dllname ivl@EXEEXT@ --def ivl.def \
dlltool --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \
--output-lib libivl.a --output-exp ivl.exp
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
else
@@ -146,8 +145,6 @@ iverilog-vpi: iverilog-vpi.sh
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
-e 's;@INCLUDEDIR@;@includedir@;' \
-e 's;@LIBDIR64@;@libdir64@;' \
-e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@
endif
@@ -177,18 +174,50 @@ lexor.cc: $(srcdir)/lexor.lex
lexor_keyword.o: lexor_keyword.cc parse.h
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-4,$$ -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
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
$(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
iverilog-vpi.pdf: iverilog-vpi.ps
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
ifeq (@MING32@,yes)
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
# version.h file in the source tree (included in snapshots and releases), and
# finally use nothing.
.PHONY: version.h
# "true" and "false" in the next few lines are Unix shell command names
ifeq ($(GIT),none)
GIT_PRESENT = false
else
GIT_PRESENT = true
endif
version.h:
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
echo "Using git-describe for VERSION_TAG"; \
tmp=`$(GIT) --git-dir $(srcdir)/.git describe \
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
echo "$$tmp" | diff - $@ > /dev/null 2>&1 || echo "$$tmp" > $@ || exit 1; \
elif test -r $(srcdir)/$@; then \
echo "Using $(srcdir)/$@ for VERSION_TAG"; \
diff $(srcdir)/$@ $@ > /dev/null 2>&1 || cp $(srcdir)/$@ $@; \
else \
echo "Using empty VERSION_TAG"; \
echo '#define VERSION_TAG ""' > $@; \
fi
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
else
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
INSTALL_DOCDIR = $(mandir)/man1
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
INSTALL_DOCDIR = $(mandir)/man1
@@ -202,43 +231,49 @@ endif
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/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)
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
$(bindir)/iverilog-vpi: ./iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivl@EXEEXT@
$(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams $@
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams $@
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
$(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl/xnf.conf
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
$(includedir)/_pli_types.h: _pli_types.h
$(INSTALL_DATA) $< $(includedir)/_pli_types.h
$(INSTALL_DATA) $< $(DESTDIR)$(includedir)/_pli_types.h
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(DESTDIR)$(includedir)/vpi_user.h
$(includedir)/acc_user.h: $(srcdir)/acc_user.h
$(INSTALL_DATA) $(srcdir)/acc_user.h $(includedir)/acc_user.h
$(INSTALL_DATA) $(srcdir)/acc_user.h $(DESTDIR)$(includedir)/acc_user.h
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h $(DESTDIR)$(includedir)/veriuser.h
$(mandir)/man1/iverilog-vpi.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.1
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf $(prefix)/iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi.pdf
# In windows installations, put a few examples and the quick_start
# into the destination directory.
@@ -261,22 +296,22 @@ $(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
endif
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl \
$(libdir)/ivl/include $(mandir) $(mandir)/man1
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl \
$(DESTDIR)$(libdir)/ivl/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
do rm -f $(libdir)/ivl/$$f; done
-rmdir $(libdir)/ivl/include
-rmdir $(libdir)/ivl
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
-rmdir $(DESTDIR)$(libdir)/ivl/include
-rmdir $(DESTDIR)$(libdir)/ivl
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
do rm -f $(bindir)/$$f; done
do rm -f $(DESTDIR)$(bindir)/$$f; done
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
do rm -f $(includedir)/$$f; done
rm -f $(mandir)/man1/iverilog-vpi.1 $(prefix)/iverilog-vpi.pdf
do rm -f $(DESTDIR)$(includedir)/$$f; done
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi.1 $(DESTDIR)$(prefix)/iverilog-vpi.pdf
-include $(patsubst %.o, dep/%.d, $O)
+2 -128
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -29,7 +26,7 @@
/* n is a permallocated string. */
Module::Module(perm_string n)
: name_(n)
: PScope(n, 0)
{
library_flag = false;
default_nettype = NetNet::NONE;
@@ -54,21 +51,6 @@ void Module::add_function(perm_string name, PFunction *func)
funcs_[name] = func;
}
PWire* Module::add_wire(PWire*wire)
{
PWire*&ep = wires_[wire->path()];
if (ep) return ep;
assert(ep == 0);
ep = wire;
return wire;
}
void Module::add_behavior(PProcess*b)
{
behaviors_.push_back(b);
}
unsigned Module::port_count() const
{
return ports.count();
@@ -111,15 +93,6 @@ unsigned Module::find_port(const char*name) const
}
PWire* Module::get_wire(const pform_name_t&name) const
{
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
if (obj == wires_.end())
return 0;
else
return (*obj).second;
}
PGate* Module::get_gate(perm_string name)
{
for (list<PGate*>::iterator cur = gates_.begin()
@@ -138,102 +111,3 @@ const list<PGate*>& Module::get_gates() const
return gates_;
}
const list<PProcess*>& Module::get_behaviors() const
{
return behaviors_;
}
/*
* $Log: Module.cc,v $
* Revision 1.27 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.26 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.25 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
*
* Revision 1.24 2004/06/13 04:56:53 steve
* Add support for the default_nettype directive.
*
* Revision 1.23 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
* Revision 1.22 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.21 2003/04/02 03:00:14 steve
* Cope with empty module ports while binding by name.
*
* Revision 1.20 2003/03/06 04:37:12 steve
* lex_strings.add module names earlier.
*
* Revision 1.19 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.18 2002/05/19 23:37:28 steve
* Parse port_declaration_lists from the 2001 Standard.
*
* Revision 1.17 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.16 2001/10/20 05:21:51 steve
* Scope/module names are char* instead of string.
*
* Revision 1.15 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.14 2000/11/15 20:31:05 steve
* Fix warning about temporaries.
*
* Revision 1.13 2000/11/05 06:05:59 steve
* Handle connectsion to internally unconnected modules (PR#38)
*
* Revision 1.12 2000/05/16 04:05:15 steve
* Module ports are really special PEIdent
* expressions, because a name can be used
* many places in the port list.
*
* Revision 1.11 2000/03/12 17:09:40 steve
* Support localparam.
*
* Revision 1.10 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.9 2000/01/09 20:37:57 steve
* Careful with wires connected to multiple ports.
*
* Revision 1.8 1999/12/11 05:45:41 steve
* Fix support for attaching attributes to primitive gates.
*
* Revision 1.7 1999/09/17 02:06:25 steve
* Handle unconnected module ports.
*
* Revision 1.6 1999/08/04 02:13:02 steve
* Elaborate module ports that are concatenations of
* module signals.
*
* Revision 1.5 1999/08/03 04:14:49 steve
* Parse into pform arbitrarily complex module
* port declarations.
*
* Revision 1.4 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* Revision 1.3 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
* Revision 1.2 1999/06/17 05:34:42 steve
* Clean up interface of the PWire class,
* Properly match wire ranges.
*
* Revision 1.1 1998/11/03 23:28:51 steve
* Introduce verilog to CVS.
*
*/
+33 -50
View File
@@ -1,7 +1,7 @@
#ifndef __Module_H
#define __Module_H
/*
* Copyright (c) 1998-2004 Stephen Williams ([email protected])
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,9 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
#endif
# include <list>
# include <map>
@@ -28,10 +26,10 @@
# include "StringHeap.h"
# include "HName.h"
# include "named.h"
# include "PScope.h"
# include "LineInfo.h"
# include "netlist.h"
# include "pform_types.h"
class PEvent;
class PExpr;
class PEIdent;
class PGate;
@@ -50,7 +48,7 @@ class NetScope;
* therefore the handle for grasping the described circuit.
*/
class Module : public LineInfo {
class Module : public PScope, public LineInfo {
/* The module ports are in general a vector of port_t
objects. Each port has a name and an ordered list of
@@ -77,14 +75,35 @@ class Module : public LineInfo {
NetNet::Type default_nettype;
struct range_t {
// True if this is an exclude
bool exclude_flag;
// lower bound
// If low_open_flag is false and low_expr=0, then use -inf
bool low_open_flag;
PExpr*low_expr;
// upper bound
// If high_open_flag is false and high_expr=0, then use +inf
bool high_open_flag;
PExpr*high_expr;
// Next range description in list
struct range_t*next;
};
/* The module has parameters that are evaluated when the
module is elaborated. During parsing, I put the parameters
into this map. */
struct param_expr_t {
PExpr*expr;
struct param_expr_t : public LineInfo {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
// Value expression
PExpr*expr;
// If there are range constrants, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
@@ -113,9 +132,6 @@ class Module : public LineInfo {
named array of PEident pointers. */
svector<port_t*> ports;
/* Keep a table of named events declared in the module. */
map<perm_string,PEvent*>events;
map<perm_string,PExpr*> attributes;
/* These are the timescale for this module. The default is
@@ -124,7 +140,7 @@ class Module : public LineInfo {
/* The module has a list of genvars that may be used in
various generate schemes. */
list<perm_string> genvars;
map<perm_string,LineInfo*> genvars;
/* the module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
@@ -132,16 +148,10 @@ class Module : public LineInfo {
list<PSpecPath*> specify_paths;
perm_string mod_name() const { return name_; }
// The mod_name() is the name of the module type.
perm_string mod_name() const { return pscope_name(); }
void add_gate(PGate*gate);
// The add_wire method adds a wire by name, but only if the
// wire name doesn't already exist. Either way, the result is
// the existing wire or the pointer passed in.
PWire* add_wire(PWire*wire);
void add_behavior(PProcess*behave);
void add_task(perm_string name, PTask*def);
void add_function(perm_string name, PFunction*def);
@@ -149,13 +159,9 @@ class Module : public LineInfo {
const svector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) const;
// Find a wire by name. This is used for connecting gates to
// existing wires, etc.
PWire* get_wire(const pform_name_t&name) const;
PGate* get_gate(perm_string name);
const list<PGate*>& get_gates() const;
const list<PProcess*>& get_behaviors() const;
void dump(ostream&out) const;
bool elaborate(Design*, NetScope*scope) const;
@@ -166,39 +172,16 @@ class Module : public LineInfo {
bool elaborate_sig(Design*, NetScope*scope) const;
private:
perm_string name_;
map<pform_name_t,PWire*> wires_;
list<PGate*> gates_;
list<PProcess*> behaviors_;
map<perm_string,PTask*> tasks_;
map<perm_string,PFunction*> funcs_;
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope);
private: // Not implemented
Module(const Module&);
Module& operator= (const Module&);
};
/*
* $Log: Module.h,v $
* Revision 1.43 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.42 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.41 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.39 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters.
*
* Revision 1.38 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*/
#endif
+3 -65
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
* Copyright (c) 1999-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -24,6 +24,7 @@
# include "PDelays.h"
# include "PExpr.h"
# include "verinum.h"
# include "netmisc.h"
PDelays::PDelays()
{
@@ -63,10 +64,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
{
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
if (NetExpr*tmp = dex->eval_tree()) {
delete dex;
dex = tmp;
}
eval_expr(dex);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
@@ -163,63 +161,3 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
decay_time = 0;
}
}
/*
* $Log: PDelays.cc,v $
* Revision 1.15 2006/07/08 21:48:46 steve
* Handle real valued literals in net contexts.
*
* Revision 1.14 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.13 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.12 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.11 2003/06/21 01:21:42 steve
* Harmless fixup of warnings.
*
* Revision 1.10 2003/02/08 19:49:21 steve
* Calculate delay statement delays using elaborated
* expressions instead of pre-elaborated expression
* trees.
*
* Remove the eval_pexpr methods from PExpr.
*
* Revision 1.9 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.8 2001/12/29 20:19:31 steve
* Do not delete delay expressions of UDP instances.
*
* Revision 1.7 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.6 2001/11/07 04:01:59 steve
* eval_const uses scope instead of a string path.
*
* Revision 1.5 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2001/01/20 02:15:50 steve
* apologize for not supporting non-constant delays.
*
* Revision 1.3 2001/01/14 23:04:55 steve
* Generalize the evaluation of floating point delays, and
* get it working with delay assignment statements.
*
* Allow parameters to be referenced by hierarchical name.
*
* Revision 1.2 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
*/
+7 -2
View File
@@ -43,7 +43,7 @@ bool PExpr::is_constant(Module*) const
return false;
}
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
{
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
<< *this << endl;
@@ -191,7 +191,7 @@ PEIdent::~PEIdent()
/*
* An identifier can be in a constant expression if (and only if) it is
* a parameter.
* a parameter or genvar.
*
* NOTE: This test does not work if the name is hierarchical!
*/
@@ -212,6 +212,11 @@ bool PEIdent::is_constant(Module*mod) const
if (cur != mod->localparams.end()) return true;
}
{ map<perm_string,LineInfo*>::const_iterator cur;
cur = mod->genvars.find(tmp);
if (cur != mod->genvars.end()) return true;
}
return false;
}
+50 -20
View File
@@ -1,7 +1,7 @@
#ifndef __PExpr_H
#define __PExpr_H
/*
* Copyright (c) 1998-2000 Stephen Williams <[email protected]>
* Copyright (c) 1998-2008 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -74,6 +74,10 @@ class PExpr : public LineInfo {
unsigned min, unsigned lval,
bool&unsized_flag) const;
// During the elaborate_sig phase, we may need to scan
// expressions to find implicit net declarations.
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
// Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the
// l-value width of an assignment),
@@ -107,8 +111,7 @@ class PExpr : public LineInfo {
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
// This is similar to elaborate_lnet, except that the
// expression is evaluated to be bi-directional. This is
@@ -119,7 +122,7 @@ class PExpr : public LineInfo {
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method. If the
// is_force flag is true, then the set of valid l-value types
// is slightly modified to accomodate the Verilog force
// is slightly modified to accommodate the Verilog force
// statement
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
@@ -157,8 +160,8 @@ class PEConcat : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
@@ -177,7 +180,6 @@ class PEConcat : public PExpr {
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
private:
svector<PExpr*>parms_;
@@ -255,7 +257,7 @@ class PEIdent : public PExpr {
explicit PEIdent(const pform_name_t&);
~PEIdent();
// Add another name to the string of heirarchy that is the
// Add another name to the string of hierarchy that is the
// current identifier.
void append_name(perm_string);
@@ -264,9 +266,10 @@ class PEIdent : public PExpr {
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
@@ -303,6 +306,11 @@ class PEIdent : public PExpr {
private:
// Common functions to calculate parts of part/bit selects.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
NetExpr* calculate_up_do_base_(Design*, NetScope*) const;
bool calculate_param_range_(Design*, NetScope*,
const NetExpr*msb_ex, long&msb,
const NetExpr*lsb_ex, long&lsb) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
private:
@@ -318,6 +326,18 @@ class PEIdent : public PExpr {
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_param_idx_up_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
@@ -379,13 +399,12 @@ class PEIdent : public PExpr {
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const;
long&midx, long&lidx) const;
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
};
@@ -472,6 +491,8 @@ class PEUnary : public PExpr {
virtual void dump(ostream&out) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -531,6 +552,8 @@ class PEBinary : public PExpr {
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -538,7 +561,7 @@ class PEBinary : public PExpr {
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
@@ -548,10 +571,10 @@ class PEBinary : public PExpr {
PExpr*left_;
PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
static void surpress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
@@ -589,6 +612,11 @@ class PEBinary : public PExpr {
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
@@ -597,7 +625,7 @@ class PEBinary : public PExpr {
};
/*
* Here are a few specilized classes for handling specific binary
* Here are a few specialized classes for handling specific binary
* operators.
*/
class PEBComp : public PEBinary {
@@ -610,8 +638,8 @@ class PEBComp : public PEBinary {
unsigned min, unsigned lval,
bool&flag) const;
NetEBinary* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
};
class PEBShift : public PEBinary {
@@ -641,6 +669,8 @@ class PETernary : public PExpr {
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -667,7 +697,7 @@ class PETernary : public PExpr {
class PECallFunction : public PExpr {
public:
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
// Call of system function (name is not heirarchical)
// Call of system function (name is not hierarchical)
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
~PECallFunction();
+3 -31
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 Stephen Williams ([email protected])
* Copyright (c) 1999-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,16 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PFunction.cc,v 1.7 2004/05/31 23:34:36 steve Exp $"
#endif
# include "config.h"
#include "PTask.h"
PFunction::PFunction(perm_string name)
: name_(name), ports_(0), statement_(0)
PFunction::PFunction(perm_string name, PScope*parent)
: PScope(name, parent), ports_(0), statement_(0)
{
return_type_.type = PTF_NONE;
}
@@ -51,28 +48,3 @@ void PFunction::set_return(PTaskFuncArg t)
{
return_type_ = t;
}
/*
* $Log: PFunction.cc,v $
* Revision 1.7 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
* speed and more type support.
*
* Revision 1.6 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2001/01/13 22:20:08 steve
* Parse parameters within nested scopes.
*
* Revision 1.3 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/08/25 22:22:41 steve
* elaborate some aspects of functions.
*
*/
+3
View File
@@ -129,6 +129,7 @@ class PGAssign : public PGate {
void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private:
};
@@ -166,6 +167,7 @@ class PGBuiltin : public PGate {
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private:
Type type_;
@@ -234,6 +236,7 @@ class PGModule : public PGate {
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
NetNet*sig, unsigned port_wid,
+2 -12
View File
@@ -33,19 +33,9 @@ PGenerate::~PGenerate()
{
}
PWire* PGenerate::add_wire(PWire*wire)
PWire* PGenerate::get_wire(perm_string name) const
{
PWire*&ep = wires[wire->path()];
if (ep) return ep;
assert(ep == 0);
ep = wire;
return wire;
}
PWire* PGenerate::get_wire(const pform_name_t&name) const
{
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
+16 -5
View File
@@ -37,7 +37,17 @@ class PGate;
class PWire;
/*
* This represents a generate scheme.
* This represents a generate scheme. The interpretation of the
* members depends on the scheme_type.
*
* GS_LOOP
*
* GS_CASE
* loop_test is the expression to be compared.
* generates contains only GS_CASE_ITEM schemes.
* GS_CASE_ITEM
* The parent points to the GS_CASE that contains this item.
* the loop_test is compared with the parent->loop_test expression.
*/
class PGenerate : public LineInfo {
@@ -50,7 +60,8 @@ class PGenerate : public LineInfo {
const unsigned id_number;
perm_string scope_name;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE};
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
GS_CASE, GS_CASE_ITEM};
scheme_t scheme_type;
// generate loops have an index variable and three
@@ -60,9 +71,8 @@ class PGenerate : public LineInfo {
PExpr*loop_test;
PExpr*loop_step;
map<pform_name_t,PWire*>wires;
PWire* add_wire(PWire*);
PWire* get_wire(const pform_name_t&name) const;
map<perm_string,PWire*>wires;
PWire* get_wire(perm_string name) const;
list<PGate*> gates;
void add_gate(PGate*);
@@ -88,6 +98,7 @@ class PGenerate : public LineInfo {
private:
bool generate_scope_loop_(Design*des, NetScope*container);
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
bool generate_scope_case_(Design*des, NetScope*container);
// Elaborate_scope within a generated scope.
void elaborate_subscope_(Design*des, NetScope*scope);
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "PScope.h"
PScope::PScope(perm_string n, PScope*p)
: name_(n), parent_(p)
{
}
PScope::~PScope()
{
}
PWire* PScope::wires_find(perm_string name)
{
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
if (cur == wires.end())
return 0;
else
return (*cur).second;
}
+80
View File
@@ -0,0 +1,80 @@
#ifndef __PScope_H
#define __PScope_H
/*
* Copyright (c) 2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "StringHeap.h"
# include "pform_types.h"
# include <map>
class PEvent;
class PProcess;
class PWire;
class Design;
class NetScope;
/*
* The PScope class is a base representation of an object that
* represents lexical scope. For example, a module, a function/task, a
* named block is derived from a PScope.
*
* NOTE: This is note the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration.
*/
class PScope {
public:
// When created, a scope has a name and a parent. The name is
// the name of the definition. For example, if this is a
// module declaration, the name is the name after the "module"
// keyword, and if this is a task scope, the name is the task
// name. The parent is the lexical parent of this scope. Since
// modules do not nest in Verilog, the parent must be nil for
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, PScope*parent);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; }
// Nets an variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
// Named events in the scope.
map<perm_string,PEvent*>events;
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
protected:
void dump_wires_(ostream&out, unsigned indent) const;
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
bool elaborate_behaviors_(Design*des, NetScope*scope) const;
private:
perm_string name_;
PScope*parent_;
};
#endif
+3 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 Stephen Williams ([email protected])
* Copyright (c) 1999-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,16 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PTask.cc,v 1.7 2002/08/12 01:34:58 steve Exp $"
#endif
# include "config.h"
# include "PTask.h"
PTask::PTask()
: ports_(0), statement_(0)
PTask::PTask(perm_string name, PScope*parent)
: PScope(name, parent), ports_(0), statement_(0)
{
}
+6 -67
View File
@@ -1,7 +1,7 @@
#ifndef __PTask_H
#define __PTask_H
/*
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
* Copyright (c) 1999-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,11 +18,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
#endif
# include "LineInfo.h"
# include "PScope.h"
# include "svector.h"
# include "StringHeap.h"
# include <string>
@@ -50,10 +48,10 @@ struct PTaskFuncArg {
/*
* The PTask holds the parsed definitions of a task.
*/
class PTask : public LineInfo {
class PTask : public PScope, public LineInfo {
public:
explicit PTask();
explicit PTask(perm_string name, PScope*parent);
~PTask();
void set_ports(svector<PWire *>*p);
@@ -89,10 +87,10 @@ class PTask : public LineInfo {
*
* The output value is not elaborated until elaborate_sig.
*/
class PFunction : public LineInfo {
class PFunction : public PScope, public LineInfo {
public:
explicit PFunction(perm_string name);
explicit PFunction(perm_string name, PScope*parent);
~PFunction();
void set_ports(svector<PWire *>*p);
@@ -110,68 +108,9 @@ class PFunction : public LineInfo {
void dump(ostream&, unsigned) const;
private:
perm_string name_;
PTaskFuncArg return_type_;
svector<PWire *> *ports_;
Statement *statement_;
};
/*
* $Log: PTask.h,v $
* Revision 1.14 2007/03/06 05:22:49 steve
* Support signed function return values.
*
* Revision 1.13 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
* speed and more type support.
*
* Revision 1.12 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.11 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.10 2001/01/13 22:20:08 steve
* Parse parameters within nested scopes.
*
* Revision 1.9 2000/07/30 18:25:43 steve
* Rearrange task and function elaboration so that the
* NetTaskDef and NetFuncDef functions are created during
* signal enaboration, and carry these objects in the
* NetScope class instead of the extra, useless map in
* the Design class.
*
* Revision 1.8 2000/03/08 04:36:53 steve
* Redesign the implementation of scopes and parameters.
* I now generate the scopes and notice the parameters
* in a separate pass over the pform. Once the scopes
* are generated, I can process overrides and evalutate
* paremeters before elaboration begins.
*
* Revision 1.7 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.6 1999/09/30 21:28:34 steve
* Handle mutual reference of tasks by elaborating
* task definitions in two passes, like functions.
*
* Revision 1.5 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.4 1999/08/25 22:22:41 steve
* elaborate some aspects of functions.
*
* Revision 1.3 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* Revision 1.2 1999/07/24 02:11:19 steve
* Elaborate task input ports.
*
* Revision 1.1 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
*/
#endif
+20 -23
View File
@@ -22,15 +22,15 @@
# include "PExpr.h"
# include <assert.h>
PWire::PWire(const pform_name_t&n,
PWire::PWire(perm_string n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_msb_(0), port_lsb_(0), port_set_(false),
net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0),
lidx_(0), ridx_(0)
lidx_(0), ridx_(0), discipline_(0)
{
if (t == NetNet::INTEGER) {
type_ = NetNet::REG;
@@ -44,9 +44,9 @@ NetNet::Type PWire::get_wire_type() const
return type_;
}
const pform_name_t& PWire::path() const
perm_string PWire::basename() const
{
return hname_;
return name_;
}
bool PWire::set_wire_type(NetNet::Type t)
@@ -135,25 +135,12 @@ bool PWire::get_isint() const
return isint_;
}
/*
* Since implicitly defined list of port declarations are no longer
* considered fully defined we no longer need this routine to force
* them to be fully defined.
*
void PWire::set_net_range()
{
net_msb_ = port_msb_;
net_lsb_ = port_lsb_;
net_set_ = true;
}
*/
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
{
switch (type) {
case SR_PORT:
if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << hname_
cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl;
error_cnt_ += 1;
} else {
@@ -165,7 +152,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
case SR_NET:
if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << hname_
cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
@@ -178,12 +165,12 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
case SR_BOTH:
if (port_set_ || net_set_) {
if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << hname_
cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl;
error_cnt_ += 1;
}
if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << hname_
cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
}
@@ -202,7 +189,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
{
if (lidx_ != 0 || ridx_ != 0) {
cerr << get_fileline() << ": error: Array ``" << hname_
cerr << get_fileline() << ": error: Array ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
@@ -211,3 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
}
}
void PWire::set_discipline(discipline_t*d)
{
assert(discipline_ == 0);
discipline_ = d;
}
discipline_t* PWire::get_discipline(void) const
{
return discipline_;
}
+9 -4
View File
@@ -36,6 +36,7 @@ class ostream;
class PExpr;
class Design;
class discipline_t;
/*
* The different type of PWire::set_range() calls.
@@ -56,13 +57,13 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
class PWire : public LineInfo {
public:
PWire(const pform_name_t&hname,
PWire(perm_string name,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
// Return a hierarchical name.
const pform_name_t&path() const;
perm_string basename() const;
NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type);
@@ -78,10 +79,12 @@ class PWire : public LineInfo {
ivl_variable_type_t get_data_type() const;
void set_range(PExpr*msb, PExpr*lsb, PWSRType type);
void set_net_range();
void set_memory_idx(PExpr*ldx, PExpr*rdx);
void set_discipline(discipline_t*);
discipline_t* get_discipline(void) const;
map<perm_string,PExpr*> attributes;
// Write myself to the specified stream.
@@ -90,7 +93,7 @@ class PWire : public LineInfo {
NetNet* elaborate_sig(Design*, NetScope*scope) const;
private:
pform_name_t hname_;
perm_string name_;
NetNet::Type type_;
NetNet::PortType port_type_;
ivl_variable_type_t data_type_;
@@ -112,6 +115,8 @@ class PWire : public LineInfo {
PExpr*lidx_;
PExpr*ridx_;
discipline_t*discipline_;
private: // not implemented
PWire(const PWire&);
PWire& operator= (const PWire&);
+8 -8
View File
@@ -86,18 +86,13 @@ PAssignNB::~PAssignNB()
{
}
PBlock::PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st)
: name_(n), bl_type_(t), list_(st)
{
}
PBlock::PBlock(BL_TYPE t, const svector<Statement*>&st)
: bl_type_(t), list_(st)
PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
: PScope(n, parent), bl_type_(t)
{
}
PBlock::PBlock(BL_TYPE t)
: bl_type_(t)
: PScope(perm_string(),0), bl_type_(t)
{
}
@@ -107,6 +102,11 @@ PBlock::~PBlock()
delete list_[idx];
}
void PBlock::set_statement(const svector<Statement*>&st)
{
list_ = st;
}
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
: path_(n), parms_(p)
{
+17 -97
View File
@@ -1,7 +1,7 @@
#ifndef __Statement_H
#define __Statement_H
/*
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,15 +18,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
#endif
# include <string>
# include "svector.h"
# include "StringHeap.h"
# include "PDelays.h"
# include "PExpr.h"
# include "PScope.h"
# include "HName.h"
# include "LineInfo.h"
class PExpr;
@@ -83,6 +81,7 @@ class Statement : public LineInfo {
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
};
/*
@@ -147,25 +146,27 @@ class PAssignNB : public PAssign_ {
* statements before constructing this object, so it knows a priori
* what is contained.
*/
class PBlock : public Statement {
class PBlock : public PScope, public Statement {
public:
enum BL_TYPE { BL_SEQ, BL_PAR };
explicit PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st);
explicit PBlock(BL_TYPE t, const svector<Statement*>&st);
// If the block has a name, it is a scope and also has a parent.
explicit PBlock(perm_string n, PScope*parent, BL_TYPE t);
// If it doesn't have a name, it's not a scope
explicit PBlock(BL_TYPE t);
~PBlock();
BL_TYPE bl_type() const { return bl_type_; }
void set_statement(const svector<Statement*>&st);
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
private:
perm_string name_;
const BL_TYPE bl_type_;
svector<Statement*>list_;
};
@@ -215,6 +216,7 @@ class PCase : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -250,6 +252,7 @@ class PCondit : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -284,6 +287,7 @@ class PDelayStatement : public Statement {
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
private:
PExpr*delay_;
@@ -331,6 +335,7 @@ class PEventStatement : public Statement {
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
// This method is used to elaborate, but attach a previously
// elaborated statement to the event.
@@ -364,6 +369,7 @@ class PForever : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -379,6 +385,7 @@ class PForStatement : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -407,6 +414,7 @@ class PRepeat : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -452,6 +460,7 @@ class PWhile : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -459,93 +468,4 @@ class PWhile : public Statement {
Statement*statement_;
};
/*
* $Log: Statement.h,v $
* Revision 1.44 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.43 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.42 2005/12/05 21:21:18 steve
* Fixes for stubborn compilers.
*
* Revision 1.41 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.40 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.39 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.38 2003/05/19 02:50:58 steve
* Implement the wait statement behaviorally instead of as nets.
*
* Revision 1.37 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.36 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.35 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.34 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.
*
* Revision 1.33 2002/04/21 22:31:02 steve
* Redo handling of assignment internal delays.
* Leave it possible for them to be calculated
* at run time.
*
* Revision 1.32 2002/04/21 04:59:07 steve
* Add support for conbinational events by finding
* the inputs to expressions and some statements.
* Get case and assignment statements working.
*
* Revision 1.31 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.30 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.29 2000/09/09 15:21:26 steve
* move lval elaboration to PExpr virtual methods.
*
* Revision 1.28 2000/09/03 17:58:35 steve
* Change elaborate_lval to return NetAssign_ objects.
*
* Revision 1.27 2000/07/26 05:08:07 steve
* Parse disable statements to pform.
*
* Revision 1.26 2000/05/11 23:37:26 steve
* Add support for procedural continuous assignment.
*
* Revision 1.25 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.24 2000/04/12 04:23:57 steve
* Named events really should be expressed with PEIdent
* objects in the pform,
*
* Handle named events within the mix of net events
* and edges. As a unified lot they get caught together.
* wait statements are broken into more complex statements
* that include a conditional.
*
* Do not generate NetPEvent or NetNEvent objects in
* elaboration. NetEvent, NetEvWait and NetEvProbe
* take over those functions in the netlist.
*/
#endif
+1 -1
View File
@@ -16,4 +16,4 @@ do
done
echo "Precompiling lexor_keyword.gperf"
gperf -o -i 7 -C -k 1-3,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
gperf -o -i 7 -C -k 1-4,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
+3 -18
View File
@@ -16,12 +16,9 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -33,7 +30,7 @@ bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
vpidir = @libdir@/ivl/@vpidir1@
vpidir = @libdir@/ivl
CC = @CC@
INSTALL = @INSTALL@
@@ -48,14 +45,6 @@ SHARED = @shared@
all:
ifeq (@enable_vvp32@,yes)
vpidir32 = $(libdir)/ivl/@vpidir2@
ALL32 = all32
INSTALL32 = install32
UNINSTALL32 = uninstall32
include $(srcdir)/enable_vvp32.mk
endif
all: dep cadpli.vpl $(ALL32)
# No specific check operations.
@@ -71,7 +60,7 @@ dep:
O = cadpli.o
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@MING32@,yes)
ifeq (@MINGW32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
@@ -97,8 +86,4 @@ uninstall: $(UNINSTALL32)
uninstall32:
ifeq (@enable_vvp32@,yes)
include $(srcdir)/enable_vvp32.mk
endif
-include $(patsubst %.o, dep/%.d, $O)
-15
View File
@@ -12,10 +12,6 @@ AX_WIN32
AC_PROG_INSTALL
# vvp32 is by default disabled
#enable_vvp32=no
AC_SUBST(enable_vvp32)
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_SIZEOF(unsigned long long)
@@ -62,15 +58,4 @@ AX_C_UNDERSCORES_TRAILING
AX_CPP_IDENT
# where to put vpi subdirectories
AC_MSG_CHECKING(for VPI subdirectories)
if test x${vpidir1} = x
then
vpidir1="."
fi
AC_SUBST(vpidir1)
AC_SUBST(vpidir2)
AC_MSG_RESULT(${vpidir1} ${vpidir2})
AC_OUTPUT(Makefile)
-39
View File
@@ -1,39 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: enable_vvp32.mk,v 1.1 2003/10/09 01:07:20 steve Exp $"
#
all32: bin32 bin32/cadpli.vpl
bin32:
mkdir bin32
bin32/%.o: %.c
$(CC) -m32 -Wall -I$(srcdir) -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $@
bin32/cadpli.vpl: $(addprefix bin32/,$O) ../vvp/bin32/libvpi.a ../libveriuser/bin32/libveriuser.o
$(CC) $(SHARED) -m32 -o $@ $(addprefix bin32/,$O) ../libveriuser/bin32/libveriuser.o ../vvp/bin32/libvpi.a
install32: all32 $(vpidir32)/cadpli.vpl
$(vpidir32)/cadpli.vpl: bin32/cadpli.vpl
$(INSTALL_PROGRAM) bin32/cadpli.vpl $(vpidir32)/cadpli.vpl
uninstall32:
rm -f $(vpidir32)/cadpli.vpl
+25 -5
View File
@@ -1,7 +1,7 @@
#ifndef __compiler_H
#define __compiler_H
/*
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
* Copyright (c) 1999-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -76,6 +76,9 @@ extern bool warn_timescale;
/* Warn about legal but questionable module port bindings. */
extern bool warn_portbinding;
/* Warn about structures that may have infinite loops. */
extern bool warn_inf_loop;
/* This is true if verbose output is requested. */
extern bool verbose_flag;
@@ -83,6 +86,7 @@ extern bool debug_scopes;
extern bool debug_eval_tree;
extern bool debug_elaborate;
extern bool debug_synth2;
extern bool debug_optimizer;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
@@ -97,26 +101,42 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
enum generation_t {
GN_VER1995 = 1,
GN_VER2001 = 2,
GN_VER2001X = 3,
GN_VER2005 = 3,
GN_DEFAULT = 3
};
extern generation_t generation_flag;
/* If this flag is true, enable extended types support. */
extern bool gn_cadence_types_flag;
/* These functions test that specific features are enabled. */
inline bool gn_cadence_types_enabled()
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
/* If this flag is true, enable miscellaneous extensions. */
extern bool gn_icarus_misc_flag;
/* If this flag is true, then elaborate specify blocks. If this flag
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* If this flag is true, then support/elaborate Verilog-AMS. */
extern bool gn_verilog_ams_flag;
/* If this flag is false a warning is printed when the port declaration
is scalar and the net/register definition is vectored. */
extern bool gn_io_range_error_flag;
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
sets of keywords. The compiler enables groups of keywords by setting
lexor_keyword_mask with the OR of the bits for the keywords to be
enabled. */
enum { GN_KEYWORDS_1364_1995 = 0x0001,
GN_KEYWORDS_1364_2001 = 0x0002,
GN_KEYWORDS_1364_2001_CONFIG = 0x0004,
GN_KEYWORDS_1364_2005 = 0x0008,
GN_KEYWORDS_VAMS_2_3 = 0x0010,
GN_KEYWORDS_ICARUS = 0x8000
};
extern int lexor_keyword_mask;
/* This is the string to use to invoke the preprocessor. */
extern char*ivlpp_string;
+3 -26
View File
@@ -9,6 +9,9 @@ AC_PROG_CC
AC_PROG_CXX
AC_CHECK_TOOL(STRIP, strip, true)
AC_CHECK_PROGS(XGPERF,gperf,none)
AC_CHECK_PROGS(MAN,man,none)
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
AC_CHECK_PROGS(GIT,git,none)
if test "$XGPERF" = "none"
then
echo ""
@@ -42,11 +45,6 @@ AC_SUBST(EXEEXT)
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
# vvp32 is by default disabled
#enable_vvp32=no
AC_SUBST(enable_vvp32)
AC_LANG_CPLUSPLUS
AC_CHECK_HEADERS(getopt.h malloc.h inttypes.h libiberty.h iosfwd sys/wait.h)
@@ -123,27 +121,6 @@ AX_C_UNDERSCORES_TRAILING
AX_CPP_IDENT
# If not otherwise specified, set the libdir64 variable
# to the same as libdir.
AC_MSG_CHECKING(for libdir64 path)
if test x${libdir64} = x
then
libdir64="${libdir}"
fi
AC_SUBST(libdir64)
AC_MSG_RESULT(${libdir64})
# where to put vpi subdirectories
AC_MSG_CHECKING(for VPI subdirectories)
if test x${vpidir1} = x
then
vpidir1="."
fi
AC_SUBST(vpidir1)
AC_SUBST(vpidir2)
AC_MSG_RESULT(${vpidir1} ${vpidir2})
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
+43
View File
@@ -0,0 +1,43 @@
// Mathematical and physical constants
`ifdef CONSTANTS_VAMS
`else
`define CONSTANTS_VAMS 1
// M_ is a mathematical constant
`define M_E 2.7182818284590452354
`define M_LOG2E 1.4426950408889634074
`define M_LOG10E 0.43429448190325182765
`define M_LN2 0.69314718055994530942
`define M_LN10 2.30258509299404568402
`define M_PI 3.14159265358979323846
`define M_TWO_PI 6.28318530717958647693
`define M_PI_2 1.57079632679489661923
`define M_PI_4 0.78539816339744830962
`define M_1_PI 0.31830988618379067154
`define M_2_PI 0.63661977236758134308
`define M_2_SQRTPI 1.12837916709551257390
`define M_SQRT2 1.41421356237309504880
`define M_SQRT1_2 0.70710678118654752440
/*
* Do we need these? For now they are not available.
*
// The following constants have been taken from http://physics.nist.gov
// P_ is a physical constant
// charge of electron in coulombs
`define P_Q 1.602176462e-19
// speed of light in vacuum in meters/sec
`define P_C 2.99792458e8
// Boltzmann's constant in joules/kelvin
`define P_K 1.3806503e-23
// Planck's constant in joules*sec
`define P_H 6.62606876e-34
// permittivity of vacuum in farads/meter
`define P_EPS0 8.854187817e-12
// permeability of vacuum in henrys/meter
`define P_U0 (4.0e-7 * `M_PI)
// zero celsius in kelvin
`define P_CELSIUS0 273.15
*/
`endif
+27
View File
@@ -23,6 +23,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
@@ -828,6 +829,32 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
count += 1;
return;
}
/* If the select input is constant, then replace with a BUFZ */
flag = obj->pin_Sel().nexus()->drivers_constant();
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
tmp->set_line(*obj);
if (debug_optimizer)
cerr << obj->get_fileline() << ": debug: "
<< "Replace binary MUX with constant select=" << sel_val
<< " with a BUFZ to the selected input." << endl;
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
connect(tmp->pin(0), obj->pin_Result());
if (sel_val == verinum::V1)
connect(tmp->pin(1), obj->pin_Data(1));
else
connect(tmp->pin(1), obj->pin_Data(0));
delete obj;
des->add_node(tmp);
count += 1;
}
}
/*
+194 -26
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.176 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -91,6 +88,34 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
return o;
}
ostream& operator << (ostream&o, ivl_switch_type_t val)
{
switch (val) {
case IVL_SW_TRAN:
o << "tran";
break;
case IVL_SW_TRANIF0:
o << "tranif0";
break;
case IVL_SW_TRANIF1:
o << "tranif1";
break;
case IVL_SW_RTRAN:
o << "rtran";
break;
case IVL_SW_RTRANIF0:
o << "rtranif0";
break;
case IVL_SW_RTRANIF1:
o << "rtranif1";
break;
case IVL_SW_TRAN_VP:
o << "tran(VP)";
break;
}
return o;
}
static inline void dump_scope_path(ostream&o, const NetScope*scope)
{
if (const NetScope*parent = scope->parent()) {
@@ -115,6 +140,10 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
o << setw(ind) << "" << "specify delay";
if (posedge_) o << " posedge";
if (negedge_) o << " negedge";
if (is_condit()) {
if (has_condit()) o << " if";
else o << " ifnone";
}
o << " src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
@@ -246,6 +275,15 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
}
}
void NetAbs::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Absolute value (NetAbs): " << name()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetAddSub::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
@@ -282,8 +320,13 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
void NetConcat::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetConcat: "
<< name()
<< " scope=" << scope_path(scope())
<< name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time() << "," << *decay_time() << ")";
else
o << " #(0,0,0)";
o << " scope=" << scope_path(scope())
<< " width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -303,6 +346,22 @@ void NetMult::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetPow::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_POW (NetPow): " << name()
<< " scope=" << scope_path(scope())
<< " delay=(";
if (rise_time())
o << *rise_time() << "," << *fall_time() << ","
<< *decay_time();
else
o << "0,0,0";
o << ")" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetMux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
@@ -336,7 +395,14 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "constant " << width_ << "'b";
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
o << value_[idx-1];
o << ": " << name() << endl;
o << ": " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
o << " #(.,.,.)";
o << endl;
dump_node_pins(o, ind+4);
}
@@ -353,7 +419,14 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
void NetLiteral::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant real " << real_
<< ": " << name() << endl;
<< ": " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
o << " #(.,.,.)";
o << endl;
dump_node_pins(o, ind+4);
}
@@ -448,12 +521,16 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
case PV:
pt = "PV";
break;
case BI:
pt = "BI";
break;
}
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
<< name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
o << " #(.,.,.)";
o << " off=" << off_ << " wid=" << wid_ <<endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -520,8 +597,12 @@ void NetSysFunc::dump_node(ostream&o, unsigned ind) const
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << scope_path(def_) << "(";
o << ")" << endl;
o << setw(ind) << "" << "USER FUNC: "
<< scope_path(def_);
if (rise_time())
o << " #(" <<*rise_time()
<<","<<*fall_time()
<< "," <<*decay_time() << ")" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -555,6 +636,20 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
o << setw(ind) << "" << "endtask" << endl;
}
void NetTran::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type_ << " " << name()
<< " island " << island;
if (type_ == IVL_SW_TRAN_VP) {
o << " width=" << vector_width()
<< " part=" << part_width()
<< " offset=" << part_offset();
}
o << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetUDP::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "UDP (" << udp_name() << "): ";
@@ -796,10 +891,36 @@ void NetForever::dump(ostream&o, unsigned ind) const
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function " << scope_path(scope_) << endl;
if (result_sig_)
o << setw(ind+2) << "" << "Return signal: "
<< result_sig_->name() << endl;
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
if (result_sig_) {
o << setw(ind+2) << "" << "Return signal: ";
if (result_sig_->get_signed()) o << "+";
o << result_sig_->name() << "[" << result_sig_->msb() << ":"
<< result_sig_->lsb() << "]" << endl;
}
o << setw(ind+2) << "" << "Arguments: ";
if (port_count() == 0) o << "<none>";
o << endl;
for (unsigned idx = 0; idx < port_count(); idx += 1) {
o << setw(ind+4) << "" << "Arg[" << idx+1 << "] = ";
switch (port(idx)->port_type()) {
default:
o << "implicit-port? ";
break;
case NetNet::PINPUT:
o << "input ";
break;
case NetNet::POUTPUT:
o << "output ";
break;
case NetNet::PINOUT:
o << "inout ";
break;
}
if (port(idx)->get_signed()) o << "+";
o << port(idx)->name() << "[" << port(idx)->msb() << ":"
<< port(idx)->lsb() << "]" << endl;
}
if (statement_)
statement_->dump(o, ind+2);
else
@@ -884,8 +1005,37 @@ void NetScope::dump(ostream&o) const
o << "[" << *(*pp).second.msb
<< ":" << *(*pp).second.lsb << "] ";
o << (*pp).first << " = " <<
*(*pp).second.expr << ";" << endl;
o << (*pp).first << " = " << *(*pp).second.expr;
for (range_t*ran = (*pp).second.range ; ran ; ran = ran->next) {
if (ran->exclude_flag)
o << " exclude ";
else
o << " from ";
if (ran->low_open_flag)
o << "(";
else
o << "[";
if (ran->low_expr)
o << *ran->low_expr;
else if (ran->low_open_flag==false)
o << "-inf";
else
o << "<?>";
if (ran->high_expr)
o << ":" << *ran->high_expr;
else if (ran->high_open_flag==false)
o << ":inf";
else
o << ":<?>";
if (ran->high_open_flag)
o << ")";
else
o << "]";
}
o << ";" << endl;
}
for (pp = localparams.begin()
@@ -950,7 +1100,10 @@ void NetScope::dump(ostream&o) const
o << " MISSING FUNCTION DEFINITION" << endl;
break;
case TASK:
task_def()->dump(o, 4);
if (task_def())
task_def()->dump(o, 4);
else
o << " MISSING TASK DEFINITION" << endl;
break;
default:
break;
@@ -1006,6 +1159,20 @@ void NetExpr::dump(ostream&o) const
void NetEBinary::dump(ostream&o) const
{
if (op_ == 'm' || op_ == 'M') {
if (op_ == 'm')
o << "min";
else
o << "max";
o << "(";
left_->dump(o);
o << ", ";
right_->dump(o);
o << ")";
return;
}
o << "(";
left_->dump(o);
o << ")";
@@ -1162,11 +1329,9 @@ void NetESignal::dump(ostream&o) const
void NetEParam::dump(ostream&o) const
{
if (scope_ != 0)
o << "<" << scope_path(scope_) << "." << name_ << ">";
else if (name_)
o << "<" << name_ << ">";
o << "<" << scope_path(scope_) << "." << (*reference_).first << ">";
else
o << "<" "???" ">";
o << "<" << (*reference_).first << ">";
}
void NetETernary::dump(ostream&o) const
@@ -1191,6 +1356,9 @@ void NetEUFunc::dump(ostream&o) const
void NetEUnary::dump(ostream&o) const
{
switch (op_) {
case 'm':
o << "abs";
break;
case 'N':
o << "~|";
break;
@@ -1217,6 +1385,7 @@ void Design::dump(ostream&o) const
if (nodes_) {
NetNode*cur = nodes_->node_next_;
do {
assert(cur);
cur->dump_node(o, 0);
cur = cur->node_next_;
} while (cur != nodes_->node_next_);
@@ -1229,4 +1398,3 @@ void Design::dump(ostream&o) const
idx->dump(o, 0);
}
+16 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,29 +16,24 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: priv.c,v 1.2 2003/10/06 21:26:27 steve Exp $"
#endif
# include "sys_priv.h"
# include "discipline.h"
PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time)
nature_t::nature_t(perm_string name, perm_string access)
: name_(name), access_(access)
{
PLI_UINT64 tmp;
tmp = time->high;
tmp <<= 32;
tmp |= (PLI_UINT64) time->low;
return tmp;
}
/*
* $Log: priv.c,v $
* Revision 1.2 2003/10/06 21:26:27 steve
* Include sys_priv.h instead of priv.h
*
* Revision 1.1 2003/10/02 21:16:11 steve
* Include timerec_to_time64 implementation.
*
*/
nature_t::~nature_t()
{
}
discipline_t::discipline_t(perm_string name, ddomain_t domain,
nature_t*pot, nature_t*flow)
: name_(name), domain_(domain), potential_(pot), flow_(flow)
{
}
discipline_t::~discipline_t()
{
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef __discipline_H
#define __discipline_H
/*
* Copyright (c) 2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* The discipline types include the discipline, nature and other
* related types for managing declared and used disciplines in a
* Verilog-AMS program.
*/
# include "StringHeap.h"
# include <iostream>
# include <map>
# include "LineInfo.h"
typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t;
extern std::ostream& operator << (std::ostream&, ddomain_t);
class nature_t : public LineInfo {
public:
explicit nature_t(perm_string name, perm_string access);
~nature_t();
perm_string name() const { return name_; }
// Identifier for the access function for this nature
perm_string access() const { return access_; }
private:
perm_string name_;
perm_string access_;
};
class discipline_t : public LineInfo {
public:
explicit discipline_t (perm_string name, ddomain_t dom,
nature_t*pot, nature_t*flow);
~discipline_t();
perm_string name() const { return name_; }
ddomain_t domain() const { return domain_; }
const nature_t*potential() const { return potential_; }
const nature_t*flow() const { return flow_; }
private:
perm_string name_;
ddomain_t domain_;
nature_t*potential_;
nature_t*flow_;
private: // not implemented
discipline_t(const discipline_t&);
discipline_t& operator = (const discipline_t&);
};
extern map<perm_string,nature_t*> natures;
extern map<perm_string,discipline_t*> disciplines;
#endif
+72
View File
@@ -0,0 +1,72 @@
// Standard definitions for Verilog-AMS
`ifdef DISCIPLINES_VAMS
`else
`define DISCIPLINES_VAMS 1
discipline \logic ;
domain discrete;
enddiscipline
discipline ddiscrete;
domain discrete;
enddiscipline
nature Current;
units = "A";
access = I;
idt_nature = Charge;
`ifdef CURRENT_ABSTOL
abstol = `CURRENT_ABSTOL
`else
abstol = 1e-12;
`endif
endnature
nature Charge;
units = "coul";
access = Q;
ddt_nature = Current;
`ifdef CHARGE_ABSTOL
abstol = `CHARGE_ABSTOL;
`else
abstol = 1e-14;
`endif
endnature
nature Voltage;
units = "V";
access = V;
idt_nature = Flux;
`ifdef VOLTAGE_ABSTOL
abstol = `VOLTAGE_ABSTOL;
`else
abstol = 1e-6;
`endif
endnature
nature Flux;
units = "Wb";
access = Phi;
ddt_nature = Voltage;
`ifdef FLUX_ABSTOL
abstol = `flux_ABSTOL;
`else
abstol = 1e-9;
`endif
endnature
discipline electrical;
potential Voltage;
flow Current;
enddiscipline
discipline voltage;
potential Voltage;
enddiscipline
discipline current;
flow Current;
enddiscipline
`endif // !`ifdef DISCIPLINES_VAMS
+4 -4
View File
@@ -16,16 +16,14 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.8.3
VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
VPATH = $(srcdir)
@@ -47,6 +45,8 @@ LDFLAGS = @LDFLAGS@
all: iverilog-vpi@EXEEXT@
check: all
clean:
rm -f *.o config.h
rm -f iverilog-vpi@EXEEXT@
+19 -12
View File
@@ -33,6 +33,7 @@
#include <windows.h>
static void setup_ivl_environment();
static void assign(char **ptr, char *str);
/* The compile options: compiler, flags, etc. are in here */
#include "config.h"
@@ -77,6 +78,7 @@ static void myExit(int exitVal)
deInitDynString(gstr.pCFLAGS);
deInitDynString(gstr.pLDLIBS);
deInitDynString(gstr.pNewPath);
free(gstr.pLD);
exit(exitVal);
}
@@ -120,7 +122,7 @@ static void init()
initDynString(&gstr.pLDLIBS);
initDynString(&gstr.pNewPath);
/* By default use the C compiler to link the programs. */
gstr.pLD = IVERILOG_VPI_CC;
assign(&gstr.pLD, IVERILOG_VPI_CC);
}
/* return true if "str" is terminated with with "end", case insensitive */
@@ -306,7 +308,7 @@ static int parse(int argc, char *argv[])
/* Check for C++ source files (*.cc) */
else if (endsIn(dot_cc_ext, argv[idx])) {
/* We need to link with the C++ compiler. */
gstr.pLD = IVERILOG_VPI_CXX;
assign(&gstr.pLD, IVERILOG_VPI_CXX);
++srcFileCnt;
append(&gstr.pCXSRC, argv[idx]);
append(&gstr.pCXSRC, " ");
@@ -317,7 +319,7 @@ static int parse(int argc, char *argv[])
/* Check for C++ source files (*.cpp) */
else if (endsIn(dot_cpp_ext, argv[idx])) {
/* We need to link with the C++ compiler. */
gstr.pLD = IVERILOG_VPI_CXX;
assign(&gstr.pLD, IVERILOG_VPI_CXX);
++srcFileCnt;
append(&gstr.pCXSRC, argv[idx]);
append(&gstr.pCXSRC, " ");
@@ -334,6 +336,14 @@ static int parse(int argc, char *argv[])
assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_o_ext));
}
/* Check for the -mingw option */
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,
@@ -354,14 +364,6 @@ static int parse(int argc, char *argv[])
append(&gstr.pDEFS, " ");
append(&gstr.pDEFS, argv[idx]);
}
/* Check for the -mingw option */
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 --cflags option */
else if (stricmp("--cflags", argv[idx]) == 0) {
setup_ivl_environment();
@@ -482,6 +484,7 @@ static void setup_mingw_environment()
assign(&gstr.pNewPath,"PATH=");
append(&gstr.pNewPath,gstr.pMINGW);
appendBackSlash(&gstr.pNewPath);
append(&gstr.pNewPath, "\\");
append(&gstr.pNewPath,"bin;");
append(&gstr.pNewPath,pOldPATH);
@@ -512,12 +515,14 @@ static void setup_ivl_environment()
append(&gstr.pCFLAGS," -I");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS, "\\");
append(&gstr.pCFLAGS,"include");
/* Build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L");
append(&gstr.pLDLIBS,gstr.pIVL);
appendBackSlash(&gstr.pLDLIBS);
append(&gstr.pLDLIBS, "\\");
append(&gstr.pLDLIBS,"lib ");
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
}
@@ -537,7 +542,9 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
assignn(&src, ptr1, len);
/* Build the object file name */
ostart = strrchr(ptr1, '/') + 1;
ostart = strrchr(ptr1, '/');
if (ostart == NULL) ostart = ptr1;
else ostart += 1;
olen = strrchr(ptr1, '.') - ostart;
assignn(&obj, ostart, olen);
append(&obj, ".o");
+17 -9
View File
@@ -16,16 +16,14 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.8
VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
VPATH = $(srcdir)
@@ -40,6 +38,8 @@ CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
MAN = @MAN@
PS2PDF = @PS2PDF@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
@@ -67,7 +67,7 @@ cfparse.h cfparse.c: cfparse.y
bison --verbose -t -d -o cfparse.c --name-prefix=cf $(srcdir)/cfparse.y
main.o: main.c globals.h
main.o: main.c globals.h ../version.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
build_string.o: build_string.c globals.h
@@ -75,15 +75,23 @@ cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
cfparse.o: cfparse.c globals.h cfparse_misc.h
iverilog.ps: $(srcdir)/iverilog.man
man -t $(srcdir)/iverilog.man > iverilog.ps
$(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
iverilog.pdf: iverilog.ps
ps2pdf iverilog.ps iverilog.pdf
$(PS2PDF) iverilog.ps iverilog.pdf
ifeq (@MING32@,yes)
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog.1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog.1
else
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
INSTALL_DOCDIR = $(mandir)/man1
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog.1
INSTALL_DOCDIR = $(mandir)/man1
-3
View File
@@ -19,9 +19,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cfparse_misc.h,v 1.6 2004/02/15 18:03:30 steve Exp $"
#endif
/*
* The vlltype supports the passing of detailed source file location
+2 -2
View File
@@ -31,10 +31,10 @@ extern const char*base;
extern char* iconfig_path;
extern char* iconfig_common_path;
/* Ths is the optional -M<dependfile> value, if one was supplied. */
/* This is the optional -M<dependfile> value, if one was supplied. */
extern const char*depfile;
/* Ths is the optional -N<path> value, if one was supplied. */
/* This is the optional -N<path> value, if one was supplied. */
extern const char*npath;
/* This is the name of the output file that the user selected. */
+40 -8
View File
@@ -1,11 +1,11 @@
.TH iverilog 1 "$Date: 2007/06/05 01:56:12 $" Version "$Date: 2007/06/05 01:56:12 $"
.TH iverilog 1 "April 22nd, 2008" Version "0.9.devel"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value]
[-g1|-g2|-g2x|-gspecify|-gxtypes|-gio-range-error]
[-dname] [-g1995|-g2001|-g2005|-g<feature>]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
@@ -43,21 +43,30 @@ Verilog source.
.B -D\fImacro=defn\fP
Defines macro \fImacro\fP as \fIdefn\fP.
.TP 8
.B -d\fIname\fP
Activate a class of compiler debugging messages. The \fB-d\fP switch may
be used as often as necessary to activate all the desired messages.
Supported names are scopes, eval_tree, elaborate, and synth2;
any other names are ignored.
.TP 8
.B -E
Preprocess the Verilog source, but do not compile it. The output file
is the Verilog input, but with file inclusions and macro references
expanded and removed. This is useful, for example, to preprocess
Verilog source for use by other compilers.
.TP 8
.B -g1\fI|\fP-g2\fI|\fP-g2x
.B -g1995\fI|\fP-g2001\fI|\fP-g2005
Select the Verilog language \fIgeneration\fP to support in the
compiler. This selects between \fIIEEE1364-1995\fP(1),
\fIIEEE1364-2001\fP(2), or \fIVerilog with extension\fP(2x). Normally,
compiler. This selects between \fIIEEE1364-1995\fP,
\fIIEEE1364-2001\fP(2), or \fIIEEE1364-2005\fP. Normally,
Icarus Verilog defaults to the latest known generation of the
language. This flag is most useful to restrict the language to a set
supported by tools of specific generations, for compatibility with
other tools.
.TP 8
.B -gverilog-ams\fI|-fP-gno-verilog-ams
Enable or disable (default) support for Verilog-AMS.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable (default) or disable specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
@@ -245,6 +254,21 @@ inherit timescale from another file. Both probably mean that
timescales are inconsistent, and simulation timing can be confusing
and dependent on compilation order.
.TP 8
.B infloop
This enables warnings for \fRalways\fP statements that may have runtime
infinite loops (has paths with no or zero delay). This class of warnings
is not included in \fB-Wall\fP and hence does not have a \fBno-\fP variant.
A fatal error message will always be printed when the compiler can
determine that there will definitely be an infinite loop (all paths have
no or zero delay).
When you suspect an always statement is producing a runtime infinite loop
use this flag to find the always statements that need to have their logic
verified. It is expected that many of the warnings will be false
positives, since the code treats the value of all variables and signals
as indeterminate.
.SH "SYSTEM FUNCTION TABLE FILES"
If the source file name as a \fB.sft\fP suffix, then it is taken to be
a system function table file. A System function table file is used to
@@ -360,12 +384,17 @@ and directory strings.
Variable values come from the operating system environment, and not
from preprocessor defines elsewhere in the file or the command line.
.SH PREDEFINED MACROS
The following macro is predefined by the compiler:
The following macros are predefined by the compiler:
.TP 8
.B __ICARUS__ = 1\fP
This is defined always when compiling with Icarus Verilog.
.TP 8
.B __VAMS_ENABLE__ = 1\fp
This is defined if Verilog-AMS is enabled.
.SH EXAMPLES
These examples assume that you have a Verilog source file called hello.v in
@@ -396,9 +425,12 @@ Steve Williams ([email protected])
vvp(1),
.BR "<http://www.icarus.com/eda/verilog/>"
Tips on using, debugging, and developing the compiler can be found at
.BR "<http://iverilog.wikia.com/>"
.SH COPYRIGHT
.nf
Copyright \(co 2002 Stephen Williams
Copyright \(co 2002-2008 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+84 -27
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2007 Stephen Williams ([email protected])
* Copyright (c) 2000-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,6 +18,7 @@
*/
# include "config.h"
# include "version.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@@ -108,7 +109,9 @@ const char*depfile = 0;
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
const char*gen_icarus = "icarus-misc";
const char*gen_io_range_error = "io-range-error";
const char*gen_verilog_ams = "no-verilog-ams";
/* Boolean: true means use a default include dir, false means don't */
int gen_std_include = 1;
@@ -156,7 +159,7 @@ typedef struct t_command_file {
p_command_file cmd_file_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
/* Function to add a comamnd file name to the FIFO. */
/* Function to add a command file name to the FIFO. */
void add_cmd_file(const char* filename)
{
p_command_file new;
@@ -173,7 +176,7 @@ void add_cmd_file(const char* filename)
}
}
/* Function to return the top comamnd file name from the FIFO. */
/* Function to return the top command file name from the FIFO. */
char *get_cmd_file()
{
char *filename;
@@ -202,7 +205,7 @@ static FILE*fopen_safe(const char*path)
if (fd != -1)
file = _fdopen(fd, "w");
return file;
return file;
}
#else
# include <fcntl.h>
@@ -215,7 +218,7 @@ static FILE*fopen_safe(const char*path)
if (fd != -1)
file = fdopen(fd, "w");
return file;
return file;
}
#endif
@@ -324,6 +327,9 @@ static int t_default(char*cmd, unsigned ncmd)
remove(defines_path);
remove(compiled_defines_path);
}
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
return rc;
#else
if (rc != 0) {
if (rc == 127) {
@@ -339,6 +345,7 @@ static int t_default(char*cmd, unsigned ncmd)
}
return 0;
#endif
}
@@ -357,6 +364,11 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"timescale") == 0) {
if (! strchr(warning_flags, 't'))
strcat(warning_flags, "t");
/* Since the infinite loop check is not part of 'all' it
* does not have a no- version. */
} else if (strcmp(name,"infloop") == 0) {
if (! strchr(warning_flags, 'l'))
strcat(warning_flags, "l");
} else if (strcmp(name,"no-implicit") == 0) {
char*cp = strchr(warning_flags, 'i');
if (cp) while (*cp) {
@@ -424,50 +436,79 @@ void process_file_name(const char*name, int lib_flag)
int process_generation(const char*name)
{
if (strcmp(name,"1") == 0)
generation = "1";
if (strcmp(name,"1995") == 0)
generation = "1995";
else if (strcmp(name,"2") == 0)
generation = "2";
else if (strcmp(name,"2001") == 0)
generation = "2001";
else if (strcmp(name,"2x") == 0)
generation = "2x";
else if (strcmp(name,"2005") == 0)
generation = "2005";
else if (strcmp(name,"xtypes") == 0)
else if (strcmp(name,"1") == 0) { /* Deprecated: use 1995 */
generation = "1995";
gen_xtypes = "no-xtypes";
gen_icarus = "no-icarus-misc";
} else if (strcmp(name,"2") == 0) { /* Deprecated: use 2001 */
generation = "2001";
gen_xtypes = "no-xtypes";
gen_icarus = "no-icarus-misc";
} else if (strcmp(name,"2x") == 0) { /* Deprecated: use 2005/xtypes */
generation = "2005";
gen_xtypes = "xtypes";
gen_icarus = "icarus-misc";
} else if (strcmp(name,"xtypes") == 0)
gen_xtypes = "xtypes";
else if (strcmp(name,"no-xtypes") == 0)
else if (strcmp(name,"no-xtypes") == 0)
gen_xtypes = "no-xtypes";
else if (strcmp(name,"specify") == 0)
else if (strcmp(name,"icarus-misc") == 0)
gen_icarus = "icarus-misc";
else if (strcmp(name,"no-icarus-misc") == 0)
gen_icarus = "no-icarus-misc";
else if (strcmp(name,"specify") == 0)
gen_specify = "specify";
else if (strcmp(name,"no-specify") == 0)
else if (strcmp(name,"no-specify") == 0)
gen_specify = "no-specify";
else if (strcmp(name,"std-include") == 0)
else if (strcmp(name,"std-include") == 0)
gen_std_include = 1;
else if (strcmp(name,"no-std-include") == 0)
else if (strcmp(name,"no-std-include") == 0)
gen_std_include = 0;
else if (strcmp(name,"io-range-error") == 0)
else if (strcmp(name,"io-range-error") == 0)
gen_io_range_error = "io-range-error";
else if (strcmp(name,"no-io-range-error") == 0)
else if (strcmp(name,"no-io-range-error") == 0)
gen_io_range_error = "no-io-range-error";
else if (strcmp(name,"verilog-ams") == 0)
gen_verilog_ams = "verilog-ams";
else if (strcmp(name,"no-verilog-ams") == 0)
gen_verilog_ams = "no-verilog-ams";
else {
fprintf(stderr, "Unknown/Unsupported Language generation "
"%s\n\n", name);
fprintf(stderr, "Supported generations are:\n");
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
" 2x -- Verilog with extensions\n"
fprintf(stderr, " 1995 -- IEEE1364-1995\n"
" 2001 -- IEEE1364-2001\n"
" 2005 -- IEEE1364-2005\n"
"Other generation flags:\n"
" specify | no-specify\n"
" verilog-ams | no-verinlog-ams\n"
" std-include | no-std-include\n"
" xtypes | no-xtypes\n"
" icarus-misc | no-icarus-misc\n"
" io-range-error | no-io-range-error\n");
return 1;
}
@@ -557,6 +598,8 @@ int main(int argc, char **argv)
}
fprintf(defines_file, "D:__ICARUS__=1\n");
if (strcmp(gen_verilog_ams,"verilog-ams") == 0)
fprintf(defines_file, "D:__VAMS_ENABLE__=1\n");
/* Create another temporary file for passing configuration
information to ivl. */
@@ -593,7 +636,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt(argc, argv, "B:c:D:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@@ -620,6 +663,9 @@ int main(int argc, char **argv)
case 'p':
fprintf(iconfig_file, "flag:%s\n", optarg);
break;
case 'd':
fprintf(iconfig_file, "debug:%s\n", optarg);
break;
case 'g':
rc = process_generation(optarg);
@@ -698,8 +744,8 @@ int main(int argc, char **argv)
pbase = base;
if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " ($Name: $)\n\n");
printf("Copyright 1998-2007 Stephen Williams\n");
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2008 Stephen Williams\n");
puts(NOTICE);
if (version_flag)
@@ -718,11 +764,20 @@ int main(int argc, char **argv)
how to handle them. */
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
/* If verilog-ams is enabled, then include the va_math module
as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0) {
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
fprintf(iconfig_file, "module:va_math\n");
}
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
fprintf(iconfig_file, "generation:%s\n", generation);
fprintf(iconfig_file, "generation:%s\n", gen_specify);
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
@@ -803,8 +858,11 @@ int main(int argc, char **argv)
rc = system(cmd);
remove(source_path);
fclose(iconfig_file);
if ( ! getenv("IVERILOG_ICONFIG"))
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
remove(defines_path);
remove(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
@@ -834,4 +892,3 @@ int main(int argc, char **argv)
return 0;
}
+24 -86
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
#endif
# include "config.h"
@@ -27,14 +24,17 @@
NetEBComp* NetEBComp::dup_expr() const
{
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
right_->dup_expr());
return result;
NetEBComp*tmp = new NetEBComp(op_, left_->dup_expr(),
right_->dup_expr());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
NetEConst* NetEConst::dup_expr() const
{
NetEConst*tmp = new NetEConst(value_);
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -42,6 +42,7 @@ NetEConst* NetEConst::dup_expr() const
NetEConstParam* NetEConstParam::dup_expr() const
{
NetEConstParam*tmp = new NetEConstParam(scope_, name_, value());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -49,6 +50,7 @@ NetEConstParam* NetEConstParam::dup_expr() const
NetECRealParam* NetECRealParam::dup_expr() const
{
NetECRealParam*tmp = new NetECRealParam(scope_, name_, value());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -67,9 +69,12 @@ NetEScope* NetEScope::dup_expr() const
NetESelect* NetESelect::dup_expr() const
{
return new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
expr_width());
NetESelect*tmp = new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
expr_width());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
NetESFunc* NetESFunc::dup_expr() const
@@ -83,14 +88,16 @@ NetESFunc* NetESFunc::dup_expr() const
tmp->parm(idx, tmp->parm(idx)->dup_expr());
}
tmp->set_line(*this);
return tmp;
}
NetESignal* NetESignal::dup_expr() const
{
NetESignal*tmp = new NetESignal(net_);
NetESignal*tmp = new NetESignal(net_, word_);
assert(tmp);
tmp->expr_width(expr_width());
tmp->set_line(*this);
return tmp;
}
@@ -99,6 +106,8 @@ NetETernary* NetETernary::dup_expr() const
NetETernary*tmp = new NetETernary(cond_->dup_expr(),
true_val_->dup_expr(),
false_val_->dup_expr());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -112,9 +121,10 @@ NetEUFunc* NetEUFunc::dup_expr() const
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms);
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -122,6 +132,7 @@ NetEUnary* NetEUnary::dup_expr() const
{
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -129,79 +140,6 @@ NetEUReduce* NetEUReduce::dup_expr() const
{
NetEUReduce*tmp = new NetEUReduce(op_, expr_->dup_expr());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
/*
* $Log: dup_expr.cc,v $
* Revision 1.21 2006/11/04 06:10:13 steve
* Handle dup of pad as well as normal select.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/06/17 16:06:18 steve
* Help system function signedness survive elaboration.
*
* Revision 1.17 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
* speed and more type support.
*
* Revision 1.16 2003/10/31 02:47:11 steve
* NetEUReduce has its own dup_expr method.
*
* Revision 1.15 2003/05/30 02:55:32 steve
* Support parameters in real expressions and
* as real expressions, and fix multiply and
* divide with real results.
*
* Revision 1.14 2003/04/22 04:48:29 steve
* Support event names as expressions elements.
*
* Revision 1.13 2003/03/15 18:08:43 steve
* Comparison operators do have defined width.
*
* Revision 1.12 2003/03/15 04:46:28 steve
* Better organize the NetESFunc return type guesses.
*
* Revision 1.11 2003/03/10 23:40:53 steve
* Keep parameter constants for the ivl_target API.
*
* Revision 1.10 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.9 2002/11/09 00:25:27 steve
* Add dup_expr for user defined function calls.
*
* Revision 1.8 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.7 2002/01/28 00:52:41 steve
* Add support for bit select of parameters.
* This leads to a NetESelect node and the
* vvp code generator to support that.
*
* Revision 1.6 2001/11/19 01:54:14 steve
* Port close cropping behavior from mcrgb
* Move window array reset to libmc.
*
* Revision 1.5 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2000/05/07 18:20:07 steve
* Import MCD support from Stephen Tell, and add
* system function parameter support to the IVL core.
*
* Revision 1.3 2000/05/04 03:37:58 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*/
+434 -175
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -30,7 +30,7 @@
# include "ivl_assert.h"
/*
* The default behavor for the test_width method is to just return the
* The default behavior for the test_width method is to just return the
* minimum width that is passed in.
*/
unsigned PExpr::test_width(Design*des, NetScope*scope,
@@ -96,7 +96,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
* and right sides, and creating one of a variety of different NetExpr
* types.
*/
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool) const
{
assert(left_);
@@ -110,11 +110,11 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
NetEBinary*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
NetExpr*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
return tmp;
}
void PEBinary::surpress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp)
void PEBinary::suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp)
{
// If either operand is unsigned, then treat the whole
// expression as unsigned. This test needs to be done here
@@ -128,26 +128,15 @@ void PEBinary::surpress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp)
lp->cast_signed(false);
}
NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
NetExpr* PEBinary::elaborate_eval_expr_base_(Design*des,
NetExpr*lp,
NetExpr*rp,
int expr_wid) const
{
/* If either expression can be evaluated ahead of time, then
do so. This can prove helpful later. */
{ NetExpr*tmp;
tmp = lp->eval_tree();
if (tmp) {
delete lp;
lp = tmp;
}
tmp = rp->eval_tree();
if (tmp) {
delete rp;
rp = tmp;
}
}
eval_expr(lp);
eval_expr(rp);
return elaborate_expr_base_(des, lp, rp, expr_wid);
}
@@ -157,7 +146,7 @@ NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
* operands are elaborated as necessary, and all I need to do is make
* 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,
int expr_wid) const
{
@@ -168,7 +157,7 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
<< *this << " expr_wid=" << expr_wid << endl;
}
NetEBinary*tmp;
NetExpr*tmp;
switch (op_) {
default:
@@ -178,6 +167,8 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case 'a':
case 'o':
lp = condition_reduce(lp);
rp = condition_reduce(rp);
tmp = new NetEBLogic(op_, lp, rp);
tmp->set_line(*this);
break;
@@ -195,11 +186,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case '%':
/* The % operator does not support real arguments in
baseline Verilog. But we allow it in our extended
form of verilog. */
if (generation_flag < GN_VER2001X) {
if (lp->expr_type()==IVL_VT_REAL || rp->expr_type()==IVL_VT_REAL) {
cerr << get_fileline() << ": error: Modulus operator may not "
"have REAL operands." << endl;
form of Verilog. */
if (! gn_icarus_misc_flag) {
if (lp->expr_type()==IVL_VT_REAL ||
rp->expr_type()==IVL_VT_REAL) {
cerr << get_fileline() << ": error: Modulus operator "
"may not have REAL operands." << endl;
des->errors += 1;
}
}
@@ -210,6 +202,56 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
break;
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, or
// there is a context determined size, use that.
if (lpval.has_len() || expr_wid > 0) {
int use_len = lpval.len();
if (expr_wid < use_len)
use_len = expr_wid;
result = verinum(result, lpval.len());
}
tmp = new NetEConst(result);
if (debug_elaborate)
cerr << get_fileline() << ": 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() < integer_width && !lpval.has_len()) {
lpval = verinum(lpval, integer_width);
lpc = new NetEConst(lpval);
lpc->set_line(*lp);
}
tmp = new NetEBShift(op_, lpc, rp);
if (debug_elaborate)
cerr << get_fileline() << ": 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': // >>>
tmp = new NetEBShift(op_, lp, rp);
@@ -237,10 +279,11 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case 'E': /* === */
case 'N': /* !== */
if (lp->expr_type() == IVL_VT_REAL
|| rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: Case equality may not "
<< "have real operands." << endl;
if (lp->expr_type() == IVL_VT_REAL ||
rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< "may not have real operands." << endl;
return 0;
}
/* Fall through... */
@@ -268,6 +311,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
des->errors += 1;
}
break;
case 'm': // min(l,r)
case 'M': // max(l,r)
tmp = new NetEBMinMax(op_, lp, rp);
tmp->set_line(*this);
break;
}
return tmp;
@@ -278,8 +327,8 @@ unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned, bool&) const
return 1;
}
NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const
NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const
{
assert(left_);
assert(right_);
@@ -313,7 +362,7 @@ NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
surpress_operand_sign_if_needed_(lp, rp);
suppress_operand_sign_if_needed_(lp, rp);
return elaborate_eval_expr_base_(des, lp, rp, use_wid);
}
@@ -531,12 +580,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
PExpr*expr = parms_[idx];
if (expr) {
NetExpr*tmp1 = expr->elaborate_expr(des, scope, -1, true);
if (NetExpr*tmp2 = tmp1->eval_tree()) {
delete tmp1;
fun->parm(idx, tmp2);
} else {
fun->parm(idx, tmp1);
}
eval_expr(tmp1);
fun->parm(idx, tmp1);
} else {
missing_parms += 1;
@@ -628,7 +673,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
if (NetNet*res = dscope->find_signal(dscope->basename())) {
NetESignal*eres = new NetESignal(res);
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms);
func->set_line(*this);
func->cast_signed(res->get_signed());
return func;
@@ -641,10 +686,13 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
// Keep track of the concatenation/repeat depth.
static int concat_depth = 0;
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool) const
{
concat_depth += 1;
NetExpr* repeat = 0;
if (debug_elaborate) {
@@ -668,6 +716,32 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1;
}
if (!rep->value().is_defined()) {
cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be undefined (" << rep->value()
<< ")." << endl;
des->errors += 1;
concat_depth -= 1;
return 0;
}
if (rep->value().is_negative()) {
cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be negative (" << rep->value().as_long()
<< ")." << endl;
des->errors += 1;
concat_depth -= 1;
return 0;
}
if (rep->value().is_zero() && concat_depth < 2) {
cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be zero in this context." << endl;
des->errors += 1;
concat_depth -= 1;
return 0;
}
repeat = rep;
}
@@ -705,6 +779,15 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
tmp->set_width(wid_sum * tmp->repeat());
if (wid_sum == 0 && concat_depth < 2) {
cerr << get_fileline() << ": error: Concatenation may not "
<< "have zero width in this context." << endl;
des->errors += 1;
concat_depth -= 1;
return 0;
}
concat_depth -= 1;
return tmp;
}
@@ -799,6 +882,51 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
return flag;
}
/*
* When we know that this is an indexed part select (up or down) this
* method calculates the up/down base, as far at it can be calculated.
*/
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.lsb != 0);
ivl_assert(*this, index_tail.msb != 0);
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1);
return tmp;
}
bool PEIdent::calculate_param_range_(Design*des, NetScope*scope,
const NetExpr*par_msb, long&par_msv,
const NetExpr*par_lsb, long&par_lsv) const
{
if (par_msb == 0) {
// If the parameter doesn't have an explicit range, then
// just return range values of 0:0. The par_msv==0 is
// correct. The par_msv is not necessarily correct, but
// clients of this function don't need a correct value.
ivl_assert(*this, par_lsb == 0);
par_msv = 0;
par_lsv = 0;
return true;
}
const NetEConst*tmp = dynamic_cast<const NetEConst*> (par_msb);
ivl_assert(*this, tmp);
par_msv = tmp->value().as_long();
tmp = dynamic_cast<const NetEConst*> (par_lsb);
ivl_assert(*this, tmp);
par_lsv = tmp->value().as_long();
return true;
}
unsigned PEIdent::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const
@@ -1011,6 +1139,131 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
static verinum param_part_select_bits(const verinum&par_val, long wid,
long lsv, long par_lsv)
{
verinum result (verinum::Vx, wid, true);
for (long idx = 0 ; idx < wid ; idx += 1) {
long off = idx + lsv - par_lsv;
if (off < 0)
result.set(idx, verinum::Vx);
else if (off < (long)par_val.len())
result.set(idx, par_val.get(off));
else if (par_val.is_string()) // Pad strings with nulls.
result.set(idx, verinum::V0);
else if (par_val.has_len()) // Pad sized parameters with X
result.set(idx, verinum::Vx);
else // Unsized parameters are "infinite" width.
result.set(idx, sign_bit(par_val));
}
// If the input is a string, and the part select is working on
// byte boundaries, then make the result into a string.
if (par_val.is_string() && (labs(lsv-par_lsv)%8 == 0) && (wid%8 == 0))
return result.as_string();
return result;
}
NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
{
long msv, lsv;
bool flag = calculate_parts_(des, scope, msv, lsv);
if (!flag)
return 0;
long par_msv, par_lsv;
flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
if (!flag)
return 0;
// Notice that the par_msv is not used is this function other
// then for this test. It is used to tell the direction that
// the bits are numbers, so that we can make sure the
// direction matches the part select direction. After that,
// we only need the par_lsv.
if (msv>lsv && par_msv<par_lsv || msv<lsv && par_msv>=par_lsv) {
cerr << get_fileline() << ": error: Part select "
<< "[" << msv << ":" << lsv << "] is out of order." << endl;
des->errors += 1;
return 0;
}
long wid = 1 + labs(msv-lsv);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Calculate part select "
<< "[" << msv << ":" << lsv << "] from range "
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
verinum result = param_part_select_bits(par_ex->value(), wid, lsv, par_lsv);
NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this);
return result_ex;
}
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
{
long par_msv, par_lsv;
bool flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
if (!flag)
return 0;
NetExpr*base = calculate_up_do_base_(des, scope);
if (base == 0)
return 0;
unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid);
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Calculate part select "
<< "[" << *base << "+:" << wid << "] from range "
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
// Handle the special case that the base is constant. In this
// case, just precalculate the entire constant result.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
long lsv = base_c->value().as_long();
// Watch out for reversed bit numbering. We're making
// the part select from LSB to MSB.
if (par_msv < par_lsv)
lsv = lsv - wid + 1;
verinum result = param_part_select_bits(par_ex->value(), wid,
lsv, par_lsv);
NetEConst*result_ex = new NetEConst(result);
result_ex->set_line(*this);
return result_ex;
}
if ((par_msb < par_lsb) && (wid>1))
base = make_add_expr(base, 1-(long)wid);
NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid);
tmp->set_line(*this);
return tmp;
}
/*
* Handle the case that the identifier is a parameter reference. The
* parameter expression has already been located for us (as the par
@@ -1023,84 +1276,29 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
{
NetExpr*tmp = par->dup_expr();
const name_component_t&name_tail = path_.back();
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
if (use_sel == index_component_t::SEL_PART) {
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb);
ivl_assert(*this, index_tail.lsb);
// NOTE TO SELF: This is the way I want to see this code
// structured. This closely follows the structure of the
// elaborate_expr_net_ code, which splits all the various
// selects to different methods.
if (use_sel == index_component_t::SEL_PART)
return elaborate_expr_param_part_(des, scope, par, found_in,
par_msb, par_lsb);
/* If the identifier has a part select, we support
it by pulling the right bits out and making a
sized unsigned constant. This code assumes the
lsb of a parameter is 0 and the msb is the
width of the parameter. */
if (use_sel == index_component_t::SEL_IDX_UP)
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
par_msb, par_lsb);
verinum*lsn = index_tail.lsb->eval_const(des, scope);
verinum*msn = index_tail.msb->eval_const(des, scope);
if ((lsn == 0) || (msn == 0)) {
cerr << get_fileline() << ": error: "
"Part select expressions must be "
"constant expressions." << endl;
des->errors += 1;
return 0;
}
// NOTE TO SELF (continued): The code below should be
// rewritten in the above format, as I get to it.
long lsb = lsn->as_long();
long msb = msn->as_long();
if ((lsb < 0) || (msb < lsb)) {
cerr << get_fileline() << ": error: invalid part "
<< "select: " << path_
<< "["<<msb<<":"<<lsb<<"]" << endl;
des->errors += 1;
return 0;
}
unsigned long ulsb=lsb;
unsigned long umsb=msb;
NetExpr*tmp = par->dup_expr();
NetEConst*le = dynamic_cast<NetEConst*>(tmp);
assert(le);
verinum result (verinum::V0, msb-lsb+1, true);
verinum exl = le->value();
/* Pull the bits from the parameter, one at a
time. If the bit is within the range, simply
copy it to the result. If the bit is outside
the range, we sign extend signed unsized
numbers, zero extend unsigned unsigned numbers,
and X extend sized numbers. */
for (unsigned long idx = ulsb ; idx <= umsb ; idx += 1) {
if (idx < exl.len())
result.set(idx-lsb, exl.get(idx));
else if (exl.is_string())
result.set(idx-lsb, verinum::V0);
else if (exl.has_len())
result.set(idx-lsb, verinum::Vx);
else if (exl.has_sign())
result.set(idx-lsb, exl.get(exl.len()-1));
else
result.set(idx-lsb, verinum::V0);
}
/* If the input is a string, and the part select
is working on byte boundaries, then the result
can be made into a string. */
if (exl.is_string()
&& (lsb%8 == 0)
&& (result.len()%8 == 0))
result = verinum(result.as_string());
delete tmp;
tmp = new NetEConst(result);
} else if (use_sel == index_component_t::SEL_IDX_UP || use_sel == index_component_t::SEL_IDX_DO) {
if (use_sel == index_component_t::SEL_IDX_DO) {
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
@@ -1141,17 +1339,18 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
ivl_assert(*this, index_tail.msb);
ivl_assert(*this, !index_tail.lsb);
const NetEConst*par_me =dynamic_cast<const NetEConst*>(par_msb);
const NetEConst*par_le =dynamic_cast<const NetEConst*>(par_lsb);
ivl_assert(*this, par_me || !par_msb);
ivl_assert(*this, par_le || !par_lsb);
ivl_assert(*this, par_me || !par_le);
/* Handle the case where a parameter has a bit
select attached to it. Generate a NetESelect
object to select the bit as desired. */
NetExpr*mtmp = index_tail.msb->elaborate_expr(des, scope, -1,false);
if (! dynamic_cast<NetEConst*>(mtmp)) {
NetExpr*re = mtmp->eval_tree();
if (re) {
delete mtmp;
mtmp = re;
}
}
eval_expr(mtmp);
/* Let's first try to get constant values for both
the parameter and the bit select. If they are
@@ -1168,7 +1367,20 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
verinum rv = re->value();
verinum::V rb = verinum::Vx;
long par_mv = lv.len()-1;
long par_lv = 0;
if (par_me) {
par_mv = par_me->value().as_long();
par_lv = par_le->value().as_long();
}
/* Convert the index to cannonical bit address. */
long ridx = rv.as_long();
if (par_mv >= par_lv) {
ridx -= par_lv;
} else {
ridx = par_mv - ridx + par_lv;
}
if ((ridx >= 0) && ((unsigned long) ridx < lv.len())) {
rb = lv[ridx];
@@ -1186,13 +1398,6 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
} else {
const NetEConst*par_me =dynamic_cast<const NetEConst*>(par_msb);
const NetEConst*par_le =dynamic_cast<const NetEConst*>(par_lsb);
assert(par_me || !par_msb);
assert(par_le || !par_lsb);
assert(par_me || !par_le);
if (par_me) {
long par_mv = par_me->value().as_long();
long par_lv = par_le->value().as_long();
@@ -1224,6 +1429,11 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
perm_string name = peek_tail_name(path_);
NetEConstParam*ptmp
= new NetEConstParam(found_in, name, ctmp->value());
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Elaborate parameter <" << name
<< "> as constant " << *ptmp << endl;
delete tmp;
tmp = ptmp;
}
@@ -1275,8 +1485,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
// Special case: The index is out of range, so the value
// of this expression is a 'bx vector the width of a word.
if (!net->array_index_is_valid(addr)) {
verinum xxx (verinum::Vx, net->vector_width());
NetEConst*resx = new NetEConst(xxx);
NetEConst*resx = make_const_x(net->vector_width());
resx->set_line(*this);
delete word_index;
return resx;
@@ -1298,9 +1507,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
if (long base = net->array_first()) {
word_index = make_add_expr(word_index, 0-base);
if (NetExpr*tmp = word_index->eval_tree()) {
word_index = tmp;
}
eval_expr(word_index);
}
}
@@ -1344,16 +1551,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
negative values. However, the width that they represent is
unsigned. Remember that any order is possible,
i.e., [1:0], [-4:6], etc. */
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
if (wid > net->vector_width()) {
cerr << get_fileline() << ": error: part select ["
<< msv << ":" << lsv << "] out of range." << endl;
des->errors += 1;
//delete lsn;
//delete msn;
return net;
}
ivl_assert(*this, wid <= net->vector_width());
unsigned long wid = 1 + labs(msv-lsv);
if (net->sig()->sb_to_idx(msv) < net->sig()->sb_to_idx(lsv)) {
cerr << get_fileline() << ": error: part select ["
@@ -1364,27 +1562,79 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
return net;
}
long sb_lsb = net->sig()->sb_to_idx(lsv);
long sb_msb = net->sig()->sb_to_idx(msv);
if (net->sig()->sb_to_idx(msv) >= net->vector_width()) {
cerr << get_fileline() << ": error: part select ["
<< msv << ":" << lsv << "] out of range." << endl;
des->errors += 1;
//delete lsn;
//delete msn;
return net;
}
// If the part select convers exactly the entire
// If the part select covers exactly the entire
// vector, then do not bother with it. Return the
// signal itself.
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
if (sb_lsb == 0 && wid == net->vector_width())
return net;
NetExpr*ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
// If the part select covers NONE of the vector, then return a
// constant X.
return ss;
if ((sb_lsb >= (signed) net->vector_width()) || (sb_msb < 0)) {
NetEConst*tmp = make_const_x(wid);
tmp->set_line(*this);
return tmp;
}
// If the part select is entirely within the vector, then make
// a simple part select.
if (sb_lsb >= 0 && sb_msb < (signed)net->vector_width()) {
NetExpr*ex = new NetEConst(verinum(sb_lsb));
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
return ss;
}
// Now the hard stuff. The part select is falling off at least
// one end. We're going to need a NetEConcat to mix the
// selection with overrun.
NetEConst*bot = 0;
if (sb_lsb < 0) {
bot = make_const_x( 0-sb_lsb );
bot->set_line(*this);
sb_lsb = 0;
}
NetEConst*top = 0;
if (sb_msb >= (signed)net->vector_width()) {
top = make_const_x( 1+sb_msb-net->vector_width() );
top->set_line(*this);
sb_msb = net->vector_width()-1;
}
unsigned concat_count = 1;
if (bot) concat_count += 1;
if (top) concat_count += 1;
NetEConcat*concat = new NetEConcat(concat_count);
concat->set_line(*this);
if (bot) {
concat_count -= 1;
concat->set(concat_count, bot);
}
if (sb_lsb == 0 && sb_msb+1 == (signed)net->vector_width()) {
concat_count -= 1;
concat->set(concat_count, net);
} else {
NetExpr*ex = new NetEConst(verinum(sb_lsb));
ex->set_line(*this);
NetESelect*ss = new NetESelect(net, ex, 1+sb_msb-sb_lsb);
ss->set_line(*this);
concat_count -= 1;
concat->set(concat_count, ss);
}
if (top) {
concat_count -= 1;
concat->set(concat_count, top);
}
ivl_assert(*this, concat_count==0);
return concat;
}
/*
@@ -1393,14 +1643,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
NetESignal*net, NetScope*found_in) const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.lsb != 0);
ivl_assert(*this, index_tail.msb != 0);
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
NetExpr*base = calculate_up_do_base_(des, scope);
unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid);
@@ -1412,7 +1655,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
long lsv = base_c->value().as_long();
// If the part select convers exactly the entire
// If the part select covers exactly the entire
// vector, then do not bother with it. Return the
// signal itself.
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
@@ -1471,10 +1714,11 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
long lsv = base_c->value().as_long();
// If the part select convers exactly the entire
// If the part select covers exactly the entire
// vector, then do not bother with it. Return the
// signal itself.
if (net->sig()->sb_to_idx(lsv) == (wid-1) && wid == net->vector_width())
if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
wid == net->vector_width())
return net;
// Otherwise, make a part select that covers the right range.
@@ -1524,8 +1768,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
/* The bit select is out of range of the
vector. This is legal, but returns a
constant 1'bx value. */
verinum x (verinum::Vx);
NetEConst*tmp = new NetEConst(x);
NetEConst*tmp = make_const_x(1);
tmp->set_line(*this);
cerr << get_fileline() << ": warning: Bit select ["
@@ -1539,7 +1782,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
}
// If the vector is only one bit, we are done. The
// bit select will return the scaler itself.
// bit select will return the scalar itself.
if (net->vector_width() == 1)
return net;
@@ -1676,6 +1919,12 @@ static bool test_ternary_operand_compat(ivl_variable_type_t l,
return true;
if (l == IVL_VT_BOOL && r == IVL_VT_LOGIC)
return true;
if (l == IVL_VT_REAL && (r == IVL_VT_LOGIC || r == IVL_VT_BOOL))
return true;
if (r == IVL_VT_REAL && (l == IVL_VT_LOGIC || l == IVL_VT_BOOL))
return true;
if (l == r)
return true;
@@ -1745,13 +1994,23 @@ NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope,
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool) const
{
/* Reduction operators and ! always have a self determined width. */
switch (op_) {
case '!':
case '&': // Reduction AND
case '|': // Reduction OR
case '^': // Reduction XOR
case 'A': // Reduction NAND (~&)
case 'N': // Reduction NOR (~|)
case 'X': // Reduction NXOR (~^)
expr_wid = -1;
default:
break;
}
NetExpr*ip = expr_->elaborate_expr(des, scope, expr_wid, false);
if (ip == 0) return 0;
/* Should we evaluate expressions ahead of time,
* just like in PEBinary::elaborate_expr() ?
*/
NetExpr*tmp;
switch (op_) {
default:
@@ -1766,15 +2025,15 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
if (expr_wid > 0)
val = pad_to_width(val, expr_wid);
/* When taking the - of a number, turn it into a
signed expression and extend it one bit to
accommodate a possible sign bit. */
/* When taking the - of a number, extend it one
bit to accommodate a possible sign bit. */
verinum zero (verinum::V0, val.len()+1, val.has_len());
zero.has_sign(val.has_sign());
verinum nval = zero - val;
if (val.has_len())
nval = verinum(nval, val.len());
nval.has_sign(true);
nval.has_sign(val.has_sign());
tmp = new NetEConst(nval);
tmp->set_line(*this);
delete ip;
+3 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -33,7 +33,7 @@
* assignment. This is common code for the = and <= statements.
*
* What gets generated depends on the structure of the l-value. If the
* l-value is a simple name (i.e., foo <= <value>) the the NetAssign_
* l-value is a simple name (i.e., foo <= <value>) then the NetAssign_
* is created the width of the foo reg and connected to all the
* bits.
*
@@ -333,9 +333,7 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
if (long base = reg->array_first()) {
word = make_add_expr(word, 0-base);
if (NetExpr*tmp = word->eval_tree()) {
word = tmp;
}
eval_expr(word);
}
NetAssign_*lv = new NetAssign_(reg);
@@ -485,4 +483,3 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
des->errors += 1;
return 0;
}
+801 -377
View File
File diff suppressed because it is too large Load Diff
+27 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0;
}
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -2);
NetExpr*tmp = elaborate_expr_base_(des, lp, rp, -2);
return tmp;
}
@@ -78,6 +78,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
"concatenation repeat expression cannot be evaluated."
<< endl;
des->errors += 1;
return 0;
}
/* continue on even if the repeat expression doesn't
@@ -108,7 +109,8 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
<< "concatenation has indefinite width: "
<< *ex << endl;
des->errors += 1;
delete tmp;
return 0;
}
tmp->set(idx, ex);
@@ -173,21 +175,31 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
switch (use_sel) {
case index_component_t::SEL_NONE:
break;
default:
case index_component_t::SEL_PART:
cerr << get_fileline() << ": sorry: Cannot part select "
"bits of parameters." << endl;
"bits of parameters." << endl;
des->errors += 1;
break;
delete res;
return 0;
case index_component_t::SEL_BIT:
/* We have here a bit select. Insert a NetESelect node
to handle it. */
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
if (tmp != 0) {
res = new NetESelect(res, tmp, 1);
if (tmp == 0) {
delete res;
return 0;
}
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Bit select [" << *tmp << "]"
<< " in parameter expression." << endl;
res = new NetESelect(res, tmp, 1);
res->set_line(*this);
break;
}
@@ -213,10 +225,11 @@ NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
NetExpr*c = expr_->elaborate_pexpr(des, scope);
NetExpr*t = tru_->elaborate_pexpr(des, scope);
NetExpr*f = fal_->elaborate_pexpr(des, scope);
if (c == 0) return 0;
if (t == 0) return 0;
if (f == 0) return 0;
return new NetETernary(c, t, f);
if (c == 0 || t == 0 || f == 0) return 0;
NetETernary*tmp = new NetETernary(c, t, f);
tmp->set_line(*this);
return tmp;
}
NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
@@ -234,10 +247,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
tmp = new NetEUnary(op_, ip);
tmp->set_line(*this);
break;
case '~':
tmp = new NetEUBits(op_, ip);
tmp->set_line(*this);
break;
case '!': // Logical NOT
case '&': // Reduction AND
case '|': // Reduction OR
@@ -249,6 +264,6 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
tmp->set_line(*this);
break;
}
return tmp;
}
+207 -79
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,6 +22,7 @@
# include "netmisc.h"
# include <cstring>
# include <iostream>
# include <cstdlib>
# include <stdio.h>
/*
@@ -43,6 +44,84 @@
# include "util.h"
# include <typeinfo>
# include <assert.h>
# include "ivl_assert.h"
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope)
{
PExpr*ex = cur.expr;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) return;
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = cur.signed_flag;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
result. Then make sure the constant expression of the
parameter value is coerced to have the correct
and defined width. */
if (cur.msb) {
assert(cur.lsb);
msb = cur.msb ->elaborate_pexpr(des, scope);
assert(msb);
lsb = cur.lsb ->elaborate_pexpr(des, scope);
assert(lsb);
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
NetScope::range_t*range_list = 0;
for (Module::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
tmp->exclude_flag = range->exclude_flag;
tmp->low_open_flag = range->low_open_flag;
tmp->high_open_flag = range->high_open_flag;
if (range->low_expr) {
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
ivl_assert(*range->low_expr, tmp->low_expr);
} else {
tmp->low_expr = 0;
}
if (range->high_expr && range->high_expr==range->low_expr) {
// Detect the special case of a "point"
// range. These are called out by setting the high
// and low expression ranges to the same
// expression. The exclude_flags should be false
// in this case
ivl_assert(*range->high_expr, tmp->low_open_flag==false && tmp->high_open_flag==false);
tmp->high_expr = tmp->low_expr;
} else if (range->high_expr) {
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
ivl_assert(*range->high_expr, tmp->high_expr);
} else {
tmp->high_expr = 0;
}
tmp->next = range_list;
range_list = tmp;
}
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
assert(val);
delete val;
}
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements) const
@@ -77,7 +156,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
for (mparm_it_t cur = localparams.begin()
@@ -88,7 +168,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
@@ -100,42 +181,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
PExpr*ex = (*cur).second.expr;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = (*cur).second.signed_flag;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
result. Then make sure the constant expression of the
parameter value is coerced to have the correct
and defined width. */
if ((*cur).second.msb) {
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
assert(msb);
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if ((*cur).second.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val = scope->set_parameter((*cur).first, val,
msb, lsb, signed_flag);
assert(val);
delete val;
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
/* run parameter replacements that were collected from the
@@ -155,6 +201,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
cerr << get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
@@ -167,31 +215,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
PExpr*ex = (*cur).second.expr;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = false;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
result. Then make sure the constant expression of the
parameter value is coerced to have the correct
and defined width. */
if ((*cur).second.msb) {
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
assert(msb);
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
signed_flag = (*cur).second.signed_flag;
}
val->cast_signed(signed_flag);
val = scope->set_parameter((*cur).first, val,
msb, lsb, signed_flag);
assert(val);
delete val;
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
// Run through the defparams for this module, elaborate the
@@ -257,6 +281,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
task_scope->set_line((*cur).second);
(*cur).second->elaborate_scope(des, task_scope);
}
@@ -280,6 +305,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
func_scope->set_line((*cur).second);
(*cur).second->elaborate_scope(des, func_scope);
}
@@ -301,8 +327,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors_.begin()
; cur != behaviors_.end() ; cur ++ ) {
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; cur ++ ) {
(*cur) -> statement() -> elaborate_scope(des, scope);
}
@@ -333,6 +359,15 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
case GS_ELSE:
return generate_scope_condit_(des, container, true);
case GS_CASE:
return generate_scope_case_(des, container);
return true;
case GS_CASE_ITEM:
cerr << get_fileline() << ": internal error: "
<< "Case item outside of a case generate scheme?" << endl;
return false;
default:
cerr << get_fileline() << ": sorry: Generate of this sort"
<< " is not supported yet!" << endl;
@@ -345,12 +380,17 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// Check that the loop_index variable was declared in a
// genvar statement.
// MISSING CODE!
// We're going to need a genvar...
int genvar;
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other paramter value is evaluated.
// the same way any other parameter value is evaluated.
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
@@ -360,12 +400,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
return false;
}
// Since we will be adding the genvar value as a local parameter
// to each instances scope. We need to make sure a parameter does
// not already exist.
const NetExpr*tmsb;
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(loop_index, tmsb, tlsb);
if (texpr != 0) {
cerr << get_fileline() << ": error: Cannot have a genvar "
<< "and parameter with the same name: " << loop_index << endl;
des->errors += 1;
return false;
}
genvar = init->value().as_long();
delete init_ex;
if (debug_elaborate)
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = genvar;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
@@ -385,12 +437,13 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
des->errors += 1;
return false;
}
if (debug_elaborate)
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Create generated scope " << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
@@ -402,9 +455,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
genvar_verinum);
scope->set_localparam(loop_index, gp);
if (debug_elaborate)
// The file and line information should really come
// from the genvar statement, not the for loop.
scope->set_localparam(loop_index, gp, *this);
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Create implicit localparam "
<< loop_index << " = " << genvar_verinum << endl;
@@ -416,7 +470,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
assert(step);
if (debug_elaborate)
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
@@ -446,7 +500,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
// scope.
if ( (test->value().as_long() == 0 && !else_flag)
|| (test->value().as_long() != 0 && else_flag) ) {
if (debug_elaborate)
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
<< " value=" << test->value() << ": skip generation"
@@ -463,7 +517,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
des->errors += 1;
return false;
}
if (debug_elaborate)
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
<< " value=" << test->value() << ": Generate scope="
@@ -471,12 +525,79 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
elaborate_subscope_(des, scope);
return true;
}
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
assert(case_value_co);
// The name of the scope to generate, whatever that item is.
hname_t use_name (scope_name);
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case "
<< "switch value=" << case_value_co->value() << endl;
PGenerate*default_item = 0;
typedef list<PGenerate*>::const_iterator generator_it_t;
generator_it_t cur = generates.begin();
while (cur != generates.end()) {
PGenerate*item = *cur;
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
// Detect that the item is a default.
if (item->loop_test == 0) {
default_item = item;
cur ++;
continue;
}
NetExpr*item_value_ex = elab_and_eval(des, container, item->loop_test, -1);
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
assert(item_value_co);
// If we stumble on the item that matches, then break
// out now.
if (case_value_co->value() == item_value_co->value()) {
delete item_value_co;
break;
}
delete item_value_co;
cur ++;
}
delete case_value_co;
case_value_co = 0;
PGenerate*item = (cur == generates.end())? default_item : *cur;
if (item == 0) {
cerr << get_fileline() << ": debug: "
<< "No generate items found" << endl;
return true;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Generate case matches item at "
<< item->get_fileline() << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
item->elaborate_subscope_(des, scope);
return true;
}
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
// Scan the generated scope for nested generate schemes,
@@ -604,6 +725,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// Create the new scope as a MODULE with my name.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
my_scope->default_nettype(mod->default_nettype);
@@ -685,7 +808,11 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
/* Stash the instance array of scopes into the parent
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;
}
@@ -738,8 +865,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
{
NetScope*my_scope = scope;
if (name_ != 0) {
hname_t use_name(name_);
if (pscope_name() != 0) {
hname_t use_name(pscope_name());
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: block/scope name "
<< use_name << " already used in this context."
@@ -750,6 +877,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
my_scope = new NetScope(scope, use_name, bl_type_==BL_PAR
? NetScope::FORK_JOIN
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());
}
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
+401 -163
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,46 +28,84 @@
# include "PGenerate.h"
# include "PTask.h"
# include "PWire.h"
# include "Statement.h"
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
# include "ivl_assert.h"
/*
* This local function checks if a named signal is connected to a
* port. It looks in the array of ports passed, for NetEIdent objects
* within the port_t that have a matching name.
*/
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
NetNet*sig)
static bool get_const_argument(NetExpr*exp, verinum&res)
{
perm_string name = sig->name();
switch (exp->expr_type()) {
case IVL_VT_REAL: {
NetECReal*cv = dynamic_cast<NetECReal*>(exp);
if (cv == 0) return false;
verireal tmp = cv->value();
res = verinum(tmp.as_long());
break;
}
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*cv = dynamic_cast<NetEConst*>(exp);
if (cv == 0) return false;
res = cv->value();
break;
}
Module::port_t*pp = ports[idx];
// Skip internally unconnected ports.
if (pp == 0)
continue;
// This port has an internal connection. In this case,
// the port has 0 or more NetEIdent objects concatenated
// together that form the port.
// Note that module ports should not have any heirarchy
// in their names: they are in the root of the module
// scope by definition.
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
perm_string pname = peek_tail_name(pp->expr[cc]->path());
assert(pp->expr[cc]);
if (pname == name)
return true;
}
default:
assert(0);;
}
return false;
return true;
}
void Statement::elaborate_sig(Design*des, NetScope*scope) const
{
}
bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
{
bool flag = true;
for (map<perm_string,PWire*>::const_iterator wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
PWire*cur = (*wt).second;
NetNet*sig = cur->elaborate_sig(des, scope);
/* If the signal is an input and is also declared as a
reg, then report an error. */
if (sig && (sig->scope() == scope)
&& (scope->type() == NetScope::MODULE)
&& (sig->port_type() == NetNet::PINPUT)
&& (sig->type() == NetNet::REG)) {
cerr << cur->get_fileline() << ": error: "
<< cur->basename() << " in "
<< scope->module_name()
<< " declared as input and as a reg type." << endl;
des->errors += 1;
}
if (sig && (sig->scope() == scope)
&& (scope->type() == NetScope::MODULE)
&& (sig->port_type() == NetNet::PINOUT)
&& (sig->type() == NetNet::REG)) {
cerr << cur->get_fileline() << ": error: "
<< cur->basename() << " in "
<< scope->module_name()
<< " declared as inout and as a reg type." << endl;
des->errors += 1;
}
}
return flag;
}
bool Module::elaborate_sig(Design*des, NetScope*scope) const
@@ -81,15 +119,27 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (pp == 0)
continue;
map<pform_name_t,PWire*>::const_iterator wt;
// The port has a name and an array of expressions. The
// expression are all identifiers that should reference
// wires within the scope.
map<perm_string,PWire*>::const_iterator wt;
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
pform_name_t port_path (pp->expr[cc]->path());
wt = wires_.find(port_path);
// A concatenated wire of a port really should not
// have any hierarchy.
if (port_path.size() != 1) {
cerr << get_fileline() << ": internal error: "
<< "Port " << port_path << " has a funny name?"
<< endl;
des->errors += 1;
}
if (wt == wires_.end()) {
wt = wires.find(peek_tail_name(port_path));
if (wt == wires.end()) {
cerr << get_fileline() << ": error: "
<< "Port " << pp->expr[cc]->path() << " ("
<< (idx+1) << ") of module " << name_
<< "Port " << port_path << " ("
<< (idx+1) << ") of module " << mod_name()
<< " is not declared within module." << endl;
des->errors += 1;
continue;
@@ -98,7 +148,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if ((*wt).second->get_port_type() == NetNet::NOT_A_PORT) {
cerr << get_fileline() << ": error: "
<< "Port " << pp->expr[cc]->path() << " ("
<< (idx+1) << ") of module " << name_
<< (idx+1) << ") of module " << mod_name()
<< " has no direction declaration."
<< endl;
des->errors += 1;
@@ -106,60 +156,9 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
}
}
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
; wt != wires_.end() ; wt ++ ) {
flag = elaborate_sig_wires_(des, scope) && flag;
PWire*cur = (*wt).second;
NetNet*sig = cur->elaborate_sig(des, scope);
// If this wire is a signal of the module (as opposed to
// a port of a function) and is a port, then check that
// the module knows about it. We know that the signal is
// the name of a signal within a subscope of a module
// (a task, a function, etc.) if the name for the PWire
// has hierarchy.
if (sig && (sig->scope() == scope)
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
if (! signal_is_in_port(ports, sig)) {
cerr << cur->get_fileline() << ": error: Signal "
<< sig->name() << " has a declared direction "
<< "but is not a port." << endl;
des->errors += 1;
}
}
/* If the signal is an input and is also declared as a
reg, then report an error. */
if (sig && (sig->scope() == scope)
&& (sig->port_type() == NetNet::PINPUT)
&& (sig->type() == NetNet::REG)) {
cerr << cur->get_fileline() << ": error: "
<< cur->path() << " in module "
<< scope->module_name()
<< " declared as input and as a reg type." << endl;
des->errors += 1;
}
if (sig && (sig->scope() == scope)
&& (sig->port_type() == NetNet::PINOUT)
&& (sig->type() == NetNet::REG)) {
cerr << cur->get_fileline() << ": error: "
<< cur->path() << " in module "
<< scope->module_name()
<< " declared as inout and as a reg type." << endl;
des->errors += 1;
}
}
// Run through all the generate schemes to enaborate the
// Run through all the generate schemes to elaborate the
// signals that they hold. Note that the generate schemes hold
// the scopes that they instantiated, so we don't pass any
// scope in.
@@ -216,14 +215,144 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
(*cur).second->elaborate_sig(des, tscope);
}
// initial and always blocks may contain begin-end and
// fork-join blocks that can introduce scopes. Therefore, I
// get to scan processes here.
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; cur ++ ) {
(*cur) -> statement() -> elaborate_sig(des, scope);
}
return flag;
}
bool PExpr::elaborate_sig(Design*des, NetScope*scope) const
{
return true;
}
bool PEConcat::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
flag = parms_[idx]->elaborate_sig(des, scope) && flag;
return flag;
}
bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
{
NetNet* sig = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
// If implicit net creation is turned off, then stop now.
if (scope->default_nettype() == NetNet::NONE)
return true;
if (error_implicit)
return true;
symbol_search(des, scope, path_, sig, par, eve);
if (eve != 0)
return false;
if (par != 0)
return true;
if (sig == 0)
sig = make_implicit_net_(des, scope);
return sig != 0;
}
bool PEBinary::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
flag = left_->elaborate_sig(des, scope) && flag;
flag = right_->elaborate_sig(des, scope) && flag;
return flag;
}
bool PETernary::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
flag = tru_->elaborate_sig(des, scope) && flag;
flag = fal_->elaborate_sig(des, scope) && flag;
return flag;
}
bool PEUnary::elaborate_sig(Design*des, NetScope*scope) const
{
return expr_->elaborate_sig(des, scope);
}
bool PGate::elaborate_sig(Design*des, NetScope*scope) const
{
return true;
}
bool PGBuiltin::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
const PExpr* pin_expr = pin(idx);
if (pin_expr == 0) {
// If there is no pin expression for this port,
// then skip it. Do not bother generating an error
// message here, that will be done during
// elaboration where these semantic details are tested.
continue;
}
ivl_assert(*this, pin_expr);
flag = pin_expr->elaborate_sig(des, scope) && flag;
}
return flag;
}
bool PGAssign::elaborate_sig(Design*des, NetScope*scope) const
{
/* Normally, l-values to continuous assignments are NOT allowed
to implicitly declare nets. However, so many tools do allow
it that Icarus Verilog will allow it, at least if extensions
are enabled. */
if (gn_icarus_misc_flag)
return pin(0)->elaborate_sig(des, scope);
return true;
}
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
Module*rmod) const
{
bool flag = true;
// First, elaborate the signals that may be created implicitly
// by ports to this module instantiation. Handle the case that
// the ports are passed by name (pins_ != 0) or position.
if (pins_)
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
const PExpr*tmp = pins_[idx].parm;
if (tmp == 0)
continue;
flag = tmp->elaborate_sig(des, scope) && flag;
}
else
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
const PExpr*tmp = pin(idx);
if (tmp == 0)
continue;
flag = tmp->elaborate_sig(des, scope) && flag;
}
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
@@ -249,10 +378,53 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
return flag;
}
bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
{
bool flag = true;
if (pins_)
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
const PExpr*tmp = pins_[idx].parm;
if (tmp == 0)
continue;
flag = tmp->elaborate_sig(des, scope) && flag;
}
else
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
const PExpr*tmp = pin(idx);
if (tmp == 0)
continue;
flag = tmp->elaborate_sig(des, scope) && flag;
}
return flag;
}
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
{
bool flag = true;
// Handle the special case that this is a CASE scheme. In this
// case the PGenerate itself does not have the generated
// item. Look instead for the case ITEM that has a scope
// generated for it.
if (scheme_type == PGenerate::GS_CASE) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: generate case"
<< " elaborate_sig in scope "
<< scope_path(container) << "." << endl;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
}
}
return flag;
}
typedef list<NetScope*>::const_iterator scope_list_it_t;
for (scope_list_it_t cur = scope_list_.begin()
; cur != scope_list_.end() ; cur ++ ) {
@@ -276,7 +448,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
// in the current scope.
typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
typedef map<perm_string,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
@@ -284,7 +456,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
if (debug_elaborate)
cerr << get_fileline() << ": debug: Elaborate PWire "
<< cur->path() << " in scope " << scope_path(scope) << endl;
<< cur->basename() << " in scope " << scope_path(scope) << endl;
cur->elaborate_sig(des, scope);
}
@@ -316,6 +488,8 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
perm_string fname = scope->basename();
assert(scope->type() == NetScope::FUNC);
elaborate_sig_wires_(des, scope);
/* Make sure the function has at least one input port. If it
fails this test, print an error message. Keep going so we
can find more errors. */
@@ -416,21 +590,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
name. We know by design that the port name is given
as two components: <func>.<port>. */
pform_name_t path = (*ports_)[idx]->path();
ivl_assert(*this, path.size() == 2);
perm_string pname = peek_tail_name(path);
perm_string ppath = peek_head_name(path);
if (ppath != scope->basename()) {
cerr << get_fileline() << ": internal error: function "
<< "port " << (*ports_)[idx]->path()
<< " has wrong name for function "
<< scope_path(scope) << "." << endl;
des->errors += 1;
}
perm_string pname = (*ports_)[idx]->basename();
NetNet*tmp = scope->find_signal(pname);
ports[idx] = 0;
if (tmp == 0) {
cerr << get_fileline() << ": internal error: function "
<< scope_path(scope) << " is missing port "
@@ -438,9 +602,27 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
scope->dump(cerr);
cerr << get_fileline() << ": Continuing..." << endl;
des->errors += 1;
continue;
}
if (tmp->port_type() == NetNet::NOT_A_PORT) {
cerr << get_fileline() << ": internal error: function "
<< scope_path(scope) << " port " << pname
<< " is a port but is not a port?" << endl;
des->errors += 1;
scope->dump(cerr);
continue;
}
ports[idx] = tmp;
if (tmp->port_type() != NetNet::PINPUT) {
cerr << tmp->get_fileline() << ": error: function "
<< scope_path(scope) << " port " << pname
<< " is not an input port." << endl;
cerr << tmp->get_fileline() << ": : Function arguments "
<< "must be input ports." << endl;
des->errors += 1;
}
}
@@ -448,7 +630,16 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
assert(def);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Attach function definition to scope "
<< scope_path(scope) << "." << endl;
scope->set_func_def(def);
// Look for further signals in the sub-statement
if (statement_)
statement_->elaborate_sig(des, scope);
}
/*
@@ -464,24 +655,12 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
elaborate_sig_wires_(des, scope);
svector<NetNet*>ports (ports_? ports_->count() : 0);
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
/* Parse the port name into the task name and the reg
name. We know by design that the port name is given
as two components: <task>.<port>. */
pform_name_t path = (*ports_)[idx]->path();
ivl_assert(*this, path.size() == 2);
perm_string scope_name = peek_head_name(path);
perm_string port_name = peek_tail_name(path);
/* check that the current scope really does have the
name of the first component of the task port name. Do
this by looking up the task scope in the parent of
the current scope. */
ivl_assert(*this, scope->basename() == scope_name);
perm_string port_name = (*ports_)[idx]->basename();
/* Find the signal for the port. We know by definition
that it is in the scope of the task, so look only in
@@ -493,6 +672,7 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
<< "Could not find port " << port_name
<< " in scope " << scope_path(scope) << endl;
scope->dump(cerr);
des->errors += 1;
}
ports[idx] = tmp;
@@ -500,11 +680,94 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
NetTaskDef*def = new NetTaskDef(scope, ports);
scope->set_task_def(def);
// Look for further signals in the sub-statement
if (statement_)
statement_->elaborate_sig(des, scope);
}
bool PGate::elaborate_sig(Design*des, NetScope*scope) const
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
{
return true;
NetScope*my_scope = scope;
if (pscope_name() != 0) {
hname_t use_name (pscope_name());
my_scope = scope->child(use_name);
if (my_scope == 0) {
cerr << get_fileline() << ": internal error: "
<< "Unable to find child scope " << pscope_name()
<< " in this context?" << endl;
des->errors += 1;
my_scope = scope;
} else {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "elaborate_sig descending into "
<< scope_path(my_scope) << "." << endl;
elaborate_sig_wires_(des, my_scope);
}
}
// elaborate_sig in the statements included in the
// block. There may be named blocks in there.
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
list_[idx] -> elaborate_sig(des, my_scope);
}
void PCase::elaborate_sig(Design*des, NetScope*scope) const
{
if (items_ == 0)
return;
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
if ( (*items_)[idx]->stat )
(*items_)[idx]->stat ->elaborate_sig(des,scope);
}
}
void PCondit::elaborate_sig(Design*des, NetScope*scope) const
{
if (if_)
if_->elaborate_sig(des, scope);
if (else_)
else_->elaborate_sig(des, scope);
}
void PDelayStatement::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
void PForever::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
void PForStatement::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
void PRepeat::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
void PWhile::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
/*
@@ -516,27 +779,6 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const
*/
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
{
/* The parser may produce hierarchical names for wires. I here
follow the scopes down to the base where I actually want to
elaborate the NetNet object. */
{ pform_name_t tmp_path = hname_;
tmp_path.pop_back();
while (! tmp_path.empty()) {
name_component_t cur = tmp_path.front();
tmp_path.pop_front();
scope = scope->child( hname_t(cur.name) );
if (scope == 0) {
cerr << get_fileline() << ": internal error: "
<< "Bad scope component for name "
<< hname_ << endl;
assert(scope);
}
}
}
NetNet::Type wtype = type_;
if (wtype == NetNet::IMPLICIT)
wtype = NetNet::WIRE;
@@ -619,12 +861,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_msb_ == 0) {
if (!gn_io_range_error_flag) {
cerr << get_fileline()
<< ": warning: Scalar port ``" << hname_
<< ": warning: Scalar port ``" << name_
<< "'' has a vectored net declaration ["
<< nmsb << ":" << nlsb << "]." << endl;
} else {
cerr << get_fileline()
<< ": error: Scalar port ``" << hname_
<< ": error: Scalar port ``" << name_
<< "'' has a vectored net declaration ["
<< nmsb << ":" << nlsb << "]." << endl;
des->errors += 1;
@@ -636,7 +878,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (net_msb_ == 0) {
cerr << port_msb_->get_fileline()
<< ": error: Vectored port ``"
<< hname_ << "'' [" << pmsb << ":" << plsb
<< name_ << "'' [" << pmsb << ":" << plsb
<< "] has a scalar net declaration at "
<< get_fileline() << "." << endl;
des->errors += 1;
@@ -647,7 +889,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_msb_ != 0 && net_msb_ != 0) {
cerr << port_msb_->get_fileline()
<< ": error: Vectored port ``"
<< hname_ << "'' [" << pmsb << ":" << plsb
<< name_ << "'' [" << pmsb << ":" << plsb
<< "] has a net declaration [" << nmsb << ":"
<< nlsb << "] at " << net_msb_->get_fileline()
<< " that does not match." << endl;
@@ -687,28 +929,26 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is "
<< "a problem evaluating indices for ``"
<< hname_ << "''." << endl;
<< name_ << "''." << endl;
des->errors += 1;
return 0;
}
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
NetEConst*rcon = dynamic_cast<NetEConst*> (rexp);
bool const_flag = true;
verinum lval, rval;
const_flag &= get_const_argument(lexp, lval);
const_flag &= get_const_argument(rexp, rval);
delete rexp;
delete lexp;
if ((lcon == 0) || (rcon == 0)) {
if (!const_flag) {
cerr << get_fileline() << ": internal error: The indices "
<< "are not constant for array ``"
<< hname_ << "''." << endl;
<< name_ << "''." << endl;
des->errors += 1;
return 0;
}
verinum lval = lcon->value();
verinum rval = rcon->value();
delete lexp;
delete rexp;
array_dimensions = 1;
array_s0 = lval.as_long();
array_e0 = rval.as_long();
@@ -748,24 +988,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
}
perm_string name = peek_tail_name(hname_);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
<< " in scope " << scope_path(scope) << endl;
}
NetNet*sig = array_dimensions > 0
? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0)
: new NetNet(scope, name, wtype, msb, lsb);
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
: new NetNet(scope, name_, wtype, msb, lsb);
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Signal " << name
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
@@ -785,4 +1024,3 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
return sig;
}
+247 -88
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.374 2007/06/05 21:35:51 steve Exp $"
#endif
# include "config.h"
@@ -88,16 +85,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
assert(pin(0));
assert(pin(1));
/* Normally, l-values to continuous assignments are NOT allowed
to implicitly declare nets. However, so many tools do allow
it that Icarus Verilog will allow it, at least if extensions
are enabled. */
bool implicit_lval_ok = false;
if (generation_flag == GN_VER2001X)
implicit_lval_ok = true;
/* Elaborate the l-value. */
NetNet*lval = pin(0)->elaborate_lnet(des, scope, implicit_lval_ok);
NetNet*lval = pin(0)->elaborate_lnet(des, scope);
if (lval == 0) {
return;
}
@@ -124,6 +113,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
return;
}
/* If either lval or rid are real then both must be real. */
if ((lval->data_type() == IVL_VT_REAL ||
rid->data_type() == IVL_VT_REAL) &&
lval->data_type() != rid->data_type()) {
cerr << get_fileline() << ": sorry: Both the r-value and "
"the l-value must be real in this context." << endl;
des->errors += 1;
return;
}
ivl_assert(*this, rid);
if (rid->pin_count() != 1) {
cerr << get_fileline() << ": internal error: "
@@ -270,7 +269,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
generated NetNet. */
NetNet*rval = pin(1)->elaborate_net(des, scope,
lval->vector_width(),
rise_time, fall_time, decay_time,
0, 0, 0,
drive0, drive1);
if (rval == 0) {
cerr << get_fileline() << ": error: Unable to elaborate r-value: "
@@ -288,6 +287,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
assert(lval && rval);
assert(rval->pin_count() == 1);
/* If either lval or rval are real then both must be real. */
if ((lval->data_type() == IVL_VT_REAL ||
rval->data_type() == IVL_VT_REAL) &&
lval->data_type() != rval->data_type()) {
cerr << get_fileline() << ": sorry: Both the r-value and "
"the l-value must be real in this context." << endl;
des->errors += 1;
return;
}
/* If the r-value insists on being smaller then the l-value
(perhaps it is explicitly sized) the pad it out to be the
right width so that something is connected to all the bits
@@ -311,6 +320,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
rval = osig;
}
/* If there is a rise/fall/decay time, then attach that delay
to the drivers for this net. */
if (rise_time || fall_time || decay_time) {
rval->pin(0).drivers_delays(rise_time, fall_time, decay_time);
}
connect(lval->pin(0), rval->pin(0));
if (lval->local_flag())
@@ -387,7 +402,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
des->errors += 1;
return;
}
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope, true);
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope);
assert(lval_sig);
/* Detect the special case that the l-value width exactly
@@ -404,7 +419,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
}
/* Allocate all the netlist nodes for the gates. */
NetLogic**cur = new NetLogic*[count];
NetNode**cur = new NetNode*[count];
assert(cur);
/* Calculate the gate delays from the delay expressions
@@ -644,6 +659,67 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XOR, instance_width);
break;
case TRAN:
if (pin_count() != 2) {
cerr << get_fileline() << ": error: Pin count for "
<< "tran device." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetTran(scope, inm, IVL_SW_TRAN);
}
break;
case RTRAN:
if (pin_count() != 2) {
cerr << get_fileline() << ": error: Pin count for "
<< "rtran device." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRAN);
return;
}
break;
case TRANIF0:
if (pin_count() != 3) {
cerr << get_fileline() << ": error: Pin count for "
<< "tranif0 device." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetTran(scope, inm, IVL_SW_TRANIF0);
}
break;
case RTRANIF0:
if (pin_count() != 3) {
cerr << get_fileline() << ": error: Pin count for "
<< "rtranif0 device." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRANIF0);
}
break;
case TRANIF1:
if (pin_count() != 3) {
cerr << get_fileline() << ": error: Pin count for "
<< "tranif1 device." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetTran(scope, inm, IVL_SW_TRANIF1);
}
break;
case RTRANIF1:
if (pin_count() != 3) {
cerr << get_fileline() << ": error: Pin count for "
<< "rtranif1 device." << endl;
des->errors += 1;
return;
} else {
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRANIF1);
}
break;
default:
cerr << get_fileline() << ": internal error: unhandled "
"gate type." << endl;
@@ -655,13 +731,18 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
cur[idx]->attribute(attrib_list[adx].key,
attrib_list[adx].val);
cur[idx]->rise_time(rise_time);
cur[idx]->fall_time(fall_time);
cur[idx]->decay_time(decay_time);
/* The logic devices have some uniform processing. Then
all may have output delays and output drive strength. */
if (NetLogic*log = dynamic_cast<NetLogic*> (cur[idx])) {
log->rise_time(rise_time);
log->fall_time(fall_time);
log->decay_time(decay_time);
cur[idx]->pin(0).drive0(drive_type(strength0()));
cur[idx]->pin(0).drive1(drive_type(strength1()));
log->pin(0).drive0(drive_type(strength0()));
log->pin(0).drive1(drive_type(strength1()));
}
cur[idx]->set_line(*this);
des->add_node(cur[idx]);
}
@@ -783,6 +864,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
}
}
// "cur" is an array of pointers, and we don't need it any more.
delete[]cur;
}
NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
@@ -797,6 +881,31 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
tmp->local_flag(true);
tmp->set_line(*sig);
// Handle the special case of a bi-directional part
// select. Create a NetTran(VP) instead of a uni-directional
// NetPartSelect node.
if (dir == NetNet::PINOUT) {
unsigned wida = sig->vector_width();
unsigned widb = tmp->vector_width();
bool part_b = widb < wida;
NetTran*node = new NetTran(scope, scope->local_symbol(),
part_b? wida : widb,
part_b? widb : wida,
0);
if (part_b) {
connect(node->pin(0), sig->pin(0));
connect(node->pin(1), tmp->pin(0));
} else {
connect(node->pin(0), tmp->pin(0));
connect(node->pin(1), sig->pin(0));
}
node->set_line(*this);
des->add_node(node);
return tmp;
}
NetPartSelect*node = 0;
switch (dir) {
@@ -825,15 +934,7 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
break;
case NetNet::PINOUT:
if (sig->vector_width() > tmp->vector_width()) {
node = new NetPartSelect(sig, 0, tmp->vector_width(),
NetPartSelect::BI);
connect(node->pin(0), tmp->pin(0));
} else {
node = new NetPartSelect(tmp, 0, sig->vector_width(),
NetPartSelect::BI);
connect(node->pin(0), sig->pin(0));
}
ivl_assert(*this, 0);
break;
default:
@@ -1014,7 +1115,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
unsigned prts_vector_width = 0;
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...
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
@@ -1115,7 +1218,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
assignment, as the port will continuous assign
into the port. */
sig = pins[idx]->elaborate_lnet(des, scope, true);
sig = pins[idx]->elaborate_lnet(des, scope);
if (sig == 0) {
cerr << pins[idx]->get_fileline() << ": error: "
<< "Output port expression must support "
@@ -1450,7 +1553,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
<< endl;
} else {
NetNet*sig = pins[0]->elaborate_lnet(des, scope, true);
NetNet*sig = pins[0]->elaborate_lnet(des, scope);
if (sig == 0) {
cerr << get_fileline() << ": error: "
<< "Output port expression is not valid." << endl;
@@ -1492,6 +1595,10 @@ bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
if (mod != pform_modules.end())
return elaborate_sig_mod_(des, scope, (*mod).second);
map<perm_string,PUdp*>::const_iterator udp = pform_primitives.find(type_);
if (udp != pform_primitives.end())
return elaborate_sig_udp_(des, scope, (*udp).second);
return true;
}
@@ -1690,7 +1797,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
netlist. The compound statement is exactly equivalent. */
if (delay || event_) {
unsigned wid = lv->lwidth();
unsigned wid = count_lval_width(lv);
rv->set_width(wid);
rv = pad_to_width(rv, wid);
@@ -1840,18 +1947,19 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
: NetBlock::SEQU;
NetScope*nscope = 0;
if (name_.str() != 0) {
nscope = scope->child(hname_t(name_));
if (pscope_name() != 0) {
nscope = scope->child(hname_t(pscope_name()));
if (nscope == 0) {
cerr << get_fileline() << ": internal error: "
"unable to find block scope " << scope_path(scope)
<< "<" << name_ << ">" << endl;
<< "<" << pscope_name() << ">" << endl;
des->errors += 1;
return 0;
}
assert(nscope);
elaborate_behaviors_(des, nscope);
}
NetBlock*cur = new NetBlock(type, nscope);
@@ -1863,7 +1971,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
// statement. There is no need to keep the block node. Also,
// don't elide named blocks, because they might be referenced
// elsewhere.
if ((list_.count() == 1) && (name_.str() == 0)) {
if ((list_.count() == 1) && (pscope_name() == 0)) {
assert(list_[0]);
NetProc*tmp = list_[0]->elaborate(des, nscope);
return tmp;
@@ -2023,14 +2131,8 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
return 0;
}
if (expr->expr_width() > 1) {
assert(expr->expr_width() > 1);
verinum zero (verinum::V0, expr->expr_width());
NetEConst*ezero = new NetEConst(zero);
ezero->set_width(expr->expr_width());
NetEBComp*cmp = new NetEBComp('n', expr, ezero);
expr = cmp;
}
// Make sure the condition expression evaluates to a condition.
expr = condition_reduce(expr);
// Well, I actually need to generate code to handle the
// conditional, so elaborate.
@@ -2097,12 +2199,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
/* Attempt to pre-evaluate the parameters. It may be
possible to at least partially reduce the
expression. */
if (eparms[idx]) {
if (NetExpr*tmp = eparms[idx]->eval_tree()) {
delete eparms[idx];
eparms[idx] = tmp;
}
}
if (eparms[idx]) eval_expr(eparms[idx]);
}
NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms);
@@ -2699,10 +2796,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
}
/* precalculate as much as possible of the wait expression. */
if (NetExpr*tmp = expr->eval_tree()) {
delete expr;
expr = tmp;
}
eval_expr(expr);
/* Detect the unusual case that the wait expression is
constant. Constant true is OK (it becomes transparent) but
@@ -2745,11 +2839,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
wait. */
assert(expr->expr_width() == 1);
expr = new NetEBComp('N', expr, new NetEConst(verinum(verinum::V1)));
NetExpr*tmp = expr->eval_tree();
if (tmp) {
delete expr;
expr = tmp;
}
eval_expr(expr);
NetEvent*wait_event = new NetEvent(scope->local_symbol());
scope->add_event(wait_event);
@@ -2836,14 +2926,14 @@ NetProc* PForever::elaborate(Design*des, NetScope*scope) const
}
/*
* Force is like a procedural assignment, most notably prodedural
* Force is like a procedural assignment, most notably procedural
* continuous assignment:
*
* force <lval> = <rval>
*
* The <lval> can be anything that a normal behavioral assignment can
* take, plus net signals. This is a little bit more lax then the
* other proceedural assignments.
* other procedural assignments.
*/
NetForce* PForce::elaborate(Design*des, NetScope*scope) const
{
@@ -2908,7 +2998,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
NetNet*sig = des->find_signal(scope, id1->path());
if (sig == 0) {
cerr << id1->get_fileline() << ": register ``" << id1->path()
<< "'' unknown in this context." << endl;
<< "'' unknown in " << scope_path(scope) << "." << endl;
des->errors += 1;
return 0;
}
@@ -2933,6 +3023,15 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
assert(etmp->expr_width() >= lv->lwidth());
}
/* Based on the specific type of the l-value, do cleanup
processing on the r-value. */
if (etmp->expr_type() != IVL_VT_REAL) {
unsigned wid = count_lval_width(lv);
etmp->set_width(wid);
etmp = pad_to_width(etmp, wid);
assert(etmp->expr_width() >= wid);
}
NetAssign*init = new NetAssign(lv, etmp);
init->set_line(*this);
@@ -3024,6 +3123,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": internal error: "
<< "No function definition for function "
<< scope_path(scope) << endl;
des->errors += 1;
return;
}
@@ -3121,6 +3221,11 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
void PTask::elaborate(Design*des, NetScope*task) const
{
// Elaborate any processes that are part of this scope that
// aren't the definition itself. This can happen, for example,
// with variable initialization statements in this scope.
elaborate_behaviors_(des, task);
NetTaskDef*def = task->task_def();
assert(def);
@@ -3252,6 +3357,29 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
verinum(1));
} while (0);
/* If this is an always block and we have no or zero delay then
* a runtime infinite loop will happen. If we possible have some
* delay then print a warning that an infinite loop is possible.
*/
if (type() == PProcess::PR_ALWAYS) {
DelayType dly_type = top->statement()->delay_type();
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
cerr << get_fileline() << ": error: always statement"
<< " does not have any delay." << endl;
cerr << get_fileline() << ": : A runtime infinite"
<< " loop will occur." << endl;
des->errors += 1;
return false;
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
cerr << get_fileline() << ": warning: always statement"
<< " may not have any delay." << endl;
cerr << get_fileline() << ": : A runtime infinite"
<< " loop may be possible." << endl;
}
}
return true;
}
@@ -3265,16 +3393,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
if (!gn_specify_blocks_flag)
return;
/* Check for various path types that are not supported. */
if (conditional && !condition) {
cerr << get_fileline() << ": sorry: ifnone specify paths"
<< " are not supported." << endl;
cerr << get_fileline() << ": : Use -g no-specify to ignore"
<< " specify blocks." << endl;
des->errors += 1;
return;
}
ivl_assert(*this, conditional || (condition==0));
ndelays = delays.size();
@@ -3306,7 +3424,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
delete cur;
}
switch (ndelays) {
switch (delays.size()) {
case 1:
case 2:
case 3:
@@ -3315,15 +3433,14 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
break;
default:
cerr << get_fileline() << ": error: Incorrect delay configuration."
<< endl;
<< " Given " << delays.size() << " delay expressions." << endl;
ndelays = 1;
des->errors += 1;
break;
}
NetNet*condit_sig = 0;
if (conditional) {
ivl_assert(*this, condition);
if (conditional && condition) {
NetExpr*tmp = elab_and_eval(des, scope, condition, -1);
ivl_assert(*condition, tmp);
@@ -3344,7 +3461,9 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: Path to " << (*cur);
if (condit_sig)
cerr << " if " << condit_sig->name();
cerr << endl;
else if (conditional)
cerr << " ifnone";
cerr << " from ";
}
NetNet*dst_sig = scope->find_signal(*cur);
@@ -3364,7 +3483,8 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
}
NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(),
src.size(), condit_sig);
src.size(), condit_sig,
conditional);
path->set_line(*this);
// The presence of the data_source_expression indicates
@@ -3407,6 +3527,11 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
NetNet*src_sig = scope->find_signal(*cur_src);
assert(src_sig);
if (debug_elaborate) {
if (cur_src != src.begin()) cerr << " and ";
cerr << src_sig->name();
}
if ( (src_sig->port_type() != NetNet::PINPUT)
&& (src_sig->port_type() != NetNet::PINOUT) ) {
@@ -3419,6 +3544,9 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
connect(src_sig->pin(0), path->pin(idx));
idx += 1;
}
if (debug_elaborate) {
cerr << endl;
}
if (condit_sig)
connect(condit_sig->pin(0), path->pin(idx));
@@ -3525,13 +3653,7 @@ bool Module::elaborate(Design*des, NetScope*scope) const
// Elaborate the behaviors, making processes out of them. This
// involves scanning the PProcess* list, creating a NetProcTop
// for each process.
const list<PProcess*>&sl = get_behaviors();
for (list<PProcess*>::const_iterator st = sl.begin()
; st != sl.end() ; st ++ ) {
result_flag &= (*st)->elaborate(des, scope);
}
result_flag &= elaborate_behaviors_(des, scope);
// Elaborate the specify paths of the module.
@@ -3548,6 +3670,27 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
{
bool flag = true;
// Handle the special case that this is a CASE scheme. In this
// case the PGenerate itself does not have the generated
// item. Look instead for the case ITEM that has a scope
// generated for it.
if (scheme_type == PGenerate::GS_CASE) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: generate case"
<< " elaborating in scope "
<< scope_path(container) << "." << endl;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
flag &= item->elaborate(des, container);
}
}
return flag;
}
typedef list<NetScope*>::const_iterator scope_list_it_t;
for (scope_list_it_t cur = scope_list_.begin()
; cur != scope_list_.end() ; cur ++ ) {
@@ -3598,6 +3741,22 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
return true;
}
bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
{
bool result_flag = true;
// Elaborate the behaviors, making processes out of them. This
// involves scanning the PProcess* list, creating a NetProcTop
// for each process.
for (list<PProcess*>::const_iterator st = behaviors.begin()
; st != behaviors.end() ; st ++ ) {
result_flag &= (*st)->elaborate(des, scope);
}
return result_flag;
}
struct root_elem {
Module *mod;
NetScope *scope;
@@ -3634,6 +3793,7 @@ Design* elaborate(list<perm_string>roots)
// Make the root scope.
NetScope*scope = des->make_root_scope(*root);
scope->set_line(rmod);
scope->time_unit(rmod->time_unit);
scope->time_precision(rmod->time_precision);
scope->default_nettype(rmod->default_nettype);
@@ -3703,4 +3863,3 @@ Design* elaborate(list<perm_string>roots)
return des;
}
+21 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -49,6 +49,12 @@ bool NetUDP::emit_node(struct target_t*tgt) const
return true;
}
bool NetAbs::emit_node(struct target_t*tgt) const
{
tgt->lpm_abs(this);
return true;
}
bool NetAddSub::emit_node(struct target_t*tgt) const
{
tgt->lpm_add_sub(this);
@@ -128,6 +134,12 @@ bool NetPartSelect::emit_node(struct target_t*tgt) const
return tgt->part_select(this);
}
bool NetPow::emit_node(struct target_t*tgt) const
{
tgt->lpm_pow(this);
return true;
}
bool NetReplicate::emit_node(struct target_t*tgt) const
{
return tgt->replicate(this);
@@ -153,6 +165,11 @@ bool NetUserFunc::emit_node(struct target_t*tgt) const
return tgt->net_function(this);
}
bool NetTran::emit_node(struct target_t*tgt) const
{
return tgt->tran(this);
}
bool NetBUFZ::emit_node(struct target_t*tgt) const
{
return tgt->bufz(this);
@@ -372,7 +389,9 @@ bool NetScope::emit_defs(struct target_t*tgt) const
case TASK:
tgt->task_def(this);
break;
default: /* BEGIN_END and FORK_JOIN, do nothing */
default: /* BEGIN_END and FORK_JOIN, GENERATE... */
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
flag &= cur->emit_defs(tgt);
break;
}
+291 -369
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -26,7 +26,7 @@
* iverilog -tpal -ppart=generic-22v10-plcc -opal_reg.jed pal_reg.v
*
* The output file name (passed through the -o<file> switch) can be
* any file you desire. If the compilation and fittin all succeed, the
* any file you desire. If the compilation and fitting all succeed, the
* output file will be a JEDEC file that you can take to your favorite
* PROM programmer to program the part.
*
@@ -45,7 +45,7 @@
*
* The output drivers are controlled by a single active low output
* enable. I used bufif0 devices in this example, but the exact same
* thing can be achived with a continuous assignment like so:
* thing can be achieved with a continuous assignment like so:
*
* assign out = oe? 8'hzz : Q;
*
@@ -76,7 +76,7 @@ endmodule
* a PLCC package.
*
* Note that this module has no logic in it. It is a convention I use
* that I put all the functionality in a seperate module (seen above)
* that I put all the functionality in a separate module (seen above)
* and isolate the Icarus Verilog specific $attribute madness into a
* top-level module. The advantage of this style is that the entire
* module can be `ifdef'ed out when doing simulation and you don't
+1 -1
View File
@@ -63,7 +63,7 @@
*
* The $dumpvars task tells the simulation what variables to write to
* the VCD output. The first parameter is how far to descend while
* scanning a scope, and the remaining paramters are signals or scope
* scanning a scope, and the remaining parameters are signals or scope
* names to include in the dump. If a scope name is given, all the
* signals within the scope are dumped. If a wire or register name is
* given, that signal is included.
+4 -4
View File
@@ -20,7 +20,7 @@
*/
/*
* This module is a synthesizeable square-root function. It is also a
* This module is a synthesizable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other than to
* be excessively specific, I will step through the process of
@@ -30,7 +30,7 @@
* In addition to Icarus Verilog, you will need implementation
* software from Xilinx. As of this writing, this example was tested
* with Foundation 4.2i, but it should work the same with ISE and
* Webpack software.
* WebPACK software.
*
* This example source contains all the Verilog needed to do
* everything described below. We use conditional compilation to
@@ -55,7 +55,7 @@
* "PASSED" and finishes the simulation.
*
* When you take a close look at the "main" module below, you will see
* that it uses Verilog constructs that are not synthesizeable. This
* that it uses Verilog constructs that are not synthesizable. This
* is fine, as we will never try to synthesize it.
*
* LIBRARY PARTS
@@ -78,7 +78,7 @@
* Without any preprocessor directives, the only module is the sqrt32
* module, so sqrt32 is compiled as the root. The ports of the module
* are automatically made into ports of the sqrt32.edf netlist, and
* the contents of the sqrt32 module are connected approprately.
* the contents of the sqrt32 module are connected appropriately.
*
* COMPLETE CHIP DESIGNS
*
+303 -69
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,6 +18,7 @@
*/
# include "config.h"
# include "compiler.h"
# include <iostream>
@@ -25,6 +26,57 @@
# include "netmisc.h"
# include "ivl_assert.h"
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
{
NetNet* sig;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verireal vrl(tmp->value().as_double());
NetECReal rlval(vrl);
sig = rlval.synthesize(des);
} else {
cerr << obj->get_fileline() << ": sorry: Cannot convert "
"bit based value (" << *expr << ") to real." << endl;
des->errors += 1;
sig = 0;
}
return sig;
}
/* Note that lsig, rsig and real_args are references. */
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
NetNet*&lsig, NetNet*&rsig, bool&real_args,
NetExpr*obj)
{
if (left->expr_type() == IVL_VT_REAL ||
right->expr_type() == IVL_VT_REAL) {
real_args = true;
/* Currently we will have a runtime assert if both expressions
are not real, though we can convert constants. */
if (left->expr_type() == IVL_VT_REAL) {
lsig = left->synthesize(des);
} else {
lsig = convert_to_real_const(des, left, obj);
}
if (right->expr_type() == IVL_VT_REAL) {
rsig = right->synthesize(des);
} else {
rsig = convert_to_real_const(des, right, obj);
}
} else {
real_args = false;
lsig = left->synthesize(des);
rsig = right->synthesize(des);
}
if (lsig == 0 || rsig == 0) return true;
else return false;
}
NetNet* NetExpr::synthesize(Design*des)
{
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
@@ -40,8 +92,12 @@ NetNet* NetEBAdd::synthesize(Design*des)
{
assert((op()=='+') || (op()=='-'));
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet *lsig=0, *rsig=0;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
assert(expr_width() >= lsig->vector_width());
assert(expr_width() >= rsig->vector_width());
@@ -87,45 +143,53 @@ NetNet* NetEBBits::synthesize(Design*des)
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetScope*scope = lsig->scope();
assert(scope);
if (lsig == 0 || rsig == 0) return 0;
if (lsig->vector_width() != rsig->vector_width()) {
cerr << get_fileline() << ": internal error: bitwise (" << op_
<< ") widths do not match: " << lsig->vector_width()
<< " != " << rsig->vector_width() << endl;
cerr << get_fileline() << ": : width="
<< lsig->vector_width() << ": " << *left_ << endl;
cerr << get_fileline() << ": : width="
<< rsig->vector_width() << ": " << *right_ << endl;
/* You cannot do bitwise operations on real values. */
if (lsig->data_type() == IVL_VT_REAL ||
rsig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: " << human_readable_op(op_)
<< " operator may not have REAL operands." << endl;
des->errors += 1;
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
unsigned width = lsig->vector_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
assert(lsig->vector_width() == rsig->vector_width());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, lsig->vector_width());
NetNet::IMPLICIT, width);
osig->local_flag(true);
osig->data_type(expr_type());
perm_string oname = scope->local_symbol();
unsigned wid = lsig->vector_width();
NetLogic*gate;
switch (op()) {
case '&':
gate = new NetLogic(scope, oname, 3, NetLogic::AND, wid);
gate = new NetLogic(scope, oname, 3, NetLogic::AND, width);
break;
case 'A':
gate = new NetLogic(scope, oname, 3, NetLogic::NAND, width);
break;
case '|':
gate = new NetLogic(scope, oname, 3, NetLogic::OR, wid);
gate = new NetLogic(scope, oname, 3, NetLogic::OR, width);
break;
case '^':
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, wid);
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, width);
break;
case 'O':
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, wid);
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, width);
break;
case 'X':
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, wid);
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, width);
break;
default:
assert(0);
@@ -144,28 +208,38 @@ NetNet* NetEBBits::synthesize(Design*des)
NetNet* NetEBComp::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
if (real_args) {
width = 1;
} else {
width = lsig->vector_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
}
NetScope*scope = lsig->scope();
assert(scope);
unsigned width = lsig->vector_width();
if (rsig->vector_width() > width)
width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
bool signed_compare = lsig->get_signed() && rsig->get_signed();
/* Handle the special case of a single bit equality
operation. Make an XNOR gate instead of a comparator. */
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR, 1);
gate->set_line(*this);
@@ -179,7 +253,7 @@ NetNet* NetEBComp::synthesize(Design*des)
/* Handle the special case of a single bit inequality
operation. This is similar to single bit equality, but uses
an XOR instead of an XNOR gate. */
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR, 1);
gate->set_line(*this);
@@ -202,22 +276,38 @@ NetNet* NetEBComp::synthesize(Design*des)
switch (op_) {
case '<':
connect(dev->pin_ALB(), osig->pin(0));
dev->set_signed(signed_compare);
break;
case '>':
connect(dev->pin_AGB(), osig->pin(0));
dev->set_signed(signed_compare);
break;
case 'e': // ==
case 'E': // === ?
if (real_args) {
cerr << get_fileline() << ": error: Case equality may "
"not have real operands." << endl;
des->errors += 1;
return 0;
}
case 'e': // ==
connect(dev->pin_AEB(), osig->pin(0));
break;
case 'G': // >=
connect(dev->pin_AGEB(), osig->pin(0));
dev->set_signed(signed_compare);
break;
case 'L': // <=
connect(dev->pin_ALEB(), osig->pin(0));
dev->set_signed(signed_compare);
break;
case 'n': // !=
case 'N': // !==
if (real_args) {
cerr << get_fileline() << ": error: Case inequality may "
"not have real operands." << endl;
des->errors += 1;
return 0;
}
case 'n': // !=
connect(dev->pin_ANEB(), osig->pin(0));
break;
@@ -233,28 +323,60 @@ NetNet* NetEBComp::synthesize(Design*des)
NetNet* NetEBPow::synthesize(Design*des)
{
cerr << get_fileline() << ": internal error: Do not yet know how to handle"
<< " power operator in this context." << endl;
des->errors += 1;
return 0;
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
lsig->vector_width(),
rsig->vector_width());
des->add_node(powr);
powr->set_signed( has_sign() );
powr->set_line(*this);
connect(powr->pin_DataA(), lsig->pin(0));
connect(powr->pin_DataB(), rsig->pin(0));
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
connect(powr->pin_Result(), osig->pin(0));
return osig;
}
NetNet* NetEBMult::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
if (lsig == 0)
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
if (rsig == 0)
return 0;
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetMult*mult = new NetMult(scope, scope->local_symbol(),
expr_width(),
width,
lsig->vector_width(),
rsig->vector_width());
des->add_node(mult);
@@ -266,8 +388,7 @@ NetNet* NetEBMult::synthesize(Design*des)
connect(mult->pin_DataB(), rsig->pin(0));
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->data_type(lsig->data_type());
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
@@ -279,13 +400,21 @@ NetNet* NetEBMult::synthesize(Design*des)
NetNet* NetEBDiv::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->local_flag(true);
@@ -294,7 +423,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
case '/': {
NetDivide*div = new NetDivide(scope, scope->local_symbol(),
expr_width(),
width,
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
@@ -307,8 +436,16 @@ NetNet* NetEBDiv::synthesize(Design*des)
}
case '%': {
/* Baseline Verilog does not support the % operator with
real arguments, but we allow it in our extended form. */
if (real_args && !gn_icarus_misc_flag) {
cerr << get_fileline() << ": error: Modulus operator "
"may not have REAL operands." << endl;
des->errors += 1;
return 0;
}
NetModulo*div = new NetModulo(scope, scope->local_symbol(),
expr_width(),
width,
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
@@ -339,11 +476,16 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
if (lsig == 0)
return 0;
if (lsig == 0 || rsig == 0) return 0;
if (rsig == 0)
/* You cannot currently do logical operations on real values. */
if (lsig->data_type() == IVL_VT_REAL ||
rsig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": sorry: " << human_readable_op(op_)
<< " is currently unsupported for real values." << endl;
des->errors += 1;
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
@@ -411,17 +553,20 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetNet* NetEBShift::synthesize(Design*des)
{
if (! dynamic_cast<NetEConst*>(right_)) {
NetExpr*tmp = right_->eval_tree();
if (tmp) {
delete right_;
right_ = tmp;
}
}
eval_expr(right_);
NetNet*lsig = left_->synthesize(des);
if (lsig == 0)
if (lsig == 0) return 0;
/* Cannot shift a real values. */
if (lsig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: shift operator ("
<< human_readable_op(op_)
<< ") cannot shift a real values." << endl;
des->errors += 1;
return 0;
}
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
@@ -508,8 +653,8 @@ NetNet* NetEBShift::synthesize(Design*des)
}
NetNet*rsig = right_->synthesize(des);
if (rsig == 0)
return 0;
if (rsig == 0) return 0;
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
@@ -627,6 +772,16 @@ NetNet* NetEUBits::synthesize(Design*des)
{
NetNet*isig = expr_->synthesize(des);
if (isig == 0) return 0;
if (isig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: bit-wise negation ("
<< human_readable_op(op_)
<< ") may not have a REAL operand." << endl;
des->errors += 1;
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
@@ -659,6 +814,16 @@ NetNet* NetEUReduce::synthesize(Design*des)
{
NetNet*isig = expr_->synthesize(des);
if (isig == 0) return 0;
if (isig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: reduction operator ("
<< human_readable_op(op_)
<< ") may not have a REAL operand." << endl;
des->errors += 1;
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
@@ -710,8 +875,8 @@ NetNet* NetESelect::synthesize(Design *des)
{
NetNet*sub = expr_->synthesize(des);
if (sub == 0)
return 0;
if (sub == 0) return 0;
NetScope*scope = sub->scope();
@@ -764,6 +929,7 @@ NetNet* NetESelect::synthesize(Design *des)
connect(pad->pin(1), sub->pin(0));
connect(pad->pin(0), net->pin(0));
net->set_signed(true);
} else {
@@ -803,9 +969,27 @@ NetNet* NetESelect::synthesize(Design *des)
*/
NetNet* NetETernary::synthesize(Design *des)
{
NetNet*csig = cond_->synthesize(des);
NetNet*tsig = true_val_->synthesize(des);
NetNet*fsig = false_val_->synthesize(des);
NetNet*csig = cond_->synthesize(des),
*tsig = true_val_->synthesize(des),
*fsig = false_val_->synthesize(des);
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
if (tsig->data_type() != fsig->data_type()) {
cerr << get_fileline() << ": error: True and False clauses of "
"ternary expression have different types." << endl;
cerr << get_fileline() << ": : True clause is: "
<< tsig->data_type() << endl;
cerr << get_fileline() << ": : False clause is: "
<< fsig->data_type() << endl;
des->errors += 1;
return 0;
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
cerr << get_fileline() << ": internal error: True and False "
"clauses of ternary both have NO TYPE." << endl;
des->errors += 1;
return 0;
}
perm_string path = csig->scope()->local_symbol();
@@ -876,3 +1060,53 @@ NetNet* NetESignal::synthesize(Design*des)
}
return tmp;
}
NetNet* NetESFunc::synthesize(Design*des)
{
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
<< *this << " in this context" << endl;
des->errors += 1;
return 0;
}
NetNet* NetEUFunc::synthesize(Design*des)
{
svector<NetNet*> eparms (parms_.count());
/* Synthesize the arguments. */
bool errors = false;
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
NetNet*tmp = parms_[idx]->synthesize(des);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to synthesize "
"port " << idx << " of call to "
<< func_->basename() << "." << endl;
errors = true;
des->errors += 1;
continue;
}
eparms[idx] = tmp;
}
if (errors) return 0;
NetUserFunc*net = new NetUserFunc(scope_, scope_->local_symbol(), func_);
net->set_line(*this);
des->add_node(net);
/* Create an output signal and connect it to the function. */
NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE,
result_sig_->vector_width());
osig->local_flag(true);
osig->data_type(result_sig_->expr_type());
connect(net->pin(0), osig->pin(0));
/* Connect the pins to the arguments. */
NetFuncDef*def = func_->func_def();
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
NetNet*tmp = pad_to_width(des, eparms[idx],
def->port(idx)->vector_width());
connect(net->pin(idx+1), tmp->pin(0));
}
return osig;
}
+1 -1
View File
@@ -59,7 +59,7 @@ types as nets.
- Ports
Module and task ports in standard verilog are restricted to logic
Module and task ports in standard Verilog are restricted to logic
types. This extension removes that restriction, allowing any type to
pass through the port consistent with the continuous assignment
connectivity that is implied by the type.
+19 -58
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.cc,v 1.35 2005/07/07 16:22:49 steve Exp $"
#endif
# include "config.h"
@@ -43,6 +40,10 @@ void functor_t::process(class Design*, class NetProcTop*)
{
}
void functor_t::lpm_abs(class Design*, class NetAbs*)
{
}
void functor_t::lpm_add_sub(class Design*, class NetAddSub*)
{
}
@@ -83,6 +84,10 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
{
}
void functor_t::lpm_pow(class Design*, class NetPow*)
{
}
void functor_t::sign_extend(class Design*, class NetSignExtend*)
{
}
@@ -173,6 +178,11 @@ void NetNode::functor_node(Design*, functor_t*)
{
}
void NetAbs::functor_node(Design*des, functor_t*fun)
{
fun->lpm_abs(des, this);
}
void NetAddSub::functor_node(Design*des, functor_t*fun)
{
fun->lpm_add_sub(des, this);
@@ -223,6 +233,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
fun->lpm_mux(des, this);
}
void NetPow::functor_node(Design*des, functor_t*fun)
{
fun->lpm_pow(des, this);
}
void NetSignExtend::functor_node(Design*des, functor_t*fun)
{
fun->sign_extend(des, this);
@@ -291,57 +306,3 @@ int proc_match_t::event_wait(NetEvWait*)
{
return 0;
}
/*
* $Log: functor.cc,v $
* Revision 1.35 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.34 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.33 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.32 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
* Revision 1.31 2002/08/16 05:18:27 steve
* Fix intermix of node functors and node delete.
*
* Revision 1.30 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.29 2002/08/10 22:07:38 steve
* Remove useless error messages.
*
* Revision 1.28 2002/06/05 03:44:25 steve
* Add support for memory words in l-value of
* non-blocking assignments, and remove the special
* NetAssignMem_ and NetAssignMemNB classes.
*
* Revision 1.27 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.26 2001/10/19 21:53:24 steve
* Support multiple root modules (Philip Blundell)
*
* Revision 1.25 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.24 2000/11/19 20:48:30 steve
* Fix cases where signal iteration might die early.
*
* Revision 1.23 2000/11/18 04:53:04 steve
* Watch out in functor, it may delete the last signal.
*
* Revision 1.22 2000/09/17 21:26:15 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.21 2000/08/01 02:48:41 steve
* Support <= in synthesis of DFF and ram devices.
*/
+7 -44
View File
@@ -1,7 +1,7 @@
#ifndef __functor_H
#define __functor_H
/*
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.h,v 1.23 2005/07/07 16:22:49 steve Exp $"
#endif
/*
* The functor is an object that can be applied to a design to
@@ -51,6 +48,9 @@ struct functor_t {
/* This method is called for each process in the design. */
virtual void process(class Design*des, class NetProcTop*);
/* This method is called for each structural abs(). */
virtual void lpm_abs(class Design*des, class NetAbs*);
/* This method is called for each structural adder. */
virtual void lpm_add_sub(class Design*des, class NetAddSub*);
@@ -81,6 +81,9 @@ struct functor_t {
/* This method is called for each MUX. */
virtual void lpm_mux(class Design*des, class NetMux*);
/* This method is called for each power. */
virtual void lpm_pow(class Design*des, class NetPow*);
/* This method is called for each unary reduction gate. */
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
@@ -97,44 +100,4 @@ struct proc_match_t {
virtual int block(class NetBlock*);
};
/*
* $Log: functor.h,v $
* Revision 1.23 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.22 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.21 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.20 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.19 2002/06/05 03:44:25 steve
* Add support for memory words in l-value of
* non-blocking assignments, and remove the special
* NetAssignMem_ and NetAssignMemNB classes.
*
* Revision 1.18 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.17 2000/09/17 21:26:15 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.16 2000/08/01 02:48:42 steve
* Support <= in synthesis of DFF and ram devices.
*
* Revision 1.15 2000/07/16 04:56:07 steve
* Handle some edge cases during node scans.
*
* Revision 1.14 2000/07/15 05:13:44 steve
* Detect muxing Vz as a bufufN.
*
* Revision 1.13 2000/04/20 00:28:03 steve
* Catch some simple identity compareoptimizations.
*/
#endif
+2 -18
View File
@@ -26,20 +26,9 @@ CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
# These are used for linking...
LD=$CC
LDFLAGS32="@SHARED@ -L@LIBDIR@"
LDFLAGS64="@SHARED@ -L@LIBDIR64@"
LDFLAGS="$LDFLAGS64"
LDFLAGS="@SHARED@ -L@LIBDIR@"
LDLIBS="-lveriuser -lvpi"
INSTDIR64="@VPIDIR1@"
INSTDIR32="@VPIDIR2@"
if test x$INSTDIR32 = x
then
INSTDIR32=$INSTDIR64
fi
INSTDIR="$INSTDIR64"
CCSRC=
CXSRC=
OBJ=
@@ -96,11 +85,6 @@ do
-D*) DEFS="$DEFS $parm"
;;
-m32) LDFLAGS="-m32 $LDFLAGS32"
CFLAGS="-m32 $CFLAGS"
INSTDIR="$INSTDIR32"
;;
--cflags)
echo "$CFLAGS"
exit;
@@ -117,7 +101,7 @@ do
;;
--install-dir)
echo "@LIBDIR@/ivl/$INSTDIR"
echo "@LIBDIR@/ivl"
exit
;;
esac
+30
View File
@@ -9,6 +9,7 @@ ivl_design_roots
ivl_design_time_precision
ivl_const_bits
ivl_const_delay
ivl_const_real
ivl_const_signed
ivl_const_type
@@ -52,6 +53,9 @@ ivl_file_table_index
ivl_file_table_item
ivl_file_table_size
ivl_island_flag_set
ivl_island_flag_test
ivl_logic_attr
ivl_logic_attr_cnt
ivl_logic_attr_val
@@ -77,6 +81,7 @@ ivl_lpm_clk
ivl_lpm_data
ivl_lpm_datab
ivl_lpm_define
ivl_lpm_delay
ivl_lpm_enable
ivl_lpm_file
ivl_lpm_lineno
@@ -113,12 +118,16 @@ ivl_nexus_ptr_pin
ivl_nexus_ptr_lpm
ivl_nexus_ptr_log
ivl_nexus_ptr_sig
ivl_nexus_ptr_switch
ivl_parameter_basename
ivl_parameter_expr
ivl_parameter_file
ivl_parameter_lineno
ivl_path_condit
ivl_path_delay
ivl_path_is_condit
ivl_path_scope
ivl_path_source
ivl_path_source_negedge
@@ -129,8 +138,12 @@ ivl_scope_attr_val
ivl_scope_basename
ivl_scope_children
ivl_scope_def
ivl_scope_def_file
ivl_scope_def_lineno
ivl_scope_event
ivl_scope_events
ivl_scope_file
ivl_scope_lineno
ivl_scope_logs
ivl_scope_log
ivl_scope_lpms
@@ -143,6 +156,8 @@ ivl_scope_port
ivl_scope_ports
ivl_scope_sigs
ivl_scope_sig
ivl_scope_switch
ivl_scope_switches
ivl_scope_time_precision
ivl_scope_time_units
ivl_scope_type
@@ -156,7 +171,9 @@ ivl_signal_attr_val
ivl_signal_basename
ivl_signal_data_type
ivl_signal_dimensions
ivl_signal_file
ivl_signal_integer
ivl_signal_lineno
ivl_signal_local
ivl_signal_lsb
ivl_signal_msb
@@ -205,6 +222,19 @@ ivl_stmt_parm_count
ivl_stmt_rval
ivl_stmt_sub_stmt
ivl_switch_a
ivl_switch_b
ivl_switch_basename
ivl_switch_enable
ivl_switch_file
ivl_switch_island
ivl_switch_lineno
ivl_switch_offset
ivl_switch_part
ivl_switch_scope
ivl_switch_type
ivl_switch_width
ivl_udp_init
ivl_udp_name
ivl_udp_nin
+149 -20
View File
@@ -1,7 +1,7 @@
#ifndef __ivl_target_H
#define __ivl_target_H
/*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.182 2007/04/02 01:12:34 steve Exp $"
#endif
# include <inttypes.h>
@@ -83,6 +80,13 @@ _BEGIN_DECL
* processes. Structural expressions are instead treated as logic
* gates.
*
* ivl_island_t
* Certain types of objects may belong to islands. The island that
* they belong to is represented by the ivl_island_t cookie. To
* know if object belong to the same island, it is sufficient to
* compare island cookies. If a==b, then island a is the same as
* island b.
*
* ivl_lpm_t
* This object is the base class for all the various LPM type
* device nodes. This object carries a few base properties
@@ -126,6 +130,9 @@ _BEGIN_DECL
* ivl_process_t object holds one of these, but a statement may in
* turn contain other statements.
*
* ivl_switch_t
* Switches are the tran/tranif devices in the design.
*
* -- A Note About Bit Sets --
* Some objects hold a value as an array of bits. In these cases there
* is some method that retrieves the width of the value and another
@@ -146,6 +153,7 @@ typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
typedef struct ivl_event_s *ivl_event_t;
typedef struct ivl_expr_s *ivl_expr_t;
typedef struct ivl_island_s *ivl_island_t;
typedef struct ivl_lpm_s *ivl_lpm_t;
typedef struct ivl_lval_s *ivl_lval_t;
typedef struct ivl_net_const_s*ivl_net_const_t;
@@ -158,6 +166,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
typedef struct ivl_process_s *ivl_process_t;
typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_signal_s *ivl_signal_t;
typedef struct ivl_switch_s *ivl_switch_t;
typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */
typedef struct ivl_statement_s*ivl_statement_t;
@@ -229,8 +238,20 @@ typedef enum ivl_logic_e {
IVL_LO_UDP = 21
} ivl_logic_t;
/* This is the type of a ivl_switch_t object */
typedef enum ivl_switch_type_e {
IVL_SW_TRAN = 0,
IVL_SW_TRANIF0 = 1,
IVL_SW_TRANIF1 = 2,
IVL_SW_RTRAN = 3,
IVL_SW_RTRANIF0 = 4,
IVL_SW_RTRANIF1 = 5,
IVL_SW_TRAN_VP = 6
} ivl_switch_type_t;
/* This is the type of an LPM object. */
typedef enum ivl_lpm_type_e {
IVL_LPM_ABS = 32,
IVL_LPM_ADD = 0,
IVL_LPM_ARRAY = 30,
IVL_LPM_CONCAT = 16,
@@ -245,9 +266,10 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5,
IVL_LPM_PART_BI= 28, /* part select: bi-directional (part on 0) */
/* IVL_LPM_PART_BI= 28, / obsolete */
IVL_LPM_PART_VP= 15, /* part select: vector to part */
IVL_LPM_PART_PV= 17, /* part select: part written to vector */
IVL_LPM_POW = 31,
IVL_LPM_RE_AND = 20,
IVL_LPM_RE_NAND= 21,
IVL_LPM_RE_NOR = 22,
@@ -382,7 +404,7 @@ typedef const struct ivl_attribute_s*ivl_attribute_t;
/* DELAYPATH
* Delaypath objects represent delay paths called out by a specify
* block in the verilog source file. The destination signal references
* block in the Verilog source file. The destination signal references
* the path object, which in turn points to the source for the path.
*
* ivl_path_scope
@@ -397,8 +419,10 @@ typedef const struct ivl_attribute_s*ivl_attribute_t;
* ivl_path_condit
* This returns the nexus that tracks the condition for the
* delay. If the delay path is unconditional, this returns nil.
* ivl_path_is_condit
* Is this a conditional structure? Needed for ifnone.
*
* ivl_path_srouce_posedge
* ivl_path_source_posedge
* ivl_path_source_negedge
* These functions return true if the source is edge sensitive.
*/
@@ -406,6 +430,7 @@ extern ivl_scope_t ivl_path_scope(ivl_delaypath_t obj);
extern ivl_nexus_t ivl_path_source(ivl_delaypath_t obj);
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt);
extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj);
extern int ivl_path_is_condit(ivl_delaypath_t obj);
extern int ivl_path_source_posedge(ivl_delaypath_t obj);
extern int ivl_path_source_negedge(ivl_delaypath_t obj);
@@ -472,7 +497,7 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
* The is the type of the node.
*
* ivl_const_bits
* This returns a pointer to an array of conststant characters,
* This returns a pointer to an array of constant characters,
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
* terminated.
*
@@ -485,6 +510,9 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
* ivl_const_width
* Return the width, in logical bits, of the constant.
*
* ivl_const_delay
* T0 delay for a transition (0, 1 and Z).
*
* SEMANTIC NOTES
*
* The const_type of the literal constant must match the
@@ -500,6 +528,7 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
*/
extern ivl_variable_type_t ivl_const_type(ivl_net_const_t net);
extern const char* ivl_const_bits(ivl_net_const_t net);
extern ivl_expr_t ivl_const_delay(ivl_net_const_t net, unsigned transition);
extern ivl_nexus_t ivl_const_nex(ivl_net_const_t net);
extern int ivl_const_signed(ivl_net_const_t net);
extern unsigned ivl_const_width(ivl_net_const_t net);
@@ -693,6 +722,16 @@ extern unsigned ivl_file_table_index(const char *);
extern unsigned ivl_file_table_size(void);
/* ISLAND
*
* ivl_island_flag_set
* ivl_island_flag_test
* Allow the user to test or set a boolean flag associated with the
* island.
*/
extern int ivl_island_flag_set(ivl_island_t net, unsigned flag, int value);
extern int ivl_island_flag_test(ivl_island_t net, unsigned flag);
/* LOGIC
* These types and functions support manipulation of logic gates. The
* ivl_logic_t enumeration identifies the various kinds of gates that
@@ -746,7 +785,7 @@ extern unsigned ivl_file_table_size(void);
* SEMANTIC NOTES
* The ivl_logic_width applies to all the pins of a logic device. If a
* logic device has width, that means that it is actually an array of
* logic devices tha each process a bit slice of the
* logic devices that each process a bit slice of the
* inputs/output. That implies that the widths of all the inputs and
* the output must be identical.
*
@@ -870,6 +909,9 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* Return the name of the device. The name is the name of the
* device with the scope part, and the basename is without the scope.
*
* ivl_lpm_delay
* LPM devices have a delay for each transition (0, 1 and Z).
*
* ivl_lpm_scope
* LPM devices exist within a scope. Return the scope that contains
* this device.
@@ -925,7 +967,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* The ivl_lpm_q nexus is the output from the concatenation.
*
* The ivl_lpm_data function returns the connections for the inputs to
* the concatentation. The ivl_lpm_size function returns the number of
* the concatenation. The ivl_lpm_size function returns the number of
* inputs help by the device.
*
* - Divide (IVL_LPM_DIVIDE)
@@ -947,6 +989,16 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* Multiply may be signed. If so, the output should be sign extended
* to fill in its result.
*
* - Power (IVL_LPM_POW)
* The power takes two inputs and generates an output. Unlike other
* arithmetic nodes, the width only refers to the output. The inputs
* have independent widths, to reflect the arithmetic truth that the
* width of a general power is the XXXX of the widths of the
* inputs.
*
* Power may be signed. If so, the output should be sign extended
* to fill in its result.
*
* - Part Select (IVL_LPM_PART_VP and IVL_LPM_PART_PV)
* There are two part select devices, one that extracts a part from a
* vector, and another that writes a part of a vector. The _VP is
@@ -999,7 +1051,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* The ivl_lpm_data() method returns the inputs of the MUX device. The
* ivl_lpm_size() method returns the number of data inputs there
* are. All the data inputs have the same width, the width of the
* ivl_lpm_q output. The type of the device is devined from the
* ivl_lpm_q output. The type of the device is divined from the
* inputs and the Q. All the types must be exactly the same.
*
* - D-FlipFlop (IVL_LPM_FF)
@@ -1052,7 +1104,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* output, but the distance has its own width.
*
* The ivl_lpm_signed() flag means for IVL_LPM_SHIFTR that the right
* shift is *signed*. For SHIFTL, then signed-ness is emaningless.
* shift is *signed*. For SHIFTL, then signed-ness is meaningless.
*
* - System function call (IVL_LPM_SFUNC)
* This device represents a netlist call to a system function. The
@@ -1073,8 +1125,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* function are connected to the net, as is the output.
*
* The function definition is associated with a scope, and the
* ivl_lpm_define fuction returns the scope that is that definition.
* See the ivl_scope_* fuctions for how to get at the actual
* ivl_lpm_define function returns the scope that is that definition.
* See the ivl_scope_* functions for how to get at the actual
* definition.
*
* As with many LPM nodes, the ivl_lpm_q function returns the nexus
@@ -1089,6 +1141,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
extern const char* ivl_lpm_basename(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_delay(ivl_lpm_t net, unsigned transition);
extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net);
extern int ivl_lpm_signed(ivl_lpm_t net);
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
@@ -1112,12 +1165,12 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_UFUNC */
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_MULT IVL_LPM_POW IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
IVL_LPM_SUB IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX */
@@ -1173,7 +1226,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
* SEMANTIC NOTES
* The ivl_lval_width is not necessarily the same as the width of the
* signal or memory word it represents. It is the width of the vector
* it receives and assigns. This may be less then the width of the
* it receives and assigns. This may be less than the width of the
* signal (or even 1) if only a part of the l-value signal is to be
* assigned.
*
@@ -1192,7 +1245,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
* an expression that calculates the address of the array word. If
* the referenced signal has more than one word, this expression must
* be present. If the signal has exactly one word (it is not an array)
* then the ivl_lval_idx exression must *not* be present.
* then the ivl_lval_idx expression must *not* be present.
*
* For array words, the ivl_lval_width is the width of the word.
*/
@@ -1293,6 +1346,7 @@ extern unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net);
extern ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net);
extern ivl_net_logic_t ivl_nexus_ptr_log(ivl_nexus_ptr_t net);
extern ivl_lpm_t ivl_nexus_ptr_lpm(ivl_nexus_ptr_t net);
extern ivl_switch_t ivl_nexus_ptr_switch(ivl_nexus_ptr_t net);
extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
/* PARAMETER
@@ -1320,11 +1374,18 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* ivl_parameter_expr
* Return the value of the parameter. This should be a simple
* constant expression, an IVL_EX_STRING or IVL_EX_NUMBER.
*
* ivl_parameter_file
* ivl_parameter_lineno
* Returns the file and line where this parameter is define
*/
extern const char* ivl_parameter_basename(ivl_parameter_t net);
extern ivl_scope_t ivl_parameter_scope(ivl_parameter_t net);
extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
extern const char* ivl_parameter_file(ivl_parameter_t net);
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
/* SCOPE
* Scopes of various sort have these properties. Use these methods to
@@ -1372,10 +1433,18 @@ extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
* ivl_scope_def function must return a statement for scopes that
* are type FUNCTION or TASK, and must return nil otherwise.
*
* ivl_scope_def_file
* ivl_scope_def_lineno
* Returns the file and line where this scope is defined.
*
* ivl_scope_event
* ivl_scope_events
* Scopes have 0 or more event objects in them.
*
* ivl_scope_file
* ivl_scope_lineno
* Returns the instantiation file and line for this scope.
*
* ivl_scope_var
* ivl_scope_vars
* REMOVED
@@ -1446,9 +1515,13 @@ extern int ivl_scope_children(ivl_scope_t net,
ivl_scope_f func, void*cd);
extern ivl_statement_t ivl_scope_def(ivl_scope_t net);
extern const char* ivl_scope_def_file(ivl_scope_t net);
extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
extern unsigned ivl_scope_events(ivl_scope_t net);
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
extern const char* ivl_scope_file(ivl_scope_t net);
extern unsigned ivl_scope_lineno(ivl_scope_t net);
extern unsigned ivl_scope_logs(ivl_scope_t net);
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_lpms(ivl_scope_t net);
@@ -1462,6 +1535,8 @@ extern unsigned ivl_scope_ports(ivl_scope_t net);
extern ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_sigs(ivl_scope_t net);
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_switches(ivl_scope_t net);
extern ivl_switch_t ivl_scope_switch(ivl_scope_t net, unsigned idx);
extern ivl_scope_type_t ivl_scope_type(ivl_scope_t net);
extern const char* ivl_scope_tname(ivl_scope_t net);
extern int ivl_scope_time_precision(ivl_scope_t net);
@@ -1488,7 +1563,7 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* ivl_signal_array_count
* The signal may be arrayed. If so, the array_count is >1. Each
* word of the array has its own nexus. The array_base is the
* address is the Verilg source for the canonical zero word. This
* address is the Verilog source for the canonical zero word. This
* may be negative, positive or zero.
*
* Note that arraying of the signal into words is distinct from the
@@ -1555,6 +1630,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* the attribute value (a string) associated with a key. This
* function returns the attribute value for the given key. If the
* key does not exist, the function returns 0.
*
* ivl_signal_file
* ivl_signal_lineno
* Returns the file and line where this signal is defined.
*/
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
@@ -1576,6 +1655,9 @@ extern const char* ivl_signal_name(ivl_signal_t net);
extern const char* ivl_signal_basename(ivl_signal_t net);
extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
extern const char* ivl_signal_file(ivl_signal_t net);
extern unsigned ivl_signal_lineno(ivl_signal_t net);
extern unsigned ivl_signal_attr_cnt(ivl_signal_t net);
extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
@@ -1780,6 +1862,53 @@ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
IVL_ST_WAIT, IVL_ST_WHILE */
extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
/* SWITCHES
*
* The switches represent the tran devices in the design.
*
* FUNCTION SUMMARY
*
* ivl_switch_type
* Return the enumerated value that is the type of the switch.
*
* ivl_switch_basename
* This is the name given to the device in the source code.
*
* ivl_switch_a
* ivl_switch_b
* The a and b ports are the two ports of the switch.
*
* ivl_switch_enable
* If the device has an enable (tranifX) then this is the enable
* port.
*
* SEMANTIC NOTES
* The a/b ports can be any type, but the types must exactly
* match, including vector widths. The enable must be a scalar.
*
* The IVL_SW_TRAN_VP is an exception to the above. In this case,
* the B side may be a different size, and the a side will have a
* a fixed width. The unused bits are padded to Z on the A side.
*/
extern ivl_switch_type_t ivl_switch_type(ivl_switch_t net);
extern ivl_scope_t ivl_switch_scope(ivl_switch_t net);
extern const char*ivl_switch_basename(ivl_switch_t net);
extern ivl_nexus_t ivl_switch_a(ivl_switch_t net);
extern ivl_nexus_t ivl_switch_b(ivl_switch_t net);
extern ivl_nexus_t ivl_switch_enable(ivl_switch_t net);
extern ivl_island_t ivl_switch_island(ivl_switch_t net);
/* These are only support for IVL_SW_TRAN_VP switches. */
extern unsigned ivl_switch_width(ivl_switch_t net);
extern unsigned ivl_switch_part(ivl_switch_t net);
extern unsigned ivl_switch_offset(ivl_switch_t net);
/* Not implemented yet
extern unsigned ivl_switch_attr_cnt(ivl_switch_t net);
extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
*** */
extern const char* ivl_switch_file(ivl_switch_t net);
extern unsigned ivl_switch_lineno(ivl_switch_t net);
#if defined(__MINGW32__) || defined (__CYGWIN32__)
# define DLLEXPORT __declspec(dllexport)
+44
View File
@@ -0,0 +1,44 @@
#ifndef __ivl_target_priv_H
#define __ivl_target_H
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <inttypes.h>
/*
* This deader has declarations related to the ivl_target.h API that
* are not to be exported outside of the core via the ivl_target.h
* interface.
*/
/*
* Information about islands. Connected branches within a net are
* collected into islands. Branches that are purely ddiscrete do not
* have disciplines and do not belong to islands.
*/
class discipline_t;
struct ivl_island_s {
discipline_t*discipline;
// user accessible flags. They are initially false, always.
vector<bool> flags;
};
#endif
-3
View File
@@ -1,6 +1,3 @@
lexor.c
parse.c
parse.h
parse.output
Makefile
ivlpp
+3 -7
View File
@@ -47,12 +47,12 @@ LDFLAGS = @LDFLAGS@
all: ivlpp@EXEEXT@
clean:
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp@EXEEXT@
rm -f *.o lexor.c ivlpp@EXEEXT@
distclean: clean
rm -f Makefile
O = main.o lexor.o parse.o
O = main.o lexor.o
ivlpp@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
@@ -60,9 +60,6 @@ ivlpp@EXEEXT@: $O
lexor.c: lexor.lex
flex -olexor.c $(srcdir)/lexor.lex
parse.h parse.c: parse.y
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
@@ -74,6 +71,5 @@ installdirs: ../mkinstalldirs
uninstall:
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
lexor.o: lexor.c parse.h globals.h
lexor.o: lexor.c globals.h
main.o: main.c globals.h
parse.o: parse.c
+2 -2
View File
@@ -39,7 +39,7 @@ extern unsigned error_count;
extern FILE *depend_file;
/* This is the entry to the parser. */
extern int yyparse();
/* This is the entry to the lexer. */
extern int yylex();
#endif
+1 -1
View File
@@ -19,7 +19,7 @@
THE IVL PREPROCESSOR
The ivlpp command is a verilog preprocessor that handles file
The ivlpp command is a Verilog preprocessor that handles file
inclusion and macro substitution. The program runs separate from the
actual compiler so as to ease the task of the compiler proper, and
provides a means of preprocessing files off-line.
+1207 -917
View File
File diff suppressed because it is too large Load Diff
+24 -20
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2007 Stephen Williams ([email protected])";
"Copyright (c) 1999-2008 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -202,23 +202,27 @@ int main(int argc, char*argv[])
FILE*precomp_out = NULL;
/* Define preprocessor keywords that I plan to just pass. */
define_macro("celldefine", "`celldefine", 1, 0);
define_macro("default_nettype", "`default_nettype", 1, 0);
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
define_macro("endcelldefine", "`endcelldefine", 1, 0);
define_macro("endprotect", "`endprotect", 1, 0);
define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
define_macro("protect", "`protect", 1, 0);
define_macro("resetall", "`resetall", 1, 0);
define_macro("suppress_faults", "`suppress_faults", 1, 0);
define_macro("timescale", "`timescale", 1, 0);
define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
define_macro("uselib", "`uselib", 1, 0);
define_macro("celldefine", "`celldefine", 1, 0);
define_macro("default_decay_time", "`default_decay_time", 1, 0);
define_macro("default_nettype", "`default_nettype", 1, 0);
define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0);
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0);
define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
define_macro("endcelldefine", "`endcelldefine", 1, 0);
define_macro("endprotect", "`endprotect", 1, 0);
define_macro("line", "`line", 1, 0);
define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
define_macro("protect", "`protect", 1, 0);
define_macro("resetall", "`resetall", 1, 0);
define_macro("suppress_faults", "`suppress_faults", 1, 0);
define_macro("timescale", "`timescale", 1, 0);
define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
define_macro("uselib", "`uselib", 1, 0);
include_cnt = 2;
include_dir = malloc(include_cnt*sizeof(char*));
@@ -352,9 +356,9 @@ int main(int argc, char*argv[])
}
/* Pass to the lexical analyzer the list of input file, and
start the parser. */
start scanning. */
reset_lexor(out, source_list);
if (yyparse()) return -1;
if (yylex()) return -1;
if(depend_file) {
fclose(depend_file);
+142 -33
View File
@@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1998-2007 Stephen Williams ([email protected])
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -34,7 +34,8 @@
# include <ctype.h>
# include <string.h>
# include "lexor_keyword.h"
# include "discipline.h"
# include <list>
# define YY_USER_INIT reset_lexor();
# define yylval VLlval
@@ -48,6 +49,11 @@
*/
extern YYLTYPE yylloc;
static char* strdupnew(char const *str)
{
return str ? strcpy(new char [strlen(str)+1], str) : 0;
}
static const char* set_file_name(char*text)
{
perm_string path = filename_strings.make(text);
@@ -78,6 +84,8 @@ static int dec_buf_div2(char *buf);
static void process_timescale(const char*txt);
static list<int> keyword_mask_stack;
static int comment_enter;
%}
@@ -88,10 +96,14 @@ static int comment_enter;
%s UDPTABLE
%x PPTIMESCALE
%x PPDEFAULT_NETTYPE
%x PPBEGIN_KEYWORDS
%s EDGES
%x REAL_SCALE
W [ \t\b\f\r]+
S [afpnumkKMGT]
%%
^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
@@ -141,6 +153,7 @@ W [ \t\b\f\r]+
"->" { return K_TRIGGER; }
"+:" { return K_PO_POS; }
"-:" { return K_PO_NEG; }
"<+" { return K_CONTRIBUTE; }
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
and ")", but since I know that this is really ( * ), replace it
@@ -205,22 +218,11 @@ W [ \t\b\f\r]+
int rc = lexor_keyword_code(yytext, yyleng);
switch (rc) {
case IDENTIFIER:
yylval.text = strdup(yytext);
yylval.text = strdupnew(yytext);
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
rc = PATHPULSE_IDENTIFIER;
break;
case K_bool:
case K_logic:
case K_wone:
if (! gn_cadence_types_enabled()) {
yylval.text = strdup(yytext);
rc = IDENTIFIER;
} else {
yylval.text = 0;
}
break;
case K_edge:
BEGIN(EDGES);
break;
@@ -230,12 +232,24 @@ W [ \t\b\f\r]+
break;
}
/* If this identifier names a discipline, then return this as
a DISCIPLINE_IDENTIFIER and return the discipline as the
value instead. */
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
perm_string tmp = lex_strings.make(yylval.text);
map<perm_string,discipline_t*>::iterator cur = disciplines.find(tmp);
if (cur != disciplines.end()) {
yylval.discipline = (*cur).second;
rc = DISCIPLINE_IDENTIFIER;
}
}
return rc;
}
}
\\[^ \t\b\f\r\n]+ {
yylval.text = strdup(yytext+1);
yylval.text = strdupnew(yytext+1);
return IDENTIFIER; }
\$([a-zA-Z0-9$_]+) {
@@ -255,7 +269,7 @@ W [ \t\b\f\r]+
return K_Ssetup;
if (strcmp(yytext,"$width") == 0)
return K_Swidth;
yylval.text = strdup(yytext);
yylval.text = strdupnew(yytext);
return SYSTEM_IDENTIFIER; }
@@ -275,6 +289,46 @@ W [ \t\b\f\r]+
based_size = yylval.number->as_ulong();
return DEC_NUMBER; }
/* These rules handle the scaled real literals from Verilog-AMS. The
value is a number with a single letter scale factor. If
verilog-ams is not enabled, then reject this rule. If it is
enabled, then collect the scale and use it to scale the value. */
[0-9][0-9_]*\.[0-9][0-9_]*/{S} {
if (!gn_verilog_ams_flag) REJECT;
BEGIN(REAL_SCALE);
yymore(); }
[0-9][0-9_]*/{S} {
if (!gn_verilog_ams_flag) REJECT;
BEGIN(REAL_SCALE);
yymore(); }
<REAL_SCALE>{S} {
size_t token_len = strlen(yytext);
char*tmp = new char[token_len + 5];
int scale = 0;
strcpy(tmp, yytext);
switch (tmp[token_len-1]) {
case 'a': scale = -18; break; /* atto- */
case 'f': scale = -15; break; /* femto- */
case 'p': scale = -12; break; /* pico- */
case 'n': scale = -9; break; /* nano- */
case 'u': scale = -6; break; /* micro- */
case 'm': scale = -3; break; /* milli- */
case 'k': scale = 3; break; /* kilo- */
case 'K': scale = 3; break; /* kilo- */
case 'M': scale = 6; break; /* mega- */
case 'G': scale = 9; break; /* giga- */
case 'T': scale = 12; break; /* tera- */
default: assert(0); break;
}
snprintf(tmp+token_len-1, 5, "e%d", scale);
yylval.realtime = new verireal(tmp);
delete[]tmp;
BEGIN(0);
return REALTIME; }
[0-9][0-9_]*\.[0-9][0-9_]*([Ee][+-]?[0-9][0-9_]*)? {
yylval.realtime = new verireal(yytext);
return REALTIME; }
@@ -296,21 +350,76 @@ W [ \t\b\f\r]+
/* These are directives that I do not yet support. I think that IVL
should handle these, not an external preprocessor. */
^{W}?`celldefine{W}?.* { }
^{W}?`celldefine{W}?.* { }
^{W}?`default_decay_time{W}?.* { }
^{W}?`default_trireg_strength{W}?.* { }
^{W}?`delay_mode_distributed{W}?.* { }
^{W}?`delay_mode_unit{W}?.* { }
^{W}?`delay_mode_path{W}?.* { }
^{W}?`disable_portfaults{W}?.* { }
^{W}?`enable_portfaults{W}?.* { }
^{W}?`endcelldefine{W}?.* { }
`endprotect { }
^{W}?`nosuppress_faults{W}?.* { }
^{W}?`nounconnected_drive{W}?.* { }
`protect { }
^{W}?`resetall{W}?.* { }
^{W}?`suppress_faults{W}?.* { }
^{W}?`unconnected_drive{W}?.* { }
^{W}?`uselib{W}?.* { }
^{W}?`delay_mode_unit{W}?.* { }
^{W}?`delay_mode_path{W}?.* { }
^{W}?`delay_mode_zero{W}?.* { }
^{W}?`disable_portfaults{W}?.* { }
^{W}?`enable_portfaults{W}?.* { }
^{W}?`endcelldefine{W}?.* { }
`endprotect { }
^{W}?`line{W}?.* { }
^{W}?`nosuppress_faults{W}?.* { }
^{W}?`nounconnected_drive{W}?.* { }
`protect { }
^{W}?`resetall{W}?.* { }
^{W}?`suppress_faults{W}?.* { }
^{W}?`unconnected_drive{W}?.* { }
^{W}?`uselib{W}?.* { }
^{W}?`begin_keywords{W}? { BEGIN(PPBEGIN_KEYWORDS); }
<PPBEGIN_KEYWORDS>\"[a-zA-Z0-9 -]*\".* {
keyword_mask_stack.push_front(lexor_keyword_mask);
char*word = yytext+1;
char*tail = strchr(word, '"');
tail[0] = 0;
if (strcmp(word,"1364-1995") == 0) {
lexor_keyword_mask = GN_KEYWORDS_1364_1995;
} else if (strcmp(word,"1364-2001") == 0) {
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|GN_KEYWORDS_1364_2001
|GN_KEYWORDS_1364_2001_CONFIG;
} else if (strcmp(word,"1364-2001-noconfig") == 0) {
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|GN_KEYWORDS_1364_2001;
} else if (strcmp(word,"1364-2005") == 0) {
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|GN_KEYWORDS_1364_2001
|GN_KEYWORDS_1364_2001_CONFIG
|GN_KEYWORDS_1364_2005;
} else if (strcmp(word,"VAMS-2.3") == 0) {
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|GN_KEYWORDS_1364_2001
|GN_KEYWORDS_1364_2001_CONFIG
|GN_KEYWORDS_1364_2005
|GN_KEYWORDS_VAMS_2_3;
} else {
fprintf(stderr, "%s:%d: Ignoring unknown keywords string: %s\n",
yylloc.text, yylloc.first_line, word);
}
BEGIN(0);
}
<PPBEGIN_KEYWORDS>.* {
fprintf(stderr, "%s:%d: Malformed keywords specification: %s\n",
yylloc.text, yylloc.first_line, yytext);
BEGIN(0);
}
^{W}?`end_keywords{W}?.* {
if (!keyword_mask_stack.empty()) {
lexor_keyword_mask = keyword_mask_stack.front();
keyword_mask_stack.pop_front();
} else {
fprintf(stderr, "%s:%d: Mismatched end_keywords directive\n",
yylloc.text, yylloc.first_line);
}
}
/* Notice and handle the default_nettype directive. The lexor
detects the default_nettype keyword, and the second part of the
@@ -337,7 +446,7 @@ W [ \t\b\f\r]+
error_count += 1;
}
pform_set_default_nettype(net_type, yylloc.text, yylloc.first_line);
}
}
<PPDEFAULT_NETTYPE>\n {
yylloc.first_line += 1;
BEGIN(0); }
@@ -978,5 +1087,5 @@ void reset_lexor()
yylloc.first_line = 1;
/* Announce the first file name. */
yylloc.text = set_file_name(strdup(vl_file.c_str()));
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
}
+160 -111
View File
@@ -6,127 +6,176 @@
#include "parse.h"
#include <string.h>
#include "lexor_keyword.h"
#include "compiler.h"
%}
struct lexor_keyword { const char*name; int tokenType; };
struct lexor_keyword { const char*name; int mask; int tokenType; };
%%
always, K_always
and, K_and
assign, K_assign
begin, K_begin
bool, K_bool
buf, K_buf
bufif0, K_bufif0
bufif1, K_bufif1
case, K_case
casex, K_casex
casez, K_casez
cmos, K_cmos
deassign, K_deassign
default, K_default
defparam, K_defparam
disable, K_disable
edge, K_edge
else, K_else
end, K_end
endcase, K_endcase
endfunction, K_endfunction
endgenerate, K_endgenerate
endmodule, K_endmodule
endprimitive, K_endprimitive
endspecify, K_endspecify
endtable, K_endtable
endtask, K_endtask
event, K_event
for, K_for
force, K_force
forever, K_forever
fork, K_fork
function, K_function
generate, K_generate
genvar, K_genvar
highz0, K_highz0
highz1, K_highz1
if, K_if
ifnone, K_ifnone
initial, K_initial
inout, K_inout
input, K_input
integer, K_integer
join, K_join
large, K_large
localparam, K_localparam
logic, K_logic
macromodule, K_macromodule
medium, K_medium
module, K_module
nand, K_nand
negedge, K_negedge
nmos, K_nmos
nor, K_nor
not, K_not
notif0, K_notif0
notif1, K_notif1
or, K_or
output, K_output
parameter, K_parameter
pmos, K_pmos
posedge, K_posedge
primitive, K_primitive
pull0, K_pull0
pull1, K_pull1
pulldown, K_pulldown
pullup, K_pullup
rcmos, K_rcmos
real, K_real
realtime, K_realtime
reg, K_reg
release, K_release
repeat, K_repeat
rnmos, K_rnmos
rpmos, K_rpmos
rtran, K_rtran
rtranif0, K_rtranif0
rtranif1, K_rtranif1
scalared, K_scalared
signed, K_signed
small, K_small
specify, K_specify
specparam, K_specparam
strong0, K_strong0
strong1, K_strong1
supply0, K_supply0
supply1, K_supply1
table, K_table
task, K_task
time, K_time
tran, K_tran
tranif0, K_tranif0
tranif1, K_tranif1
tri, K_tri
tri0, K_tri0
tri1, K_tri1
triand, K_triand
trior, K_trior
trireg, K_trireg
vectored, K_vectored
wait, K_wait
wand, K_wand
weak0, K_weak0
weak1, K_weak1
while, K_while
wire, K_wire
wone, K_wone
wor, K_wor
xnor, K_xnor
xor, K_xor
abs, GN_KEYWORDS_VAMS_2_3, K_abs
abstol, GN_KEYWORDS_VAMS_2_3, K_abstol
access, GN_KEYWORDS_VAMS_2_3, K_access
acos, GN_KEYWORDS_VAMS_2_3, K_acos
acosh, GN_KEYWORDS_VAMS_2_3, K_acosh
always, GN_KEYWORDS_1364_1995, K_always
analog, GN_KEYWORDS_VAMS_2_3, K_analog
and, GN_KEYWORDS_1364_1995, K_and
asin, GN_KEYWORDS_VAMS_2_3, K_asin
asinh, GN_KEYWORDS_VAMS_2_3, K_asinh
assign, GN_KEYWORDS_1364_1995, K_assign
atan, GN_KEYWORDS_VAMS_2_3, K_atan
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
begin, GN_KEYWORDS_1364_1995, K_begin
bool, GN_KEYWORDS_ICARUS, K_bool
buf, GN_KEYWORDS_1364_1995, K_buf
bufif0, GN_KEYWORDS_1364_1995, K_bufif0
bufif1, GN_KEYWORDS_1364_1995, K_bufif1
case, GN_KEYWORDS_1364_1995, K_case
casex, GN_KEYWORDS_1364_1995, K_casex
casez, GN_KEYWORDS_1364_1995, K_casez
ceil, GN_KEYWORDS_VAMS_2_3, K_ceil
cmos, GN_KEYWORDS_1364_1995, K_cmos
continuous, GN_KEYWORDS_VAMS_2_3, K_continuous
cos, GN_KEYWORDS_VAMS_2_3, K_cos
cosh, GN_KEYWORDS_VAMS_2_3, K_cosh
ddt_nature, GN_KEYWORDS_VAMS_2_3, K_ddt_nature
deassign, GN_KEYWORDS_1364_1995, K_deassign
default, GN_KEYWORDS_1364_1995, K_default
defparam, GN_KEYWORDS_1364_1995, K_defparam
disable, GN_KEYWORDS_1364_1995, K_disable
discipline, GN_KEYWORDS_VAMS_2_3, K_discipline
discrete, GN_KEYWORDS_VAMS_2_3, K_discrete
domain, GN_KEYWORDS_VAMS_2_3, K_domain
edge, GN_KEYWORDS_1364_1995, K_edge
else, GN_KEYWORDS_1364_1995, K_else
end, GN_KEYWORDS_1364_1995, K_end
endcase, GN_KEYWORDS_1364_1995, K_endcase
enddiscipline, GN_KEYWORDS_VAMS_2_3, K_enddiscipline
endfunction, GN_KEYWORDS_1364_1995, K_endfunction
endgenerate, GN_KEYWORDS_1364_1995, K_endgenerate
endmodule, GN_KEYWORDS_1364_1995, K_endmodule
endnature, GN_KEYWORDS_VAMS_2_3, K_endnature
endprimitive, GN_KEYWORDS_1364_1995, K_endprimitive
endspecify, GN_KEYWORDS_1364_1995, K_endspecify
endtable, GN_KEYWORDS_1364_1995, K_endtable
endtask, GN_KEYWORDS_1364_1995, K_endtask
event, GN_KEYWORDS_1364_1995, K_event
exclude, GN_KEYWORDS_VAMS_2_3, K_exclude
exp, GN_KEYWORDS_VAMS_2_3, K_exp
floor, GN_KEYWORDS_VAMS_2_3, K_floor
flow, GN_KEYWORDS_VAMS_2_3, K_flow
for, GN_KEYWORDS_1364_1995, K_for
force, GN_KEYWORDS_1364_1995, K_force
forever, GN_KEYWORDS_1364_1995, K_forever
fork, GN_KEYWORDS_1364_1995, K_fork
from, GN_KEYWORDS_VAMS_2_3, K_from
function, GN_KEYWORDS_1364_1995, K_function
generate, GN_KEYWORDS_1364_2001, K_generate
genvar, GN_KEYWORDS_1364_2001, K_genvar
ground, GN_KEYWORDS_VAMS_2_3, K_ground
highz0, GN_KEYWORDS_1364_1995, K_highz0
highz1, GN_KEYWORDS_1364_1995, K_highz1
hypot, GN_KEYWORDS_VAMS_2_3, K_hypot
idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature
if, GN_KEYWORDS_1364_1995, K_if
ifnone, GN_KEYWORDS_1364_1995, K_ifnone
inf, GN_KEYWORDS_VAMS_2_3, K_inf
initial, GN_KEYWORDS_1364_1995, K_initial
inout, GN_KEYWORDS_1364_1995, K_inout
input, GN_KEYWORDS_1364_1995, K_input
integer, GN_KEYWORDS_1364_1995, K_integer
join, GN_KEYWORDS_1364_1995, K_join
large, GN_KEYWORDS_1364_1995, K_large
ln, GN_KEYWORDS_VAMS_2_3, K_ln
localparam, GN_KEYWORDS_1364_2001, K_localparam
log, GN_KEYWORDS_VAMS_2_3, K_log
logic, GN_KEYWORDS_ICARUS, K_logic
macromodule, GN_KEYWORDS_1364_1995, K_macromodule
max, GN_KEYWORDS_VAMS_2_3, K_max
medium, GN_KEYWORDS_1364_1995, K_medium
min, GN_KEYWORDS_VAMS_2_3, K_min
module, GN_KEYWORDS_1364_1995, K_module
nand, GN_KEYWORDS_1364_1995, K_nand
nature, GN_KEYWORDS_VAMS_2_3, K_nature
negedge, GN_KEYWORDS_1364_1995, K_negedge
nmos, GN_KEYWORDS_1364_1995, K_nmos
nor, GN_KEYWORDS_1364_1995, K_nor
not, GN_KEYWORDS_1364_1995, K_not
notif0, GN_KEYWORDS_1364_1995, K_notif0
notif1, GN_KEYWORDS_1364_1995, K_notif1
or, GN_KEYWORDS_1364_1995, K_or
output, GN_KEYWORDS_1364_1995, K_output
parameter, GN_KEYWORDS_1364_1995, K_parameter
pmos, GN_KEYWORDS_1364_1995, K_pmos
posedge, GN_KEYWORDS_1364_1995, K_posedge
potential, GN_KEYWORDS_VAMS_2_3, K_potential
pow, GN_KEYWORDS_VAMS_2_3, K_pow
primitive, GN_KEYWORDS_1364_1995, K_primitive
pull0, GN_KEYWORDS_1364_1995, K_pull0
pull1, GN_KEYWORDS_1364_1995, K_pull1
pulldown, GN_KEYWORDS_1364_1995, K_pulldown
pullup, GN_KEYWORDS_1364_1995, K_pullup
rcmos, GN_KEYWORDS_1364_1995, K_rcmos
real, GN_KEYWORDS_1364_1995, K_real
realtime, GN_KEYWORDS_1364_1995, K_realtime
reg, GN_KEYWORDS_1364_1995, K_reg
release, GN_KEYWORDS_1364_1995, K_release
repeat, GN_KEYWORDS_1364_1995, K_repeat
rnmos, GN_KEYWORDS_1364_1995, K_rnmos
rpmos, GN_KEYWORDS_1364_1995, K_rpmos
rtran, GN_KEYWORDS_1364_1995, K_rtran
rtranif0, GN_KEYWORDS_1364_1995, K_rtranif0
rtranif1, GN_KEYWORDS_1364_1995, K_rtranif1
scalared, GN_KEYWORDS_1364_1995, K_scalared
signed, GN_KEYWORDS_1364_2001, K_signed
sin, GN_KEYWORDS_VAMS_2_3, K_sin
sinh, GN_KEYWORDS_VAMS_2_3, K_sinh
small, GN_KEYWORDS_1364_1995, K_small
specify, GN_KEYWORDS_1364_1995, K_specify
specparam, GN_KEYWORDS_1364_1995, K_specparam
sqrt, GN_KEYWORDS_VAMS_2_3, K_sqrt
string, GN_KEYWORDS_VAMS_2_3, K_string
strong0, GN_KEYWORDS_1364_1995, K_strong0
strong1, GN_KEYWORDS_1364_1995, K_strong1
supply0, GN_KEYWORDS_1364_1995, K_supply0
supply1, GN_KEYWORDS_1364_1995, K_supply1
table, GN_KEYWORDS_1364_1995, K_table
tan, GN_KEYWORDS_VAMS_2_3, K_tan
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
task, GN_KEYWORDS_1364_1995, K_task
time, GN_KEYWORDS_1364_1995, K_time
tran, GN_KEYWORDS_1364_1995, K_tran
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
tri, GN_KEYWORDS_1364_1995, K_tri
tri0, GN_KEYWORDS_1364_1995, K_tri0
tri1, GN_KEYWORDS_1364_1995, K_tri1
triand, GN_KEYWORDS_1364_1995, K_triand
trior, GN_KEYWORDS_1364_1995, K_trior
trireg, GN_KEYWORDS_1364_1995, K_trireg
units, GN_KEYWORDS_VAMS_2_3, K_units
vectored, GN_KEYWORDS_1364_1995, K_vectored
wait, GN_KEYWORDS_1364_1995, K_wait
wand, GN_KEYWORDS_1364_1995, K_wand
weak0, GN_KEYWORDS_1364_1995, K_weak0
weak1, GN_KEYWORDS_1364_1995, K_weak1
while, GN_KEYWORDS_1364_1995, K_while
wire, GN_KEYWORDS_1364_1995, K_wire
wone, GN_KEYWORDS_1364_1995, K_wone
wor, GN_KEYWORDS_1364_1995, K_wor
xnor, GN_KEYWORDS_1364_1995, K_xnor
xor, GN_KEYWORDS_1364_1995, K_xor
%%
int lexor_keyword_mask = 0;
int lexor_keyword_code(const char*str, unsigned nstr)
{
const struct lexor_keyword*rc = check_identifier(str, nstr);
if (rc == 0)
return IDENTIFIER;
else if ((rc->mask & lexor_keyword_mask) == 0)
return IDENTIFIER;
else
return rc->tokenType;
}
+5 -37
View File
@@ -30,7 +30,6 @@ VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
libdir64 = @libdir64@
includedir = $(prefix)/include
CC = @CC@
@@ -58,12 +57,6 @@ getlongp.o getp.o getsimtime.o io_print.o math.o mc_scan_plusargs.o \
nodeinfo.o nump.o putlongp.o putp.o spname.o typep.o workarea.o \
veriusertfs.o priv.o $A
ifeq (@enable_vvp32@,yes)
ALL32 = all32
INSTALL32 = install32
UNINSTALL32 = uninstall32
endif
all: dep libveriuser.a $(ALL32)
check: all
@@ -93,40 +86,15 @@ clean:
distclean: clean
rm -f Makefile config.status config.log config.cache config.h
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
$(libdir64)/libveriuser.a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(libdir64)/libveriuser.a
$(libdir)/libveriuser.a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(libdir64)
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
uninstall::
rm -f $(libdir64)/libveriuser.a
ifeq (@enable_vvp32@,yes)
all32: bin32 bin32/libveriuser.a
bin32:
mkdir bin32
bin32/%.o: %.c
$(CC) -m32 $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $@
bin32/libveriuser.o: $(addprefix bin32/,$O)
$(LD) -melf_i386 -r -o $@ $(addprefix bin32/,$O)
bin32/libveriuser.a: bin32/libveriuser.o
rm -f $@
ar cvq $@ bin32/libveriuser.o
$(RANLIB) $@
install32: $(libdir)/libveriuser.a
$(libdir)/libveriuser.a: bin32/libveriuser.a
$(INSTALL_DATA) bin32/libveriuser.a $(libdir)/libveriuser.a
-include $(patsubst bin32/%.o, bin32/%.d, $(addprefix bin32/,$O))
endif
rm -f $(libdir)/libveriuser.a
-include $(patsubst %.o, dep/%.d, $O)
+3 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: a_fetch_value.c,v 1.5 2003/06/17 16:55:07 steve Exp $"
#endif
# include <acc_user.h>
# include <vpi_user.h>
@@ -104,7 +101,8 @@ static char* fetch_strength_value(handle obj)
val.format = vpiStrengthVal;
vpi_get_value(obj, &val);
vpip_format_strength(str, &val);
/* Should this iterate over the bits? It now matches the old code. */
vpip_format_strength(str, &val, 0);
if (pli_trace) {
fprintf(pli_trace, "acc_fetch_value(<%s>, \"%%v\") --> %s\n",
@@ -125,30 +123,3 @@ char* acc_fetch_value(handle obj, const char*fmt, s_acc_value*value)
vpi_printf("XXXX acc_fetch_value(..., \"%s\", ...)\n", fmt);
return "<acc_fetch_value>";
}
/*
* $Log: a_fetch_value.c,v $
* Revision 1.5 2003/06/17 16:55:07 steve
* 1) setlinebuf() for vpi_trace
* 2) Addes error checks for trace file opens
* 3) removes now extraneous flushes
* 4) fixes acc_next() bug
*
* Revision 1.4 2003/05/18 00:16:35 steve
* Add PLI_TRACE tracing of PLI1 modules.
*
* Add tf_isetdelay and friends, and add
* callback return values for acc_vcl support.
*
* Revision 1.3 2003/04/24 02:02:37 steve
* Clean up some simple warnings.
*
* Revision 1.2 2003/04/20 02:49:07 steve
* acc_fetch_value support for %v format.
*
* Revision 1.1 2003/04/12 18:57:14 steve
* More acc_ function stubs.
*
*/
+1 -1
View File
@@ -52,7 +52,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
/*
* The acc_next_* functions need to be reentrant, so we need to
* rescan all the items upto the previous one, then return
* rescan all the items up to the previous one, then return
* the next one.
*/
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
-14
View File
@@ -10,10 +10,6 @@ AC_PROG_RANLIB
AC_EXEEXT
AX_CPP_IDENT
# vvp32 is by default disabled
#enable_vvp32=no
AC_SUBST(enable_vvp32)
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_SIZEOF(unsigned long long)
@@ -29,14 +25,4 @@ AX_C_PICFLAG
AC_SUBST(EXEEXT)
AC_SUBST(EXTRALIBS)
# If not otherwise specified, set the libdir64 variable
# to the same as libdir.
AC_MSG_CHECKING(for libdir64 path)
if test x${libdir64} = x
then
libdir64="${libdir}"
fi
AC_SUBST(libdir64)
AC_MSG_RESULT(${libdir64})
AC_OUTPUT(Makefile)
+1 -1
View File
@@ -24,7 +24,7 @@
#include <acc_user.h>
/*
* tf_getinstance implemented using equvalent acc_ routing
* tf_getinstance implemented using equivalent acc_ routing
*/
char *tf_getcstringp(int n)
{
+1 -1
View File
@@ -32,7 +32,7 @@
extern char* __acc_newstring(const char*txt);
/*
* Trace file for loggint ACC and TF calls.
* Trace file for logging ACC and TF calls.
*/
FILE* pli_trace;
+1 -1
View File
@@ -23,7 +23,7 @@
/*
* Contains the routines required to implement veriusertfs routines
* via VPI. This is extremly ugly, so don't look after eating dinner.
* via VPI. This is extremely ugly, so don't look after eating dinner.
*/
# include <string.h>
+91 -114
View File
@@ -1,6 +1,6 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2005 Stephen Williams ([email protected])";
"Copyright (c) 1998-2008 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
@@ -18,9 +18,6 @@ const char COPYRIGHT[] =
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.95 2007/04/19 02:52:53 steve Exp $"
#endif
# include "config.h"
@@ -60,6 +57,7 @@ const char NOTICE[] =
# include "netlist.h"
# include "target.h"
# include "compiler.h"
# include "discipline.h"
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt);
@@ -85,12 +83,14 @@ const char*target = "null";
/*
* These are the language support control flags. These support which
* language features (the generation) to support. The generation_flag
* is a major moce, and the gn_* flags control specifc sub-features.
* is a major mode, and the gn_* flags control specific sub-features.
*/
generation_t generation_flag = GN_DEFAULT;
bool gn_icarus_misc_flag = true;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
bool gn_io_range_error_flag = true;
bool gn_verilog_ams_flag = false;
map<string,const char*> flags;
char*vpi_module_list = 0;
@@ -113,6 +113,7 @@ FILE *depend_file = NULL;
bool warn_implicit = false;
bool warn_timescale = false;
bool warn_portbinding = false;
bool warn_inf_loop = false;
bool error_implicit = false;
@@ -123,6 +124,8 @@ bool debug_scopes = false;
bool debug_eval_tree = false;
bool debug_elaborate = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
/*
* Verbose messages enabled.
*/
@@ -199,14 +202,30 @@ const char *net_func_to_name(const net_func func)
static void process_generation_flag(const char*gen)
{
if (strcmp(gen,"1") == 0) {
if (strcmp(gen,"1") == 0) { // FIXME: Deprecated for 1995
generation_flag = GN_VER1995;
} else if (strcmp(gen,"2") == 0) {
} else if (strcmp(gen,"2") == 0) { // FIXME: Deprecated for 2001
generation_flag = GN_VER2001;
} else if (strcmp(gen,"2x") == 0) {
generation_flag = GN_VER2001X;
} else if (strcmp(gen,"2x") == 0) { // FIXME: Deprecated for 2001
generation_flag = GN_VER2001;
gn_icarus_misc_flag = true;
} else if (strcmp(gen,"1995") == 0) {
generation_flag = GN_VER1995;
} else if (strcmp(gen,"2001") == 0) {
generation_flag = GN_VER2001;
} else if (strcmp(gen,"2005") == 0) {
generation_flag = GN_VER2005;
} else if (strcmp(gen,"icarus-misc") == 0) {
gn_icarus_misc_flag = true;
} else if (strcmp(gen,"no-icarus-misc") == 0) {
gn_icarus_misc_flag = false;
} else if (strcmp(gen,"xtypes") == 0) {
gn_cadence_types_flag = true;
@@ -220,6 +239,12 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;
} else if (strcmp(gen,"no-verilog-ams") == 0) {
gn_verilog_ams_flag = false;
} else if (strcmp(gen,"io-range-error") == 0) {
gn_io_range_error_flag = true;
@@ -356,9 +381,9 @@ static void read_iconfig_file(const char*ipath)
basedir = strdup(cp);
} else if (strcmp(buf, "debug") == 0) {
if (strcmp(cp, "scope") == 0) {
if (strcmp(cp, "scopes") == 0) {
debug_scopes = true;
cerr << "debug: Enable scope debug" << endl;
cerr << "debug: Enable scopes debug" << endl;
} else if (strcmp(cp,"eval_tree") == 0) {
debug_eval_tree = true;
cerr << "debug: Enable eval_tree debug" << endl;
@@ -368,6 +393,9 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(cp,"synth2") == 0) {
debug_synth2 = true;
cerr << "debug: Enable synth2 debug" << endl;
} else if (strcmp(cp,"optimizer") == 0) {
debug_optimizer = true;
cerr << "debug: Enable optimizer debug" << endl;
} else {
}
@@ -434,6 +462,9 @@ static void read_iconfig_file(const char*ipath)
case 'i':
warn_implicit = true;
break;
case 'l':
warn_inf_loop = true;
break;
case 'p':
warn_portbinding = true;
break;
@@ -591,6 +622,29 @@ int main(int argc, char*argv[])
}
}
lexor_keyword_mask = 0;
switch (generation_flag) {
case GN_VER1995:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
break;
case GN_VER2001:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
break;
case GN_VER2005:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
break;
}
if (gn_cadence_types_flag)
lexor_keyword_mask |= GN_KEYWORDS_ICARUS;
if (gn_verilog_ams_flag)
lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3;
if (verbose_flag) {
if (times_flag)
@@ -604,11 +658,14 @@ int main(int argc, char*argv[])
case GN_VER2001:
cout << "IEEE1364-2001";
break;
case GN_VER2001X:
cout << "IEEE1364-2001+Extensions";
case GN_VER2005:
cout << "IEEE1364-2005";
break;
}
if (gn_verilog_ams_flag)
cout << ",verilog-ams";
if (gn_specify_blocks_flag)
cout << ",specify";
else
@@ -619,6 +676,11 @@ int main(int argc, char*argv[])
else
cout << ",no-xtypes";
if (gn_icarus_misc_flag)
cout << ",icarus-misc";
else
cout << ",no-icarus-misc";
cout << endl << "PARSING INPUT" << endl;
}
@@ -627,6 +689,16 @@ int main(int argc, char*argv[])
if (pf_path) {
ofstream out (pf_path);
out << "PFORM DUMP NATURES:" << endl;
for (map<perm_string,nature_t*>::iterator cur = natures.begin()
; cur != natures.end() ; cur ++ ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP DISCIPLINES:" << endl;
for (map<perm_string,discipline_t*>::iterator cur = disciplines.begin()
; cur != disciplines.end() ; cur ++ ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP MODULES:" << endl;
for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
; mod != pform_modules.end()
@@ -728,7 +800,7 @@ int main(int argc, char*argv[])
des->set_flags(flags);
/* Done iwth all the pform data. Delete the modules. */
/* Done with all the pform data. Delete the modules. */
for (map<perm_string,Module*>::iterator idx = pform_modules.begin()
; idx != pform_modules.end() ; idx ++) {
@@ -753,6 +825,11 @@ int main(int argc, char*argv[])
func(des);
}
if (verbose_flag) {
cout << "CALCULATING ISLANDS" << endl;
}
des->join_islands();
if (net_path) {
if (verbose_flag)
cerr<<" dumping netlist to " <<net_path<< "..." <<endl;
@@ -830,103 +907,3 @@ int main(int argc, char*argv[])
return des? des->errors : 1;
}
/*
* $Log: main.cc,v $
* Revision 1.95 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.94 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.93 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.92 2005/07/14 23:38:43 steve
* Display as version 0.9.devel
*
* Revision 1.91 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.90 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.89 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.88 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.87 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.86 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
* Revision 1.85 2004/09/25 01:58:44 steve
* Add a debug_elaborate flag
*
* Revision 1.84 2004/09/10 23:51:42 steve
* Fix the evaluation of constant ternary expressions.
*
* Revision 1.83 2004/09/05 17:44:42 steve
* Add support for module instance arrays.
*
* Revision 1.82 2004/03/10 04:51:24 steve
* Add support for system function table files.
*
* Revision 1.81 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.80 2004/02/15 00:19:29 steve
* Report elaboration errors without crashing.
*
* Revision 1.79 2003/11/26 01:37:14 steve
* Properly initialize vpi_module_list with system.
*
* Revision 1.78 2003/11/13 05:55:33 steve
* Move the DLL= flag to target config files.
*
* Revision 1.77 2003/11/13 04:09:49 steve
* Pass flags through the temporary config file.
*
* Revision 1.76 2003/11/13 03:10:38 steve
* ivl -F and -t flags are onpassed throught the -C file.
*
* Revision 1.75 2003/11/10 20:59:03 steve
* Design::get_flag returns const char* instead of string.
*
* Revision 1.74 2003/11/01 04:22:30 steve
* Accept functors in the config file.
*
* Revision 1.73 2003/10/26 22:43:42 steve
* Improve -V messages,
*
* Revision 1.72 2003/09/26 02:17:14 steve
* Delete pform when done with it.
*
* Revision 1.71 2003/09/25 00:25:14 steve
* Summary list of missing modules.
*
* Revision 1.70 2003/09/23 05:57:36 steve
* Pass -m flag from driver via iconfig file.
*
* Revision 1.69 2003/09/22 01:12:08 steve
* Pass more ivl arguments through the iconfig file.
*
* Revision 1.68 2003/06/20 00:53:19 steve
* Module attributes from the parser
* through to elaborated form.
*
* Revision 1.67 2003/04/24 05:25:27 steve
* Dump design even on errors.
*
* Revision 1.66 2003/03/01 06:25:30 steve
* Add the lex_strings string handler, and put
* scope names and system task/function names
* into this table. Also, permallocate event
* names from the beginning.
*/
+4 -2
View File
@@ -47,6 +47,8 @@ critical, but these are the versions I use.
msys-1.0 <http://www.mingw/org>
msysDTK-1.0 <http://www.mingw.org>
Mingw32-5.x <http://www.mingw.org>
... including the sub-packages binutils, gcc-core and gcc-g++
if you are given the option.
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
@@ -91,7 +93,7 @@ commands below.
The obvious step 2, then, is install the mingw compilers. These can be
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
is a convenient remote installer. Download this program and run
it. The installer will ask wich components you want to install. You
it. The installer will ask which components you want to install. You
need only the base C compiler and the C++ compiler. (You may install
other languages if you wish.)
@@ -150,7 +152,7 @@ You will need these gnuwin32 packages to compile Icarus Verilog:
I suggest creating a common directory for holding all your gnuwin32
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
has a "setup" link for each of these packages. Click the setup to
download the installer for each of the desired programes, then execute
download the installer for each of the desired programs, then execute
the downloaded .exe files to invoke the installer. Install into the
c:\gunwin32 directory.
+283 -150
View File
@@ -20,6 +20,7 @@
# include "config.h"
# include <iostream>
# include <cstdlib>
/*
* This source file contains all the implementations of the Design
@@ -31,6 +32,7 @@
# include "compiler.h"
# include "netmisc.h"
# include <sstream>
# include "ivl_assert.h"
Design:: Design()
: errors(0), nodes_(0), procs_(0), lcounter_(0)
@@ -242,6 +244,260 @@ void Design::evaluate_parameters()
(*scope)->evaluate_parameters(this);
}
void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
{
long msb = 0;
long lsb = 0;
bool range_flag = false;
/* Evaluate the msb expression, if it is present. */
if ((*cur).second.msb) {
eval_expr((*cur).second.msb);
if (! eval_as_long(msb, (*cur).second.msb)) {
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": "
<< *(*cur).second.msb << endl;
des->errors += 1;
return;
}
range_flag = true;
}
/* Evaluate the lsb expression, if it is present. */
if ((*cur).second.lsb) {
eval_expr((*cur).second.lsb);
if (! eval_as_long(lsb, (*cur).second.lsb)) {
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": "
<< *(*cur).second.lsb << endl;
des->errors += 1;
return;
}
range_flag = true;
}
/* Evaluate the parameter expression, if necessary. */
NetExpr*expr = (*cur).second.expr;
assert(expr);
eval_expr(expr);
/* The eval_expr may delete any replace the expr pointer, so the
second.expr value cannot be relied on. Might as well replace
it now with the expression that we evaluated. */
(*cur).second.expr = expr;
switch (expr->expr_type()) {
case IVL_VT_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) {
cerr << expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate real parameter value: "
<< *expr << endl;
des->errors += 1;
return;
}
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
if (! dynamic_cast<const NetEConst*>(expr)) {
cerr << expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate parameter "
<< (*cur).first
<< " value: " << *expr << endl;
des->errors += 1;
return;
}
break;
default:
cerr << expr->get_fileline()
<< ": internal error: "
<< "unhandled expression type?" << endl;
des->errors += 1;
return;
}
/* If the parameter has range information, then make
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) {
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
NetEConst*val = dynamic_cast<NetEConst*>(expr);
assert(val);
verinum value = val->value();
if (! (value.has_len()
&& (value.len() == wid)
&& (value.has_sign() == (*cur).second.signed_flag))) {
verinum tmp (value, wid);
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
expr = val;
}
}
// If there are no value ranges to test the value against,
// then we are done.
if ((*cur).second.range == 0) {
return;
}
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
ivl_assert(*(*cur).second.expr, (*cur).second.expr);
ivl_assert(*(*cur).second.expr, val);
verinum value = val->value();
bool from_flag = (*cur).second.range == 0? true : false;
for (range_t*value_range = (*cur).second.range
; value_range ; value_range = value_range->next) {
// If we already know that the value is
// within a "from" range, then do not test
// any more of the from ranges.
if (from_flag && value_range->exclude_flag==false)
continue;
if (value_range->low_expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->low_expr);
ivl_assert(*value_range->low_expr, tmp);
if (value_range->low_open_flag && value <= tmp->value())
continue;
else if (value < tmp->value())
continue;
}
if (value_range->high_expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->high_expr);
ivl_assert(*value_range->high_expr, tmp);
if (value_range->high_open_flag && value >= tmp->value())
continue;
else if (value > tmp->value())
continue;
}
// Within the range. If this is a "from"
// range, then set the from_flag and continue.
if (value_range->exclude_flag == false) {
from_flag = true;
continue;
}
// OH NO! In an excluded range. signal an error.
from_flag = false;
break;
}
// If we found no from range that contains the
// value, then report an error.
if (! from_flag) {
cerr << val->get_fileline() << ": error: "
<< "Parameter value " << value
<< " is out of range for parameter " << (*cur).first
<< "." << endl;
des->errors += 1;
}
}
void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
{
NetExpr*expr = (*cur).second.expr;
assert(expr);
NetECReal*res = 0;
eval_expr(expr);
switch (expr->expr_type()) {
case IVL_VT_REAL:
if (NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
res = tmp;
} else {
ivl_assert(*expr, 0);
}
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verireal val (tmp->value().as_long());
res = new NetECReal(val);
res->set_line(*tmp);
} else {
ivl_assert(*expr, 0);
}
break;
default:
ivl_assert(*expr, 0);
break;
}
(*cur).second.expr = res;
double value = res->value().as_double();
bool from_flag = (*cur).second.range == 0? true : false;
for (range_t*value_range = (*cur).second.range
; value_range ; value_range = value_range->next) {
if (from_flag && value_range->exclude_flag==false)
continue;
if (value_range->low_expr) {
double tmp;
bool flag = eval_as_double(tmp, value_range->low_expr);
ivl_assert(*value_range->low_expr, flag);
if (value_range->low_open_flag && value <= tmp)
continue;
else if (value < tmp)
continue;
}
if (value_range->high_expr) {
double tmp;
bool flag = eval_as_double(tmp, value_range->high_expr);
ivl_assert(*value_range->high_expr, flag);
if (value_range->high_open_flag && value >= tmp)
continue;
else if (value > tmp)
continue;
}
if (value_range->exclude_flag == false) {
from_flag = true;
continue;
}
// All the above tests failed, so we must have tripped
// an exclude rule.
from_flag = false;
break;
}
if (! from_flag) {
cerr << res->get_fileline() << ": error: "
<< "Parameter value " << value
<< " is out of range for parameter " << (*cur).first
<< "." << endl;
des->errors += 1;
}
}
void NetScope::evaluate_parameters(Design*des)
{
NetScope*cur = sub_;
@@ -256,163 +512,29 @@ void NetScope::evaluate_parameters(Design*des)
// scanning code. Now the parameter expression can be fully
// evaluated, or it cannot be evaluated at all.
typedef map<perm_string,param_expr_t>::iterator mparm_it_t;
for (mparm_it_t cur = parameters.begin()
for (param_ref_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
long msb = 0;
long lsb = 0;
bool range_flag = false;
NetExpr*expr;
/* Evaluate the msb expression, if it is present. */
expr = (*cur).second.msb;
if (expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
if (! tmp) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.msb = nexpr;
tmp = dynamic_cast<NetEConst*>(nexpr);
}
assert(tmp);
msb = tmp->value().as_long();
range_flag = true;
}
/* Evaluate the lsb expression, if it is present. */
expr = (*cur).second.lsb;
if (expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
if (! tmp) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.lsb = nexpr;
tmp = dynamic_cast<NetEConst*>(nexpr);
}
assert(tmp);
lsb = tmp->value().as_long();
assert(range_flag);
}
/* Evaluate the parameter expression, if necessary. */
expr = (*cur).second.expr;
assert(expr);
switch (expr->expr_type()) {
case IVL_VT_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate real parameter value: "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
}
switch ((*cur).second.type) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
evaluate_parameter_logic_(des, cur);
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
if (! dynamic_cast<const NetEConst*>(expr)) {
// Try to evaluate the expression.
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unable to evaluate parameter "
<< (*cur).first
<< " value: " <<
*expr << endl;
des->errors += 1;
continue;
}
// The evaluate worked, replace the old
// expression with this constant value.
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
// Set the signedness flag.
(*cur).second.expr
->cast_signed( (*cur).second.signed_flag );
}
case IVL_VT_REAL:
evaluate_parameter_real_(des, cur);
break;
default:
cerr << (*cur).second.expr->get_fileline()
<< ": internal error: "
<< "unhandled expression type?" << endl;
des->errors += 1;
continue;
}
/* If the parameter has range information, then make
sure the value is set right. */
if (range_flag) {
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
assert(val);
verinum value = val->value();
if (! (value.has_len()
&& (value.len() == wid)
&& (value.has_sign() == (*cur).second.signed_flag))) {
verinum tmp (value, wid);
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
(*cur).second.expr = val;
}
cerr << (*cur).second.get_fileline() << ": internal error: "
<< "Unexpected expression type " << (*cur).second.type
<< "." << endl;
cerr << (*cur).second.get_fileline() << ": : "
<< "Parameter name: " << (*cur).first << endl;
cerr << (*cur).second.get_fileline() << ": : "
<< "Expression is: " << *(*cur).second.expr << endl;
ivl_assert((*cur).second, 0);
break;
}
}
@@ -555,3 +677,14 @@ void Design::delete_process(NetProcTop*top)
delete top;
}
void Design::join_islands(void)
{
if (nodes_ == 0)
return;
NetNode*cur = nodes_->node_next_;
do {
join_island(cur);
cur = cur->node_next_;
} while (cur != nodes_->node_next_);
}
+39 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,6 +20,7 @@
# include "config.h"
# include "netlist.h"
# include "compiler.h"
# include "netmisc.h"
# include <iostream>
/*
@@ -80,6 +81,7 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
}
unsigned pad_width = lossless_flag? 1 : 0;
cast_signed(l->has_sign() && r->has_sign());
/* Now that we have the operand sizes the way we like, or as
good as we are going to get them, set the size of myself. */
@@ -90,8 +92,6 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
} else {
expr_width(l->expr_width() + pad_width);
}
cast_signed(l->has_sign() && r->has_sign());
}
NetEBAdd::~NetEBAdd()
@@ -218,6 +218,27 @@ ivl_variable_type_t NetEBDiv::expr_type() const
return IVL_VT_LOGIC;
}
NetEBMinMax::NetEBMinMax(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width( max(l->expr_width(), r->expr_width()) );
cast_signed(l->has_sign() || r->has_sign());
}
NetEBMinMax::~NetEBMinMax()
{
}
ivl_variable_type_t NetEBMinMax::expr_type() const
{
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
return IVL_VT_LOGIC;
}
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
@@ -258,7 +279,8 @@ NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
assert(op == 'p');
expr_width(l->expr_width());
/* This is incorrect! a * (2^b - 1) is close. */
expr_width(l->expr_width()+r->expr_width());
cast_signed(l->has_sign() || r->has_sign());
}
@@ -365,15 +387,7 @@ unsigned NetEConcat::repeat()
if (repeat_calculated_)
return repeat_value_;
assert(repeat_);
if (! dynamic_cast<NetEConst*>(repeat_)) {
NetExpr*tmp = repeat_->eval_tree();
if (tmp != 0) {
delete repeat_;
repeat_ = tmp;
}
}
eval_expr(repeat_);
NetEConst*repeat_const = dynamic_cast<NetEConst*>(repeat_);
@@ -462,7 +476,12 @@ NetEParam::NetEParam()
}
NetEParam::NetEParam(Design*d, NetScope*s, perm_string n)
: des_(d), scope_(s), name_(n)
: des_(d), scope_(s), reference_(scope_->find_parameter(n))
{
}
NetEParam::NetEParam(Design*d, NetScope*s, ref_t ref)
: des_(d), scope_(s), reference_(ref)
{
}
@@ -475,9 +494,14 @@ bool NetEParam::has_width() const
return false;
}
ivl_variable_type_t NetEParam::expr_type() const
{
return (*reference_).second.type;
}
NetEParam* NetEParam::dup_expr() const
{
NetEParam*tmp = new NetEParam(des_, scope_, name_);
NetEParam*tmp = new NetEParam(des_, scope_, reference_);
tmp->set_line(*this);
return tmp;
}
+18
View File
@@ -49,6 +49,24 @@ NetUserFunc::~NetUserFunc()
{
}
ivl_variable_type_t NetUserFunc::data_type(unsigned port) const
{
NetFuncDef*def = def_->func_def();
/* Port 0 is the return port. */
if (port == 0) {
const NetNet*sig = def->return_sig();
assert(sig);
return sig->data_type();
}
port -= 1;
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
return port_sig->data_type();
}
unsigned NetUserFunc::port_width(unsigned port) const
{
NetFuncDef*def = def_->func_def();
+20 -85
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.21 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -101,6 +98,11 @@ Link::DIR Link::get_dir() const
return dir_;
}
void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
{
nexus_->drivers_delays(rise, fall, decay);
}
void Link::drive0(Link::strength_t str)
{
drive0_ = str;
@@ -245,6 +247,19 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
{
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() != Link::OUTPUT)
continue;
NetObj*obj = cur->get_obj();
obj->rise_time(rise);
obj->fall_time(fall);
obj->decay_time(decay);
}
}
void Nexus::unlink(Link*that)
{
if (name_) {
@@ -413,7 +428,7 @@ NexusSet::~NexusSet()
{
if (nitems_ > 0) {
assert(items_ != 0);
delete[] items_;
free(items_);
} else {
assert(items_ == 0);
}
@@ -523,83 +538,3 @@ bool NexusSet::intersect(const NexusSet&that) const
return false;
}
/*
* $Log: net_link.cc,v $
* Revision 1.21 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.20 2007/03/26 18:17:50 steve
* Remove pretense of general use for t_cookie.
*
* Revision 1.19 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.18 2005/09/25 23:40:11 steve
* Simplify NexusSet set handling.
*
* Revision 1.17 2005/06/13 23:22:37 steve
* Fix compile errors.
*
* Revision 1.16 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.15 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.14 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.13 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.12 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.11 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
* Revision 1.10 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.9 2002/07/03 03:08:47 steve
* Clear drive cache on link or unlink.
*
* Revision 1.8 2002/06/30 02:21:31 steve
* Add structure for asynchronous logic synthesis.
*
* Revision 1.7 2002/06/24 01:49:39 steve
* Make link_drive_constant cache its results in
* 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.
*
*/
+1 -1
View File
@@ -180,7 +180,7 @@ NexusSet* NetAssignBase::nex_input(bool rem_out)
{
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 have nex_input values. In
particular, index expressions are statement inputs as well,
so should be addressed here. */
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
+1 -1
View File
@@ -105,7 +105,7 @@ void NetPDelay::nex_output(NexusSet&out)
/*
* For the purposes of synthesis, system task calls have no output at
* all. This is OK because most system tasks are not synthesizeable in
* all. This is OK because most system tasks are not synthesizable in
* the first place.
*/
void NetSTask::nex_output(NexusSet&out)
+73 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,16 +16,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.38 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
# include "netlist.h"
# include <cstring>
# include <cstdlib>
# include <sstream>
# include "ivl_assert.h"
/*
* The NetScope class keeps a scope tree organized. Each node of the
@@ -44,11 +43,13 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
lcounter_ = 0;
if (up) {
default_nettype_ = up->default_nettype();
time_unit_ = up->time_unit();
time_prec_ = up->time_precision();
sib_ = up_->sub_;
up_->sub_ = this;
} else {
default_nettype_ = NetNet::NONE;
time_unit_ = 0;
time_prec_ = 0;
assert(t == MODULE);
@@ -79,15 +80,50 @@ NetScope::~NetScope()
/* name_ and module_name_ are perm-allocated. */
}
void NetScope::set_line(const LineInfo*info)
{
file_ = info->get_file();
def_file_ = file_;
lineno_ = info->get_lineno();
def_lineno_ = lineno_;
}
void NetScope::set_line(perm_string file, unsigned lineno)
{
file_ = file;
def_file_ = file;
lineno_ = lineno;
def_lineno_ = lineno;
}
void NetScope::set_line(perm_string file, perm_string def_file,
unsigned lineno, unsigned def_lineno)
{
file_ = file;
def_file_ = def_file;
lineno_ = lineno;
def_lineno_ = def_lineno;
}
NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
NetExpr*msb, NetExpr*lsb, bool signed_flag)
ivl_variable_type_t type,
NetExpr*msb, NetExpr*lsb, bool signed_flag,
NetScope::range_t*range_list,
const LineInfo&file_line)
{
param_expr_t&ref = parameters[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.type = type;
ref.msb = msb;
ref.lsb = lsb;
ref.signed_flag = signed_flag;
ivl_assert(file_line, ref.range == 0);
ref.range = range_list;
ref.set_line(file_line);
ivl_assert(file_line, type != IVL_VT_NO_TYPE);
return res;
}
@@ -110,29 +146,30 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
}
/*
* Return false if this creates a new parameter.
* Return false if the parameter does not already exist.
* A parameter is not automatically created.
*/
bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
{
bool flag = true;
param_expr_t&ref = parameters[key];
bool flag = false;
NetExpr* res = ref.expr;
if (parameters.find(key) != parameters.end()) {
param_expr_t&ref = parameters[key];
if (res) {
delete res;
} else {
flag = false;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
delete ref.expr;
ref.expr = expr;
flag = true;
}
ref.expr = expr;
return flag;
}
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
/*
* This is not really complete (msb, lsb, sign). It is currently only
* used to add a genver to the local parameter list.
*/
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
const LineInfo&file_line)
{
param_expr_t&ref = localparams[key];
NetExpr* res = ref.expr;
@@ -140,6 +177,7 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
ref.set_line(file_line);
return res;
}
@@ -172,6 +210,20 @@ const NetExpr* NetScope::get_parameter(const char* key,
return 0;
}
map<perm_string,NetScope::param_expr_t>::iterator NetScope::find_parameter(perm_string key)
{
map<perm_string,param_expr_t>::iterator idx;
idx = parameters.find(key);
if (idx != parameters.end())
return idx;
idx = localparams.find(perm_string::literal(key));
if (idx != localparams.end())
return idx;
return (map<perm_string,param_expr_t>::iterator) 0;
}
NetScope::TYPE NetScope::type() const
{
@@ -295,10 +347,10 @@ void NetScope::rem_event(NetEvent*ev)
}
NetEvent* NetScope::find_event(const char*name)
NetEvent* NetScope::find_event(perm_string name)
{
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
if (strcmp(cur->name(), name) == 0)
if (cur->name() == name)
return cur;
return 0;
@@ -337,7 +389,7 @@ void NetScope::rem_signal(NetNet*net)
* is assumed to be the base name of the signal, so no sub-scopes are
* searched.
*/
NetNet* NetScope::find_signal(const char*key)
NetNet* NetScope::find_signal(perm_string key)
{
if (signals_ == 0)
return 0;
@@ -403,4 +455,3 @@ string NetScope::local_hsymbol()
return string(name()) + "." + string(local_symbol());
}
#endif
+160
View File
@@ -0,0 +1,160 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include <iostream>
# include <typeinfo>
# include <cstdlib>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "ivl_target_priv.h"
# include "ivl_assert.h"
static bool has_enable(ivl_switch_type_t tt)
{
switch (tt) {
case IVL_SW_TRANIF0:
case IVL_SW_TRANIF1:
case IVL_SW_RTRANIF0:
case IVL_SW_RTRANIF1:
return true;
default:
return false;
}
}
NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
: NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
{
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
if (pin_count() == 3) {
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("E"), 0);
}
}
NetTran::NetTran(NetScope*scope, perm_string n, unsigned wid, unsigned part, unsigned off)
: NetNode(scope, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
{
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
}
NetTran::~NetTran()
{
}
unsigned NetTran::vector_width() const
{
return wid_;
}
unsigned NetTran::part_width() const
{
return part_;
}
unsigned NetTran::part_offset() const
{
return off_;
}
void join_island(NetObj*obj)
{
IslandBranch*branch = dynamic_cast<IslandBranch*> (obj);
// If this is not even a branch, then stop now.
if (branch == 0)
return;
// If this is a branch, but already given to an island, then
// stop.
if (branch->island)
return;
list<NetObj*> uncommitted_neighbors;
// Look for neighboring objects that might already be in
// islands. If we find something, then join that island.
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
Nexus*nex = obj->pin(idx).nexus();
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
unsigned pin;
NetObj*tmp;
cur->cur_link(tmp, pin);
// Skip self.
if (tmp == obj)
continue;
// If tmb is not a branch, then skip it.
IslandBranch*tmp_branch = dynamic_cast<IslandBranch*> (tmp);
if (tmp_branch == 0)
continue;
// If that is an uncommitted branch, then save
// it. When I finally choose an island for self,
// these branches will be scanned so tha they join
// this island as well.
if (tmp_branch->island == 0) {
uncommitted_neighbors.push_back(tmp);
continue;
}
ivl_assert(*obj, branch->island==0 || branch->island==tmp_branch->island);
// We found an existing island to join. Join it
// now. Keep scanning in order to find more neighbors.
if (branch->island == 0) {
if (debug_elaborate)
cerr << obj->get_fileline() << ": debug: "
<< "Join brach to existing island." << endl;
branch->island = tmp_branch->island;
} else if (branch->island != tmp_branch->island) {
cerr << obj->get_fileline() << ": internal error: "
<< "Oops, Found 2 neighboring islands." << endl;
ivl_assert(*obj, 0);
}
}
}
// If after all that we did not find an idland to join, then
// start the island not and join it.
if (branch->island == 0) {
branch->island = new ivl_island_s;
branch->island->discipline = 0;
if (debug_elaborate)
cerr << obj->get_fileline() << ": debug: "
<< "Create new island for this branch" << endl;
}
// Now scan all the uncommitted neighbors I found. Calling
// join_island() on them will cause them to notice me in the
// process, and thus they will join my island. This process
// will recurse until all the connected branches join this island.
for (list<NetObj*>::iterator cur = uncommitted_neighbors.begin()
; cur != uncommitted_neighbors.end() ; cur ++ ) {
join_island(*cur);
}
}
+318 -169
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -235,11 +235,12 @@ NetBus::~NetBus()
{
}
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n,
unsigned npins, bool condit_src)
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
bool condit_src, bool conditional)
: NetObj(s, n, npins + (condit_src?1:0))
{
condit_flag_ = false;
conditional_ = conditional;
posedge_ = false;
negedge_ = false;
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
@@ -379,6 +380,11 @@ const Link& NetDelaySrc::src_pin(unsigned idx) const
}
bool NetDelaySrc::is_condit() const
{
return conditional_;
}
bool NetDelaySrc::has_condit() const
{
return condit_flag_;
}
@@ -398,10 +404,11 @@ const Link& NetDelaySrc::condit_pin() const
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), msb_(npins-1), lsb_(0), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
signed_(false), isint_(false), msb_(npins-1), lsb_(0), dimensions_(0),
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
assert(npins>0);
verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE;
@@ -437,7 +444,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
: NetObj(s, n, 1),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
isint_(false), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -483,8 +490,8 @@ static unsigned calculate_count(long s, long e)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls, long array_s, long array_e)
: NetObj(s, n, calculate_count(array_s, array_e)),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)
{
@@ -641,7 +648,7 @@ bool NetNet::sb_is_valid(long sb) const
return (sb <= lsb_) && (sb >= msb_);
}
unsigned NetNet::sb_to_idx(long sb) const
long NetNet::sb_to_idx(long sb) const
{
if (msb_ >= lsb_)
return sb - lsb_;
@@ -754,10 +761,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
pin(0).set_dir(Link::INPUT);
pin(1).set_dir(Link::OUTPUT);
break;
case NetPartSelect::BI:
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::OUTPUT);
break;
}
pin(0).set_name(perm_string::literal("Part"), 0);
pin(1).set_name(perm_string::literal("Vect"), 0);
@@ -780,10 +783,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
pin(0).set_dir(Link::INPUT);
pin(1).set_dir(Link::OUTPUT);
break;
case NetPartSelect::BI:
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
break;
}
pin(2).set_dir(Link::INPUT);
@@ -1039,6 +1038,24 @@ const verinum& NetFF::sset_value() const
}
NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
}
NetAbs::~NetAbs()
{
}
unsigned NetAbs::width() const
{
return width_;
}
/*
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
* assigned like so:
@@ -1132,6 +1149,9 @@ NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Address"), 0);
// Increment the expression reference count for the target
// memory so that it is not deleted underneath me.
mem->incr_eref();
}
NetArrayDq::~NetArrayDq()
@@ -1553,6 +1573,78 @@ const Link& NetMult::pin_DataB() const
return pin(2);
}
NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
unsigned wa, unsigned wb)
: NetNode(sc, n, 3),
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetPow::~NetPow()
{
}
void NetPow::set_signed(bool flag)
{
signed_ = flag;
}
bool NetPow::get_signed() const
{
return signed_;
}
unsigned NetPow::width_r() const
{
return width_r_;
}
unsigned NetPow::width_a() const
{
return width_a_;
}
unsigned NetPow::width_b() const
{
return width_b_;
}
Link& NetPow::pin_Result()
{
return pin(0);
}
const Link& NetPow::pin_Result() const
{
return pin(0);
}
Link& NetPow::pin_DataA()
{
return pin(1);
}
const Link& NetPow::pin_DataA() const
{
return pin(1);
}
Link& NetPow::pin_DataB()
{
return pin(2);
}
const Link& NetPow::pin_DataB() const
{
return pin(2);
}
/*
* The NetMux class represents an LPM_MUX device. The pinout is assigned
* like so:
@@ -1842,8 +1934,9 @@ const NetExpr* NetSTask::parm(unsigned idx) const
return parms_[idx];
}
NetEUFunc::NetEUFunc(NetScope*def, NetESignal*res, svector<NetExpr*>&p)
: func_(def), result_sig_(res), parms_(p)
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
svector<NetExpr*>&p)
: scope_(scope), func_(def), result_sig_(res), parms_(p)
{
expr_width(result_sig_->expr_width());
}
@@ -2186,6 +2279,11 @@ ivl_variable_type_t NetETernary::expr_type() const
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
return IVL_VT_REAL;
if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
return IVL_VT_REAL;
if (tru != fal) {
cerr << get_fileline() << ": internal error:"
<< " Unexpected ?: type clash:"
@@ -2206,6 +2304,7 @@ NetEUnary::NetEUnary(char op, NetExpr*ex)
switch (op_) {
case '-':
case '+':
case 'm': // abs()
cast_signed(ex->has_sign());
break;
default:
@@ -2337,155 +2436,205 @@ const NetProc*NetTaskDef::proc() const
}
/*
* $Log: netlist.cc,v $
* Revision 1.258 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.257 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.256 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.255 2007/03/01 06:19:38 steve
* Add support for conditional specify delay paths.
*
* Revision 1.254 2007/02/20 05:58:36 steve
* Handle unary minus of real valued expressions.
*
* Revision 1.253 2007/02/14 05:59:46 steve
* Handle type of ternary expressions properly.
*
* Revision 1.252 2007/01/19 04:25:37 steve
* Fix missing passive setting for array word pins.
*
* Revision 1.251 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.250 2006/11/10 04:54:26 steve
* Add test_width methods for PETernary and PEString.
*
* Revision 1.249 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.248 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.247 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.246 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.245 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.244 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.243 2005/05/08 23:44:08 steve
* Add support for variable part select.
*
* Revision 1.242 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.241 2005/04/08 04:51:16 steve
* All memory addresses are signed.
*
* Revision 1.240 2005/04/06 05:29:08 steve
* Rework NetRamDq and IVL_LPM_RAM nodes.
*
* Revision 1.239 2005/03/09 05:52:04 steve
* Handle case inequality in netlists.
*
* Revision 1.238 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.237 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
*
* Revision 1.236 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.235 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.234 2005/01/28 05:39:33 steve
* Simplified NetMult and IVL_LPM_MULT.
*
* Revision 1.233 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.232 2005/01/22 18:16:01 steve
* Remove obsolete NetSubnet class.
*
* Revision 1.231 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.230 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors.
*
* Revision 1.229 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.228 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.227 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.226 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*
* Revision 1.225 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.224 2004/06/13 04:56:54 steve
* Add support for the default_nettype directive.
*
* Revision 1.223 2004/05/31 23:34:37 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
* speed and more type support.
*
* Revision 1.222 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
* Revision 1.221 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.220 2003/11/10 19:44:30 steve
* Fix return value warnings.
*
* Revision 1.219 2003/09/03 23:32:10 steve
* Oops, missing pin_Sset implementation.
*
* Revision 1.218 2003/08/15 02:23:52 steve
* Add synthesis support for synchronous reset.
*
* Revision 1.217 2003/07/05 20:42:08 steve
* Fix some enumeration warnings.
*
* Revision 1.216 2003/06/18 03:55:18 steve
* Add arithmetic shift operators.
*
* Revision 1.215 2003/05/01 01:13:57 steve
* More complete bit range internal error message,
* Better test of part select ranges on non-zero
* signal ranges.
* These are the delay_type() functions. They are used to determine
* the type of delay for the given object.
*/
/*
* This function implements the following table:
*
* in_A in_B out
* NO NO NO
* NO ZERO ZERO
* NO POS POS
* NO DEF POS
* ZERO NO ZERO
* ZERO ZERO ZERO
* ZERO POS POS
* ZERO DEF POS
* POS NO POS
* POS ZERO POS
* POS POS POS
* POS DEF POS
* DEF NO POS
* DEF ZERO POS
* DEF POS POS
* DEF DEF DEF
*
* It is used to combine two delay values.
*/
static DelayType combine_delays(const DelayType a, const DelayType b)
{
/* The default is POSSIBLE_DELAY. */
DelayType result = POSSIBLE_DELAY;
/* If both are no or zero delay then we return ZERO_DELAY. */
if ((a == NO_DELAY || a == ZERO_DELAY) &&
(b == NO_DELAY || b == ZERO_DELAY)) {
result = ZERO_DELAY;
}
/* Except if both are no delay then we return NO_DELAY. */
if (a == NO_DELAY && b == NO_DELAY) {
result = NO_DELAY;
}
/* If both are definite delay then we return DEFINITE_DELAY. */
if (a == DEFINITE_DELAY && b == DEFINITE_DELAY) {
result = DEFINITE_DELAY;
}
return result;
}
/*
* This is used to see what we can find out about the delay when it
* is given as an expression. We also use this for loop expressions.
*/
static DelayType delay_type_from_expr(const NetExpr*expr)
{
DelayType result = POSSIBLE_DELAY;
if (const NetEConst*e = dynamic_cast<const NetEConst*>(expr)) {
if (e->value().is_zero()) result = ZERO_DELAY;
else result = DEFINITE_DELAY;
}
if (const NetECReal*e = dynamic_cast<const NetECReal*>(expr)) {
if (e->value().as_double() == 0.0) result = ZERO_DELAY;
else result = DEFINITE_DELAY;
}
return result;
}
/*
* The looping structures can use the same basic code so put it here
* instead of duplicating it for each one (repeat and while).
*/
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
{
DelayType result;
switch (delay_type_from_expr(expr)) {
/* We have a constant false expression so the body never runs. */
case ZERO_DELAY:
result = NO_DELAY;
break;
/* We have a constant true expression so the body always runs. */
case DEFINITE_DELAY:
result = proc->delay_type();
break;
/* We don't know if the body will run so reduce a DEFINITE_DELAY
* to a POSSIBLE_DELAY. All other stay the same. */
case POSSIBLE_DELAY:
result = combine_delays(NO_DELAY, proc->delay_type());
break;
/* This should never happen since delay_type_from_expr() only
* returns three different values. */
default:
assert(0);
}
return result;
}
/* The default object does not have any delay. */
DelayType NetProc::delay_type() const
{
return NO_DELAY;
}
DelayType NetBlock::delay_type() const
{
DelayType result = NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
}
return result;
}
DelayType NetCase::delay_type() const
{
DelayType result = NO_DELAY;
bool def_stmt = false;
unsigned nstmts = nitems();
for (unsigned idx = 0; idx < nstmts; idx += 1) {
if (!expr(idx)) def_stmt = true;
if (idx == 0) {
result = stat(idx)->delay_type();
} else {
result = combine_delays(result, stat(idx)->delay_type());
}
}
/* If we don't have a default statement we don't know for sure
* that we have a delay. */
if (!def_stmt) result = combine_delays(NO_DELAY, result);
return result;
}
DelayType NetCondit::delay_type() const
{
DelayType result;
if (else_) {
result = combine_delays(if_->delay_type(), else_->delay_type());
} else {
result = if_->delay_type();
}
return result;
}
DelayType NetEvWait::delay_type() const
{
return DEFINITE_DELAY;
}
DelayType NetForever::delay_type() const
{
return statement_->delay_type();
}
DelayType NetPDelay::delay_type() const
{
if (expr_) {
return delay_type_from_expr(expr_);
} else {
if (delay() > 0) {
return DEFINITE_DELAY;
} else {
if (statement_) {
return statement_->delay_type();
} else {
return NO_DELAY;
}
}
}
}
DelayType NetRepeat::delay_type() const
{
return get_loop_delay_type(expr_, statement_);
}
DelayType NetTaskDef::delay_type() const
{
return proc_->delay_type();
}
DelayType NetUTask::delay_type() const
{
return task()->task_def()->delay_type();
}
DelayType NetWhile::delay_type() const
{
return get_loop_delay_type(cond_, proc_);
}
+429 -225
View File
File diff suppressed because it is too large Load Diff
+128 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -123,21 +123,57 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
return res;
}
NetEConst* make_const_x(unsigned long wid)
{
verinum xxx (verinum::Vx, wid);
NetEConst*resx = new NetEConst(xxx);
return resx;
}
NetExpr* condition_reduce(NetExpr*expr)
{
if (expr->expr_width() == 1)
return expr;
verinum zero (verinum::V0, expr->expr_width());
NetEConst*ezero = new NetEConst(zero);
ezero->cast_signed(expr->has_sign());
ezero->set_line(*expr);
ezero->set_width(expr->expr_width());
NetEBComp*cmp = new NetEBComp('n', expr, ezero);
cmp->cast_signed(false);
cmp->set_line(*expr);
return cmp;
}
NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid, int prune_width)
{
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
if (tmp == 0)
return 0;
if (tmp == 0) return 0;
if (NetExpr*tmp2 = tmp->eval_tree(prune_width)) {
delete tmp;
tmp = tmp2;
}
eval_expr(tmp, prune_width);
return tmp;
}
void eval_expr(NetExpr*&expr, int prune_width)
{
assert(expr);
if (dynamic_cast<NetEConst*>(expr)) return;
if (dynamic_cast<NetECReal*>(expr)) return;
NetExpr*tmp = expr->eval_tree(prune_width);
if (tmp != 0) {
tmp->set_line(*expr);
delete expr;
expr = tmp;
}
}
bool eval_as_long(long&value, NetExpr*expr)
{
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) {
@@ -153,6 +189,21 @@ bool eval_as_long(long&value, NetExpr*expr)
return false;
}
bool eval_as_double(double&value, NetExpr*expr)
{
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) {
value = tmp->value().as_long();
return true;
}
if (NetECReal*rtmp = dynamic_cast<NetECReal*>(expr)) {
value = rtmp->value().as_double();
return true;
}
return false;
}
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
@@ -191,3 +242,73 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
return res;
}
/*
* Human readable version of op. Used in elaboration error messages.
*/
const char *human_readable_op(const char op)
{
const char *type;
switch (op) {
case '~': type = "~"; break; // Negation
case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND
case 'A': type = "~&"; break; // NAND (~&)
case '|': type = "|"; break; // Bitwise OR
case 'O': type = "~|"; break; // NOR
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case 'E': type = "==="; break; // Case equality
case 'N': type = "!=="; break; // Case inequality
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
default: assert(0);
}
return type;
}
const_bool const_logical(const NetExpr*expr)
{
switch (expr->expr_type()) {
case IVL_VT_REAL: {
const NetECReal*val = dynamic_cast<const NetECReal*> (expr);
if (val == 0) return C_NON;
if (val->value().as_double() == 0.0) return C_0;
else return C_1;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
const NetEConst*val = dynamic_cast<const NetEConst*> (expr);
if (val == 0) return C_NON;
verinum cval = val->value();
const_bool res = C_0;
for (unsigned idx = 0; idx < cval.len(); idx += 1) {
switch (cval.get(idx)) {
case verinum::V1:
res = C_1;
break;
case verinum::V0:
break;
default:
if (res == C_0) res = C_X;
break;
}
}
return res;
}
default:
break;
}
return C_NON;
}
+37 -5
View File
@@ -1,7 +1,7 @@
#ifndef __netmisc_H
#define __netmisc_H
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.h,v 1.31 2007/06/02 03:42:13 steve Exp $"
#endif
# include "netlist.h"
@@ -67,6 +64,13 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
/*
* Take the input expression and return a variation that assures that
* the expression is 1-bit wide and logical. This reflects the needs
* of conditions i.e. for "if" statements or logical operators.
*/
extern NetExpr*condition_reduce(NetExpr*expr);
/*
* This function transforms an expression by cropping the high bits
* off with a part select. The result has the width w passed in. This
@@ -89,7 +93,7 @@ extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
* make_add_expr
* Make a NetEBAdd expression with <expr> the first argument and
* <val> the second. This may get turned into a subtract if <val> is
* less then zero. If val is exactly zero, then return <expr> as is.
* less than zero. If val is exactly zero, then return <expr> as is.
*
* make_sub_expr
* Make a NetEBAdd(subtract) node that subtracts the given
@@ -98,6 +102,11 @@ extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
extern NetExpr*make_add_expr(NetExpr*expr, long val);
extern NetExpr*make_sub_expr(long val, NetExpr*expr);
/*
* Make a NetEConst object that contains only X bits.
*/
extern NetEConst*make_const_x(unsigned long wid);
/*
* 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
@@ -122,6 +131,11 @@ class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid,
int prune_width =-1);
/*
* This procedure elaborates an expression and if the elaboration is
* successful the original expression is replaced with the new one.
*/
void eval_expr(NetExpr*&expr, int prune_width =-1);
/*
* Get the long integer value for the passed in expression, if
@@ -129,8 +143,26 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
* down to a constant) then return false and leave value unchanged.
*/
bool eval_as_long(long&value, NetExpr*expr);
bool eval_as_double(double&value, NetExpr*expr);
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
/*
* Return a human readable version of the operator.
*/
const char *human_readable_op(const char op);
/*
* Is the expression a constant value and if so what is its logical
* value.
*
* C_NON - the expression is not a constant value.
* C_0 - the expression is constant and it has a false value.
* C_1 - the expression is constant and it has a true value.
* C_X - the expression is constant and it has an 'bX value.
*/
enum const_bool { C_NON, C_0, C_1, C_X };
const_bool const_logical(const NetExpr*expr);
#endif
+999 -543
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -33,7 +33,7 @@ class PUdp;
/*
* These are maps of the modules and primitives parsed from the
* 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 map<perm_string,PUdp*> pform_primitives;
+8
View File
@@ -23,6 +23,7 @@
#endif
# include <list>
# include "compiler.h"
# include "pform.h"
/*
@@ -39,6 +40,13 @@ struct vlltype {
};
# define YYLTYPE struct vlltype
class LineInfo;
inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
{
tmp->set_lineno(where.first_line);
tmp->set_file(filename_strings.make(where.text));
}
/* This for compatibility with new and older bison versions. */
#ifndef yylloc
# define yylloc VLlloc
+217 -162
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -27,6 +27,7 @@
# include "PUdp.h"
# include "PGenerate.h"
# include "PSpec.h"
# include "discipline.h"
# include <list>
# include <map>
# include <assert.h>
@@ -49,7 +50,7 @@ string vl_file = "";
extern int VLparse();
/* This tracks the current module being processed. There can only be
exactly one module currently being parsed, since verilog does not
exactly one module currently being parsed, since Verilog does not
allow nested module definitions. */
static Module*pform_cur_module = 0;
@@ -81,47 +82,56 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
obj->set_file(filename_strings.make(file));
}
static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
{
tmp->set_lineno(where.first_line);
tmp->set_file(filename_strings.make(where.text));
}
/*
* The scope stack and the following functions handle the processing
* of scope. As I enter a scope, the push function is called, and as I
* leave a scope the pop function is called. Entering tasks, functions
* and named blocks causes scope to be pushed and popped. The module
* name is not included in this scope stack.
* The lexical_scope keeps track of the current lexical scope that is
* being parsed. The lexical scope may stack, so the current scope may
* have a parent, that is restored when the current scope ends.
*
* The hier_name function, therefore, converts the name to the scoped
* name within the module currently in progress. It never includes an
* instance name.
*
* The scope stack does not include any scope created by a generate
* scheme.
* Items that have scoped names are put in the lexical_scope object.
*/
static pform_name_t scope_stack;
void pform_push_scope(char*name)
{
scope_stack.push_back(name_component_t(lex_strings.make(name)));
}
static PScope* lexical_scope = 0;
void pform_pop_scope()
{
scope_stack.pop_back();
lexical_scope = lexical_scope->pscope_parent();
}
static pform_name_t hier_name(const char*tail)
PTask* pform_push_task_scope(char*name)
{
pform_name_t name = scope_stack;
name.push_back(name_component_t(lex_strings.make(tail)));
return name;
perm_string task_name = lex_strings.make(name);
PTask*task = new PTask(task_name, pform_cur_module);
// Add the task to the current module
pform_cur_module->add_task(task->pscope_name(), task);
// Make this the current lexical scope
lexical_scope = task;
return task;
}
static PWire*get_wire_in_module(const pform_name_t&name)
PFunction* pform_push_function_scope(char*name)
{
perm_string func_name = lex_strings.make(name);
PFunction*func = new PFunction(func_name, lexical_scope);
// Add the task to the current module
pform_cur_module->add_function(func->pscope_name(), func);
// Make this the current lexical scope
lexical_scope = func;
return func;
}
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
{
perm_string block_name = lex_strings.make(name);
PBlock*block = new PBlock(block_name, lexical_scope, bt);
// Make this the current lexical scope
lexical_scope = block;
return block;
}
PWire*pform_get_wire_in_scope(perm_string name)
{
/* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes
@@ -130,7 +140,7 @@ static PWire*get_wire_in_module(const pform_name_t&name)
if (pform_cur_generate)
return pform_cur_generate->get_wire(name);
return pform_cur_module->get_wire(name);
return lexical_scope->wires_find(name);
}
void pform_set_default_nettype(NetNet::Type type,
@@ -259,6 +269,9 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
FILE_NAME(pform_cur_module, file, lineno);
pform_cur_module->library_flag = pform_library_flag;
ivl_assert(*pform_cur_module, lexical_scope == 0);
lexical_scope = pform_cur_module;
/* The generate scheme numbering starts with *1*, not
zero. That's just the way it is, thanks to the standard. */
scope_generate_counter = 1;
@@ -285,14 +298,14 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
* reference. This is a name without a .X(...), so the internal name
* should be generated to be the same as the X.
*/
Module::port_t* pform_module_port_reference(char*name,
Module::port_t* pform_module_port_reference(perm_string name,
const char*file,
unsigned lineno)
{
Module::port_t*ptmp = new Module::port_t;
PEIdent*tmp = new PEIdent(lex_strings.make(name));
PEIdent*tmp = new PEIdent(name);
FILE_NAME(tmp, file, lineno);
ptmp->name = lex_strings.make(name);
ptmp->name = name;
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = tmp;
@@ -331,18 +344,26 @@ void pform_endmodule(const char*name)
msg << "Module " << name << " was already declared here: "
<< (*test).second->get_fileline() << endl;
VLerror(msg.str().c_str());
pform_cur_module = 0;
return;
} else {
pform_modules[mod_name] = pform_cur_module;
}
pform_modules[mod_name] = pform_cur_module;
// The current lexical scope should be this module by now, and
// this module should not have a parent lexical scope.
ivl_assert(*pform_cur_module, lexical_scope == pform_cur_module);
lexical_scope = pform_cur_module->pscope_parent();
ivl_assert(*pform_cur_module, lexical_scope == 0);
pform_cur_module = 0;
}
void pform_genvars(list<perm_string>*names)
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
{
list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) {
pform_cur_module->genvars.push_back( *cur );
LineInfo*lni = new LineInfo();
FILE_NAME(lni, li);
pform_cur_module->genvars[*cur] = lni;
}
delete names;
@@ -412,6 +433,51 @@ void pform_start_generate_else(const struct vlltype&li)
pform_cur_generate->loop_step = 0;
}
/*
* The GS_CASE version of the PGenerate contains only case items. The
* items in turn contain the generated items themselves.
*/
void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_CASE;
pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = expr;
pform_cur_generate->loop_step = 0;
}
/*
* The generate case item is a special case schema that takes its id
* from the case schema that it is a part of. The idea is that the
* case schema can only instantiate exactly one item, so the items
* need not have a unique number.
*/
void pform_generate_case_item(const struct vlltype&li, PExpr*expr)
{
assert(pform_cur_generate);
assert(pform_cur_generate->scheme_type == PGenerate::GS_CASE);
PGenerate*gen = new PGenerate(pform_cur_generate->id_number);
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM;
pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = expr;
pform_cur_generate->loop_step = 0;
}
void pform_generate_block_name(char*name)
{
assert(pform_cur_generate != 0);
@@ -439,10 +505,14 @@ void pform_endgenerate()
PGenerate*cur = pform_cur_generate;
pform_cur_generate = cur->parent;
if (pform_cur_generate != 0)
if (pform_cur_generate != 0) {
assert(cur->scheme_type == PGenerate::GS_CASE_ITEM
|| pform_cur_generate->scheme_type != PGenerate::GS_CASE);
pform_cur_generate->generates.push_back(cur);
else
} else {
assert(cur->scheme_type != PGenerate::GS_CASE_ITEM);
pform_cur_module->generate_schemes.push_back(cur);
}
}
bool pform_expression_is_constant(const PExpr*ex)
@@ -496,6 +566,11 @@ PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max)
return res;
}
template <> inline svector<perm_string>::svector(unsigned size)
: nitems_(size), items_(new perm_string[size])
{
}
static void process_udp_table(PUdp*udp, list<string>*table,
const char*file, unsigned lineno)
{
@@ -507,7 +582,7 @@ static void process_udp_table(PUdp*udp, list<string>*table,
placed in the PUdp object.
The table strings are made up by the parser to be two or
three substrings seperated by ';', i.e.:
three substrings separated by ';', i.e.:
0101:1:1 (synchronous device entry)
0101:0 (combinational device entry)
@@ -563,7 +638,7 @@ static void process_udp_table(PUdp*udp, list<string>*table,
udp->toutput = output;
}
void pform_make_udp(perm_string name, list<string>*parms,
void pform_make_udp(perm_string name, list<perm_string>*parms,
svector<PWire*>*decl, list<string>*table,
Statement*init_expr,
const char*file, unsigned lineno)
@@ -575,11 +650,10 @@ void pform_make_udp(perm_string name, list<string>*parms,
off with the parameters in the list. If the port is already
in the map, merge the port type. I will rebuild a list
of parameters for the PUdp object. */
map<string,PWire*> defs;
map<perm_string,PWire*> defs;
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) {
pform_name_t pname = (*decl)[idx]->path();
string port_name = peek_tail_name(pname).str();
perm_string port_name = (*decl)[idx]->basename();
if (PWire*cur = defs[port_name]) {
bool rc = true;
@@ -605,8 +679,8 @@ void pform_make_udp(perm_string name, list<string>*parms,
UDP declaration, and the defs map maps that name to a
PWire* created by an input or output declaration. */
svector<PWire*> pins (parms->size());
svector<string> pin_names (parms->size());
{ list<string>::iterator cur;
svector<perm_string> pin_names (parms->size());
{ list<perm_string>::iterator cur;
unsigned idx;
for (cur = parms->begin(), idx = 0
; cur != parms->end()
@@ -740,7 +814,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
// Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
udp->ports[idx] = peek_tail_name(pins[idx]->path());
udp->ports[idx] = pins[idx]->basename();
process_udp_table(udp, table, file, lineno);
udp->initial = init;
@@ -765,10 +839,9 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
svector<PWire*> pins(parms->size() + 1);
/* Make the PWire for the output port. */
pins[0] = new PWire(hier_name(out_name),
pins[0] = new PWire(out_name,
synchronous_flag? NetNet::REG : NetNet::WIRE,
NetNet::POUTPUT,
IVL_VT_LOGIC);
NetNet::POUTPUT, IVL_VT_LOGIC);
FILE_NAME(pins[0], file, lineno);
/* Make the PWire objects for the input ports. */
@@ -778,10 +851,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
; cur != parms->end()
; idx += 1, cur++) {
assert(idx < pins.count());
pins[idx] = new PWire(hier_name(*cur),
NetNet::WIRE,
NetNet::PINPUT,
IVL_VT_LOGIC);
pins[idx] = new PWire(*cur, NetNet::WIRE,
NetNet::PINPUT, IVL_VT_LOGIC);
FILE_NAME(pins[idx], file, lineno);
}
assert(idx == pins.count());
@@ -822,7 +893,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
// Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
udp->ports[idx] = peek_tail_name(pins[idx]->path());
udp->ports[idx] = pins[idx]->basename();
assert(udp);
assert(table);
@@ -837,39 +908,18 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
delete init_expr;
}
/*
* This function is used to set the net range for a port that uses
* the new (1364-2001) list_of_port_declarations, but omitted a
* register/wire/etc. that would have triggered it to be set elsewhere.
*/
/*
* Since implicitly defined list of port declarations are no longer
* considered fully defined we no longer need this routine to force
* them to be fully defined.
*
void pform_set_net_range(const char* name)
{
PWire*cur = get_wire_in_module(hier_name(name));
if (cur == 0) {
VLerror("error: name is not a valid net.");
return;
}
cur->set_net_range();
}
*/
/*
* This function attaches a range to a given name. The function is
* only called by the parser within the scope of the net declaration,
* and the name that I receive only has the tail component.
*/
static void pform_set_net_range(const char* name,
static void pform_set_net_range(perm_string name,
const svector<PExpr*>*range,
bool signed_flag,
ivl_variable_type_t dt,
PWSRType rt)
{
PWire*cur = get_wire_in_module(hier_name(name));
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
VLerror("error: name is not a valid net.");
return;
@@ -1184,24 +1234,23 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
* BTF-B14.
*/
void pform_make_reginit(const struct vlltype&li,
const char*name, PExpr*expr)
perm_string name, PExpr*expr)
{
const pform_name_t sname = hier_name(name);
PWire*cur = pform_cur_module->get_wire(sname);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
VLerror(li, "internal error: reginit to non-register?");
delete expr;
return;
}
PEIdent*lval = new PEIdent(sname);
PEIdent*lval = new PEIdent(name);
FILE_NAME(lval, li);
PAssign*ass = new PAssign(lval, expr);
FILE_NAME(ass, li);
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
FILE_NAME(top, li);
pform_cur_module->add_behavior(top);
lexical_scope->behaviors.push_back(top);
}
/*
@@ -1215,18 +1264,17 @@ void pform_make_reginit(const struct vlltype&li,
* as is done for the old method.
*/
void pform_module_define_port(const struct vlltype&li,
const char*nm,
perm_string name,
NetNet::PortType port_type,
NetNet::Type type,
bool signed_flag,
svector<PExpr*>*range,
svector<named_pexpr_t*>*attr)
{
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur) {
ostringstream msg;
msg << nm << " definition conflicts with "
msg << name << " definition conflicts with "
<< "definition at " << cur->get_fileline()
<< ".";
VLerror(msg.str().c_str());
@@ -1257,7 +1305,7 @@ void pform_module_define_port(const struct vlltype&li,
cur->attributes[tmp->name] = tmp->parm;
}
}
pform_cur_module->add_wire(cur);
lexical_scope->wires[name] = cur;
}
/*
@@ -1280,27 +1328,25 @@ void pform_module_define_port(const struct vlltype&li,
*/
/*
* this is the basic form of pform_makwire. This takes a single simple
* this is the basic form of pform_makewire. This takes a single simple
* name, port type, net type, data type, and attributes, and creates
* the variable/net. Other forms of pform_makewire ultimately call
* this one to create the wire and stash it.
*/
void pform_makewire(const vlltype&li, const char*nm,
void pform_makewire(const vlltype&li, perm_string name,
NetNet::Type type, NetNet::PortType pt,
ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr)
{
pform_name_t name = hier_name(nm);
PWire*cur = get_wire_in_module(name);
PWire*cur = pform_get_wire_in_scope(name);
// If this is not implicit ("implicit" meaning we don't know
// what the type is yet) then set thay type now.
// what the type is yet) then set the type now.
if (cur && type != NetNet::IMPLICIT) {
bool rc = cur->set_wire_type(type);
if (rc == false) {
ostringstream msg;
msg << nm << " definition conflicts with "
msg << name << " definition conflicts with "
<< "definition at " << cur->get_fileline()
<< ".";
VLerror(msg.str().c_str());
@@ -1344,9 +1390,9 @@ void pform_makewire(const vlltype&li, const char*nm,
if (new_wire_flag) {
if (pform_cur_generate)
pform_cur_generate->add_wire(cur);
pform_cur_generate->wires[name] = cur;
else
pform_cur_module->add_wire(cur);
lexical_scope->wires[name] = cur;
}
}
@@ -1406,32 +1452,28 @@ void pform_makewire(const vlltype&li,
SR_NET);
}
perm_string first_name = lex_strings.make(first->name);
pform_name_t name = hier_name(first_name);
PWire*cur = get_wire_in_module(name);
PWire*cur = pform_get_wire_in_scope(first->name);
if (cur != 0) {
PEIdent*lval = new PEIdent(first_name);
PEIdent*lval = new PEIdent(first->name);
FILE_NAME(lval, li.text, li.first_line);
PGAssign*ass = pform_make_pgassign(lval, first->expr,
delay, str);
FILE_NAME(ass, li.text, li.first_line);
}
free(first->name);
delete first;
first = next;
}
}
void pform_set_port_type(perm_string nm, NetNet::PortType pt,
void pform_set_port_type(perm_string name, NetNet::PortType pt,
const char*file, unsigned lineno)
{
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno);
pform_cur_module->add_wire(cur);
lexical_scope->wires[name] = cur;
}
switch (cur->get_port_type()) {
@@ -1442,14 +1484,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: "
<< "port " << nm << " is not in the port list."
<< "port " << name << " is not in the port list."
<< endl;
error_count += 1;
break;
default:
cerr << file << ":" << lineno << ": error: "
<< "port " << nm << " already has a port declaration."
<< "port " << name << " already has a port declaration."
<< endl;
error_count += 1;
break;
@@ -1509,18 +1551,17 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; cur ++ ) {
perm_string txt = *cur;
pform_name_t name = hier_name(txt);
perm_string name = *cur;
/* Look for a preexisting wire. If it exists, set the
port direction. If not, create it. */
PWire*curw = pform_cur_module->get_wire(name);
PWire*curw = lexical_scope->wires_find(name);
if (curw) {
curw->set_port_type(pt);
} else {
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
FILE_NAME(curw, file, lineno);
pform_cur_module->add_wire(curw);
lexical_scope->wires[name] = curw;
}
curw->set_signed(signed_flag);
@@ -1541,22 +1582,9 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
return res;
}
void pform_set_task(perm_string name, PTask*task)
{
pform_cur_module->add_task(name, task);
}
void pform_set_function(perm_string name, PFunction*func)
{
pform_cur_module->add_function(name, func);
}
void pform_set_attrib(perm_string name, perm_string key, char*value)
{
pform_name_t path = hier_name(name);
if (PWire*cur = pform_cur_module->get_wire(path)) {
if (PWire*cur = lexical_scope->wires_find(name)) {
cur->attributes[key] = new PEString(value);
} else if (PGate*cur = pform_cur_module->get_gate(name)) {
@@ -1590,13 +1618,13 @@ void pform_set_type_attrib(perm_string name, const string&key,
* This function attaches a memory index range to an existing
* register. (The named wire must be a register.
*/
void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r)
void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
{
PWire*cur = 0;
if (pform_cur_generate) {
cur = pform_cur_generate->get_wire(hier_name(name));
cur = pform_cur_generate->get_wire(name);
} else {
cur = pform_cur_module->get_wire(hier_name(name));
cur = lexical_scope->wires_find(name);
}
if (cur == 0) {
VLerror("internal error: name is not a valid memory for index.");
@@ -1606,44 +1634,76 @@ void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r)
cur->set_memory_idx(l, r);
}
void pform_set_parameter(perm_string name, bool signed_flag,
svector<PExpr*>*range, PExpr*expr)
Module::range_t* pform_parameter_value_range(bool exclude_flag,
bool low_open, PExpr*low_expr,
bool hig_open, PExpr*hig_expr)
{
// Detect +-inf and make the the *_open flags false to force
// the range interpretation as inf.
if (low_expr == 0) low_open = false;
if (hig_expr == 0) hig_open = false;
Module::range_t*tmp = new Module::range_t;
tmp->exclude_flag = exclude_flag;
tmp->low_open_flag = low_open;
tmp->low_expr = low_expr;
tmp->high_open_flag = hig_open;
tmp->high_expr = hig_expr;
tmp->next = 0;
return tmp;
}
void pform_set_parameter(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type,
bool signed_flag, svector<PExpr*>*range, PExpr*expr,
Module::range_t*value_range)
{
assert(expr);
pform_cur_module->parameters[name].expr = expr;
Module::param_expr_t&parm = pform_cur_module->parameters[name];
FILE_NAME(&parm, loc);
parm.expr = expr;
parm.type = type;
if (range) {
assert(range->count() == 2);
assert((*range)[0]);
assert((*range)[1]);
pform_cur_module->parameters[name].msb = (*range)[0];
pform_cur_module->parameters[name].lsb = (*range)[1];
parm.msb = (*range)[0];
parm.lsb = (*range)[1];
} else {
pform_cur_module->parameters[name].msb = 0;
pform_cur_module->parameters[name].lsb = 0;
parm.msb = 0;
parm.lsb = 0;
}
pform_cur_module->parameters[name].signed_flag = signed_flag;
parm.signed_flag = signed_flag;
parm.range = value_range;
pform_cur_module->param_names.push_back(name);
}
void pform_set_localparam(perm_string name, bool signed_flag,
svector<PExpr*>*range, PExpr*expr)
void pform_set_localparam(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type,
bool signed_flag, svector<PExpr*>*range, PExpr*expr)
{
assert(expr);
pform_cur_module->localparams[name].expr = expr;
Module::param_expr_t&parm = pform_cur_module->localparams[name];
FILE_NAME(&parm, loc);
parm.expr = expr;
parm.type = type;
if (range) {
assert(range->count() == 2);
assert((*range)[0]);
assert((*range)[1]);
pform_cur_module->localparams[name].msb = (*range)[0];
pform_cur_module->localparams[name].lsb = (*range)[1];
parm.msb = (*range)[0];
parm.lsb = (*range)[1];
} else {
pform_cur_module->localparams[name].msb = 0;
pform_cur_module->localparams[name].lsb = 0;
parm.msb = 0;
parm.lsb = 0;
}
pform_cur_module->localparams[name].signed_flag = signed_flag;
parm.signed_flag = signed_flag;
parm.range = 0;
}
void pform_set_specparam(perm_string name, PExpr*expr)
@@ -1743,16 +1803,15 @@ void pform_set_port_type(const struct vlltype&li,
delete range;
}
static void pform_set_reg_integer(const char*nm)
static void pform_set_reg_integer(perm_string name)
{
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
cur = new PWire(name, NetNet::INTEGER,
NetNet::NOT_A_PORT,
IVL_VT_LOGIC);
cur->set_signed(true);
pform_cur_module->add_wire(cur);
lexical_scope->wires[name] = cur;
} else {
bool rc = cur->set_wire_type(NetNet::INTEGER);
assert(rc);
@@ -1778,13 +1837,12 @@ void pform_set_reg_integer(list<perm_string>*names)
delete names;
}
static void pform_set_reg_time(const char*nm)
static void pform_set_reg_time(perm_string name)
{
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
pform_cur_module->add_wire(cur);
lexical_scope->wires[name] = cur;
} else {
bool rc = cur->set_wire_type(NetNet::REG);
assert(rc);
@@ -1818,9 +1876,7 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
; cur != names->end()
; cur ++ ) {
perm_string txt = *cur;
pform_name_t tmp;
tmp.push_back(name_component_t(txt));
PWire*pp = new PWire(tmp,
PWire*pp = new PWire(txt,
NetNet::IMPLICIT,
NetNet::PINPUT,
IVL_VT_LOGIC);
@@ -1848,7 +1904,7 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
if (pform_cur_generate)
pform_cur_generate->add_behavior(pp);
else
pform_cur_module->add_behavior(pp);
pform_cur_module->behaviors.push_back(pp);
return pp;
}
@@ -1897,4 +1953,3 @@ void pform_error_nested_modules()
cerr << pform_cur_module->get_fileline() << ": error: original module "
"(" << pform_cur_module->mod_name() << ") defined here." << endl;
}
+64 -24
View File
@@ -1,7 +1,7 @@
#ifndef __pform_H
#define __pform_H
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $"
#endif
# include "netlist.h"
# include "HName.h"
@@ -33,6 +30,7 @@
# include "PUdp.h"
# include "PWire.h"
# include "verinum.h"
# include "discipline.h"
# include <iostream>
# include <string>
# include <list>
@@ -40,7 +38,7 @@
/*
* These classes implement the parsed form (P-form for short) of the
* original verilog source. the parser generates the pform for the
* original Verilog source. the parser generates the pform for the
* convenience of later processing steps.
*/
@@ -95,7 +93,7 @@ struct parmvalue_t {
struct str_pair_t { PGate::strength_t str0, str1; };
struct net_decl_assign_t {
char*name;
perm_string name;
PExpr*expr;
struct net_decl_assign_t*next;
};
@@ -118,11 +116,19 @@ struct lgate {
unsigned lineno;
};
/* The lexor calls this function to change the default nettype. */
extern void pform_set_default_nettype(NetNet::Type net,
const char*file,
unsigned lineno);
/*
* Look for the given wire in the current lexical scope. If the wire
* (including variables of any type) cannot be found in the current
* scope, then return 0.
*/
extern PWire* pform_get_wire_in_scope(perm_string name);
/*
* The parser uses startmodule and endmodule together to build up a
* module as it parses it. The startmodule tells the pform code that a
@@ -138,19 +144,19 @@ extern void pform_module_set_ports(svector<Module::port_t*>*);
port_definition_list. In this case, we have everything needed to
define the port, all in one place. */
extern void pform_module_define_port(const struct vlltype&li,
const char*name,
perm_string name,
NetNet::PortType,
NetNet::Type type,
bool signed_flag,
svector<PExpr*>*range,
svector<named_pexpr_t*>*attr);
extern Module::port_t* pform_module_port_reference(char*name,
extern Module::port_t* pform_module_port_reference(perm_string name,
const char*file,
unsigned lineno);
extern void pform_endmodule(const char*);
extern void pform_make_udp(perm_string name, list<string>*parms,
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
svector<PWire*>*decl, list<string>*table,
Statement*init,
const char*file, unsigned lineno);
@@ -167,18 +173,21 @@ extern void pform_make_udp(perm_string name,
* name string onto the scope hierarchy. The pop pulls it off and
* deletes it. Thus, the string pushed must be allocated.
*/
extern void pform_push_scope(char*name);
extern void pform_pop_scope();
extern PTask*pform_push_task_scope(char*name);
extern PFunction*pform_push_function_scope(char*name);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
const char*file, unsigned loneno);
const char*file, unsigned lineno);
/*
* This function takes the list of names as new genvars to declare in
* the current module scope.
*/
extern void pform_genvars(list<perm_string>*names);
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
extern void pform_start_generate_for(const struct vlltype&li,
char*ident1,
@@ -188,6 +197,8 @@ extern void pform_start_generate_for(const struct vlltype&li,
PExpr*next);
extern void pform_start_generate_if(const struct vlltype&li, PExpr*test);
extern void pform_start_generate_else(const struct vlltype&li);
extern void pform_start_generate_case(const struct vlltype&lp, PExpr*test);
extern void pform_generate_case_item(const struct vlltype&lp, PExpr*test);
extern void pform_generate_block_name(char*name);
extern void pform_endgenerate();
@@ -196,7 +207,7 @@ extern void pform_endgenerate();
* The makewire functions announce to the pform code new wires. These
* go into a module that is currently opened.
*/
extern void pform_makewire(const struct vlltype&li, const char*name,
extern void pform_makewire(const struct vlltype&li, perm_string name,
NetNet::Type type,
NetNet::PortType pt,
ivl_variable_type_t,
@@ -224,7 +235,7 @@ extern void pform_makewire(const struct vlltype&li,
ivl_variable_type_t);
extern void pform_make_reginit(const struct vlltype&li,
const char*name, PExpr*expr);
perm_string name, PExpr*expr);
/* Look up the names of the wires, and set the port type,
i.e. input, output or inout. If the wire does not exist, create
@@ -237,17 +248,14 @@ extern void pform_set_port_type(const struct vlltype&li,
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno);
extern void pform_set_net_range(const char* name);
extern void pform_set_net_range(list<perm_string>*names,
svector<PExpr*>*,
bool signed_flag,
ivl_variable_type_t,
PWSRType rt = SR_NET);
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names);
extern void pform_set_task(perm_string name, PTask*);
extern void pform_set_function(perm_string name, PFunction*);
/* pform_set_attrib and pform_set_type_attrib exist to support the
$attribute syntax, which can only set string values to
@@ -258,13 +266,21 @@ extern void pform_set_attrib(perm_string name, perm_string key,
extern void pform_set_type_attrib(perm_string name, const string&key,
char*value);
extern void pform_set_parameter(perm_string name,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr);
extern void pform_set_localparam(perm_string name,
extern Module::range_t* pform_parameter_value_range(bool exclude_flag,
bool low_open, PExpr*low_expr,
bool hig_open, PExpr*hig_expr);
extern void pform_set_parameter(const struct vlltype&loc,
perm_string name,
ivl_variable_type_t type,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr, Module::range_t*value_range);
extern void pform_set_localparam(const struct vlltype&loc,
perm_string name,
ivl_variable_type_t type,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr);
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
@@ -337,7 +353,7 @@ extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
/*
* These are functions that the outside-the-parser code uses the do
* interesting things to the verilog. The parse function reads and
* interesting things to the Verilog. The parse function reads and
* parses the source file and places all the modules it finds into the
* mod list. The dump function dumps a module to the output stream.
*/
@@ -349,4 +365,28 @@ extern void pform_dump(ostream&out, Module*mod);
*/
extern void pform_error_nested_modules();
/* ** pform_discipline.cc
* Functions for handling the parse of natures and disciplines. These
* functions are in pform_disciplines.cc
*/
class discipline_t;
extern void pform_start_nature(const char*name);
extern void pform_end_nature(const struct vlltype&loc);
extern void pform_nature_access(const struct vlltype&loc, const char*name);
extern void pform_start_discipline(const char*name);
extern void pform_end_discipline(const struct vlltype&loc);
extern void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain);
extern void pform_discipline_potential(const struct vlltype&loc, const char*name);
extern void pform_discipline_flow(const struct vlltype&loc, const char*name);
extern void pform_attach_discipline(const struct vlltype&loc,
discipline_t*discipline, list<perm_string>*names);
extern void pform_dump(ostream&out, const nature_t*);
extern void pform_dump(ostream&out, const discipline_t*);
#endif
+195
View File
@@ -0,0 +1,195 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "compiler.h"
# include "pform.h"
# include "parse_misc.h"
# include "discipline.h"
map<perm_string,nature_t*> natures;
map<perm_string,discipline_t*> disciplines;
static perm_string nature_name = perm_string::perm_string();
static perm_string nature_access = perm_string::perm_string();
void pform_start_nature(const char*name)
{
nature_name = lex_strings.make(name);
}
void pform_nature_access(const struct vlltype&loc, const char*name)
{
if (nature_access) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "Too many access names for nature "
<< nature_name << "." << endl;
error_count += 1;
return;
}
nature_access = lex_strings.make(name);
}
void pform_end_nature(const struct vlltype&loc)
{
// The nature access function is required. If it is missing,
// then signal an error. For a temporary expedient, we can set
// the nature name as the access function, but don't expect it
// to work.
if (! nature_access) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "Missing access name for nature "
<< nature_name << "." << endl;
error_count += 1;
nature_access = nature_name;
}
nature_t*tmp = new nature_t(nature_name, nature_access);
natures[nature_name] = tmp;
FILE_NAME(tmp, loc);
nature_name = perm_string::perm_string();
nature_access = perm_string::perm_string();
}
static perm_string discipline_name;
static ddomain_t discipline_domain = DD_NONE;
static nature_t* discipline_potential = 0;
static nature_t* discipline_flow = 0;
void pform_start_discipline(const char*name)
{
discipline_name = lex_strings.make(name);
discipline_domain = DD_NONE;
}
void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain)
{
assert(use_domain != DD_NONE);
if (discipline_domain != DD_NONE) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "Too many domain attributes for discipline "
<< discipline_name << "." << endl;
error_count += 1;
return;
}
discipline_domain = use_domain;
}
void pform_discipline_potential(const struct vlltype&loc, const char*name)
{
if (discipline_potential) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "Too many potential natures for discipline "
<< discipline_name << "." << endl;
error_count += 1;
return;
}
perm_string key = lex_strings.make(name);
discipline_potential = natures[key];
if (discipline_potential == 0) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "nature " << key << " is not declared." << endl;
error_count += 1;
return;
}
}
void pform_discipline_flow(const struct vlltype&loc, const char*name)
{
if (discipline_flow) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "Too many flow natures for discipline "
<< discipline_name << "." << endl;
error_count += 1;
return;
}
perm_string key = lex_strings.make(name);
discipline_flow = natures[key];
if (discipline_flow == 0) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "nature " << key << " is not declared." << endl;
error_count += 1;
return;
}
}
void pform_end_discipline(const struct vlltype&loc)
{
// If the domain is not otherwise specified, then take it to
// be continuous if potential or flow natures are given.
if (discipline_domain == DD_NONE && (discipline_potential||discipline_flow))
discipline_domain = DD_CONTINUOUS;
discipline_t*tmp = new discipline_t(discipline_name, discipline_domain,
discipline_potential, discipline_flow);
disciplines[discipline_name] = tmp;
FILE_NAME(tmp, loc);
/* Clear the static variables for the next item. */
discipline_name = perm_string::perm_string();
discipline_domain = DD_NONE;
discipline_potential = 0;
discipline_flow = 0;
}
/*
* The parser uses this function to attach a discipline to a wire. The
* wire may be declared by now, or will be declared further later. If
* it is already declared, we just attach the discipline. If it is not
* declared yet, then this is the declaration and we create the signal
* in the current lexical scope.
*/
void pform_attach_discipline(const struct vlltype&loc,
discipline_t*discipline, list<perm_string>*names)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; cur ++ ) {
PWire* cur_net = pform_get_wire_in_scope(*cur);
if (cur_net == 0) {
/* Not declared yet, declare it now. */
pform_makewire(loc, *cur, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
cur_net = pform_get_wire_in_scope(*cur);
assert(cur_net);
}
if (discipline_t*tmp = cur_net->get_discipline()) {
cerr << loc.text << ":" << loc.first_line << ": error: "
<< "discipline " << discipline->name()
<< " cannot override existing discipline " << tmp->name()
<< " on net " << cur_net->basename() << endl;
error_count += 1;
} else {
cur_net->set_discipline(discipline);
}
}
}
+136 -25
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -29,6 +29,7 @@
# include "PEvent.h"
# include "PGenerate.h"
# include "PSpec.h"
# include "discipline.h"
# include <iostream>
# include <iomanip>
# include <typeinfo>
@@ -97,7 +98,7 @@ ostream& operator<< (ostream&out, const index_component_t&that)
}
out << "]";
return out;
}
}
ostream& operator<< (ostream&out, const name_component_t&that)
{
@@ -128,6 +129,26 @@ ostream& operator<< (ostream&o, const pform_name_t&that)
return o;
}
std::ostream& operator << (std::ostream&out, ddomain_t dom)
{
switch (dom) {
case DD_NONE:
out << "no-domain";
break;
case DD_DISCRETE:
out << "discrete";
break;
case DD_CONTINUOUS:
out << "continuous";
break;
default:
assert(0);
break;
}
return out;
}
void PExpr::dump(ostream&out) const
{
out << typeid(*this).name();
@@ -215,11 +236,30 @@ void PETernary::dump(ostream&out) const
void PEUnary::dump(ostream&out) const
{
out << op_ << "(" << *expr_ << ")";
switch (op_) {
case 'm':
out << "abs";
break;
default:
out << op_;
break;
}
out << "(" << *expr_ << ")";
}
void PEBinary::dump(ostream&out) const
{
/* Handle some special cases, where the operators are written
in function notation. */
if (op_ == 'm') {
out << "min(" << *left_ << "," << *right_ << ")";
return;
}
if (op_ == 'M') {
out << "min(" << *left_ << "," << *right_ << ")";
return;
}
out << "(" << *left_ << ")";
switch (op_) {
case 'a':
@@ -281,6 +321,10 @@ void PWire::dump(ostream&out, unsigned ind) const
out << " signed";
}
if (discipline_) {
out << " discipline<" << discipline_->name() << ">";
}
if (port_set_) {
if (port_msb_ == 0) {
out << " port<scalar>";
@@ -296,7 +340,7 @@ void PWire::dump(ostream&out, unsigned ind) const
}
}
out << " " << hname_;
out << " " << name_;
// If the wire has indices, dump them.
if (lidx_ || ridx_) {
@@ -504,10 +548,13 @@ void PAssignNB::dump(ostream&out, unsigned ind) const
void PBlock::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "begin";
if (name_ != 0)
out << " : " << name_;
if (pscope_name() != 0)
out << " : " << pscope_name();
out << endl;
if (pscope_name() != 0)
dump_wires_(out, ind+2);
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
if (list_[idx])
list_[idx]->dump(out, ind+2);
@@ -697,15 +744,17 @@ void PFunction::dump(ostream&out, unsigned ind) const
out << "] ";
}
out << name_ << ";" << endl;
out << pscope_name() << ";" << endl;
if (ports_)
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
out << setw(ind) << "";
out << "input ";
out << (*ports_)[idx]->path() << ";" << endl;
out << (*ports_)[idx]->basename() << ";" << endl;
}
dump_wires_(out, ind);
if (statement_)
statement_->dump(out, ind);
else
@@ -743,9 +792,11 @@ void PTask::dump(ostream&out, unsigned ind) const
assert(0);
break;
}
out << (*ports_)[idx]->path() << ";" << endl;
out << (*ports_)[idx]->basename() << ";" << endl;
}
dump_wires_(out, ind);
if (statement_)
statement_->dump(out, ind);
else
@@ -854,6 +905,15 @@ void PGenerate::dump(ostream&out, unsigned indent) const
case GS_ELSE:
out << " else !(" << *loop_test << ")";
break;
case GS_CASE:
out << " case (" << *loop_test << ")";
break;
case GS_CASE_ITEM:
if (loop_test)
out << " (" << *loop_test << ") == (" << *parent->loop_test << ")";
else
out << " default:";
break;
}
if (scope_name)
@@ -861,7 +921,7 @@ void PGenerate::dump(ostream&out, unsigned indent) const
out << endl;
for (map<pform_name_t,PWire*>::const_iterator idx = wires.begin()
for (map<perm_string,PWire*>::const_iterator idx = wires.begin()
; idx != wires.end() ; idx++) {
(*idx).second->dump(out, indent+2);
@@ -882,7 +942,17 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2);
}
out << " endgenerate" << endl;
out << setw(indent) << "" << "endgenerate" << endl;
}
void PScope::dump_wires_(ostream&out, unsigned indent) const
{
// Iterate through and display all the wires.
for (map<perm_string,PWire*>::const_iterator wire = wires.begin()
; wire != wires.end() ; wire ++ ) {
(*wire).second->dump(out, indent);
}
}
void Module::dump(ostream&out) const
@@ -902,7 +972,7 @@ void Module::dump(ostream&out) const
out << " *) ";
}
out << "module " << name_ << ";" << endl;
out << "module " << mod_name() << ";" << endl;
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
port_t*cur = ports[idx];
@@ -924,7 +994,7 @@ void Module::dump(ostream&out) const
typedef map<pform_name_t,PExpr*>::const_iterator parm_hiter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << " parameter ";
out << " parameter " << (*cur).second.type << " ";
if ((*cur).second.signed_flag)
out << "signed ";
if ((*cur).second.msb)
@@ -932,9 +1002,38 @@ void Module::dump(ostream&out) const
<< *(*cur).second.lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr << ";" << endl;
out << *(*cur).second.expr;
else
out << "/* ERROR */;" << endl;
out << "/* ERROR */";
for (Module::range_t*tmp = (*cur).second.range
; tmp ; tmp = tmp->next) {
if (tmp->exclude_flag)
out << " exclude ";
else
out << " from ";
if (tmp->low_open_flag)
out << "(";
else
out << "[";
if (tmp->low_expr)
out << *(tmp->low_expr);
else if (tmp->low_open_flag==false)
out << "-inf";
else
out << "<nil>";
out << ":";
if (tmp->high_expr)
out << *(tmp->high_expr);
else if (tmp->high_open_flag==false)
out << "inf";
else
out << "<nil>";
if (tmp->high_open_flag)
out << ")";
else
out << "]";
}
out << ";" << endl;
}
for (parm_iter_t cur = localparams.begin()
@@ -950,10 +1049,10 @@ void Module::dump(ostream&out) const
out << "/* ERROR */;" << endl;
}
typedef list<perm_string>::const_iterator genvar_iter_t;
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
for (genvar_iter_t cur = genvars.begin()
; cur != genvars.end() ; cur++) {
out << " genvar " << (*cur) << ";" << endl;
out << " genvar " << ((*cur).first) << ";" << endl;
}
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
@@ -986,12 +1085,7 @@ void Module::dump(ostream&out) const
}
// Iterate through and display all the wires.
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
; wire != wires_.end()
; wire ++ ) {
(*wire).second->dump(out);
}
dump_wires_(out, 4);
// Dump the task definitions.
typedef map<perm_string,PTask*>::const_iterator task_iter_t;
@@ -1021,8 +1115,8 @@ void Module::dump(ostream&out) const
}
for (list<PProcess*>::const_iterator behav = behaviors_.begin()
; behav != behaviors_.end()
for (list<PProcess*>::const_iterator behav = behaviors.begin()
; behav != behaviors.end()
; behav ++ ) {
(*behav)->dump(out, 4);
@@ -1084,3 +1178,20 @@ void PUdp::dump(ostream&out) const
out << "endprimitive" << endl;
}
void pform_dump(std::ostream&out, const nature_t*nat)
{
out << "nature " << nat->name() << endl;
out << " access " << nat->access() << ";" << endl;
out << "endnature" << endl;
}
void pform_dump(std::ostream&out, const discipline_t*dis)
{
out << "discipline " << dis->name() << endl;
out << " domain " << dis->domain() << ";" << endl;
if (const nature_t*tmp = dis->potential())
out << " potential " << tmp->name() << ";" << endl;
if (const nature_t*tmp = dis->flow())
out << " flow " << tmp->name() << ";" << endl;
out << "enddiscipline" << endl;
}
+1 -1
View File
@@ -53,7 +53,7 @@ struct name_component_t {
extern bool operator < (const name_component_t&lef, const name_component_t&rig);
/*
* The pform_name_t is the general form for a heirarchical identifier.
* The pform_name_t is the general form for a hierarchical identifier.
*/
typedef std::list<name_component_t> pform_name_t;
+63
View File
@@ -0,0 +1,63 @@
#!/bin/sh
# This script makes snapshots from a git repository. The input is
# the number for a snapshot and the path to a temporary directory.
# for example:
#
# sh scripts/MAKE_SNAPSHOT.sh 20080428 ~/tmp
#
# The above assumes that there is a tag "s20080428" at the point
# to be snaphot. (The tag has the "s", but the argument to this
# script does not have the "s"). This script extracts based on the
# tag, uses the temporary directory to stage intermediate results,
# and finally creates a file called verilog-20080428.tar.gz that
# contains the snapshot ready to go.
#
# The complete steps to make a snapshot YYYYMMDD generally are:
#
# git tag -a sYYYYMMDD
# (Make the tag in the local git repository.)
#
# sh scripts/MAKE_SNAPSHOT.sh YYYYMMDD ~/tmp
# (Make the snapshot bundle verilog-YYYYMMDD.tar.gz)
#
# git push --tags
# (Publish the tag to the repository.)
#
id=$1
destdir=$2
# The git tag to use is the snapshot id with a prepended "s".
tag="s$id"
# The prefix is the directory that contains the extracted files
# of the bundle. This is also the name of the bundle file itself.
prefix="verilog-$id"
if [ ! -d $destdir ]; then
echo "ERROR: Directory $destdir does not exist."
exit 1
fi
if [ -e $destdir/$prefix ]; then
echo "ERROR: $destdir/$prefix already exists."
exit 1
fi
echo "Exporting $tag to $destdir/$prefix..."
git-archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
versionh="$destdir/$prefix/version.h"
echo "Create $versionh ..."
echo "#define VERSION_TAG \"$tag\"" > $versionh
echo "Running autoconf.sh..."
( cd $destdir/$prefix && sh autoconf.sh )
echo "Making bundle $prefix.tar.gz..."
tar czf $prefix.tar.gz --exclude=autom4te.cache -C "$destdir" $prefix
echo "Removing temporary $destdir/$prefix..."
rm -rf "$destdir/$prefix"
echo done
+6 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -185,8 +185,7 @@ bool NetEBMult::set_width(unsigned w, bool)
bool NetEBPow::set_width(unsigned w, bool last_chance)
{
bool flag = left_->set_width(w, last_chance);
return flag;
return w == expr_width();
}
/*
@@ -414,8 +413,10 @@ bool NetETernary::set_width(unsigned w, bool last_chance)
*/
bool NetEUFunc::set_width(unsigned wid, bool)
{
expr_width(wid);
return true;
if (result_sig_->expr_width() == wid)
return true;
else
return false;
}
bool NetEUnary::set_width(unsigned w, bool)
@@ -445,4 +446,3 @@ bool NetEUReduce::set_width(unsigned w, bool)
{
return w == 1;
}
+4 -1
View File
@@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
* Copyright (c) 2000-2007 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -263,6 +263,9 @@ struct tokenize : public proc_match_t {
last_->next_ = cur;
last_ = cur;
/* Because synthesis is broken this is needed to prevent
* a seg. fault. */
if (!dev->if_clause()) return 0;
dev -> if_clause() -> match_proc(this);
if (dev->else_clause()) {

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