blob: 14e436f1954a588f5ae5cdd4350602eb387113ea [file] [log] [blame]
Cindy Chen0bad7832019-11-07 11:25:00 -08001// 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 Chenf3b61c02021-01-14 21:34:25 -08007// TODO: This automation currently only support register without HW write access
Rupert Swarbrickede94802021-02-08 09:16:50 +00008<%
9 from reggen import (gen_fpv)
Rupert Swarbrick4d645362021-02-08 17:17:05 +000010 from reggen.register import Register
Rupert Swarbrickede94802021-02-08 09:16:50 +000011
12 from topgen import lib
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000013
14 lblock = block.name.lower()
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000015
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 Chen0bad7832019-11-07 11:25:00 -080020%>\
21<%def name="construct_classes(block)">\
Cindy Chen0bad7832019-11-07 11:25:00 -080022
Greg Chadwickcf423082020-02-05 16:52:23 +000023`include "prim_assert.sv"
Cindy Chenf3b61c02021-01-14 21:34:25 -080024`ifdef UVM
25 import uvm_pkg::*;
26`endif
Greg Chadwickcf423082020-02-05 16:52:23 +000027
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000028// Block: ${lblock}
Cindy Chen9a02ccb2021-03-22 12:09:01 -070029module ${mod_base}_csr_assert_fpv import tlul_pkg::*;
Cindy Chen6cc1abc2020-09-17 13:48:51 -070030 import top_pkg::*;(
Cindy Chen0bad7832019-11-07 11:25:00 -080031 input clk_i,
32 input rst_ni,
33
Cindy Chena3976db2020-07-26 19:13:09 -070034 // tile link ports
Cindy Chen0bad7832019-11-07 11:25:00 -080035 input tl_h2d_t h2d,
Cindy Chen9a02ccb2021-03-22 12:09:01 -070036 input tl_d2h_t d2h
Cindy Chen0bad7832019-11-07 11:25:00 -080037);
Cindy Chend0a00122021-04-16 11:49:17 -070038<%
39 addr_width = rb.get_addr_width()
40 addr_msb = addr_width - 1
Rupert Swarbrick7252f172021-06-17 17:04:20 +010041 hro_regs_list = [r for r in rb.flat_regs if not r.is_hw_writable()]
Cindy Chend0a00122021-04-16 11:49:17 -070042 num_hro_regs = len(hro_regs_list)
43 hro_map = {r.offset: (idx, r) for idx, r in enumerate(hro_regs_list)}
44%>\
Cindy Chen0bad7832019-11-07 11:25:00 -080045
Cindy Chend0a00122021-04-16 11:49:17 -070046// Currently FPV csr assertion only support HRO registers.
47% if num_hro_regs > 0:
Cindy Chen6cc1abc2020-09-17 13:48:51 -070048`ifndef VERILATOR
49`ifndef SYNTHESIS
50
Cindy Chend0a00122021-04-16 11:49:17 -070051 parameter bit[3:0] MAX_A_SOURCE = 10; // used for FPV only to reduce runtime
52
Cindy Chenf3b61c02021-01-14 21:34:25 -080053 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 Chen6cc1abc2020-09-17 13:48:51 -070059
60 bit disable_sva;
61
Cindy Chen0bad7832019-11-07 11:25:00 -080062 // mask register to convert byte to bit
Cindy Chen6cc1abc2020-09-17 13:48:51 -070063 logic [TL_DW-1:0] a_mask_bit;
Cindy Chen0bad7832019-11-07 11:25:00 -080064
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 Chend0a00122021-04-16 11:49:17 -070070 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-snps7bc9c7d2021-06-17 14:12:27 -070080 default: hro_idx <= ${num_hro_regs};
Cindy Chend0a00122021-04-16 11:49:17 -070081 endcase
82 end
83
Cindy Chenf3b61c02021-01-14 21:34:25 -080084 // store internal expected values for HW ReadOnly registers
Cindy Chend0a00122021-04-16 11:49:17 -070085 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 Chenf3b61c02021-01-14 21:34:25 -080092
Cindy Chenb2970df2020-08-04 12:16:57 -070093 // normalized address only take the [${addr_msb}:2] address from the TLUL a_address
Cindy Chen6cc1abc2020-09-17 13:48:51 -070094 assign normalized_addr = {h2d.a_address[${addr_msb}:2], 2'b0};
95
Cindy Chend0a00122021-04-16 11:49:17 -070096% if num_hro_regs > 0:
Cindy Chenf3b61c02021-01-14 21:34:25 -080097 // 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 Chend0a00122021-04-16 11:49:17 -0700102 exp_vals[${hro_map.get(hro_reg.offset)[0]}] <= ${hro_reg.resval};
Cindy Chenf3b61c02021-01-14 21:34:25 -0800103 % endfor
104 end else begin
105 if (h2d.a_valid && d2h.a_ready) begin
Cindy Chend0a00122021-04-16 11:49:17 -0700106 pend_trans[h2d.a_source].addr <= normalized_addr;
Cindy Chenf3b61c02021-01-14 21:34:25 -0800107 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 Chend0a00122021-04-16 11:49:17 -0700117 exp_vals[hro_idx] <= pend_trans[d2h.d_source].wr_data;
Cindy Chenf3b61c02021-01-14 21:34:25 -0800118 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 Swarbrick200d8b42021-03-08 12:32:11 +0000136
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 Chenf3b61c02021-01-14 21:34:25 -0800141%>\
Cindy Chenf3b61c02021-01-14 21:34:25 -0800142 % if reg_mask != 0:
143<% reg_mask_hex = format(reg_mask, 'x') %>\
Cindy Chend0a00122021-04-16 11:49:17 -0700144 `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 Chenf3b61c02021-01-14 21:34:25 -0800148
149 % endif
150 % endfor
151% endif
Cindy Chena3976db2020-07-26 19:13:09 -0700152
Cindy Chend0a00122021-04-16 11:49:17 -0700153 // 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 Chen6cc1abc2020-09-17 13:48:51 -0700156 `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 Chend0a00122021-04-16 11:49:17 -0700167`endif
168`endif
169% endif
170endmodule
Cindy Chen0bad7832019-11-07 11:25:00 -0800171</%def>\
172${construct_classes(block)}