Compare commits

...
926 Commits
Author SHA1 Message Date
Kevin Cameron 4ee9cc6247 Additions and changes for using VVP as DLL with an analog simulator. 2008-11-16 18:29:02 -08:00
Larry Doolittle e0a1b41b37 Correct and enhance some debug_elaborate messages
Make port number self-consistent, starting at 1.
Add messages marking the start and stop of recursive elaboration.
2008-11-16 18:01:23 -08:00
Larry Doolittle fe38f7a9a9 Quiet compiler warnings
Eliminate three "warning: suggest parentheses around assignment used as truth value"
Obviously not needed, but it's easier to add the superfluous parentheses
than remember that these warnings are benign.
2008-11-16 17:57:50 -08:00
Stephen Williams 4892e93a09 Fix special case that one of the arguments of a compare is a real expression.
If one of the arguments of a comparison expression has a real value, then
the expression with is 1 no matter the width of the other argument. This
means that the arguments may have different widths in this special case.
Patch is from pr2251119, suggested by Martin Whitaker.
2008-11-15 21:42:02 -08:00
Martin Whitaker a42eb5cf94 Improved automatic variable error reporting.
This patch moves the checks for automatic variables being passed to
the $monitor or $strobe system tasks from the calltf routine to a
new compiletf routine. It also adds the file name and line number
of an offending call to the error message.
2008-11-15 20:48:41 -08:00
Nick Gasson 1d4ade80b2 Fix select from non-variable-reference error (pr2281519)
VHDL can't select bits from arbitrary expression so sometimes
translating IVL_EX_SELECT would fail. This is easily fixed by
replacing the select with a shift in this instance (and the
resizing)
2008-11-15 20:39:00 -08:00
Martin Whitaker fe199a7593 Fix for pr2276163.
The VVP %join function was incorrectly treating the return from a
non-automatic function as a return from an automatic function in
the case that the non-automatic function result was being used as
a parameter to an automatic function. This patch fixes this error.
2008-11-15 11:04:51 -08:00
Cary R 407ce5e152 Add support for the 1364-2001 generate of a named block.
This is obsolete in 1364-2005, but is supported 1364-2001.
Icarus already supported generate with unnamed block.
2008-11-15 08:08:29 -08:00
Larry Doolittle 1d41037009 Avoid crash with typo in varaible name
A simple typo in the rhs of an expression would crash the compiler.
Example:

module crash3;
reg clk;
integer cnt1=0;
always @(posedge clk) begin
        cnt1 <= (cnt==81) ? 0 : (cnt1+1);
end
endmodule
2008-11-14 22:29:09 -08:00
Stephen Williams 574c8a870d Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-11-14 22:18:20 -08:00
Cary R c278b4e41f Add support for arrayed instances with inout ports.
A NetTran (TRAN_VP) can be used to connect arrayed instance inout
ports. This allows bi-directionality and conflict resolution.
2008-11-14 22:13:41 -08:00
Stephen Williams 91972cd9a1 Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-11-14 21:53:01 -08:00
Cary R dc6a9e03c9 Shifting a signed constant should just return the L-value.
We already covered the case of shifting zero, but the case of
shifting a signed constant was missed.
2008-11-14 21:48:09 -08:00
Cary R 221b83b932 Rework $plusarg routines.
This patch addresses a number of issues:

Rewrote the $test$plusargs and $value$plusargs routines to have
better error/warning messages, to support runtime strings, to
correctly load bit based values (truncating, padding, negative
value), added support for the real formats using strtod() and
added "x/X" as an alias for "h/H" to match the other part of
Icarus.

Rewrite the vpip_{bin,oct,hex}_str_to_vec4 routines to ignore
embedded "_" characters. Add support for a negative value and
set the entire value to 'bx if an invalid digit is found. A
warning is printed for this case.

Rewrite vpip_dec_str_to_vec4 to ignore embedded "_" characters,
to support a single "x" or "z" constant and to return 'bx if an
invalid digit is found. A warning is printed for this case.

It simplifies the system task/functions error/warning messages.

It removes the signed flag for the bin and dec string conversions.
This was not being used (was always false) and the new negative
value support makes this obsolete.

Add support for a real variable to handle Bin, Oct, Dec and Hex
strings. They are converted into a vvp_vector4_t which is then
converted to a real value.

Add support for setting a bit based value using a real value.

Removed an unneeded rfp signal in vpip_make_reg()
2008-11-13 15:56:29 -08:00
Martin Whitaker 69428bb050 Fix for pr2271367.
This patch fixes a bug introduced by one of the checks for illegal
use of automatically allocated variables.
2008-11-13 15:52:17 -08:00
Nick Gasson 256454960c Add complete list of VHDL reserved words
make_safe_name now makes sure a VHDL signal is never given a
name that conflicts with any reserved words. If it does, we
just prepend VL_.

(This code was already present, but the full list of reserved
words wasn't.)
2008-11-13 15:45:41 -08:00
Stephen Williams d06092d7d7 Merge branch 'vhdl' 2008-11-13 15:45:37 -08:00
Martin Whitaker 416bd35f2e Fix for leak in thread vector allocation.
In the vvp code generator, when zero/sign extending a sub-expression,
the sub-expression is first evaluated and stored in one location in
the thread vector store, then is copied and extended into a second
location. The storage used for the initial sub-expression evaluation
is never deallocated.
2008-11-12 22:12:00 -08:00
Stephen Williams 87654f8661 Fix bug generating code for shift of constant zero.
The code generator detects this case, but instead of returning the
constant zero, it breaks out and writes partial code for the shift.
2008-11-12 21:46:23 -08:00
Stephen Williams 9f2b5cd9b7 Make the associative sum constant elimination more resilient to size details.
The NetEBAdd::eval_tree method is able to use the associative property
of addition to reduce some constants, but it is picky about widths.
Make it a little bit more resilient to expression widths.
2008-11-12 20:59:10 -08:00
Nick Gasson 5fd32937f2 Fix overly restrictive check for slices
Fixes some instances of "can only select from a variable reference"
2008-11-12 22:26:44 +00:00
Nick Gasson f1a2e71aab Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-11-12 22:15:57 +00:00
Stephen Williams 7c50c9aedf Scan concat arguments with test_width.
Even though we cannot immediately give a width for a concatenation
that has a repeat expression (the expression must be evaluated first)
we still must scan the test_width of the arguments so that they can
resolve their types.
2008-11-11 21:09:19 -08:00
Martin Whitaker 04377151bc Checks for illegal use of automatically allocated variables.
This patch adds a number of compile and run-time checks for illegal
uses of variables declared in automatic tasks and functions. It
also adds a check for event expressions in automatic tasks that use
features not yet supported in VVP.
2008-11-11 20:45:19 -08:00
Cary R bbdf622ea5 Fix numerous problems with the divide and modulus operators.
This patch fixes a number of problems related to the divide and
modulus operators.

The net version (CA) of modulus did not support a signed version.

Division or modulus of a value wider than the machine word did
not correctly check for division by zero and return 'bx.

Fixed a problem in procedural modulus. The sign of the result is
only dependent on the L-value.

Division or modulus of a signed value that was the same width as
the machine word was creating an incorrect sign mask.

Division of a signed value that would fit into a single machine
word was not checking for division by zero.

Division or modulus of a wide value was always being done as
unsigned.

Added a negative operator for vvp_vector2_t. This made
implementing the signed wide division and modulus easier.
2008-11-07 19:58:00 -08:00
Cary R 1e06a2ddef ivlpp - clear lexor dynamic state information for flex >= 2.5.9
For flex version 2.5.9 and later there is a function
"yylex_destroy()" that clears any space dynamically
allocated by the scanner.
2008-11-04 16:01:47 -08:00
Cary R 049290d0fc Fix a memory leak and release all dynamically allocated memory (ivlpp)
This patch fixes a minor memory leak in ivlpp and releases all
dynamically allocated memory before the program exits. Other than
the dynamically allocated push state buffer in flex, ivlpp has no
valgrind memory errors or warnings.
2008-11-04 11:58:49 -08:00
Cary R 4c67bd0b35 Fix memory leak and free temp. file names to make valgrind happy.
There was a memory leak in the preprocess_only code (cmd was not
being freed when the command completed successfully.  Valgrind
was also marking the temporary file names as still reachable, so
they are not memory leaks, but freeing them makes valgrind happier.
2008-11-04 11:41:31 -08:00
Stephen Williams 4f7457fcec Merge branch 'verilog-ams' 2008-11-04 11:37:58 -08:00
Cary R 95ea159e75 Print `include comment after included text.
The inline comment text that appears after an `include directive
should appear after the included text not before.
2008-11-04 11:26:27 -08:00
Stephen Williams ddb2c60701 Remove svector class from Module.h
The goal is to completely remove the svector class because the standard
vector class works perfectly well. This removes the uses in the Module.h
header file.
2008-11-02 20:08:38 -08:00
Stephen Williams 77eb68d314 Minor documentation improvements. 2008-11-02 16:56:25 -08:00
Stephen Williams f4687757f1 Bring signal discipline all the way to the ivl_target API.
Signals may have VMA disciplines attached. Make the attached discipline
visible through the ivl_target.h API. Also, re-arrange the internal
handling of the discipline structure so that we can expose disciplines
through the ivl_target C API without creating new structures. The
t-dll-api implementations of the discipline access functions can look
at the elaborated discipline structure directly. This is possible since
the discipline parse and elaboration are very simple.
2008-11-02 08:10:41 -08:00
Stephen Williams b20019d8b6 Merge branch 'master' into verilog-ams 2008-11-01 21:09:29 -07:00
Stephen Williams 6cac1d2cab Add support for real/realtime arrays.
Support arrays of realtime variable arrays and net arrays. This
involved a simple fix to the ivl core parser, proper support in
the code generator, and rework the runtime support in vvp.
2008-11-01 20:44:03 -07:00
Larry Doolittle 520d9b9dd0 Touch up new developer quick start
Spelling and other minor touch-up for the new and
much-appreciated developer-quick-start.txt
2008-10-31 20:44:54 -07:00
Stephen Williams 403a1e9415 Add a dup_expr method to NetEUBits.
The NetEUBits needs to create a NetEUBits when the dup_expr method is
called, so it needs its own dup_expr method.
2008-10-30 22:11:05 -07:00
Larry Doolittle 9b640f3114 Shadow reduction part 4
Continue cleaning up shadowed variables, flagged by turning on -Wshadow.
No intended change in functionality.  This patch set covers the tgt-vhdl
directory, and was tested by Nick.
2008-10-30 21:46:44 -07:00
Cary R 7ac35e478b The scope of real values needs to be calculated.
Finding the scope of a real value is no longer simple, so it must
be calculated.
2008-10-30 21:41:36 -07:00
Cary R 2c7fe8aa2a Fixes for real VPI interface, etc.
This patch fixes some problems found when trying to dump words
from a real wire array. There are still a few more things that
look suspicious and need testing.
2008-10-30 21:41:28 -07:00
Stephen Williams 1ec09327e9 Elaborate divide expressions to the proper width.
If the operands of a divide expression are fixed width, pad them out
to the width of the expression so that the calculations come out right.
2008-10-30 21:19:56 -07:00
Nick Gasson ea9bbf804c Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-10-30 20:00:53 +00:00
Stephen Williams 1922a0df9e Fix C++ compiler warning.
classes with virtual methods must have virtual destructors. Otherwise,
destruction may not work corectly.
2008-10-29 21:03:44 -07:00
Martin Whitaker 18edf2f15f Rework of automatic task/function support.
This patch splits any VVP net functor that needs to access both
statically and automatically allocated state into two sub-classes,
one for handling operations on statically allocated state, the
other for handling operations on automatically allocated state.
This undoes the increase in run-time memory use introduced when
automatic task/function support was first introduced.

This patch also fixes various issues with event handling in automatic
scopes. Event expressions in automatic scopes may now reference either
statically or automatically allocated variables or arrays, or part
selects or word selects thereof. More complex expressions (e.g.
containing arithmetic or logical operators, function calls, etc.) are
not currently supported.

This patch introduces some error checking for language constructs
that may not reference automatically allocated variables. Further
error checking will follow in a subsequent patch.
2008-10-29 20:43:00 -07:00
Stephen Williams ea057a7574 Elaborate logical and/or to account for special properties.
The arguments of logical and/or are self determined, and the width is
fixed as 1 bit. Account for this special behavior by creating the
PEBLogic class.
2008-10-29 20:31:26 -07:00
Stephen Williams b7d3276e4d Enforce bit width of operands of comparisons operators.
The comparison operator operands are self determined, but are forced
to be the width of the wider operand. This means that the operands must
be evaluated with their widths truncated. In spite of all this, note
that comparisons expression results are 1 bit wide.
2008-10-29 19:34:44 -07:00
Cary R 22ddb26389 Add support for arrays of real nets.
This patch adds support for arrays of real values nets (wire real).
2008-10-27 21:45:02 -07:00
Stephen Williams 9b89ca49bb Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-10-27 21:39:47 -07:00
Stephen Williams 94e7d71b97 Make sure divide expressions are evaluated using the expression width.
The operands of divide need to be at least the width of the expression
when calculating a constant divide. The only matters for the special
case where the result is x, because the verinum implementation of
divide will get the result width from the left expression width.
2008-10-27 21:39:07 -07:00
Stephen Williams 810686d88e Merge branch 'master' into verilog-ams 2008-10-27 09:23:13 -07:00
Stephen Williams 0bd1739225 Merge branch 'vhdl' 2008-10-27 09:19:13 -07:00
Stephen Williams 038b024e71 Merge branch 'master' into verilog-ams 2008-10-26 21:59:53 -07:00
Stephen Williams 27410f5d88 Remove the now obsolete NetNet list in NetScopes.
Now that NetNet objects in NetScopes are kept in a map, remove the
linked list for scanning them. This improves the lookup process from
an O(e**N) process to more like O(log(N)). This matters for very
large designs.
2008-10-26 20:42:11 -07:00
Stephen Williams 0af896a7ff Keep a map of NetNets for fast access.
It turns out that netnets in scopes are accessed a lot, and mapping
them may help with performance.
2008-10-26 16:50:46 -07:00
Stephen Williams 81a0007f22 Add developer quict start.
Some basic documentation to help new developers get oriented.
2008-10-26 16:34:21 -07:00
Stephen Williams 2a5ea9e874 Remove the vpip contents.
These files are (were) related to the old vvm backend that is no longer
in use. Thus, these files are dead code.
2008-10-26 14:29:09 -07:00
Stephen Williams b9272f750d Update the BUG submission guidlines. 2008-10-26 13:43:35 -07:00
Nick Gasson f49a4e4336 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-10-26 12:48:22 +00:00
Cary R 26e1693b2f generate case items can have an optional statement.
generate case supports optional statements by putting
 a ';' in place of the statement. This patch adds
this functionality for all generate case items.
2008-10-25 23:27:00 -07:00
Stephen Williams 68fbb94b3a Basic elaboration of analog contribution statements.
Get at least basic elaboration of analog processes and contribution
statements. Bring the statements and analog statements together and
net future elaboration work sort out which statements are valid in
a given context. This makes sense because there really is a lot of
syntactic overlap, and analog behavioral code is processed somewhat
sequentially.
2008-10-22 21:56:00 -07:00
Stephen Williams 5aa810dde7 Infrastructure for elaborating analog statements.
Put together the infrastructure for elaborating analog statements,
including create the NetAnalogTop objects that hold analog statements
and are in turn held by the design.

While doing this, clean up the various unique initial/always enumerations
to use the ivl_process_type_t type.
2008-10-21 22:15:49 -07:00
Larry Doolittle 365960df9d Spelling fixes
No code changes.
2008-10-21 19:55:19 -07:00
Cary R 644465ccc1 Remove one input is const. Z mux optimization.
The optimization that allowed a mux that had one input always
connected to high-Z produces code that is actually slower than
the original mux, so for now we are removing that optimization.
2008-10-21 19:51:07 -07:00
Larry Doolittle 904e76f176 Shadow reduction part 3
Continue cleaning up shadowed variables, flagged by turning on -Wshadow.
No intended change in functionality.  Patch looks right, and is tested
to compile and run on my machine.  No regressions in test suite.
2008-10-20 21:43:02 -07:00
Cary R de2b10b445 An optimized mux should use MOS devices not bufif devices.
The bufif devices do not correctly propagate the Z value as
required by the standard. The MOS devices do propagate a Z
value, but they do not correctly handle the case where both
inputs are Z and the select is undefined/Z. The standard
specifies that this should be X, but we produce Z. The full
MUX and %blend operator also function this way, so Icarus
may not match the standard, but it is consistent. I would
also argue that the standard is incorrect. If both inputs
are Z then the output should be Z no matter what select is.
2008-10-20 21:34:00 -07:00
Stephen Williams a654bdc169 Clean up some handling of test_width for ternary expressions.
The condition expression needs its width tested, even if the width
is not used. Also clean up some handling of widths/types for other
expression types.
2008-10-18 22:00:22 -07:00
Martin Whitaker cb2ed9210c Fix for pr2169870.
This patch fixes a bug which prevented storage being allocated for
automatic tasks that had no input or output parameters.
2008-10-16 21:06:38 -07:00
Cary R 50550ca79e Fix %ix/getv and %ix/getv/s documentation.
These two operators had their arguments wrong.
2008-10-16 21:03:00 -07:00
Larry Doolittle f3cb18343a Conditional test width
Add the test_width call for PCondit expr_
Very similar to commit 5fdd9d8339
2008-10-16 21:00:36 -07:00
Cary R c6a5a43620 Fix port signedness calculation.
This fixes the sign calculation for port padding. It also reports if
the padding will be signed or not in the warning message. The inout
calculation may not be correct. It requires both the signal and the
port to be signed, but inout is not currently padded anyway.
2008-10-16 20:55:09 -07:00
Cary R b0e57a1a67 Ignore PS that are outside the signal and allow PS to extend past the signal.
If a part select (either a constant or constant indexed part select)
of a L-value is fully outside the signal the part select will be
omitted after printing a warning. If a part select straddles the
upper portion of a signal a warning will be printed. The run time
will use only the appropriate part of the select. Straddling the
lower part of the signal is not currently supported and a message
is printed for this case.
2008-10-14 19:47:55 -07:00
Stephen Williams 5fdd9d8339 Test the width of expression for shift amounts.
The right-operand of shift expressions is self-determined, but we still
need to run a test_width to get the PExpr decorated with types and
expression widths.
2008-10-14 19:36:48 -07:00
Nick Gasson 8a3309d79d Add a comment to the output about casex/z translation 2008-10-14 20:21:19 +01:00
Nick Gasson a47b7352b4 Add casex/z support
A casex statement cannot be directly translated to a VHDL case
statement as VHDL does not treat the don't-care bit as special.
The solution here is to generate an if statement from the casex
which compares only the non-don't-care bit positions.
2008-10-14 20:16:10 +01:00
Stephen Williams fff5e494ed Do not truncate subtraction expressions based on l-value.
The l-value doesn't really constrain the size of unsized expressions
because there are possible sub-expressions that may pull high bits
down to the low bits. (Divide, for example.)
2008-10-13 22:06:03 -07:00
Stephen Williams 1c90997499 concatentations that reduce to constants need proper signed-ness
It is possible, via the use of the $signed() function, for concatenation
expressions to be signed. Make sure the evaluated constant had the
proper sign by checking explicitly.
2008-10-13 20:50:56 -07:00
Stephen Williams 1a3e655285 Merge test_width rework
This collection of patches fixes a variety of bugs with the handling
of signed-ness in exprsesions.
2008-10-13 20:23:50 -07:00
Larry Doolittle 3adcbb5611 Shadow reduction part 2
Continue cleaning up shadowed variables, flagged by turning on -Wshadow.
No intended change in functionality.  Patch looks right, and is tested
to compile and run on my machine.  No regressions in test suite.
2008-10-13 20:12:47 -07:00
Martin Whitaker 647b3e5bda Bias storage of events towards static scopes.
This patch modifies the code that finds and combines similar events
such that if similar events are found in both static and automatic
scopes, the retained event will be in a static scope. This is a
performance enhancement, as VVP has more run-time overhead when
handling events declared in an automatic scope.
2008-10-13 20:10:22 -07:00
Cary R c41fb50929 Copy from the existing function when duping a system function.
This code was likely never checked properly since it makes no
sense to copy the expression from the new temporary system
function. You must copy the value from the current function.
2008-10-13 20:06:41 -07:00
Stephen Williams c5d4d9eec1 Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-10-13 20:00:49 -07:00
Cary R 9cb62a4d64 Check that numbers fit into the correct immediate width (32 bits).
Even on 64 bit machines immediate values should be limited to
32 bits so that the a.out file will run correctly on a 32 bit
machine. This patch fixes a number of places where the code
generator was not checking for/observing this.
2008-10-13 19:56:46 -07:00
Stephen Williams 25f6282a54 Generate signed comparisons independent of the signedness of the expression
The signedness of comparison expressions is typically unsigned, even if
the comparison to be performed is signed. The comparison (and particularly
the expr_synth of the comparison) needs to account for this explicitly.
2008-10-13 19:43:02 -07:00
Stephen Williams 55b8ff4441 Pad the subexpression of unary not.
The operand of unary not needs to be padded to the expression width
before the operator itself. Otherwise, the high (pad) bits will come
out wrong.
2008-10-12 21:38:07 -07:00
Stephen Williams 62f518c205 The signedness of a ternary expression comes from its operands.
If either of the operands of a ternary expression are unsigned, then
both are treated as unsigned. It works just like a binary expression
in that regard.
2008-10-11 21:52:41 -07:00
Stephen Williams 864a86f7ee Multiply nodes are always unsigned.
It is up to the elaborator to sign-extend the inputs if the multiply
is signed in the Verilog source. The run time always processes the
multiply as unsigned.
2008-10-11 21:08:14 -07:00
Stephen Williams 995fc380e8 Get padding of signed comparison operands.
The results of comparisons are unsigned, but the arguments may be signed
and the calculation performed may be signed. Handle the padding properly
for comparisons so that the math is properly signed.
2008-10-11 09:20:49 -07:00
Stephen Williams bd71b7fbb2 Real valued multiply are always signed.
By definition.
2008-10-11 09:19:11 -07:00
Stephen Williams 3a99a5e800 Suppress operand has_sign if expression is unsigned.
Fix processing of arguments of +- and * when only one of the operands
is signed.
2008-10-11 08:39:06 -07:00
Stephen Williams a9497e9c6a Less agressive padding of unsized lossless addition.
When doing lossless addition to an unsized constant, we make the size
be width of an integer, only to be consistent with other tools. In fact,
don't go overboard if we don't have to.
2008-10-10 20:45:11 -07:00
Stephen Williams c85eff93f2 The test_width methods scan and mark expressions with type and size.
Later passes need the intermediate results for width and size so that
some special cases, were self-determined arguments occur, can be
processed properly during elaboration. This can be especially tricky
and interesting for ternary expressions.
2008-10-10 20:42:07 -07:00
Larry Doolittle c010145eaf Shadow reduction part 1
Start cleaning up shadowed variables, flagged by turning on -Wshadow.
No intended change in functionality.  Patch looks right, and is tested
to compile and run on my machine.  YMMV.
2008-10-09 11:55:26 -07:00
Martin Whitaker b5ad161f90 Fix for pr2148500.
This patch fixes the expression width calculation for a multiply
operation with an unsized operation. The expression width needs
to be at least the minimum of the maximum multiply result width
and the width of an integer.
2008-10-09 11:52:40 -07:00
Martin Whitaker 610dedc2b8 Fix for pr2146824.
Currently, a bitwise boolean operator will cause the expression
width to be reduced to the size of the result. This can give
rise to incorrect results. This patch changes the behaviour to
take into account the required precision for calculating the
two operands.
2008-10-09 11:33:14 -07:00
Martin Whitaker 082e06edb0 Remove checks for constant expressions from the parser.
This patch removes all the checks for constant expressions performed
during the parsing phase, as these checks are (mostly) repeated during
elaboration. It adds the missing check in the elaboration phase (the
RHS of a register initialisation), and improves the error reporting
and error recovery in other checks.

This patch fixes pr2132552, which was caused by a fault in the parser
constant expression checking.
2008-10-09 11:11:32 -07:00
Nick Gasson fd4018cb33 Fix IVL_LPM_MUX where inputs are different signedness to outputs 2008-10-05 17:08:19 +01:00
Nick Gasson b40de5ccb0 Implement IVL_LPM_CMP_NE(E)
Looks like I forgot this one
2008-10-05 17:04:19 +01:00
Nick Gasson a7cbb38248 Fix resizing of constant bit vectors
Emitting a VHDL expression like Resize("01", 32) is ambiguous
between interpreting "01" as a Signed or an Unsigned. There's
no point actually outputting this as we can sign-extend the
constant value in the code generator, which is what this
patch does.
2008-10-05 13:49:07 +01:00
Nick Gasson 4394aff909 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl
Conflicts:

	tgt-vhdl/stmt.cc
2008-10-05 12:44:30 +01:00
Stephen Williams 5cfe47da2b Don't try to shrink a valid r-vlaue width.
In assignments, the expression width may be defined by the width of
operands, and not that of the l-value. Choose whichever is creater and
set (or pad) the expression to that width.
2008-10-04 21:44:10 -07:00
Stephen Williams cc9e3d1536 Comments should be tossed by the lexor.
It is silly to use yymore() to collect even more of the comment so that
it can be tossed at the tail end of the comment processing. So don't.
2008-10-04 20:35:22 -07:00
Stephen Williams 03fd124d5a Handle multiply with constant zero.
Multiply of any expression with constant 0 will always return zero.
We can handle this early, during elaboration, and save a lot of code
downstream the trouble.

Also, while we are at it, fix up test_width to re-test the left
expression width if the right expression width is unsized. This allows
for the left expression code to adapt to the unsized-ness of the
expression context.
2008-10-04 20:01:19 -07:00
Stephen Williams 18de6980ff Fix associative add tree to get result width correct.
When evaluating A+1+2 in eval_tree, the (1+2) needs to have the correct
result width, or the elaborated expression with will be lost.
2008-10-03 19:52:26 -07:00
Cary R 5fd3be570e Pad input and output ports correctly.
This patch pads inputs and output ports correctly when the port
and the port expression have different widths. It does not fix
inout ports.

It also sets the file and line number information in the unsigned
pad_to_width() routine.
2008-10-03 17:40:05 -07:00
Cary R bd504ea14e Do not evaluate parameters too early.
This patch pushes the evaluation of constant system functions into
normal elaboration vs doing them in the preliminary parameter
elaboration.

It also fixes the compiler version of clog2 to return integer_width
vs a fixed 32 bits.
2008-10-03 17:29:10 -07:00
Stephen Williams aebd9c2bc7 Sign extend r-values that refuse to pad themselves.
There are cases where the r-value doesn't pad itself to the width
that is requested by the call to elaborate_expr. This impacts the
elaboration of PGAssign. Pad/sign extend as appropreate.
2008-10-02 22:02:35 -07:00
Stephen Williams 7b4fda8785 Process arguments to bitwise operator using singned/unsigned rules.
The arguments to bitwise operators are padded if *either* of the operands
is unsigned. This is according to the sign/unsigned expression rules
of Verilog, and also matches the behavior of the "Big-3."
2008-10-01 22:38:53 -07:00
Jared Casper feba5d9470 Compatibility with gcc-4.3
The addition of UINT_MAX in netlist.cc requires #include <climits> when compiling with gcc-4.3.2.

I also noticed that commit 8704e3e used c style includes in c++ sources contrary to the style used in the rest of the c++ code and fixed those.
2008-09-30 21:57:25 -07:00
Cary R 6b62cce14a Produce a better message for ! and real values.
In the transition to the new expression code we forgot how to
handle the logical not (!) of a real value. This patch adds a
more appropriate error message until we get this reimplemented.
2008-09-30 21:53:25 -07:00
Cary R 3bce8bb995 GetProcAddress expects no underscore (MinGW)
MinGW uses the GetProcAddress() function to find the address of
the vlog_startup_routines() procedure in a .vpi file. This routine
requires that the leading underscore be omitted from the name even
though the underlying routine really has one.
2008-09-30 21:51:28 -07:00
Cary R 716853699f Initialize real value in automatic functions.
alloc_instance for real values was just passing a new double
to be added to the context items. The new constructor does
not set the default value so we need to do that manually.
2008-09-30 21:48:13 -07:00
Stephen Williams 55a15d604d Pad operands of bitwise operators.
When elaborating bitwise operators width context determined width,
pad the operands.
2008-09-30 21:35:09 -07:00
Stephen Williams b548dec070 Width of identifier accounts for expression minimum
When the test_width method is called with a expression min width,
then the PEIdent::test_width needs to honor that minimum.
2008-09-29 22:04:28 -07:00
Stephen Williams 2da50e1788 Cast to real when add arguments have mixed type.
When synthesizing, be careful (especiall for addition) that if the
arguments are mixed, then cast the non-IVL_VT_REAL arguments to
IVL_VT_REAL.
2008-09-29 21:02:37 -07:00
Stephen Williams 3aaea46144 Content-free portability fixes.
These are patches from ITOH Yasufumi and Larry Doolittle of pr2120948.
They change nothing, but make the code compile with older compilers.
2008-09-29 18:06:47 -07:00
Stephen Williams 2251844124 Merge branch 'master' into expression-width-rework 2008-09-28 21:21:41 -07:00
Stephen Williams 729771e562 Check expression width for sanity
Assertion to check for insane expression widths that are likely caused
by compiler bugs.
2008-09-28 08:58:08 -07:00
Stephen Williams 0bb1f9740b Fix width of short circuit FALSE clase of Ternary / Fix expr type if system functions
Simple error setting the expression width of the FALSE clause of a
ternary expression when the expression is short cuirted to false.

Fix a simple error where the type of a system function is not returned
through the test_width function.
2008-09-28 08:57:25 -07:00
Martin Whitaker 7ebcc6b357 Support for automatic tasks and functions.
This patch adds support for automatic tasks and functions.
Refer to the overview in vvp/README.txt for details.
2008-09-27 15:51:16 -07:00
Stephen Williams 3296b1dee3 Include a calculation of the expression type in test_width methods.
The type of the sub-expression is sometimes needed by clients of the
test_width methods, so add that as an output.
2008-09-26 22:20:11 -07:00
Stephen Williams 42d412c626 Unify all the r-value elaboration.
R-value expression elaboration happens in several places. Factor out
the common code so that they are all handled correctly and uniformly.
2008-09-25 21:22:21 -07:00
Stephen Williams 4919b70da6 Give l-value nets their proper type.
L-value nets (i.e. in continuous assignments) that were words in
arrays need to have the data type of their parent array.
2008-09-25 21:21:00 -07:00
Stephen Williams d3f17f27c1 Handle widths of real value arguments to user functions.
The arguments to user defined functions are self-determined. And if
the result is real valued, we can call them lossless self-determined.
Treat these arguments like r-value elaboration for assignments.

Also clean up the binary divide elaboration a little bit.

Also, floating point literals are unsized with width==1.
2008-09-25 20:37:18 -07:00
Stephen Williams 873ed60ff8 Multiply of real values has width of 1.
When a multiply expression is IVL_VT_REAL, then the default width is
the width of the operands, and not the sum of the operands. In fact, it
should turn out to be 1.

Also, the width of the multiply expression when we get to the ivl_target
API, need not be the sum of the widths of its arguments. In fact, if the
arguments are signed, that would be completely wrong. So adjust the
stub target to properly test this constraint.
2008-09-25 20:33:29 -07:00
Stephen Williams ce7dd6b4ff Account for real type l-values when working with widths.
Widths of real values are always 1. When paired with vectorable types
in expressions, the vectorable type is processed as losslessly self-
determined. ("unsized" in the test_width methods.)
2008-09-22 21:09:06 -07:00
Stephen Williams 2381fc72b0 Constants may take on the width of the l-value.
Don't force the expression with to be different from the l-value if the
l-value is the immediate destination. This saves the effort of handling
overly wide constant values in simple cases.

Also, in determined contexts, signed unary minus does not need to pad the
width of the expression.
2008-09-21 18:14:26 -07:00
Stephen Williams 6e12c1f236 Elaborate of PGAssign always passes calculated width.
the PGAssign elaborate method used the test_width to get the width
of the r-value expression. This should be completely sufficient to
get the width of the expression, so always use a defined width to
elaborate the expression.
2008-09-20 19:23:54 -07:00
Stephen Williams dc313436c1 Self-determined ternary expressions use better width tester.
When ternary expressions are self-determined, use the test_width
method to get a proper reading of the expression width. Also improve
the test_width method to handle unsized operands.
2008-09-20 18:17:17 -07:00
Stephen Williams 46bf03bba4 Pad signed arguments to multiply
Arguments to multiply that are signed must be the width of the output
for the 2s complement multiply to work correctly.
2008-09-19 22:00:29 -07:00
Cary R 103b351641 Document the %assign/av/e opcode. 2008-09-19 21:13:01 -07:00
Cary R f7d3c7c711 Add non-blocking EC for arrays and other fixes.
This patch adds non-blocking event control for array words.
It also fixes a problem where the word used to put the
calculated delay for a non-blocking array assignment was
not being released. It also fixes the non-blocking array
assignments to correctly handle off the end/beginning part
selects.
2008-09-19 21:08:03 -07:00
Cary R a39b9d4ef1 Elaboration debug messages should depend on debug flag.
The debug messages for the ternary were missing a conditional
on the debug flag.
2008-09-19 20:49:02 -07:00
Martin Whitaker a4973c217d Support parameter, localparam, and event declarations in any scope.
Currently, parameters and localparams declared in tasks, functions,
generate blocks, and named blocks are placed in the parent module
scope. Event declarations in these scopes are not permitted (a
syntax error is reported). This patch corrects this behaviour, so
that all the above declarations are accepted and are placed in the
scope in which they are declared.

Note that the IEEE standard does not permit parameter declarations
in generate blocks. This patch causes the parser to reject such
declarations.
2008-09-19 20:23:14 -07:00
Cary R 626394d198 Some event control assigns can be skipped so add an event clear.
Since some event control assignments can be skipped we need an
event control clear so that future %evctl statements do not fail
their assert. This patch adds %evctl/c and uses it in the compiler
as appropriate to keep the event control information in sync.
2008-09-19 20:04:51 -07:00
Cary R 8ffec473ef Add event control for vectors and parts of a vectors.
This patch adds full event control for vectors and parts of a
vector. It also fixes the other non-blocking part select code
to correctly handle a negative offset ([1:-2] of a [4:0] will
have an offset of -2).
2008-09-19 19:46:33 -07:00
Stephen Williams 38e62bb1d2 Fix conversion of negative integer to real.
When an integer/bool value is constant and negative,
and is used in a real-valued context, fix the
code generator calculation of the negative value.
2008-09-19 17:04:40 -07:00
Cary R 2d1e0b3ade When evaluating a constant into an index make sure to clear bit 4.
When evaluating an expression into an index register bit 4 is used
to determine if the expression had any X/Z bits. In the case of a
constant immediate value this can not happen so make sure the bit
is cleared.
2008-09-18 21:52:00 -07:00
Cary R 3ba9e945d7 Fix MinGW to us _snprintf in tgt-vvp/vvp_process.c
We need consistent pointer output (%p) and under MinGW we need to
us _snprintf instead of snprintf to get this. The recent event
control addition missed this. This has been reported to the MinGW
developers and they are working on a solution.
2008-09-18 14:53:42 -07:00
Larry Doolittle 2a1608c075 Configure UL_AND_TIME without warnings
The previous patch (commit 8b0ca902a6)
dealing with the possibilities of (unsigned long) and (vvp_time64_t)
being either the same or different managed to redefine UL_AND_TIME64_DIFF
in the 64-bit case.  This does, of course, trigger a compiler warning.
That warning is repeated on every .cc file with a #include "config.h",
which is to say, just about every file.

This patch inverts the sense of the preprocessor conditional, calling
it UL_AND_TIME64_SAME.  No more warnings!
2008-09-18 14:49:11 -07:00
Stephen Williams 411ee517ee Instance arrays with multiple outputs and not vectorized.
It takes a carefully crafted source file to cause elabortion to make
an arrayed multiple-output gate that is not vectorized into a single
wide gate. But that special case does need to be handled.
2008-09-16 21:03:26 -07:00
Cary R 8b0ca902a6 We don't need a special vector4_to_value if vvp_time64_t == unsigned long.
When vvp_time64_t is equivalent to an unsigned long we do not want
(cannot have) both an unsigned long and vvp_time64_t version of
vector4_to_value().
2008-09-16 20:00:58 -07:00
Cary R 6f46930c23 Make it an error to have a `timescale inside a module definition.
While the standard is not completely clear about this, we are making
it an error for a `timescale directive to be inside a (macro)module
definition. This means that all modules and any statements contained
within have a single well defined time unit and precision.
2008-09-15 21:25:41 -07:00
Stephen Williams 0e699ca226 Handle logic gates with multiple outputs.
Logic gates usually have one output and several inputs, but a few
have multiple outputs and one input. Since the NetNode objects have
only a single output, handle the case by creating multiple NetNode
objects, one for each output.
2008-09-14 21:04:03 -07:00
Cary R 5463e5e66b More refinements on negative real variable delays.
This should do the rounding correctly on real negative delay
values.
2008-09-14 09:13:03 -07:00
Cary R 441f173ced Variable delays for .delay must be scaled correctly.
A variable that is used to set the delay of a .delay statement
must be scaled to match the local units and for real values
rounded using the precision. This value is then converted to
the simulation precision.
2008-09-14 09:12:53 -07:00
Stephen Williams d3d54144ff Be more explicit with the type matching rules.
Signals of a nexus must have types that exactly match, but the drivers
of a signal nexus have slightly more subtle rules for the case where
the signal is IVL_VT_LOGIC. Express those rules in the function
check_signal_drive_type, and use it to check the type of constants
driving a signal.
2008-09-13 20:22:48 -07:00
Stephen Williams e4c9ad2b17 Remove redundant NetPins node pointer.
Remove redundant pointer to the containing NetPins object by keeping
the pointer only in the first Link (pin 0) of an array of links. In
this link, replace the pin number with the NetPins pointer, and set
a pins_zero_ flag to indicate that this has happened. This way, only
the first pin in a Link array will have the pointer to the NetPins
that contains the array, and the pointer takes up practically no space
at all.
2008-09-13 19:49:38 -07:00
Stephen Williams 0339e9eb1e Cleanup unused junk in NetAddSub class.
This class was old, and its original design pulled literally from
the LPM reference. But of nine pins declared, only 4 were used.
Remove all the excess junk and clean up the designed dump handling
of the device.
2008-09-13 18:28:43 -07:00
Stephen Williams 7d6b391572 In continuous assignment, r-value is sized or lossless, never self determined.
The r-value expression takes on at least the width of the l-value. If
there is a sized width greater then the l-value width, take that on
instead. But if the r-value is unsized, there are unsized sub-expressions
that cause the expression as a whole to be unlimited width, so elaborate
and evalulate the r-value as lossless.
2008-09-13 17:40:19 -07:00
Stephen Williams 804f5a94d5 Manage expression types for ternary a little better.
The true and false expression clauses must have compatible types,
which are not necesarily identical. In particular, VT_BOOL and
VT_LOGIC are compatible for the purposes of ternary arguments. The
test in NetETernary::synthesize was incorrect.

In the process, fix the type handling of NetConst objects to allow
for IVL_VT_BOOL constants. This is information that the downstream
may find useful, so should be handled correctly.
2008-09-13 16:43:39 -07:00
Cary R 3d5998cd63 Allow variable delay in continuous assignments.
Add the ability to delay continuous assignments using a
variable delay.
2008-09-13 15:01:23 -07:00
Nick Gasson eda1df5df2 Avoid processing tgt-vhdl/Makefile.in twice
It's processed once by AC_OUTPUT in configure.in and then again
by AC_OUTPUT in tgt-vhdl/configure.in. This is a bug from when I
first started on the VHDL target, and was basing it on the tgt-vvp
code. The call to configure in the tgt-vhdl directory is not
actually necessary either, since it doesn't do any checks not
performed elsewhere, so that should proably be removed later.
2008-09-13 14:57:33 -07:00
Stephen Williams 3d86cc1a15 Reduce the size of Link class objects.
Put the enumerated members of the Link class into bit fields to keep
the size down to a minimum.
2008-09-13 14:51:42 -07:00
Nick Gasson c5263268ed Tidy up reduction functions in support.cc
This removes some unnecessary code duplication as the functions
only differ (or need to differ) in two places.
2008-09-13 18:20:12 +01:00
Nick Gasson e5abe182c1 Add reduction XOR/XNOR in expressions 2008-09-13 18:09:11 +01:00
Nick Gasson e5343ef73f Implement arithmetic right shift >>>
This is currently implemented using the numeric_std
shift_right function as the sra operator is not defined on
signed/unsigned types before VHDL-2006.
2008-09-13 15:23:42 +01:00
Cary R 1f9f73a4be Modify $realtime to use vpiScaledRealTime
$realtime should use vpiScaledRealTime instead of scaling the
time itself. This also allows it to work for time over 32 bits.
2008-09-12 20:36:08 -07:00
Cary R 1e60754ff0 Partial non-blocking event control implementation
This patch pushes the non-blocking event control information to
the code generator. It adds the %evctl statements that are used
to put the event control information into the special thread
event control registers. The signed version (%evctl/s) required
the implementation of %ix/getv/s to load a signed value into
an index register. It then adds %assign/wr/e event control based
non-blocking assignment for real values. It also fixes the other
non-blocking real assignments to use Transport instead of inertial
delays.
2008-09-12 20:00:28 -07:00
Larry Doolittle cdfb2315cf One more signed vs unsigned comparison fix
Introduced in a8ad505af7
Various improgements to expression ::synthesize methods
2008-09-12 19:39:15 -07:00
Nick Gasson 2516d63805 A basic translation of the Verilog power operator to VHDL
The exponentiation operator in VHDL is not defined for numeric_std
types. We can get around this by converting the operands to integers,
performing the operation, then converting the result back to the
original type. This will work OK in simulation but certainly will not
synthesise unless the operands are constant.

However, even this does not work quite correctly. The Integer type in
VHDL is signed and usually only 32 bits, therefore any result larger
than this will overflow and raise an exception. I can't see a way
around this at the moment.
2008-09-12 20:19:22 +01:00
Stephen Williams 3abf51dcad Get rid of names attached to Links.
This is simply no need for the names on links,
other then for debug messages, and there are
better ways to handle that.
2008-09-10 19:34:28 -07:00
Stephen Williams 5dfecb3789 Remove useless Link instance number. 2008-09-10 07:29:23 -07:00
Cary R 088c7f3feb Add calculated delay, real valued, non-blocking assignments.
This patch add the ability to do a non-blocking assignment
for real values using a non-constant (calculated) delay.
2008-09-09 20:09:49 -07:00
Cary R 3982781e97 Add cast to remove warning. 2008-09-09 19:24:14 -07:00
Larry Doolittle f233793061 Spelling fixes
No code changes.
2008-09-09 19:21:42 -07:00
Larry Doolittle 8704e3e34f Compatibility with gcc-4.3
Add "include"s to fix errors flagged by gcc-4.3.2
2008-09-09 19:19:51 -07:00
Nick Gasson ec2511da64 Use British spelling and fix a few typos 2008-09-09 19:57:32 +01:00
Stephen Williams 05f129211e Remove the elaborate_net methods.
These methods are no longer in use, their functionality taked over
by a compination of elab_and_eval and NetExpr::synthesize methods.
2008-09-08 21:26:26 -07:00
Stephen Williams eb9d037bf0 Remove elaborate_net from all elaborations.
Use elaborate_expr and synthesize() methods in place of the
elaborate_net methods, so that elaboration is more consistent.
2008-09-08 19:13:49 -07:00
Stephen Williams 90f55a1d00 Merge branch 'elaborate-net-rework' 2008-09-08 18:02:51 -07:00
Stephen Williams 527f5c4849 The -V flag gets version information from all parts.
When the -V flag is passed to the iverilog command, we can easily
print the version information for the driver itself, but it is also
valuable to probe all the components that would have been used for
a real compile. So the driver executes the preprocessor and the ivl
core to have them print version information.

The ivl core program also tries to load the target code generator
and get version information to print. For this to work, create a new
optional entry point "target_query" that takes a query key string as
an argument and returns a const string as the result. Use this with
the key "version" to get version information out of the target.
2008-09-07 21:54:46 -07:00
Stephen Williams 4898cd04c6 Remove redundant back-end selections.
Target selection is done by the DLL target code generator, so there
is no value having a layer of target selection ahead of it. Remove
all that redundant code and simplify the target config files to reflect
this.
2008-09-07 16:43:54 -07:00
Stephen Williams 6411e96193 Generate delay devices for sign-extend devices.
It is possible for signe-extend to have a delay attached to it. (Same
for repeat.) Handle it like other LPM devices, by stuffing a .delay
device into the output path of the device, if appropriate.
2008-09-06 18:05:18 -07:00
Stephen Williams dd47599d55 Merge branch 'master' into elaborate-net-rework 2008-09-06 17:20:14 -07:00
Nick Gasson 8fc35fa32a Avoid emitting empty string at end of $display translation
This happened if the last part of a format string was a % code.
2008-09-06 13:23:55 +01:00
Nick Gasson 6fe7583784 Cary R.'s additional system functions, real value error messages, etc.
I've changed the find_entity() error messages to asserts since
this should be fixed by the previous patch.
2008-09-06 12:06:01 +01:00
Nick Gasson a34348bb35 Add (temporary) error for ICT_SCOPE_GENERATE
Generate scopes were previously ignored, and this would cause a segfault
later on. This patch gives an error whenever it encounters a generate
scope. This should be removed once generate statements are implemented.
2008-09-06 11:38:37 +01:00
Stephen Williams 8717a85f7f Prepare for snapshot 20080905 2008-09-05 17:44:41 -07:00
Cary R 5bf55485d5 Pass file and line number information for expression constants.
This patch passes the file and line number information for
constants that are used in expressions.
2008-09-05 17:33:45 -07:00
Stephen Williams 38970fea65 Merge branch 'vhdl' 2008-09-05 14:40:48 -07:00
Cary R 90fbac6e33 Add callbacks to vpiMemory objects.
This patch adds the ability to set a global array callback.
These type of callbacks will be called when any element of
the array changes.
2008-09-04 21:37:50 -07:00
Larry Doolittle 66949122cf Non-controversial whitespace cleanup
Nothing to do with tab width!  Eliminates useless
trailing spaces and tabs, and nearly all <space><tab>
pairings.  No change to derived files (e.g., .vvp),
non-master files (e.g., lxt2_write.c) or the new tgt-vhdl
directory.

Low priority, simple entropy reduction.  Please apply
unless it deletes some steganographic content you want
to keep.
2008-09-04 21:31:30 -07:00
Stephen Williams 6f002935d7 Parse attributes on statements within event statements.
Statements can have attributes attached to them. Handle a few cases in
the parser where attributes may be attached to statements, and get them
as far as the pform.
2008-09-04 21:27:21 -07:00
Stephen Williams 5f0b723534 Merge branch 'master' into elaborate-net-rework 2008-09-03 19:59:31 -07:00
Cary R 7beb059d90 Add blocking repeat event control, make repeat sign aware
This patch adds blocking repeat event controls and also makes the
base repeat statement sign aware. If the argument to repeat is
negative (it must be a signed variable) then this is treated just
like an argument of 0 (there is no looping). Doing this allows us
to model the repeat event control as follows.

  lhs = repeat(count) @(event) rhs;

is translated to:

  begin
    temp = rhs;
    repeat (count) @(event);
    lhs = temp;
  end

This patch also pushes the non-blocking event control
information to the elaboration phase where it will report they
are not currently supported.
2008-09-03 19:35:54 -07:00
Stephen Williams 60169f6353 Get generate block scope from generate case.
The generate block is a placeholder for the generate items, and it
is the items themselves that can specify the name of the generate
block that is created.
2008-09-03 17:59:39 -07:00
Stephen Williams e4411777ed Remove unused net_force.cc source file. 2008-09-02 18:38:04 -07:00
Stephen Williams 456fffa7ed Remove last vestiges of XNF.
XNF hasn't been supported in a while. Xilinx doesn't put any effort
into it either, for that matter.
2008-09-02 18:23:48 -07:00
Nick Gasson 4cb2090978 Fix vhdl_expr::cast when expression has no assigned type
This avoids a couple of segfaults
2008-09-02 20:22:50 +01:00
Nick Gasson ff766899b0 Add IVL_LPM_CMP_GT 2008-09-02 19:07:38 +01:00
Nick Gasson 122890fef4 Make sure LPM expression is cast to the output type
This fixes some signed/unsigned bugs identified by the signedX tests.
2008-09-02 19:02:54 +01:00
Cary R 1944f372c5 Fix a couple uninitialized value problems found with tgt-vhdl.
This patch fixes two uninitialized variable problems found
with valgrind when testing the VHDL code generator.
2008-09-01 21:23:58 -07:00
Cary R 8fbfdffe91 Allow .array/port input access generate statement.
For nested array accesses the .array/port statement must
evaluate its input argument before it starts printing the
actual .array/port statement.
2008-09-01 14:04:51 -07:00
Larry Doolittle 23127852c7 Compatibility with gcc-4.3
Add "include" to fix error with abort() in dup_expr.cc
Add "include" to AStatement.h so usage of struct PExpr works
Get rid of eval_tree.cc:577: warning: suggest parentheses around comparison in operand of ^
2008-09-01 13:55:57 -07:00
Stephen Williams c150223a3a Fix problem with vvp_vector2_t right shift
that trips only when starting with perfectly
aligned inputs.
2008-09-01 13:55:42 -07:00
Stephen Williams c0a4b7c670 Fix a bug in vector evaluation of abs().
The calculation of the abs of a signed value
was inverting the value if it was signed,
and not if it was negative.
2008-08-30 17:35:57 -07:00
Stephen Williams 319b886118 Build files compatible with snapshot 20080830 2008-08-30 17:09:51 -07:00
Stephen Williams fc476aa281 Fix right shift of vvp_vector2_t.
The right shift of vvp_vector2_t needs to
account for and mask off shifted bits. Otherwise
there will be unexpected results after
a vvp_vector2_t::trim method.
2008-08-30 15:30:22 -07:00
Stephen Williams 49c4f2d106 Fix crash on uninitialized data. 2008-08-30 15:28:31 -07:00
Stephen Williams bc3411e28e Merge branch 'master' into elaborate-net-rework 2008-08-29 22:13:07 -07:00
Cary R 97e662d667 Remove unneeded real compare code.
The code removed is unneeded since real values are already
handled by the real specific comparison that is called at
the beginning of each function.
2008-08-29 21:16:59 -07:00
Stephen Williams f900b6d541 Add the Verilog-2005 and Verilog-AMS constant system functions.
This patch adds the constant system functions for Verilog-2005
and Verilog-AMS. These are evaluated at compile time. $abs(),
$min() and $max() support their polymorphic behavior in the
compiler where it really matters. They are always evaluated
as reals in the run time and the result/argument(s) will be
converted as needed.

The Verilog-2005 functions are available if using the 2005
generation (default) and if either the icarus-misc (also on
by default) or verilog-ams flags are set.

The Verilog-AMS functions are available if either the
icarus-misc or verilog-ams flags are set.
2008-08-29 21:11:44 -07:00
Cary R 0804eccfec Evaluate constant real EQ and NE constructs.
This patch adds code to evaluate constant == and != with real values.
2008-08-29 20:41:10 -07:00
Cary R 2e97b28185 More NaN constant fixes.
This patch cleans up %loadi/wr regarding NaN values. It also
fixes the code generator to correctly output a NaN value as
a Cr<> constant.
2008-08-29 19:32:00 -07:00
Cary R 2d3cd7cb9a Handle NaN constant in the code generator and fix loadi/wr NaN bug.
This patch fixes a bug in %loadi/wr regarding NaN values. It also
fixes the code generator to correctly output a NaN value.
2008-08-29 19:31:50 -07:00
Stephen Williams c9efe87146 Merge branch 'master' into elaborate-net-rework 2008-08-29 19:10:48 -07:00
Stephen Williams 1ca8241b88 Merge branch 'master' into verilog-ams 2008-08-29 19:03:34 -07:00
Stephen Williams 8d21c0390e Remove dead EEQ code.
The EEQ function is handled by vvp_cmp_eeq, an arithmetic expression
processor and the logic version of EEQ is never used.
2008-08-29 18:45:19 -07:00
Stephen Williams 3b778b1a06 Minor improvements to expression debug prints. 2008-08-29 18:44:45 -07:00
Stephen Williams e322cce650 Clean up $clog2() measurement of unsized numbers.
If the argument to $clog2() is unsized constant, then trim it to the
smallest representation that doesn't lose the sign, then do the $clog2
on that.

Also, use integer_width instead of 32 for the minimum $clog2() result
for a negative value.
2008-08-29 18:42:22 -07:00
Nick Gasson ed929a37bb Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-29 18:38:49 +01:00
Stephen Williams 4c7144afc0 Remove dead EEQ code.
The EEQ function is handled by vvp_cmp_eeq, an arithmetic expression
processor and the logic version of EEQ is never used.
2008-08-28 22:08:46 -07:00
Stephen Williams 5d5228b6b8 Minor improvements to expression debug prints. 2008-08-28 21:16:44 -07:00
Stephen Williams e6c2637367 Clean up $clog2() measurement of unsized numbers.
If the argument to $clog2() is unsized constant, then trim it to the
smallest representation that doesn't lose the sign, then do the $clog2
on that.

Also, use integer_width instead of 32 for the minimum $clog2() result
for a negative value.
2008-08-28 21:15:43 -07:00
Stephen Williams 468f45b4db Merge branch 'master' into elaborate-net-rework 2008-08-28 18:17:24 -07:00
Cary R 8c38872b4b Fix the always zero delay check to happen after elaboration.
This patch moves the always zero or possibly zero delay checks
to a point after the circuit is full elaborated. Before it
could try to check tasks that had not already been evaluated
resulting in a crash.
2008-08-28 17:49:41 -07:00
Cary R d15e2a2f73 Work around a flex limitation with yyrestart()
See the comments added with this patch for more information.
2008-08-28 17:41:13 -07:00
Cary R 150d51c19b Optimize block delay type check
When looking for a delay_type() in a block stop when we have a
DEFINITE_DELAY. Doing this could reduce the number of statements
that need to be checked.
2008-08-28 17:38:02 -07:00
Larry Doolittle b455f3af5d Spelling fixes
Comments only, no code changes
2008-08-28 17:36:32 -07:00
Nick Gasson 0e458501b3 Ensure binary operands have correct signedness
Previously only signedness was only corrected for the
result. This patch ensures the VHDL operands have the
same signedness as their Verilog counterparts.

This fixes a few of the signedX tests.
2008-08-28 21:53:12 +01:00
Cary R 3b8dc81a97 By default convert a recv_vec8_pv to a recv_vec4_pv
Assume that anything that is strength aware already handles a
recv_vec8_pv and make the default function convert the bits
to a vec4 and then call recv_vec4_pv with this new value.
2008-08-27 21:22:18 -07:00
Cary R 0ae8f744c4 Variable arrays need to keep their signedness.
Since variable arrays create their elements dynamically the base array
structure for them needs to keep the signedness information.
2008-08-27 21:16:25 -07:00
Cary R 370ff9719f Make &A and &PV nestable.
This patch makes it so that &A and &PV can nest for the symbol
argument. This allows nested array selects, etc.
2008-08-27 21:09:41 -07:00
Stephen Williams 3ed0c4e809 Don't crash looking for delay_type of empty task.
It is legal for a task to have no definition. In that case, the
delay_type calculations (used to detect infinite loops) can assume
that an empty definition is a no-op and return NO_DELAY.
2008-08-27 18:42:05 -07:00
Stephen Williams 0121c41942 Better optimization of constants in expressions
Be more sophisticated with the code generated for constant values.
When values are large, use an optimal mix of %movi and %mov
instructions to get the desired value, no matter what the content.
2008-08-27 18:22:23 -07:00
Stephen Williams 091a546387 Broken run-time wide divide.
The wide-divide function was broke. It generated bad results.
2008-08-27 18:20:35 -07:00
Nick Gasson 8323d5d01d Finish cast.cc cleanup
Replace big if statement with switch statemetn
2008-08-27 16:59:05 +01:00
Nick Gasson b5e65ac9ed Refactor and clean up cast.cc
This splits up the monolithic and confusing vhdl_expr::cast function into
several smaller to_XXX functions which each generate code to cast an 
expression to type XXX. This makes it much easier to understand and maintain.
2008-08-27 16:47:07 +01:00
Stephen Williams 63e200726f Merge branch 'master' into elaborate-net-rework 2008-08-26 21:53:44 -07:00
Stephen Williams b2b0f45473 Use the expression with to calculate expression width in assignments.
In continuous assignment, the width of the expression needs to come
from the expression itself, and not just from the width of the l-value.
Use the PExpr::test_width method to get the width of the expression
to pass to the elaborate.
2008-08-26 21:33:24 -07:00
Cary R bccb762e9f Correctly cast strlen() for %*s width argument.
We had fixed many of these warning before, but I missed this
one since this file was not part of the distribution when we
fixed the other cases.
2008-08-26 16:09:00 -07:00
Stephen Williams c26ee8534d Improved comments. 2008-08-25 21:52:40 -07:00
Nick Gasson 924ddb787a Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-25 20:07:49 +01:00
Stephen Williams 0341679360 Handle real-valued unary subtract.
the sub_net_from function is used by the ::synthesize method of the
NetEUnary class to make the expression 0-N. By making that function
handle a real-valued net, the NetEUnary suddenly supports real-valued
nets, and this probably helps in other places as well.
2008-08-23 18:11:11 -07:00
Stephen Williams 65c3bc91de Short-circuit elaboration of ternary expressions.
When the condition expression of a ternary is constant 1 or 0, we can
short-circuit the elaboration by only processing the clause (true or
false) that we need. This saves compile time and execution time.
2008-08-23 10:50:24 -07:00
Cary R be3d7b435d Print a better message for instance port expression errors.
This patch adds code to print an error message when there is
a syntax error in the port expression list.
2008-08-23 09:34:12 -07:00
Cary R 92dd13a225 Error message for missing system tasks/functions.
This patch adds an error message for the standard system
tasks and functions that are not currently implemented.
These are currently $fmonitor*, $ferror, $fread, the
queue and PLA tasks.
2008-08-23 09:20:30 -07:00
Nick Gasson 8e023d1227 Remove redundant function 2008-08-22 21:27:24 +01:00
Nick Gasson d21b3258e3 Support conversion of (un)signed to std_logic
Take the least-significant bit. This fixes a couple of broken
test cases.
2008-08-22 20:59:14 +01:00
Nick Gasson 331a51e842 Add more warnings about untranslatable constructs 2008-08-22 20:25:58 +01:00
Nick Gasson 63a1e25129 Catch case where component name and instance differ only in case
This causes an error in VHDL (which is case-insensitive). This 
patch simply appends _Inst to the instance name if it detects this.
2008-08-22 20:20:17 +01:00
Nick Gasson fae7ab2418 Use case-insensitive string comparison for get_decl
This will allow us to detect cases where identifiers differ only by case
2008-08-22 20:15:45 +01:00
Stephen Williams 65a4f36de5 Watch out for left operand of left shift that is not known early.
It is possible for the left operand of a left shift to be not known
early during elaborate expression. In that case, make a punt expression
and expect it to be resolved later.
2008-08-21 18:58:38 -07:00
Stephen Williams 04d49fcf35 Merge branch 'master' into elaborate-net-rework 2008-08-21 18:11:21 -07:00
Nick Gasson 535ef6be38 Change function return value from Verilog_Result to <funcname>_Result 2008-08-21 19:44:12 +01:00
Nick Gasson d3b7d7a13d Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-21 18:35:54 +01:00
Nick Gasson b92b62a8fb Include cstring required for GCC 4.3
GCC 4.3 has tightened up header dependencies so that
`strcmp' is no longer declared if <cstdlib> is included
(which it was in prior versions). This causes the changes
in 5e512e6570 to fail to
build with 4.3.

This patch includes <cstring> in the files that are failing.
2008-08-21 09:36:03 -07:00
Cary R 7eb34013dd Add vpip_calc_clog2 to vvp.def file
This is needed to get cygwin to compile correctly.
2008-08-21 09:34:33 -07:00
Stephen Williams e18eb32d8b Process shift by constant amounts early in expression elaboration.
The expr:::synthesize methods need not deal with saturating left or
right shifts if they are dealt with early, in elaborate_expr methods.
So the elaborate_expr for shift takes on much more responsibility.
2008-08-20 21:47:07 -07:00
Nick Gasson 4ebe09bb72 Various fixes to support automatic functions
Mostly this ensures that a recursive call to a function
is made with the correct types (this may involve generating
code to cast expressions to the correct type).
2008-08-20 22:54:53 +01:00
Nick Gasson a07dc968e7 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-20 18:58:46 +01:00
Stephen Williams 28991d30f4 Fix some ambiguous casts. 2008-08-20 09:40:16 -07:00
Cary R 11109f519c Push the automatic property for tasks and functions to the code gen.
This patch pushes the automatic property for both tasks and
functions to the code generators. The vvp back end does not
currently support this so it will error out during code
generation. The VHDL back end should be able to use this
property and tgt-stub prints the property. Having this will
also make it easier when we do adding this to the runtime.
2008-08-20 09:23:14 -07:00
Cary R 5e512e6570 Finish $clog2 function.
This patch fixes problems in the initial $clog2 implementation
and adds correct functionality to the runtime.
2008-08-20 09:01:21 -07:00
Cary R c032d28aaa Convert the infinities to 'bx
This patch modifies the double to vector conversions to return
'bx for either +/- infinity.
2008-08-20 09:01:09 -07:00
Cary R 768633e464 Add $clog2 function.
This patch adds the $clog2 system function. It also makes this
function work as a constant function. The runtime version still
needs to be updated to use an integer based version instead of
the current double based method. The double method suffers from
rounding errors.
2008-08-20 08:59:36 -07:00
Cary R e501bbdd27 Fix problems in VPI callback time and value formats.
This patch adds support for vpiScaledRealTime and vpiSuppressTime
to VPI callbacks. It also fixes a bug where the callback data
object was not being copied correctly and adds support for
vpiSuppressVal. This requires adding vpiSuppressVal to a few
other routines. It adds the ability for a callback to return
more than vpiScalarVal (all values supported by the
vpip_vec4_get_value() procedure). It also fixes a bug where
vpip_vec4_get_value() would incorrectly return vpiZ for a BIT4_X
scalar value. It also comments the potentially dangerous
vpiScalarVal calculation in the vvp_fun_signal::get_value()
procedure.
2008-08-20 08:52:09 -07:00
Nick Gasson cb1d4fd278 Amend inaccurate comment 2008-08-18 16:15:05 +01:00
Nick Gasson e1deba51ab Handle BUFIF logic when vector inputs 2008-08-18 15:48:07 +01:00
Nick Gasson d53014a07f Fix leading comma it expression only has "others" part
Stop syntax errors caused by things like this:
  (, others => '1')
2008-08-18 15:36:11 +01:00
Nick Gasson 7865264de0 Implement IVL_LPM_REPEAT 2008-08-18 15:34:58 +01:00
Nick Gasson 86661c1538 Add a few more `unsupported' messages 2008-08-18 15:29:30 +01:00
Nick Gasson e2dd7425bd Add error messages for unsupported statement types 2008-08-18 15:24:38 +01:00
Nick Gasson e01b16e586 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-18 15:16:02 +01:00
Nick Gasson 6adc3c9f13 Add short section on VHDL to man page 2008-08-17 19:42:07 +01:00
Stephen Williams 0de2dcb211 Allow elaborate_expr to handle implicit nets.
When the elaborate_expr code is used for expressions of continuous
assignments, it needs to be able to create implicit nets.
2008-08-17 08:22:42 -07:00
Stephen Williams a8ad505af7 Various improgements to expression ::synthesize methods
Since NetExpr::synthesize methods were rarely used, then had a lot
of bugs. Now that continuous assign uses these methods, these bugs
must be fixed.

Binary and Unary minus properly pad/extens its arguments,
Case compare generates correct code,
Divide properly takes on signed flag,
Signed right shift sign-extends its argument to prevent loss of sign bits
and uses the NetSignExtend instead of simple padding,
Use the correct target node for reduction NAND,
Properly handle constant arguments of NetESelect

Handle some exressions that were not handled before, include abs()
and POW.
2008-08-17 08:21:24 -07:00
Stephen Williams e8804500b0 Replace an assert in vvp/arith.cc with a detailed message.
... and an assert.
2008-08-16 19:02:09 -07:00
Stephen Williams 66bed241f1 Prevent silent overflow of mantissa
When converting a binary constant to a real value in the vvp code
generator, make sure the mantissa does not overflow. If it does,
panic in some way.
2008-08-16 18:30:07 -07:00
Stephen Williams f8bd8e1bd6 Unary minus and signed right shift need to extend their arguments.
In signed contextx, the right shift and unary minus expressions need
to be sign extended before they operate, otherwise there may be bad
results in the high bits in the greater context.
2008-08-16 17:30:32 -07:00
Stephen Williams d2eba7eefe Modulus value bit width should match input dividend width. 2008-08-16 16:25:56 -07:00
Stephen Williams 5ddf34d39b Signed operands do not make power (**) real. 2008-08-16 15:36:14 -07:00
Martin Whitaker 2c1426a44d Patch to ensure functions are evaluated immediately.
This patch causes a thread that is created to evaluate a function
to be executed immediately. The parent thread is resumed when the
function thread terminates.
2008-08-16 14:42:17 -07:00
Stephen Williams 30e6cfce41 Real valued nets are signed, and pform unary expression have width.
Real valued nets should ne treated as signed no matter what.
Also, PEUnary nary expressions need a useful test_width method.
2008-08-15 22:03:19 -07:00
Stephen Williams 1ae2c0c9e0 Extra diagnostic details in elaboration of continuous assignment. 2008-08-15 21:19:04 -07:00
Cary R 1f5b11246e Correctly pass a concatenation elaboration error.
Because Icarus tries to elaborate as much as it can even after
an error has occurred we need to check for these errors during
elaboration. This patch prevent an undefined identifier from
crashing the compiler.
2008-08-15 17:26:08 -07:00
Cary R d3caa547ba Print an error for automatic tasks or functions.
This patch adds code to recognize and report that automatic
task or functions are not currently supported.
2008-08-15 17:10:59 -07:00
Nick Gasson 026d941734 Avoid printing field widths in $display/$write output
This removes some unwanted artifacts from the output.
2008-08-15 19:43:16 +01:00
Stephen Williams 61b9c5e069 Pad signed expressions in continuous asignments
When the continuous assignment is signed, then sign-extend the r-value
in the few cases where the expression is stubbornly smaller then the
desired width.
2008-08-14 20:38:34 -07:00
Stephen Williams 4b646aca90 Account for signed multiply
When multiply is done in native words, the conversion to words from the
vp_vector4_t vectors must be done signed. This only matters if the
input operands are different sizes (and themselves signed) but will
not hurt even if we want an  unsigned result.
2008-08-14 20:37:04 -07:00
Stephen Williams 50c1533fdd Fix evaluation of logical equality with x bits.
Logical (in)equality needs to look at all the bits of both operands,
and cannot short circuit the test unless defined bits differ. If there
are undefined bits, the equality is undefined at that point, but return
x only if there are not other bits that make the results clearly
unequal.
2008-08-13 22:22:59 -07:00
Nick Gasson a577ee447b Generate process for sequential UDPs 2008-08-13 17:03:03 +01:00
Nick Gasson d7b85c42a0 Split sequential and combinatorial UDPs into separate functions 2008-08-13 11:57:05 +01:00
Stephen Williams 3def0e0dec Fix some expression elaborate vector width problems. 2008-08-12 21:32:21 -07:00
Stephen Williams dc6d3f4afb Fix a spurious non-local net.
During elaboration of continuous assignment that connected the rval
to the lval with a part select forgot to mark the signal it created
as temporary.
2008-08-12 21:31:39 -07:00
Stephen Williams 3d1f363be8 Handle special case of net assigned to net.
When nets are assigned directly to a net, we need to create a driver
to carry the strength. Normally, the implied drive of a continuous
assignment is carried by whatever gate the r-value expression ends
with, but with simble net-to-net assignment, there is no net so we
need to install a BUFZ to carry the assignment.
2008-08-12 21:03:38 -07:00
Nick Gasson dea54df71b Catch possibly NULL return value
This is caused by using a hierarchical reference (which can't
be translated to VHDL). The result of get_decl is NULL since
the signal has been declared in a different VHDL architecture.
Adding the assert is cleaner than having it segfault, for the
moment, until a nicer error message can be added.
2008-08-12 09:47:03 +01:00
Stephen Williams 6051150c14 Continuous assign no longer uses elaborate_net.
convert the continuous assign elaboration to use elaborate_expr
and synthesize methods instead of the elaborate_net methods of
PExpr. This exposes problems with the synthesize methods, but it
is a better way to do it.
2008-08-11 21:21:33 -07:00
Nick Gasson a3929330b0 Fix regression caused by UDP delay patch
translate_time_expr cannot be passed a NULL ivl_expr_t.
2008-08-11 20:53:13 +01:00
Nick Gasson c404b761b7 Change out' ports to buffer' when the signal is read
Previously this was handled by creating an internal
signal that was connected to the output and could also
be read inside the entity. The correct solution is to
make the output `buffer' rather than `out'. However, this
does not work in the case when an output is connected to
an output of a child entity, and that values is read
in the parent. In this case *both* the outputs of the child
and the parent need to be made `buffer'.
2008-08-11 20:48:28 +01:00
Nick Gasson 9b1f2d5971 Remove UDP debug messages from output 2008-08-11 20:37:10 +01:00
Nick Gasson 9d7e4ac15f Allow delays in combinatorial UDPs
Add a `after' clause to the `with .. select' statement.
2008-08-11 20:36:09 +01:00
Nick Gasson d55a3a073a Handle '?' in vl_to_vhdl_bit
The rough translation is '-', although the semantics are incompatible
in some cases (e.g. '-' = '1' is false)
2008-08-11 13:53:42 +01:00
Nick Gasson 01bf741983 Implement combinatorial UDPs
Using a `with .. select' statement
2008-08-11 13:23:50 +01:00
Nick Gasson bf3734110e Add VHDL syntax element for `with .. select' statement
This will be used to implement combinatorial UDPs
2008-08-11 13:09:52 +01:00
Nick Gasson 6dcf936807 Generate combined input for UDP devices
Combinatorial UDPs will be implemented with a `with ... select'
statemetnt. However the input to this must be "locally static".
This patch joins the inputs into a vector which can be used as
the select expression.
2008-08-11 12:58:46 +01:00
Stephen Williams 1d884cb0e9 Shuffle the argument list for the synthesize method.
In preparation for using the synthesize method to replace the
elaborate_net method of PExpr, rework the interface to the
synthesize() method. This changes no fnctionality, but does set
up the infrastructure for the next step.
2008-08-10 18:22:34 -07:00
Nick Gasson 8e0bf3ebff Add conversion from std_logic to (un)signed types
Implemented using the expression (0 => X, others => '0')
2008-08-10 11:22:23 +01:00
Nick Gasson 380e3a8121 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-10 09:51:20 +01:00
Cary R 1f8ff7ff8d Pass a NULL expression when parameter expression elaboration fails
When elaborating a parameter expression fails we need to set the
expression to 0 since it has already been partially allocated.
Doing this allows us to not evaluate the dummy expression later.
2008-08-09 19:27:14 -07:00
Cary R b1f1c11441 User task and function arguments can be time or realtime
This patch adds the time and realtime properties for user
task and function arguments. It also make a common rule
for real and realtime since they are the same.
2008-08-09 19:10:09 -07:00
Cary R c918cf4a46 User task and function arguments can take an optional reg.
User task and function arguments can take an optional reg
property. This property is completely ignored by Icarus.
2008-08-09 19:04:17 -07:00
Cary R f835c7569e Check for a possible corrupt function definition and return.
If a function definition has no ports and no return type it is
assumed to be a bad definition so we don't check it further.
2008-08-09 18:46:18 -07:00
Martin Whitaker 5aecd044c5 Patch to fix pr2043585.
This patch fixes a bug in the VVP code generator that causes syntactically
incorrect code to be generated if an event expression contains a memory or
array port.
2008-08-09 18:22:46 -07:00
Cary R 2a389a9abe Display signal array size when using -delaborate.
This patch modifies one of the debug_elaborate messages to display
the array information when needed.
2008-08-09 18:10:59 -07:00
Nick Gasson 6527262348 Add correct file/line information to signals
This patch adds a FILE_NAME function for signals to extract
the file/line information from the net's LineInfo, replacing
the dummy values.
2008-08-09 16:57:26 -07:00
Stephen Williams 79e1273814 Do not consome pform defparams in module definition.
The list of defparams in the pform module definitions (in class Module)
should not be consumed when they are used. The module may be instantiated
moltiple times, so consuming the defparams during elaboration will cause
subsequent instantiations to not have the defparams. That's wrong.
2008-08-09 16:45:20 -07:00
Nick Gasson 709c850e69 Add correct file/line information to signals
This patch adds a FILE_NAME function for signals to extract
the file/line information from the net's LineInfo, replacing
the dummy values.
2008-08-08 20:35:27 +01:00
Nick Gasson 7ed8c0915d Add file/line comments to signal declarations 2008-08-08 20:28:16 +01:00
Nick Gasson eef1c968dc Add message that casex cannot be translated
...with the correct behavior. It would be possible to
just translate it as a regular VHDL case statement (as
it was before this patch). But the behavior is not
correct as VHDL only does the equivalent of case-equality
in case statements and this can be confusing when debugging
the output. An alternative might be to emit a warning rather
than an error.
2008-08-08 20:09:40 +01:00
Nick Gasson 0985158090 Handle %% in $display 2008-08-08 20:07:22 +01:00
Nick Gasson 090ae5fa56 Catch case where signal with same name in task and module
This fixes task3.14C
2008-08-08 19:47:20 +01:00
Nick Gasson 13cb81f4bb Add task signals to containing architecture
This is necessary to support the in-line expansion of tasks
2008-08-08 19:31:45 +01:00
Cary R ef66ca6498 Do a part select of the array selection result not the base array.
When doing the part select of an array selection you need to use
the result from the array selection to do the part select not the
base array signal.
2008-08-07 20:45:58 -07:00
Cary R d43452f88d Check all generate expressions for failure.
This patch adds code to check that the various generate expressions
evaluate correctly.
2008-08-07 20:41:24 -07:00
Cary R e719dc250a %load/av now matches %load/v for truncating/extension.
This patch adds code to make %load/av extend or truncate
a value like %load/v.
2008-08-07 20:34:20 -07:00
Nick Gasson bb0efda526 Make make_safe_name case insensitive 2008-08-07 17:58:42 +01:00
Nick Gasson e4d0a92d7c Division and modulus operators 2008-08-07 14:18:26 +01:00
Nick Gasson 28d782e13c Remove redundant verilog_support.vhd file 2008-08-07 13:10:53 +01:00
Nick Gasson 6f5f700cb9 Very minimal implementation of tasks
This expands the task in-line inside the process to avoid
problems with global variables (VHDL processes cannot
reference globals)
2008-08-07 10:54:39 +01:00
Nick Gasson a17924f819 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-07 09:19:13 +01:00
Stephen Williams 893aae2ca4 Add BUFZ to input ports when necessary.
When driving an input port to a module, watch out for the case where
the net is also driven within the instance. If this is the case, take
pains to make sure what goes on in the instance doesn't leak out
through the input port. Add a BUFZ (continuous assignment) to isolate
the context from internal driving.
2008-08-06 21:04:52 -07:00
Nick Gasson 4cbec1c817 Add XNOR binary operand 2008-08-06 11:18:01 +01:00
Holger Wächtler d84771428a need to decrement string len if we have a '-' sign 2008-08-05 15:26:29 -07:00
Holger Wächtler 484d3ea36b this patch adds support for conversion of negative vpiDecStrVal in vpip_dec_str_to_vec4() 2008-08-05 15:26:22 -07:00
Holger Wächtler c71e930ffa $fscanf("%s"): accept '-' and '_' chars. 2008-08-05 15:26:16 -07:00
Holger Wächtler 15584a4f81 fix $fscan("%d") for values > 32 bit
The old code returns a vpiIntVal for $fscanf("%d") format strings. This
limits the maximum input range arbitrarily to 32 bit.

This patch implements %d parsing similiar to %b and %x.

'?' and 'X' chars are not accepted for %d format.
2008-08-05 15:26:09 -07:00
Nick Gasson f86f454956 Apply the last patch to if/case statements too
This further cleans up the output by removing more
useless `wait for 0ns' statements.
2008-08-05 11:09:51 +01:00
Nick Gasson e01e038cf9 Avoid generating useless `wait for 0ns' statements
If the final statement in a process is a non-blocking
assignment then there is no point adding a `wait for 0ns'
after it since it will be immediately followed by another
wait. This case is suprisingly common, so this patch helps
generate much cleaner output without breaking the cases
where the 0ns wait is actually required (e.g. to implement
non-blocking assignment properly).
2008-08-05 11:02:36 +01:00
Nick Gasson c849dfeec4 Add XNOR logic device 2008-08-05 10:45:01 +01:00
Nick Gasson 8d7b03576c Correctly implement unary XNOR
Forgot to negate the output.
2008-08-05 10:38:43 +01:00
Stephen Williams b292a5fc05 Create a branch object to be the argument to the access function.
The NetBranch object is connected, but not like an object, so the
NetPins object base class is factored out from NetObj to handle the
connectivity, and the NetBranch class uses the NetPins to connect a
branch.

Also, account for the fact that nets with a discipline are by default
real-valued.
2008-08-04 20:54:05 -07:00
Nick Gasson 72019959a8 Translate some ternary expressions to if statements
This re-implements some earlier functionality where
ternary expressions on an assignment RHS are translated
to an if statement.
2008-08-03 15:47:32 +01:00
Nick Gasson 9565ea1034 Add some whitespace above component instantiations 2008-08-03 14:50:13 +01:00
Nick Gasson 49a2693357 Add file / line number information to functions 2008-08-03 14:46:57 +01:00
Nick Gasson 10a5ca199d Add file / line number comments to instantiations 2008-08-03 14:38:08 +01:00
Nick Gasson c2f622327f Use ivl_scope_def_* for definition file/line numbers 2008-08-03 14:34:41 +01:00
Nick Gasson 0e2628a3fb Minimal implementation of IVL_LPM_MUX
This handles the (common) case of the select being only
1 bit wide. Implemented as a concurrent assignment with
a `when' clause.
2008-08-03 12:46:50 +01:00
Nick Gasson 45dfa28dba Remember signal pin a nexus was attached to
Also modify nexus_to_var_ref to set the correct array
offset when the signal is an array (the offset comes
from the pin).
2008-08-03 11:41:26 +01:00
Nick Gasson c8cbac58f5 Add forward declarations for functions
This patch adds a forward declaration for every user funciton.
This fixes VHDL compile problems if a function calls another
before it has been declared.
2008-08-03 10:50:31 +01:00
Nick Gasson c1b5424ca6 Implement assignment with multiple lvals
Multiple lvals are implemented by first assigning the complete
RHS to a temporary, and then assigning each lval in turn as
bit-selects of the temporary
2008-08-02 18:40:24 +01:00
Nick Gasson c706c94e38 Generate a vhdl_var_ref for every assignment lval
This completes the refactoring of make_assignment
necessary to implement multiple lvals.
2008-08-02 18:20:18 +01:00
Nick Gasson fad8abee34 Start refactoring make_assignment for multiple lvals
This patch lifts the RHS generating code out of the
lval-specific code and sticks a loop around the lvals.
2008-08-02 16:38:44 +01:00
Nick Gasson 9448c5939c Always user Ternary_* support functions for ternary assignments
Previously the code generator expanded ternary assignments to
and `if' statement. This patch replaces that with a single assignment
and a call to a Ternary_* support function. This will make it
much easier to support multiple lvals later.
2008-08-02 15:46:36 +01:00
Nick Gasson 752a90dc2f Insert blank line before VHDL process in output 2008-08-02 10:45:38 +01:00
Nick Gasson a60216ec15 Use ivl_process_* functions for file/line number information 2008-08-02 10:44:03 +01:00
Nick Gasson 5d0df8d880 Change format of line file/line numbers 2008-08-02 10:42:00 +01:00
Nick Gasson 1cd13ecdbd Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-02 10:37:22 +01:00
Stephen Williams c14987aa18 Merge branch 'master' into verilog-ams 2008-08-01 21:15:11 -07:00
Cary R aeec93a322 $time, $stime and $simtime return an integer rounded value for %f
The $time, $stime, $simtime (integer time) system functions should
return a rounded integer value in a real context.
2008-08-01 20:37:41 -07:00
Cary R 61930c3b6e Add file and line information to processes.
This patch adds file and line information to processes
(initial and always).
2008-08-01 20:13:29 -07:00
Cary R 296f1bacc1 vvp_vector4_t words are unsigned long.
The double to vvp_vector4_t constructor was not using the correct
declaration for the bit words. This worked as long as unsigned and
unsigned long were the same size (usually).
2008-08-01 20:10:52 -07:00
Nick Gasson bb80b432e6 Add comments file/line number comments
Added to entities, architectures, and processes
2008-08-01 21:21:42 +01:00
Stephen Williams be551a6b68 Add a stub vvp_net_t::delete method
Some compilers reference the delete method for the vvp_net_t object
even though it is never used. So provide a stub with an assert.
2008-08-01 09:48:59 -07:00
Nick Gasson e0834f7f38 Add NAND and NOR logic devices 2008-08-01 17:46:04 +01:00
Nick Gasson a26d91557b Add binary NAND and NOR operators 2008-08-01 17:42:26 +01:00
Nick Gasson 3f73c9bb54 Make sure argument to unary - is signed 2008-08-01 16:35:47 +01:00
Nick Gasson 09f3eb4a36 Don't bother calling reduction function if argument is std_logic 2008-08-01 16:27:55 +01:00
Nick Gasson 33885ed891 Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl 2008-08-01 08:25:38 +01:00
Nick Gasson d21277f1b9 Tidy up whitespace in output 2008-07-31 21:17:49 +01:00
Nick Gasson 7b0f675785 Add check for sequential UDPs 2008-07-31 21:08:59 +01:00
Nick Gasson db339b8fc3 Stub for UDP logic devices 2008-07-31 20:59:20 +01:00
Stephen Williams eca8a46b40 Merge branch 'master' into verilog-ams 2008-07-30 18:18:40 -07:00
Stephen Williams 4ca7f2a9bd Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-07-30 18:05:43 -07:00
Stephen Williams 221c63b766 Add some simple error checking. 2008-07-30 18:02:07 -07:00
Stephen Williams 9f04641fc7 Detect and elaborate AMS access functions.
Detect function call expressions that turn out to be calls to the
access function of a nature. Elaborate the access function and stub
the emit code. This gets the access function just short of the code
generator.
2008-07-30 18:01:41 -07:00
Cary R 3191b3efcb An included file should start at line 1.
The preprocessor was incorrectly setting the line when starting
an include file to the line it was called from instead of 1.
This would give incorrect line numbers for errors/warnings in
the included file.
2008-07-30 15:04:19 -07:00
Cary R 1a41ac3145 Update real to int conversion: -inf is 'b0 not 'b1 like +inf.
The new real to int conversion was incorrectly setting the
bits for minus infinity to all ones. This is incorrect in a
two's complement encoding where the largest negative number
would be a leading 1 followed by an infinite number of zeros.
2008-07-30 14:59:13 -07:00
nog 6d4dd5ae3b Fix macro argument replacements
When searching for macro arguments to replace, make sure that the
argument is not the begining of another identifier.
2008-07-30 14:52:04 -07:00
Cary R 6cb3d86d15 Update %cvt/vr to use new double to vector conversion (constructor).
This patch updates the %cvt/vr command to use the new double to vector
constructor. This allows the resulting bit pattern to be larger than
a long. The old method was producing incorrect results without a
warning for large bit values.
2008-07-30 14:40:14 -07:00
Cary R 7a4f85d382 Make .part/pv strength aware and resolv vec8_pv aware.
This patch makes .part/pv strength aware, resolv vec8_pv
aware. vvp_net_fun_t adds vec8_pv as a virtual function
with an appropriate error default. vvp_fun_signal should
full support vec8_pv (not tested and may not be needed).
2008-07-30 14:31:33 -07:00
Cary R 5207be0778 Use ivl_signal_dimensions to find arrays not ivl_signal_array_count
ivl_signal_dimensions() is the correct call to use to determine
if a signal is part of an array. If it is greater than zero the
signal is an array.
2008-07-30 14:25:29 -07:00
Cary R 2ceb0539af IVL_VT_LOGIC is default localparam type not IVL_VT_NO_TYPE
This patch fixes a bug where a local parameter with only a range
was incorrectly setting the default parameter type to IVL_VT_NO_TYPE.
This would create a compile time assert for any untyped
parameter/localparam immediately following it.
2008-07-30 14:16:18 -07:00
Cary R f9c67e21b2 Some variable part select arguments must be drawn before the part select.
Some variable part selects need to draw the select argument before the
variable part select is printed e.g.(.array/port).
2008-07-30 14:07:03 -07:00
Nick Gasson baa2363e85 Split logic device code into separate file 2008-07-30 10:13:08 +01:00
Nick Gasson e5b8abfb23 Remove debugging output 2008-07-29 21:15:51 +01:00
Nick Gasson 9f6f711f8d Remove unused variable 2008-07-29 21:08:50 +01:00
Nick Gasson 9a5b7bb0b0 Connect signals together if joined in a nexus 2008-07-29 21:03:00 +01:00
Nick Gasson eaf1cc9120 Fix assertion failure with arrayed signals 2008-07-29 19:47:17 +01:00
Nick Gasson 3bcd42dc8f Fix case where logic device has no valid output 2008-07-29 19:39:20 +01:00
Nick Gasson 744fbed783 Finish re-writing nexus code 2008-07-29 19:33:40 +01:00
Nick Gasson c9454b346e Fix module3.12B 2008-07-29 19:04:41 +01:00
Nick Gasson 5ec2c37e7e Get functions working again 2008-07-29 15:29:49 +01:00
Nick Gasson 25602e487d Comment 2008-07-29 15:12:51 +01:00
Nick Gasson e037ffd952 Create temporaries for LPM outputs 2008-07-29 15:09:58 +01:00
Nick Gasson 48c1a7982c Make seen_nexus private 2008-07-29 14:24:04 +01:00
Nick Gasson a842b327c7 Generate constant drivers as concurrent assignments 2008-07-29 14:02:05 +01:00
Nick Gasson f8034d69ef Fix constants in nexuses 2008-07-29 13:30:54 +01:00
Nick Gasson d94dac28a8 Remove redundant lpm_output 2008-07-29 13:08:13 +01:00
Nick Gasson 680c6f0503 Make sure LPMs have valid inputs/outputs 2008-07-29 13:06:21 +01:00
Nick Gasson 39717989a8 Call set_active_entity in the right places 2008-07-29 13:04:29 +01:00
Nick Gasson c26b7ce675 Port maps 2008-07-29 13:02:55 +01:00
Nick Gasson c6f6ea7358 Instantiation working again 2008-07-29 12:21:19 +01:00
Nick Gasson c0c838f1bc Logic devices now working again 2008-07-29 12:11:44 +01:00
Nick Gasson 1a45e9164f Find signal a logic device is connected to 2008-07-29 12:04:40 +01:00
Nick Gasson 8a5f129e56 Draw nexus in multiple passes 2008-07-29 12:00:26 +01:00
Nick Gasson 65c2ceb89d Build entity hierarchy in separate stages 2008-07-29 11:01:02 +01:00
Nick Gasson 7a2e9c02cd Simplify support function emitting code 2008-07-28 22:48:21 +01:00
Nick Gasson f88415b1d7 Conversion of std_logic to integer 2008-07-28 22:46:39 +01:00
Nick Gasson 1250010696 Merge branch 'vhdl' of [email protected]:nickg/iverilog into vhdl
Conflicts:

	tgt-vhdl/support.cc
2008-07-28 21:47:37 +01:00
Nick Gasson 506a0ba7d6 Support repeat in concatenation 2008-07-28 21:46:19 +01:00
Nick Gasson 1d4914c590 Undo last commit 2008-07-28 13:04:30 +01:00
Nick Gasson 3e28a10676 Compress support function names a bit 2008-07-28 13:02:04 +01:00
Nick Gasson 78028a3310 Fully support ternary expressions 2008-07-28 12:59:10 +01:00
Stephen Williams 25a27f9dd9 Parse contribution statements as far as pform.
Contribution statements have an l-value and r-value. Parse those
expressions into pform so that elaboration has something to work with.

In this process, this patch also changes the PECallFunction class to
use the vector template instead of the svector template. The latter
doesn't add anything over the STL vector template, so this is a start
of working the svector out.
2008-07-27 17:22:19 -04:00
Stephen Williams 03e306c805 Infrastructure for parsing analog process statements.
Organize the parsing infrastructure for parsing analog processes,
including holding them in scopes, and collecting analog statements.
2008-07-27 15:02:09 -04:00
Nick Gasson b9cecbef64 Make sure LPM comparison result is std_logic not Boolean 2008-07-27 19:05:49 +01:00
Nick Gasson 8b32096e2a Convert std_logic to Boolean in loop tests 2008-07-27 18:39:16 +01:00
Nick Gasson ba462eb8b7 Merge branch 'vhdl' of [email protected]:nickg/iverilog into vhdl 2008-07-25 20:00:26 +01:00
Nick Gasson 5a09819729 Catch case of select expression on non-variable 2008-07-24 16:00:12 +01:00
Nick Gasson d3296d4895 Refactor while/for loop code to use common base 2008-07-24 15:22:25 +01:00
Nick Gasson 39c9c54760 Add repeat statement 2008-07-24 14:52:06 +01:00
Nick Gasson 8bee5b1108 Add `forever' statement type 2008-07-24 14:30:10 +01:00
Nick Gasson e4c2400eb2 Refactor the expression->time code into a single function 2008-07-23 16:18:49 +01:00
Nick Gasson 1409207def Correctly indent case statements 2008-07-23 14:31:41 +01:00
Nick Gasson 30fdadc525 Support delays in logic devices 2008-07-23 13:40:42 +01:00
Nick Gasson a5db0297b0 Unary minus 2008-07-22 15:44:29 +01:00
Nick Gasson e25f946ac0 Merge branch 'vhdl' of file:///media/disk/data/iverilog/ into vhdl 2008-07-21 15:20:42 +01:00
Nick Gasson 2f4f075005 Typo 2008-07-21 15:20:40 +01:00
Nick Gasson 3ca85491ee Unary AND and XOR 2008-07-20 16:41:57 +01:00
Nick Gasson d8351ec1b2 Fix reduction OR in procedural code 2008-07-20 15:13:20 +01:00
Nick Gasson 77508b9afa Reduction OR operator 2008-07-20 15:10:00 +01:00
Nick Gasson 38de6ebf3a Compress support function definitions a bit 2008-07-19 21:04:52 +01:00
Nick Gasson af3ee49f57 Refactor support function code a bit 2008-07-19 20:49:55 +01:00
Nick Gasson 0cb6ea34d7 Move type conversion code into a separate file 2008-07-19 15:23:47 +01:00
Nick Gasson b6df73d3b9 Support functions for converting (un)signed -> boolean 2008-07-19 15:15:16 +01:00
Nick Gasson 2d79e1a2e0 Store the currently active entity 2008-07-19 14:45:00 +01:00
Nick Gasson 7b311b6adb Translate internal delays in assignments 2008-07-18 14:47:35 +01:00
Nick Gasson df4a380e42 Fix implementation of IVL_LPM_UFUNC
Function name was not correct.
2008-07-18 14:31:12 +01:00
Nick Gasson 6ff80e80a4 Catch case where (un)signed is converted to boolean 2008-07-18 12:30:24 +01:00
Nick Gasson 8b6b111541 Add IVL_LPM_CMP_EQ 2008-07-18 11:58:26 +01:00
Nick Gasson fd8f01e317 Add IVL_LPM_CMP_GE 2008-07-18 11:56:00 +01:00
Nick Gasson 00317dd47f Dummy implementation of $time 2008-07-18 11:50:05 +01:00
Nick Gasson e9637f6d11 Generate synthesisable code for sequential processes
Whilst adding `wait until ...' at the end of every
process is a valid translation of the input, it is not
actually synthesisable in at least one commercial
synthesiser (XST). According to the XST manual the
correct template is to use `wait until ...' at the
start of sequential processes and `wait on ...'
(equivalent to `wait until ...' with 'Event on all
the signals) at the end of combinatorial processes.
This patch implements that.
2008-07-17 17:36:42 +01:00
Nick Gasson 1f9ed2c5ec VHDL AST element for `wait on' statement 2008-07-17 17:23:21 +01:00
Nick Gasson 7677b59650 Make sure offset of IVL_LPM_ARRAY is integer 2008-07-17 16:41:34 +01:00
Nick Gasson 9cf4792d53 Translate array references in expressions 2008-07-17 14:47:10 +01:00
Nick Gasson 4d9f029000 Generate correct array bounds 2008-07-17 14:38:07 +01:00
Nick Gasson 9916686c24 Convert constant bits to integers 2008-07-17 14:29:56 +01:00
Nick Gasson c86377790f Automatically convert constant bit strings to integers 2008-07-17 14:26:35 +01:00
Nick Gasson 2a791bfb38 Assignment to arrays 2008-07-17 13:41:44 +01:00
Nick Gasson 1d3ac6bc1f Generate VHDL array type declarations of Verilog arrays 2008-07-17 13:08:55 +01:00
Nick Gasson 3fa5a04947 Merge branch 'vhdl' into array 2008-07-17 12:01:09 +01:00
Nick Gasson 7c5b0f737c Class for VHDL type declarations 2008-07-17 11:59:02 +01:00
Nick Gasson c116808fdb Remove duplicated code 2008-07-17 11:46:36 +01:00
Nick Gasson 553f3d77a9 Code for VHDL array type 2008-07-17 11:43:59 +01:00
Nick Gasson 642fbe9fc5 Correct check for arrays 2008-07-17 11:31:06 +01:00
Nick Gasson 395a2248d8 Make sure 1-bit constants are std_logic not (un)signed 2008-07-16 16:52:15 +01:00
Nick Gasson be67cae29f Add translation for IVL_ST_CASEX 2008-07-16 16:42:44 +01:00
Nick Gasson f62a00bedb Fix LPM binop with different signedness
Need to explicitly cast between signed/unsigned to
make sure both arguments have the same type or the
VHDL won't compile.
2008-07-16 16:20:08 +01:00
Nick Gasson 646a6056a2 Add IVL_LPM_CMP_EEQ support 2008-07-16 12:50:55 +01:00
Nick Gasson 4504c2bceb Fix initialisation order bug with `if' statements
If an assignment appears inside an if statement branch
it could be incorrectly used as the signal's initial
value.
2008-07-16 12:11:00 +01:00
Nick Gasson d343db34fd Fix initialisation order
Initial processes set a magic flag in the code generator
which allows it to push constant assignments into the
VHDL signal initialisation and omit the assignment.
However, it should only do this if the signal has not
already been read (otherwise the previous read would
not get the undefined value as expected)
2008-07-16 12:00:11 +01:00
Nick Gasson b5e12077b2 Fix assignment to lval slice
It was broken in yeserday's refactoring
2008-07-15 18:40:30 +01:00
Nick Gasson f3753ea9ad Add warning that arrays are not yet implemented 2008-07-15 18:09:18 +01:00
Nick Gasson 45e289d32d Implement IVL_LPM_SHIFTL/R 2008-07-15 18:01:37 +01:00
Nick Gasson 40cabff44f Leave blank line at end of function 2008-07-15 16:30:50 +01:00
Nick Gasson a9c98ad5f2 Handle `if' with empty cond_true part
Fixes assertion failure with following statement:

if (foo)
  begin
  end
else
  ...
2008-07-15 14:26:19 +01:00
Nick Gasson b8e758edf0 Refactor LPM code 2008-07-15 14:09:24 +01:00
Nick Gasson 0b48f69b4e Tidy up blocking assignment code 2008-07-15 10:44:48 +01:00
Nick Gasson d1e7e325b7 Remove redundant edge_detector function 2008-07-14 21:34:48 +01:00
Nick Gasson 75b1db0add Fix assignment with ternary RHS
This was also broken in the last commit
2008-07-14 21:27:21 +01:00
Nick Gasson 6e965523a1 Fix PV assignment (was broken in last commit) 2008-07-14 21:09:19 +01:00
Nick Gasson 8589c0691b Refactor assignment code 2008-07-14 21:04:09 +01:00
Nick Gasson 99ef8ec4f1 Simplify edge detector code
Now generates a `wait until' statement rather than a
sensitivity list.
2008-07-14 20:29:49 +01:00
Nick Gasson d22c9a8b05 Simplify blocking assignment
Now generates 'wait for 0 ns' after non-blocking assignment
2008-07-14 19:54:45 +01:00
Nick Gasson f84f50842c Support bufif for tri1 nets 2008-07-14 19:13:11 +01:00
Nick Gasson 65720f49fe Simple bufif cases 2008-07-14 19:00:58 +01:00
Nick Gasson 6243736481 Pull-up/pull-down logic devices 2008-07-14 12:04:20 +01:00
Nick Gasson e331e4831b Fix nexus_to_expr where nexus has IVL_LPM_SELECT_PV 2008-07-14 11:53:38 +01:00
Nick Gasson 78ee61558d Remove redundant test
Signal is guaranteed to appear in arch_scope or its parent
by the surrounding `if' statement.
2008-07-13 15:27:07 +01:00
Nick Gasson 07c4ff7ea7 Add assertion about result of lpm_to_expr 2008-07-13 15:26:03 +01:00
Nick Gasson e5422dddd2 Remove useless `ignore' param to nexus_to_expr 2008-07-13 15:24:35 +01:00
Nick Gasson 6af201ea03 Refactor nexus expansion functions.
Now a single function nexus_to_expr
2008-07-13 15:17:14 +01:00
Nick Gasson 27a40cfdcd Constant assignments to outputs
If the Verilog source contained a continuous assignment
of a constant to an output, it would not be present in
the VHDL output. This patch generates a VHDL continous
assignment in these cases.
2008-07-13 13:02:17 +01:00
Nick Gasson 3bd480a375 Allow ouput to be read if connected to child output
If output P of A is connected to output Q of B (and A is
instantiated inside B) then VHDL does not allow B to read
the value of Q (also P), but Verilog does. To get around
this the output Q is mapped to P_Sig which is then connected
to P, this allows B to read the value of P/Q via P_Sig.
2008-07-13 12:41:02 +01:00
Nick Gasson aa951af2b7 Change 'signdness' to 'signdness' 2008-07-10 19:27:17 +01:00
Nick Gasson 55747bf79d Refactor signdness changing code into a single function
This is the code that generated calls to signed/unsigned in
the VHDL output.
2008-07-08 13:07:11 +01:00
Nick Gasson 1cd7689d03 Fix casting with signed/unsigned expressions
Previously the code generator tried to infer the VHDL types. Now it
takes a much more dumb approach and forces the VHDL type to be
the same as the ivl type (derived from ivl_expr_signed and
ivl_expr_width) in the expression tree. This works much better :-)
2008-07-08 12:58:50 +01:00
Nick Gasson bd5cc96956 Correct vector sizes for bit select 2008-07-08 00:20:31 +01:00
Nick Gasson a0dbb1aa5d Fix more bugs in part selects 2008-07-07 21:45:27 +01:00
Nick Gasson 4777966b4c Bit select bug fixes 2008-07-07 21:19:59 +01:00
Nick Gasson 860a74ddd8 Allow LPMs in port maps 2008-07-07 20:41:29 +01:00
Nick Gasson 2bb645e0bc Refactor LPM code to allow lpm->expr function 2008-07-07 19:46:18 +01:00
Nick Gasson 47db80315c Add sign extension LPM 2008-07-07 19:27:52 +01:00
Nick Gasson 0348664512 Correctly determine VHDL type of LHS of part select 2008-07-07 16:35:39 +01:00
Nick Gasson 3987e0753d Fix case where booleans are compared against vectors 2008-07-07 16:31:27 +01:00
Nick Gasson 6b73cc39a5 Add Active_High support func and fix LPM part select 2008-07-07 16:17:54 +01:00
Nick Gasson b0de1a8d7e Implement part select for LHS of assignment 2008-07-07 16:11:45 +01:00
Nick Gasson 37fe6e4219 Dummy implementation of IVL_LO_BUF* 2008-07-07 15:49:51 +01:00
Nick Gasson 89cdbf63be Reduction LPM types 2008-07-07 15:45:20 +01:00
Nick Gasson 7f955cc070 Move the VHDL support package 2008-07-07 15:36:13 +01:00
Nick Gasson 4db5b9d7ed Add unary OR/NOR
These are currently implemented with reference to an external
Reduce_OR function
2008-07-07 15:23:57 +01:00
Nick Gasson dadd145d09 Add message for unsupported LPM nexus pointer 2008-07-07 15:04:28 +01:00
Nick Gasson bdf5ee7ab7 Concat LPM 2008-07-07 14:48:57 +01:00
Nick Gasson ebaa4c7d5d Implement assignment to part select properly
Previously the base of the lval was ignored, this ensures
the correct assignment is generated.
2008-07-07 11:00:27 +01:00
Nick Gasson c33600bcc3 Add concatenation operator 2008-07-06 18:21:34 +01:00
Nick Gasson 85d2cc78d6 Finish ternary operator expansion 2008-07-06 17:56:48 +01:00
Nick Gasson 18071562ba Partially implement ternary expressions
This handles the case where the expression appears as the
right hand side of an assignment. The expression is converted
into a regular if statement.
2008-07-04 21:55:51 +01:00
Nick Gasson 5aeff6d47d Merge blocking and non-blocking assignment code 2008-07-04 20:07:38 +01:00
Nick Gasson a298b03735 Add bitwise OR 2008-07-04 12:05:49 +01:00
Nick Gasson 3d0a2b55ce Avoid declaring same function multiple times
If it appears in multiple places in the hierarchy
2008-07-04 12:03:37 +01:00
Nick Gasson 19871efd5a Fix bug where sensitivity might reference undefined signals 2008-07-04 11:58:33 +01:00
Nick Gasson 1410c339de Make sure any calls to numeric_std Resize have correct type
The signed/unsigned-ness of an expression needs to be
preserved over any call to Resize. Also add a sanity
check to make sure non-vector types are not resized.
2008-07-04 11:36:11 +01:00
Nick Gasson 96d32b29c9 Translate logical expressions correctly.
For logical AND/OR in VHDL both operands must be of the
same type (Boolean)
2008-07-04 11:23:32 +01:00
Nick Gasson 88816e150a Properly parenthesise unary operators 2008-07-04 11:17:24 +01:00
Nick Gasson 409fc4dc19 Check if case expression variable is already defined
Verilog_Case_Ex is used as a temporary to store the result of
any non-static case expression. This fixes a bug where it would
be declared multiple times if there were multiple case statements
in a block.
2008-07-04 11:15:34 +01:00
Nick Gasson c54b36c902 Add logical AND operator 2008-07-04 11:10:20 +01:00
Nick Gasson 19cbab78b2 Tidy up code to generate default branch of case 2008-07-03 20:04:47 +01:00
Nick Gasson 1736cd9bc8 Fix uneccessarily complicated generated case statement
No need to generate separate case test variable if the
test in the VL source is a simple variable reference.
2008-07-03 16:27:36 +01:00
Nick Gasson a5264e9995 Make sure all choices are covered in case statement 2008-07-03 16:17:56 +01:00
Nick Gasson 6868127ba3 Make sure case expression has the correct type 2008-07-03 16:14:17 +01:00
Nick Gasson dbbadbc309 Make sure the renamed signal is used in the sensitivity list 2008-07-03 16:13:02 +01:00
Nick Gasson fb08164cbc List some more illegal VHDL names 2008-07-03 15:20:43 +01:00
Nick Gasson 7e999c5496 Fix continuous assignment of constants
E.g. in assign p = 1 the RHS signal in the generated LPM now
has a correct intial value (and it will never be written to
elsewhere)
2008-07-03 15:13:12 +01:00
Nick Gasson 4fac825457 Add PV part select type 2008-07-03 14:45:54 +01:00
Nick Gasson 35c66744db Cleanup and remove debug output 2008-07-01 11:31:00 +01:00
Nick Gasson 930e04f6c7 Ensure port map expressions are globally static 2008-07-01 11:28:02 +01:00
Nick Gasson 37756b8d06 Avoid mapping a signal to itself 2008-07-01 11:13:02 +01:00
Nick Gasson 596c93ce7e Rename instance if it has the same name as the type 2008-07-01 11:05:24 +01:00
Nick Gasson edfae1abfb PV LPM part select type 2008-07-01 11:02:49 +01:00
Nick Gasson 624943b3ca Simplify port map generation code 2008-07-01 10:59:31 +01:00
Nick Gasson ef89a760d6 Add vhdl_element::print method for debugging 2008-07-01 10:44:20 +01:00
Nick Gasson 050aa277ae Make vhdl_element::emit a little more generic 2008-07-01 10:37:22 +01:00
Nick Gasson f03dfb50ad Refactor nexus_to_var_ref 2008-07-01 10:33:46 +01:00
Nick Gasson 6e8474f584 Fix bug where func had to be declared before use 2008-06-30 17:58:15 +01:00
Nick Gasson 4e73b1b133 Fix bug when resolving nexus to VHDL signal 2008-06-30 17:47:45 +01:00
Nick Gasson e08e29c8b4 Add UFUNC LPM type 2008-06-30 16:35:29 +01:00
Nick Gasson b82ca28190 Add XOR logic type and fix part select 2008-06-30 16:18:55 +01:00
Stephen Williams e02d186946 Handle multiple passes of scope and defparam elaboration.
When generate schems and instance arrays are nested, it takes
multiple iterations of elaborate scope, defparams and evaluate
parameters before everything is worked out. Rework the work item
processing so that the loop elaborates scopes and runs defparams
in phases. The phases are needed so that we can tell when the
remaining defparams are orphaned.
2008-06-30 03:46:46 +02:00
Stephen Williams d9b02657a7 Modules within generate schemes are not default roots.
Modules mentioned within generate schemes are not candidates for
defaults guesses at root modules. They are, obviously, used within
the generate schem.
2008-06-28 13:34:46 -05:00
Stephen Williams d761a2273c Run generate schemes after defparams.
We must run generate schemes after running defparams because the
defparams may define the results of the generate schemes. So put
the generate schemes for a module scope into elaborator work items.
2008-06-28 13:06:14 -05:00
Stephen Williams e3d9cc30a8 Checkin some developer convenience scripts. 2008-06-28 09:51:42 -07:00
Stephen Williams 1ef7994ae2 Handle indexed defparams.
The l-value of a defparam assignment is a hierarchical name that may
include array selects to select scopes from module arrays. Therefore
it makes no sense to store parsed defparams in a map. Instead, they
should go into an ordered list. This also maked more sense because later
defparams *may* have the same name as a previous defparam, and will
override the previous defparam. So replace the map of parsed defparams
with a list of parsed defparams.

Also, as soon as the defparam expression is elaborated, the list entry
is no longer needed, so delete it. Save memory.
2008-06-28 09:30:09 -07:00
Nick Gasson 081f397460 Implement LPM part select 2008-06-27 14:58:03 +01:00
Nick Gasson f800298d01 Fix memory leak 2008-06-27 12:29:50 +01:00
Nick Gasson 301a25303f Remove useless assertion 2008-06-27 12:21:53 +01:00
Nick Gasson b24eb6ce88 Handle local variables in functions 2008-06-27 12:21:27 +01:00
Nick Gasson fd60bfd3d2 Rewrite function parameter finding code 2008-06-27 12:18:39 +01:00
Stephen Williams da2c4b0fa1 Multiple passes for run_defparams.
It is possible for defparams to not find their target the first time
around, because the elaboration of the target scope is not yet done.
So retry the defparams once for each scope by putting it on a work
item in the elaborator_work_items list.
2008-06-25 22:02:22 -07:00
Stephen Williams 4251979e8b Merge branch 'master' into defparam-rework 2008-06-25 20:26:01 -07:00
Cary R 12783674cb Clean up compiler warning. 2008-06-25 16:34:54 -07:00
Cary R c17ffcae2c Rework previous patch to use the correct method. 2008-06-25 15:42:41 -07:00
Cary R 897f14e60a Fix memory leak in recent patch. 2008-06-25 15:42:34 -07:00
Cary R 4163eb28d0 Copy file and line info during a macro expansion.
The file and line number information needs to be copied when
doing a macro expansion. This prevents a macro that expands to
an `ifdef of other construct that needs to push the stack
from core dumping.
2008-06-25 15:42:29 -07:00
Nick Gasson 500442e5c5 Working function calls 2008-06-25 22:15:57 +01:00
Stephen Williams 8c54803094 vpi_get_value of integer values replaces x/z bits with 0.
In arithmetic expressions, vectors with x/z are replaced with 0,
but vpi_get_value replaces x/z bits with 0 bits without replacing
the whole vector.
2008-06-25 13:59:39 -07:00
Nick Gasson 2baf31dff8 Fix bug with $display and integer literals 2008-06-25 21:54:11 +01:00
Nick Gasson d997397c38 Generate function calls with parameters 2008-06-25 21:49:22 +01:00
Nick Gasson 7773000c36 Generate function declarations 2008-06-25 21:40:35 +01:00
Nick Gasson 042f7ccbcd Generate a return type for functions 2008-06-25 18:43:50 +01:00
Nick Gasson 44aa8a6b91 Associate signals with scopes rather than entities 2008-06-25 18:12:57 +01:00
Nick Gasson 43c671cb5c Emit VHDL for function declarations 2008-06-25 18:00:48 +01:00
Nick Gasson a3df37b851 Initial code to generate function calls
Also catch a few null-pointer issues
2008-06-25 17:29:09 +01:00
Nick Gasson c01c2bd742 Dummy code for handling function scopes 2008-06-25 12:48:46 +01:00
Stephen Williams 533ee87bb1 Delay elaborate of instance array scopes to allow defparams to propagate.
When we detect that a module instance is an array of instances, delay
the elaboration of the array until after the first defparam processing
is complete. This allows for defparam statements to control the
instantiation of module instance arrays.
2008-06-24 22:03:28 -07:00
Stephen Williams c810406195 run scope elaboration as queued work items.
Putting scope elaboration into work queue items allows for handling
more complex processing order. The elaboration_work_list queue drives
the processing of elaborate_scope and parameter evaluation.
2008-06-24 20:28:08 -07:00
Larry Doolittle 3ec8a867db Spelling fixes
comments, documentation, a variable name, and a couple of messages
2008-06-24 17:01:45 -07:00
Nick Gasson 899a70908e Fix small bug with initialisation and ammend comments 2008-06-24 20:13:18 +01:00
Nick Gasson bf95d77562 Finish replacing vhdl_process with vhdl_procedural 2008-06-24 20:01:06 +01:00
Nick Gasson db992e808f Start using vhdl_procedural instead of vhdl_process 2008-06-24 19:54:22 +01:00
Nick Gasson f2aca68b82 Add new vhdl_procedural superclass for process/task/func 2008-06-24 19:50:57 +01:00
Nick Gasson 12b448ef01 Merge branch 'vhdl' of [email protected]:nickg/iverilog into vhdl
Conflicts:

	tgt-vhdl/vhdl_syntax.cc
2008-06-24 19:42:35 +01:00
Nick Gasson e77bb0157e Remove redundant methods from vhdl_arch 2008-06-24 19:39:05 +01:00
Nick Gasson 75631bd8f1 Move is_inital code out of vhdl_process into vhdl_scope
Part of tidy up before implementing functions
2008-06-24 19:06:06 +01:00
Nick Gasson 63b1887ff2 Refactor code to use the new vhdl_scope class 2008-06-24 18:52:25 +01:00
Nick Gasson ba36e47575 Add new vhdl_scope class and refactor 2008-06-24 18:12:00 +01:00
Nick Gasson 3866c4526e Simplify code to emit operators 2008-06-24 14:58:58 +01:00
Nick Gasson cb08f02de1 Resize signed/unsigned bit vectors correctly 2008-06-24 10:58:21 +01:00
Nick Gasson 4188fbecee Add XOR operator and catch default case branch 2008-06-24 10:55:45 +01:00
Nick Gasson f261bf7e97 Fix bug where variables could be declared twice 2008-06-23 15:13:10 +01:00
Nick Gasson 88dc9b6b63 Remove debugging information from the output 2008-06-23 15:02:26 +01:00
Nick Gasson 632a265e14 Fix casting/resizing order bug 2008-06-23 15:00:55 +01:00
Nick Gasson 449cd0a76e Correctly generate signed/unsigned types 2008-06-23 14:28:27 +01:00
Nick Gasson 181a53d3ed Merge branch 'master' of git://github.com/steveicarus/iverilog into vhdl 2008-06-23 13:48:56 +01:00
Nick Gasson 44958409f5 A slightly smarter $display 2008-06-23 13:45:24 +01:00
Nick Gasson f81129aa68 Fix some bugs with blocking assignment 2008-06-23 13:36:28 +01:00
Nick Gasson e5ef0d97bd Fix signed/unsigned resizing 2008-06-23 13:04:28 +01:00
Nick Gasson 469036990a Output blocking assignments in the right place 2008-06-23 12:30:48 +01:00
Nick Gasson d06f5c7c54 Emit loop statements with the correct indent 2008-06-23 12:27:30 +01:00
Nick Gasson 9911939576 Simplify casting code 2008-06-23 12:21:10 +01:00
Nick Gasson c9ace14c40 Shift operators working correctly 2008-06-23 12:14:12 +01:00
Nick Gasson d5cdb91d55 Handle complex expressions in case statement 2008-06-23 11:36:12 +01:00
Stephen Williams 360be597a8 Minor cleanup and comments.
The initial elaboration needs better comments/documentation.
2008-06-21 18:36:46 -07:00
Nick Gasson 75f7c9ae0c Only move constant assignments into initialisation 2008-06-21 16:40:18 +01:00
Nick Gasson c926454a41 Statements might be emitted in wrong order 2008-06-21 16:33:05 +01:00
Nick Gasson 5cfe7ea0aa Tidy up output 2008-06-21 16:28:07 +01:00
Nick Gasson c70fb4ba08 Simple implementation of IVL_EX_SELECT 2008-06-21 16:17:44 +01:00
Nick Gasson 7cba9f3cb2 Shift left/right 2008-06-21 15:19:33 +01:00
Nick Gasson d6acb8d059 Less than / greater than 2008-06-21 15:16:22 +01:00
Nick Gasson ec23b70bb7 While loops 2008-06-21 15:13:44 +01:00
Nick Gasson 58f2f5007d Bitwise AND 2008-06-21 15:05:48 +01:00
Nick Gasson 0caf4fd9d0 Add case statement 2008-06-21 15:03:36 +01:00
Nick Gasson 037ce08f72 Fix tiny bug in $display code 2008-06-21 14:42:54 +01:00
Cary R 27cdd27889 Add .cast/int and update .cast/real.
This patch adds .cast/int and updates .cast/real to act as a local
(temporary) net and to support either a signed or unsigned input.
The vvp_vector4_t class not can convert an arbitrarily sized double
to a vector value. This removes the restriction of lround().

Also document the new statements.
2008-06-20 19:45:18 -07:00
Larry Doolittle f60a6561bb Cast strlen to int for printf field width
strlen is a size_t, and the * field width takes an int.
Make this an explicit cast.  It's good for 64-bit machines
and squelches warnings from gcc-4.3.
2008-06-20 15:54:32 -07:00
Nick Gasson 204862ac3c Implement $write 2008-06-20 19:00:07 +01:00
Nick Gasson 0f50849fbb Add call to To_Integer when printing signed/unsigned 2008-06-20 18:26:39 +01:00
Nick Gasson 404c22ac86 Improved implementation of $display 2008-06-20 11:51:13 +01:00
Stephen Williams fe555e4539 Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-06-19 21:32:18 -07:00
Stephen Williams c87e629150 Better handle nesting of scopes inside generate blocks.
Within generate schemes it is possible to have nested scopes, even
more liberally then outside generate blocks. So see to it that the
scopes properly stack with the generate blocks, and that wires and
behaviors are put in the right scopes.
2008-06-19 21:31:53 -07:00
Stephen Williams b9d6c816f1 Properly evaluate a unary ! with logic argument and real result. 2008-06-19 19:14:19 -07:00
Stephen Williams 0153a25061 Elaborate nets with real-valued parameters. 2008-06-19 19:13:50 -07:00
Cary R 476a4c7bc4 Add a script to manually build the version.h file.
This script is used to manually build a version.h file.
It is needed when building with MinGW using a cygwin
hosted repository.
2008-06-19 16:59:22 -07:00
Nick Gasson 08d80b35cb Rename signals that would be illegal VHDL names 2008-06-19 16:15:47 +01:00
Nick Gasson 6622b5fe3a Compare logic values for === and !== 2008-06-19 16:08:33 +01:00
Nick Gasson d7bb5658f2 Translate IVL_ST_DELAYX statements 2008-06-19 12:16:19 +01:00
Stephen Williams 2f3627cd6d Allow generate schemes to generate task/function definitions.
Generating task/function definitions involves getting the functions
to put themselves into the generate scheme instead of the module,
and getting elaboration to elaborate those definitions in the
generate scheme.
2008-06-18 21:54:58 -07:00
Stephen Williams ce9fd0147f Detect and warn about anachronistic use of begin/end in generate.
Verilog-2001 only allows a single generate item within a generate-
endgenerate region, but allowed one to collect generate schemes with
begin/end blocks. Verilog-2005 cleaned up that mess, and it is the
2005 syntax that Icarus Verilog implements. This patch detects the
anachronistic use of begin/end within the generate region, ignores
the begin/end words, and prints a warning that the user is using an
obsolete syntax.
2008-06-18 20:33:30 -07:00
Nick Gasson be12f56856 Document blocking assignment behaviour 2008-06-18 14:04:16 +01:00
Nick Gasson e0f41198d6 Blocking assignment working correctly 2008-06-18 13:49:03 +01:00
Nick Gasson fb31a88c51 Blocking assignment nearly working 2008-06-18 13:30:19 +01:00
Nick Gasson 254ccb9ccb First passing at blocking assignment 2008-06-18 13:06:27 +01:00
Nick Gasson d2bebee9d9 Refactor before adding blocking assignment 2008-06-18 12:51:11 +01:00
Stephen Williams b2c9352bb5 Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-06-17 21:45:58 -07:00
Stephen Williams 15481a9520 Elaborate block scopes burried in generate schemes.
Named begin/end blocks burried within generate schemes need to be
elaborated. Handle this by remembering to elaborate_scope on the
statements within the generate scheme.

In the process, clean up/regularize some of the member names and
methods.
2008-06-17 21:45:37 -07:00
Stephen Williams 37723698dc Handle non-real operands to real division.
This handles the general case of a non-real operand to a real-valued
division. This can turn up if only 1 operand of a divide is real. In
this case the division as a whole is real and the other operand must
be cast to real.

This method creates an extra node, but it should be a very compact
node and this node does no evaluation tricks so in the run time should
be no more expensive then folding the cast into the .arith/div.r itself.
2008-06-17 17:07:19 -07:00
Nick Gasson af8c08e6a7 Allow optional VHPI $finish implementation 2008-06-17 20:16:16 +01:00
Nick Gasson 01249000c3 Temporarily treat blocking assignment as non-blocking 2008-06-17 14:07:36 +01:00
Cary R f6edd098a9 More file name and mode checks for $fopen{a,r,w}?.
This patch adds checks that $fopen is only called with a valid
mode argument. It also checks that the file name for $fopen{a,r,w}?
is a valid looking file name (all characters satisfy isprint()).
The later should prevent creating weird file names because of
Verilog bugs.
2008-06-16 18:00:31 -07:00
Cary R 6321fb6a92 Pad Octal string value correctly.
This patch changes the base oct to string converter to correctly
pad the top digit. x or xx should display as a single lower case
x when they are located in the top bits. Before these were being
interpreted as 00x or 0xx and displayed X. Also modified the hex
conversion to use this same scheme instead of a loop.
2008-06-16 17:58:16 -07:00
Stephen Williams 69ba009439 Cleanup the resolver function.
First, handle the trivial (but possibly common) resolution cases in
inlined code, and only call the complete function for the complicated
cases. Then clean up the complex function for readability, and account
for the constraints that the front-end function established.
2008-06-16 17:45:08 -07:00
Stephen Williams 86e5762b1c Compact of vvp_vector4_t in arrays.
Arrays of vvp_vector4_t values redundantly store some fields in every
word. Create a special type that stores vvp_vector4_t values in a form
that does not duplicate the width of all the items. This can save a lot
of space when big memories are simulated.
2008-06-16 15:02:07 -07:00
Stephen Williams 49363c660c Remove the duplicate schedule_assign_vector.
The schedule_assign_plucked_vector is a better way to implement the
schedule_assign_vector, or at least no worse, so remove the now
redundent schedule_assign_vector.
2008-06-16 13:40:20 -07:00
Nick Gasson 1debbc3100 Simplify edge_detector() a bit 2008-06-16 20:06:06 +01:00
Nick Gasson ae0b09dd3a Don't bother emitting else part if it's empty 2008-06-16 19:53:42 +01:00
Nick Gasson 8d0afa632d Subtraction and multiplication LPM devices 2008-06-16 19:49:24 +01:00
Nick Gasson 561953e494 Minial LPM to support continuous assignments 2008-06-16 19:41:01 +01:00
Nick Gasson 83a7796b74 Make sure signal names conform to VHDL rules 2008-06-16 17:37:17 +01:00
Nick Gasson ce72eb4eb4 Fix Valgrind warnings 2008-06-16 14:26:38 +01:00
Nick Gasson 7cde5f247e Add translation for not-equals operator 2008-06-16 12:47:41 +01:00
Nick Gasson 849e7cb4d5 Add equality operator 2008-06-16 12:20:28 +01:00
Nick Gasson 92c823680a Fix crash when if' statement had no else' 2008-06-16 12:13:01 +01:00
Stephen Williams 05f1541903 Make reg initializations account for generated scope.
During parse, reg initialization may be in generated scopes. Handle
that properly.
2008-06-14 21:50:48 -07:00
Stephen Williams 30d42e2806 Allow l-value part select to be out of bounds.
It is legal (though worthy of a warning, I think) for the part select
of an l-value to me out of bounds, so replace the error message with
a warning, and generate the appropriate code. In the process, clean
up some of the code for signal l-values to divide out the various kinds
of processing that can be done. This cleans things up a bit.
2008-06-14 21:22:55 -07:00
Cary R ebdf4e478a Rework more compiletf and calltf routines in the vpi directory.
This is a major rework on the sys_fileio routines. They now have
improved compiletf routines and the calltf routines are now
standardized. Along the way a few bug were fixed as well. Some
updates to other vpi files as well.

I changed the order of the $fputc() arguments to match C and the
rest of the system functions like it ($fungetc, etc.). I recently
fixed $fungetc() so I'm assuming the $fputc() needs the same fix.
It's an Icarus specific function.
2008-06-14 20:13:52 -07:00
Stephen Williams f6bc1afcbb Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-06-14 20:00:51 -07:00
Stephen Williams 9013dcb527 Signed load-and-add for arrays.
The load-and-add for vectors %load/vp0/s can be combined with the
load-and-add for array words, and the %load/avp0/s added to round
out the combinations. This can make for fewer instructions when
words are padded in arithmetic expressions.
2008-06-14 19:59:57 -07:00
Stephen Williams dbe13aecea Signed load-and-add for arrays.
The load-and-add for vectors %load/vp0/s can be combined with the
load-and-add for array words, and the %load/avp0/s added to round
out the combinations. This can make for fewer instructions when
words are padded in arithmetic expressions.
2008-06-14 18:16:23 -07:00
Stephen Williams 6521ceaf92 Union scope and parent pointers for signals.
If a signal is part of an array, then it can get its scope from its
parent, so the scope and parent pointers can go into a union.
2008-06-14 16:17:25 -07:00
Stephen Williams f497dbf01e Created too mane vvp_net_t objects?
The functor_ref_lookup() function fills its argument in with the
vvp_net_t* pointer that matches the var name, so there is no need
to create the vvp_net_t object before then.
2008-06-14 15:31:48 -07:00
Nick Gasson 8a9486eb49 Eliminate useless Resize() call 2008-06-14 18:11:10 +01:00
Nick Gasson 2fb57805ea Use signed rather than std_logic_vector
Arithmetic operators now working correctly
2008-06-14 18:03:25 +01:00
Nick Gasson 919c1d695c Adding binary + 2008-06-14 17:09:31 +01:00
Stephen Williams 1530594b4b Implement vpiIndex for vpiMemoryWord objects.
The vpiIndex is really just a different view into the same object,
so implement the trickery needed to support a vpiIndex with the
absolute minimum memory cost.
2008-06-13 22:05:19 -07:00
Stephen Williams 6f0d8e8dda Load_add_immediate to work with signed expressions
The %load/vp0 instruction adds a signed value to the signal value being
loaded, but it doesn't allow for a signed source vector. Add the
%load/vp0/s instruction that pads the loaded vector, and add the code
generator details to properly use it.
2008-06-13 20:23:40 -07:00
Stephen Williams 62d7c081dc Sign extend signed vectors when getting vpiIntVal.
When getting values using vpi_get_value, the vpiIntVal is the integer
value and should be sign-extended if the source value is signed.
2008-06-13 19:47:48 -07:00
Cary R f78994b66c Allow &PV<> to reference a VPI object (signal) for the base.
This patch adds code to allow &PV<> to access a VPI object
(signal) for the base of an indexed part select. This
mirrors the code added to &A<>.
2008-06-13 18:42:08 -07:00
Cary R 50a8c17cf8 Comparison arguments are in a self determined context.
This patch makes comparison arguments be evaluated in a self
determined context. It also cleans up some other code items.
2008-06-13 18:05:46 -07:00
Stephen Williams 6f9643df79 Better array statistics.
Allocation counters for arrays and array words of various types.
2008-06-13 17:41:24 -07:00
Stephen Williams aeaf8e8433 Permalloc vvp_net_fun_t objects.
The vvp_net_fun_t objects, and derived objects, are small, and are
created in large quantities. Tightly pack them into permanently
allocated space in order to save on system allocation overhead, and
thus save overall on memory.
2008-06-13 17:08:11 -07:00
Stephen Williams 7afb280990 Allow that sum immediate values can be signed.
Actually, the immediate value handling is a little chaotic and should
be cleaned up. This patch opens the door for allowing signed immediate
values, and uses them in a few places where they are explicitly handled.
We must go through the opcodes that can take immediate values and make
explicit whether they are signed/unsigned/etc, and what their size
limits are.
2008-06-13 13:32:06 -07:00
Cary R 99a46fd5af Fix incorrect typecast.
This patch fixes an incorrect typecast in vvp/main.cc.
2008-06-13 11:38:18 -07:00
Larry Doolittle eed4ff7e2d Spelling fixes
Mostly comments, but includes quite a few
user-visible error, debug, and help messages.
2008-06-13 08:51:28 -07:00
Stephen Williams 659714f45d Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-06-13 08:41:40 -07:00
Larry Doolittle 8f70c5ca35 Add missing include to vvp/vvp_net.h
Fixes FTBFS under gcc-4.3
2008-06-13 08:40:26 -07:00
Nick Gasson 0ea64ad8ab Correct misleading comment 2008-06-13 14:47:06 +01:00
Nick Gasson 9fbb449e06 Optimise away empty (VHDL) processes 2008-06-13 14:17:24 +01:00
Nick Gasson be3c4cf268 Generate signal initial values from `initial' processes 2008-06-13 14:10:28 +01:00
Nick Gasson 0a8fd50c4a Find assignments that could be initializers 2008-06-13 13:59:48 +01:00
Nick Gasson 70db096b6d Clean up the edge detector code a bit 2008-06-13 12:52:20 +01:00
Nick Gasson 005df31a0d Use renamed signal in expressions, if there is one 2008-06-13 12:39:18 +01:00
Nick Gasson d6193c1622 Add _Reg internal signal if output is registered 2008-06-13 12:34:27 +01:00
Stephen Williams a74f2827b2 Part select of signals is always unsigned.
Part select of an entire signal returns just the NetESignal itself,
but since part selects are always unsigned, even if the selected
signal is signed, we need to cast the NetESignal to unsigned first.
2008-06-12 21:56:46 -07:00
Stephen Williams 392b162024 Allow canonical part select of net vectors to be larger then the vector
The part select of a vector is converted by the compiler during
elaboration to a 0-based canonical address. But since it is legal
to address bits below the LSB, the canonical address can be negative.
So make the part select base for selecting from signals work with
signed arithmetic and make the code generator generate negative
indices when needed.
2008-06-12 21:41:11 -07:00
Stephen Williams 4af4c8cca9 Permallocate scheduler cells in chunks
Scheduler cells are small objects that come and go in great quantities.
Even though they are allocated and deallocated a lot, they tend to a
steady state quantity, so put together a heap that is unique for each
cell type.

This heap actually saves memory overall because cells are allocated in
chunks, thus eliminating allocator overhead, and they are pulled/pushed
from/to a heap very quickly so that what overhead remains is slight and
bounded.
2008-06-12 19:55:53 -07:00
Stephen Williams 3c4346acb2 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.(cherry picked from commit d0f303463d)
2008-06-12 13:00:31 -07:00
Nick Gasson b8c1f9ab67 A system for linking ivl_signal_t to entities 2008-06-12 20:26:23 +01:00
Stephen Williams 2e9970a98c Have vvp_vector8_t avoid allocating tiny scalar arrays.(cherry picked from commit 35fe8fae00) 2008-06-12 12:10:58 -07:00
Stephen Williams 4914b734dc 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 have the islands take more care not to perform resolution if the
inputs aren't really different.

NOTE: This is a port of commit 2f4e5bf5b6
from the "performance" branch, without the resolver scheduling changes.
This was causing test suite variances with pr1820472.v. It looks like
there might be a race in that program anyhow, but for now leave out the
resolver scheduling changes so that the rest of this commit can go in.
2008-06-12 12:08:02 -07:00
Nick Gasson 0df3eabe26 Convert if (foo) ..' to if foo = '1' then ..' 2008-06-12 11:36:21 +01:00
Nick Gasson 8fe2211e2b Generate after' modifier instead of wait' statements 2008-06-12 11:24:43 +01:00
Nick Gasson 645ee2003f Translation for unary not 2008-06-12 10:56:28 +01:00
Nick Gasson d6f1162547 Generate correct VHDL signal values 2008-06-12 10:50:46 +01:00
Nick Gasson 46991aa65c Generate process bodies in the right place 2008-06-12 10:47:52 +01:00
Nick Gasson 7eb41304e6 Generate rising/falling edge detectors 2008-06-12 10:36:38 +01:00
Stephen Williams 24da00bd5a Add value change callback for vpiPartSelect.
The __vpiPV objects express themselves as vpiPartSelect objects.
Add support for value change callbacks by attaching the callback
to the signal that we part select from.
2008-06-11 21:28:21 -07:00
Cary R 34efc7db51 Add parameter time/realtime types and other fixes.
This patch adds the time and realtime types to parameters
and local parameters. It also makes the width (range) of
an integer parameter match the variable "integer_width"
(normally 32 bits). It also converts a real value to
an integer when a range is implicitly or explicitly
given. This all matches what the standard specifies.

Fixed an error in converting -1 to a unsized verinum.
2008-06-11 19:48:15 -07:00
Cary R acf010326c Remove the signed/unsigned comparison warning 2008-06-11 19:44:21 -07:00
Stephen Williams d7814ed767 Better handle some vector size matters for %load/v
The %load/v instruction was doing some spurious resizes of the vector
that comes from the signal. Eliminate those resizes that can be
removed, and optimize some that remain.
2008-06-11 14:38:35 -07:00
Nick Gasson 19e60b698f Translate if statements 2008-06-11 14:20:05 +01:00
Nick Gasson a7cfdc3a87 Add VHDL if statement to AST types 2008-06-11 14:11:37 +01:00
Nick Gasson b010b8e3ca Use `assert false' as initial translation of $finish 2008-06-11 13:37:21 +01:00
Nick Gasson 26a2c69c2e Change architecture name to `FromVerilog' 2008-06-11 11:31:43 +01:00
Stephen Williams 608bad26cf Allow &A<> argument syntax to take a reference to a VPI object.
This allows the array index to be evaluated when the word is accessed,
and that in turn allows access in the ROSYNC scheduler phase to work
properly.
2008-06-10 20:36:31 -07:00
Stephen Williams 70768176f9 Change bit select instruction to a part select.
There is no point in having a bit select instruction and running it in
a loop (always) when we can simply turn it into a part select instruction.
2008-06-10 17:29:47 -07:00
Stephen Williams 694a6ed4a1 Remove some unused opcodes.
Codes from a dfiferent era.
2008-06-10 16:33:34 -07:00
Cary R dc15fa965b Remove MinGW unused variable warning
This patch moves the definition of rtn into the non-MinGW
branch since that is the only place it is used.
2008-06-10 15:42:56 -07:00
Cary R d78739d163 Make &PV<> put_value work correctly.
This patch finishes the put_value routine for &PV<>. It should
now work as expected.
2008-06-10 15:07:52 -07:00
Larry Doolittle d90ce68f5d Spelling fixes
No code changes.
2008-06-10 15:02:18 -07:00
Larry Doolittle d2c52ff35b Spelling fixes
No code changes.
2008-06-10 15:00:54 -07:00
Larry Doolittle 813b4cf74c Add explicit parentheses to elaborate_expr_param_part_
Removes gcc-4.3 warning: suggest parentheses around && within ||
2008-06-10 14:57:50 -07:00
Larry Doolittle a437b38270 Fix vpip_make_vthr_A prototype with duplicate parameters
Causes FTBFS with gcc-4.3
2008-06-10 14:56:55 -07:00
Stephen Williams f9d060146c Merge branch 'master' of ssh://[email protected]/~steve-icarus/git/verilog 2008-06-10 14:18:30 -07:00
Stephen Williams 7f0c6b9c21 Fix access to deleted memory.
When parameters are replaced, the expression that is replaced is deleted
so make sure the pointer in the map is properly updated. Also, make sure
the defparam expression itself is not deleted because it is used to
print messages, such as design dumps.
2008-06-10 13:25:40 -07:00
Nick Gasson 5a7cfd8c02 Clean up vhdl_comp_inst 2008-06-10 14:00:15 +01:00
Nick Gasson babe694366 Generate port mappings 2008-06-10 13:58:41 +01:00
Nick Gasson 7560b29fb9 Find signals to map together 2008-06-10 12:21:48 +01:00
Nick Gasson f6753a9013 Add ports to component declarations 2008-06-10 11:24:16 +01:00
Cary R 647e53bcbb Make &A<> use the same thread access syntax as &PV<>.
This patch makes &A<> use the same thread access syntax as
&PV<> this is two unsigned numbers separated by a space
instead of a single number.
2008-06-09 21:26:36 -07:00
Cary R 8439fc6c19 Remove two memory leaks.
This patch removes two memory leaks. One in the driver and one
in the runtime.
2008-06-09 21:23:27 -07:00
Cary R 6f61cf2e4e A memory word is a number
This will be cleaned up more once I finish all the compiletf
routines, but for now this allows the test to pass.
2008-06-09 20:00:03 -07:00
Nick Gasson 191187ed1b Cosmetic change to avoid useless `null' statement after delay 2008-06-09 16:40:32 +01:00
Nick Gasson 1fb01d4d98 Emit port declarations 2008-06-09 16:37:05 +01:00
Nick Gasson 3106fe0ed6 Generate port declarations for entities.
But doesn't emit them yet!
2008-06-09 16:27:04 +01:00
Nick Gasson e29954e03f Generate concurrent assignments from logic gates 2008-06-09 15:05:32 +01:00
Nick Gasson 3b5d56e087 Allow n-ary expressions 2008-06-09 14:53:50 +01:00
Nick Gasson aa91186119 Add AST elements for unary/binary expressions to model logic gates 2008-06-09 14:39:58 +01:00
Nick Gasson d08f5af9c6 Add concurrent assignments 2008-06-09 14:21:55 +01:00
Nick Gasson b96e471fa2 Stub code for handling logic gates 2008-06-09 14:08:27 +01:00
Nick Gasson 7120ab7b13 Expression type might be null in some cases 2008-06-09 12:54:21 +01:00
Nick Gasson 2f5dcda3b6 Delay statements now translated correctly 2008-06-09 12:49:38 +01:00
Nick Gasson 120b5dc80e Add constant integers 2008-06-09 12:46:55 +01:00
Nick Gasson d762253f74 Wait statements 2008-06-09 12:40:59 +01: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
Nick Gasson 1d28b935e8 Split vhdl_element.cc into multiple files 2008-06-08 13:27:48 +01:00
Nick Gasson 4b4a1c6cac Tidy up type casting 2008-06-08 12:55:18 +01:00
Nick Gasson 110a1b2ac7 Replace type classes with enumeration 2008-06-08 12:48:56 +01:00
Nick Gasson 79558910d1 Catch case where NULL return wasn't detected 2008-06-07 16:44:01 +01:00
Nick Gasson fbf85398da Support converting bit strings to std_logic 2008-06-07 16:19:10 +01:00
Nick Gasson 1e4b96aa0a Simplify code a bit as rval type is never needed 2008-06-07 14:57:20 +01:00
Nick Gasson c064ae6bc3 Generate VHDL for non-blocking assignments 2008-06-07 14:54:00 +01:00
Nick Gasson 39228f3495 VHDL AST element for non-blocking assignment 2008-06-07 14:31:33 +01:00
Nick Gasson 12e2237131 Add Type'Image cast to $display parameters 2008-06-07 14:21:50 +01:00
Nick Gasson 066a9b7a61 Add AST element for function call expressions 2008-06-07 13:29:27 +01:00
Nick Gasson cdb180e1d4 Associate a type with each VHDL expression node 2008-06-07 13:23:21 +01:00
Nick Gasson a8ecce7421 Make sure all declarations have a type 2008-06-07 12:15:46 +01:00
Nick Gasson 8c3461f0ff Generate sensitivity lists properly and add signal declarations 2008-06-07 11:48:38 +01:00
Nick Gasson 305f448d05 Generate code for signal references 2008-06-07 11:24:09 +01: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
Nick Gasson 5f90a3e48c Translate sub-statement of @{..} 2008-06-06 18:22:03 +01:00
Nick Gasson 96cf190720 Generate signals and sensitivity list for @(..) statement 2008-06-06 17:56:52 +01:00
Nick Gasson 373832ba22 Specify correct sensitivity list 2008-06-06 17:36:15 +01:00
Nick Gasson 4f472e451e Stubs for statement types in mux2.v test 2008-06-06 16:55:45 +01: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
Nick Gasson d36bbec5b5 Generate VHDL for no-op statements 2008-06-05 13:16:35 +01: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
Nick Gasson e258058cf1 Fully qualify std.textio.Output to avoid name collisions 2008-06-04 21:58:51 +01:00
Nick Gasson c3ac1aac8c Remove debugging messages from output 2008-06-04 21:07:50 +01:00
Nick Gasson 234f73e7bf Don't generate any output if there were errors 2008-06-04 21:03:36 +01:00
Nick Gasson f49dd97d24 Add support for blocks and make hello1.v test pass 2008-06-04 20:57:15 +01:00
Nick Gasson 7bd1565cfb $display now (mostly) working 2008-06-04 20:42:44 +01: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
Nick Gasson 6e448da90d Emit Write() calls for parameters of $display 2008-06-04 15:19:44 +01:00
Nick Gasson 9f035108e1 Stub code for translating expressions 2008-06-04 14:59:04 +01:00
Nick Gasson 4bf2e1669d Store packages required with entity rather than globally
Add parent link to architecture and process so code generators can push things higher up
$display now prints blank lines
2008-06-04 13:52:56 +01:00
Nick Gasson dd30c1b39d Support procedure call generation for $display 2008-06-04 13:27:42 +01: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
Nick Gasson 94006cb44c Working on code generation for $display task 2008-06-03 19:46:10 +01:00
Nick Gasson 2e6ec91ce0 Scalar types 2008-06-03 19:20:45 +01: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
Nick Gasson fe80da362c Collect required packages as compilation progresses 2008-06-03 19:14:47 +01:00
Nick Gasson 82aca1b02e Stub code for handling $display 2008-06-03 18:44:17 +01:00
Nick Gasson 4211e651d0 Stub file for processing statements 2008-06-03 18:26:36 +01:00
Nick Gasson f9e1289463 Tidy up vhdl_element.cc 2008-06-03 17:43:54 +01:00
Nick Gasson a09b4e3b92 Initial process have wait at the end
(do it properly this time rather than a hack :-)
2008-06-03 17:39:24 +01: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
Nick Gasson ab6ae621cb Remove useless comments in output 2008-06-02 20:24:25 +01:00
Nick Gasson 17ae0a6a09 Fix a bug where the same instantiation appeared multiple times 2008-06-02 18:05:39 +01:00
Nick Gasson 041925c123 Component instantiation to replicate Verilog hierarchy 2008-06-02 17:45:58 +01:00
Nick Gasson 9292a087e8 Generate VHDL processes from Verilog processes 2008-06-02 16:17:01 +01: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
Nick Gasson fef0fd82ff Comments 2008-06-02 00:12:47 +01: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
Nick Gasson 5cbd587833 Clean up generated objects 2008-05-31 16:08:57 +01:00
Nick Gasson 7c9d154461 Forgot source files for entity generation 2008-05-31 15:31:48 +01:00
Nick Gasson 8189c4ee43 Generate VHDL entities and architectures for all module scopes 2008-05-31 15:28:25 +01: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
Nick Gasson 05de2f56b4 Dummy code for processes 2008-05-30 01:04:47 +01: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
Nick Gasson e38494a10c Pretty-print VHDL output 2008-05-29 16:24:16 +01: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
Nick Gasson e178baefbd Merge branch 'master' of git://github.com/steveicarus/iverilog into vhdl 2008-05-28 17:23:12 +01:00
Nick Gasson bfa2bfc8ae Makefile and autoconf changes to build VHDL code generator 2008-05-28 17:17:39 +01: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
321 changed files with 35197 additions and 21097 deletions
+37
View File
@@ -0,0 +1,37 @@
/*
* 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 "config.h"
# include "AStatement.h"
AContrib::AContrib(PExpr*lv, PExpr*rv)
: lval_(lv), rval_(rv)
{
}
AContrib::~AContrib()
{
delete lval_;
delete rval_;
}
AProcess::~AProcess()
{
}
+85
View File
@@ -0,0 +1,85 @@
#ifndef __AStatement_H
#define __AStatement_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 <map>
# include "ivl_target.h"
# include "StringHeap.h"
# include "LineInfo.h"
# include "Statement.h"
# include "PExpr.h"
class PExpr;
class NetAnalog;
class NetScope;
class Design;
/*
* A contribution statement is like an assignment: there is an l-value
* expression and an r-value expression. The l-value is a branch probe
* expression.
*/
class AContrib : public Statement {
public:
AContrib(PExpr*lval, PExpr*rval);
~AContrib();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
PExpr*lval_;
PExpr*rval_;
};
/*
* An analog process is not a statement, but contains an analog
* statement. The process is where we attach process characteristics
* such as initial vs. always, attributes....
*/
class AProcess : public LineInfo {
public:
AProcess(ivl_process_type_t t, Statement*st)
: type_(t), statement_(st) { }
~AProcess();
bool elaborate(Design*des, NetScope*scope) const;
ivl_process_type_t type() const { return type_; }
Statement*statement() { return statement_; }
map<perm_string,PExpr*> attributes;
// Dump the analog process
void dump(ostream&out, unsigned ind) const;
private:
ivl_process_type_t type_;
Statement*statement_;
private: // not implemented
AProcess(const AProcess&);
AProcess& operator= (const AProcess&);
};
#endif
+62 -68
View File
@@ -4,23 +4,24 @@ HOW TO REPORT BUGS
Before I can fix an error, I need to understand what the problem
is. Try to explain what is wrong and why you think it is wrong. Please
try to include sample code that demonstrates the problem. Include a
description of what ivl does that is wrong, and what you expect should
happen. And include the command line flags passed to the compiler to make
the error happen. (This is often overlooked, and sometimes important.)
description of what Icarus Verilog does that is wrong, and what you
expect should happen. And include the command line flags passed to the
compiler to make the error happen. (This is often overlooked, and
sometimes important.)
* The Compiler Doesn't Compile
If the Icarus Verilog don't compile, I need to know about the
If Icarus Verilog doesn't compile, I need to know about the
compilation tools you are using. Specifically, I need to know:
- Operating system and processor type,
- Compiler w/ version,
- Library version, and
- Versions of any libraries being linked, and
- anything else you think relevant.
Be aware that I do not have at my disposal a porting lab. I have the
alpha on my desk, and the Linux/Intel box with a logic analyzer and
'scope hanging off it.
workstation on my desk, a Mac laptop, and the Linux/Intel box with a
logic analyzer and 'scope hanging off it.
* The Compiler Crashes
@@ -28,26 +29,26 @@ No compiler should crash, no matter what kind of garbage is fed to
it. If the compiler crashes, you definitely found a bug and I need to
know about it.
Ivl internally checks its state while it works, and if it detects
something wrong that it cannot recover from, it will abort
Icarus Verilog internally checks its state while it works, and if it
detects something wrong that it cannot recover from, it will abort
intentionally. The "assertion failure" message that the program
prints in the process of dying is very important. It tells me where in
the source the bad thing happened. Include that message in the bug
report.
If there are not assertion messages, I need to know that as well.
If there are no assertion messages, I need to know that as well.
I also need a complete test program that demonstrates the crash.
* It Doesn't Like My Perfectly Valid Program(tm)
I need to know what you think is right that ivl gets wrong. Does it
reject your "Perfectly Valid Program(tm)" or does it compile it but
give incorrect results? The latter is the most insidious as it doesn't
scream out to be fixed unless someone is watching closely. However, if
I get a sample program from you, and I can compile it, and I run it
and nuclear junk doesn't fall from the sky, I'm moving on to the next
problem.
I need to know what you think is right that Icarus Verilog gets
wrong. Does it reject your "Perfectly Valid Program(tm)" or does it
compile it but give incorrect results? The latter is the most
insidious as it doesn't scream out to be fixed unless someone is
watching closely. However, if I get a sample program from you, and I
can compile it, and I run it and nuclear junk doesn't fall from the
sky, I'm moving on to the next problem.
So, if your program doesn't compile, tell me so, tell me where the
error occurs, and include a complete Perfectly Valid Test Program(tm).
@@ -57,24 +58,25 @@ know. What's on my disk is more recent then the latest snapshot.
If your program does compile, but generates incorrect output, I need
to know what it says and what you think it should say. From this I can
take your sample program and work on ivl until it gets the proper
results. For this to work, of course, I first need to know what is
wrong with the output. Spell it out, because I've been known to miss
the obvious. Compiler writers often get buried in the details of the
wrong problem.
take your sample program and work on Icarus Verilog until it gets the
proper results. For this to work, of course, I first need to know what
is wrong with the output. Spell it out, because I've been known to
miss the obvious. Compiler writers often get buried in the details of
the wrong problem.
* It Generates Incorrect Target Code (XNF, EDIF/LPM, etc.)
* It Generates Incorrect Target Code
As ivl adds target code generators, there will be cases where errors
in the output netlist format occur. This is a tough nut because I
might not have all the tools to test the target format you are
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.
As Icarus Verilog adds target code generators, there will be cases
where errors in the output netlist format occur. This is a tough nut
because I might not have all the tools to test the target format you
are reporting problems with. However, if you clearly explain what is
right and wrong about the generated output, 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,
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.
wrong or what is expected. If it is not clear to me, I will ask for
clarification.
* The Output is Correct, But Less Than Ideal
@@ -91,13 +93,13 @@ demonstrates the problem. If the error occurs after elaboration,
please include a top level module in the program that is suitable for
the target format. If I have to write the module myself, I might not
write it in a way that tickles the bug. So please, send all the
Verilog source (after preprocessing) that I need to invoke the error.
Verilog source that I need to invoke the error.
Also, include the command line you use to invoke the compiler. For
example:
ivl foo.vl -o foo.cc -tvvm
ivl foo.vl -s starthere
iverilog -o foo.out -tvvp foo.v
iverilog foo.vl -s starthere
If the error occurs with the null target (``-tnull'') then a top level
module may not be needed as long as the ``-s <name>'' switch is
@@ -108,15 +110,19 @@ invoke the error without any Verilog other than what is included?" And
while we are at it, please place a copyright notice in your test
program and include a GPL license statement if you can. Your test
program may find its way into the test suite, and the notices will
make it all nice and legal.
make it all nice and legal. Please look at the existing tests in the
test suite <http://sourceforge.net/ivtest> for examples of good test
programs.
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
The URL <http://www.icarus.com/cgi-bin/ivl-bugs> is the main bug
tracking system. Once you believe you have found a bug, you may browse
the bugs database for existing bugs that may be related to yours. You
might find that your bug has already been fixed in a later release or
snapshot. If that's the case, then you are set.
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
bug tracking system. Once you believe you have found a bug, you may
browse the bugs database for existing bugs that may be related to
yours. You might find that your bug has already been fixed in a later
release or snapshot. If that's the case, then you are set. Also,
consider if you are reporting a bug or really asking for a new
feature, and use the appropriate tracker.
The bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
@@ -125,8 +131,7 @@ broken. You may for example find a related bug that explains your
symptom.
The root page of the bug report database describes how to submit your
completed bug report. You may submit it via the web form, or via
e-mail.
completed bug report.
HOW TO SEND PATCHES
@@ -134,21 +139,26 @@ Bug reports with patches are very welcome, especially if they are
formatted such that I can inspect them, decide that they are obviously
correct, and apply them without worry.
I prefer context diffs as emitted by diff from GNU diffutils. Human
beings can read such things, and they are resilient to changing
originals. A good set of flags to diff are ``diff -cNB''. With such
diffs, I can look at the changes you are offering and probably tell at
a glance that they are plausible. Then I can use patch(1) to apply
them. Or I can apply them by hand.
I prefer patches generated by the git source code tracking system. If
you are editing the source, you really should be using the latest
version from git. Please see the developer documentation for more
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
However, if you send patches, *please* tell me what this patch is
supposed to accomplish, and if appropriate include a test program that
demonstrates the efficacy of the patch. (If I have no idea what the
patch is for, I will ask for clarification before applying it.)
When you make a patch, submit it to the "Patches" tracker at
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
the "Patches" tracker enter the developer workflow, are checked,
applied to the appropriate git branch, and are pushed. Then the
tracker item is closed.
If you send patches, *please* tell me what this patch is supposed to
accomplish, which branch you intended to be patched, and if
appropriate include a test program that demonstrates the efficacy of
the patch. (If I have no idea what the patch is for, I will ask for
clarification before applying it.)
COPYRIGHT ISSUES
Icarus Verilog is Copyright (c) 1998-2003 Stephen Williams except
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
where otherwise noted. Minor patches are covered as derivative works
(or editorial comment or whatever the appropriate legal term is) and
folded into the rest of ivl. However, if a submission can reasonably
@@ -158,19 +168,3 @@ then falls under the "otherwise noted" category.
I must insist that any copyright material submitted for inclusion
include the GPL license notice as shown in the rest of the source.
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
$Log: BUGS.txt,v $
Revision 1.5 2007/03/22 16:08:14 steve
Spelling fixes from Larry
Revision 1.4 2003/02/19 04:36:31 steve
Notes on hte bug database.
Revision 1.3 2003/01/30 16:23:07 steve
Spelling fixes.
Revision 1.2 1999/08/06 04:05:28 steve
Handle scope of parameters.
+15 -31
View File
@@ -1,7 +1,7 @@
#ifndef __HName_H
#define __HName_H
/*
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
* Copyright (c) 2001-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: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
#endif
# include <iostream>
# include <list>
# include "StringHeap.h"
#ifdef __GNUC__
#if __GNUC__ > 2
@@ -57,7 +55,7 @@ class hname_t {
private:
perm_string name_;
// If the number is anything other then INT_MIN, then this is
// If the number is anything other than INT_MIN, then this is
// the numeric part of the name. Otherwise, it is not part of
// the name at all.
int number_;
@@ -70,30 +68,16 @@ extern bool operator == (const hname_t&, const hname_t&);
extern bool operator != (const hname_t&, const hname_t&);
extern ostream& operator<< (ostream&, const hname_t&);
/*
* $Log: HName.h,v $
* Revision 1.7 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.6 2007/05/16 19:12:33 steve
* Fix hname_t use of space for 1 perm_string.
*
* Revision 1.5 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.4 2002/11/02 03:27:51 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/06/14 03:25:51 steve
* Compiler portability.
*
* Revision 1.1 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
*/
inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
{
list<hname_t>::const_iterator cur = ll.begin();
out << *cur;
cur ++;
while (cur != ll.end()) {
out << "." << *cur;
cur ++;
}
return out;
}
#endif
+80 -47
View File
@@ -16,11 +16,25 @@
# 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
# Normally, the "make" will build all the files only by dependencies.
# The MODE, however, can control your rebuild intentions. The proper way
# to use the MODE is on the make command like, this this:
#
# make MODE=XXXX all
#
# The possible MODE= values are:
#
# regular
# Build as normal
#
# full
# Do some extra builds. in particular:
# Build version.h again, even if it already exists.
#
MODE=regular
# This version string is only used in the version message printed
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
@@ -51,21 +65,24 @@ 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@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@
CXXFLAGS = -Wall @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
all: dep version.h ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
for dir in ivlpp ; \
do (cd $$dir ; $(MAKE) $@); done
do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
# 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
@@ -99,20 +116,22 @@ 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 elaborate_analog.o \
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
elab_sig.o emit.o eval.o eval_attrib.o \
elab_sig.o elab_sig_analog.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 \
load_module.o netlist.o netmisc.o net_analog.o net_assign.o \
net_design.o net_event.o net_expr.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_analog.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 \
verinum.o verireal.o target.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o AStatement.o StringHeap.o \
$(FF) $(TT)
Makefile: Makefile.in config.h.in config.status
@@ -174,22 +193,30 @@ 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
# 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.
ifeq ($(MODE),full)
.PHONY: version.h
endif
# "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 test -d $(srcdir)/.git; then \
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
echo "Using git-describe for VERSION_TAG"; \
tmp=`git --git-dir $(srcdir)/.git describe \
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 \
@@ -200,10 +227,18 @@ version.h:
echo '#define VERSION_TAG ""' > $@; \
fi
ifeq (@MING32@,yes)
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
@@ -215,45 +250,43 @@ else
WIN32_INSTALL = $(bindir)/iverilog-vpi
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/xnf-s.conf: $(srcdir)/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf
$(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams $(DESTDIR)$(libdir)/ivl/include/constants.vams
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
$(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl/xnf.conf
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl/include/disciplines.vams
$(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.
@@ -276,22 +309,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 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)
+7 -17
View File
@@ -26,7 +26,7 @@
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScope(n, 0)
: PScope(n)
{
library_flag = false;
default_nettype = NetNet::NONE;
@@ -41,19 +41,9 @@ void Module::add_gate(PGate*gate)
gates_.push_back(gate);
}
void Module::add_task(perm_string name, PTask*task)
{
tasks_[name] = task;
}
void Module::add_function(perm_string name, PFunction *func)
{
funcs_[name] = func;
}
unsigned Module::port_count() const
{
return ports.count();
return ports.size();
}
/*
@@ -61,10 +51,10 @@ unsigned Module::port_count() const
* module. If the port is internally unconnected, return an empty
* array.
*/
const svector<PEIdent*>& Module::get_port(unsigned idx) const
const vector<PEIdent*>& Module::get_port(unsigned idx) const
{
assert(idx < ports.count());
static svector<PEIdent*> zero;
assert(idx < ports.size());
static const vector<PEIdent*> zero;
if (ports[idx])
return ports[idx]->expr;
@@ -75,7 +65,7 @@ const svector<PEIdent*>& Module::get_port(unsigned idx) const
unsigned Module::find_port(const char*name) const
{
assert(name != 0);
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
if (ports[idx] == 0) {
/* It is possible to have undeclared ports. These
are ports that are skipped in the declaration,
@@ -89,7 +79,7 @@ unsigned Module::find_port(const char*name) const
return idx;
}
return ports.count();
return ports.size();
}
+13 -24
View File
@@ -22,7 +22,8 @@
# include <list>
# include <map>
# include "svector.h"
# include <vector>
# include <utility>
# include "StringHeap.h"
# include "HName.h"
# include "named.h"
@@ -58,7 +59,7 @@ class Module : public PScope, public LineInfo {
public:
struct port_t {
perm_string name;
svector<PEIdent*> expr;
vector<PEIdent*> expr;
};
public:
@@ -75,19 +76,6 @@ class Module : public PScope, public LineInfo {
NetNet::Type default_nettype;
/* 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;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
/* specparams are simpler then other params, in that they have
no type information. They are merely constant
expressions. */
@@ -97,7 +85,8 @@ class Module : public PScope, public LineInfo {
new parameters within the module, but may be used to set
values within this module (when instantiated) or in other
instantiated modules. */
map<pform_name_t,PExpr*>defparms;
typedef pair<pform_name_t,PExpr*> named_expr_t;
list<named_expr_t>defparms;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
@@ -109,7 +98,7 @@ class Module : public PScope, public LineInfo {
/* This is an array of port descriptors, which is in turn a
named array of PEident pointers. */
svector<port_t*> ports;
vector<port_t*> ports;
map<perm_string,PExpr*> attributes;
@@ -117,9 +106,13 @@ class Module : public PScope, public LineInfo {
set by the `timescale directive. */
int time_unit, time_precision;
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
/* 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. */
@@ -131,11 +124,9 @@ class Module : public PScope, public LineInfo {
perm_string mod_name() const { return pscope_name(); }
void add_gate(PGate*gate);
void add_task(perm_string name, PTask*def);
void add_function(perm_string name, PFunction*def);
unsigned port_count() const;
const svector<PEIdent*>& get_port(unsigned idx) const;
const vector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) const;
PGate* get_gate(perm_string name);
@@ -146,14 +137,12 @@ class Module : public PScope, public LineInfo {
bool elaborate(Design*, NetScope*scope) const;
typedef map<perm_string,NetExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
bool elaborate_sig(Design*, NetScope*scope) const;
private:
list<PGate*> gates_;
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);
+5 -5
View File
@@ -101,7 +101,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
return dex;
}
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
{
if (dynamic_cast<NetESignal*> (expr))
return expr;
@@ -109,7 +109,7 @@ static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
if (dynamic_cast<NetEConst*> (expr))
return expr;
NetNet*sig = expr->synthesize(des);
NetNet*sig = expr->synthesize(des, scope);
if (sig == 0) {
cerr << expr->get_fileline() << ": error: Expression " << *expr
<< " is not suitable for delay expression." << endl;
@@ -132,17 +132,17 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, rise_time);
rise_time = make_delay_nets(des, scope, rise_time);
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, fall_time);
fall_time = make_delay_nets(des, scope, fall_time);
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, decay_time);
decay_time = make_delay_nets(des, scope, decay_time);
} else {
if (rise_time < fall_time)
+80 -61
View File
@@ -1,5 +1,5 @@
/*
* 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
@@ -21,28 +21,31 @@
# include <iostream>
# include "compiler.h"
# include "PExpr.h"
# include "Module.h"
# include "netmisc.h"
# include <typeinfo>
PExpr::PExpr()
{
expr_type_ = IVL_VT_NO_TYPE;
}
PExpr::~PExpr()
{
}
bool PExpr::has_aa_term(Design*, NetScope*) const
{
return false;
}
bool PExpr::is_the_same(const PExpr*that) const
{
return typeid(this) == typeid(that);
}
bool PExpr::is_constant(Module*) const
{
return false;
}
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
{
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
@@ -67,9 +70,10 @@ PEBinary::~PEBinary()
{
}
bool PEBinary::is_constant(Module*mod) const
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
{
return left_->is_constant(mod) && right_->is_constant(mod);
assert(left_ && right_);
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
@@ -81,6 +85,16 @@ PEBComp::~PEBComp()
{
}
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
assert(op == 'a' || op == 'o');
}
PEBLogic::~PEBLogic()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
@@ -90,7 +104,7 @@ PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
: path_(n), parms_(parms)
{
}
@@ -103,7 +117,7 @@ static pform_name_t pn_from_ps(perm_string n)
return tmp;
}
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(parms)
{
}
@@ -113,29 +127,52 @@ PECallFunction::PECallFunction(perm_string n)
{
}
// NOTE: Anachronism. Try to work all use of svector out.
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(vector_from_svector(parms))
{
}
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(vector_from_svector(parms))
{
}
PECallFunction::~PECallFunction()
{
}
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
flag = parms_[idx]->has_aa_term(des, scope) || flag;
}
return flag;
}
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
: parms_(p), repeat_(r)
{
}
bool PEConcat::is_constant(Module *mod) const
{
bool constant = repeat_? repeat_->is_constant(mod) : true;
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
constant = constant && parms_[i]->is_constant(mod);
}
return constant;
}
PEConcat::~PEConcat()
{
delete repeat_;
}
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
flag = parms_[idx]->has_aa_term(des, scope) || flag;
}
if (repeat_)
flag = repeat_->has_aa_term(des, scope) || flag;
return flag;
}
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
: type_(t), expr_(e)
{
@@ -150,6 +187,12 @@ PEEvent::edge_t PEEvent::type() const
return type_;
}
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
{
assert(expr_);
return expr_->has_aa_term(des, scope);
}
PExpr* PEEvent::expr() const
{
return expr_;
@@ -170,11 +213,6 @@ const verireal& PEFNumber::value() const
return *value_;
}
bool PEFNumber::is_constant(Module*) const
{
return true;
}
PEIdent::PEIdent(const pform_name_t&that)
: path_(that)
{
@@ -189,30 +227,20 @@ PEIdent::~PEIdent()
{
}
/*
* An identifier can be in a constant expression if (and only if) it is
* a parameter.
*
* NOTE: This test does not work if the name is hierarchical!
*/
bool PEIdent::is_constant(Module*mod) const
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
{
if (mod == 0) return false;
NetNet* net = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
/* */
perm_string tmp = path_.back().name;
const NetExpr*ex1, *ex2;
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->parameters.find(tmp);
if (cur != mod->parameters.end()) return true;
}
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->localparams.find(tmp);
if (cur != mod->localparams.end()) return true;
}
return false;
if (scope)
return scope->is_auto();
else
return false;
}
PENumber::PENumber(verinum*vp)
@@ -240,11 +268,6 @@ bool PENumber::is_the_same(const PExpr*that) const
return *value_ == *obj->value_;
}
bool PENumber::is_constant(Module*) const
{
return true;
}
PEString::PEString(char*s)
: text_(s)
{
@@ -260,11 +283,6 @@ string PEString::value() const
return text_;
}
bool PEString::is_constant(Module*) const
{
return true;
}
PETernary::PETernary(PExpr*e, PExpr*t, PExpr*f)
: expr_(e), tru_(t), fal_(f)
{
@@ -274,11 +292,12 @@ PETernary::~PETernary()
{
}
bool PETernary::is_constant(Module*m) const
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
{
return expr_->is_constant(m)
&& tru_->is_constant(m)
&& fal_->is_constant(m);
assert(expr_ && tru_ && fal_);
return expr_->has_aa_term(des, scope)
|| tru_->has_aa_term(des, scope)
|| fal_->has_aa_term(des, scope);
}
PEUnary::PEUnary(char op, PExpr*ex)
@@ -290,8 +309,8 @@ PEUnary::~PEUnary()
{
}
bool PEUnary::is_constant(Module*m) const
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
{
return expr_->is_constant(m);
assert(expr_);
return expr_->has_aa_term(des, scope);
}
+137 -235
View File
@@ -36,9 +36,6 @@ class NetScope;
* The PExpr class hierarchy supports the description of
* expressions. The parser can generate expression objects from the
* source, possibly reducing things that it knows how to reduce.
*
* The elaborate_net method is used by structural elaboration to build
* up a netlist interpretation of the expression.
*/
class PExpr : public LineInfo {
@@ -49,11 +46,15 @@ class PExpr : public LineInfo {
virtual void dump(ostream&) const;
// This method tests whether the expression contains any
// references to automatically allocated variables.
virtual bool has_aa_term(Design*des, NetScope*scope) const;
// This method tests the width that the expression wants to
// be. It is used by elaboration of assignments to figure out
// the width of the expression.
//
// The "min" is the width of the local context, so it the
// The "min" is the width of the local context, so is the
// minimum width that this function should return. Initially
// this is the same as the lval width.
//
@@ -66,13 +67,22 @@ class PExpr : public LineInfo {
// the subexpression should not make l-value related
// optimizations.
//
// The unsigned_flag is set to true if the expression is
// The expr_type is an output argument that gives the
// calculated type for the expression.
//
// The unsized_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
// After the test_width method is complete, these methods
// return valid results.
ivl_variable_type_t expr_type() const { return expr_type_; }
unsigned expr_width() const { return expr_width_; }
// During the elaborate_sig phase, we may need to scan
// expressions to find implicit net declarations.
@@ -98,17 +108,6 @@ class PExpr : public LineInfo {
// evaluation of parameters.
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
// This method elaborate the expression as gates, for use in a
// continuous assign or other wholly structural context.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0 =Link::STRONG,
Link::strength_t drive1 =Link::STRONG)
const;
// 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) const;
@@ -138,11 +137,12 @@ class PExpr : public LineInfo {
// expressions that must be structurally "identical".
virtual bool is_the_same(const PExpr*that) const;
// Return true if this expression is a valid constant
// expression. the Module pointer is needed to find parameter
// identifiers and any other module specific interpretations
// of expressions.
virtual bool is_constant(Module*) const;
protected:
// The derived class test_width methods should fill these in.
ivl_variable_type_t expr_type_;
unsigned expr_width_;
static void suppress_binary_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
private: // not implemented
PExpr(const PExpr&);
@@ -160,24 +160,22 @@ class PEConcat : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
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,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual bool is_constant(Module*) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
@@ -208,6 +206,8 @@ class PEEvent : public PExpr {
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
private:
edge_t type_;
PExpr *expr_;
@@ -229,21 +229,14 @@ class PEFNumber : public PExpr {
any rounding that is needed to get the value. */
virtual verinum* eval_const(Design*des, NetScope*sc) const;
/* A PEFNumber is a constant, so this returns true. */
virtual bool is_constant(Module*) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
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 NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual void dump(ostream&) const;
private:
@@ -262,9 +255,13 @@ class PEIdent : public PExpr {
void append_name(perm_string);
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@@ -278,15 +275,6 @@ class PEIdent : public PExpr {
NetScope*scope,
bool is_force) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@@ -295,7 +283,6 @@ class PEIdent : public PExpr {
// only applies to Ident expressions.
NetNet* elaborate_port(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(Design*des, NetScope*sc) const;
const pform_name_t& path() const { return path_; }
@@ -306,21 +293,40 @@ 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:
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
index_component_t::ctype_t) const;
private:
NetExpr*elaborate_expr_param(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_param_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb,
int expr_wid) 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,
@@ -348,38 +354,6 @@ class PEIdent : public PExpr {
NetESignal*net,
NetScope*found) const;
public:
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_net_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_net_idx_up_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sig,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
@@ -387,9 +361,7 @@ class PEIdent : public PExpr {
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const;
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
long&midx, long&lidx) const;
};
class PENumber : public PExpr {
@@ -403,15 +375,9 @@ class PENumber : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@@ -422,7 +388,6 @@ class PENumber : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_the_same(const PExpr*that) const;
virtual bool is_constant(Module*) const;
private:
verinum*const value_;
@@ -446,22 +411,14 @@ class PEString : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* eval_const(Design*, NetScope*) const;
virtual bool is_constant(Module*) const;
private:
char*text_;
};
@@ -474,47 +431,22 @@ class PEUnary : public PExpr {
virtual void dump(ostream&out) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
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;
virtual bool is_constant(Module*) const;
private:
NetNet* elab_net_uminus_const_logic_(Design*des, NetScope*scope,
NetEConst*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elab_net_uminus_const_real_(Design*des, NetScope*scope,
NetECReal*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elab_net_unary_real_(Design*des, NetScope*scope,
NetExpr*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetExpr* elaborate_expr_bits_(NetExpr*operand, int expr_wid) const;
private:
char op_;
@@ -527,23 +459,17 @@ class PEBinary : public PExpr {
explicit PEBinary(char op, PExpr*l, PExpr*r);
~PEBinary();
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@@ -557,54 +483,13 @@ class PEBinary : public PExpr {
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 suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_lshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_rshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
unsigned lwidth,
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,
const NetExpr* fall,
const NetExpr* decay) const;
};
/*
@@ -619,10 +504,31 @@ class PEBComp : public PEBinary {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&flag) const;
ivl_variable_type_t&expr_type,
bool&flag);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
};
/*
* This derived class is for handling logical expressions: && and ||.
*/
class PEBLogic : public PEBinary {
public:
explicit PEBLogic(char op, PExpr*l, PExpr*r);
~PEBLogic();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
};
class PEBShift : public PEBinary {
@@ -632,7 +538,11 @@ class PEBShift : public PEBinary {
~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const;
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
};
/*
@@ -645,23 +555,18 @@ class PETernary : public PExpr {
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
~PETernary();
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
@@ -679,45 +584,42 @@ class PETernary : public PExpr {
*/
class PECallFunction : public PExpr {
public:
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
// Call of system function (name is not hierarchical)
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
// svector versions. Should be removed!
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
~PECallFunction();
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
private:
pform_name_t path_;
svector<PExpr *> parms_;
vector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
ivl_variable_type_t&expr_type,
bool&unsized_flag);
};
#endif
+2 -1
View File
@@ -21,9 +21,10 @@
#include "PTask.h"
PFunction::PFunction(perm_string name, PScope*parent)
PFunction::PFunction(perm_string name, PScope*parent, bool is_auto__)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto__;
return_type_.type = PTF_NONE;
}
+14 -7
View File
@@ -1,7 +1,7 @@
#ifndef __PGate_H
#define __PGate_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,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: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
#endif
# include "svector.h"
# include "StringHeap.h"
@@ -83,7 +80,7 @@ class PGate : public LineInfo {
bool as_net_flag =false) const;
unsigned pin_count() const { return pins_? pins_->count() : 0; }
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
strength_t strength0() const;
strength_t strength1() const;
@@ -170,8 +167,16 @@ class PGBuiltin : public PGate {
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private:
Type type_;
unsigned calculate_array_count_(Design*, NetScope*,
long&high, long&low) const;
unsigned calculate_output_count_(void) const;
NetNode* create_gate_for_output_(Design*, NetScope*,
perm_string gate_name,
unsigned instance_width) const;
Type type_;
PExpr*msb_;
PExpr*lsb_;
};
@@ -232,15 +237,17 @@ class PGModule : public PGate {
PExpr*msb_;
PExpr*lsb_;
friend class delayed_elaborate_scope_mod_instances;
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
void elaborate_scope_mod_instances_(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,
NetNet::PortType dir) const;
NetNet::PortType dir, bool as_signed) const;
};
#endif
+1 -14
View File
@@ -27,27 +27,14 @@ PGenerate::PGenerate(unsigned id)
: id_number(id)
{
parent = 0;
lexical_scope = 0;
}
PGenerate::~PGenerate()
{
}
PWire* PGenerate::get_wire(perm_string name) const
{
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
return (*obj).second;
}
void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::add_behavior(PProcess*proc)
{
behaviors.push_back(proc);
}
+17 -13
View File
@@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006 Stephen Williams ([email protected])
* Copyright (c) 2006-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,13 +18,11 @@
* 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: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include "HName.h"
# include "PScope.h"
# include <list>
# include <map>
# include "pform_types.h"
@@ -32,7 +30,9 @@
class Design;
class NetScope;
class PExpr;
class PFunction;
class PProcess;
class PTask;
class PGate;
class PWire;
@@ -49,10 +49,10 @@ class PWire;
* The parent points to the GS_CASE that contains this item.
* the loop_test is compared with the parent->loop_test expression.
*/
class PGenerate : public LineInfo {
class PGenerate : public LineInfo, public LexicalScope {
public:
PGenerate(unsigned id_number);
explicit PGenerate(unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
@@ -60,8 +60,12 @@ class PGenerate : public LineInfo {
const unsigned id_number;
perm_string scope_name;
// This is used during parsing to stack lexical scopes within
// this generate scheme.
PScope*lexical_scope;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
GS_CASE, GS_CASE_ITEM};
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
scheme_t scheme_type;
// generate loops have an index variable and three
@@ -71,16 +75,15 @@ class PGenerate : public LineInfo {
PExpr*loop_test;
PExpr*loop_step;
map<perm_string,PWire*>wires;
PWire* get_wire(perm_string name) const;
list<PGate*> gates;
void add_gate(PGate*);
list<PProcess*> behaviors;
void add_behavior(PProcess*behave);
// Tasks instantiated within this scheme.
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
list<PGenerate*> generates;
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
PGenerate*parent;
// This method is called by the elaboration of a module to
@@ -99,6 +102,7 @@ class PGenerate : public LineInfo {
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);
bool generate_scope_nblock_(Design*des, NetScope*container);
// Elaborate_scope within a generated scope.
void elaborate_subscope_(Design*des, NetScope*scope);
+8 -3
View File
@@ -19,8 +19,13 @@
# include "PScope.h"
PScope::PScope(perm_string n, PScope*p)
: name_(n), parent_(p)
PScope::PScope(perm_string n, PScope*parent)
: name_(n), parent_(parent)
{
}
PScope::PScope(perm_string n)
: name_(n), parent_(0)
{
}
@@ -28,7 +33,7 @@ PScope::~PScope()
{
}
PWire* PScope::wires_find(perm_string name)
PWire* LexicalScope::wires_find(perm_string name)
{
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
if (cur == wires.end())
+71 -14
View File
@@ -19,11 +19,15 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
# include <map>
class PEvent;
class PExpr;
class AProcess;
class PProcess;
class PWire;
@@ -35,10 +39,74 @@ class NetScope;
* 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
* NOTE: This is not the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration.
*/
class PScope {
class LexicalScope {
public:
explicit LexicalScope() { }
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
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 scope has parameters that are evaluated when the scope
is elaborated. During parsing, I put the parameters into
this map. */
struct param_expr_t : public LineInfo {
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 constraints, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
// Named events in the scope.
map<perm_string,PEvent*>events;
// Nets and variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
protected:
void dump_parameters_(ostream&out, unsigned indent) const;
void dump_localparams_(ostream&out, unsigned indent) const;
void dump_events_(ostream&out, unsigned indent) const;
void dump_wires_(ostream&out, unsigned indent) const;
private:
};
class PScope : public LexicalScope {
public:
// When created, a scope has a name and a parent. The name is
@@ -50,24 +118,13 @@ class PScope {
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, PScope*parent);
PScope(perm_string name);
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;
+2 -29
View File
@@ -21,9 +21,10 @@
# include "PTask.h"
PTask::PTask(perm_string name, PScope*parent)
PTask::PTask(perm_string name, PScope*parent, bool is_auto__)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto__;
}
PTask::~PTask()
@@ -41,31 +42,3 @@ void PTask::set_statement(Statement*s)
assert(statement_ == 0);
statement_ = s;
}
/*
* $Log: PTask.cc,v $
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 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.5 2001/04/19 03:04:47 steve
* Spurious assert of empty statemnt.
*
* 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/07/24 02:11:19 steve
* Elaborate task input ports.
*
* Revision 1.1 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
*/
+8 -2
View File
@@ -51,7 +51,7 @@ struct PTaskFuncArg {
class PTask : public PScope, public LineInfo {
public:
explicit PTask(perm_string name, PScope*parent);
explicit PTask(perm_string name, PScope*parent, bool is_auto);
~PTask();
void set_ports(svector<PWire *>*p);
@@ -69,11 +69,14 @@ class PTask : public PScope, public LineInfo {
// Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const;
bool is_auto() const { return is_auto_; };
void dump(ostream&, unsigned) const;
private:
svector<PWire*>*ports_;
Statement*statement_;
bool is_auto_;
private: // Not implemented
PTask(const PTask&);
@@ -90,7 +93,7 @@ class PTask : public PScope, public LineInfo {
class PFunction : public PScope, public LineInfo {
public:
explicit PFunction(perm_string name, PScope*parent);
explicit PFunction(perm_string name, PScope*parent, bool is_auto);
~PFunction();
void set_ports(svector<PWire *>*p);
@@ -105,12 +108,15 @@ class PFunction : public PScope, public LineInfo {
/* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const;
bool is_auto() const { return is_auto_; };
void dump(ostream&, unsigned) const;
private:
PTaskFuncArg return_type_;
svector<PWire *> *ports_;
Statement *statement_;
bool is_auto_;
};
#endif
+11 -14
View File
@@ -30,7 +30,7 @@ PWire::PWire(perm_string n,
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;
@@ -135,19 +135,6 @@ 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) {
@@ -211,3 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
}
}
void PWire::set_discipline(ivl_discipline_t d)
{
assert(discipline_ == 0);
discipline_ = d;
}
ivl_discipline_t PWire::get_discipline(void) const
{
return discipline_;
}
+5 -4
View File
@@ -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: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
#endif
# include "netlist.h"
# include "LineInfo.h"
@@ -78,10 +75,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(ivl_discipline_t);
ivl_discipline_t get_discipline(void) const;
map<perm_string,PExpr*> attributes;
// Write myself to the specified stream.
@@ -112,6 +111,8 @@ class PWire : public LineInfo {
PExpr*lidx_;
PExpr*ridx_;
ivl_discipline_t discipline_;
private: // not implemented
PWire(const PWire&);
PWire& operator= (const PWire&);
+1 -4
View File
@@ -12,10 +12,7 @@ home page at <http://www.icarus.com/eda/verilog>.
Icarus Verilog is not aimed at being a simulator in the traditional
sense, but a compiler that generates code employed by back-end
tools. These back-end tools currently include a simulator engine
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF FPGA
netlist generator. In the future, backends are expected for EDIF/LPM,
structural Verilog, VHDL, etc.
tools.
For instructions on how to run Icarus Verilog,
see the ``iverilog'' man page.
+37 -56
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-1999 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: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -29,20 +26,20 @@ Statement::~Statement()
{
}
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
: event_(0), lval_(lval), rval_(ex)
PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant)
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant)
{
delay_ = 0;
}
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
: event_(0), lval_(lval), rval_(ex)
PAssign_::PAssign_(PExpr*lval__, PExpr*de, PExpr*ex)
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(false)
{
delay_ = de;
}
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
: event_(ev), lval_(lval), rval_(ex)
PAssign_::PAssign_(PExpr*lval__, PExpr*cnt, PEventStatement*ev, PExpr*ex)
: event_(ev), count_(cnt), lval_(lval__), rval_(ex), is_constant_(false)
{
delay_ = 0;
}
@@ -53,18 +50,23 @@ PAssign_::~PAssign_()
delete rval_;
}
PAssign::PAssign(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
PAssign::PAssign(PExpr*lval__, PExpr*ex)
: PAssign_(lval__, ex, false)
{
}
PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
: PAssign_(lval, d, ex)
PAssign::PAssign(PExpr*lval__, PExpr*d, PExpr*ex)
: PAssign_(lval__, d, ex)
{
}
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
: PAssign_(lval, d, ex)
PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval__, cnt, d, ex)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
: PAssign_(lval__, ex, is_constant)
{
}
@@ -72,13 +74,18 @@ PAssign::~PAssign()
{
}
PAssignNB::PAssignNB(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
PAssignNB::PAssignNB(PExpr*lval__, PExpr*ex)
: PAssign_(lval__, ex, false)
{
}
PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex)
: PAssign_(lval, d, ex)
PAssignNB::PAssignNB(PExpr*lval__, PExpr*d, PExpr*ex)
: PAssign_(lval__, d, ex)
{
}
PAssignNB::PAssignNB(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval__, cnt, d, ex)
{
}
@@ -92,7 +99,7 @@ PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
}
PBlock::PBlock(BL_TYPE t)
: PScope(perm_string(),0), bl_type_(t)
: PScope(perm_string()), bl_type_(t)
{
}
@@ -221,6 +228,15 @@ void PEventStatement::set_statement(Statement*st)
statement_ = st;
}
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
{
bool flag = false;
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
flag = expr_[idx]->has_aa_term(des, scope) || flag;
}
return flag;
}
PForce::PForce(PExpr*l, PExpr*r)
: lval_(l), expr_(r)
{
@@ -298,38 +314,3 @@ PWhile::~PWhile()
delete cond_;
delete statement_;
}
/*
* $Log: Statement.cc,v $
* Revision 1.30 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.29 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.28 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.27 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.26 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.25 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.24 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.23 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)
*/
+26 -102
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,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: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
#endif
# include <string>
# include "ivl_target.h"
# include "svector.h"
# include "StringHeap.h"
# include "PDelays.h"
@@ -49,16 +47,14 @@ class NetScope;
class PProcess : public LineInfo {
public:
enum Type { PR_INITIAL, PR_ALWAYS };
PProcess(Type t, Statement*st)
PProcess(ivl_process_type_t t, Statement*st)
: type_(t), statement_(st) { }
virtual ~PProcess();
bool elaborate(Design*des, NetScope*scope) const;
Type type() const { return type_; }
ivl_process_type_t type() const { return type_; }
Statement*statement() { return statement_; }
map<perm_string,PExpr*> attributes;
@@ -66,7 +62,7 @@ class PProcess : public LineInfo {
virtual void dump(ostream&out, unsigned ind) const;
private:
Type type_;
ivl_process_type_t type_;
Statement*statement_;
};
@@ -85,6 +81,8 @@ class Statement : public LineInfo {
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;
map<perm_string,PExpr*> attributes;
};
/*
@@ -94,23 +92,27 @@ class Statement : public LineInfo {
*/
class PAssign_ : public Statement {
public:
explicit PAssign_(PExpr*lval, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant);
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
virtual ~PAssign_() =0;
const PExpr* lval() const { return lval_; }
const PExpr* rval() const { return rval_; }
PExpr* rval() const { return rval_; }
protected:
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
ivl_variable_type_t type) const;
PExpr* delay_;
PEventStatement*event_;
PExpr* count_;
private:
PExpr* lval_;
PExpr* rval_;
bool is_constant_;
};
class PAssign : public PAssign_ {
@@ -118,7 +120,8 @@ class PAssign : public PAssign_ {
public:
explicit PAssign(PExpr*lval, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
~PAssign();
virtual void dump(ostream&out, unsigned ind) const;
@@ -132,6 +135,7 @@ class PAssignNB : public PAssign_ {
public:
explicit PAssignNB(PExpr*lval, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
~PAssignNB();
virtual void dump(ostream&out, unsigned ind) const;
@@ -336,10 +340,15 @@ class PEventStatement : public Statement {
void set_statement(Statement*st);
virtual void dump(ostream&out, unsigned ind) const;
// Call this with a NULL statement only. It is used to print
// the event expression for inter-assignment event controls.
virtual void dump_inline(ostream&out) 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;
bool has_aa_term(Design*des, NetScope*scope);
// This method is used to elaborate, but attach a previously
// elaborated statement to the event.
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
@@ -351,6 +360,8 @@ class PEventStatement : public Statement {
Statement*statement_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);
class PForce : public Statement {
public:
@@ -417,6 +428,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:
@@ -462,6 +474,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:
@@ -469,93 +482,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
+2 -31
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002 Stephen Williams ([email protected])
* Copyright (c) 2002-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: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
#endif
# include "config.h"
@@ -87,34 +84,8 @@ bool NetProc::is_asynchronous()
bool NetProcTop::is_asynchronous()
{
if (type_ == NetProcTop::KINITIAL)
if (type_ == IVL_PR_INITIAL)
return false;
return statement_->is_asynchronous();
}
/*
* $Log: async.cc,v $
* Revision 1.7 2004/01/18 23:26:54 steve
* The is_combinational function really need not recurse.
*
* Revision 1.6 2003/12/20 00:33:39 steve
* More thorough check that NetEvWait is asynchronous.
*
* Revision 1.5 2003/09/04 20:28:05 steve
* Support time0 resolution of combinational threads.
*
* Revision 1.4 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/07/04 00:24:16 steve
* initial statements are not asynchronous.
*
* Revision 1.1 2002/06/30 02:21:31 steve
* Add structure for asynchronous logic synthesis.
*
*/
+2 -2
View File
@@ -9,11 +9,11 @@
echo "Autoconf in root..."
autoconf -f
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
for dir in vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf -f --include=.. )
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
+5 -8
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@
@@ -63,7 +60,7 @@ dep:
O = cadpli.o
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@MING32@,yes)
ifeq (@MINGW32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
@@ -79,13 +76,13 @@ distclean: clean
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
$(vpidir)/cadpli.vpl: ./cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl $(vpidir)/cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl $(DESTDIR)$(vpidir)/cadpli.vpl
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(vpidir)
$(srcdir)/../mkinstalldirs $(DESTDIR)$(vpidir)
uninstall: $(UNINSTALL32)
rm -f $(vpidir)/cadpli.vpl
rm -f $(DESTDIR)$(vpidir)/cadpli.vpl
uninstall32:
+11 -11
View File
@@ -35,16 +35,16 @@ typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
static inline ivl_dll_t ivl_dlopen(const char *name)
static __inline__ ivl_dll_t ivl_dlopen(const char *name)
{ return (void *)LoadLibrary(name); }
static inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
static __inline__ void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
static inline void ivl_dlclose(ivl_dll_t dll)
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
static inline const char *dlerror(void)
static __inline__ const char *dlerror(void)
{
static char msg[256];
unsigned long err = GetLastError();
@@ -61,10 +61,10 @@ static inline const char *dlerror(void)
}
#elif defined(HAVE_DLFCN_H)
static inline ivl_dll_t ivl_dlopen(const char*name)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
{ return dlopen(name,RTLD_LAZY); }
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym = dlsym(dll, nm);
/* Not found? try without the leading _ */
@@ -73,24 +73,24 @@ static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
return sym;
}
static inline void ivl_dlclose(ivl_dll_t dll)
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
static inline ivl_dll_t ivl_dlopen(const char*name)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
static inline void ivl_dlclose(ivl_dll_t dll)
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
static inline const char*dlerror(void)
static __inline__ const char*dlerror(void)
{ return strerror( errno ); }
#endif
+22 -4
View File
@@ -86,6 +86,8 @@ extern bool debug_scopes;
extern bool debug_eval_tree;
extern bool debug_elaborate;
extern bool debug_synth2;
extern bool debug_optimizer;
extern bool debug_automatic;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
@@ -100,26 +102,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;
+1 -1
View File
@@ -93,4 +93,4 @@
* junk, and support gcc 3.0. (Stephan Boettcher)
*
*/
#endif // __config_H
#endif /* __config_H */
+4 -1
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 ""
@@ -119,6 +122,6 @@ AX_C_UNDERSCORES_TRAILING
AX_CPP_IDENT
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp tgt-vhdl libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
+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
+50 -33
View File
@@ -1,5 +1,5 @@
/*
* 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
* and/or modify it in source code form under the terms of the GNU
@@ -23,6 +23,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
@@ -738,7 +739,8 @@ v }
}
}
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
#if 0
static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
{
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
@@ -748,7 +750,7 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
connect(obj->pin_Data(type==NetLogic::PMOS? 0 : 1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
@@ -779,10 +781,11 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
delete obj;
}
#endif
/*
* This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a bufif with the sel
* Vz. In this case, replace the device with a mos with the sel
* input used to enable the output.
*/
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
@@ -792,42 +795,57 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
if (obj->sel_width() != 1)
return;
#if 0
/*
* This is slower than the actual MUXZ so we are skipping this for now.
* If we had a half mux functor this could be faster and more compact
* so I'm leaving the code for future reference.
*/
/* If the first input is all constant Vz, then replace the
NetMux with an array of BUFIF1 devices, with the enable
NetMux with an array of NMOS devices, with the enable
connected to the select input. */
bool flag = true;
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF1);
if (obj->pin_Data(0).nexus()->drivers_constant() &&
obj->pin_Data(0).nexus()->driven_value() == verinum::Vz) {
replace_with_mos(des, obj, NetLogic::NMOS);
count += 1;
return;
}
/* If instead the second input is all constant Vz, replace the
NetMux with an array of BUFIF0 devices. */
flag = true;
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF0);
NetMux with an array of PMOS devices. */
if (obj->pin_Data(1).nexus()->drivers_constant() &&
obj->pin_Data(1).nexus()->driven_value() == verinum::Vz) {
replace_with_mos(des, obj, NetLogic::PMOS);
count += 1;
return;
}
#endif
/* If the select input is constant, then replace with a BUFZ */
bool 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;
}
}
/*
@@ -870,7 +888,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetObj*cur;
NetPins*cur;
unsigned pin;
clnk->cur_link(cur, pin);
@@ -896,7 +914,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetObj*cur;
NetPins*cur;
unsigned pin;
clnk->cur_link(cur, pin);
@@ -947,4 +965,3 @@ void cprop(Design*des)
cprop_dc_functor dc;
des->functor(&dc);
}
+241 -26
View File
@@ -27,6 +27,7 @@
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
# include "discipline.h"
# include "ivl_assert.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
@@ -88,6 +89,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()) {
@@ -112,9 +141,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 (is_condit()) {
if (has_condit()) o << " if";
else o << " ifnone";
}
o << " src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
@@ -158,6 +188,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " inout";
break;
}
if (ivl_discipline_t dis = get_discipline())
o << " discipline=" << dis->name();
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());
@@ -207,11 +241,14 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
/* This is the generic dumping of all the signals connected to each
pin of the object. The "this" object is not printed, only the
signals connected to this. */
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) const
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
<< "<" << pin(idx).get_inst() << ">";
o << setw(ind) << "" << idx;
if (pin_names && pin_names[idx])
o << " " << pin_names[idx];
else
o << " pin" << idx;
switch (pin(idx).get_dir()) {
case Link::PASSIVE:
@@ -246,12 +283,28 @@ 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()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
dump_node_pins(o, ind+4);
static const char* pin_names[] = {
"Cout ",
"DataA ",
"DataB ",
"Result"
};
dump_node_pins(o, ind+4, pin_names);
dump_obj_attr(o, ind+4);
}
@@ -264,6 +317,22 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetCastInt::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
name() << " width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCastReal::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to real (NetCastReal): " <<
name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
@@ -274,7 +343,9 @@ void NetCLShift::dump_node(ostream&o, unsigned ind) const
void NetCompare::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " << name() << endl;
o << setw(ind) << "" << "LPM_COMPARE (NetCompare "
<< (get_signed()? "signed" : "unsigned") << "): "
<< name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -483,9 +554,6 @@ 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();
@@ -511,8 +579,14 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetSignExtend: "
<< name() << " output width=" << width_ << endl;
o << setw(ind) << "" << "NetSignExtend: " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
o << " #(.,.,.)";
o << " output width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -601,6 +675,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() << "): ";
@@ -614,11 +702,11 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
void NetProcTop::dump(ostream&o, unsigned ind) const
{
switch (type_) {
case NetProcTop::KINITIAL:
case IVL_PR_INITIAL:
o << "initial /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case NetProcTop::KALWAYS:
case IVL_PR_ALWAYS:
o << "always /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
@@ -632,6 +720,28 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetAnalogTop::dump(ostream&o, unsigned ind) const
{
switch (type_) {
case IVL_PR_INITIAL:
o << "analog initial /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS:
o << "analog /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
}
statement_->dump(o, ind+2);
}
void NetAlloc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
}
void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
@@ -683,6 +793,11 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
if (count_)
o << "repeat(" << *count_ << ") ";
if (event_) {
o << *event_;
}
o << *rval() << ";" << endl;
@@ -770,6 +885,15 @@ void NetCondit::dump(ostream&o, unsigned ind) const
}
}
void NetContribution::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "";
lval_->dump(o);
o << " <+ ";
rval_->dump(o);
o << ";" << endl;
}
void NetDeassign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "deassign ";
@@ -827,6 +951,25 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
o << setw(ind+2) << "" << "/* noop */ ;" << endl;
}
ostream& operator << (ostream&out, const NetEvWait&obj)
{
obj.dump_inline(out);
return out;
}
void NetEvWait::dump_inline(ostream&o) const
{
o << "@(";
if (nevents() > 0)
o << event(0)->name();
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
o << " or " << event(idx)->name();
o << ") ";
}
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force ";
@@ -840,6 +983,11 @@ void NetForever::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetFree::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
}
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
@@ -933,6 +1081,7 @@ void NetScope::dump(ostream&o) const
o << " generate block";
break;
}
if (is_auto()) o << " (automatic)";
o << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
@@ -949,6 +1098,8 @@ void NetScope::dump(ostream&o) const
; pp != parameters.end() ; pp ++) {
o << " parameter ";
o << pp->second.type << " ";
if ((*pp).second.signed_flag)
o << "signed ";
@@ -956,8 +1107,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()
@@ -969,7 +1149,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */
{
map<pform_name_t,NetExpr*>::const_iterator pp;
list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " <<
@@ -977,6 +1157,15 @@ void NetScope::dump(ostream&o) const
}
}
{
list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
for (pp = defparams_later.begin()
; pp != defparams_later.end() ; pp ++ ) {
o << " defparam(later) " << pp->first << " = " <<
*(pp->second) << ";" << endl;
}
}
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
@@ -985,12 +1174,9 @@ void NetScope::dump(ostream&o) const
}
// Dump the signals,
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
cur->dump_net(o, 4);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
cur->second->dump_net(o, 4);
}
// Dump specparams
@@ -1079,8 +1265,34 @@ void NetExpr::dump(ostream&o) const
o << "(?" << typeid(*this).name() << "?)";
}
void NetEAccess::dump(ostream&o) const
{
o << nature_->name() << "." << nature_->access() << "(";
assert(branch_);
if (branch_->pin(0).is_linked())
o << branch_->pin(0).nexus()->name();
o << ", ";
if (branch_->pin(1).is_linked())
o << branch_->pin(1).nexus()->name();
o << ")";
}
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 << ")";
@@ -1237,11 +1449,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
@@ -1266,6 +1476,9 @@ void NetEUFunc::dump(ostream&o) const
void NetEUnary::dump(ostream&o) const
{
switch (op_) {
case 'm':
o << "abs";
break;
case 'N':
o << "~|";
break;
@@ -1304,4 +1517,6 @@ void Design::dump(ostream&o) const
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
idx->dump(o, 0);
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
idx->dump(o, 0);
}
+149
View File
@@ -0,0 +1,149 @@
Developer Quick Start for Icarus Verilog
The documentation for getting, building and installing Icarus Verilog
is kept and maintained at the iverilog documentation wiki at
<http://iverilog.wikia.com>. See the Installation Guide for getting
the current source from the git repository (and how to use the git
repository) and see the Developer Guide for instructions on
participating in the Icarus Verilog development process. That
information will not be repeated here.
What this documentation *will* cover is the gross structure of the
Icarus Verilog compiler source. This will help orient you to the
source code itself, so that you can find the global parts where you
can look for even better detail.
* Compiler Components
- The compiler driver (driver/)
This is the binary that is installed as "iverilog". This program takes
the command line arguments and assembles invocations of all the other
subcommands to perform the steps of compilation.
- The preprocessor (ivlpp/)
This implements the Verilog pre-processor. In Icarus Verilog, the
compiler directives `define, `include, `ifdef and etc. are implemented
in an external program. The ivlpp/ directory contains the source for
this program.
- The core compiler (this directory)
The "ivl" program is the core that does all the Verilog compiler
processing that is not handled elsewhere. This is the main core of the
Icarus Verilog compiler, not the runtime. See below for more details
on the core itself.
- The loadable code generators (tgt-*/)
This core compiler, after it is finished with parsing and semantic
analysis, uses loadable code generators to emit code for supported
targets. The tgt-*/ directories contains the source for the target
code generators that are bundled with Icarus Verilog. The tgt-vvp/
directory in particular contains the code generator for the vvp
runtime.
* Runtime Components
- The vvp runtime (vvp/)
This program implements the runtime environment for Icarus
Verilog. It implements the "vvp" command described in the user
documentation. See the vvp/ subdirectory for further developer
documentation.
- The system tasks implementations (vpi/)
The standard Verilog system tasks are implemented using VPI (PLI-2)
and the source is in this subdirectory.
- The PLI-1 compatibility library (libveriuser/)
The Icarus Verilog support for the deprecated PLI-1 is in this
subdirectory. The vvp runtime does not directly support the
PLI-1. Instead, the libveriuser library emulates it using the builtin
PLI-2 support.
- The Cadence PLI module compatibility module (cadpli/)
It is possible in some specialized situations to load and execute
PLI-1 code written for Verilog-XL. This directory contains the source
for the module that provides the Cadence PLI interface.
* The Core Compiler
The "ivl" binary is the core compiler that does the heavy lifting of
compiling the Verilog source (including libraries) and generating the
output. This is the most complex component of the Icarus Verilog
compilation system.
The process in the abstract starts with the Verilog lexical analysis
and parsing to generate an internal "pform". The pform is then
translated by elaboration into the "netlist" form. The netlist is
processed by some functors (which include some optimizations and
optional synthesis) then is translated into the ivl_target internal
form. And finally, the ivl_target form is passed via the ivl_target.h
API to the code generators.
- Lexical Analysis
Lexical analysis and parsing use the tools "flex", "gperf", and
"bison". The "flex" input file "lexor.lex" recognizes the tokens in
the input stream. This is called "lexical analysis". The lexical
analyzer also does some processing of compiler directives that are not
otherwise taken care of by the external preprocessor. The lexical
analyzer uses a table of keywords that is generated using the "gperf"
program and the input file "lexor_keywords.gperf". This table allows
the lexical analyzer to efficiently check input words with the rather
large set of potential keywords.
- Parsing
The parser input file "parse.y" is passed to the "bison" program to
generate the parser. The parser uses the functions in parse*.h,
parse*.cc, pform.h, and pform*.cc to generate the pform from the
stream of input tokens. The pform is what compiler writers call a
"decorated parse tree".
The pform itself is described by the classes in the header files
"PScope.h", "Module.h", "PGenerate.h", "Statement.h", and
"PExpr.h". The implementations of the classes in those header files
are in the similarly named C++ files.
- Elaboration
Elaboration transforms the pform to the netlist form. Elaboration is
conceptually divided into several major steps: Scope elaboration,
parameter overrides and defparam propagation, signal elaboration, and
statement and expression elaboration.
The elaboration of scopes and parameter overrides and defparam
propagation are conceptually separate, but are in practice
intermingled. The elaboration of scopes scans the pform to find and
instantiate all the scopes of the design. New scopes are created by
instantiation of modules (starting with the root instances) by user
defined tasks and functions, named blocks, and generate schemes. The
elaborate_scope methods implement scope elaboration, and the
elab_scope.cc source file has the implementations of those
methods.
The elaborate.cc source file contains the initial calls to the
elaborate_scope for the root scopes to get the process started. In
particular, see the "elaborate" function near the bottom of the
elaborate.cc source file. The calls to Design::make_root_scope create
the initial root scopes, and the creation and enqueue of the
elaborate_root_scope_t work items primes the scope elaboration work
list.
Intermingled in the work list are defparms work items that call the
Design::run_defparams and Design::evaluate_parameters methods that
override and evaluate parameters. The override and evaluation of
parameters must be intermingled with the elaboration of scopes because
the exact values of parameters may impact the scopes created (imagine
generate schemes and instance arrays) and the created scopes in turn
create new parameters that need override and evaluation.
+39
View File
@@ -0,0 +1,39 @@
/*
* 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 "discipline.h"
nature_t::nature_t(perm_string name__, perm_string access__)
: name_(name__), access_(access__)
{
}
nature_t::~nature_t()
{
}
ivl_discipline_s::ivl_discipline_s(perm_string name__, ivl_dis_domain_t domain__,
nature_t*pot, nature_t*flow__)
: name_(name__), domain_(domain__), potential_(pot), flow_(flow__)
{
}
ivl_discipline_s::~ivl_discipline_s()
{
}
+77
View File
@@ -0,0 +1,77 @@
#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 "ivl_target.h"
# include "LineInfo.h"
extern std::ostream& operator << (std::ostream&, ivl_dis_domain_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 ivl_discipline_s : public LineInfo {
public:
explicit ivl_discipline_s (perm_string name, ivl_dis_domain_t dom,
nature_t*pot, nature_t*flow);
~ivl_discipline_s();
perm_string name() const { return name_; }
ivl_dis_domain_t domain() const { return domain_; }
const nature_t*potential() const { return potential_; }
const nature_t*flow() const { return flow_; }
private:
perm_string name_;
ivl_dis_domain_t domain_;
nature_t*potential_;
nature_t*flow_;
private: // not implemented
ivl_discipline_s(const ivl_discipline_s&);
ivl_discipline_s& operator = (const ivl_discipline_s&);
};
extern map<perm_string,nature_t*> natures;
extern map<perm_string,ivl_discipline_t> disciplines;
// Map access function name to the nature that it accesses.
extern map<perm_string,nature_t*> access_function_nature;
#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
+3 -4
View File
@@ -16,12 +16,9 @@
# 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@
@@ -48,6 +45,8 @@ LDFLAGS = @LDFLAGS@
all: iverilog-vpi@EXEEXT@
check: all
clean:
rm -f *.o config.h
rm -f iverilog-vpi@EXEEXT@
+8 -8
View File
@@ -336,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,
@@ -356,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();
+19 -12
View File
@@ -16,9 +16,6 @@
# 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.9.devel
@@ -41,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@
@@ -76,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
@@ -93,17 +100,17 @@ endif
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC)
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(DESTDIR)$(bindir)/iverilog@EXEEXT@
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
$(INSTALL_DATA) $(srcdir)/iverilog.man $(DESTDIR)$(mandir)/man1/iverilog.1
$(prefix)/iverilog.pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
$(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(INSTALL_DOCDIR)
uninstall:
rm -f $(bindir)/iverilog@EXEEXT@
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
rm -f $(DESTDIR)$(bindir)/iverilog@EXEEXT@
rm -f $(DESTDIR)$(mandir)/man1/iverilog.1 $(DESTDIR)$(prefix)/iverilog.pdf
+1 -1
View File
@@ -149,7 +149,7 @@ int cmdfile_stack_ptr = 0;
cflval.text = trim_trailing_white(yytext, 0);
BEGIN(0);
return TOK_STRING; }
/* Fallback match. */
. { return yytext[0]; }
+20 -16
View File
@@ -5,7 +5,7 @@ iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value]
[-dname] [-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
@@ -14,7 +14,7 @@ iverilog - Icarus Verilog compiler
\fIiverilog\fP is a compiler that translates Verilog source code into
executable programs for simulation, or other netlist formats for
further processing. The currently supported targets are \fIvvp\fP for
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
simulation, and \fIfpga\fP for synthesis. Other target
types are added as code generators are implemented.
.SH OPTIONS
@@ -55,15 +55,18 @@ 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
@@ -209,17 +212,18 @@ This is the default. The vvp target generates code for the vvp
runtime. The output is a complete program that simulates the design
but must be run by the \fBvvp\fP command.
.TP 8
.B xnf
This is the Xilinx Netlist Format used by many tools for placing
devices in FPGAs or other programmable devices. This target is
obsolete, use the \fBfpga\fP target instead.
.TP 8
.B fpga
This is a synthesis target that supports a variety of fpga devices,
mostly by EDIF format output. The Icarus Verilog fpga code generator
can generate complete designs or EDIF macros that can in turn be
imported into larger designs by other tools. The \fBfpga\fP target
implies the synthesis \fB-S\fP flag.
.TP 8
.B vhdl
This target produces a VHDL translation of the Verilog netlist. The
output is a single file containing VHDL entities corresponding to
the modules in the Verilog source code. Note that only a subset of
the Verilog language is supported. See the wiki for more information.
.SH "WARNING TYPES"
These are the types of warnings that can be selected by the \fB-W\fP
@@ -384,9 +388,14 @@ 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
@@ -404,11 +413,6 @@ To compile and run explicitly using the vvp runtime:
iverilog -ohello.vvp -tvvp hello.v
To compile hello.v to a file in XNF-format called hello.xnf
iverilog -txnf -ohello.xnf hello.v
.SH "AUTHOR"
.nf
Steve Williams ([email protected])
+194 -83
View File
@@ -51,6 +51,7 @@ const char HELP[] =
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
@@ -106,10 +107,12 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "2x";
const char*generation = "2005";
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;
@@ -257,18 +260,113 @@ static const char*my_tempfile(const char*str, FILE**fout)
return pathbuf;
}
static int t_version_only(void)
{
remove(source_path);
free(source_path);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
system(tmp);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
iconfig_path, iconfig_common_path);
system(tmp);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
free(iconfig_path);
remove(defines_path);
free(defines_path);
remove(compiled_defines_path);
free(compiled_defines_path);
}
return 0;
}
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F%s -f%s -p%s ",
pbase,sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
}
static int t_preprocess_only(void)
{
int rc;
char*cmd;
unsigned ncmd;
build_preprocess_command(1);
ncmd = strlen(tmp);
cmd = malloc(ncmd+1);
strcpy(cmd, tmp);
if (strcmp(opath,"-") != 0) {
snprintf(tmp, sizeof tmp, " > %s", opath);
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
strcpy(cmd+ncmd, tmp);
ncmd += strlen(tmp);
}
if (verbose_flag)
printf("preprocess: %s\n", cmd);
rc = system(cmd);
remove(source_path);
free(source_path);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
free(iconfig_path);
remove(defines_path);
free(defines_path);
remove(compiled_defines_path);
free(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
fprintf(stderr, "errors preprocessing Verilog program.\n");
return WEXITSTATUS(rc);
}
fprintf(stderr, "Command signaled: %s\n", cmd);
free(cmd);
return -1;
}
free(cmd);
return 0;
}
/*
* This is the default target type. It looks up the bits that are
* needed to run the command from the configuration file (which is
* already parsed for us) so we can handle must of the generic cases.
*/
static int t_default(char*cmd, unsigned ncmd)
static int t_compile()
{
unsigned rc;
/* Start by building the preprocess command line. */
build_preprocess_command(0);
size_t ncmd = strlen(tmp);
char*cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
#ifdef __MINGW32__
unsigned ncmd_start = ncmd;
#else
int rtn;
#endif
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s/ivl", base);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
@@ -321,25 +419,34 @@ static int t_default(char*cmd, unsigned ncmd)
rc = system(cmd);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(source_path);
free(source_path);
remove(iconfig_path);
free(iconfig_path);
remove(defines_path);
free(defines_path);
remove(compiled_defines_path);
free(compiled_defines_path);
}
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
free(cmd);
return rc;
#else
rtn = 0;
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
return 1;
rtn = 1;
} else if (WIFEXITED(rc)) {
rtn = WEXITSTATUS(rc);
} else {
fprintf(stderr, "Command signaled: %s\n", cmd);
rtn = -1;
}
if (WIFEXITED(rc))
return WEXITSTATUS(rc);
fprintf(stderr, "Command signaled: %s\n", cmd);
return -1;
}
return 0;
free(cmd);
return rtn;
#endif
}
@@ -430,21 +537,42 @@ 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)
gen_xtypes = "no-xtypes";
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";
@@ -463,17 +591,25 @@ int process_generation(const char*name)
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-verilog-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;
}
@@ -487,7 +623,7 @@ int process_generation(const char*name)
void add_sft_file(const char *module)
{
char *file;
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
sprintf(file, "%s%c%s.sft", base, sep, module);
if (access(file, R_OK) == 0)
@@ -497,8 +633,6 @@ void add_sft_file(const char *module)
int main(int argc, char **argv)
{
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
@@ -563,6 +697,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. */
@@ -616,7 +752,7 @@ int main(int argc, char **argv)
case 'c':
case 'f':
add_cmd_file(optarg);
break;
break;
case 'D':
process_define(optarg);
break;
@@ -635,9 +771,9 @@ int main(int argc, char **argv)
if (rc != 0)
return -1;
break;
case 'h':
fprintf(stderr, "%s\n", HELP);
return 1;
case 'h':
fprintf(stderr, "%s\n", HELP);
return 1;
case 'I':
process_include_dir(optarg);
@@ -710,9 +846,6 @@ int main(int argc, char **argv)
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2008 Stephen Williams\n");
puts(NOTICE);
if (version_flag)
return 0;
}
/* Make a common conf file path to reflect the target. */
@@ -727,11 +860,29 @@ int main(int argc, char **argv)
how to handle them. */
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
/* If verilog-2005 is enabled or icarus-misc or verilog-ams,
* then include the v2005_math library. */
if (strcmp(generation, "2005") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0 ||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
fprintf(iconfig_file, "module:v2005_math\n");
}
/* If verilog-ams or icarus_misc is enabled, then include the
* va_math module as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0) {
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
fprintf(iconfig_file, "module:va_math\n");
}
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);
@@ -777,60 +928,11 @@ int main(int argc, char **argv)
fclose(defines_file);
defines_file = 0;
if (source_count == 0) {
if (source_count == 0 && !version_flag) {
fprintf(stderr, "%s: no source files.\n\n%s\n", argv[0], HELP);
return 1;
}
/* Start building the preprocess command line. */
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s -p%s ", pbase,sep,
verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
ncmd = strlen(tmp);
cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
if (e_flag) {
int rc;
if (strcmp(opath,"-") != 0) {
sprintf(tmp, " > %s", opath);
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
strcpy(cmd+ncmd, tmp);
ncmd += strlen(tmp);
}
if (verbose_flag)
printf("preprocess: %s\n", cmd);
rc = system(cmd);
remove(source_path);
fclose(iconfig_file);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
remove(defines_path);
remove(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
fprintf(stderr, "errors preprocessing Verilog program.\n");
return WEXITSTATUS(rc);
}
fprintf(stderr, "Command signaled: %s\n", cmd);
return -1;
}
return 0;
}
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
/* Write the preprocessor command needed to preprocess a
@@ -842,7 +944,16 @@ int main(int argc, char **argv)
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
return t_default(cmd, ncmd);
/* If we're only here for the version output, then we're done. */
if (version_flag)
return t_version_only();
return 0;
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
if (e_flag)
return t_preprocess_only();
/* Otherwise, this is a full compile. */
return t_compile();
}
+20 -2
View File
@@ -21,6 +21,16 @@
# include "netlist.h"
# include <cassert>
# include <stdlib.h>
# include "ivl_assert.h"
NetEAccess* NetEAccess::dup_expr() const
{
NetEAccess*tmp = new NetEAccess(branch_, nature_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBComp* NetEBComp::dup_expr() const
{
@@ -84,8 +94,8 @@ NetESFunc* NetESFunc::dup_expr() const
tmp->cast_signed(has_sign());
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
assert(tmp->parm(idx));
tmp->parm(idx, tmp->parm(idx)->dup_expr());
assert(parm(idx));
tmp->parm(idx, parm(idx)->dup_expr());
}
tmp->set_line(*this);
@@ -128,6 +138,14 @@ NetEUFunc* NetEUFunc::dup_expr() const
return tmp;
}
NetEUBits* NetEUBits::dup_expr() const
{
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
NetEUnary* NetEUnary::dup_expr() const
{
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
+1 -2
View File
@@ -115,7 +115,7 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, sig, mem, par, eve);
symbol_search(this, des, scope, path_, sig, mem, par, eve);
if (mem != 0) {
@@ -211,4 +211,3 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
* Check lvalue of procedural continuous assign (PR#29)
*
*/
+1492 -366
View File
File diff suppressed because it is too large Load Diff
+72 -103
View File
@@ -152,7 +152,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, reg, par, eve);
symbol_search(this, des, scope, path_, reg, par, eve);
if (reg == 0) {
cerr << get_fileline() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(scope) <<
@@ -208,101 +208,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
long msb, lsb;
NetExpr*mux;
if (use_sel == index_component_t::SEL_BIT) {
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
/* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the
expression it not constant, then return the
expression as a mux. */
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
msb = index_con->value().as_long();
lsb = index_con->value().as_long();
mux = 0;
} else {
msb = 0;
lsb = 0;
mux = index_expr;
}
} else {
/* No select expressions, so presume a part select the
width of the register. */
msb = reg->msb();
lsb = reg->lsb();
mux = 0;
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
}
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
NetAssign_*lv;
if (mux) {
/* If there is a non-constant bit select, make a
NetAssign_ to the target reg and attach a
bmux to select the target bit. */
lv = new NetAssign_(reg);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
lv = new NetAssign_(reg);
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return 0;
}
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
cerr << get_fileline() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
lv = new NetAssign_(reg);
lv->set_part(new NetEConst(verinum(loff)), wid);
}
/* No select expressions. */
NetAssign_*lv = new NetAssign_(reg);
return lv;
}
@@ -374,10 +291,67 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
return lv;
}
bool PEIdent::elaborate_lval_net_bit_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
const name_component_t&name_tail = path_.back();
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
NetNet*reg = lv->sig();
// Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit
// width of 1.
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
long lsb = 0;
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
lsb = index_con->value().as_long();
mux = 0;
}
if (mux) {
// Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select expression.
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (lsb == reg->msb() && lsb == reg->lsb()) {
// Constant bit mux that happens to select the only bit
// of the l-value. Don't bother with any select at all.
} else {
// Constant bit select that does something useful.
long loff = reg->sb_to_idx(lsb);
if (loff < 0 || loff >= (long)reg->vector_width()) {
cerr << get_fileline() << ": error: bit select "
<< reg->name() << "[" <<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
lv->set_part(new NetEConst(verinum(loff)), 1);
}
return true;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
// The range expressions of a part select must be
// constant. The calculate_parts_ function calculates the
// values into msb and lsb.
long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
if (!flag)
@@ -388,17 +362,14 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
/* Part select covers the entire vector. Simplest case. */
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
/* Get the canonical offsets into the vector. */
long loff = reg->sb_to_idx(lsb);
long moff = reg->sb_to_idx(msb);
long wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
@@ -408,17 +379,15 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
return false;
}
/* If the part select extends beyond the extreme of the
/* If the part select extends beyond the extremes of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
cerr << get_fileline() << ": error: bit/part select "
if (loff < 0 || moff >= (signed)reg->vector_width()) {
cerr << get_fileline() << ": warning: Part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
+141 -3007
View File
File diff suppressed because it is too large Load Diff
+174 -3
View File
@@ -57,6 +57,52 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp;
}
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);
NetExpr*rp = right_->elaborate_pexpr(des, scope);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
return 0;
}
suppress_binary_operand_sign_if_needed_(lp, rp);
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
tmp->set_line(*this);
bool flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl;
des->errors += 1;
}
return tmp;
}
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);
NetExpr*rp = right_->elaborate_pexpr(des, scope);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
return 0;
}
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
tmp->set_line(*this);
bool flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl;
des->errors += 1;
}
return tmp;
}
/*
* Event though parameters are not generally sized, parameter
* expressions can include concatenation expressions. This requires
@@ -132,13 +178,13 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
{
pform_name_t path = path_;
pform_name_t oldpath = path_;
name_component_t name_tail = path_.back();
path.pop_back();
oldpath.pop_back();
NetScope*pscope = scope;
if (path_.size() > 0) {
list<hname_t> tmp = eval_scope_path(des, scope, path);
list<hname_t> tmp = eval_scope_path(des, scope, oldpath);
pscope = des->find_scope(scope, tmp);
}
@@ -267,3 +313,128 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp;
}
NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
{
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
perm_string nm = peek_tail_name(path_);
if (nm[0] == '$' && (generation_flag >= GN_VER2005 ||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
if (nm == "$clog2" ||
nm == "$ln" ||
nm == "$log10" ||
nm == "$exp" ||
nm == "$sqrt" ||
nm == "$floor" ||
nm == "$ceil" ||
nm == "$sin" ||
nm == "$cos" ||
nm == "$tan" ||
nm == "$asin" ||
nm == "$acos" ||
nm == "$atan" ||
nm == "$sinh" ||
nm == "$cosh" ||
nm == "$tanh" ||
nm == "$asinh" ||
nm == "$acosh" ||
nm == "$atanh") {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
NetESFunc*rtn;
if (nm == "$clog2") {
rtn = new NetESFunc(nm, IVL_VT_BOOL, integer_width, 1);
} else {
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
}
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg);
return rtn;
}
if (nm == "$pow" ||
nm == "$atan2" ||
nm == "$hypot") {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 2);
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg0);
rtn->parm(1, arg1);
return rtn;
}
/* These are only available with verilog-ams or icarus-misc. */
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(nm == "$log" || nm == "$abs")) {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
NetESFunc*rtn;
if (nm == "$log") {
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
} else {
/* This can return either a real or an arbitrary
* width vector, so set things to fail if this
* does not get replaced with a constant during
* elaboration. */
rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 1);
}
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg);
return rtn;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(nm == "$min" || nm == "$max")) {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
/* See $log above for why this has no type or width. */
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 2);
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg0);
rtn->parm(1, arg1);
return rtn;
}
cerr << get_fileline() << ": error: this is not a constant "
"system function (" << *this << ")." << endl;
des->errors += 1;
return 0;
}
/* Constant user function code goes here. */
cerr << get_fileline() << ": sorry: constant user functions are not "
"currently supported." << endl;
des->errors += 1;
return 0;
}
+499 -143
View File
@@ -22,6 +22,7 @@
# include "netmisc.h"
# include <cstring>
# include <iostream>
# include <cstdlib>
# include <stdio.h>
/*
@@ -39,19 +40,55 @@
# include "PTask.h"
# include "PWire.h"
# include "Statement.h"
# include "AStatement.h"
# include "netlist.h"
# 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)
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_scope_parameters_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void collect_scope_localparams_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void elaborate_parm_item_(perm_string name,
const LexicalScope::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;
@@ -62,9 +99,53 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
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);
}
NetScope::range_t*range_list = 0;
for (LexicalScope::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;
}
/* Set the parameter expression to 0 if the evaluation failed. */
if (val == 0) {
val = scope->set_parameter(name, val, cur.type, msb, lsb,
signed_flag, range_list, cur);
delete val;
return;
}
if (signed_flag) {
@@ -80,14 +161,165 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
signed_flag = val->has_sign();
}
val = scope->set_parameter(name, val,
msb, lsb, signed_flag);
assert(val);
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
range_list, cur);
delete val;
}
static void elaborate_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
}
static void elaborate_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
for (Module::replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
NetExpr*val = (*cur).second;
if (val == 0) {
cerr << loc.get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
<< (*cur).first;
}
assert(val);
if (debug_scopes) {
cerr << loc.get_fileline() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
cerr << loc.get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
}
static void elaborate_scope_events_(Design*des, NetScope*scope,
const map<perm_string,PEvent*>&events)
{
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
; et != events.end() ; et ++ ) {
(*et).second->elaborate_scope(des, scope);
}
}
static void elaborate_scope_tasks(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
for (tasks_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << loc.get_fileline() << ": error: task/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
task_scope->is_auto((*cur).second->is_auto());
task_scope->set_line((*cur).second);
if (debug_scopes)
cerr << cur->second->get_fileline() << ": debug: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
(*cur).second->elaborate_scope(des, task_scope);
}
}
static void elaborate_scope_funcs(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
for (funcs_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << loc.get_fileline() << ": error: function/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
func_scope->is_auto((*cur).second->is_auto());
func_scope->set_line((*cur).second);
if (debug_scopes)
cerr << cur->second->get_fileline() << ": debug: "
<< "Elaborate function scope " << scope_path(func_scope) << endl;
(*cur).second->elaborate_scope(des, func_scope);
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
: elaborator_work_item_t(des__), scope_(scope), mod_(mod)
{ }
void elaborate_runrun()
{
if (debug_scopes)
cerr << mod_->get_fileline() << ": debug: "
<< "Processing generate schemes for "
<< scope_path(scope_) << endl;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = mod_->generate_schemes.begin()
; cur != mod_->generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope_);
}
}
private:
// The scope_ is the scope that contains the generate scheme
// we are to work on. the mod_ is the Module definition for
// that scope, and contains the parsed generate schemes.
NetScope*scope_;
Module*mod_;
};
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements) const
const replace_t&replacements)
{
if (debug_scopes) {
cerr << get_fileline() << ": debug: Elaborate scope "
@@ -105,77 +337,25 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// the pform and just place a NetEParam placeholder in the
// place of the elaborated expression.
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
// Scan the parameters in the module, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
// This loop scans the parameters in the module, and creates
// stub parameter entries in the scope for the parameter name.
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
elaborate_scope_parameters_(des, scope, parameters);
/* run parameter replacements that were collected from the
containing scope and meant for me. */
for (replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
replace_scope_parameters_(scope, *this, replacements);
NetExpr*val = (*cur).second;
if (val == 0) {
cerr << get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
<< (*cur).first;
}
assert(val);
if (debug_scopes) {
cerr << get_fileline() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
elaborate_scope_localparams_(des, scope, localparams);
// Run through the defparams for this module, elaborate the
// expressions in this context and save the result is a table
@@ -187,15 +367,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
for (pform_parm_it_t cur = defparms.begin()
; cur != defparms.end() ; cur ++ ) {
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
for (defparms_iter_t cur = defparms.begin()
; cur != defparms.end() ; cur ++) {
PExpr*ex = (*cur).second;
PExpr*ex = cur->second;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) continue;
scope->defparams[(*cur).first] = val;
scope->defparams.push_back(make_pair(cur->first, val));
}
// Evaluate the attributes. Evaluate them in the scope of the
@@ -208,64 +390,29 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
delete[]attr;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
// Generate schemes need to have their scopes elaborated, but
// we cannot do that until defparams are run, so push it off
// into an elaborate work item.
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Schedule generates within " << scope_path(scope)
<< " for elaboration after defparams." << endl;
des->elaboration_work_list.push_back(new generate_schemes_work_item_t(des, scope, this));
// Tasks introduce new scopes, so scan the tasks in this
// module. Create a scope for the task and pass that to the
// elaborate_scope method of the PTask for detailed
// processing.
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
for (tasks_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: task/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
(*cur).second->elaborate_scope(des, task_scope);
}
elaborate_scope_tasks(des, scope, *this, tasks);
// Functions are very similar to tasks, at least from the
// perspective of scopes. So handle them exactly the same
// way.
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
for (funcs_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: function/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
(*cur).second->elaborate_scope(des, func_scope);
}
elaborate_scope_funcs(des, scope, *this, funcs);
// Gates include modules, which might introduce new scopes, so
// scan all of them to create those scopes.
@@ -295,11 +442,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// elaboration, so do it now. This allows for normal
// elaboration to reference these events.
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
; et != events.end() ; et ++ ) {
(*et).second->elaborate_scope(des, scope);
}
elaborate_scope_events_(des, scope, events);
return des->errors == 0;
}
@@ -318,7 +461,9 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
case GS_CASE:
return generate_scope_case_(des, container);
return true;
case GS_NBLOCK:
return generate_scope_nblock_(des, container);
case GS_CASE_ITEM:
cerr << get_fileline() << ": internal error: "
@@ -337,6 +482,11 @@ 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;
@@ -352,17 +502,34 @@ 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_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);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
@@ -383,6 +550,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
@@ -394,8 +562,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
genvar_verinum);
scope->set_localparam(loop_index, gp);
// 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 "
@@ -407,7 +576,12 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
assert(step);
if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " step expression: " << *loop_step << endl;
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
@@ -432,7 +606,12 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
{
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
assert(test);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
// If the condition evaluates as false, then do not create the
// scope.
@@ -463,6 +642,7 @@ 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);
@@ -473,10 +653,12 @@ 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 (case_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
<< " expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case "
@@ -485,8 +667,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
PGenerate*default_item = 0;
typedef list<PGenerate*>::const_iterator generator_it_t;
generator_it_t cur = generates.begin();
while (cur != generates.end()) {
generator_it_t cur = generate_schemes.begin();
while (cur != generate_schemes.end()) {
PGenerate*item = *cur;
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
@@ -515,7 +697,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
delete case_value_co;
case_value_co = 0;
PGenerate*item = (cur == generates.end())? default_item : *cur;
PGenerate*item = (cur == generate_schemes.end())? default_item : *cur;
if (item == 0) {
cerr << get_fileline() << ": debug: "
<< "No generate items found" << endl;
@@ -527,13 +709,40 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
<< "Generate case matches item at "
<< item->get_fileline() << endl;
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
item->elaborate_subscope_(des, scope);
return true;
}
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
{
hname_t use_name (scope_name);
if (container->child(use_name)) {
cerr << get_fileline() << ": error: block/scope name "
<< scope_name << " already used in this context."
<< endl;
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate named block "
<< ": Generate scope=" << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
elaborate_subscope_(des, scope);
return true;
}
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
// Scan the generated scope for nested generate schemes,
@@ -541,11 +750,24 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
// from simple elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
// Scan the localparams in this scope, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_localparams_(scope, localparams);
// Now scan the localparams again, this time elaborating them
// for use as parameter values.
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the task and function declarations in this
// scope.
elaborate_scope_tasks(des, scope, *this, tasks);
elaborate_scope_funcs(des, scope, *this, funcs);
// Scan the generated scope for gates that may create
// their own scopes.
typedef list<PGate*>::const_iterator pgate_list_it_t;
@@ -554,10 +776,54 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) ->elaborate_scope(des, scope);
}
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; cur ++ ) {
(*cur) -> statement() -> elaborate_scope(des, scope);
}
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
// Save the scope that we created, for future use.
scope_list_.push_back(scope);
}
class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
public:
delayed_elaborate_scope_mod_instances(Design*des__,
const PGModule*obj,
Module*mod,
NetScope*sc)
: elaborator_work_item_t(des__), obj_(obj), mod_(mod), sc_(sc)
{ }
~delayed_elaborate_scope_mod_instances() { }
virtual void elaborate_runrun();
private:
const PGModule*obj_;
Module*mod_;
NetScope*sc_;
};
void delayed_elaborate_scope_mod_instances::elaborate_runrun()
{
if (debug_scopes)
cerr << obj_->get_fileline() << ": debug: "
<< "Resume scope elaboration of instances of "
<< mod_->mod_name() << "." << endl;
obj_->elaborate_scope_mod_instances_(des, mod_, sc_);
}
/*
* Here we handle the elaborate scope of a module instance. The caller
* has already figured out that this "gate" is a module, and has found
* the module definition. The "sc" argument is the scope that will
* contain this instance.
*/
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
{
if (get_name() == "") {
@@ -604,6 +870,36 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
return;
}
if (msb_ || lsb_) {
// If there are expressions to evaluate in order to know
// the actual number of instances that will be
// instantiated, then we have to delay further scope
// elaboration until after defparams (above me) are
// run. Do that by appending a work item to the
// elaboration work list.
if (debug_scopes)
cerr << get_fileline() << ": debug: delay elaborate_scope"
<< " of array of " << get_name()
<< " in scope " << scope_path(sc) << "." << endl;
elaborator_work_item_t*tmp
= new delayed_elaborate_scope_mod_instances(des, this, mod, sc);
des->elaboration_work_list.push_back(tmp);
} else {
// If there are no expressions that need to be evaluated
// to elaborate the scope of this next instances, then
// get right to it.
elaborate_scope_mod_instances_(des, mod, sc);
}
}
/*
* This method is called to process a module instantiation after basic
* sanity testing is already complete.
*/
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
{
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
@@ -661,6 +957,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);
@@ -689,16 +987,16 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
assert(parms_ == 0);
list<perm_string>::const_iterator cur
= mod->param_names.begin();
unsigned idx = 0;
unsigned jdx = 0;
for (;;) {
if (idx >= overrides_->count())
if (jdx >= overrides_->count())
break;
if (cur == mod->param_names.end())
break;
replace[*cur] = (*overrides_)[idx];
replace[*cur] = (*overrides_)[jdx];
idx += 1;
jdx += 1;
cur ++;
}
}
@@ -707,8 +1005,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// so the mapping into the replace list is much easier.
if (parms_) {
assert(overrides_ == 0);
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
replace[parms_[idx].name] = parms_[idx].parm;
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
replace[parms_[jdx].name] = parms_[jdx].parm;
}
@@ -768,6 +1066,25 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::FUNC);
// Scan the parameters in the function, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (statement_)
statement_->elaborate_scope(des, scope);
}
@@ -776,6 +1093,25 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
// Scan the parameters in the task, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (statement_)
statement_->elaborate_scope(des, scope);
}
@@ -811,11 +1147,31 @@ 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());
my_scope->is_auto(scope->is_auto());
// Scan the parameters in the scope, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(my_scope, parameters);
collect_scope_localparams_(my_scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, my_scope, parameters);
elaborate_scope_localparams_(des, my_scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);
}
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
list_[idx] -> elaborate_scope(des, my_scope);
}
/*
+117 -62
View File
@@ -108,13 +108,49 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
return flag;
}
static void elaborate_sig_funcs(Design*des, NetScope*scope,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
(*cur).second->elaborate_sig(des, fscope);
}
}
static void elaborate_sig_tasks(Design*des, NetScope*scope,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
}
bool Module::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
// Scan all the ports of the module, and make sure that each
// is connected to wires that have port declarations.
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
Module::port_t*pp = ports[idx];
if (pp == 0)
continue;
@@ -123,7 +159,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
// 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) {
for (unsigned cc = 0 ; cc < pp->expr.size() ; cc += 1) {
pform_name_t port_path (pp->expr[cc]->path());
// A concatenated wire of a port really should not
// have any hierarchy.
@@ -182,38 +218,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
flag &= (*gt)->elaborate_sig(des, scope);
}
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
(*cur).second->elaborate_sig(des, fscope);
}
// After all the wires are elaborated, we are free to
// elaborate the ports of the tasks defined within this
// module. Run through them now.
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
// initial and always blocks may contain begin-end and
// fork-join blocks that can introduce scopes. Therefore, I
@@ -256,7 +266,7 @@ bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
if (error_implicit)
return true;
symbol_search(des, scope, path_, sig, par, eve);
symbol_search(this, des, scope, path_, sig, par, eve);
if (eve != 0)
return false;
@@ -323,7 +333,7 @@ bool PGAssign::elaborate_sig(Design*des, NetScope*scope) const
to implicitly declare nets. However, so many tools do allow
it that Icarus Verilog will allow it, at least if extensions
are enabled. */
if (generation_flag == GN_VER2001X)
if (gn_icarus_misc_flag)
return pin(0)->elaborate_sig(des, scope);
return true;
@@ -351,11 +361,11 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
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) {
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
// I know a priori that the elaborate_scope created the scope
// already, so just look it up as a child of the current scope.
NetScope*my_scope = instance[idx];
@@ -415,8 +425,8 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
<< scope_path(container) << "." << endl;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++) {
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
@@ -461,9 +471,12 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
cur->elaborate_sig(des, scope);
}
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> elaborate_sig(des, scope);
}
@@ -576,9 +589,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
break;
default:
cerr << get_fileline() << ": internal error: I don't know how "
<< "to deal with return type of function "
<< scope->basename() << "." << endl;
if (ports_) {
cerr << get_fileline() << ": internal error: I don't know "
<< "how to deal with return type of function "
<< scope->basename() << "." << endl;
} else {
/* If we do not have any ports or a return type this
* is probably a bad function definition. */
cerr << get_fileline() << ": error: Bad definition for "
<< "function " << scope->basename() << "?" << endl;
return;
}
}
svector<NetNet*>ports (ports_? ports_->count() : 0);
@@ -758,6 +779,18 @@ void PForStatement::elaborate_sig(Design*des, NetScope*scope) const
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);
}
/*
* Elaborate a source wire. The "wire" is the declaration of wires,
* registers, ports and memories. The parser has already merged the
@@ -780,16 +813,19 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_set_ || net_set_) {
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
bool bad_lsb = false, bad_msb = false;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && port_msb_ != 0) {
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
if (! eval_as_long(pmsb, texpr)) {
cerr << port_msb_->get_fileline() << ": error: "
"Unable to evaluate MSB constant expression ``"
<< *port_msb_ << "''." << endl;
"Range expressions must be constant." << endl;
cerr << port_msb_->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *port_msb_ << endl;
des->errors += 1;
return 0;
bad_msb = true;
}
delete texpr;
@@ -798,10 +834,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (! eval_as_long(plsb, texpr)) {
cerr << port_lsb_->get_fileline() << ": error: "
"Unable to evaluate LSB constant expression ``"
<< *port_lsb_ << "''." << endl;
"Range expressions must be constant." << endl;
cerr << port_lsb_->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *port_lsb_ << endl;
des->errors += 1;
return 0;
bad_lsb = true;
}
delete texpr;
@@ -813,15 +851,17 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_lsb_ == 0) assert(port_msb_ == 0);
/* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && net_msb_ != 0) {
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
if (! eval_as_long(nmsb, texpr)) {
cerr << net_msb_->get_fileline() << ": error: "
"Unable to evaluate MSB constant expression ``"
<< *net_msb_ << "''." << endl;
"Range expressions must be constant." << endl;
cerr << net_msb_->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *net_msb_ << endl;
des->errors += 1;
return 0;
bad_msb = true;
}
delete texpr;
@@ -830,10 +870,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (! eval_as_long(nlsb, texpr)) {
cerr << net_lsb_->get_fileline() << ": error: "
"Unable to evaluate LSB constant expression ``"
<< *net_lsb_ << "''." << endl;
"Range expressions must be constant." << endl;
cerr << net_lsb_->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *net_lsb_ << endl;
des->errors += 1;
return 0;
bad_lsb = true;
}
delete texpr;
@@ -886,6 +928,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
}
/* Attempt to recover from errors. */
if (bad_lsb) nlsb = 0;
if (bad_msb) nmsb = nlsb;
lsb = nlsb;
msb = nmsb;
if (nmsb > nlsb)
@@ -930,16 +976,18 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete lexp;
if (!const_flag) {
cerr << get_fileline() << ": internal error: The indices "
cerr << get_fileline() << ": error: The indices "
<< "are not constant for array ``"
<< name_ << "''." << endl;
des->errors += 1;
return 0;
}
/* Attempt to recover from error, */
array_s0 = 0;
array_e0 = 0;
} else {
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
array_dimensions = 1;
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
/* If the net type is supply0 or supply1, replace it
@@ -978,8 +1026,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
<< " in scope " << scope_path(scope) << endl;
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
if (array_dimensions > 0) {
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
}
cerr << " in scope " << scope_path(scope) << endl;
}
@@ -1004,6 +1055,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (ivl_discipline_t dis = get_discipline()) {
sig->set_discipline(dis);
}
if (pull)
connect(sig->pin(0), pull->pin(0));
+26
View File
@@ -0,0 +1,26 @@
/*
* 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 "AStatement.h"
# include <cstdlib>
# include <iostream>
+1211 -682
View File
File diff suppressed because it is too large Load Diff
+64
View File
@@ -0,0 +1,64 @@
/*
* 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 "AStatement.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
# include <typeinfo>
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
{
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
NetContribution*st = new NetContribution(lval, rval);
st->set_line(*this);
return st;
}
bool AProcess::elaborate(Design*des, NetScope*scope) const
{
NetProc*statement = statement_->elaborate(des, scope);
if (statement == 0)
return false;
NetAnalogTop*top = new NetAnalogTop(scope, type_, statement);
// Evaluate the attributes for this process, if there
// are any. These attributes are to be attached to the
// NetProcTop object.
struct attrib_list_t*attrib_list = 0;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
top->attribute(attrib_list[adx].key,
attrib_list[adx].val);
delete[]attrib_list;
top->set_line(*this);
des->add_process(top);
return true;
}
+61 -32
View File
@@ -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);
@@ -66,6 +72,16 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
return true;
}
bool NetCastInt::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_int(this);
}
bool NetCastReal::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_real(this);
}
bool NetCLShift::emit_node(struct target_t*tgt) const
{
tgt->lpm_clshift(this);
@@ -159,6 +175,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);
@@ -169,16 +190,28 @@ bool NetProcTop::emit(struct target_t*tgt) const
return tgt->process(this);
}
bool NetAnalogTop::emit(struct target_t*tgt) const
{
cerr << get_fileline() << ": sorry: "
<< "I don't know how to emit for analog processes." << endl;
return false;
}
bool NetProc::emit_proc(struct target_t*tgt) const
{
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
return false;
}
bool NetAlloc::emit_proc(struct target_t*tgt) const
{
tgt->proc_alloc(this);
return true;
}
bool NetAssign::emit_proc(struct target_t*tgt) const
{
tgt->proc_assign(this);
return true;
return tgt->proc_assign(this);
}
bool NetAssignNB::emit_proc(struct target_t*tgt) const
@@ -229,6 +262,12 @@ bool NetForever::emit_proc(struct target_t*tgt) const
return true;
}
bool NetFree::emit_proc(struct target_t*tgt) const
{
tgt->proc_free(this);
return true;
}
bool NetPDelay::emit_proc(struct target_t*tgt) const
{
return tgt->proc_delay(this);
@@ -341,23 +380,20 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
cur->emit_scope(tgt);
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
tgt->signal(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
tgt->signal(cur->second);
}
/* Run the signals again, but this time to connect the
delay paths. This is done as a second pass because
the paths reference other signals that may be later
in the list. We can do it here becase delay paths are
always connected within the scope. */
cur = signals_->sig_next_;
do {
tgt->signal_paths(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
// Run the signals again, but this time to connect the
// delay paths. This is done as a second pass because
// the paths reference other signals that may be later
// in the list. We can do it here because delay paths are
// always connected within the scope.
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
tgt->signal_paths(cur->second);
}
}
@@ -427,6 +463,8 @@ int Design::emit(struct target_t*tgt) const
bool proc_rc = true;
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
proc_rc &= idx->emit(tgt);
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
proc_rc &= idx->emit(tgt);
rc = tgt->end_design(this);
@@ -440,6 +478,11 @@ int Design::emit(struct target_t*tgt) const
return rc;
}
void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_access_func(this);
}
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_binary(this);
@@ -515,17 +558,3 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_unary(this);
}
int emit(const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx];
if (strcmp(tgt->name, type) == 0)
return des->emit(tgt->meth);
}
cerr << "error: Code generator type " << type
<< " not found." << endl;
return -1;
}
+1 -1
View File
@@ -185,7 +185,7 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
return new verinum(scope->genvar_tmp_val);
}
symbol_search(des, scope, path_, net, expr, eve);
symbol_search(this, des, scope, path_, net, expr, eve);
if (expr == 0)
return 0;
+10 -6
View File
@@ -53,14 +53,19 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
/* If the attribute value is given in the source, then
evaluate it as a constant. If the value is not
given, then assume the value is 1. */
verinum*tmp;
if (exp)
verinum*tmp = 0;
if (exp) {
tmp = exp->eval_const(des, scope);
else
if (tmp == 0) {
cerr << exp->get_fileline() << ": error: ``"
<< *exp << "'' is not a constant expression."
<< endl;
des->errors += 1;
}
}
if (tmp == 0)
tmp = new verinum(1);
if (tmp == 0)
cerr << "internal error: no result for " << *exp << endl;
assert(tmp);
table[idx].val = *tmp;
@@ -106,4 +111,3 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
* of complex attributes attached to gates.
*
*/
+437 -68
View File
@@ -22,6 +22,8 @@
# include <iostream>
# include <cstdlib>
# include <cstring>
# include <math.h>
# include "netlist.h"
# include "ivl_assert.h"
@@ -131,6 +133,19 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
if (lval.len() < expr_width())
lval = pad_to_width(lval, expr_width());
if (rval.len() < expr_width())
rval = pad_to_width(rval, expr_width());
if (se->expr_width() > this->expr_width()) {
cerr << get_fileline() << ": internal error: "
<< "expr_width()=" << expr_width()
<< ", sub expr_width()=" << se->expr_width()
<< ", sub expression=" << *se << endl;
}
ivl_assert(*this, se->expr_width() <= this->expr_width());
verinum val;
if (op_ == se->op_) {
/* (a + lval) + rval --> a + (rval+lval) */
@@ -142,6 +157,15 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
val = rval - lval;
}
// Since we padded the operands above to be the minimum
// width, the val should also be at least expr_width().
ivl_assert(*this, val.len() >= expr_width());
if (val.len() > expr_width()) {
verinum tmp (val, expr_width());
tmp.has_sign(val.has_sign());
val = tmp;
}
NetEConst*tmp = new NetEConst(val);
left_ = se->left_->dup_expr();
delete se;
@@ -338,19 +362,15 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
switch (le->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (le);
if (rtmp == 0)
return 0;
if (rtmp == 0) return 0;
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (le);
if (vtmp == 0)
return 0;
lv = vtmp->value().as_long();
if (vtmp == 0) return 0;
lv = vtmp->value().as_double();
break;
default:
@@ -359,23 +379,18 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
assert(0);
}
switch (ri->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (ri);
if (rtmp == 0)
return 0;
if (rtmp == 0) return 0;
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (ri);
if (vtmp == 0)
return 0;
rv = vtmp->value().as_long();
if (vtmp == 0) return 0;
rv = vtmp->value().as_double();
break;
default:
@@ -479,19 +494,6 @@ NetEConst* NetEBComp::eval_gt_()
return tmp;
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
double rr = tmp->value().as_double();
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -530,19 +532,6 @@ NetEConst* NetEBComp::eval_gteq_()
return tmp;
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
double rr = tmp->value().as_double();
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -561,8 +550,73 @@ NetEConst* NetEBComp::eval_gteq_()
}
}
/*
* Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
* bits and returns true(false) if there are any bits in the vector
* that are defined (0 or 1) and different. If all the defined bits
* are equal, but there are are x/z bits, then the situation is
* ambiguous so the result is x.
*/
NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag)
{
NetEConst*vtmp;
NetECReal*rtmp;
double lv, rv;
switch (le->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (le);
if (rtmp == 0) return 0;
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (le);
if (vtmp == 0) return 0;
lv = vtmp->value().as_double();
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected expression type? " << le->expr_type() << endl;
assert(0);
}
switch (ri->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (ri);
if (rtmp == 0) return 0;
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (ri);
if (vtmp == 0) return 0;
rv = vtmp->value().as_double();
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected expression type? " << ri->expr_type() << endl;
assert(0);
}
verinum result(((lv == rv) ^ ne_flag) ? verinum::V1 : verinum::V0, 1);
vtmp = new NetEConst(result);
vtmp->set_line(*this);
return vtmp;
}
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
{
if (right_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(right_, left_, ne_flag);
if (left_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(right_, left_, ne_flag);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
NetEConst*r = dynamic_cast<NetEConst*>(right_);
@@ -581,11 +635,14 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
for (unsigned idx = 0 ; idx < top ; idx += 1) {
bool x_bit_present = false;
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
@@ -597,17 +654,20 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
break;
}
if (res == verinum::Vx)
break;
if (x_bit_present)
continue;
if (rv.get(idx) != lv.get(idx))
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
break;
}
}
if (res != verinum::Vx) {
@@ -766,9 +826,9 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
verireal lval = lc->value();
if (NetECReal*rc = dynamic_cast<NetECReal*>(right_)) {
if (NetECReal*rcr = dynamic_cast<NetECReal*>(right_)) {
NetECReal*tmp = 0;
verireal rval = rc->value();
verireal rval = rcr->value();
switch (op_) {
case '/':
@@ -811,8 +871,10 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum lval = lc->value();
verinum rval = rc->value();
// Make sure the expression is evaluated at the
// expression width.
verinum lval = pad_to_width(lc->value(), expr_width());
verinum rval = pad_to_width(rc->value(), expr_width());
NetExpr*tmp = 0;
switch (op_) {
@@ -1153,6 +1215,11 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
val = verinum(val.as_string());
}
// Normally, concatenations are unsigned. However, the
// $signed() function works by marking the expression as
// signed, so we really have to check.
val.has_sign( this->has_sign() );
NetEConst*res = new NetEConst(val);
res->set_width(val.len());
return res;
@@ -1171,17 +1238,9 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
}
assert(scope_);
const NetExpr*expr_msb;
const NetExpr*expr_lsb;
const NetExpr*expr = scope_->get_parameter(name_, expr_msb, expr_lsb);
if (expr == 0) {
cerr << get_fileline() << ": internal error: Unable to match "
<< "parameter " << name_ << " in scope "
<< scope_path(scope_) << endl;
return 0;
}
assert(expr);
perm_string name = (*reference_).first;
const NetExpr*expr = (*reference_).second.expr;
ivl_assert(*this, expr);
NetExpr*nexpr = expr->dup_expr();
assert(nexpr);
@@ -1190,7 +1249,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
// return the constant value.
if (NetEConst*tmp = dynamic_cast<NetEConst*>(nexpr)) {
verinum val = tmp->value();
NetEConstParam*ptmp = new NetEConstParam(scope_, name_, val);
NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
ptmp->set_line(*this);
delete nexpr;
return ptmp;
@@ -1198,7 +1257,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
if (NetECReal*tmp = dynamic_cast<NetECReal*>(nexpr)) {
verireal val = tmp->value();
NetECRealParam*ptmp = new NetECRealParam(scope_, name_, val);
NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
ptmp->set_line(*this);
delete nexpr;
return ptmp;
@@ -1209,7 +1268,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
NetExpr*res = nexpr->eval_tree();
if (res == 0) {
cerr << get_fileline() << ": internal error: Unable to evaluate "
<< "parameter " << name_ << " expression: "
<< "parameter " << name << " expression: "
<< *nexpr << endl;
delete nexpr;
return 0;
@@ -1217,7 +1276,12 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
// The result can be saved as the value of the parameter for
// future reference, and return a copy to the caller.
scope_->replace_parameter(name_, res);
bool flag = scope_->replace_parameter(name, res);
if (!flag) {
cerr << get_fileline() << ": internal error: Could not "
<< "replace parameter expression for " << name << endl;
return 0;
}
/* Return as a result a NetEConstParam or NetECRealParam
object, depending on the type of the expression. */
@@ -1229,7 +1293,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
{ NetEConst*tmp = dynamic_cast<NetEConst*>(res);
if (tmp == 0) {
cerr << get_fileline() << ": internal error: parameter "
<< name_ << " evaluates to incomprehensible "
<< name << " evaluates to incomprehensible "
<< *res << "." << endl;
return 0;
}
@@ -1237,7 +1301,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
assert(tmp);
verinum val = tmp->value();
NetEConstParam*ptmp = new NetEConstParam(scope_, name_, val);
NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
return ptmp;
}
@@ -1246,7 +1310,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
{ NetECReal*tmp = dynamic_cast<NetECReal*>(res);
if (tmp == 0) {
cerr << get_fileline() << ": internal error: parameter "
<< name_ << " evaluates to incomprehensible "
<< name << " evaluates to incomprehensible "
<< *res << "." << endl;
return 0;
}
@@ -1254,7 +1318,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
assert(tmp);
verireal val = tmp->value();
NetECRealParam*ptmp = new NetECRealParam(scope_, name_, val);
NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
return ptmp;
}
@@ -1342,7 +1406,7 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
case C_0:
eval_expr(false_val_);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate ternary with "
<< "constant condition value: ";
print_ternary_cond(cond_);
@@ -1610,3 +1674,308 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
return new NetEConst(verinum(res, 1));
}
NetExpr* evaluate_clog2(NetExpr*&arg_)
{
eval_expr(arg_);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
if (tmpi || tmpr) {
verinum arg;
if (tmpi) {
arg = tmpi->value();
} else {
arg = verinum(tmpr->value().as_double(), true);
}
/* If we have an x in the verinum we return 'bx. */
if (!arg.is_defined()) {
verinum tmp (verinum::Vx, integer_width);
tmp.has_sign(true);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
bool is_neg = false;
uint64_t res = 0;
if (arg.is_negative()) {
is_neg = true;
// If the length is not defined, then work with
// the trimmed version of the number.
if (! arg.has_len())
arg = trim_vnum(arg);
}
arg.has_sign(false); // $unsigned()
if (!arg.is_zero()) {
arg = arg - verinum((uint64_t)1, 1);
while (!arg.is_zero()) {
res += 1;
arg = arg >> 1;
}
}
if (is_neg && res < integer_width)
res = integer_width;
verinum tmp (res, integer_width);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
return 0;
}
NetExpr* evaluate_math_one_arg(NetExpr*&arg_, const char*name)
{
eval_expr(arg_);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
if (tmpi || tmpr) {
double arg;
if (tmpi) {
arg = tmpi->value().as_double();
} else {
arg = tmpr->value().as_double();
}
if (strcmp(name, "$ln") == 0) {
return new NetECReal(verireal(log(arg)));
} else if (strcmp(name, "$log") == 0) {
return new NetECReal(verireal(log10(arg)));
} else if (strcmp(name, "$log10") == 0) {
return new NetECReal(verireal(log10(arg)));
} else if (strcmp(name, "$exp") == 0) {
return new NetECReal(verireal(exp(arg)));
} else if (strcmp(name, "$sqrt") == 0) {
return new NetECReal(verireal(sqrt(arg)));
} else if (strcmp(name, "$floor") == 0) {
return new NetECReal(verireal(floor(arg)));
} else if (strcmp(name, "$ceil") == 0) {
return new NetECReal(verireal(ceil(arg)));
} else if (strcmp(name, "$sin") == 0) {
return new NetECReal(verireal(sin(arg)));
} else if (strcmp(name, "$cos") == 0) {
return new NetECReal(verireal(cos(arg)));
} else if (strcmp(name, "$tan") == 0) {
return new NetECReal(verireal(tan(arg)));
} else if (strcmp(name, "$asin") == 0) {
return new NetECReal(verireal(asin(arg)));
} else if (strcmp(name, "$acos") == 0) {
return new NetECReal(verireal(acos(arg)));
} else if (strcmp(name, "$atan") == 0) {
return new NetECReal(verireal(atan(arg)));
} else if (strcmp(name, "$sinh") == 0) {
return new NetECReal(verireal(sinh(arg)));
} else if (strcmp(name, "$cosh") == 0) {
return new NetECReal(verireal(cosh(arg)));
} else if (strcmp(name, "$tanh") == 0) {
return new NetECReal(verireal(tanh(arg)));
} else if (strcmp(name, "$asinh") == 0) {
return new NetECReal(verireal(asinh(arg)));
} else if (strcmp(name, "$acosh") == 0) {
return new NetECReal(verireal(acosh(arg)));
} else if (strcmp(name, "$atanh") == 0) {
return new NetECReal(verireal(atanh(arg)));
}
}
return 0;
}
NetExpr* evaluate_math_two_args(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
{
eval_expr(arg0_);
eval_expr(arg1_);
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
} else {
arg0 = tmpr0->value().as_double();
}
if (tmpi1) {
arg1 = tmpi1->value().as_double();
} else {
arg1 = tmpr1->value().as_double();
}
if (strcmp(name, "$pow") == 0) {
return new NetECReal(verireal(pow(arg0, arg1)));
} else if (strcmp(name, "$atan2") == 0) {
return new NetECReal(verireal(atan2(arg0, arg1)));
} else if (strcmp(name, "$hypot") == 0) {
return new NetECReal(verireal(hypot(arg0, arg1)));
}
}
return 0;
}
NetExpr* evaluate_abs(NetExpr*&arg_)
{
eval_expr(arg_);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
if (tmpi) {
verinum arg = tmpi->value();
if (arg.is_negative()) {
arg = v_not(arg) + verinum(1);
}
return new NetEConst(arg);
}
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
if (tmpr) {
double arg = tmpr->value().as_double();
return new NetECReal(verireal(fabs(arg)));
}
return 0;
}
NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
{
eval_expr(arg0_);
eval_expr(arg1_);
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
if (tmpi0 && tmpi1) {
verinum arg0 = tmpi0->value();
verinum arg1 = tmpi1->value();
if (strcmp(name, "$min") == 0) {
return new NetEConst( arg0 < arg1 ? arg0 : arg1);
} else if (strcmp(name, "$max") == 0) {
return new NetEConst( arg0 < arg1 ? arg1 : arg0);
}
}
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
} else {
arg0 = tmpr0->value().as_double();
}
if (tmpi1) {
arg1 = tmpi1->value().as_double();
} else {
arg1 = tmpr1->value().as_double();
}
if (strcmp(name, "$min") == 0) {
return new NetECReal(verireal(arg0 < arg1 ? arg0 : arg1));
} else if (strcmp(name, "$max") == 0) {
return new NetECReal(verireal(arg0 < arg1 ? arg1 : arg0));
}
}
return 0;
}
NetExpr* NetESFunc::eval_tree(int prune_to_width)
{
/* If we are not targeting at least Verilog-2005, Verilog-AMS
* or using the Icarus misc flag then we do not support these
* functions as constant. */
if (generation_flag < GN_VER2005 &&
!gn_icarus_misc_flag && !gn_verilog_ams_flag) {
return 0;
}
const char*nm = name();
NetExpr*rtn = 0;
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
if (strcmp(nm, "$clog2") == 0 ||
strcmp(nm, "$ln") == 0 ||
strcmp(nm, "$log10") == 0 ||
strcmp(nm, "$exp") == 0 ||
strcmp(nm, "$sqrt") == 0 ||
strcmp(nm, "$floor") == 0 ||
strcmp(nm, "$ceil") == 0 ||
strcmp(nm, "$sin") == 0 ||
strcmp(nm, "$cos") == 0 ||
strcmp(nm, "$tan") == 0 ||
strcmp(nm, "$asin") == 0 ||
strcmp(nm, "$acos") == 0 ||
strcmp(nm, "$atan") == 0 ||
strcmp(nm, "$sinh") == 0 ||
strcmp(nm, "$cosh") == 0 ||
strcmp(nm, "$tanh") == 0 ||
strcmp(nm, "$asinh") == 0 ||
strcmp(nm, "$acosh") == 0 ||
strcmp(nm, "$atanh") == 0) {
if (nparms() != 1 || parm(0) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
return 0;
}
NetExpr*arg = parm(0)->dup_expr();
if (strcmp(nm, "$clog2") == 0) {
rtn = evaluate_clog2(arg);
} else {
rtn = evaluate_math_one_arg(arg, nm);
}
delete arg;
}
if (strcmp(nm, "$pow") == 0 ||
strcmp(nm, "$atan2") == 0 ||
strcmp(nm, "$hypot") == 0) {
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
return 0;
}
NetExpr*arg0 = parm(0)->dup_expr();
NetExpr*arg1 = parm(1)->dup_expr();
rtn = evaluate_math_two_args(arg0, arg1, nm);
delete arg0;
delete arg1;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(strcmp(nm, "$log") == 0 || strcmp(nm, "$abs") == 0)) {
if (nparms() != 1 || parm(0) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
return 0;
}
NetExpr*arg = parm(0)->dup_expr();
if (strcmp(nm, "$log") == 0) {
rtn = evaluate_math_one_arg(arg, nm);
} else {
rtn = evaluate_abs(arg);
}
delete arg;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(strcmp(nm, "$min") == 0 || strcmp(nm, "$max") == 0)) {
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
return 0;
}
NetExpr*arg0 = parm(0)->dup_expr();
NetExpr*arg1 = parm(1)->dup_expr();
rtn = evaluate_min_max(arg0, arg1, nm);
delete arg0;
delete arg1;
}
if (rtn != 0) {
rtn->set_line(*this);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate constant "
<< nm << "." << endl;
}
}
return rtn;
}
+1 -1
View File
@@ -154,7 +154,7 @@
*
* The POST_MAP compiler directive causes the GSR manipulations
* included in the test bench to be compiled in, to simulate the chip
* startup. Other then that, the test bench runs the post-map design
* startup. Other than that, the test bench runs the post-map design
* the same way the pre-synthesis design works.
*
* Run this design with the command:
+367 -162
View File
@@ -20,56 +20,56 @@
# include "config.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
{
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;
}
verireal vrl(expr->value().as_double());
NetECReal rlval(vrl);
NetNet* sig = rlval.synthesize(des, scope);
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)
static bool process_binary_args(Design*des, NetScope*scope,
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. */
/* Convert the arguments to real. Handle the special
cases of constants, which can be converted more directly. */
if (left->expr_type() == IVL_VT_REAL) {
lsig = left->synthesize(des);
lsig = left->synthesize(des, scope);
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (left)) {
lsig = convert_to_real_const(des, scope, tmpc);
} else {
lsig = convert_to_real_const(des, left, obj);
NetNet*tmp = left->synthesize(des, scope);
lsig = cast_to_real(des, scope, tmp);
}
if (right->expr_type() == IVL_VT_REAL) {
rsig = right->synthesize(des);
rsig = right->synthesize(des, scope);
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (right)) {
rsig = convert_to_real_const(des, scope, tmpc);
} else {
rsig = convert_to_real_const(des, right, obj);
NetNet*tmp = right->synthesize(des, scope);
rsig = cast_to_real(des, scope, tmp);
}
} else {
real_args = false;
lsig = left->synthesize(des);
rsig = right->synthesize(des);
lsig = left->synthesize(des, scope);
rsig = right->synthesize(des, scope);
}
@@ -77,7 +77,7 @@ bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
else return false;
}
NetNet* NetExpr::synthesize(Design*des)
NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
{
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
<< *this << endl;
@@ -88,25 +88,35 @@ NetNet* NetExpr::synthesize(Design*des)
/*
* Make an LPM_ADD_SUB device from addition operators.
*/
NetNet* NetEBAdd::synthesize(Design*des)
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
{
assert((op()=='+') || (op()=='-'));
ivl_assert(*this, (op()=='+') || (op()=='-'));
NetNet *lsig=0, *rsig=0;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
assert(expr_width() >= lsig->vector_width());
assert(expr_width() >= rsig->vector_width());
ivl_assert(*this, expr_width() >= lsig->vector_width());
ivl_assert(*this, expr_width() >= rsig->vector_width());
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
unsigned width;
if (expr_type() == IVL_VT_REAL) {
width = 1;
if (lsig->data_type() != IVL_VT_REAL)
lsig = cast_to_real(des, scope, lsig);
if (rsig->data_type() != IVL_VT_REAL)
rsig = cast_to_real(des, scope, rsig);
assert(lsig->vector_width() == rsig->vector_width());
unsigned width=lsig->vector_width();
} else {
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
assert(lsig->vector_width() == rsig->vector_width());
width=lsig->vector_width();
}
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
@@ -138,10 +148,10 @@ NetNet* NetEBAdd::synthesize(Design*des)
* signals, then just connect a single gate to each bit of the vector
* of the expression.
*/
NetNet* NetEBBits::synthesize(Design*des)
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet*lsig = left_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des, scope);
if (lsig == 0 || rsig == 0) return 0;
@@ -154,10 +164,7 @@ NetNet* NetEBBits::synthesize(Design*des)
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
unsigned width = lsig->vector_width();
unsigned width = expr_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
@@ -205,13 +212,13 @@ NetNet* NetEBBits::synthesize(Design*des)
return osig;
}
NetNet* NetEBComp::synthesize(Design*des)
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -222,22 +229,58 @@ NetNet* NetEBComp::synthesize(Design*des)
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);
if (lsig->get_signed())
lsig = pad_to_width_signed(des, lsig, width);
else
lsig = pad_to_width(des, lsig, width);
if (rsig->get_signed())
rsig = pad_to_width_signed(des, rsig, width);
else
rsig = pad_to_width(des, rsig, width);
}
NetScope*scope = lsig->scope();
assert(scope);
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);
// Test if the comparison is signed.
//
// Note 1: This is not the same as asking if the result is
// signed. In fact, the result will typically be UNsigned. The
// decision to make the comparison signed depends on the
// operand expressions.
//
// Note 2: The operand expressions may be signed even if the
// sig that comes out of synthesis is unsigned. The $signed()
// function marks the expression but doesn't change the
// underlying signals.
bool signed_compare = left_->has_sign() && right_->has_sign();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Comparison (" << op_ << ")"
<< " is " << (signed_compare? "signed" : "unsigned")
<< endl;
cerr << get_fileline() << ": : lsig is "
<< (lsig->get_signed()? "signed" : "unsigned")
<< " rsig is " << (rsig->get_signed()? "signed" : "unsigned")
<< endl;
}
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E'?true:false);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
des->add_node(gate);
return osig;
}
/* 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')) && !real_args) {
if ((width == 1) && (op_ == 'e') && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR, 1);
gate->set_line(*this);
@@ -251,7 +294,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')) && !real_args) {
if ((width == 1) && (op_ == 'n') && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR, 1);
gate->set_line(*this);
@@ -274,9 +317,11 @@ 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': // === ?
if (real_args) {
@@ -290,9 +335,11 @@ NetNet* NetEBComp::synthesize(Design*des)
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': // !==
if (real_args) {
@@ -315,12 +362,12 @@ NetNet* NetEBComp::synthesize(Design*des)
return osig;
}
NetNet* NetEBPow::synthesize(Design*des)
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -328,9 +375,6 @@ NetNet* NetEBPow::synthesize(Design*des)
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());
@@ -353,12 +397,12 @@ NetNet* NetEBPow::synthesize(Design*des)
return osig;
}
NetNet* NetEBMult::synthesize(Design*des)
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -366,9 +410,6 @@ NetNet* NetEBMult::synthesize(Design*des)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetMult*mult = new NetMult(scope, scope->local_symbol(),
width,
lsig->vector_width(),
@@ -392,12 +433,12 @@ NetNet* NetEBMult::synthesize(Design*des)
return osig;
}
NetNet* NetEBDiv::synthesize(Design*des)
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -405,12 +446,11 @@ NetNet* NetEBDiv::synthesize(Design*des)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->set_signed(has_sign());
osig->local_flag(true);
switch (op()) {
@@ -421,6 +461,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
div->set_signed(has_sign());
des->add_node(div);
connect(div->pin_DataA(), lsig->pin(0));
@@ -432,7 +473,7 @@ 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 && generation_flag < GN_VER2001X) {
if (real_args && !gn_icarus_misc_flag) {
cerr << get_fileline() << ": error: Modulus operator "
"may not have REAL operands." << endl;
des->errors += 1;
@@ -443,6 +484,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
div->set_signed(has_sign());
des->add_node(div);
connect(div->pin_DataA(), lsig->pin(0));
@@ -453,7 +495,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
default: {
cerr << get_fileline() << ": internal error: "
<< "NetEBDiv has unexpeced op() code: "
<< "NetEBDiv has unexpected op() code: "
<< op() << endl;
des->errors += 1;
@@ -465,10 +507,10 @@ NetNet* NetEBDiv::synthesize(Design*des)
return osig;
}
NetNet* NetEBLogic::synthesize(Design*des)
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet*lsig = left_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des, scope);
if (lsig == 0 || rsig == 0) return 0;
@@ -481,9 +523,6 @@ NetNet* NetEBLogic::synthesize(Design*des)
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
@@ -545,11 +584,11 @@ NetNet* NetEBLogic::synthesize(Design*des)
return osig;
}
NetNet* NetEBShift::synthesize(Design*des)
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
{
eval_expr(right_);
NetNet*lsig = left_->synthesize(des);
NetNet*lsig = left_->synthesize(des, scope);
if (lsig == 0) return 0;
@@ -562,10 +601,8 @@ NetNet* NetEBShift::synthesize(Design*des)
return 0;
}
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
NetScope*scope = lsig->scope();
const bool right_flag = op_ == 'r' || op_ == 'R';
const bool signed_flag = op_ == 'R';
/* Detect the special case where the shift amount is
constant. Evaluate the shift amount, and simply reconnect
@@ -574,7 +611,7 @@ NetNet* NetEBShift::synthesize(Design*des)
verinum shift_v = rcon->value();
long shift = shift_v.as_long();
if (op() == 'r')
if (right_flag)
shift = 0-shift;
if (shift == 0)
@@ -587,34 +624,13 @@ NetNet* NetEBShift::synthesize(Design*des)
// ushift is the amount of pad created by the shift.
unsigned long ushift = shift>=0? shift : -shift;
if (ushift > osig->vector_width())
ushift = osig->vector_width();
ivl_assert(*this, ushift < osig->vector_width());
// part_width is the bits of the vector that survive the shift.
unsigned long part_width = osig->vector_width() - ushift;
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
/* Detect the special case that the shift is the size of
the whole expression. Simply connect the pad to the
osig and escape. */
if (ushift >= osig->vector_width()) {
connect(zcon->pin(0), osig->pin(0));
return osig;
}
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
/* Create a part select to reduce the width of the lsig
to the amount left by the shift. */
// Create a part select to reduce the width of the lsig
// to the amount left by the shift.
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
part_width,
NetPartSelect::VP);
@@ -627,6 +643,34 @@ NetNet* NetEBShift::synthesize(Design*des)
psig->set_line(*this);
connect(psig->pin(0), psel->pin(0));
// Handle the special case of a signed right shift. In
// this case, use the NetSignExtend device to pad the
// result to the desired width.
if (signed_flag && right_flag) {
NetSignExtend*pad = new NetSignExtend(scope, scope->local_symbol(),
osig->vector_width());
des->add_node(pad);
pad->set_line(*this);
connect(pad->pin(1), psig->pin(0));
connect(pad->pin(0), osig->pin(0));
return osig;
}
// Other cases are handled by zero-extending on the
// proper end.
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(), 2);
ccat->set_line(*this);
@@ -646,7 +690,7 @@ NetNet* NetEBShift::synthesize(Design*des)
return osig;
}
NetNet*rsig = right_->synthesize(des);
NetNet*rsig = right_->synthesize(des, scope);
if (rsig == 0) return 0;
@@ -672,13 +716,13 @@ NetNet* NetEBShift::synthesize(Design*des)
return osig;
}
NetNet* NetEConcat::synthesize(Design*des)
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
{
/* First, synthesize the operands. */
NetNet**tmp = new NetNet*[parms_.count()];
bool flag = true;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
tmp[idx] = parms_[idx]->synthesize(des);
tmp[idx] = parms_[idx]->synthesize(des, scope);
if (tmp[idx] == 0)
flag = false;
}
@@ -686,9 +730,7 @@ NetNet* NetEConcat::synthesize(Design*des)
if (flag == false)
return 0;
assert(tmp[0]);
NetScope*scope = tmp[0]->scope();
assert(scope);
ivl_assert(*this, tmp[0]);
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
@@ -706,7 +748,9 @@ NetNet* NetEConcat::synthesize(Design*des)
unsigned cur_pin = 1;
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
connect(concat->pin(cur_pin), tmp[parms_.count()-idx-1]->pin(0));
unsigned concat_item = parms_.count()-idx-1;
ivl_assert(*this, tmp[concat_item]);
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
cur_pin += 1;
}
}
@@ -715,17 +759,14 @@ NetNet* NetEConcat::synthesize(Design*des)
return osig;
}
NetNet* NetEConst::synthesize(Design*des)
NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
{
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
unsigned width=expr_width();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
osig->data_type(expr_type());
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
connect(osig->pin(0), con->pin(0));
@@ -737,11 +778,8 @@ NetNet* NetEConst::synthesize(Design*des)
/*
* Create a NetLiteral object to represent real valued constants.
*/
NetNet* NetECReal::synthesize(Design*des)
NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
{
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
@@ -762,9 +800,9 @@ NetNet* NetECReal::synthesize(Design*des)
* The bitwise unary logic operator (there is only one) is turned
* into discrete gates just as easily as the binary ones above.
*/
NetNet* NetEUBits::synthesize(Design*des)
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des);
NetNet*isig = expr_->synthesize(des, scope);
if (isig == 0) return 0;
@@ -776,9 +814,6 @@ NetNet* NetEUBits::synthesize(Design*des)
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
unsigned width = isig->vector_width();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
@@ -804,13 +839,56 @@ NetNet* NetEUBits::synthesize(Design*des)
return osig;
}
NetNet* NetEUReduce::synthesize(Design*des)
NetNet* NetEUnary::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des);
if (op_ == '+')
return expr_->synthesize(des, scope);
if (op_ == '-') {
NetNet*sig = expr_->synthesize(des, scope);
sig = sub_net_from(des, scope, 0, sig);
return sig;
}
if (op_ == 'm') {
NetNet*sub = expr_->synthesize(des, scope);
if (expr_->has_sign() == false)
return sub;
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sub->vector_width());
sig->set_line(*this);
sig->local_flag(true);
sig->data_type(sub->data_type());
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
des->add_node(tmp);
tmp->set_line(*this);
connect(tmp->pin(1), sub->pin(0));
connect(tmp->pin(0), sig->pin(0));
return sig;
}
cerr << get_fileline() << ": iternal error: "
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
des->errors += 1;
return expr_->synthesize(des, scope);
}
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des, scope);
if (isig == 0) return 0;
if (isig->data_type() == IVL_VT_REAL) {
if (op() == '!') {
cerr << get_fileline() << ": sorry: ! is currently "
"unsupported for real values." << endl;
des->errors += 1;
return 0;
}
cerr << get_fileline() << ": error: reduction operator ("
<< human_readable_op(op_)
<< ") may not have a REAL operand." << endl;
@@ -818,9 +896,6 @@ NetNet* NetEUReduce::synthesize(Design*des)
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
@@ -843,7 +918,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
rtype = NetUReduce::XOR;
break;
case 'A':
rtype = NetUReduce::XNOR;
rtype = NetUReduce::NAND;
break;
case 'X':
rtype = NetUReduce::XNOR;
@@ -865,22 +940,101 @@ NetNet* NetEUReduce::synthesize(Design*des)
return osig;
}
NetNet* NetESelect::synthesize(Design *des)
/*
* Turn a part/bit select expression into gates.
* We know some things about the expression that elaboration enforces
* for us:
*
* - Expression elaboration already converted the offset expression into
* canonical form, so we don't have to worry about that here.
*/
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
{
NetNet*sub = expr_->synthesize(des);
NetNet*sub = expr_->synthesize(des, scope);
if (sub == 0) return 0;
NetScope*scope = sub->scope();
NetNet*off = 0;
// Detect the special case that there is a base expression and
// it is constant. In this case we can generate fixed part selects.
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
verinum base_tmp = base_const->value();
ivl_assert(*this, base_tmp.is_defined());
long base_val = base_tmp.as_long();
unsigned select_width = expr_width();
// Any below X bits?
NetNet*below = 0;
if (base_val < 0) {
unsigned below_width = abs(base_val);
base_val = 0;
ivl_assert(*this, below_width < select_width);
select_width -= below_width;
below = make_const_x(des, scope, below_width);
below->set_line(*this);
}
// Any above bits?
NetNet*above = 0;
if ((unsigned)base_val+select_width > sub->vector_width()) {
select_width = sub->vector_width() - base_val;
unsigned above_width = expr_width() - select_width;
above = make_const_x(des, scope, above_width);
above->set_line(*this);
}
// Make the make part select.
NetPartSelect*sel = new NetPartSelect(sub, base_val, select_width,
NetPartSelect::VP);
des->add_node(sel);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, select_width);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(sel->pin(0), tmp->pin(0));
unsigned concat_count = 1;
if (above)
concat_count += 1;
if (below)
concat_count += 1;
if (concat_count > 1) {
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
expr_width(), concat_count);
cat->set_line(*this);
des->add_node(cat);
if (below) {
connect(cat->pin(1), below->pin(0));
connect(cat->pin(2), tmp->pin(0));
} else {
connect(cat->pin(1), tmp->pin(0));
}
if (above) {
connect(cat->pin(concat_count), above->pin(0));
}
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, expr_width());
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(cat->pin(0), tmp->pin(0));
}
return tmp;
}
// This handles the case that the NetESelect exists to do an
// actual part/bit select. Generate a NetPartSelect object to
// do the work, and replace "sub" with the selected output.
if (base_ != 0) {
off = base_->synthesize(des);
off = base_->synthesize(des, scope);
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
sel->set_line(*this);
@@ -923,6 +1077,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 {
@@ -960,21 +1115,26 @@ NetNet* NetESelect::synthesize(Design *des)
* expressions to the B and A inputs. This way, when the select input
* is one, the B input, which is the true expression, is selected.
*/
NetNet* NetETernary::synthesize(Design *des)
NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
{
NetNet*csig = cond_->synthesize(des),
*tsig = true_val_->synthesize(des),
*fsig = false_val_->synthesize(des);
NetNet*csig = cond_->synthesize(des, scope),
*tsig = true_val_->synthesize(des, scope),
*fsig = false_val_->synthesize(des, scope);
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;
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
cerr << get_fileline() << ": internal error: "
<< " True and False clauses of ternary expression "
<< " have incompatible types." << endl;
cerr << get_fileline() << ": : True clause is: "
<< tsig->data_type() << endl;
<< tsig->data_type()
<< " (" << true_val_->expr_type() << "): "
<< *true_val_ << endl;
cerr << get_fileline() << ": : False clause is: "
<< fsig->data_type() << endl;
<< fsig->data_type()
<< " (" << false_val_->expr_type() << "): "
<< *false_val_ << endl;
des->errors += 1;
return 0;
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
@@ -986,7 +1146,7 @@ NetNet* NetETernary::synthesize(Design *des)
perm_string path = csig->scope()->local_symbol();
assert(csig->vector_width() == 1);
ivl_assert(*this, csig->vector_width() == 1);
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
@@ -1018,26 +1178,25 @@ NetNet* NetETernary::synthesize(Design *des)
* a bit more work needs to be done. Return a temporary that represents
* the selected word.
*/
NetNet* NetESignal::synthesize(Design*des)
NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
{
if (word_ == 0)
return net_;
NetScope*scope = net_->scope();
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(net_->data_type());
// For NetExpr objects, the word index is already converted to
// a canonical (lsb==0) address. Just use the index directly.
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
long index = index_co->value().as_long();
assert(net_->array_index_is_valid(index));
index = net_->array_index_to_address(index);
connect(tmp->pin(0), net_->pin(index));
} else {
unsigned selwid = word_->expr_width();
@@ -1046,7 +1205,7 @@ NetNet* NetESignal::synthesize(Design*des)
mux->set_line(*this);
des->add_node(mux);
NetNet*index_net = word_->synthesize(des);
NetNet*index_net = word_->synthesize(des, scope);
connect(mux->pin_Address(), index_net->pin(0));
connect(tmp->pin(0), mux->pin_Result());
@@ -1054,22 +1213,68 @@ NetNet* NetESignal::synthesize(Design*des)
return tmp;
}
NetNet* NetESFunc::synthesize(Design*des)
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope)
{
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
<< *this << " in this context" << endl;
des->errors += 1;
return 0;
const struct sfunc_return_type*def = lookup_sys_func(name_);
/* We cannot use the default value for system functions in a
* continuous assignment since the function name is NULL. */
if (def == 0 || def->name == 0) {
cerr << get_fileline() << ": error: System function "
<< name_ << " not defined in system "
"table or SFT file(s)." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Net system function "
<< name_ << " returns " << def->type << endl;
}
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
def, 1+nparms_);
net->set_line(*this);
des->add_node(net);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, def->wid);
osig->local_flag(true);
osig->set_signed(def->type==IVL_VT_REAL? true : false);
osig->data_type(def->type);
osig->set_line(*this);
connect(net->pin(0), osig->pin(0));
unsigned errors = 0;
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) {
NetNet*tmp = parms_[idx]->synthesize(des, scope);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to elaborate "
<< "argument " << idx << " of call to " << name_ <<
"." << endl;
errors += 1;
des->errors += 1;
continue;
}
connect(net->pin(1+idx), tmp->pin(0));
}
if (errors > 0) return 0;
return osig;
}
NetNet* NetEUFunc::synthesize(Design*des)
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
{
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);
NetNet*tmp = parms_[idx]->synthesize(des, scope);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to synthesize "
"port " << idx << " of call to "
@@ -1096,7 +1301,7 @@ NetNet* NetEUFunc::synthesize(Design*des)
/* 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],
NetNet*tmp = pad_to_width(des, eparms[idx],
def->port(idx)->vector_width());
connect(net->pin(idx+1), tmp->pin(0));
}
+14 -13
View File
@@ -40,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*)
{
}
@@ -107,20 +111,12 @@ void NetScope::run_functor(Design*des, functor_t*fun)
// apply to signals. Each iteration, allow for the possibility
// that the current signal deletes itself.
if (signals_) {
unsigned count = 0;
NetNet*cur = signals_->sig_next_;
do {
count += 1;
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
cur = signals_->sig_next_;
for (unsigned idx = 0 ; idx < count ; idx += 1) {
NetNet*tmp = cur->sig_next_;
fun->signal(des, cur);
cur = tmp;
}
signals_map_iter_t cur = signals_map_.begin();
while (cur != signals_map_.end()) {
signals_map_iter_t tmp = cur;
cur ++;
fun->signal(des, tmp->second);
}
}
@@ -174,6 +170,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);
+3
View File
@@ -48,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*);
+34
View File
@@ -15,6 +15,9 @@ ivl_const_signed
ivl_const_type
ivl_const_width
ivl_discipline_domain
ivl_discipline_name
ivl_event_any
ivl_event_basename
ivl_event_name
@@ -53,6 +56,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
@@ -115,9 +121,12 @@ 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
@@ -132,8 +141,13 @@ 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_is_auto
ivl_scope_lineno
ivl_scope_logs
ivl_scope_log
ivl_scope_lpms
@@ -146,6 +160,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
@@ -159,7 +175,10 @@ ivl_signal_attr_val
ivl_signal_basename
ivl_signal_data_type
ivl_signal_dimensions
ivl_signal_discipline
ivl_signal_file
ivl_signal_integer
ivl_signal_lineno
ivl_signal_local
ivl_signal_lsb
ivl_signal_msb
@@ -177,6 +196,8 @@ ivl_path_source
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_file
ivl_process_lineno
ivl_process_scope
ivl_process_stmt
ivl_process_type
@@ -208,6 +229,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
+166 -6
View File
@@ -80,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
@@ -123,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
@@ -141,13 +151,16 @@ _BEGIN_DECL
typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
typedef struct ivl_discipline_s*ivl_discipline_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;
typedef struct ivl_net_logic_s*ivl_net_logic_t;
typedef struct ivl_udp_s *ivl_udp_t;
typedef struct ivl_nature_s *ivl_nature_t;
typedef struct ivl_net_probe_s*ivl_net_probe_t;
typedef struct ivl_nexus_s *ivl_nexus_t;
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
@@ -155,6 +168,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;
@@ -164,6 +178,12 @@ typedef struct ivl_statement_s*ivl_statement_t;
* changes and additions to the enumerations.
*/
typedef enum ivl_dis_domain_e {
IVL_DIS_NONE = 0,
IVL_DIS_DISCRETE = 1,
IVL_DIS_CONTINUOUS = 2
} ivl_dis_domain_t;
typedef enum ivl_drive_e {
IVL_DR_HiZ = 0,
IVL_DR_SMALL = 1,
@@ -181,6 +201,7 @@ typedef enum ivl_drive_e {
typedef enum ivl_expr_type_e {
IVL_EX_NONE = 0,
IVL_EX_ARRAY = 18,
IVL_EX_BACCESS= 19,
IVL_EX_BINARY = 2,
IVL_EX_CONCAT = 3,
IVL_EX_EVENT = 17,
@@ -226,10 +247,24 @@ 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_CAST_INT = 34,
IVL_LPM_CAST_REAL = 33,
IVL_LPM_CONCAT = 16,
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQ = 10,
@@ -242,7 +277,7 @@ 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,
@@ -316,6 +351,7 @@ typedef enum ivl_signal_type_e {
typedef enum ivl_statement_type_e {
IVL_ST_NONE = 0,
IVL_ST_NOOP = 1,
IVL_ST_ALLOC = 25,
IVL_ST_ASSIGN = 2,
IVL_ST_ASSIGN_NB = 3,
IVL_ST_BLOCK = 4,
@@ -332,6 +368,7 @@ typedef enum ivl_statement_type_e {
IVL_ST_FORCE = 14,
IVL_ST_FOREVER = 15,
IVL_ST_FORK = 16,
IVL_ST_FREE = 26,
IVL_ST_RELEASE = 17,
IVL_ST_REPEAT = 18,
IVL_ST_STASK = 19,
@@ -475,7 +512,8 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
* ivl_const_bits
* This returns a pointer to an array of constant characters,
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
* terminated.
* terminated. This value is only value if ivl_const_type is
* IVL_VT_LOGIC or IVL_VT_BOOL. It returns nil otherwise.
*
* ivl_const_nex
* Return the ivl_nexus_t of the output for the constant.
@@ -513,6 +551,28 @@ extern double ivl_const_real(ivl_net_const_t net);
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
/* DISCIPLINES
*
* Disciplines are Verilog-AMS construct. A discipline is a collection
* of attributes that can be attached to a signal.
*
* FUNCTION SUMMARY
*
* ivl_discipline_name
* This is the name of the discipline in the Verilog-AMS source.
*
* ivl_discipline_domain
* This is the domain: continuous or discrete.
*
* SEMANTIC NOTES
*
* The discipline domain will not be IVL_DIS_NONE. The "none" domain
* is a place-holder internally for incomplete parsing, and is also
* available for code generaters to use.
*/
extern const char*ivl_discipline_name(ivl_discipline_t net);
extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
/* EVENTS
*
* Events are a unification of named events and implicit events
@@ -698,6 +758,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
@@ -952,8 +1022,9 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* more than the width of the output, although the possibility of
* overflow exists at run time.
*
* Multiply may be signed. If so, the output should be sign extended
* to fill in its result.
* The inputs are always treated as unsigned. If the expression is
* supposed to be signed, elaboration will generate the necessary sign
* extension, so the target need not (must not) consider signedness.
*
* - Power (IVL_LPM_POW)
* The power takes two inputs and generates an output. Unlike other
@@ -1217,7 +1288,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
*/
extern unsigned ivl_lval_width(ivl_lval_t net);
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@@ -1312,6 +1383,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
@@ -1339,11 +1411,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
@@ -1391,10 +1470,21 @@ 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_is_auto
* Is the task or function declared to be automatic?
*
* ivl_scope_var
* ivl_scope_vars
* REMOVED
@@ -1465,9 +1555,14 @@ 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_is_auto(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);
@@ -1481,6 +1576,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);
@@ -1517,6 +1614,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* The signal may be an array (of vectors) in which case this
* function returns >0, the number of dimensions of the array.
*
* ivl_signal_discipline
* If the signal has been declared with a domain (Verilog-AMS) then
* this function wil return a non-nil ivl_discipline_t.
*
* ivl_signal_msb
* ivl_signal_lsb
* ivl_signal_width
@@ -1574,12 +1675,17 @@ 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);
extern int ivl_signal_array_base(ivl_signal_t net);
extern unsigned ivl_signal_array_count(ivl_signal_t net);
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
extern int ivl_signal_msb(ivl_signal_t net);
extern int ivl_signal_lsb(ivl_signal_t net);
extern unsigned ivl_signal_width(ivl_signal_t net);
@@ -1595,6 +1701,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);
@@ -1630,6 +1739,9 @@ extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
extern unsigned ivl_process_attr_cnt(ivl_process_t net);
extern ivl_attribute_t ivl_process_attr_val(ivl_process_t net, unsigned idx);
extern const char* ivl_process_file(ivl_process_t net);
extern unsigned ivl_process_lineno(ivl_process_t net);
/*
* These functions manage statements of various type. This includes
* all the different kinds of statements (as enumerated in
@@ -1799,6 +1911,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)
@@ -1807,7 +1966,7 @@ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
#endif
extern DLLEXPORT int target_design(ivl_design_t des);
extern DLLEXPORT const char* target_query(const char*key);
/* target_design
@@ -1825,6 +1984,7 @@ extern DLLEXPORT int target_design(ivl_design_t des);
ivl core. This function is how the target module is invoked. */
typedef int (*target_design_f)(ivl_design_t des);
typedef const char* (*target_query_f) (const char*key);
_END_DECL
+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
+4 -4
View File
@@ -40,7 +40,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
@@ -63,13 +63,13 @@ lexor.c: lexor.lex
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivlpp@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl
$(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
rm -f $(DESTDIR)$(libdir)/ivl/ivlpp@EXEEXT@
lexor.o: lexor.c globals.h
main.o: main.c globals.h
+3 -1
View File
@@ -1,7 +1,7 @@
#ifndef __globals_H
#define __globals_H
/*
* 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
@@ -22,9 +22,11 @@
# include <stdio.h>
extern void reset_lexor(FILE*out, char*paths[]);
extern void destroy_lexor();
extern void load_precompiled_defines(FILE*src);
extern void define_macro(const char*name, const char*value, int keyword,
int argc);
extern void free_macros();
extern void dump_precompiled_defines(FILE*out);
/* These variables contain the include directories to be searched when
+114 -34
View File
@@ -42,7 +42,7 @@ static void do_define();
static int def_is_done();
static int is_defined(const char*name);
static int macro_needs_args();
static int macro_needs_args(const char*name);
static void macro_start_args();
static void macro_add_to_arg();
static void macro_finish_arg();
@@ -72,10 +72,15 @@ struct include_stack_t
*/
int ebs;
int stringify_flag;
unsigned lineno;
YY_BUFFER_STATE yybs;
struct include_stack_t* next;
/* A single line comment can be associated with this include. */
char* comment;
};
static void emit_pathline(struct include_stack_t* isp);
@@ -86,6 +91,8 @@ static void emit_pathline(struct include_stack_t* isp);
*/
static struct include_stack_t* file_queue = 0;
static int do_expand_stringify_flag = 0;
/*
* The istack is the inclusion stack.
*/
@@ -111,7 +118,7 @@ static void ifdef_enter(void)
struct ifdef_stack_t*cur;
cur = (struct ifdef_stack_t*) calloc(1, sizeof(struct ifdef_stack_t));
cur->path = strdup(istack->path);
if (istack->path) cur->path = strdup(istack->path);
cur->lineno = istack->lineno;
cur->next = ifdef_stack;
@@ -127,8 +134,10 @@ static void ifdef_leave(void)
cur = ifdef_stack;
ifdef_stack = cur->next;
if (strcmp(istack->path,cur->path) != 0)
{
/* If either path is from a non-file context e.g.(macro expansion)
* we assume that the non-file part is from this file. */
if (istack->path != NULL && cur->path != NULL &&
strcmp(istack->path,cur->path) != 0) {
fprintf
(
stderr,
@@ -245,7 +254,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
}
<PCOMENT>`[a-zA-Z][a-zA-Z0-9_$]* {
if (macro_needs_args()) yy_push_state(MA_START); else do_expand(0);
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
}
/* Strings do not contain preprocessor directives, but can expand
@@ -262,21 +271,6 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<CSTRING>\" { BEGIN(string_enter); ECHO; }
<CSTRING>. { ECHO; }
<CSTRING>`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
}
<CSTRING>`[a-zA-Z][a-zA-Z0-9_$]* {
if (macro_needs_args()) yy_push_state(MA_START); else do_expand(0);
}
/* This set of patterns matches the include directive and the name
* that follows it. when the directive ends, the do_include function
* performs the include operation.
@@ -295,7 +289,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
}
<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* {
if (macro_needs_args()) yy_push_state(MA_START); else do_expand(0);
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
}
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
@@ -304,9 +298,10 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
/* Catch single-line comments that share the line with an include
* directive. And while I'm at it, I might as well preserve the
* comment in the output stream.
* comment in the output stream. This will be printed after the
* file has been included.
*/
<PPINCLUDE>"//"[^\r\n]* { ECHO; }
<PPINCLUDE>"//"[^\r\n]* { standby->comment = strdup(yytext); }
/* These finish the include directive (EOF or EOL) so I revert the
* lexor state and execute the inclusion.
@@ -551,12 +546,23 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
/* This pattern notices macros and arranges for them to be replaced. */
`[a-zA-Z_][a-zA-Z0-9_$]* {
if (macro_needs_args())
if (macro_needs_args(yytext+1))
yy_push_state(MA_START);
else
do_expand(0);
}
/* Stringified version of macro expansion. */
``[a-zA-Z_][a-zA-Z0-9_$]* {
assert(do_expand_stringify_flag == 0);
do_expand_stringify_flag = 1;
fputc('"', yyout);
if (macro_needs_args(yytext+2))
yy_push_state(MA_START);
else
do_expand(0);
}
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
<MA_START>{W} {}
@@ -696,7 +702,7 @@ static int is_defined(const char*name)
* These variables are also used for storing the actual arguments when
* a macro is instantiated.
*/
#define MAX_DEF_ARG 256 // allows argument IDs to be stored in a single char
#define MAX_DEF_ARG 256 /* allows argument IDs to be stored in a single char */
#define DEF_BUF_CHUNK 256
@@ -705,14 +711,14 @@ static int def_buf_size = 0;
static int def_buf_free = 0;
static int def_argc = 0;
static int def_argo[MAX_DEF_ARG]; // offset of first character in arg
static int def_argl[MAX_DEF_ARG]; // length of arg string.
static int def_argo[MAX_DEF_ARG]; /* offset of first character in arg */
static int def_argl[MAX_DEF_ARG]; /* length of arg string. */
/*
* Return a pointer to the start of argument 'arg'. Returned pointers
* may go stale after a call to def_buf_grow_to_fit.
*/
static inline char* def_argv(int arg)
static /* inline */ char* def_argv(int arg)
{
return def_buf + def_argo[arg];
}
@@ -827,6 +833,21 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
}
}
static void free_macro(struct define_t* def)
{
if (def == 0) return;
free_macro(def->left);
free_macro(def->right);
free(def->name);
free(def->value);
free(def);
}
void free_macros()
{
free_macro(def_table);
}
/*
* The do_define function accumulates the defined value in these
* variables. When the define is over, the def_finish() function
@@ -856,6 +877,7 @@ static int define_continue_flag = 0;
static char *find_arg(char*ptr, char*head, char*arg)
{
char *cp = ptr;
size_t len = strlen(arg);
while (1) {
/* Look for a candidate match, just return if none is found. */
@@ -866,7 +888,8 @@ static char *find_arg(char*ptr, char*head, char*arg)
* match is not in the middle of another identifier.
*/
if (cp != head &&
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$')) {
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' ||
isalnum(*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) {
cp++;
continue;
}
@@ -941,7 +964,7 @@ static void do_define()
}
/* Detect the continuation sequence. If I find it, remove it
* and the white space that preceeds it, then replace all that
* and the white space that precedes it, then replace all that
* with a single newline.
*/
if ((cp > yytext) && (cp[-1] == '\\'))
@@ -1171,16 +1194,16 @@ static void def_undefine()
*/
static struct define_t* cur_macro = 0;
static int macro_needs_args()
static int macro_needs_args(const char*text)
{
cur_macro = def_lookup(yytext+1);
cur_macro = def_lookup(text);
if (cur_macro)
return (cur_macro->argc > 1);
else
{
emit_pathline(istack);
fprintf(stderr, "warning: macro %s undefined (and assumed null) at this point.\n", yytext);
fprintf(stderr, "warning: macro %s undefined (and assumed null) at this point.\n", text);
return 0;
}
}
@@ -1348,6 +1371,8 @@ static void do_expand(int use_args)
isp = (struct include_stack_t*) calloc(1, sizeof(struct include_stack_t));
isp->stringify_flag = do_expand_stringify_flag;
do_expand_stringify_flag = 0;
if (use_args)
{
isp->str = &exp_buf[head];
@@ -1364,6 +1389,11 @@ static void do_expand(int use_args)
istack = isp;
yy_switch_to_buffer(yy_create_buffer(istack->file, YY_BUF_SIZE));
} else {
if (do_expand_stringify_flag) {
do_expand_stringify_flag = 0;
fputc('"', yyout);
}
}
}
@@ -1407,6 +1437,7 @@ static void include_filename()
standby->path = strdup(yytext+1);
standby->path[strlen(standby->path)-1] = 0;
standby->lineno = 0;
standby->comment = NULL;
}
static void do_include()
@@ -1446,6 +1477,8 @@ static void do_include()
if ((standby->file = fopen(path, "r")))
{
/* Free the original path before we overwrite it. */
free(standby->path);
standby->path = strdup(path);
goto code_that_switches_buffers;
}
@@ -1457,13 +1490,17 @@ static void do_include()
code_that_switches_buffers:
/* Clear the current files path from the search list. */
include_dir[0] = 0;
if(depend_file)
fprintf(depend_file, "%s\n", standby->path);
if (line_direct_flag)
fprintf(yyout, "\n`line %u \"%s\" 1\n", istack->lineno+1, standby->path);
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
standby->next = istack;
standby->stringify_flag = 0;
istack->yybs = YY_CURRENT_BUFFER;
istack = standby;
@@ -1518,6 +1555,17 @@ static int load_next_input()
/* Delete the current input buffers, and free the cell. */
yy_delete_buffer(YY_CURRENT_BUFFER);
/* If there was a comment for this include print it before we
* return to the previous input stream. This technically belongs
* to the previous stream, but it should not create any problems
* since it is only a comment.
*/
if (isp->comment) {
fprintf(yyout, "%s\n", isp->comment);
free(isp->comment);
isp->comment = NULL;
}
if (isp->file)
{
free(isp->path);
@@ -1537,6 +1585,10 @@ static int load_next_input()
exp_buf_free += isp->ebs;
}
if (isp->stringify_flag) {
fputc('"', yyout);
}
free(isp);
/* If I am out of include stack, the main input is
@@ -1572,6 +1624,12 @@ static int load_next_input()
if(depend_file)
fprintf(depend_file, "%s\n", istack->path);
/* This works around an issue in flex yyrestart() where it
* uses yyin to create a new buffer when one does not exist.
* I would have assumed that it would use the file argument.
* The problem is that we have deleted the buffer and freed
* yyin (isp->file) above. */
yyin = 0;
yyrestart(istack->file);
return 1;
}
@@ -1604,7 +1662,11 @@ static int load_next_input()
static void do_dump_precompiled_defines(FILE* out, struct define_t* table)
{
if (!table->keyword)
#ifdef __MINGW32__ /* MinGW does not know about z. */
fprintf(out, "%s:%d:%d:%s\n", table->name, table->argc, strlen(table->value), table->value);
#else
fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value);
#endif
if (table->left)
do_dump_precompiled_defines(out, table->left);
@@ -1699,6 +1761,8 @@ void reset_lexor(FILE* out, char* paths[])
isp->str = 0;
isp->ebs = 0;
isp->lineno = 0;
isp->stringify_flag = 0;
isp->comment = NULL;
if (isp->file == 0)
{
@@ -1728,6 +1792,8 @@ void reset_lexor(FILE* out, char* paths[])
isp->ebs = 0;
isp->next = 0;
isp->lineno = 0;
isp->stringify_flag = 0;
isp->comment = NULL;
if (tail)
tail->next = isp;
@@ -1737,3 +1803,17 @@ void reset_lexor(FILE* out, char* paths[])
tail = isp;
}
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
# endif
}
+33 -9
View File
@@ -17,7 +17,8 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "config.h"
# include "version.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@@ -35,8 +36,6 @@ const char NOTICE[] =
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
const char VERSION[] = "$Name: $ $State: Exp $";
# include <stdio.h>
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
@@ -103,6 +102,8 @@ static int flist_read_flags(const char*path)
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
/* Remove trailing white space. */
char*tail = cp + strlen(cp);
char*arg;
while (tail > cp) {
if (! isspace(tail[-1]))
break;
@@ -118,7 +119,7 @@ static int flist_read_flags(const char*path)
continue;
/* The arg points to the argument to the keyword. */
char*arg = strchr(cp, ':');
arg = strchr(cp, ':');
if (arg) *arg++ = 0;
if (strcmp(cp,"D") == 0) {
@@ -188,12 +189,14 @@ static int flist_read_names(const char*path)
add_source_file(cp);
}
fclose(fd);
return 0;
}
int main(int argc, char*argv[])
{
int opt, idx;
unsigned lp;
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
@@ -229,7 +232,7 @@ int main(int argc, char*argv[])
include_dir[0] = 0; /* 0 is reserved for the current files path. */
include_dir[1] = strdup(".");
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
@@ -282,14 +285,21 @@ int main(int argc, char*argv[])
fclose(src);
break;
}
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
VERSION);
fprintf(stderr, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stderr, "%s\n", COPYRIGHT);
fputs(NOTICE, stderr);
break;
case 'V':
fprintf(stdout, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stdout, "%s\n", COPYRIGHT);
fputs(NOTICE, stdout);
return 0;
default:
flag_errors += 1;
break;
@@ -304,7 +314,8 @@ int main(int argc, char*argv[])
" -o<fil> - Send the output to <fil>\n"
" -p<fil> - Write precompiled defines to <fil>\n"
" -P<fil> - Read precompiled defines from <fil>\n"
" -v - Print version information\n",
" -v - Verbose\n"
" -V - Print version information and quit\n",
argv[0]);
return flag_errors;
}
@@ -359,6 +370,7 @@ int main(int argc, char*argv[])
start scanning. */
reset_lexor(out, source_list);
if (yylex()) return -1;
destroy_lexor();
if(depend_file) {
fclose(depend_file);
@@ -369,5 +381,17 @@ int main(int argc, char*argv[])
fclose(precomp_out);
}
/* Free the source and include directory lists. */
for (lp = 0; lp < source_cnt; lp += 1) {
free(source_list[lp]);
}
free(source_list);
for (lp = 0; lp < include_cnt; lp += 1) {
free(include_dir[lp]);
}
free(include_dir);
free_macros();
return error_count;
}
+138 -22
View File
@@ -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
@@ -83,7 +84,10 @@ static int dec_buf_div2(char *buf);
static void process_timescale(const char*txt);
static list<int> keyword_mask_stack;
static int comment_enter;
static bool in_module = false;
%}
%x CCOMMENT
@@ -93,10 +97,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(); }
@@ -116,8 +124,8 @@ W [ \t\b\f\r]+
/* The contents of C-style comments are ignored, like white space. */
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
<CCOMMENT>. { yymore(); }
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
<CCOMMENT>. { ; }
<CCOMMENT>\n { yylloc.first_line += 1; }
<CCOMMENT>"*/" { BEGIN(comment_enter); }
@@ -146,6 +154,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
@@ -215,26 +224,36 @@ W [ \t\b\f\r]+
rc = PATHPULSE_IDENTIFIER;
break;
case K_bool:
case K_logic:
case K_wone:
if (! gn_cadence_types_enabled()) {
yylval.text = strdupnew(yytext);
rc = IDENTIFIER;
} else {
yylval.text = 0;
}
break;
case K_edge:
BEGIN(EDGES);
break;
case K_module:
case K_macromodule:
in_module = true;
break;
case K_endmodule:
in_module = false;
break;
default:
yylval.text = 0;
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,ivl_discipline_t>::iterator cur = disciplines.find(tmp);
if (cur != disciplines.end()) {
yylval.discipline = (*cur).second;
rc = DISCIPLINE_IDENTIFIER;
}
}
return rc;
}
@@ -280,6 +299,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; }
@@ -294,6 +353,12 @@ W [ \t\b\f\r]+
^{W}?`timescale { BEGIN(PPTIMESCALE); }
<PPTIMESCALE>.* { process_timescale(yytext); }
<PPTIMESCALE>\n {
if (in_module) {
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
"`timescale directive can not be inside a module "
"definition." << endl;
error_count += 1;
}
yylloc.first_line += 1;
BEGIN(0); }
@@ -321,6 +386,57 @@ W [ \t\b\f\r]+
^{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
rule collects the rest of the line and processes it. We only need
@@ -339,7 +455,7 @@ W [ \t\b\f\r]+
} else {
cerr << yylloc.text << ":" << yylloc.first_line
<< " error: Net type " << yytext
<< ": error: Net type " << yytext
<< " is not a valid (and supported)"
<< " default net type." << endl;
net_type = NetNet::WIRE;
@@ -357,37 +473,37 @@ W [ \t\b\f\r]+
^{W}?`define{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `define not supported. Use an external preprocessor."
": warning: `define not supported. Use an external preprocessor."
<< endl;
}
^{W}?`else{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `else not supported. Use an external preprocessor."
": warning: `else not supported. Use an external preprocessor."
<< endl;
}
^{W}?`endif{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `endif not supported. Use an external preprocessor."
": warning: `endif not supported. Use an external preprocessor."
<< endl;
}
^{W}?`ifdef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `ifdef not supported. Use an external preprocessor."
": warning: `ifdef not supported. Use an external preprocessor."
<< endl;
}
^`include{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `include not supported. Use an external preprocessor."
": warning: `include not supported. Use an external preprocessor."
<< endl;
}
^`undef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `undef not supported. Use an external preprocessor."
": warning: `undef not supported. Use an external preprocessor."
<< endl;
}
@@ -743,7 +859,7 @@ static verinum*make_unsized_dec(const char*ptr)
if (ptr[0] == '\'') {
/* The number has decorations of the form 'sd<digits>,
possibly with space between the d and the <digits>.
Also, the 's' is optional, and markes the number as
Also, the 's' is optional, and marks the number as
signed. */
ptr += 1;
+161 -111
View File
@@ -6,127 +6,177 @@
#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
automatic, GN_KEYWORDS_1364_2001, K_automatic
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;
}
+3 -3
View File
@@ -89,12 +89,12 @@ distclean: clean
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
$(libdir)/libveriuser.a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(DESTDIR)$(libdir)/libveriuser.a
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
$(srcdir)/mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)
uninstall::
rm -f $(libdir)/libveriuser.a
rm -f $(DESTDIR)$(libdir)/libveriuser.a
-include $(patsubst %.o, dep/%.d, $O)
+1 -1
View File
@@ -99,7 +99,7 @@ PLI_INT32 acc_fetch_fulltype(handle obj)
return accTopModule;
else
return accModuleInstance;
// FIXME accCellInstance
/* FIXME accCellInstance */
case vpiNamedEvent: return accNamedEvent;
+1 -1
View File
@@ -55,7 +55,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
* rescan all the items up to the previous one, then return
* the next one.
*/
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
iter = vpi_iterate(vpiScope, scope); /* ICARUS extension */
if (prev) {
while ((hand = vpi_scan(iter))) {
if (hand == prev) break;
+1 -1
View File
@@ -35,7 +35,7 @@ int acc_object_of_type(handle object, PLI_INT32 type)
if (pli_trace) {
fprintf(pli_trace, "acc_object_of_type(%p \"%s\", %d)",
object, vpi_get_str(vpiName, object), type);
object, vpi_get_str(vpiName, object), type);
fflush(pli_trace);
}
+1 -1
View File
@@ -366,7 +366,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
s_cb_data cb;
s_vpi_time ti = {vpiSimTime};
// Scale delay to SimTime
/* Scale delay to SimTime */
ivl_u64_t delay = ((dly
* pow(10, tf_gettimeprecision() - tf_gettimeunit()))
+ 0.5);
+5 -4
View File
@@ -60,8 +60,9 @@ bool Nexus::drivers_constant() const
if (cur_dir == Link::PASSIVE) {
const NetObj*obj = cur->get_obj();
if (obj->scope()->parent() != 0)
const NetPins*obj = cur->get_obj();
const NetObj*as_obj = dynamic_cast<const NetObj*>(obj);
if (as_obj == 0 || as_obj->scope()->parent() != 0)
continue;
sig = dynamic_cast<const NetNet*>(cur->get_obj());
@@ -80,8 +81,8 @@ bool Nexus::drivers_constant() const
/* If there is a supply net, then this nexus will have a
constant value independent of any drivers. */
if (const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj()))
switch (sig->type()) {
if (const NetNet*s = dynamic_cast<const NetNet*>(cur->get_obj()))
switch (s->type()) {
case NetNet::SUPPLY0:
driven_ = V0;
return true;
+162 -46
View File
@@ -20,6 +20,7 @@ const char COPYRIGHT[] =
*/
# include "config.h"
# include "version.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@@ -54,9 +55,12 @@ const char NOTICE[] =
#endif
# include "pform.h"
# include "parse_api.h"
# include "PGenerate.h"
# include "netlist.h"
# include "target.h"
# include "compiler.h"
# include "discipline.h"
# include "t-dll.h"
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt);
@@ -73,21 +77,19 @@ extern "C" const char*optarg;
/* Count errors detected in flag processing. */
unsigned flag_errors = 0;
const char VERSION[] = "$Name: $";
const char*basedir = ".";
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 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;
@@ -121,6 +123,9 @@ bool debug_scopes = false;
bool debug_eval_tree = false;
bool debug_elaborate = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
bool debug_automatic = false;
/*
* Verbose messages enabled.
*/
@@ -155,9 +160,6 @@ extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*);
static struct net_func_map {
@@ -169,9 +171,6 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@@ -197,14 +196,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;
@@ -214,10 +229,16 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} 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;
@@ -245,6 +266,9 @@ static void parm_to_flagmap(const string&flag)
flags[key] = value;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
/*
* Read the contents of a config file. This file is a temporary
* configuration file made by the compiler driver to carry the bulky
@@ -268,7 +292,7 @@ static void parm_to_flagmap(const string&flag)
* -T:<min/typ/max>
* Select which expression to use.
*
* -t:<target>
* -t:<target> (obsolete)
* Usually, "-t:dll"
*
* basedir:<path>
@@ -366,6 +390,11 @@ 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 if (strcmp(cp,"automatic") == 0) {
debug_automatic = true;
} else {
}
@@ -455,7 +484,7 @@ static void read_iconfig_file(const char*ipath)
library_suff.push_back(strdup(cp));
} else if (strcmp(buf,"-t") == 0) {
target = strdup(cp);
// NO LONGER USED
} else if (strcmp(buf,"-T") == 0) {
if (strcmp(cp,"min") == 0) {
@@ -505,6 +534,7 @@ int main(int argc, char*argv[])
{
bool help_flag = false;
bool times_flag = false;
bool version_flag = false;
const char* net_path = 0;
const char* pf_path = 0;
@@ -548,10 +578,8 @@ int main(int argc, char*argv[])
# endif
break;
case 'V':
cout << "Icarus Verilog version " << VERSION << endl;
cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl;
return 0;
version_flag = true;
break;
default:
flag_errors += 1;
break;
@@ -560,8 +588,20 @@ int main(int argc, char*argv[])
if (flag_errors)
return flag_errors;
if (version_flag) {
cout << "\n\nIcarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl;
cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl;
dll_target_obj.test_version(flags["DLL"]);
return 0;
}
if (help_flag) {
cout << "Icarus Verilog version " << VERSION << endl <<
cout << "Icarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl <<
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
@@ -592,6 +632,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)
@@ -605,11 +668,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
@@ -620,6 +686,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;
}
@@ -628,6 +699,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,ivl_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()
@@ -658,15 +739,7 @@ int main(int argc, char*argv[])
for (mod = pform_modules.begin()
; mod != pform_modules.end()
; mod++) {
list<PGate*> gates = (*mod).second->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); gate++) {
PGModule *mod = dynamic_cast<PGModule*>(*gate);
if (mod) {
// Note that this module has been instantiated
mentioned_p[mod->get_type()] = true;
}
}
find_module_mention(mentioned_p, mod->second);
}
for (mod = pform_modules.begin()
@@ -754,6 +827,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;
@@ -778,20 +856,21 @@ int main(int argc, char*argv[])
}
if (verbose_flag) {
cout << "CODE GENERATION -t "<<target<< endl;
cout << "CODE GENERATION" << endl;
}
int emit_rc;
emit_rc = emit(des, target);
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
if (int emit_rc = des->emit(&dll_target_obj)) {
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
assert(emit_rc);
}
if (verbose_flag) {
@@ -831,3 +910,40 @@ int main(int argc, char*argv[])
return des? des->errors : 1;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*mod)
{
list<PGate*> gates = mod->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); gate++) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = mod->generate_schemes.begin()
; cur != mod->generate_schemes.end() ; cur ++) {
find_module_mention(check_map, *cur);
}
}
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*schm)
{
list<PGate*>::const_iterator gate;
for (gate = schm->gates.begin(); gate != schm->gates.end(); gate++) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = schm->generate_schemes.begin()
; cur != schm->generate_schemes.end() ; cur ++) {
find_module_mention(check_map, *cur);
}
}
+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>
+37
View File
@@ -0,0 +1,37 @@
/*
* 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 <typeinfo>
# include <cstdlib>
# include <climits>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
NetContribution::NetContribution(NetExpr*l, NetExpr*r)
: lval_(l), rval_(r)
{
}
NetContribution::~NetContribution()
{
}
+26 -36
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_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -84,6 +81,11 @@ unsigned NetAssign_::lwidth() const
return lwid_;
}
ivl_variable_type_t NetAssign_::expr_type() const
{
return sig_->data_type();
}
perm_string NetAssign_::name() const
{
if (sig_) {
@@ -212,15 +214,34 @@ NetAssign::~NetAssign()
{
}
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv)
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev, NetExpr*cnt)
: NetAssignBase(lv, rv)
{
event_ = ev;
count_ = cnt;
}
NetAssignNB::~NetAssignNB()
{
}
unsigned NetAssignNB::nevents() const
{
if (event_) return event_->nevents();
return 0;
}
const NetEvent*NetAssignNB::event(unsigned idx) const
{
if (event_) return event_->event(idx);
return 0;
}
const NetExpr*NetAssignNB::get_count() const
{
return count_;
}
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
@@ -256,34 +277,3 @@ NetRelease::NetRelease(NetAssign_*l)
NetRelease::~NetRelease()
{
}
/*
* $Log: net_assign.cc,v $
* Revision 1.22 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.21 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* 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: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.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
*
* Revision 1.17 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*/
+409 -160
View File
@@ -20,6 +20,8 @@
# include "config.h"
# include <iostream>
# include <set>
# include <cstdlib>
/*
* This source file contains all the implementations of the Design
@@ -31,9 +33,10 @@
# include "compiler.h"
# include "netmisc.h"
# include <sstream>
# include "ivl_assert.h"
Design:: Design()
: errors(0), nodes_(0), procs_(0), lcounter_(0)
: errors(0), nodes_(0), procs_(0), aprocs_(0), lcounter_(0)
{
procs_idx_ = 0;
des_precision_ = 0;
@@ -206,10 +209,12 @@ void NetScope::run_defparams(Design*des)
}
}
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
NetExpr*val = (*pp).second;
pform_name_t path = (*pp).first;
while (! defparams.empty()) {
pair<pform_name_t,NetExpr*> pp = defparams.front();
defparams.pop_front();
pform_name_t path = pp.first;
NetExpr*val = pp.second;
perm_string perm_name = peek_tail_name(path);
path.pop_back();
@@ -220,11 +225,20 @@ void NetScope::run_defparams(Design*des)
is the current scope. */
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
cerr << val->get_fileline() << ": warning: scope of " <<
path << "." << perm_name << " not found." << endl;
// Push the defparam onto a list for retry
// later. It is possible for the scope lookup to
// fail if the scope being defparam'd into is
// generated by an index array for generate.
eval_path.push_back(hname_t(perm_name));
defparams_later.push_back(make_pair(eval_path,val));
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(perm_name, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
@@ -233,6 +247,66 @@ void NetScope::run_defparams(Design*des)
}
}
// If some of the defparams didn't find a scope in the name,
// then try again later. It may be that the target scope is
// created later by generate scheme or instance array.
if (! defparams_later.empty())
des->defparams_later.insert(this);
}
void NetScope::run_defparams_later(Design*des)
{
set<NetScope*> target_scopes;
list<pair<list<hname_t>,NetExpr*> > defparams_even_later;
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
defparams_later.pop_front();
list<hname_t>eval_path = cur.first;
perm_string name = eval_path.back().peek_name();
eval_path.pop_back();
NetExpr*val = cur.second;
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
// If a scope in the target path is not found,
// then push this defparam for handling even
// later. Maybe a later generate scheme or
// instance array will create the scope.
defparams_even_later.push_back(cur);
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(name, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< name << " not found in "
<< scope_path(targ_scope) << "." << endl;
}
// We'll need to re-evaluate parameters in this scope
target_scopes.insert(targ_scope);
}
// All the scopes that this defparam set touched should have
// their parameters re-evaluated.
for (set<NetScope*>::iterator cur = target_scopes.begin()
; cur != target_scopes.end() ; cur ++ )
(*cur)->evaluate_parameters(des);
// If there are some scopes that still have missing scopes,
// then sav them back into the defparams_later list for a
// later pass.
defparams_later = defparams_even_later;
if (! defparams_later.empty())
des->defparams_later.insert(this);
}
void Design::evaluate_parameters()
@@ -242,180 +316,339 @@ void Design::evaluate_parameters()
(*scope)->evaluate_parameters(this);
}
void NetScope::evaluate_parameters(Design*des)
void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
{
NetScope*cur = sub_;
while (cur) {
cur->evaluate_parameters(des);
cur = cur->sib_;
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;
if (expr == NULL) return; // This is an invalid parameter so return.
eval_expr(expr);
/* The eval_expr may delete and 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;
/* If we have a real value convert it to an integer. */
if(NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
verinum nval(tmp->value().as_long64());
expr = new NetEConst(nval);
expr->set_line(*((*cur).second.expr));
(*cur).second.expr = expr;
}
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);
(*cur).second.expr = 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*curs = sub_;
while (curs) {
curs->evaluate_parameters(des);
curs = curs->sib_;
}
if (debug_scopes)
cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl;
// Evaluate the parameter values. The parameter expressions
// have already been elaborated and replaced by the scope
// 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;
}
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. 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*>((*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;
}
}
}
void Design::residual_defparams()
{
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); scope++)
(*scope)->residual_defparams(this);
}
void NetScope::residual_defparams(Design*des)
{
// Clean out the list of defparams that never managed to match
// a scope. Print a warning for each.
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
defparams_later.pop_front();
cerr << cur.second->get_fileline() << ": warning: "
<< "Scope of " << cur.first << " not found." << endl;
}
NetScope*cur = sub_;
while (cur) {
cur->residual_defparams(des);
cur = cur->sib_;
}
}
const char* Design::get_flag(const string&key) const
{
map<string,const char*>::const_iterator tmp = flags_.find(key);
@@ -531,6 +764,11 @@ void Design::add_process(NetProcTop*pro)
procs_ = pro;
}
void Design::add_process(NetAnalogTop*pro)
{
pro->next_ = aprocs_;
aprocs_ = pro;
}
void Design::delete_process(NetProcTop*top)
{
assert(top);
@@ -553,3 +791,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_);
}
+7 -3
View File
@@ -173,6 +173,12 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
if (tmp == this)
continue;
/* For automatic tasks, the VVP runtime holds state for events
in the automatically allocated context. This means we can't
merge similar events in different automatic tasks. */
if (scope()->is_auto() && (tmp->scope() != scope()))
continue;
if ((*idx).second != probe_count)
continue;
@@ -251,7 +257,6 @@ NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
{
for (unsigned idx = 0 ; idx < p ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("P"), idx);
}
enext_ = event_->probes_;
@@ -299,7 +304,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
Nexus*nex = pin(0).nexus();
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
NetObj*obj = lcur->get_obj();
NetPins*obj = lcur->get_obj();
if (obj->pin_count() != pin_count())
continue;
@@ -554,4 +559,3 @@ NetProc* NetEvWait::statement()
* Simulate named event trigger and waits.
*
*/
+94 -39
View File
@@ -35,8 +35,8 @@ ivl_variable_type_t NetExpr::expr_type() const
* Create an add/sub node from the two operands. Make a best guess of
* the
*/
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
: NetEBinary(op, l, r)
NetEBAdd::NetEBAdd(char op__, NetExpr*l, NetExpr*r, bool lossless_flag)
: NetEBinary(op__, l, r)
{
NetEConst* tmp;
@@ -56,40 +56,51 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
&& (! tmp->has_width())
&& (tmp->expr_width() > l->expr_width() || integer_width > l->expr_width()) ) {
unsigned target_width = l->expr_width() + 1;
verinum tmp_v = trim_vnum(tmp->value());
unsigned target_width = l->expr_width();
if (target_width < tmp_v.len())
target_width = tmp_v.len();
if (lossless_flag)
target_width += 1;
if (target_width < integer_width)
target_width = integer_width;
r->set_width(target_width);
/* Note: This constant value will not gain a defined
width from this. Make sure. */
assert(! r->has_width() );
expr_width(target_width);
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
&& (! tmp->has_width())
&& (tmp->expr_width() > r->expr_width() || integer_width > r->expr_width()) ) {
unsigned target_width = r->expr_width() + 1;
verinum tmp_v = trim_vnum(tmp->value());
unsigned target_width = r->expr_width();
if (target_width < tmp_v.len())
target_width = tmp_v.len();
if (lossless_flag)
target_width += 1;
if (target_width < integer_width)
target_width = integer_width;
l->set_width(target_width);
/* Note: This constant value will not gain a defined
width from this. Make sure. */
assert(! l->has_width() );
}
expr_width(target_width);
unsigned pad_width = lossless_flag? 1 : 0;
/* 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. */
if (r->expr_width() > l->expr_width()) {
expr_width(r->expr_width() + pad_width);
} else if (r->expr_width() > l->expr_width()) {
unsigned loss_pad = lossless_flag? 1 : 0;
expr_width(r->expr_width() + loss_pad);
} else {
expr_width(l->expr_width() + pad_width);
unsigned loss_pad = lossless_flag? 1 : 0;
expr_width(l->expr_width() + loss_pad);
}
cast_signed(l->has_sign() && r->has_sign());
@@ -125,9 +136,12 @@ ivl_variable_type_t NetEBAdd::expr_type() const
* expression. Otherwise, the netlist will have to allow the
* expressions to have different widths.
*/
NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
NetEBComp::NetEBComp(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
{
// The output of compare is always unsigned.
cast_signed_base_(false);
if (NetEConst*tmp = dynamic_cast<NetEConst*>(r)) do {
if (tmp->has_width())
@@ -186,8 +200,8 @@ ivl_variable_type_t NetEBComp::expr_type() const
return IVL_VT_BOOL;
}
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
NetEBDiv::NetEBDiv(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
{
unsigned w = l->expr_width();
if (r->expr_width() > w)
@@ -219,18 +233,39 @@ ivl_variable_type_t NetEBDiv::expr_type() const
return IVL_VT_LOGIC;
}
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
NetEBMinMax::NetEBMinMax(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
{
expr_width(l->expr_width() + r->expr_width());
cast_signed(l->has_sign() && r->has_sign());
expr_width( max(l->expr_width(), r->expr_width()) );
cast_signed(l->has_sign() || r->has_sign());
}
/* If it turns out that this is not a signed expression, then
cast the signedness out of the operands as well. */
if (! has_sign()) {
l->cast_signed(false);
r->cast_signed(false);
}
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)
{
if (expr_type() == IVL_VT_REAL)
expr_width(1);
else
expr_width(l->expr_width() + r->expr_width());
if (expr_type() == IVL_VT_REAL)
cast_signed(true);
else
cast_signed(l->has_sign() && r->has_sign());
}
NetEBMult::~NetEBMult()
@@ -255,10 +290,10 @@ ivl_variable_type_t NetEBMult::expr_type() const
return IVL_VT_LOGIC;
}
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
NetEBPow::NetEBPow(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
{
assert(op == 'p');
assert(op__ == 'p');
/* 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());
@@ -282,21 +317,17 @@ ivl_variable_type_t NetEBPow::expr_type() const
return IVL_VT_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->has_sign())
return IVL_VT_REAL;
if (right_->has_sign())
return IVL_VT_REAL;
return IVL_VT_LOGIC;
}
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
NetEBShift::NetEBShift(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
{
expr_width(l->expr_width());
// The >>> is signed if the left operand is signed.
if (op == 'R') cast_signed(l->has_sign());
if (op__ == 'R') cast_signed(l->has_sign());
}
NetEBShift::~NetEBShift()
@@ -456,7 +487,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)
{
}
@@ -469,9 +505,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;
}
@@ -558,3 +599,17 @@ ivl_variable_type_t NetESFunc::expr_type() const
{
return type_;
}
NetEAccess::NetEAccess(NetBranch*br, nature_t*nat)
: branch_(br), nature_(nat)
{
}
NetEAccess::~NetEAccess()
{
}
ivl_variable_type_t NetEAccess::expr_type() const
{
return IVL_VT_REAL;
}
-82
View File
@@ -1,82 +0,0 @@
/*
* Copyright (c) 2000-2004 Stephen Williams (steve@picturel.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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
/*
* This file contains implementation of the NetForce, NetRelease,
* NetCAssign and NetDeassign classes. These are similar or related in
* that they handle the procedural continuous assign and force
* statements.
*/
# include "netlist.h"
# include <assert.h>
/*
* $Log: net_force.cc,v $
* Revision 1.13 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.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.11 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.10 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.9 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
* Revision 1.8 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.7 2002/01/19 19:02:08 steve
* Pass back target errors processing conditionals.
*
* Revision 1.6 2001/11/14 03:28:49 steve
* DLL target support for force and release.
*
* Revision 1.5 2001/10/31 05:24:52 steve
* ivl_target support for assign/deassign.
*
* Revision 1.4 2001/10/28 01:14:53 steve
* NetObj constructor finally requires a scope.
*
* Revision 1.3 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.2 2000/05/12 01:22:41 steve
* NetCAssign needs to incr_eref its lval to lock it down.
*
* Revision 1.1 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
*/
+10 -14
View File
@@ -34,12 +34,10 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
def_(d)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(def_->basename(), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
@@ -51,36 +49,36 @@ NetUserFunc::~NetUserFunc()
ivl_variable_type_t NetUserFunc::data_type(unsigned port) const
{
NetFuncDef*def = def_->func_def();
NetFuncDef*fdef = def_->func_def();
/* Port 0 is the return port. */
if (port == 0) {
const NetNet*sig = def->return_sig();
const NetNet*sig = fdef->return_sig();
assert(sig);
return sig->data_type();
}
port -= 1;
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
assert(port < fdef->port_count());
const NetNet*port_sig = fdef->port(port);
return port_sig->data_type();
}
unsigned NetUserFunc::port_width(unsigned port) const
{
NetFuncDef*def = def_->func_def();
NetFuncDef*fdef = def_->func_def();
/* Port 0 is the return port. */
if (port == 0) {
const NetNet*sig = def->return_sig();
const NetNet*sig = fdef->return_sig();
assert(sig);
return sig->vector_width();
}
port -= 1;
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
assert(port < fdef->port_count());
const NetNet*port_sig = fdef->port(port);
return port_sig->vector_width();
}
@@ -104,7 +102,7 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
1 nil pointer. This is how the parser tells me of no
parameter. In other words, ``func()'' is 1 nil parameter. */
unsigned parms_count = parms_.count();
unsigned parms_count = parms_.size();
if ((parms_count == 1) && (parms_[0] == 0))
parms_count = 0;
@@ -135,13 +133,11 @@ NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
{
def_ = def;
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
pin(0).set_dir(Link::OUTPUT); // Q
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
+82 -34
View File
@@ -64,7 +64,7 @@ void connect(Link&l, Link&r)
Link::Link()
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
inst_(0), next_(0), nexus_(0)
next_(0), nexus_(0)
{
(new Nexus()) -> relink(this);
}
@@ -103,6 +103,11 @@ void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
nexus_->drivers_delays(rise, fall, decay);
}
void Link::drivers_drive(strength_t drive0__, strength_t drive1__)
{
nexus_->drivers_drive(drive0__, drive1__);
}
void Link::drive0(Link::strength_t str)
{
drive0_ = str;
@@ -134,16 +139,16 @@ verinum::V Link::get_init() const
}
void Link::cur_link(NetObj*&net, unsigned &pin)
void Link::cur_link(NetPins*&net, unsigned &pin)
{
net = node_;
pin = pin_;
net = get_obj();
pin = get_pin();
}
void Link::cur_link(const NetObj*&net, unsigned &pin) const
void Link::cur_link(const NetPins*&net, unsigned &pin) const
{
net = node_;
pin = pin_;
net = get_obj();
pin = get_pin();
}
void Link::unlink()
@@ -186,35 +191,30 @@ const Link* Link::next_nlink() const
return next_;
}
const NetObj*Link::get_obj() const
const NetPins*Link::get_obj() const
{
return node_;
if (pin_zero_)
return node_;
const Link*tmp = this - pin_;
assert(tmp->pin_zero_);
return tmp->node_;
}
NetObj*Link::get_obj()
NetPins*Link::get_obj()
{
return node_;
if (pin_zero_)
return node_;
Link*tmp = this - pin_;
assert(tmp->pin_zero_);
return tmp->node_;
}
unsigned Link::get_pin() const
{
return pin_;
}
void Link::set_name(perm_string n, unsigned i)
{
name_ = n;
inst_ = i;
}
perm_string Link::get_name() const
{
return name_;
}
unsigned Link::get_inst() const
{
return inst_;
if (pin_zero_)
return 0;
else
return pin_;
}
Nexus::Nexus()
@@ -247,19 +247,68 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
bool Nexus::drivers_present() const
{
assert(list_);
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() == Link::OUTPUT)
return true;
if (cur->get_dir() == Link::INPUT)
continue;
// Must be PASSIVE, so if it is some kind of net, see if
// it is the sort that might drive the nexus.
const NetPins*obj;
unsigned pin;
cur->cur_link(obj, pin);
if (const NetNet*net = dynamic_cast<const NetNet*>(obj))
switch (net->type()) {
case NetNet::SUPPLY0:
case NetNet::SUPPLY1:
case NetNet::TRI0:
case NetNet::TRI1:
case NetNet::WAND:
case NetNet::WOR:
case NetNet::TRIAND:
case NetNet::TRIOR:
case NetNet::REG:
return true;
default:
break;
}
}
return false;
}
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();
NetObj*obj = dynamic_cast<NetObj*>(cur->get_obj());
if (obj == 0)
continue;
obj->rise_time(rise);
obj->fall_time(fall);
obj->decay_time(decay);
}
}
void Nexus::drivers_drive(Link::strength_t drive0, Link::strength_t drive1)
{
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() != Link::OUTPUT)
continue;
cur->drive0(drive0);
cur->drive1(drive1);
}
}
void Nexus::unlink(Link*that)
{
if (name_) {
@@ -397,12 +446,11 @@ const char* Nexus::name() const
if (sig == 0) {
const Link*lnk = first_nlink();
const NetObj*obj = lnk->get_obj();
const NetObj*obj = dynamic_cast<const NetObj*>(lnk->get_obj());
pin = lnk->get_pin();
cerr << "internal error: No signal for nexus of " <<
obj->name() << " pin " << pin << "(" <<
lnk->get_name() << "<" << lnk->get_inst() << ">)"
" type=" << typeid(*obj).name() << "?" << endl;
cerr << "internal error: No signal for nexus of "
<< obj->name() << " pin " << pin
<< " type=" << typeid(*obj).name() << "?" << endl;
}
assert(sig);
+14 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2005 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_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
#endif
# include "config.h"
@@ -40,12 +37,9 @@ NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
: NetNode(s, n, 3),
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);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
}
NetModulo::~NetModulo()
@@ -72,6 +66,16 @@ Link& NetModulo::pin_Result()
return pin(0);
}
void NetModulo::set_signed(bool flag)
{
signed_flag_ = flag;
}
bool NetModulo::get_signed() const
{
return signed_flag_;
}
const Link& NetModulo::pin_Result() const
{
return pin(0);
@@ -96,25 +100,3 @@ const Link& NetModulo::pin_DataB() const
{
return pin(2);
}
/*
* $Log: net_modulo.cc,v $
* Revision 1.9 2005/09/15 22:54:47 steve
* Fix bug configuring NetModulo pins.
*
* Revision 1.8 2005/03/12 06:43:35 steve
* Update support for LPM_MOD.
*
* Revision 1.7 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.6 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.5 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/
+15 -2
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
@@ -53,8 +53,13 @@ NexusSet* NetEBinary::nex_input(bool rem_out)
NexusSet* NetEConcat::nex_input(bool rem_out)
{
if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
if (parms_[idx] == NULL) {
delete result;
return NULL;
}
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
@@ -62,6 +67,11 @@ NexusSet* NetEConcat::nex_input(bool rem_out)
return result;
}
NexusSet* NetEAccess::nex_input(bool rem_out)
{
return new NexusSet;
}
/*
* A constant has not inputs, so always return an empty set.
*/
@@ -98,6 +108,10 @@ NexusSet* NetESelect::nex_input(bool rem_out)
{
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
}
result->add(*tmp);
delete tmp;
return result;
@@ -381,4 +395,3 @@ NexusSet* NetWhile::nex_input(bool rem_out)
delete tmp;
return result;
}
+75 -44
View File
@@ -22,7 +22,9 @@
# 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
@@ -36,9 +38,9 @@
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
signals_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
if (up) {
default_nettype_ = up->default_nettype();
@@ -78,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;
}
@@ -109,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 genvar 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;
@@ -139,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;
}
@@ -171,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
{
@@ -208,6 +261,7 @@ NetFuncDef* NetScope::func_def()
assert( type_ == FUNC );
return func_;
}
bool NetScope::in_func()
{
return (type_ == FUNC) ? true : false;
@@ -222,7 +276,7 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n)
{
assert(type_ == MODULE);
module_name_ = n; /* NOTE: n mus have been permallocated. */
module_name_ = n; /* NOTE: n must have been permallocated. */
}
perm_string NetScope::module_name() const
@@ -305,30 +359,13 @@ NetEvent* NetScope::find_event(perm_string name)
void NetScope::add_signal(NetNet*net)
{
if (signals_ == 0) {
net->sig_next_ = net;
net->sig_prev_ = net;
} else {
net->sig_next_ = signals_->sig_next_;
net->sig_prev_ = signals_;
net->sig_next_->sig_prev_ = net;
net->sig_prev_->sig_next_ = net;
}
signals_ = net;
signals_map_[net->name()]=net;
}
void NetScope::rem_signal(NetNet*net)
{
assert(net->scope() == this);
if (signals_ == net)
signals_ = net->sig_prev_;
if (signals_ == net) {
signals_ = 0;
} else {
net->sig_prev_->sig_next_ = net->sig_next_;
net->sig_next_->sig_prev_ = net->sig_prev_;
}
signals_map_.erase(net->name());
}
/*
@@ -338,16 +375,10 @@ void NetScope::rem_signal(NetNet*net)
*/
NetNet* NetScope::find_signal(perm_string key)
{
if (signals_ == 0)
if (signals_map_.find(key)!=signals_map_.end())
return signals_map_[key];
else
return 0;
NetNet*cur = signals_;
do {
if (cur->name() == key)
return cur;
cur = cur->sig_prev_;
} while (cur != signals_);
return 0;
}
/*
+163
View File
@@ -0,0 +1,163 @@
/*
* 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(1).set_dir(Link::PASSIVE);
if (pin_count() == 3) {
pin(2).set_dir(Link::INPUT); // Enable
}
}
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(1).set_dir(Link::PASSIVE);
}
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;
NetPins*tmp_pins;
cur->cur_link(tmp_pins, pin);
NetObj*tmp = dynamic_cast<NetObj*> (tmp_pins);
if (tmp == 0)
continue;
// 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 that 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 branch 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 island 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);
}
}
-2
View File
@@ -30,10 +30,8 @@ NetUDP::NetUDP(NetScope*s, perm_string n, unsigned pins, PUdp *u)
: NetNode(s, n, pins), udp(u)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}
+277 -256
View File
File diff suppressed because it is too large Load Diff
+636 -265
View File
File diff suppressed because it is too large Load Diff
+192 -39
View File
@@ -76,6 +76,86 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
#endif
}
NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
{
NetNet*zero_net = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
zero_net->data_type(sig->data_type());
zero_net->local_flag(true);
if (sig->data_type() == IVL_VT_REAL) {
verireal zero (val);
NetLiteral*zero_obj = new NetLiteral(scope, scope->local_symbol(), zero);
des->add_node(zero_obj);
connect(zero_net->pin(0), zero_obj->pin(0));
} else {
verinum zero ((int64_t)val);
zero = pad_to_width(zero, sig->vector_width());
NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero);
des->add_node(zero_obj);
connect(zero_net->pin(0), zero_obj->pin(0));
}
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), sig->vector_width());
des->add_node(adder);
adder->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
connect(zero_net->pin(0), adder->pin_DataA());
connect(adder->pin_DataB(), sig->pin(0));
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
tmp->data_type(sig->data_type());
tmp->local_flag(true);
connect(adder->pin_Result(), tmp->pin(0));
return tmp;
}
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
{
if (src->data_type() != IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
tmp->data_type(IVL_VT_LOGIC);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastInt*cast = new NetCastInt(scope, scope->local_symbol(), wid);
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
{
if (src->data_type() == IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
tmp->data_type(IVL_VT_REAL);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed());
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
/*
* Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made
@@ -123,6 +203,34 @@ 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;
}
NetEConst* make_const_0(unsigned long wid)
{
verinum xxx (verinum::V0, wid);
NetEConst*resx = new NetEConst(xxx);
return resx;
}
NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
{
verinum xxx (verinum::Vx, wid);
NetConst*res = new NetConst(scope, scope->local_symbol(), xxx);
des->add_node(res);
NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
sig->local_flag(true);
sig->data_type(IVL_VT_LOGIC);
connect(sig->pin(0), res->pin(0));
return sig;
}
NetExpr* condition_reduce(NetExpr*expr)
{
if (expr->expr_width() == 1)
@@ -182,6 +290,72 @@ 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;
}
/*
* At the parser level, a name component is a name with a collection
* of expressions. For example foo[N] is the name "foo" and the index
* expression "N". This function takes as input the name component and
* returns the path component name. It will evaluate the index
* expression if it is present.
*/
hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp)
{
// No index expression, so the path component is an undecorated
// name, for example "foo".
if (comp.index.empty())
return hname_t(comp.name);
// The parser will assure that path components will have only
// one index. For example, foo[N] is one index, foo[n][m] is two.
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
// The parser will assure that path components will have only
// bit select index expressions. For example, "foo[n]" is OK,
// but "foo[n:m]" is not.
assert(index.sel == index_component_t::SEL_BIT);
// Evaluate the bit select to get a number.
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
// Now we should have a constant value for the bit select
// expression, and we can use it to make the final hname_t
// value, for example "foo[5]".
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
hname_t res(comp.name, ctmp->value().as_long());
delete ctmp;
return res;
}
// Darn, the expression doesn't evaluate to a constant. That's
// an error to be reported. And make up a fake index value to
// return to the caller.
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
delete tmp;
return hname_t (comp.name, 0);
}
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
@@ -191,30 +365,7 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
const name_component_t&comp = *cur;
if (comp.index.empty()) {
res.push_back(hname_t(comp.name));
continue;
}
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
assert(index.sel == index_component_t::SEL_BIT);
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
delete ctmp;
continue;
} else {
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
}
return res;
res.push_back( eval_path_component(des,scope,comp) );
}
return res;
@@ -227,26 +378,28 @@ const char *human_readable_op(const char op)
{
const char *type;
switch (op) {
case '~': type = "~"; break; // Negation
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 '^': 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 '!': type = "!"; break; // Logical NOT
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 '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
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
default: assert(0);
default:
assert(0);
}
return type;
}
+62 -8
View File
@@ -36,21 +36,25 @@
* ex2 is the lsb expression for the range. If there is no range, then
* these values are set to 0.
*/
extern NetScope* symbol_search(Design*des,
NetScope*start, pform_name_t path,
extern NetScope* symbol_search(const LineInfo*li,
Design*des,
NetScope*start,
pform_name_t path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
inline NetScope* symbol_search(Design*des,
NetScope*start, const pform_name_t&path,
inline NetScope* symbol_search(const LineInfo*li,
Design*des,
NetScope*start,
const pform_name_t&path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */)
{
const NetExpr*ex1, *ex2;
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
}
/*
@@ -64,6 +68,13 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
/*
* Generate the nodes necessary to cast an expression (a net) to a
* real value.
*/
extern NetNet*cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid);
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
/*
* Take the input expression and return a variation that assures that
* the expression is 1-bit wide and logical. This reflects the needs
@@ -84,6 +95,7 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
* return a new NetNet value that is the output of an addition.
*/
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig);
/*
* These functions make various sorts of expressions, given operands
@@ -102,6 +114,17 @@ 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);
extern NetEConst*make_const_0(unsigned long wid);
/*
* Make A const net
*/
extern NetNet* make_const_x(Design*des, NetScope*scope, 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
@@ -118,14 +141,27 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* The expr_width is the width of the context where the expression is
* being elaborated, or -1 if the expression is self-determined width.
*
* Also, the prune_width is the maximum width of the result, and it
* passed to the eval_tree method of the expression to limit constant
* results if possible.
* The prune_width is the maximum width of the result, and is passed
* to the eval_tree method of the expression to limit constant
* results. The evaluation will prune any constant result down to the
* prune_width (if >0) so should only be used at the point where it is
* bound to the destination.
*/
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid,
int prune_width =-1);
/*
* This function elaborates an expression as if it is for the r-value
* of an assignment, The data_type_lv and expr_wid_lv are the type and
* with of the l-value, and the expr is the expression to
* elaborate. The result is the NetExpr elaborated and evaluated.
* (See elab_expr.cc)
*/
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t data_type_lv,
int expr_wid_lv, PExpr*expr);
/*
* This procedure elaborates an expression and if the elaboration is
* successful the original expression is replaced with the new one.
@@ -138,10 +174,28 @@ void eval_expr(NetExpr*&expr, int prune_width =-1);
* 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);
/*
* Evaluate the component of a scope path to get an hname_t value. Do
* the evaluation in the context of the given scope.
*/
extern hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp);
/*
* Evaluate an entire scope path in the context of the given scope.
*/
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
/*
* Return true if the data type is a type that is normally available
* in vector for. IVL_VT_BOOL and IVL_VT_LOGIC are vectorable,
* IVL_VT_REAL is not.
*/
extern bool type_is_vectorable(ivl_variable_type_t type);
/*
* Return a human readable version of the operator.
*/
+82 -55
View File
@@ -37,14 +37,18 @@ class nodangle_f : public functor_t {
void event(Design*des, NetEvent*ev);
void signal(Design*des, NetNet*sig);
unsigned count_;
unsigned iteration;
unsigned stotal, etotal;
bool scontinue, econtinue;
bool scomplete, ecomplete;
};
void nodangle_f::event(Design*des, NetEvent*ev)
{
if (ecomplete) return;
/* If there are no references to this event, then go right
ahead and delete in. There is no use looking further at
ahead and delete it. There is no use looking further at
it. */
if ((ev->nwait() + ev->ntrig() + ev->nexpr()) == 0) {
delete ev;
@@ -52,58 +56,79 @@ void nodangle_f::event(Design*des, NetEvent*ev)
return;
}
/* Try to remove duplicate probes from the event. */
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
unsigned jdx = idx + 1;
while (jdx < ev->nprobe()) {
NetEvProbe*ip = ev->probe(idx);
NetEvProbe*jp = ev->probe(jdx);
if (iteration == 0) {
/* Try to remove duplicate probes from the event. This
is done as a separate initial pass to ensure similar
events are detected as soon as possible in subsequent
iterations. */
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
unsigned jdx = idx + 1;
while (jdx < ev->nprobe()) {
NetEvProbe*ip = ev->probe(idx);
NetEvProbe*jp = ev->probe(jdx);
if (ip->edge() != jp->edge()) {
jdx += 1;
continue;
}
if (ip->edge() != jp->edge()) {
jdx += 1;
continue;
}
bool fully_connected = true;
for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
unsigned ipin = 0;
bool connected_flag = false;
for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
if (connected(ip->pin(ipin), jp->pin(jpin))) {
connected_flag = true;
break;
}
bool fully_connected = true;
for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
unsigned ipin = 0;
bool connected_flag = false;
for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
if (connected(ip->pin(ipin), jp->pin(jpin))) {
connected_flag = true;
break;
}
if (!connected_flag) {
fully_connected = false;
break;
}
}
if (!connected_flag) {
fully_connected = false;
break;
}
}
if (fully_connected) {
delete jp;
} else {
jdx += 1;
}
}
if (fully_connected) {
delete jp;
} else {
jdx += 1;
}
}
}
econtinue = true;
} else {
/* Postpone examining events in an automatic scope until the
third (optional) pass. This will mean similar events are
biased towards being stored in static scopes. */
if (ev->scope()->is_auto()) {
if (iteration == 1) {
econtinue = true;
return;
}
} else {
if (iteration == 2) {
return;
}
}
/* Try to find all the events that are similar to me, and
replace their references with references to me. */
list<NetEvent*> match;
ev->find_similar_event(match);
for (list<NetEvent*>::iterator idx = match.begin()
; idx != match.end() ; idx ++) {
NetEvent*tmp = *idx;
assert(tmp != ev);
tmp ->replace_event(ev);
}
}
/* Try to find all the events that are similar to me, and
replace their references with references to me. */
list<NetEvent*> match;
ev->find_similar_event(match);
for (list<NetEvent*>::iterator idx = match.begin()
; idx != match.end() ; idx ++) {
NetEvent*tmp = *idx;
assert(tmp != ev);
tmp ->replace_event(ev);
}
}
void nodangle_f::signal(Design*des, NetNet*sig)
{
if (scomplete) return;
/* Cannot delete signals referenced in an expression
or an l-value. */
if (sig->get_refs() > 0)
@@ -174,7 +199,7 @@ void nodangle_f::signal(Design*des, NetNet*sig)
/* If every pin is connected to another significant signal,
then I can delete this one. */
if (significant_flags == sig->pin_count()) {
count_ += 1;
scontinue = true;
delete sig;
stotal += 1;
}
@@ -183,23 +208,26 @@ void nodangle_f::signal(Design*des, NetNet*sig)
void nodangle(Design*des)
{
nodangle_f fun;
unsigned count_iterations = 0;
fun.iteration = 0;
fun.stotal = 0;
fun.etotal = 0;
fun.scomplete = false;
fun.ecomplete = false;
do {
fun.count_ = 0;
fun.scontinue = false;
fun.econtinue = false;
des->functor(&fun);
count_iterations += 1;
fun.iteration += 1;
fun.scomplete = !fun.scontinue;
fun.ecomplete = !fun.econtinue;
if (verbose_flag) {
cout << " ... " << count_iterations << " iterations"
cout << " ... " << fun.iteration << " iterations"
<< " deleted " << fun.stotal << " dangling signals"
<< " and " << fun.etotal << " events."
<< " (count=" << fun.count_ << ")" << endl;
<< " and " << fun.etotal << " events." << endl;
}
} while (fun.count_ > 0);
} while (fun.scontinue || fun.econtinue);
}
@@ -285,4 +313,3 @@ void nodangle(Design*des)
* symbols generated by elaboration and other steps.
*
*/
+1
View File
@@ -88,6 +88,7 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
tmp->data_type( net->data_type() );
tmp->set_line(*net);
tmp->local_flag(true);
connect(cc->pin(0), tmp->pin(0));
+844 -313
View File
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -30,6 +30,15 @@ unsigned error_count = 0;
unsigned warn_count = 0;
unsigned long based_size = 0;
std::ostream& operator << (std::ostream&o, const YYLTYPE&loc)
{
if (loc.text)
o << loc.text << ":";
o << loc.first_line;
return o;
}
void VLerror(const char*msg)
{
error_count += 1;
@@ -39,20 +48,14 @@ void VLerror(const char*msg)
void VLerror(const YYLTYPE&loc, const char*msg)
{
error_count += 1;
if (loc.text)
cerr << loc.text << ":";
cerr << loc.first_line << ": " << msg << endl;
cerr << loc << ": " << msg << endl;
based_size = 0; /* Clear the base information if we have an error. */
}
void yywarn(const YYLTYPE&loc, const char*msg)
{
warn_count += 1;
if (loc.text)
cerr << loc.text << ":";
cerr << loc.first_line << ": warning: " << msg << endl;
cerr << loc << ": warning: " << msg << endl;
}
int VLwrap()

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