IM324: Support one-time callbacks and multiple callbacks

From: Per Bojsen <per.bojsen@amd.com>
Date: Tue Mar 30 2010 - 09:55:54 PDT

Hi,

Here's my attempt at capturing what we talked about at the last few
meetings. I took Amy's latest proposal from 3/3/2010 and modified it
to include notify pipe handles and multiple callbacks:

The following is a function declaration for notification callback functions that
are used to notify the C side that an operation is possible on an input or output
transaction pipe.

typedef void (*scemi_pipe_notify_callback)(
     void *context ); // input: C model context

The following is a type declaration of the notify callback handles.

typedef <implementation defined type> scemi_pipe_notify_handle;

The notify callback handle type is opaque and the underlying type is
implementation defined.

All notification callbacks must be registered using the following call:

scemi_pipe_notify_handle scemi_pipe_set_notify_callback(
     void *pipe_handle, // input: pipe handle
     scemi_pipe_notify_callback notify_callback,
                            // input: notify callback function
     void *notify_context, // input: notify context
     int when = 0 // input: notify condition
);

Note the following properties:

* pipe_handle - the handle identifying the specific pipe as derived from the unique combination of the HDL scope and the pipe ID (see section 0)

* notify_callback - the name of the user callback function being registered.

* notify_context - the user defined context object to be passed to the function whenever it is called

* when - the user defined notify condition.

When conditions:

* 0: Static and persistent call back; callback condition determined by infrastructure based on the mode of operation.

* N > 0: Dynamic and one-time callback; callback condition specified by the application per callback registration.
         . For input pipe: call back when scemi_pipe_c_can_send() >= N.
         . For output pipe: call back when sceni_pipe_c_can_receive() >= N.

The return value of scemi_pipe_set_notify_callback is a notify callback handle
that uniquely identifies the callback. Any number of callbacks can be
registered for each pipe. On notify events, if more than one callback is
eligible to be called (as determined by the when argument), they eligible
callbacks will be called in the order of registration.

If a callback modifies the pipe state in any way, e.g., by removing elements
from the pipe, any downstream callbacks will see the effect of this operation.

This handle can be used to remove a
callback at any time using the following function:

bool scemi_pipe_clear_notify_callback(
   scemi_notify_handle notify_handle // input: notify callback handle
);

[Note: I don't think bool is a valid C type except in very recent C
versions but we can adjust that.]

The scemi_pipe_clear_notify_callback() returns true if the notify callback
identified by the notify_handle argument was successfully removed. It returns
false, otherwise. Those conditions include:

   * The notify_handle value is not a value returned by a previous
     scemi_pipe_set_notify_callback() call.

   * The callback was already removed by a prior call of
     scemi_pipe_clear_notify_callback().

   * The callback was registered with a when value greater than 0 and the
     callback has expired and been removed by the infrastructure.

The following call can be used to retrieve a notify context object for a given
notify callback:

void *scemi_pipe_get_notify_context( // return: notify context object pointer
     scemi_pipe_notify_handle notify_handle ); // input: notify handle

*******

The following example shows how dynamic callback can be used to implement the blocking send function on top of the non-blocking send function:

static void notify_ok_to_send_or_receive(
     void *context ){ // input: notify context
     sc_event *me = (sc_event *)context;
     me->notify();
}

void scemi_pipe_c_send(
     void *pipe_handle, // input: pipe handle
     int num_elements, // input: #elements to be written
     const svBitVecVal *data, // input: data
     svBit eom ) // input: end-of-message marker flag
{
   int byte_offset = 0;
   int elements_sent;
   int pipe_depth = scemi_pipe_get_depth(pipe_handle);
   while( num_elements ){
     elements_sent = scemi_pipe_c_try_send(pipe_handle, byte_offset, num_elements, data, eom );
     byte_offset += elements_sent * scemi_pipe_get_bytes_per_element( pipe_handle );
     num_elements -= elements_sent;
     if(num_elements > 0){
       int N = (num_elements > pipe_depth)?pipe_depth:num_elements;
       if( ok_to_send == NULL ) ok_to_send = new sc_event;
       scemi_pipe_set_notify_callback(pipe_handle, notify_ok_to_send_or_receive, ok_to_send, N);
       wait( *ok_to_send );
     }
   }
}

Thanks,
Per

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Tue Mar 30 09:56:40 2010

This archive was generated by hypermail 2.1.8 : Tue Mar 30 2010 - 09:56:47 PDT