Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | // FPV CSR read and write assertions auto-generated by `reggen` containing data structure |
| 6 | // Do Not Edit directly |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 7 | // TODO: This automation currently only support register without HW write access |
Rupert Swarbrick | ede9480 | 2021-02-08 09:16:50 +0000 | [diff] [blame] | 8 | <% |
| 9 | from reggen import (gen_fpv) |
Rupert Swarbrick | 4d64536 | 2021-02-08 17:17:05 +0000 | [diff] [blame] | 10 | from reggen.register import Register |
Rupert Swarbrick | ede9480 | 2021-02-08 09:16:50 +0000 | [diff] [blame] | 11 | |
| 12 | from topgen import lib |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 13 | |
| 14 | lblock = block.name.lower() |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 15 | |
| 16 | # This template shouldn't be instantiated if the device interface |
| 17 | # doesn't actually have any registers. |
| 18 | assert rb.flat_regs |
| 19 | |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 20 | %>\ |
| 21 | <%def name="construct_classes(block)">\ |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 22 | |
Greg Chadwick | cf42308 | 2020-02-05 16:52:23 +0000 | [diff] [blame] | 23 | `include "prim_assert.sv" |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 24 | `ifdef UVM |
| 25 | import uvm_pkg::*; |
| 26 | `endif |
Greg Chadwick | cf42308 | 2020-02-05 16:52:23 +0000 | [diff] [blame] | 27 | |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 28 | // Block: ${lblock} |
Cindy Chen | 9a02ccb | 2021-03-22 12:09:01 -0700 | [diff] [blame] | 29 | module ${mod_base}_csr_assert_fpv import tlul_pkg::*; |
Cindy Chen | 6cc1abc | 2020-09-17 13:48:51 -0700 | [diff] [blame] | 30 | import top_pkg::*;( |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 31 | input clk_i, |
| 32 | input rst_ni, |
| 33 | |
Cindy Chen | a3976db | 2020-07-26 19:13:09 -0700 | [diff] [blame] | 34 | // tile link ports |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 35 | input tl_h2d_t h2d, |
Cindy Chen | 9a02ccb | 2021-03-22 12:09:01 -0700 | [diff] [blame] | 36 | input tl_d2h_t d2h |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 37 | ); |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 38 | <% |
| 39 | addr_width = rb.get_addr_width() |
| 40 | addr_msb = addr_width - 1 |
Rupert Swarbrick | 7252f17 | 2021-06-17 17:04:20 +0100 | [diff] [blame] | 41 | hro_regs_list = [r for r in rb.flat_regs if not r.is_hw_writable()] |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 42 | num_hro_regs = len(hro_regs_list) |
| 43 | hro_map = {r.offset: (idx, r) for idx, r in enumerate(hro_regs_list)} |
| 44 | %>\ |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 45 | |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 46 | // Currently FPV csr assertion only support HRO registers. |
| 47 | % if num_hro_regs > 0: |
Cindy Chen | 6cc1abc | 2020-09-17 13:48:51 -0700 | [diff] [blame] | 48 | `ifndef VERILATOR |
| 49 | `ifndef SYNTHESIS |
| 50 | |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 51 | parameter bit[3:0] MAX_A_SOURCE = 10; // used for FPV only to reduce runtime |
| 52 | |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 53 | typedef struct packed { |
| 54 | logic [TL_DW-1:0] wr_data; |
| 55 | logic [TL_AW-1:0] addr; |
| 56 | logic wr_pending; |
| 57 | logic rd_pending; |
| 58 | } pend_item_t; |
Cindy Chen | 6cc1abc | 2020-09-17 13:48:51 -0700 | [diff] [blame] | 59 | |
| 60 | bit disable_sva; |
| 61 | |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 62 | // mask register to convert byte to bit |
Cindy Chen | 6cc1abc | 2020-09-17 13:48:51 -0700 | [diff] [blame] | 63 | logic [TL_DW-1:0] a_mask_bit; |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 64 | |
| 65 | assign a_mask_bit[7:0] = h2d.a_mask[0] ? '1 : '0; |
| 66 | assign a_mask_bit[15:8] = h2d.a_mask[1] ? '1 : '0; |
| 67 | assign a_mask_bit[23:16] = h2d.a_mask[2] ? '1 : '0; |
| 68 | assign a_mask_bit[31:24] = h2d.a_mask[3] ? '1 : '0; |
| 69 | |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 70 | bit [${addr_msb}-2:0] hro_idx; // index for exp_vals |
| 71 | bit [${addr_msb}:0] normalized_addr; |
| 72 | |
| 73 | // Map register address with hro_idx in exp_vals array. |
| 74 | always_comb begin: decode_hro_addr_to_idx |
| 75 | unique case (pend_trans[d2h.d_source].addr) |
| 76 | % for idx, r in hro_map.values(): |
| 77 | ${r.offset}: hro_idx <= ${idx}; |
| 78 | % endfor |
| 79 | // If the register is not a HRO register, the write data will all update to this default idx. |
ayann-snps | 7bc9c7d | 2021-06-17 14:12:27 -0700 | [diff] [blame] | 80 | default: hro_idx <= ${num_hro_regs}; |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 81 | endcase |
| 82 | end |
| 83 | |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 84 | // store internal expected values for HW ReadOnly registers |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 85 | logic [TL_DW-1:0] exp_vals[${num_hro_regs + 1}]; |
| 86 | |
| 87 | `ifdef FPV_ON |
| 88 | pend_item_t [MAX_A_SOURCE:0] pend_trans; |
| 89 | `else |
| 90 | pend_item_t [2**TL_AIW-1:0] pend_trans; |
| 91 | `endif |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 92 | |
Cindy Chen | b2970df | 2020-08-04 12:16:57 -0700 | [diff] [blame] | 93 | // normalized address only take the [${addr_msb}:2] address from the TLUL a_address |
Cindy Chen | 6cc1abc | 2020-09-17 13:48:51 -0700 | [diff] [blame] | 94 | assign normalized_addr = {h2d.a_address[${addr_msb}:2], 2'b0}; |
| 95 | |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 96 | % if num_hro_regs > 0: |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 97 | // for write HRO registers, store the write data into exp_vals |
| 98 | always_ff @(negedge clk_i or negedge rst_ni) begin |
| 99 | if (!rst_ni) begin |
| 100 | pend_trans <= '0; |
| 101 | % for hro_reg in hro_regs_list: |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 102 | exp_vals[${hro_map.get(hro_reg.offset)[0]}] <= ${hro_reg.resval}; |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 103 | % endfor |
| 104 | end else begin |
| 105 | if (h2d.a_valid && d2h.a_ready) begin |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 106 | pend_trans[h2d.a_source].addr <= normalized_addr; |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 107 | if (h2d.a_opcode inside {PutFullData, PutPartialData}) begin |
| 108 | pend_trans[h2d.a_source].wr_data <= h2d.a_data & a_mask_bit; |
| 109 | pend_trans[h2d.a_source].wr_pending <= 1'b1; |
| 110 | end else if (h2d.a_opcode == Get) begin |
| 111 | pend_trans[h2d.a_source].rd_pending <= 1'b1; |
| 112 | end |
| 113 | end |
| 114 | if (d2h.d_valid) begin |
| 115 | if (pend_trans[d2h.d_source].wr_pending == 1) begin |
| 116 | if (!d2h.d_error) begin |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 117 | exp_vals[hro_idx] <= pend_trans[d2h.d_source].wr_data; |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 118 | end |
| 119 | pend_trans[d2h.d_source].wr_pending <= 1'b0; |
| 120 | end |
| 121 | if (h2d.d_ready && pend_trans[d2h.d_source].rd_pending == 1) begin |
| 122 | pend_trans[d2h.d_source].rd_pending <= 1'b0; |
| 123 | end |
| 124 | end |
| 125 | end |
| 126 | end |
| 127 | |
| 128 | // for read HRO registers, assert read out values by access policy and exp_vals |
| 129 | % for hro_reg in hro_regs_list: |
| 130 | <% |
| 131 | r_name = hro_reg.name.lower() |
| 132 | reg_addr = hro_reg.offset |
| 133 | reg_addr_hex = format(reg_addr, 'x') |
| 134 | regwen = hro_reg.regwen |
| 135 | reg_mask = 0 |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 136 | |
| 137 | for f in hro_reg.get_field_list(): |
| 138 | f_access = f.swaccess.key.lower() |
| 139 | if f_access == "rw" and regwen == None: |
| 140 | reg_mask = reg_mask | f.bits.bitmask() |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 141 | %>\ |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 142 | % if reg_mask != 0: |
| 143 | <% reg_mask_hex = format(reg_mask, 'x') %>\ |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 144 | `ASSERT(${r_name}_rd_A, d2h.d_valid && pend_trans[d2h.d_source].rd_pending && |
| 145 | pend_trans[d2h.d_source].addr == ${addr_width}'h${reg_addr_hex} |-> |
| 146 | d2h.d_error || |
| 147 | (d2h.d_data & 'h${reg_mask_hex}) == (exp_vals[${hro_map.get(reg_addr)[0]}] & 'h${reg_mask_hex})) |
Cindy Chen | f3b61c0 | 2021-01-14 21:34:25 -0800 | [diff] [blame] | 148 | |
| 149 | % endif |
| 150 | % endfor |
| 151 | % endif |
Cindy Chen | a3976db | 2020-07-26 19:13:09 -0700 | [diff] [blame] | 152 | |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 153 | // This FPV only assumption is to reduce the FPV runtime. |
| 154 | `ASSUME_FPV(TlulSource_M, h2d.a_source >= 0 && h2d.a_source <= MAX_A_SOURCE, clk_i, !rst_ni) |
| 155 | |
Cindy Chen | 6cc1abc | 2020-09-17 13:48:51 -0700 | [diff] [blame] | 156 | `ifdef UVM |
| 157 | initial forever begin |
| 158 | bit csr_assert_en; |
| 159 | uvm_config_db#(bit)::wait_modified(null, "%m", "csr_assert_en"); |
| 160 | if (!uvm_config_db#(bit)::get(null, "%m", "csr_assert_en", csr_assert_en)) begin |
| 161 | `uvm_fatal("csr_assert", "Can't find csr_assert_en") |
| 162 | end |
| 163 | disable_sva = !csr_assert_en; |
| 164 | end |
| 165 | `endif |
| 166 | |
Cindy Chen | d0a0012 | 2021-04-16 11:49:17 -0700 | [diff] [blame] | 167 | `endif |
| 168 | `endif |
| 169 | % endif |
| 170 | endmodule |
Cindy Chen | 0bad783 | 2019-11-07 11:25:00 -0800 | [diff] [blame] | 171 | </%def>\ |
| 172 | ${construct_classes(block)} |