| # CSR utilities | 
 |  | 
 |  | 
 | This csr_utils folder intends to implement CSR related methods and test sequences for DV | 
 | to share across all testbenches. | 
 |  | 
 | ### CSR utility package | 
 | `csr_utils_pkg` provides common methods and properties to support and manage CSR accesses | 
 | and CSR related test sequences. | 
 |  | 
 | #### Global types and variables | 
 | All common types and variables are defined at this package level. Examples are: | 
 | ```systemverilog | 
 |   uint       outstanding_accesses        = 0; | 
 |   uint       default_timeout_ns          = 1_000_000; | 
 | ``` | 
 |  | 
 | ##### Outstanding_accesses | 
 | `csr_utils_pkg` used an internal variable to store the number of accesses | 
 | (read or write) that have not yet completed. This variable is shared among all methods of | 
 | register reading and writing. Directly accessing this variable is discouraged. Instead, | 
 | the following methods are used to control this variable to keep track of non-blocking | 
 | accesses made in the testbench: | 
 | ```systemverilog | 
 |   function automatic void increment_outstanding_access(); | 
 |     outstanding_accesses++; | 
 |   endfunction | 
 |  | 
 |   function automatic void decrement_outstanding_access(); | 
 |     outstanding_accesses--; | 
 |   endfunction | 
 |  | 
 |   task automatic wait_no_outstanding_access(); | 
 |     wait(outstanding_accesses == 0); | 
 |   endtask | 
 |  | 
 |   function automatic void clear_outstanding_access(); | 
 |     outstanding_accesses = 0; | 
 |   endfunction | 
 | ``` | 
 |  | 
 | ##### CSR spinwait | 
 | One of the commonly used tasks in `csr_utils_pkg` is `csr_spinwait`. This task | 
 | can poll a CSR or CSR field continuously or periodically until it reads out the | 
 | expected value. This task also has a timeout check in case due to DUT or testbench | 
 | issue, the CSR or CSR field never returns the expected value. | 
 | Example below uses the `csr_spinwait` to wait until the CSR `fifo_status` field | 
 | `fifo_full` reaches value bit 1: | 
 | ```systemverilog | 
 | csr_spinwait(.ptr(ral.status.fifo_full), .exp_data(1'b0)); | 
 | ``` | 
 |  | 
 | ##### Read and check all CSRs | 
 | The purpose of the `read_and_check_all_csrs` task is to read all valid CSRs from | 
 | the given `uvm_reg_block` and check against their expected values from RAL. This | 
 | task is primarily implemented to use after reset, to make sure all the CSRs are | 
 | being reset to the default value. | 
 |  | 
 | ##### Under_reset | 
 | Due to `csr_utils_pkg` is not connected to any interface, methods inside | 
 | this package are not able to get reset information. Current the `under_reset` | 
 | bit is declared with two functions: | 
 | ```systemverilog | 
 | function automatic void reset_asserted(); | 
 |   under_reset = 1; | 
 | endfunction | 
 |  | 
 | function automatic void reset_deasserted(); | 
 |   under_reset = 0; | 
 | endfunction | 
 | ``` | 
 | This reset information is updated in `dv_lib/dv_base_vseq.sv`. When the | 
 | `apply_reset` task is triggered, it will set and reset the `under_reset` bit | 
 | via the functions above. | 
 |  | 
 | #### Global CSR util methods | 
 | ##### Global methods for CSR and MEM attributes | 
 | This package provides methods to access CSR or Memory attributes, such as address, | 
 | value, etc. Examples are: | 
 |  * `get_csr_addrs` | 
 |  * `get_mem_addr_ranges` | 
 |  * `decode_csr_or_field` | 
 |  | 
 | ##### Global methods for CSR access | 
 | The CSR access methods are based on `uvm_reg` methods, such as `uvm_reg::read()`, | 
 | `uvm_reg::write()`, `uvm_reg::update()`. For all CSR methods, user can | 
 | pass either a register or a field handle. Examples are: | 
 |  * `csr_rd_check`: Given the uvm_reg or uvm_reg_field object, this method will | 
 |    compare the CSR value with the expected value (given as an input) or with | 
 |    the RAL mirrored value | 
 |  * `csr_update`: Given the uvm_reg object, this method will update the value of the | 
 |    register in DUT to match the desired value | 
 |  | 
 | To enhance the usability, these methods support CSR blocking, non-blocking | 
 | read/write, and a timeout checking. | 
 |  * A blocking thread will not execute the next sequence until the current CSR | 
 |    access is finished | 
 |  * A non-blocking thread allows multiple CSR accesses to be issued back-to-back | 
 |    without waiting for the response | 
 |  * A timeout check will discard the ongoing CSR access by disabling the forked | 
 |    thread and will throw a UVM_ERROR once the process exceeds the max timeout setting | 
 |  | 
 | ### CSR sequence library | 
 | `csr_seq_lib.sv` provides common CSR related test sequences to share across all testbenches. | 
 | These test sequences are based off the standard sequences provided in UVM1.2 RAL. | 
 | The parent class (DUT-specific test or sequence class) that creates them needs to provide them | 
 | with the DUT RAL model. The list of CSRs are then extracted from the RAL model to performs the checks. | 
 | In addition, the test sequences provide an ability to exclude a CSR from writes or reads (or both) | 
 | depending on the behavior of the CSR in the design. This is explained more in the | 
 | [CSR exclusion methodology](#csr-exclusion-methodology) section below. | 
 | All CSR accesses in these sequences are made non-blocking to ensure back-to-back scenarios | 
 | are exercised. | 
 | Supported CSR test sequences are: | 
 |  * `csr_hw_reset`: Write all CSRs with random values and then reset the DUT. | 
 |    After reset, read all CSRs and compare with expected values | 
 |  * `csr_rw`: Write a randomly selected CSRs, then read out the updated | 
 |    CSR or CSR field and compare with expected value | 
 |  * `csr_bit_bash`: Randomly select a CSR and write 1's and 0's to | 
 |    every bit, then read the CSR to compare with expected value | 
 |  * `csr_aliasing`: Randomly write a CSR, then read all CSRs to | 
 |    verify that only the CSR that was written was updated | 
 |  * `mem_walk`: Write and read all valid addresses in the memory. Compare | 
 |    the read results with the expected values | 
 |  | 
 | ### CSR exclusion methodology | 
 | The CSR test sequences listed above intend to perform a basic check to CSR | 
 | read/write accesses, but do not intend to check specific DUT functionalities. Thus the | 
 | sequences might need to exclude reading or writing certain CSRs depending on the | 
 | specific testbench. | 
 | `csr_excl_item` is a class that supports adding exclusions to CSR test sequences. | 
 | Examples of useful functions in this class are: | 
 | * `add_excl`: Add exclusions to the CSR test sequences. This function has two inputs: | 
 |   - Exclusion scope: A hierarchical path name at all levels including block, | 
 |     CSR, and field. This input supports * and ? wildcards for glob style matching | 
 |   - CSR_exclude type: An enumeration defined as below: | 
 |     ```systemverilog | 
 |     typedef enum bit[2:0] { | 
 |       CsrNoExcl         = 3'b000, // no exclusions | 
 |       CsrExclInitCheck  = 3'b001, // exclude csr from init val check | 
 |       CsrExclWriteCheck = 3'b010, // exclude csr from write-read check | 
 |       CsrExclCheck      = 3'b011, // exclude csr from init or write-read check | 
 |       CsrExclWrite      = 3'b100, // exclude csr from write | 
 |       CsrExclAll        = 3'b111  // exclude csr from init or write or write-read check | 
 |     } csr_excl_type_e; | 
 |     ``` | 
 |  | 
 |   One example to use this function in HMAC to exclude all CSRs or fields with | 
 |   names starting with "key": | 
 |   ```systemverilog | 
 |   csr_excl.add_excl({scope, ".", "key?"}, CsrExclWrite); | 
 |   ``` | 
 |  | 
 | * `has_excl`: Check if the CSR has a match in the existing exclusions loopup, | 
 |   and is not intended to use externally | 
 |  | 
 | ### CSR sequence framework | 
 | The [cip_lib]({{< relref "hw/dv/sv/cip_lib/doc" >}}) includes a virtual sequence named `cip_base_vseq`, | 
 | that provides a common framework for all testbenchs to run these CSR test sequences and | 
 | add exclusions. |