Sean Anderson [Mon, 29 May 2023 21:39:41 +0000 (17:39 -0400)]
vhpi: Add support for getting/putting IndexedNames
This allows getting/putting nested arrays, and individual elements of an
array. The final index calculation is done lazily, although this
could be done eagerly by moving it to init_indexedName.
The tests for indexednames and the various enum types are extended now
that it is easier to access them.
Sean Anderson [Mon, 29 May 2023 21:49:14 +0000 (17:49 -0400)]
vhpi: Fix vhpi_get_value with EnumVecVal format
The Logic, SmallEnum, and Enum formats were not treated consistently.
Sometimes the wrong value type was used to store signals, and the
variable signal size of Enum was not handled properly. The correct
relationships for these types may be seen in the following table:
Format Value type Signal size
================ ============== ===========
vhpiLogicVal vhpiEnumT 8
vhpiSmallEnumVal vhpiSmallEnumT 8
vhpiEnumVal vhpiEnumT variable
In order to handle the variable size of Enum, we need to use FOR_ALL_SIZES
from model.c. Move it to util.h, and rename a conflicting macro with a
similar purpose. This also adds support for getting SmallEnumVecs.
This adds a test for the Vec versions of these formats; the non-vec
versions will be tested when indexedName get/put support is added.
Sean Anderson [Mon, 29 May 2023 21:04:52 +0000 (17:04 -0400)]
vhpi: Add support for IndexedNames
IndexedNames (e.g. `a(0)` or `a(2, 3)`) are necessary to access elements
of nested or multidimensional arrays (which have too many dimensions for
vhpiLogicVecVal) or to set individual elements of single-dimensional
arrays. Add basic support for these objects.
Although objDecls are names too, they also include the decl properties
which we don't want. Therefore, we use a separate hierarchy for
exprs/names. For future work, it might be nice to use the object
framework (tree_t, type_t, etc) for VHPI as well.
IndexedNames are created lazily. This is useful for nested arrays. For
example, a signal like
type a is array(0 to 9) of std_logic_vector(31 downto 0);
signal b: a;
might only be accessed like `b(0)` and never like `b(2)(3)`.
The encoding of prefixedName varies slightly from the UML. To reuse the
above example, while the UML says that the prefix of `b(0)` is `b`,
we set prefix as NULL in this situation, using simpleName instead. This
makes it easier to walk nested prefixes, since we don't have to compare
prefix to simpleName.
To populate IndexedNames, we must iterate over all constraints on the
array, and create `c_indexedName`s for each. One option here would be to
pass BaseIndex to init_indexedName. However, this would require decoding
the BaseIndex into indices for each constraint. Indead, I chose to pass
the indices directly, and create BaseIndex from them. I think this is
easier, because it doesn't involve any division.
Sean Anderson [Mon, 29 May 2023 20:11:56 +0000 (16:11 -0400)]
vhpi: Rework size calculation
IndexedNames represent a subset of the elements in a signal. Their size
is dependent on their type. In preparation for adding IndexedName
support, rework the size calculation to be based on the type of the
object instead of the width of the backing signal.
Sean Anderson [Mon, 29 May 2023 19:45:06 +0000 (15:45 -0400)]
vhpi: Support constraints
Add support for range constraints on arrays and subtypes. I think the
from/to on unconstrained ranges should reflect the from/to of the
underlying type, but I have left that out for now. Currently no
properties are supported, but that will change soon.
Sean Anderson [Mon, 29 May 2023 19:23:07 +0000 (15:23 -0400)]
vhpi: Add support for subtypes
Add very basic support for subtypes. This is just enough to place them
in the type hierarchy, and not much else. Array subtypes are always
created as arrayTypeDecls, since this will let us expose the element
subtype properly.
Sean Anderson [Mon, 29 May 2023 23:02:31 +0000 (19:02 -0400)]
vhpi: Pass type directly to init_typeDecl
Anonymous types can't be looked up by their ident, so the decl is for
their base type instead. Pass the type directly instead of using
tree_type to ensure the type matches what it represents.
Sean Anderson [Mon, 29 May 2023 18:36:17 +0000 (14:36 -0400)]
vhpi: Move iterator initialization to init_iterator
In preparation for merging the logic in vhpi_iterator with
vhpi_handle_for_index, split off iterator initialization into its own
function. This replaces new_iterator so we can avoid a memory
allocation if possible in vhpi_handle_for_index.
Sean Anderson [Mon, 29 May 2023 17:09:37 +0000 (13:09 -0400)]
vhpi: Move BaseType to c_typeDecl
Each Type has a BaseType. Except for subtypes, the BaseType is the Type
itself. In preparation for adding subTypeDecls, move BaseType to
typeDecl. This allows us to calculate the BaseType when necessary,
removing the need to have a redundant BaseType reference.
Sean Anderson [Mon, 22 May 2023 16:01:38 +0000 (12:01 -0400)]
Fix coverage generation for unary operators
Unary functions (such as reductions) cause an assertion failure in
lower_logic_expr_coverage. As they operate on arrays, and arrays are
skipped anyway, modify this function to skip such operators. Also remove
a debug print while we're here.
Add a test case to ensure such functions are excluded from coverage.
Sean Anderson [Sat, 20 May 2023 21:02:19 +0000 (17:02 -0400)]
vhpi: Calculate callback timeout at registration
Callback timeouts must be calculated at registration, not at enabling:
> Disabling a callback simply determines whether or not the callback will
> be triggered when its trigger event occurs. For example, disabling a
> callback that is registered to trigger after a given delay and
> subsequently enabling before expiry of the delay does not postpone the
> time at which the trigger event occurs.
Additionally, any data in cb_data_p that we do not save (such as time)
may not be accessed after we return from registration.
Sean Anderson [Sat, 20 May 2023 18:05:38 +0000 (14:05 -0400)]
vhpi: Fix use-after-free when removing callbacks
Callbacks can generally be in a few states:
- Disabled or mature
- Actively executing
- Waiting to execute
For all callbacks except for AfterDelay, when the callback is waiting to
execute then clearing it will prevent further execution. However,
AfterDelay callbacks can be absent from the eventq_heap in the driverq
workqueue awaiting execution. Clearing these callbacks will not prevent
them from executing.
To work around this, make model_clear_timeout_cb return a boolean
indicating whether a callback was actually cleared. If no callback was
cleared and the callback is not currently executing, then the callback
is in a workqueue. In this case, just free the callback later.
Otherwise, we have actually removed a callback and we can be sure that
it will not execute, so free it now.
Fixes: d6e523a4 ("vhpi: Free callbacks in remove")
Sean Anderson [Sat, 20 May 2023 18:00:08 +0000 (14:00 -0400)]
vhpi: Allow disabling ValueChange callbacks
Allow disabling ValueChange callbacks by clearing the individual
wakeables. This function could take rt_signal_t and user data, but the
signal is calculated for VHPI callbacks, and it is easier to just store
the watch instead.
Sean Anderson [Sat, 20 May 2023 17:55:37 +0000 (13:55 -0400)]
model: Correct timing of RT_LAST_KNOWN_DELTA_CYCLE
According to the spec, vhpiCbLastKnownDeltaCycle callbacks can create
further delta cycles:
> h) If the next simulation cycle will be a delta cycle, the remainder of
> step h) is skipped. Otherwise, the following actions occur in the
> indicated order:
>
> 1. Each registered and enabled `vhpiCbLastKnownDeltaCycle` and
> `vhpiCbRepLastKnownDeltaCycle` callback is executed. T_n is
> recalculated according to the rules of 14.7.5.1.
> 2. If the next simulation cycle will be a delta cycle, the remainder
> of step h) is skipped.
> 3. ...
Fire RT_LAST_KNOWN_DELTA_CYCLE before disabling delta cycles to allow
this to happen.
Sean Anderson [Wed, 17 May 2023 21:26:39 +0000 (17:26 -0400)]
vhpi: Free callbacks in remove
Callback handles should be released in vhpi_remove_cb. We can't just
free directly because callbacks may remove themselves while they
are executing. Instead, keep track of whether a callback is executing
and don't free the callback until after it's done.
Sean Anderson [Tue, 16 May 2023 23:17:02 +0000 (19:17 -0400)]
vhpi: Add support for nonstandard search strings
As far as I can tell, search strings of the form
unit.signal
are relative, and therefore cannot be used with a scope of NULL.
However, they appear to be both supported by other simulators [1], and
expected by cocotb. Add support.
Sean Anderson [Wed, 17 May 2023 00:04:45 +0000 (20:04 -0400)]
vhpi: Add tool object
Add a tool object, allowing applications to read the tool name and
version in a standard way. Also support a (very minimal) argv, as some
applications expect it to exist when the tool does.
Sean Anderson [Tue, 16 May 2023 22:34:47 +0000 (18:34 -0400)]
vhpi: Stub out prefix support
As far as I can tell, none of the entities we support have prefixes.
However, some existing VHPI applications try to get prefixes without
regard to kind. Just return NULL to satisfy them.
Sean Anderson [Tue, 16 May 2023 22:18:34 +0000 (18:18 -0400)]
vhpi: Implement size
This property isn't defined anywhere in the spec. Fortunately, there's a
blurb in the UML diagram [1]:
> If the object or value denoted by the name is determined, the value of
> the Size property is the number of scalar values denoted by the name.
> The object or value denoted by the name is determined for a locally
> static name. The object or value denoted by the name may also be
> determined for a globally static name in the design hierarchy information
> model. In other cases, the object or value denoted by the name is not
> determined, and the value of the Size property is vhpiUndefined.
>
> For a name that denotes an object or value of a scalar or access type,
> the value of the Size property is 1.
>
> For a name that denotes an object or value of a composite type, the value
> of the Size property is the number of scalar subelements of the object or
> value.
>
> For a name that denotes an object or value of a file type or a protected
> type, the value of the Size property is vhpiUndefined.
Effectively, this is the number of elements in the value. Although the
spec says to return vhpiUndefined on error, we return 0 instead to
placate existing applications.