Posted by Shankar Hemmady on 4th September 2009
Rahul V. Shah (bio)
Director of Customer Solutions, eInfochips
It is always challenging when it comes to controlled randomization. Constraints may be an easier way to think about it, but at chip level we are often interested in generating a few scenarios which are controlled in specific sequences. However, we still don’t want to develop scenarios that are very directed.
Let’s consider an example: we have an AHB bus interface with different master. We have a DMA controller on the bus along with few other masters. The chip level stress scenario might include multiple master performing data transfer to the memory interface on the bus. The transactions can be completely random. To make the scenario more interesting, we may want to add random reads from the status register, random read of some read only registers along with other data xfer.
One of the scenarios can include handling an error/exception scenario where we want read the status register, followed by the interrupt register followed by a write transfer to clear the interrupt. In the normal scenario, we can generate such scenario in directed fashion. But that will take away the random behavior.
Earlier, such scenarios were implemented in a lot more complex fashion as it was difficult to create a random scenario while getting exclusive access to randomness whenever required. Here I describe a mechanism to get exclusive access to a channel when required, while utilizing the benefits of randomness.
Scenario generators are used to generate a sequence of transactions. Multiple scenario generators may be connected to the same output channel but such a connection does not prevent other generators to concurrently inject transactions to that channel. A scenario is thus not guaranteed the exclusive access to an output channel. Multiple threads in the same multi-stream scenario, or multiple single stream scenarios, or any transactor may inject transactions in the same channel.
If the requirement is to generate a sequence of transactions without any interruption from other generator or from any transactor, an exclusive access of channel can be obtained and later released when exclusive access is no longer required. Let’s consider the scenario below:
01. class my_scenario extends vmm_ms_scenario;
02. rand atm_cell atm_cell_inst ;
03. atm_cell_channel atm_out_chan;
04. int MSC = this.define_scenario(“MY SCENARIO”, 0);
05. local bit [7:0] id;
07. function new();
09. atm_cell_inst = new;
10. endfunction: new
12. task execute(ref int n);
13. $cast(atm_out_chan, this.get_channel(“ATM_SCENARIO_CHANNEL”));
15. repeat (10) begin
17. repeat (10) @ (posedge clk) ;
20. endtask: execute
21. endclass: my_scenario
If a scenario requires exclusive access to a channel to ensure the uninterrupted execution of the sequence of transactions, it can grab the channel as shown in line 16, atm_out_chan.grab(this). This will grab the atm_out_chan channel and once grabbed, access of this channel will not be provided to any other scenario until it is explicitly ungrabbed. As shown in lines 15-18, the scenario sends 10 sequential transactions with a delay of 10 clock cycless after grabbing the channel. To inject transactions in the grabbed channel, a reference to the scenario currently injecting the transaction must be provided to the put method as shown in line 16 atm_out_chan.put(atm_scenario,.grabber(this)). After completion of the sequence of transactions, the channel is ungrabbed at line 19 atm_out_chan.ungrab(this).
When the channel is grabbed by one scenario and other scenarios try to put transactions in the same channel, the put method is blocked until the channel is ungrabbed by the scenario who has previously grabbed the channel. To prevent the blocking that would occur as a result of the grabbed channel, we can check the status of the channel using the vmm_channel::is_grabbed() function. This function will return “1”, if the channel is grabbed.