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.