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