Two functions are declared as static member functions to implement the upcalls from the Or1ksim library (see Section 4.2.6 for an explanation of why these functions are static).
The static functions receive the pointer to the
Or1ksimSC
instance which originally started the
Or1ksim ISS (provided as an argument to
or1ksim_init
described in Section 4.3.3).
This allows each static function to call the instance function which
implements the upcall, as shown here with
staticReadUpcall
:
int Or1ksimSC::staticReadUpcall (void *instancePtr, unsigned long int addr, unsigned char mask[], unsigned char rdata[], int dataLen) { Or1ksimSC *classPtr = (Or1ksimSC *) instancePtr; return classPtr->readUpcall (addr, mask, rdata, dataLen); } // staticReadUpcall()
The instancePtr
argument allows identification of
the particular instance of the class which called
or1ksim_run
and hence to which the upcall is
directed. The remaining arguments are passed to the instance method
unchanged.
Caution | |
---|---|
It might be thought that providing a direct upcall to the C++
upcall functions of the class would be more efficient, using the C++
member reference operator ( Linkage to static functions is much simpler and usually works between C and C++. So the approach used here is more reliable. |
The upcalls from the ISS generate the transactional activity. These functions set up the payload, execute the transaction (i.e exchange the payload and result with the target) and return the result to the ISS.
The example here is coded in a very simple fashion, in the knowledge
that the requests to read are always four bytes long (the OpenRISC 1000 has
a simple 32 bit bus), possibly with some bytes masked out for byte
and half-word reads. This matches the default
BUSWIDTH
of the simple initiator socket.
As noted in Section 4.2.6, the payload is declared as a class instance variable, rather than locally here for performance reasons. This has the added benefit that it will also work should we ever convert the model to using a non-blocking socket, where the lifetime of the payload would need to be longer than the lifetime of the upcall. TLM 2.0 requires that the payload, data and mask fields all remain valid for the duration of the complete transaction.