lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 1 | {{% lowrisc-doc-hdr Comportable IP Testbench Architecture }} |
| 2 | |
| 3 | Going along the lines of what it takes to design an IP that adheres to the |
| 4 | [Comportability Specifications](../../../../doc/rm/comportability_specification.md), |
| 5 | we attempt to standardize the DV methodology for developing the IP level |
| 6 | testbench environment as well by following the same approach. This document describes |
| 7 | the Comportable IP (CIP) library, which is a complete UVM enviromnent framework that |
| 8 | each IP level environment components can extend from to get started with DV. The goal |
| 9 | here is to maximize code reuse across all test benches so that we can improve the |
| 10 | efficiency and time to market. The features described here are not exhaustive, |
| 11 | so it is highly recommended to the reader that they examine the code directly. In |
| 12 | course of development, we also periodically identify pieces of verification logic that |
| 13 | might be developed for one IP but is actually a good candidate to be added to |
| 14 | these library classes instead. This doc is instead intended to provide the user |
| 15 | a foray into what these are and how are the meant to be used. |
| 16 | |
| 17 | {{% toc 3 }} |
| 18 | |
| 19 | |
| 20 | ## CIP environment block diagram |
| 21 |  |
| 22 | |
| 23 | ## CIP library classes |
| 24 | The CIP library includes the base ral model, env cfg object, coverage |
| 25 | object, virtual sequencer, scoreboard, env, base virtual sequence and finally |
| 26 | the test class. To achieve run-time polymorphism, these classes are type |
| 27 | parameterized to indicate what type of child objects are to be created. In the |
| 28 | IP environments, the extended classes indicate the correct type parameters. |
| 29 | |
| 30 | ### cip_base_env_cfg |
| 31 | This class is intended to contain all of the settings, knobs, features, interface |
| 32 | handles and downstream agent cfg handles. Features that are common to all IPs in |
| 33 | accordance with the comportability spec are made a part of this base class, while the |
| 34 | extended IP env cfg class will contain settings specific to that IP. An instance of |
| 35 | the env cfg class is created in `cip_base_test::build_phase` and the handle is |
| 36 | passed over uvm_config_db for the CIP env components to pick up. This allows |
| 37 | the handle to the env cfg object to be available in the env's build_phase. Settings |
| 38 | in the env cfg can then be used to configure the env based on the test needs. |
| 39 | |
| 40 | A handle to this class instance is passed on to the scoreboard, virtual |
| 41 | sequencer and coverage objects so that all such common settings and features |
| 42 | are instantly accessible everywhere. |
| 43 | |
| 44 | This class is type parameterized in the following way: |
| 45 | ``` |
| 46 | class cip_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object; |
| 47 | ``` |
| 48 | The IP env cfg class will then extend from this class with the RAL_T parameter set |
| 49 | to the actual IP RAL model class. This results in IP RAL model getting factory |
| 50 | overridden automatically in the base env cfg itself during creation, so there is no |
| 51 | need for manual factory override. We follow the same philosophy in all CIP library |
| 52 | classes. |
| 53 | |
| 54 | The following is a list of common features and settings: |
| 55 | * **clk_rst_if**: A handle to the clk_rst_if that controls the main clk and reset |
| 56 | to the DUT. |
| 57 | * **intr_vif**: This is a handle to the `pins_if #(NUM_MAX_INTERRUPTS=64)` interface |
| 58 | instance created in the tb to hookup the DUT interrupts. The actual number of |
| 59 | interrupts might be much less than 64, but that is ok - we just connect as |
| 60 | many as the DUT provides. The reason for going with a fixed width pins_if is |
| 61 | to allow the intr_vif to be available in this base env cfg class (which does not |
| 62 | know how many interrupt each IP DUT provides). |
| 63 | * **alerts_vif**: This is a handle to the `pins_if #(NUM_MAX_ALERTS=64)` interface |
| 64 | instance created in the tb to hookup the DUT alerts, similar to intr_vif. |
| 65 | * **devmode_vif**: THis is a handle to the `pins_if #(1)` interface instance created |
| 66 | in the tb to hookup the DUT input `devmode`. |
| 67 | * **tl_agent_cfg**: The downstream TileLink host agent created in the cip_base_env |
| 68 | class requires the agent cfg handle to tell it how to configure the agent. |
| 69 | * **ral**: This is the instance to the auto-generated RAL model that is |
| 70 | extended from `dv_base_reg_block`. In the base class, this is created using |
| 71 | the RAL_T class parameter which the extended IP env cfg class sets correctly. |
| 72 | |
| 73 | Apart from these, there are several common settings such as `zero_delays`, |
| 74 | `clk_freq_mhz`, which are randomized as well as knobs such as `en_scb` and |
| 75 | `en_cov` to turn on/off scoreboard and coverage collection respectively. |
| 76 | |
| 77 | The base class provides a virtual method called `initialize()` which is called |
| 78 | in `cip_base_test::build_phase` to create some of the objects listed above. If |
| 79 | the extended IP env cfg class has more such objects added, then the `initialize()` |
| 80 | method is required to be overridden to create those objects as well. |
| 81 | |
| 82 | We make all downstream interface agent cfg handles as a part of IP extension of |
| 83 | cip_base_env_cfg so that all settings for the env and all downstream agents are |
| 84 | avaiable within the env cfg handle. Since the env cfg handle is passed to all cip |
| 85 | components, all those settings are also accesible. |
| 86 | |
| 87 | ### cip_base_env_cov |
| 88 | This is the base coverage object that contain all functional coverpoints and |
| 89 | covergroups. The main goal is to have all functional coverage elements |
| 90 | implemented in a single place. This class is extended from `uvm_component` |
| 91 | so that it allows items to be set via `'uvm_config_db` using the component's |
| 92 | hierarchy. This is created in cip_base_env and a handle to it is passed to the |
| 93 | scoreboard and the virtual sequencer. This allows coverage to be sampled in |
| 94 | scoreboard as well as the test sequences. |
| 95 | |
| 96 | This class is type parameterized with the env cfg class type `CFG_T` so that it |
| 97 | can derive coverage on some of the env cfg settings. |
| 98 | ``` |
| 99 | class cip_base_env_cov #(type CFG_T = cip_base_env_cfg) extends uvm_component; |
| 100 | ``` |
| 101 | |
| 102 | ### cip_base_virtual_sequencer |
| 103 | This is the base virtual sequencer class that contains a handle to the |
| 104 | `tl_sequencer` to allow layered test sequences to be created. The extended IP |
| 105 | virtual sequencer class will include handles to the IP specific agent |
| 106 | sequencers. |
| 107 | G |
| 108 | This class is type-parameterized with the env cfg class type `CFG_T` and coverage |
| 109 | class type `COV_T` so that all test sequences can access the env cfg settings and |
| 110 | sample the coverage via the `p_sequencer` handle. |
| 111 | ``` |
| 112 | class cip_base_virtual_sequencer #(type CFG_T = cip_base_env_cfg, |
| 113 | type COV_T = cip_base_env_cov) extends uvm_sequencer; |
| 114 | ``` |
| 115 | |
| 116 | ### cip_base_scoreboard |
| 117 | This is the base scoreboard component that already connects with the TileLink |
| 118 | agent monitor to grab tl packets via analysis port at the address and the data |
| 119 | phases. It provides a virtual task called `process_tl_access` that the extended |
| 120 | IP scoreboard needs to implement. Please see code for additional details. The |
| 121 | extended IP scoreboard class will connect with the IP-specific interface monitors |
| 122 | if applicable to grab items from those analysis ports. |
| 123 | |
| 124 | This class is type-parameterized with the env cfg class type `CFG_T`, ral class |
| 125 | type `RAL_T` and the coverage class type `COV_T`. |
| 126 | ``` |
| 127 | class cip_base_scoreboard #(type RAL_T = dv_base_reg_block, |
| 128 | type CFG_T = cip_base_env_cfg, |
| 129 | type COV_T = cip_base_env_cov) extends uvm_component; |
| 130 | ``` |
| 131 | There are several virtual tasks and functions that are to be overridden |
| 132 | in extended IP scoreboard class. Please take a look at the code for more |
| 133 | details. |
| 134 | |
| 135 | ### cip_base_env |
| 136 | This is the base UVM env that puts all of the above components together |
| 137 | and creates and makes connections across them. In the build phase, it retrieves |
| 138 | the env cfg class type handle from `uvm_config_db` as well as all the virtual |
| 139 | interfaces (which are actually part of the env cfg class). It then uses the env |
| 140 | cfg settings to modify the downstream agent cfg settings as required. All of |
| 141 | the above components are created based on env cfg settings, along with the TileLink |
| 142 | host agent. In the connect phase, the scoreboard connects with the monitor |
| 143 | within the TileLink agent to be able to grab packets from the TL interface |
| 144 | during address and the data phases. In the end of elaboration phase, the ral |
| 145 | model within the env cfg handle is locked and the ral sequencer and adapters are |
| 146 | set to be used with the TileLink interface. |
| 147 | |
| 148 | This class is type parameterized with env cfg class type CFG_T, coverage class type |
| 149 | `COV_T`, virtual sequencer class type `VIRTUAL_SEQUENCER_T` and scoreboard class |
| 150 | type `SCOREBOARD_T`. |
| 151 | ``` |
| 152 | class cip_base_env #(type CFG_T = cip_base_env_cfg, |
| 153 | type VIRTUAL_SEQUENCER_T = cip_base_virtual_sequencer, |
| 154 | type SCOREBOARD_T = cip_base_scoreboard, |
| 155 | type COV_T = cip_base_env_cov) extends uvm_env; |
| 156 | ``` |
| 157 | |
| 158 | ### cip_base_vseq |
| 159 | This is the base virtual sequence class that will run on the cip virtual |
| 160 | sequencer. This base class provides 'sequencing' set of tasks such as |
| 161 | `dut_init()` and `dut_shutdown()` which are called within `pre_start` and |
| 162 | `post_start` respectively. This sequence also provides an array of |
| 163 | sub-sequences some of which are complete tests within themselves, but |
| 164 | implemented as tasks. The reason for doing so is SystemVerilog does not |
| 165 | support multi-inheritance so all sub-sequences that are identified as being |
| 166 | common to all IP benches implemented as tasks in this base virtual sequence class. |
| 167 | Some examples: |
| 168 | * **task run_csr_vseq_wrapper**: This is a complete CSR test suite in itself - |
| 169 | Extended IP CSR vseq can simply call this in the body. This is paired with a |
| 170 | helper function `add_csr_exclusions`. |
| 171 | * **function add_csr_exclusions**: This is extended in the IP CSR vseq to add |
| 172 | exclusions when running the CSR suite of tests. |
| 173 | * **task tl_access**: This is a common generic task to create a read or a write |
| 174 | access over the TileLink host interface. |
| 175 | * **task cfg_interrupts, check_interrupts**: All interrupt CSRs are standardized |
| 176 | according to the comportability spec, which allows us to create common tasks |
| 177 | to turn on / off interrupts as well as check them. |
| 178 | |
| 179 | This class is type parameterized with the env cfg class type `CFG_T`, ral class type |
| 180 | `RAL_T` and the virtual sequencer class type `VIRTUAL_SEQUENCER_T` so that the |
| 181 | env cfg settings, the ral CSRs are accessible and the `p_sequencer` type can be |
| 182 | declared. |
| 183 | |
| 184 | ``` |
| 185 | class cip_base_vseq #(type RAL_T = dv_base_reg_block, |
| 186 | type CFG_T = cip_base_env_cfg, |
| 187 | type COV_T = cip_base_env_cov, |
| 188 | type VIRTUAL_SEQUENCER_T = cip_base_virtual_sequencer) extends uvm_sequence; |
| 189 | ``` |
| 190 | All virtual sequences in the extended IP will eventually extend from this class and |
| 191 | can hence, call these tasks and functions directly as needed. |
| 192 | |
| 193 | ### cip_base_test |
| 194 | This basically creates the IP UVM env and its env cfg class instance. Any env cfg |
| 195 | setting that may be required to be controlled externally via plusargs are looked |
| 196 | up here, before the env instance is created. This also sets a few variables that |
| 197 | pertain to how / when should the test exit on timeout or failure. In the run |
| 198 | phase, the test calls `run_seq` which basically uses factory to create the |
| 199 | virtual sequence instance using the `UVM_TEST_SEQ` string that is passed via |
| 200 | plusarg. As a style guide, it is preferred to encapsulate a complete test within |
| 201 | a virtual sequence and use the same `UVM_TEST` plusarg for all of the tests (which |
| 202 | points to the extended IP test class), and only change the `UVM_TEST_SEQ` plusarg. |
| 203 | |
| 204 | This class is type parameterized with the env cfg class type `CFG_T` and the env |
| 205 | class type `ENV_T` so that when extended IP test class creates the env and env cfg |
| 206 | specific to that IP. |
| 207 | ``` |
| 208 | class cip_base_test #(type CFG_T = cip_base_env_cfg, |
| 209 | type ENV_T = cip_base_env) extends uvm_test; |
| 210 | ``` |
| 211 | |
| 212 | # Extending from CIP library classes |
| 213 | Let's say we are verifying an actual comportable IP `uart` which has `uart_tx` |
| 214 | and `uart_rx` interface. User then develops the `uart_agent` to be able to talk |
| 215 | to that interface. User invokes the `ralgen` tool to generate the `uart_reg_block`, |
| 216 | and then starts developing UVM environment by extending from the CIP library |
| 217 | classes in the following way. |
| 218 | |
| 219 | ## uart_env_cfg |
| 220 | ``` |
| 221 | class uart_env_cfg extends cip_base_env_cfg #(.RAL_T(uart_reg_block)); |
| 222 | ``` |
| 223 | User adds the `uart_agent_cfg` object as a member so that it remains as a |
| 224 | part of the env cfg and can be accessed everywhere. In the base class's |
| 225 | `initialize()` function call, an instance of `uart_reg_block` is created, not |
| 226 | the `dv_base_reg_block`, since we override the `RAL_T` type. |
| 227 | |
| 228 | ## uart_env_cov |
| 229 | ``` |
| 230 | class uart_env_cov extends cip_base_env_cov #(.CFG_T(uart_env_cfg)); |
| 231 | ``` |
| 232 | User adds `uart` IP specific coverage items and uses the `cov` handle in |
| 233 | scoreboard and test sequences to sample the coverage. |
| 234 | |
| 235 | ## uart_virtual_sequencer |
| 236 | ``` |
| 237 | class uart_virtual_sequencer extends cip_base_virtual_sequencer #(.CFG_T(uart_env_cfg), |
| 238 | .COV_T(uart_env_cov)); |
| 239 | ``` |
| 240 | User adds the `uart_sequencer` handle to allow layered test sequences |
| 241 | to send traffic to / from TileLink as well as `uart` interfaces. |
| 242 | |
| 243 | ## uart_scoreboard |
| 244 | ``` |
| 245 | class uart_scoreboard extends cip_base_scoreboard #(.CFG_T(uart_env_cfg), |
| 246 | .RAL_T(uart_reg_block), |
| 247 | .COV_T(uart_env_cov)); |
| 248 | ``` |
| 249 | User adds analysis ports to grab packets from the `uart_monitor` to |
| 250 | perform end-to-end checking. |
| 251 | |
| 252 | ## uart_env |
| 253 | ``` |
| 254 | class uart_env extends cip_base_env #(.CFG_T (uart_env_cfg), |
| 255 | .COV_T (uart_env_cov), |
| 256 | .VIRTUAL_SEQUENCER_T (uart_virtual_sequencer), |
| 257 | .SCOREBOARD_T (uart_scoreboard)); |
| 258 | ``` |
| 259 | User creates `uart_agent` object in the env and use it to connect with the |
| 260 | virtual sequencer and the scoreboard. User also uses the env cfg settings to |
| 261 | manipulate the uart agent cfg settings if required. |
| 262 | |
| 263 | ## uart_base_vseq |
| 264 | ``` |
| 265 | class uart_base_vseq extends cip_base_vseq #(.CFG_T (uart_env_cfg), |
| 266 | .RAL_T (uart_reg_block), |
| 267 | .COV_T (uart_env_cov), |
| 268 | .VIRTUAL_SEQUENCER_T (uart_virtual_sequencer)); |
| 269 | ``` |
| 270 | User adds a base virtual sequence as a starting point and adds common tasks and |
| 271 | functions to perform `uart` specific operations. User then extends from |
| 272 | `uart_base_vseq` to add layered test sequences. |
| 273 | |
| 274 | ## uart_base_test |
| 275 | ``` |
| 276 | class uart_base_test extends cip_base_test #(.ENV_T(uart_env), .CFG_T(uart_env_cfg)); |
| 277 | ``` |
| 278 | User sets `UVM_TEST` plus arg to `uart_base_test` so that all tests create the UVM env |
| 279 | that is automatically tailored to UART IP. Each test then sets the |
| 280 | `UVM_TEST_SEQ` plusarg to run the specific test sequence, along with additional |
| 281 | plusargs as required. |
| 282 | |
| 283 | # CIP Testbench |
| 284 |  |
| 285 | The block diagram above shows the CIP testbench architecture, that puts |
| 286 | together the static side `tb` which instantiates the `dut`, and the dynamic |
| 287 | side, which is the UVM environment extended from CIP library. The diagram |
| 288 | lists some common items that need to be instantiated in `tb` |
| 289 | and set into `uvm_config_db` for the testbench to work. |