| # 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](../cip_lib/README.md) includes a virtual sequence named `cip_base_vseq`, |
| that provides a common framework for all testbenches to run these CSR test sequences and |
| add exclusions. |