2.4.13 PVBusSlaveControl protocol

The PVBusSlaveControl protocol enables you to access and modify the underlying memory that PVBusSlave controls.

setFillPattern(uint32_t fill1, uint32_t fill2)
This sets a two-word alternating fill pattern to be used by uninitialized memory.
setAccess(pv::bus_addr_t base, pv::bus_addr_t top, pv::accessType type, pv::accessMode mode)

This reconfigures handling for a region of memory.

base (inclusive value) and top (exclusive value) specify the address range to configure.

type selects what types of bus access must be reconfigured. It can be one of:


mode controls what happens when an address is accessed. Legal values for the pv::accessMode enumeration are:

Act as memory. The PVBusSlave manages the underlying storage to provide 4KB of memory, which can be ROM or RAM, depending on how you configure it to handle bus write transactions.
Act as a device. Requests to the select pages are routed to the PVBusSlave device port, where the necessary behavior can be implemented by the component.
Generate bus abort signals for any accesses to this page.
Ignore accesses to this page. Bus read requests return 0.
getReadStorage(pv::bus_addr_t address, pv::bus_addr_t *limit) : const uint8_t *
getWriteStorage(pv::bus_addr_t address, pv::bus_addr_t *limit) : uint8_t *

These two methods permit you to access the underlying storage that PVBusSlave allocates to implement a region of memory.

The return value is a pointer to the byte that represents the storage corresponding to the address of base.

The limit pointer returns the device address for the limit of the accessible memory.

The pointer value returned is not guaranteed to remain valid indefinitely. Bus activities, or other calls to the control port, might invalidate the pointer.

provideReadStorage(pv::bus_addr_t device_base, pv::bus_addr_t device_limit, const uint8_t *storage)
provideWriteStorage(pv::bus_addr_t device_base, pv::bus_addr_t device_limit, uint8_t *storage)
provideReadWriteStorage(pv::bus_addr_t device_base, pv::bus_addr_t device_limit, uint8_t *storage)

These methods enable you to allocate blocks of memory that the PVBusSlave can use to manage regions of RAM/ROM. Only use these methods when you require a high degree of control over memory, such as when you require a device to map specific regions of host memory into the simulation.

The memory region pointed to by storage must be large enough to contain (limit - base) bytes.

After these calls, PVBusSlave controls access to the underlying memory. The owner must call getWriteStorage() before modifying the memory contents and getReadStorage() before reading the memory contents.

provideReadStorageEx(pv::bus_addr_t device_base, pv::bus_addr_t device_limit, const uint8_t *storage, double latency)
provideWriteStorageEx(pv::bus_addr_t device_base, pv::bus_addr_t device_limit, const uint8_t *storage, double latency)
provideReadWriteStorageEx(pv::bus_addr_t device_base, pv::bus_addr_t device_limit, uint8_t *storage, double read_latency, double write_latency)

These methods take additional parameters to specify average latencies (in seconds) per byte, used when Timing Annotation is enabled.

In all other aspects they behave the same as provideReadStorage(), provideWriteStorage() and provideReadWriteStorage(), respectively.

slave behavior getRegionIterHandle(): uint32_t;
slave behavior getNextRegionInfo(uint32_t iter_handle, pv::PVBusSlaveRegionInfo *info) : bool;
slave behavior closeRegionIterHandle(uint32_t iter_handle);

These methods form an iterator-like API that allows a PVBusSlave providing storage to report all the regions of the address space that have backing store.

The iteration begins by calling getRegionIterHandle(). This allocates an iterator and if successful returns a nonzero iter_handle to identify it.

The caller can then repeatedly call getNextRegionInfo() with iter_handle. If it finds a region, the behavior returns true and writes to the info struct if the pointer is non-null. Access the data in the region using getReadStorage() or getWriteStorage().

The implementation can return regions in any order. They can be of any size or alignment, but must not overlap.

The implementation need not report allocated regions that are filled entirely with the default fill pattern, or allocated regions that contain only the data they had at simulation start.

On reaching the last region, the iterator closes automatically. If the handle is invalid or there are no further regions, the behavior returns false.

A caller can close an iterator opened by getRegionIterHandle() at any time using closeRegionIterHandle(). This deallocates the iterator, and further uses of the handle are invalid.

Non-ConfidentialPDF file icon PDF version100964_1110_00_en
Copyright © 2014–2020 Arm Limited or its affiliates. All rights reserved.