Subject: $sv-ec Re: PROPOSAL: Re: ISSUE:DirectC:DirectC i/f should supportmechanism for calling Verilog task/function from a DirectC
From: Kevin Cameron (Kevin.Cameron@nsc.com)
Date: Fri Oct 25 2002 - 10:31:30 PDT
"Stickley, John" wrote:
> Fellow SV-CC'ers,
>
> ...
>
> Kevin suggests something similar ...
>
> Kevin Cameron x3251 wrote:
>
>> I would suggest considering module instances as being like class
>> instances in C++. You could get the handle to a module instance
>> using the standard PLI mechanisms and then use it in C++ as a
>> class instance pointer with the tasks and functions of the module
>> as virtual functions.
>>
>> Doing this stuff in C rather than C++ is awkward because C doesn't
>> support overloading of names, so you would have to come up with
>> some name mangling scheme.
>
> Our proposal accomplishes the same thing but uses user defined
> context pointers rather than handles denoting HDL module
> instances - at least for the HDL-to-C function call direction.
> (I'll show later that for C-to-HDL, Kevin's approach is right
> on the mark.).
Thanks :-)
>
> .....
>
> C-to-HDL Function Calls: Context Pointers for Instance Specific HDL Callee Bindings
>
> In the case where the user cares about which specific instances of HDL callee
> functions are being called (which is probably most of the time), for those instances
> the user will want to pass to the C proxy function, a context pointer that refers to a
> specific HDL module instance that contains the HDL callee function.
> [Note: This is exactly what Kevin C. suggested in the previous quoted text above.]
>
> In this case a handle representing the HDL callee instance would be passed into
> the proxy function call as the void *context argument whenever the call from a
> C model is made.
>
> In order to support instance specific HDL callee function calls, the following
> API function is added to the DirectC API interface to obtain an HDL callee
> instance handle:
>
> void *
> BindHDLCallee(
> const char *callerInstanceName,
> const char *functionName );
>
> The handle returned can then be passed by the C caller code to future calls of the
> C proxy function.
>
> So, getting back to our ATM cell example described above,
> the following code is an example of how we might generate
> the context handle representing a specific instance of a
> function call in a particular module instance:
>
> void *getAtmCellContext = BindHDLCallee( "top.u1", "getAtmCell" );
> void *putAtmCellContext = BindHDLCallee( "top.u2", "putAtmCell" );
>
> These getAtmCellContext and putAtmCellContext pointers are then
> the pointers that the user must pass into the calls to the HDL functions shown
> previously. The runtime system interprets the context pointer and routes the
> function call to the appropriate HDL code.
>
> -- johnS
I prefer to go with the C++ virtual function approach because it would be possible
to swap C++ and SV implementations - particularly if they are in DLLs - and also
mix C++ and SV instances. In your example you have four "EthPortWrapper"
cells, it may be handy to be able to do one in SV and the others in C++, but
have the C++ callers of get/putAtmCell unaware of the difference.
BTW this touches on a topic I brought up at the last EC meeting on inheritance
"would you want to inherit a module from a class?". I think the answer is "yes"
because you can then match up the virtual functions reliably, e.g.:
class atmFunc {
virtual void getAtmCell(cell&) = 0;
virtual void putAtmCell(cell&) = 0;
}
....
module atmCell : atmFunc (...);
task getAtmCell(input cr) // implements atmFunc::getAtmCell
cell cr;
endmodule
task putAtmCell(output co)
cell co;
endmodule
...
endmodule
....
class atmCell : public atmFunc {
virtual void getAtmCell(cell&) {
...}
virtual void putAtmCell(cell&) {
....};
}
Neither the versions of atmCell need to implement all the functions in
atmFunc, unimplemented functions are inherited.
The calling C++ would be something like:
atmFunc *ap[4];
ap[0]= LocateAtm("top.u1"); // User Func (SV/PLI or C++)
ap[1]= LocateAtm("top.u2");
ap[2]= LocateAtm("top.u3");
ap[3]= LocateAtm("top.u4");
...
ap[0]->putAtmCell(cll_out);
ap[1]->getAtmCell(cll_in);
atmCompare(cll_out,cll_in);
If you don't use the virtual function approach you can't mix SV and C
module implementations because the there would be a name clash when
linking (it would have to be all SV instances or all C++).
Kev.
-- National Semiconductor, Tel: (408) 721 3251 2900 Semiconductor Drive, Mail Stop D3-500, Santa Clara, CA 95052-8090
This archive was generated by hypermail 2b28 : Fri Oct 25 2002 - 10:34:49 PDT