
The registered callback function is busReadWrite,
which breaks out the address, byte enable mask pointer and data
pointer. A switch statement on the mask is used
to determine the offset of the actual byte requested and hence the
exact byte address, allowing for the endianness of the model. This
also provides a check that only a single byte is being requested.
switch( *((uint32_t *)maskPtr) ) {
case 0x000000ff: offset = isLittleEndian ? 0 : 3; break;
case 0x0000ff00: offset = isLittleEndian ? 1 : 2; break;
case 0x00ff0000: offset = isLittleEndian ? 2 : 1; break;
case 0xff000000: offset = isLittleEndian ? 3 : 0; break;
default: // Invalid request
payload.set_response_status( tlm::TLM_GENERIC_ERROR_RESPONSE );
return;
}
In a perfect world, the router/arbiter function would have masked
the address to the range handled by the UART. However for this
simple model, the full address is received, so masking with
UART_ADDR_MASK is carried out here, to give the
address of the UART register being read.
Separate functions, busRead and
busWrite are used to implement the register
specific behavior, selected as appropriate based on the payload
command field.
Single byte reads and writes always succeed, so the response is set
to tlm::TLM_OK_RESPONSE in all cases.
