// 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 does not support: shadow reg, has_d has_de not has_q (right now does not
// have internal storage if de=0)
<% from reggen import (gen_fpv)
%>\
<% from topgen import lib
%>\
<%def name="construct_classes(block)">\
% for b in block.blocks:
${construct_classes(b)}
% endfor

`include "prim_assert.sv"

// 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

`ifdef UVM
  import uvm_pkg::*;
  % if block.hier_path:
  `define REGWEN_PATH dut.${block.hier_path}.u_reg
  % elif block.name == "flash_ctrl":
  `define REGWEN_PATH dut.u_flash_ctrl.u_reg
  % else:
  `define REGWEN_PATH dut.u_reg
  % endif
`else
  `define REGWEN_PATH u_reg
`endif

  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
%>\
  // 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};

  // declare common read and write sequences
  sequence device_wr_S(logic [${addr_msb}:0] addr);
    normalized_addr == addr && h2d.a_opcode inside {PutFullData, PutPartialData} &&
        h2d.a_valid && h2d.d_ready && !d2h.d_valid;
  endsequence

  sequence device_rd_S(logic [${addr_msb}:0] addr);
    normalized_addr == addr && h2d.a_opcode inside {Get} && h2d.a_valid && h2d.d_ready &&
        !d2h.d_valid;
  endsequence

  // declare common read and write properties
  // for homog registers, we check by a reg; for non-homog regs, we check by field.
  // `mask` is used for checking by field. It masks out any act_data that are not within the field
  // `lsb` is used to check non-homog multi_reg. Because we are using a local copy `_fpv` variable
  // to store all the multi-reg within one basefield, we need to shift the `_fpv` value to the
  // correct bits, then compare with read/write exp_data.

  property wr_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit regen,
                bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_wr_S(addr) and regen, id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask) ##1
        first_match(##[0:$] d2h.d_valid && d2h.d_source == id) |->
        (d2h.d_error || (act_data << lsb) == exp_data);
  endproperty

  // this property is to check when regen is set to 0, the write data should not be updated
  property wr_regen_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit regen,
                bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_wr_S(addr) and !regen, id = h2d.a_source, exp_data = (act_data << lsb)) ##1
        first_match(##[0:$] d2h.d_valid && d2h.d_source == id) |->
        (d2h.d_error || (act_data << lsb) == exp_data);
  endproperty

  // external reg will use one clk cycle to update act_data from external
  property wr_ext_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit regen,
                    bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_wr_S(addr) and regen, id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask) ##1
        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
        (d2h.d_error || ($past(act_data) << lsb) == exp_data);
  endproperty

  property wr_ext_regen_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit regen,
                    bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_wr_S(addr) and !regen, id = h2d.a_source, exp_data = (act_data << lsb)) ##1
        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
        (d2h.d_error || ($past(act_data) << lsb) == exp_data);
  endproperty

  // W1C register, if write 1 external data will be cleared to 0;
  // if write 0, internal data won't change
  // TODO: add regen check for W1C regs
  property w1c_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit regen,
                 bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_wr_S(addr) and regen, id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask) ##1
        first_match(##[0:$] d2h.d_valid && d2h.d_source == id) |->
        (d2h.d_error || ((act_data << lsb) & exp_data) == 0);
  endproperty

  property w1c_ext_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit regen,
                     bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_wr_S(addr) and regen, id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask) ##1
        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
        (d2h.d_error || ($past(act_data) << lsb) == exp_data);
  endproperty

  property rd_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit [TL_DW-1:0] mask, int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_rd_S(addr), id = h2d.a_source, exp_data = $past(act_data)) ##1
        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
        (d2h.d_error || (d2h.d_data & mask) >> lsb == exp_data);
  endproperty

  property rd_ext_P(bit [${addr_msb}:0] addr, bit [TL_DW-1:0] act_data, bit [TL_DW-1:0] mask,
      int lsb);
    logic [TL_DW-1:0] id, exp_data;
    (device_rd_S(addr), id = h2d.a_source, exp_data = act_data) ##1
        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
        (d2h.d_error || (d2h.d_data & mask) >> lsb == exp_data);
  endproperty

% for r in block.regs:
<%
  has_q  = r.get_n_bits(["q"]) > 0
  has_d  = r.get_n_bits(["d"]) > 0
  has_de = r.get_n_bits(["de"]) > 0
%>\
  % if not r.get_field_flat(0).shadowed:
  % if r.is_multi_reg():
<%
      mreg_name          = r.name
      mreg_width_list    = list()
      mreg_fpv_name_list = list()
      mreg_dut_path_list = list()
      mreg_has_q_list    = list()
      mreg_has_d_list    = list()
      mreg_has_de_list   = list()
      mreg_num_regs      = r.get_n_fields_flat()

      mreg_msb = -1
      mreg_lsb = 0
      i        = 0
%>\
   % if not r.ishomog:
     % for field in r.get_reg_flat(0).fields:
<%
  mreg_fpv_name_list.append(mreg_name + "_" + field.get_basename())
  mreg_dut_path_list.append(mreg_name + "[s]." + field.get_basename())
  mreg_width_list.append(field.msb - field.lsb + 1)
  mreg_has_q_list.append(field.get_n_bits(["q"]) > 0)
  mreg_has_d_list.append(field.get_n_bits(["d"]) > 0)
  mreg_has_de_list.append(field.get_n_bits(["de"]) > 0)
%>\
     % endfor
<%
  mreg_num_base_fields = len(mreg_fpv_name_list)
  mreg_num_regs        = mreg_num_regs / mreg_num_base_fields
%>\
   % else:
<%
  f = r.get_field_flat(0)
  mreg_num_base_fields = 1
  mreg_fpv_name_list.append(mreg_name)
  mreg_dut_path_list.append(mreg_name + "[s]")
  mreg_width_list.append(f.msb - f.lsb + 1)
  mreg_has_q_list.append(has_q)
  mreg_has_d_list.append(has_d)
  mreg_has_de_list.append(has_de)
%>\
   % endif

  // define local fpv variable for multi-reg
   % if r.get_n_bits(["q", "d"]):
     % for fpv_name in mreg_fpv_name_list:
${declare_fpv_var(fpv_name, int(mreg_width_list[loop.index] * mreg_num_regs - 1), loop.index)}\
     % endfor
  for (genvar s = 0; s < ${int(mreg_num_regs)}; s++) begin : gen_${mreg_name}_q
     % for fpv_name in mreg_fpv_name_list:
${assign_fpv_var(fpv_name, mreg_dut_path_list[loop.index], int(mreg_width_list[loop.index]), loop.index)}\
     % endfor
  end
   % endif
  % endif

  % for reg_flat in r.get_regs_flat():
<%
  reg_name    = reg_flat.name
  reg_offset  =  str(reg_width) + "'h" + "%x" % reg_flat.offset
  reg_msb     = reg_flat.width - 1
  regwen      = reg_flat.regwen
  reg_wr_mask = 0
%>\
  // assertions for register: ${reg_name}
    % if regwen:
<% reg_wen = "`REGWEN_PATH." + regwen + "_qs" %>\
    % else:
<% reg_wen = "1" %>\
    % endif
    % for f in reg_flat.get_fields_flat():
<%
      field_name      = f.name
      assert_path     = reg_name + "." + field_name
      assert_name     = reg_name + "_" + field_name
      field_access    = f.swaccess.name
      field_wr_mask   = ((1 << (f.msb-f.lsb + 1)) -1) << f.lsb
      field_wr_mask_h = format(field_wr_mask, 'x')
      reg_wr_mask    |= field_wr_mask
      reg_wr_mask_h   = format(reg_wr_mask, 'x')
      lsb             = f.lsb
      sw_rdaccess     = f.swrdaccess.name
      had_q           = f.get_n_bits(["q"]) > 0
      has_d           = f.get_n_bits(["d"]) > 0
      has_de          = f.get_n_bits(["de"]) > 0
%>\
      % if not r.ishomog:
        % if r.is_multi_reg():
  // this is a non-homog multi-reg
<%
      mreg_lsb = i * mreg_width_list[loop.index]
      mreg_msb = mreg_lsb + mreg_width_list[loop.index] - 1
%>\
${gen_multi_reg_asserts_by_category(assert_name, mreg_name + "_" + f.get_basename(), mreg_msb, mreg_lsb, reg_flat.hwext, field_wr_mask_h)}\
        % else:
${gen_asserts_by_category(assert_name, assert_path, reg_flat.hwext, field_wr_mask_h)}\
        % endif
      % endif
    % endfor
    % if r.is_multi_reg():
<%
      mreg_lsb = i * (mreg_msb - mreg_lsb + 1)
      mreg_msb = mreg_lsb + reg_msb
      i += 1
%>\
    % endif
    % if r.ishomog:
      % if r.is_multi_reg():
${gen_multi_reg_asserts_by_category(reg_name, mreg_name, mreg_msb, mreg_lsb, reg_flat.hwext, reg_wr_mask_h)}\
      % else:
${gen_asserts_by_category(reg_name, reg_name, reg_flat.hwext, reg_wr_mask_h)}\
      % endif
    % endif
  % endfor
  % endif
% endfor

  `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 name="gen_asserts_by_category(assert_name, assert_path, is_ext, wr_mask)">\
  % if has_q:
<% reg_w_path = "reg2hw." + assert_path + ".q" %>\
${gen_wr_asserts(assert_name, is_ext, reg_w_path, wr_mask)}\
    % if not has_d:
${gen_rd_asserts(assert_name, is_ext, reg_w_path, wr_mask)}\
    % endif
  % endif
  % if has_d:
    % if has_de and has_q:
<% reg_r_path = "hw2reg." + assert_path + ".de ? hw2reg." + assert_path + ".d :reg2hw." + assert_path + ".q" %>\
${gen_rd_asserts(assert_name, is_ext, reg_r_path, wr_mask)}\
    % elif not has_de:
<% reg_r_path = "hw2reg." + assert_path + ".d" %>\
${gen_rd_asserts(assert_name, is_ext, reg_r_path, wr_mask)}\
    % endif
  % endif
</%def>\
<%def name="gen_multi_reg_asserts_by_category(assert_name, multi_reg_name, mreg_msb, mreg_lsb, is_ext, wr_mask)">\
  % if has_q:
<% reg_w_path = multi_reg_name + "_q_fpv[" + str(mreg_msb) + ":" + str(mreg_lsb) + "]"%>\
${gen_wr_asserts(assert_name, is_ext, reg_w_path, wr_mask)}\
    % if not has_d:
${gen_rd_asserts(assert_name, is_ext, reg_w_path, wr_mask)}\
    % endif
  % endif
  % if has_d:
    % if not has_de:
<% reg_r_path = multi_reg_name + "_d_fpv[" + str(mreg_msb) + ":" + str(mreg_lsb) + "]"%>\
${gen_rd_asserts(assert_name, is_ext, reg_r_path, wr_mask)}\
    % endif
  % endif
</%def>\
<%def name="gen_wr_asserts(name, is_ext, reg_w_path, wr_mask)">\
  % if is_ext:
<% wr_property = "ext_P" %>\
  % else:
<% wr_property = "P" %>\
  % endif
  % if not r.ishomog:
<% shift_index = lsb %>\
  % else:
<% shift_index = 0 %>\
  % endif
  % if field_access == "W1C":
  `ASSERT(${name}_w1c_A, w1c_${wr_property}(${reg_offset}, ${reg_w_path}, ${reg_wen}, 'h${wr_mask}, ${shift_index}), clk_i, !rst_ni || disable_sva)
  % elif field_access in {"RW", "WO", "W0C"}:
  `ASSERT(${name}_wr_A, wr_${wr_property}(${reg_offset}, ${reg_w_path}, ${reg_wen}, 'h${wr_mask}, ${shift_index}), clk_i, !rst_ni || disable_sva)
    % if reg_wen != "1":
  `ASSERT(${name}_wr_regen_A, wr_${wr_property}(${reg_offset}, ${reg_w_path}, ${reg_wen}, 'h${wr_mask}, ${shift_index}), clk_i, !rst_ni || disable_sva)
    % endif
  % endif
</%def>\
<%def name="gen_rd_asserts(name, is_ext, reg_r_path, mask)">\
  % if is_ext:
<% rd_property = "rd_ext_P" %>\
  % else:
<% rd_property = "rd_P" %>\
  % endif
  % if not r.ishomog:
<% shift_index = lsb %>\
  % else:
<% shift_index = 0 %>\
  % endif
  % if sw_rdaccess == "NONE" and field_access == "W1C":
  `ASSERT(${name}_rd_A, ${rd_property}(${reg_offset}, 0, 'h${mask}, ${shift_index}), clk_i, !rst_ni || disable_sva)
  % elif field_access in {"RW", "W0C", "W1C"}:
  `ASSERT(${name}_rd_A, ${rd_property}(${reg_offset}, ${reg_r_path}, 'h${mask}, ${shift_index}), clk_i, !rst_ni || disable_sva)
  % endif
</%def>\
<%def name="declare_fpv_var(name, width, l_index)">\
  % if mreg_has_q_list[l_index]:
  logic [${width}:0] ${name}_q_fpv;
  % endif
  % if mreg_has_d_list[l_index]:
  logic [${width}:0] ${name}_d_fpv;
  % endif
</%def>\
<%def name="assign_fpv_var(fpv_name, dut_path, width, l_index)">\
  % if mreg_has_q_list[l_index]:
    assign ${fpv_name}_q_fpv[((s+1)*${width}-1):s*${width}] = reg2hw.${dut_path}.q;
  % endif
  % if mreg_has_d_list[l_index]:
    assign ${fpv_name}_d_fpv[((s+1)*${width}-1):s*${width}] = hw2reg.${dut_path}.d;
  % endif
</%def>\
</%def>\
${construct_classes(block)}
`undef REGWEN_PATH
`endif
`endif
endmodule
