Re: DirectC: C layer


Subject: Re: DirectC: C layer
From: Stickley, John (john_stickley@mentorg.com)
Date: Fri Dec 13 2002 - 17:07:42 PST


Francoise,

Francoise Martinolle wrote:
> Andrzej,
>
> It was very difficult today to place any word during the meeting so I am
> gathering my issues/comments in this email.
>
> I have 3 main issues with the proposal.
>
> The first one has to do with passing by reference the simulation object
> value and that
> value be modified by the directC interface. When and how is the
> propagation of that value
> done? Wires and regs have fan out and updates to their values should cause
> propagation and fanout. When does this happen? What about if there is a
> force in effect on that
> object? Would the value be updated by the C code?

johnS:
I don't think this would be a problem. While in the C function,
we've all agreed time advance is 0-time, correct ? So what would
happen is that the calling of the C function would be an instantaneous
call somewhere in the process activation phase of the SV simulation
cycle that would essentially block the kernel for the duration of
the call, much as PLI callbacks do today.

The generated code representing the SV process that makes the function
call (I'm talking about an SV-to-C call now) will make the call which,
upon return, would update the output argument which could,
in turn, update the value of the nets as if the value had been
directly assigned with local, conventional blocking assign statement.
To me that's the easiest semantic to describe and understand.
Effectively the function acts as a combinatorial argument
transformation such one would see with direct blocking assignment.
If non-blocking semantics are desired, the function return or
output argument could simply become the source expression of a
non-blocking assignment on the SV side.

Example:

Continuous assignment:

      wire dest;
      dest = my_ret_func( source );

Blocking and non-blocking assignment w/ void function that has output arg:

      reg dest;

      always @(posedge clk) begin
          ...
          my_void_func( source, dest ); // Blocking assign semantics to dest
          nb_dest <= dest; // Non-blocking assign of arg to nb_dest

Blocking, assignment w/ non-void function that returns arg:

      reg dest;

      always @(posedge clk) begin
          ...
          dest = my_ret_func( source ); // Blocking assign semantics to dest

Non-blocking, assignment w/ non-void function that returns arg:

      reg dest;

      always @(posedge clk) begin
          ...
          nb_dest <= my_ret_func( source ); // Non-blocking assign semantics

So, unless I'm missing something, I don't see where the pass-by-reference
semantic makes a difference here for the case of the void function
with an output arg. And for return args, the implication is always
return-by-value.

> Depending on what is your answer, we have a further problem as we are
> thinking
> of allowing SV tasks and functions to be called from inside the C function.
> What would be the values that these task/functions will see, has the
> value already propagated?

johnS:
Actually, my last understanding was that we're considering
only functions (including void functions in lieu of tasks)
to avoid conflict with the 0-time requirement.

So the C-to-SV direction you mention here is a little trickier
than for the SV-to-C direction described above but I think
it is still workable.

You can consider two cases.

1. The C-to-SV function is called from within another SV-to-C function.
In this case, the semantics are identical to that described above
and there is no issue. This is also probably the most common case
in non-multi-threaded C environments.

2. The C-to-SV function is called from some "process" on the C side
(such as a SystemC thread). In this case, the imlicit assumption is that
there is proper synchronization among the two threading systems
which the infrastructure guarantees. And, as such, the C "processes"
get evaluted at the appropriate time in the cycle when HDL processes
do and so are properly sequenced with respect to value propagation.

>
> My second issue is related to the first one: you pass by reference large
> simulation objects
> but you provide user callable functions to copy the simulator value into
> a canonical representation.
> The memory allocation for the canonical value being the responsibility
> of the user seems
> dangerous and would require them to find out the size/range of the
> simulation object, thus requiring
> more API functions to inquire about the object. The conclusion is that
> you may pass by reference
> but this requires the user to transform the value in the canonical form
> before reading or writing to it.
> Unless the user cares to know about the internal simulator
> representation and therefore can directly
> dereference the simulation value passed by reference. This leads me to
> the third issue.
>
>
> The third issue is related to the internal representation of wires in
> Verilog.
> There is no common layout for wires in a single Verilog simulator. Wires
> may be expanded or
> vectored and depending on this the wire value may not be consecutive
> bits in memory.
> A scalar wire can be shared between different wire arrays. Various
> layouts can apply depending on
> Verilog code generation optimizations, thus invalidating the directC
> user code.
> This tells you that in many cases you cannot pass a wire by reference
> and that SV will have to
> compose the value of a non scalar wire before passing the value by reference
> to C and if C modifies that value then that value will have to be decomposed
> back on the SV side. You may want to force the layout of the composed
> value to be
> similar as the one chosen for reg and variables in a given simulator but
> this will have
> some implication on simulation performance.

johnS:
Again the SV compiler should worry about this. This can be thought
of as similar to the issue of type coercion of actual arguments
to match the type of the formal. Such coercion may indeed require
assemblage of an aggregate structure that is passed to the function.

As an analogy in pure C++ for example, this can even result in implicit
construction of an automatic variable that is then passed as the arg.

But it seems to me that this issue is idependent of whether an
SV function is calling a C function or another SV function. The
problem will still have to be solved either way.

Similarly for output arguments, the SV would generate code to automatically
copy the output (whether by reference or by value) to the target SV
actual.

>
> I believe that the only sound technical solution is to do copy in and
> copy out. Then you don't
> have the 3 issues I mentioned. Calling a directC function is in line
> with the copy-in copy-out rules
> of Verilog tasks and functions, commonly understood by Verilog users.
> You solve the fanout/force problem, fanout occurs when the function
> returns, update occurs after the
> function returns.
> The transformation of the value between SV and C is done on the
> simulator side rather than by
> a C user function, the simulator knows how much he needs to allocate.
> And as a bonus this solution is always binary compatible if we agree on
> the canonical representation
> of the copyout value on the C side, which I think should be in a VPI
> vecval structure format.
> There is no C API function to manipulate the values that are passed.
>
> I would like to know what you think about these issues.
>
> Francoise
> '
>
> At 02:47 AM 12/7/2002 -0500, Andrzej Litwiniuk wrote:
                                                               __
                           ______ | \
______________________/ \__ / \
                                    \ H Dome ___/ |
John Stickley E | a __ ___/ / \____
Principal Engineer l | l | \ /
Verification Solutions Group | f | \/ ____
Mentor Graphics Corp. - MED C \ -- / /
17 E. Cedar Place a \ __/ / /
Ramsey, NJ 07446 p | / ___/
                                     | / /
mailto:John_Stickley@mentor.com \ /
Phone: (201)818-2585 \ /
                                       ---------



This archive was generated by hypermail 2b28 : Fri Dec 13 2002 - 17:11:05 PST