Re: Vote on Kevin's proposal


Subject: Re: Vote on Kevin's proposal
From: Kevin Cameron x3251 (Kevin.Cameron@nsc.com)
Date: Fri Jan 03 2003 - 14:50:08 PST


> From john_stickley@mentorg.com Fri Jan 3 12:21:11 2003
>
> Kevin,
>
> Kevin Cameron x3251 wrote:
....
> >>>>Here are my other main objections to it:
> >>>>
> >>>>1. We don't need both a "call forward" "register locator"
> >>>> *and* a "call back" binding function. All we would need is
> >>>> a call forward binding function (i.e. svBind()).
> >>>
> >>>
> >>>You do if you want to link arbitrary C++ compilers code
> >>>dynamically.
> >>
> >>johnS:
> >>I think call forward from C would work quite nicely in
> >>a simplified dynamic binding scheme.
> >
> >
> > You need the locator if you don't have a a matching C name
> > in your library. If you only use the C name you cannot overload
> > calls the same way C++ and other languages do without generating
> > extra layers of indirection.
> >
> > If you have multiple libraries with different versions of
> > a particular routine, static linking with a single C name is
> > impossible, and using C++ is only possible if you stick with
> > one compiler.
> >
> > If SV dynamically loads a library then it could use call-forward
> > for locating functions, however, if you use static linking the
> > simulator cannot know which libraries it actually has unless the
> > libraries announce themselves somehow. The "register locator"
> > methodology avoids the simulator having to search for each library's
> > symbols in the simulation executable. The locator function is particular
> > to each library so they can't have the same C name in a static link.
> >
>
> johnS:
>
> I think you might have misunderstood what I meant by a
> call forward dynamic bind capability. In the scheme I
> had in mind, C symbols are not required.
>
> Let me see if I can elaborate a little more - here
> again, assuming dynamic binding is necessary -
> which I think is still questionable.
>
> The idea is this:
>
> 1. Use dlopen to dynamically load a C or C++ library.
>
> 2. Use dlsym to dynamically lookup the "bootstrap()"
> function of a pre-known name in that library.
>
> 3. Now the bootstrap() function would call a function that's
> a required part of the API called svBind() whose prototype
> looks something like this:
>
> void svBind( void *realFunctionPtr, const char *functionName );
>
> So, using our example below you would do something like
> this:
>
> SV declaration:
>
> extern dynamic context "foo_double" integer foo( real arg );
> extern dynamic context "foo_int" integer foo( integer arg );
>
> Dynamically loaded .so code:
>
> static int actual_foo_double( svHandle context, double arg ){
> return (*real_foo_double)( context, arg ); }
>
> static int actual_foo_int( svHandle context, int arg ){
> return (*real_foo_int)( context, arg ); }
>
> bootstrap(){
> svBind( (void *)&actual_foo_double, "foo_double" );
> svBind( (void *)&actual_foo_int, "foo_int" );

I got confused by the '&'s - they aren't required.

> }
>
> So, here, because I used a one way call forward dynamic bind
> function, I never actually had to have function symbols called
> "foo_double" and "foo_int" in my code. Nor did I have to have a
> "call forward" register locator *and* a "call back" binding
> function of the sort you have proposed.
>
> Rather, I'm just making a single forward call per bound
> function to inform the infrastructure what actual functions to
> use in place of the functions named in the SV declarations.
>
> This does imply that an extra "dynamic" attribute should be
> added to the SV extern declaration so that the SV compiler will
> know not to generate code that externally references the symbols.
>
> I think this scheme may be simpler to use than what
> you've proposed while still allowing true dynamic binding.
> However, I think it is still overkill for what we actually
> need.

It works for a subset of the functionality. As I said before, It doesn't
work well with a static link of the libraries since you can't have multiple
routines called "bootstrap". Using the registration approach allows you
to handle the initialisation externally to SV and effectively just hand
over all the bootstrap function addresses - which allows static linking.

> Also, in this scheme I don't show a way of querying
> argument types so that you can form mangled names as
> you've shown in your examples. However, I think a better
> way to do that would be through a VPI like abstract interface
> that lets you query the interface declarations of an
> extern'ed C function. From those query results you can form
> your compiler specific mangled names. This would be cleaner
> and more consistent than the awkward type specficiation strings
> that you've proposed.

But when would you do that? When the routine is called?

What's awkward about the type specification? (NB: the interface is
extensible, you could have a VPI interface as well if you want to
spec it.)

The reason my scheme uses the call-back (locator) is that you don't
know which arguments a routine will be called with until the code
is elaborated and different call instances may require different
handling or with C++ overloading go to different implementations.
If you use "svBind" to do the same job you would have to register
all the possible versions of the function whether they are used or
not. Also, the call-back/locator approach lets the code in the
library set up a specific interface on-the-fly. i.e. there is no
need to have an actual entry-point in the library prior to it being
asked for.

....

> >>>You don't have the data setup phase.
> >>
> >>johnS:
> >>I'm not sure what you mean by this. Please elaborate.
> >
> >
> > All your calls are not specific to the calling context, any
> > context dependent behavior has to be evaluated when the routine
> > is called.
> >
> > My scheme can interogate the context when deciding which routine
> > to use and set the context user data at that time so that calls
> > to the routine later do not have to interogate the context. In
> > my example I set the context user data differently for each call
> > when I do the linking.
> >
> > Your scheme can only bind one C routine for multiple instances
> > of a call, mine can bind a different routine for each instance.
> > Since module instances can vary substantially due to parameters
> > being different, my scheme offers performance benefits from being
> > able to move some context dependent decision making into the
> > locate/link phase.
>
> johnS:
> Any dynamic binding scheme can do this, including the one
> I described above.

Your scheme doesn't bind on context or arguments, only on the (C) linker
name. In my proposal I can handle the two calls to my_prnt in this SV code
seperately at link time:

    extern context,line,static void my_prnt(const char *,...);

    module x;
        double d;
        int i[1:0];
        always @(y) if (z) my_prnt("%g",d);
                    else my_prnt("%d %d",i[1],i[0]);
        ....

- which gives me more opportunity to optimize the calls.

Kev.



This archive was generated by hypermail 2b28 : Fri Jan 03 2003 - 14:50:38 PST