Subject: Re: [sv-cc] LRM modifications for svGet/PutUserData proposal
From: Andrzej Litwiniuk (Andrzej.Litwiniuk@synopsys.com)
Date: Wed Mar 26 2003 - 08:02:26 PST
Team,
Perhaps I'm missing something and oversimplifying the issue.
I don't see, however, why a unique ID may be needed per module instance
or per module type. I tend to think that one ID per application should
do the trick.
If there were only =one= application, then a single pointer per instance
would do?
Having a single =private= pointer per each instance, an application
may implement whatever association of data with an instance, using whatever
kind of keys: strings (function names, for example), function pointers,
enum types, etc. All it takes to implement it is a simple list: <key,data,next>
with the sole pointer per instance used as a list pointer. Of course, a more
subtle scheme could be used in order to improve the run-time performance.
Note that such a dynamic scheme bears no inherent memory overhead other than 
one pointer per instance, if data association is not needed for a particular
instance and a key.
If something is missing in the above scheme - again: one application assumed! -
then please skip the rest and accept my appologies for making a fool of myself.
Now, consider a scenario with several applications.
Each application needs only one private pointer per instance, right?
Let's re-use the above scheme. Now, several pointers are needed per instance,
one per an application. Let each application be a unique key - and magically
everything will work! (The proposed implementation is perhaps a bit simplistic,
yet memory efficient and run-time-wise tolerable; surely more sophisticated
solutions could be found.)
- each application has its unique ID
- each instance contains one pointer,
- the sole pointer per instance points to a list of 
  <application_ID, application_private_pointer_per_instance> pairs
- each application implements the required association of data
  with instances on its own, having a single handle per instance.
Is anything wrong with this scheme?
You may notice 3 layers here:
- core DPI provides one shared pointer per instance
- complimentary layer of DPI provides unique IDs and uses such a pointer
  to provide an association  (instance x ID) --> data
- application builds its own asscociation (instance x key) --> data 
  using one pointer (per instance) provided by the previous layer
Note that both the second and third layer implement their stuff utilizing
a single pointer provided by the previous layer.
L1:	instance ---> ptr1
L2:	request (apllication) ---> ID
L2:                   ptr1    x    ID ---> ptr2
L3:                                        ptr2  x key ---> appl_data
=====================================================================
        instance              x    ID            x key ---> appl_data
> >  > /* Return a unique ID that can be used as a key to store user
> >  >     data in a given module scope. */
> >  > int svGetUserDataIdForScope(const svScope scope);
I'd propose:
        #define SV_NO_ID	0
        typedef int svUserId;
        svUserId svGetUniqueUserId();
> >  > /* Set arbitrary user data pointer into specified instance scope */
> >  > void svPutUserData(const svScope scope, int userDataId, void* userData);
> >  >
> >  > /* Retrieve arbitrary user data from specified instance scope */
> >  > void* svGetUserData(const svScope scope, int userDataId );
I'd replace them with:
void  svPutUserData(const svScope scope, svUserId userId, void* userData);
void* svGetUserData(const svScope scope, svUserId userId);
Users may define their own layer for storing/retrieving data:
 
typedef ... DataKey;
void  myPutUserData(const svScope scope, DataKey key, void* userData);
void* myGetUserData(const svScope scope, DataKey key);
The implementation may look like:
static svUserId myId = SV_NO_ID; /* no assigned yet */
static getMyId() {
        return(myId != SV_NO_ID ? myId : (myId = svGetUniqueUserId()));
}
void  myPutUserData(const svScope scope, DataKey key, void* userData) {
        svUserId Id = getMyId();
        LIST   *ptr = (LIST*)svGetUserData(scope, Id);
        if (!ptr) { /* no list yet */
                ptr = (LIST*)malloc(sizeof(LIST));
                ...
        }
        ....
        /* search the list ptr for a key */
        ....
        /* if not found, allocate and link a new list elem */
        ....
        /* elem for a key exists (found or a new one); put data into it */
        ptr-> ... = userData;
        /* update the list */
        svPutUserData(scope, Id, ptr);
}
> >  > The returned ID can be stored in a place known to the
> >  > C code (most likely a static or global variable) and
> >  > later be frequently referenced during run-time when
Yes.
> >  > The functions svPutUserData() and svGetuserData() each
> >  > require a module scope handle and a user data ID argument.
"user ID" rather than "user data ID"
> >  > ID=0 is reserved to denote the NULL or invalid ID. This
> >  > allows a variable used to store an ID to be conveniently
> >  > tested for validity.
--->  SV_NO_ID
> >  > class MyCModel {
> >  >      private:
> >  >          static int dUserDataId;
> >  >      public:
> >  >          // Constructor
> >  >              ....
> >  >              // Allocate a unique ID to be used as key to associate
> >  >              // user data with module scope. Skip this step if ID
> >  >              // has already been assigned.
> >  >              if( dUserDataId != 0 )
> >  >                  dUserDataId = svGetUserDataIdForScope( scope );
> >  >              ....
I would rather request ID only once per application, rather than once per 
instance/class.
Thanks and regards,
Andrzej
This archive was generated by hypermail 2b28 : Wed Mar 26 2003 - 08:08:58 PST