3.5 Memory access

Memory accesses are performed by the CADI methods CADIMemRead() and CADIMemWrite().

In contrast to register accesses, a memory access is not described by a data structure but by several parameters that must be passed to the methods.

The prototype of CADIMemRead(), for example, is:

CADIReturn_t CADIMemRead( CADIAddrComplete_t startAddress,
                            uint32_t unitsToRead, 
                            uint32_t unitSizeInBytes, 
                            uint8_t *data,
                            uint32_t *actualNumOfUnitsRead, 
                            uint8_t doSideEffects);

The start address is specified in the location.add data member of an object of type CADIAddrComplete_t.

The unitsToRead and unitSizeInBytes parameters specify the number and the size of units that are accessed. The size of a unit is specified in bytes and must be a supported multiple of the Minimum Access Size (MAU). A list of the supported multiples can be obtained from the corresponding memory block information.

Note:

Memory accesses must consider invariance. The unitSizeInBytes memory space property specifies the number of bytes that are treated as one unit. The coherence of these bytes is preserved, especially if converting endianness.

The total memory accessed in bytes is equal to the number of access units multiplied by their size in bytes. The data buffer that is used to perform the memory access is an array of uint8_t that must have exactly the same size as the complete access size.

The number of actually read or written access units is returned. If the memory access is completely successful, the value identified by actualNumOfUnitsRead equals the number of units requested in unitsToRead.

Note:

The requested number of units is not the size in bytes.

If an access succeeds partially, the returned number equals the number of completed units, and the contents of data is valid for additional processing. An example of such a situation is an attempt to access memory that is not part of a memory block. This might happen when performing an access that exceeds a valid memory range.

Memory accesses can be optionally performed depending on the corresponding parameter passed to CADIMemRead() or CADIMemWrite(). As for register accesses, the target ultimately must decide which side effects can be omitted.

For CADIMemRead(), an example of a side effect is clear-on-read. If a read is done with the doSideEffects parameter set to false, all side effects must be omitted. Such a debug read cannot interfere with the execution of the target.

A side effect during writing to memory might be for example the usage of a memory-mapped register whose contents control the mode of a certain component. If this value is changed, the component must perform this side effect even if doSideEffects is set to false. If the side effect was not done, the simulated target would behave incorrectly.

Writing to memory
eslapi::CADI* cadi;
eslapi::CADIMemSpaceInfo_t mem_space;
eslapi::CADIMemBlockInfo_t mem_block;
// ...fill the variables declared above with feasible data...
// Preparing a write access to the beginning of the memory block.
eslapi::CADIAddrComplete_t startAddress;
startAddress.location.space = mem_space.memSpaceId;
startAddress.location.addr = mem_block.startAddr;
// Writing 256 4-byte words.
uint32_t unitsToWrite = 256;
uint32_t unitSizeInBytes = 4;
uint32_t actualNumOfUnitsWritten = 0;
uint32_t completeAccessInBytes = unitsToWrite * unitSizeInBytes;
uint8_t* data = new uint8_t[completeAccessInBytes]();
// ...filling data buffer "data"...
eslapi::CADIReturn_t status;
status = cadi->CADIMemWrite(startAddress, unitsToWrite, unitSizeInBytes,
                            data,&actualNumOfUnitsWritten, 0); 
// Do no side effects.
// ...check status and actualNumOfUnitsWritten...
delete[] data;
Non-ConfidentialPDF file icon PDF version100963_0200_03_en
Copyright © 2014–2018 Arm Limited or its affiliates. All rights reserved.