Re: Modified Proposal for Context Sensitive Function Calls


Subject: Re: Modified Proposal for Context Sensitive Function Calls
From: Kevin Cameron x3251 (Kevin.Cameron@nsc.com)
Date: Tue Nov 19 2002 - 16:53:16 PST


> From john_stickley@mentorg.com Tue Nov 19 15:00:12 2002
>
> Kevin,
>
> This is very similar to my proposal for C-to-SV as of the version I
> sent out today except for 2 key differences:
>
> 1. Your proposal requires new, currently non-existent API calls,
> while mine uses existing VPI or PLI calls.
>
> 2. Your proposal uses dynamic binding to retreive an exported function
> pointer whereas mine uses static "matched name" bindings.
>
> Regarding item #1, at Joao's urging, if it is at all possible, we should
> avoid inventing new API calls if we can reuse existing ones. By doing
> so we keep the new DirectC standard as strictly SV syntax extensions
> and no new API calls. Probably a worthy goal.
>
> However, regarding item #2, after reading your proposal, it occurs
> to me that there's a potential problem with using non-scoped static
> "matched name" bindings as per my proposal, and that is that you
> cannot simply reference a scoped SV task or function from C by
> simple name match. The reason is that the same task name can
> be used in multiple module scopes.
>
> Your approach solves this problem, however I think a more elegant
> way to solve it is, rather than to use dynamic binding as you suggest,
> to have a globally scoped "C name" indication as part of the the
> export declaration. This would be more consistent with the global
> scoping used counterpart extern declarations for the SV-to-C
> direction as was outlined by Andrezj today.

That still suffers from the inefficiency that you have one "C" name
for multiple (distinct) instances of the task/function, so you need
an extra level of indirection to get to the actual task or function.
Calculating the indirection may be nontrivial, so it is prefereable
to do it just once (as with the dynamic binding) rather than on
every call.

I'll take efficiency over elegance :-)

The dynamic binding mechanisms are also less dependent on the linker's
capabilities, avoid C name clashes entirely, and also allow checking
that the arguments match up (which C linking doesn't).

I'm OK with the "export ... <module>::<function>" syntax (I used that
in the earlier e-mail proposal).

Kev.

 
> Here's a suggested modification of my proposal to handle this.
> Basically I've added an "as clause" to the basic export declaration
> to declare globally scoped C alias to a locally scoped Verilog task:
>
> export_decl ::=
> export access_mode ? attribute (, attribute) * ?
> function | task [modulename::]fname as cname;
>
> access_mode ::= ( "A" | "C" )
>
> attribute ::= pure | context
>
> Example SV code:
>
> // Declare a C callable, context specific, SV task
> export "C" context task MySvModule::MySvTask as MySvModule_MySvTask;
>
> module MySvModule( ... );
> ...
> task MySvTask;
> input int portID;
> output int mappedID;
>
> mappedID = map(portID);
> endtask
> ...
> endmodule
>
> Note that the MySvModule:: prefix is not necessary if the export declaration
> is located in module scope. It is only necessary only at $root scope. In either
> case, the declared C name identifier, MySvModule_MySvTask is always
> global scope regardless of where the declaration is, as is the case with
> C names in counterpart extern declarations used for the SV-to-C
> direction.
>
> Note also that we can still use tf_*() or VPI calls to establish context as I
> originally proposed:
>
> Example C code:
>
> // During initialization, establish a context handle
> // to the SV callee instance:
> void MyCModel::Init( ){
> svContext = tf_mipname( "top.u1" );
> }
>
> // Now at run-time call the exported SV function from C passing the context
> // handle as the first argument:
> void MyCModel::RunTest( int portID ){
> MySvModule_MySvTask( svContext, portID, &mappedID );
> . . .
> }
>
> The beauty of this is that we've continued to keep new API calls
> out of the specification yet we've solved the C-to-SV scoping issue
> and can still use static name match style binding, thus avoiding the
> use of function pointers and dynamic binding.
>
> -- johnS
>
> Kevin Cameron x3251 wrote:
>
>
> I just resent a couple of emails that I'd forgotten to send
>
> to the reflector, the first one ( http://www.eda.org/sv-cc/hm/0332.html
> <http://www.eda.org/sv-cc/hm/0332.html> )
>
> has an alternative method for binding/calling an SV task/function
>
> which should be more efficient since it avoids having to decoded
>
> the task/context on every call - i.e. a task may have a per-instance
>
> implementation so the call -
>
>
>
> <task name>(<sv context>,...)
>
>
>
> - from C to SV requires a lookup on the context to obtain an entry-point
>
> to the actual code. Decoding the actual entry-point at setup time avoids
>
> the lookup overhead on later calls, and avoids the exported
> task/function
>
> having to appear in the C routine name space (for linking).
>
>
>
> The converse mechanism could be used to link module (class) specific
>
> routines to module instances, i.e. if a module declares an XF (rather
>
> than in $root) it would be bound to a C/C++ function pointer at
> elaboration
>
> by calling a user-supplied (PLI) routine e.g.:
>
>
>
> pointer ($)svcGetXF(<module name>,<module instance name>,<function
> name>,
>
> {,<argument type>});
>
>
>
> The XF would then be called as:
>
>
>
> (*xf_pointer)(<instance pli handle>,<context pointer>,...);
>
>
>
>
>
> Note: since multiple C/C++ libraries may be involved from different
> sources
>
> it would probably be better to allow multiple "svcGetXF" functions by
>
> providing a registration mechanism in SV, e.g.:
>
>
>
> bool svcXFlocater(<function name>,
>
> <locater context>,
>
> <module name regexp>); // returns false if
> registration fails
>
>
>
> Which would lead to code like the following to bind a class method:
>
>
>
> static pointer myBinder(void *,char *,char *,char *,void **,...);
>
> class foo {
>
>
>
> bind(char *,char *,char *);
>
>
>
> my_class() { svcXFlocater(myBinder,
>
> this,"foo"); // XF locater for module
> "foo"
>
> ... }
>
>
>
> }
>
>
>
> static pointer myBinder(void *context,char *modname,char
> *inst_name,char *rtn_name,
>
> void **p_context,...)
>
> {
>
> pointer rtn_addr = ((foo
> *)context)->bind(modname,inst_name,rtn_name);
>
>
>
> if (rtn_addr) *p_context = this; // set context for future calls.
>
>
>
> return rtn_addr;
>
> }
>
>
>
> The module name (regexp) with the svcXFlocater call is necessary to
> limit the scope
>
> of the binding (and speed it up).
>
>
>
> The locater function could create all the class/context data on the fly
> so
>
> that it is only created if the calling module is instanced (maybe
> indicated
>
> by a null locater context).
>
>
>
> Kev.
>
>
>
>
>
> --
>
> __
>
> ______ | \
>
> ______________________/ \__ / \
>
> \ 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 <mailto:John_Stickley@mentor.com> \
> /
>
> Phone: (201)818-2585 \ /
>
> ---------
>



This archive was generated by hypermail 2b28 : Tue Nov 19 2002 - 16:53:55 PST