Testbench architecture: Mapping to implementation
Divide the functionality to various blocks or layers. Map the blocks to classes. Designate the classes as data classes and processing classes. Clearly define the…
Divide the functionality to various blocks or layers. Map the blocks to classes. Designate the classes as data classes and processing classes. Clearly define the interface between various classes for communicating the information and achieving the synchronization.
Data classes do not have any threads for processing. While processing classes have the single or multiple threads internally to process the data classes.
Data classes help model transaction classes or helper classes. Transaction classes represent a unit of data, which stays together. Example of transaction data class can be protocol data units (PDU) of the bus protocol or image to be processed by image processing engine. Helper classes can come in variety of forms containing various related tasks and functions. They could be forming different types of protocol data units for processing based on discrete information, implementing various encoding & decoding algorithms, managing sequence numbers etc.
For processing classes the number of threads, blocking and unblocking conditions for threads, pseudo code for the functionality of the thread should be specified.
Arbitrations are tricky to design in both the RTL and behavioral form. For any arbiters clearly identify the purpose of arbitration, at what level of abstraction the arbitration needs to be implemented, which unit of data is arbitrated. Behavioral arbitration structure should additionally have ability to start and stop the arbitration process and ability to override the arbitration scheme defined.
Concurrent threads even if they execute in zero time, if they have blocking statements there is no guarantee on atomic execution of threads. This has to be kept in mind.
Shared resources such as state objects should be protected with the semaphores for access. Clearly define what part is being protected, on what conditions lock will be acquired and what will conditions to release the locks.
Parent objects should have pointer to child objects and child objects should have pointer to parents. This is really useful in the during the debugs in the interactive debug environment.