by Amit Kumar Jain, Questa VIP Product Team, Mentor Graphics
ABSTRACT
In a multi-processor system, a cache coherence protocol is vital to maintaining data consistency between local caches and the main memory. With the local processor cache, the bus stimulus must be compliant with the cacheline state in the local cache, and must follow predefined ordering rules between the read/write and cache snoop stimulus. These constraints can make it confusing to generate stimulus on a cache coherent interface. This article addresses such stimulus generation issues by providing easy to use generic APIs along with a cache controller.
INTRODUCTION
The advent of heterogeneous, multi-processor systems with multiple caches sharing the same data has made interconnect design more complex and prompted the development of cache coherent protocols such as ARM® AMBA® 4 ACE (AXI Coherency Extension) and ARM® AMBA® 5 CHI (Coherent Hub Interface).
As per the latest cache coherency protocol specifications from ARM®, the cached processor bus stimulus is compliant with the particular initial cacheline state in the local cache. Similarly, the processor needs to update the cacheline state and data in the local cache as needed at the end of a transaction. If a user is creating a testbench environment for verifying a cache coherent interface, the stimulus dependency on cache memory can complicate user sequences. The user needs to access cache memory at the start and end of each transaction. Beyond dependency on the local cache, there is dependency on setting the address region and domain (shareable or non-shareable) that is, in general, based on a system address map.
For example, here are the steps if a user wants to perform a cache maintenance operation (CMO):
- Check system address map to make sure address lies correctly in one of the shareable regions
- Access the master cache model to check initial cacheline state
- Check ordering for the same ID and cacheline transactions in progress
- Set a longer list of transaction attributes as per protocol legality
- Perform the cache data/state update at end of transaction, as needed
AMBA® 4 ACE and AMBA® 5 CHI Questa Verification IP (VIP) introduces a single ACE/CHI QVIP agent with a generic API master sequence and master cache controller. This makes it easier for a user to generate stimulus on a cache coherent interface without worrying about accessing/ updating the cache and accessing the system address map; the cache controller takes care of this internally.
 |
Figure 1: Generic master sequence.
|
GENERIC MASTER SEQUENCE
This is a simple reusable sequence that provides a different set of APIs such as instruction-level and transactional read/write, and barrier and coherency. APIs in the generic sequence further make use of the cache controller APIs to execute the transaction and perform the required operation. The cache controller implements logic to execute the transaction on the bus after doing required operations such as accessing the cache memory and system address map. At the end of transaction, it performs the required cache memory update.
Generic read/write instruction-level APIs To verify a processor-based interface, a user needs to read or write a chunk of data in memory preferably without worrying about protocol intricacies and a huge list of attributes associated with the protocol-specific transaction items. So the first stimulus generation requirement is for a generic read/write instruction-level API. Figure 2 shows a generic transaction item for passing generic read/write transaction information to the read/write API. This sequence item encapsulates a request to read or write a selected number of bytes in the system/cache memory.
class rw_txn extends uvm_sequence_item;
typedef rw_txn this_t;
typedef enum bit[7:0] {READ, WRITE, BARRIER} cmd_e;
typedef enum bit[7:0] { OKAY, ERROR } status_e;
typedef longint unsigned addr_t;
// Input attributes
int id = -1;
rand cmd_e cmd;
rand addr_t addr;
rand int size;
// This is Write data input for WRITE cmd, output for
// READ cmd
rand byte unsigned data[];
rand bit strobes[];
// Output attributes – Set after execution is complete status_e status; |
Figure 2: Generic read/write transaction class.
|
The read/write API is for conducting basic reads and writes as if from a program running on a processor. It provides a basic interface, letting the master cache controller choose the most appropriate bus protocol transaction based on current cache state and the type of memory being targeted (snoopable, non-snoopable, etc).
The API methods have only a handful of simple arguments (command, address and data) with no direct dependency on bus-specific attributes. Bus-specific attributes will be determined configurations that change less frequently such as the address map and attributes API, both of which are described later.
The generic master sequence provides the following instruction level read/write APIs, as well as a read/write transaction API (with minimal arguments and no protocol or cache dependencies). Figure 3 shows a basic block diagram and Figure 4 (on the next page) provides the code.
 |
Figure 3: Generic read/write instruction level API.
|
Generic Read-Write Instruction API Declaration Abstract Writes
// Write a single byte of data at addr
task write8 (longint unsigned addr, byte unsigned data,
int id=-1);
// Write a single 16-bit half-word of data at addr
task write16 (longint unsigned addr, shortint data,
int id=-1);
// Write a single 32-bit word of data at addr
task write32 (longint unsigned addr, int data,
int id=-1);
// Write a single 64-bit long word of data at addr
task write64 (longint unsigned addr, longint data,
int id=-1);
// Write a variable-length array of data at addr
task write (longint unsigned addr, ref byte unsigned
data[], input int id=-1); Abstract Reads
// Read a single byte of data at addr
task read8 (longint unsigned addr,
output byte unsigned data,
input int id=-1);
// Read a single 16-bit half-word of data at addr
task read16 (longint unsigned addr, output shortint data,
input int id=-1);
// Read a single 32-bit word of data at addr
task read32 (longint unsigned addr, output int data,
input int id=-1);
// Read a single 64-bit long word of data at addr
task read64 (longint unsigned addr, output longint data,
input int id=-1);
// Read size number of bytes into data starting from addr
task read (longint unsigned addr, ref byte unsigned
data[], input int unsigned size, int id=-1); Barrier
// Execute a barrier transaction with the optional
transaction
// stream id
task barrier (int id = -1); Transaction RW
// Execute a transaction whose attributes are specified in
// txn, of type rw_txn (generic read/write transaction class).
task execute_txn (rw_txn txn); |
Figure 4: Generic read/write instruction API declarations.
|
Coherency APIs
The instruction-level and transactional read/write APIs mentioned above are declared within a generic reusable master sequence. Along with these APIs, a user would also want to run protocol specific coherency transactions. Coherency APIs provide flexibility to the user to run coherency transactions such as cache-maintenance operations (CMO), copy-back (CB), DVM and barrier transaction.
If a user wants to run a CMO, then generally he wants to run specific cache maintenance operations on a selected cacheline instead of worrying about lots of other protocolrelated transaction attributes. This coherency API takes the CMO transaction type and cacheline address information from the user (with an optional transaction stream-ID) as input. The coherency API for copy-back operations behaves similarly.
Along with generic coherency APIs is an API to run a busspecific transaction/sequence-item directly, so that the user has the flexibility to specify transaction item attributes. Figure 5 gives the list of coherency APIs in the generic master sequence; Figure 6, the coherency API declarations.
 |
Figure 5: Coherency APIs.
|
Coherency API Declarations
// Execute a specific cache maintenance transaction
// on particular cacheline
task execute_cmo_txn (txn_type_e txn_type,
longint unsigned addr,
int id = -1);
// Execute a copy back transaction on particular
// cacheline (CB transaction is chosen based on
// initial cacheline state)
task execute_cb_txn (longint unsigned addr,
int id = -1,
bit invalidate);
// Initiate a DVM transaction
task execute_dvm_txn (dvm_info_s dvm_msg[],
int id = -1);
// This API is meant for the user to start a desired
// protocol specific transaction/sequence-item
task execute_ace_txn (ace_rw_txn txn); // For ACE
task execute_chi_txn (chi_rw_txn txn); // For CHI |
Figure 6: Coherency API declarations.
|
MASTER CACHE CONTROLLER
The cache controller is a background process that runs continuously on the VIP master components. It receives and executes read/write requests from user sequences and automatically performs protocol compliance/legality checks (such that ordering rules are followed to generate legal stimulus as per protocol specification) and cache updates. This is the base class for driving stimulus and controlling behavior on a cached master VIP. It contains handles to the cache memory model and VIP configuration class object. The controller basically starts transactions on both read and write channels depending on the cacheline state, as illustrated in figure 7.
Transaction ordering rules and related protocol compliance/ legality are automatically taken care by controller logic. An example: an ordering rule requires that while generating stimulus a CMO transaction should be issued only after the previous CMO transaction is completed inside the controller.
 |
Figure 7: Master cache controller.
|
The master cache controller generates a transaction stimulus on the read/write request channel and handles snoop requests on the snoop virtual channel. As a cache processor is also responsible for responding to snoop requests on its respective channel, the controller implements respective snoop handling logic.
The snoop sequence logic in controller receives snoop requests via the snoop request virtual channel, processes the request, possibly modifies the cacheline state in its local cache (whenever needed) and then sends the appropriate response on the response virtual channel. If data transfer must occur, it is sent via the data virtual channel.
CACHE MODEL, SYSTEM ADDRESS MAP AND ATTRIBUTES API
As described above, a generic master sequence consists of the following set of APIs:
- Generic read/write instructions
- Transactional read/write
- Coherency API
The top level transaction includes many attributes to allow precise control over bus activity, but remains simple to use as the API is abstracted so that only minimal inputs are required.
The Master controller implements execution of these generic APIs and finally starts at the top abstraction level bus sequence item on the VIP BFM. In order to do this, the master controller needs to obtain and set values of all other transaction attributes that are not provided as input to generic instruction read/write or coherency APIs.
These attributes come through the following means:
- Master local cache
This is accessed at the start of a transaction to determine if the transaction to be executed is legal or not as per the initial cacheline state. It extracts the following information from the cache model for executing transactions on the bus:
- Cacheline state
- Cacheline data
- System address map
This defines the address map for a master and consists of multiple address region entries. Each address map entry defines the range of addresses and attributes for addresses in this entry. These attributes are:
- Target : The slave (target) that services requests to this region of memory
- Domain: Shareable (inner/outer) or non-shareable
- Region: The optional region in which this memory belongs
- Prot: Protection mechanism attributes mapped to by the address map
- Memory type: Normal or device memory
- Attributes API
There are a few other transaction attributes that are not extracted from the cache model and system address map. A separate attributes API (set/get methods for each attribute) is provided in the generic master sequence that can be set once and used by multiple transactions until changed again. If not set, then the default value is used for the attribute.
VIP AGENT
The Verification IP agent (shown below) automatically does the following:
- Creates and maintains the cache memory model
- Automatically starts the cache controller
 |
Figure 8: VIP UVM agent.
|
CONCLUSION
This article lists and describes VIP master APIs that could be reused to generate stimulus on a cache coherent interface without worrying about accessing the cache model and other testbench objects that are typically needed to know about transaction attributes. Instruction level read/ write and coherency APIs make it easy to write stimulus sequences on a cache coherent interface such as ARM® AMBA® 4 ACE and AMBA® 5 CHI.
REFERENCES
- ARM® AMBA®4 AXI and ACE Protocol Specification – IHI0022E by ARM®
- UVM – Universal Verification Methodology Cookbook
Back to Top