blob: 313440ac889b1fac911460c6bafa46bce6ea3ed6 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// FPV CSR read and write assertions auto-generated by `reggen` containing data structure
// Do Not Edit directly
// TODO: This automation currently only support register without HW write access
<%
from reggen import (gen_fpv)
from reggen.register import Register
from topgen import lib
%>\
<%def name="construct_classes(block)">\
% for b in block.blocks:
${construct_classes(b)}
% endfor
`include "prim_assert.sv"
`ifdef UVM
import uvm_pkg::*;
`endif
// Block: ${block.name}
module ${block.name}_csr_assert_fpv import tlul_pkg::*; import ${block.name}_reg_pkg::*;
import top_pkg::*;(
input clk_i,
input rst_ni,
// tile link ports
input tl_h2d_t h2d,
input tl_d2h_t d2h,
// reg and hw ports
input ${block.name}_reg2hw_t reg2hw,
input ${block.name}_hw2reg_t hw2reg
);
`ifndef VERILATOR
`ifndef SYNTHESIS
typedef struct packed {
logic [TL_DW-1:0] wr_data;
logic [TL_AW-1:0] addr;
logic wr_pending;
logic rd_pending;
} pend_item_t;
bit disable_sva;
// mask register to convert byte to bit
logic [TL_DW-1:0] a_mask_bit;
assign a_mask_bit[7:0] = h2d.a_mask[0] ? '1 : '0;
assign a_mask_bit[15:8] = h2d.a_mask[1] ? '1 : '0;
assign a_mask_bit[23:16] = h2d.a_mask[2] ? '1 : '0;
assign a_mask_bit[31:24] = h2d.a_mask[3] ? '1 : '0;
<%
addr_msb = block.addr_width - 1
reg_width = block.addr_width
block_size = ((block.reg_block.flat_regs[-1].offset) >> 2) + 1
%>\
// store internal expected values for HW ReadOnly registers
logic [TL_DW-1:0] exp_vals[${block_size}];
pend_item_t [2**TL_AIW-1:0] pend_trans;
// normalized address only take the [${addr_msb}:2] address from the TLUL a_address
bit [${addr_msb}:0] normalized_addr;
assign normalized_addr = {h2d.a_address[${addr_msb}:2], 2'b0};
<% hro_regs_list = list(); %>\
% for r in block.reg_block.flat_regs:
% if not r.hwaccess.allows_write():
<% hro_regs_list.append(r) %>\
% endif
% endfor
% if len(hro_regs_list) > 0:
// for write HRO registers, store the write data into exp_vals
always_ff @(negedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
pend_trans <= '0;
% for hro_reg in hro_regs_list:
exp_vals[${hro_reg.offset >> 2}] <= ${hro_reg.resval};
% endfor
end else begin
if (h2d.a_valid && d2h.a_ready) begin
pend_trans[h2d.a_source].addr <= normalized_addr >> 2;
if (h2d.a_opcode inside {PutFullData, PutPartialData}) begin
pend_trans[h2d.a_source].wr_data <= h2d.a_data & a_mask_bit;
pend_trans[h2d.a_source].wr_pending <= 1'b1;
end else if (h2d.a_opcode == Get) begin
pend_trans[h2d.a_source].rd_pending <= 1'b1;
end
end
if (d2h.d_valid) begin
if (pend_trans[d2h.d_source].wr_pending == 1) begin
if (!d2h.d_error) begin
exp_vals[pend_trans[d2h.d_source].addr] <= pend_trans[d2h.d_source].wr_data;
end
pend_trans[d2h.d_source].wr_pending <= 1'b0;
end
if (h2d.d_ready && pend_trans[d2h.d_source].rd_pending == 1) begin
pend_trans[d2h.d_source].rd_pending <= 1'b0;
end
end
end
end
// for read HRO registers, assert read out values by access policy and exp_vals
% for hro_reg in hro_regs_list:
<%
r_name = hro_reg.name.lower()
reg_addr = hro_reg.offset
reg_addr_hex = format(reg_addr, 'x')
regwen = hro_reg.regwen
reg_mask = 0
%>\
% for f in hro_reg.get_field_list():
<% f_access = f.swaccess.key.lower() %>\
% if f_access == "rw" and regwen == None:
<% reg_mask = reg_mask | f.bits.bitmask() %>\
% endif
% endfor
% if reg_mask != 0:
<% reg_mask_hex = format(reg_mask, 'x') %>\
`ASSERT(${r_name}_rd_A, d2h.d_valid && pend_trans[d2h.d_source].rd_pending &&
pend_trans[d2h.d_source].addr == (${reg_width}'h${reg_addr_hex} >> 2) |->
d2h.d_error ||
(d2h.d_data & 'h${reg_mask_hex}) == (exp_vals[${reg_addr >> 2}] & 'h${reg_mask_hex}))
% endif
% endfor
% endif
`ifdef UVM
initial forever begin
bit csr_assert_en;
uvm_config_db#(bit)::wait_modified(null, "%m", "csr_assert_en");
if (!uvm_config_db#(bit)::get(null, "%m", "csr_assert_en", csr_assert_en)) begin
`uvm_fatal("csr_assert", "Can't find csr_assert_en")
end
disable_sva = !csr_assert_en;
end
`endif
</%def>\
${construct_classes(block)}
`endif
`endif
endmodule