[aes/dv] added FI for ctr fsm

Signed-off-by: Rasmus Madsen <rasmus.madsen@wdc.com>
diff --git a/hw/ip/aes/dv/aes_base_sim_cfg.hjson b/hw/ip/aes/dv/aes_base_sim_cfg.hjson
index 7e94401..8f6c9ad 100644
--- a/hw/ip/aes/dv/aes_base_sim_cfg.hjson
+++ b/hw/ip/aes/dv/aes_base_sim_cfg.hjson
@@ -174,6 +174,11 @@
       uvm_test: aes_fi_test
       uvm_test_seq: aes_cipher_fi_vseq
     }
+    {
+      name: aes_ctr_fi
+      uvm_test: aes_fi_test
+      uvm_test_seq: aes_ctr_fi_vseq
+    }
   ]
 
   // List of regressions.
diff --git a/hw/ip/aes/dv/env/aes_env.core b/hw/ip/aes/dv/env/aes_env.core
index aa8f6f0..961f897 100644
--- a/hw/ip/aes/dv/env/aes_env.core
+++ b/hw/ip/aes/dv/env/aes_env.core
@@ -40,6 +40,7 @@
       - seq_lib/aes_fi_vseq.sv: {is_include_file: true}
       - seq_lib/aes_control_fi_vseq.sv: {is_include_file: true}
       - seq_lib/aes_cipher_fi_vseq.sv: {is_include_file: true}
+      - seq_lib/aes_ctr_fi_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 generate:
diff --git a/hw/ip/aes/dv/env/aes_env_cfg.sv b/hw/ip/aes/dv/env/aes_env_cfg.sv
index 6e4dcd0..c2e9592 100644
--- a/hw/ip/aes/dv/env/aes_env_cfg.sv
+++ b/hw/ip/aes/dv/env/aes_env_cfg.sv
@@ -24,6 +24,7 @@
 
   virtual fi_control_if aes_control_fi_vif[Sp2VWidth];
   virtual fi_cipher_if aes_cipher_control_fi_vif[Sp2VWidth];
+  virtual fi_ctr_fsm_if aes_ctr_fsm_fi_vif[Sp2VWidth];
 
   rand key_sideload_agent_cfg keymgr_sideload_agent_cfg;
   // test environment constraints //
@@ -273,6 +274,12 @@
         `uvm_fatal(`gfn, $sformatf("FAILED TO GET HANDLE TO ROUND COUNTER INJECT INTERFACE %d",nn))
       end
     end
-
+    foreach (aes_ctr_fsm_fi_vif[nn]) begin
+      if (!uvm_config_db#(virtual fi_ctr_fsm_if)::get(null, "*.env",
+                           $sformatf("aes_ctr_fsm_fi_vif_%0d",  nn),
+                           aes_ctr_fsm_fi_vif[nn])) begin
+        `uvm_fatal(`gfn, $sformatf("FAILED TO GET HANDLE TO ROUND COUNTER INJECT INTERFACE %d",nn))
+      end
+    end
   endfunction
 endclass
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_ctr_fi_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_ctr_fi_vseq.sv
new file mode 100644
index 0000000..d8b6e3a
--- /dev/null
+++ b/hw/ip/aes/dv/env/seq_lib/aes_ctr_fi_vseq.sv
@@ -0,0 +1,75 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// Test that injects random resets &
+// bit errors into FSMs
+class aes_ctr_fi_vseq extends aes_base_vseq;
+  `uvm_object_utils(aes_ctr_fi_vseq)
+
+  `uvm_object_new
+  aes_message_item my_message;
+  status_t aes_status;
+  bit  finished_all_msgs = 0;
+  bit  wait_for_alert_clear = 0;
+  bit  alert = 0;
+
+
+  localparam bit FORCE   = 0;
+  localparam bit RELEASE = 1;
+
+  rand bit [31:0]           force_value;
+  rand int                  if_num;
+  rand int                  target;
+
+  int                       if_size;
+
+
+  task body();
+    `uvm_info(`gfn, $sformatf("\n\n\t ----| STARTING AES MAIN SEQUENCE |----\n %s",
+                              cfg.convert2string()), UVM_LOW)
+
+    // generate list of messages //
+    generate_message_queue();
+
+    // process all messages //
+    fork
+      begin: isolation_fork
+        fork
+          error: begin
+            // avoid forcing IDLE
+            if (!randomize(force_value) with { force_value != '0;}) begin
+              `uvm_fatal(`gfn, $sformatf("Randomization failed"))
+            end
+            if (!randomize(if_num) with { if_num inside { [0:2] };}) begin
+              `uvm_fatal(`gfn, $sformatf("Randomization failed"))
+            end
+            // workaround for vcs issue
+            if_size = cfg.aes_ctr_fsm_fi_vif[if_num].get_if_size();
+            if (!randomize(target) with {
+              target inside { [0:if_size -1]};}) begin
+              `uvm_fatal(`gfn, $sformatf("Randomization failed"))
+            end
+            cfg.clk_rst_vif.wait_clks(cfg.inj_delay);
+            `uvm_info(`gfn, $sformatf("FORCING %h on if[%d]", force_value, if_num), UVM_MEDIUM)
+            cfg.aes_ctr_fsm_fi_vif[if_num].force_signal(target, FORCE, force_value);
+            wait_for_alert_clear = 1;
+          end
+          basic: begin
+            send_msg_queue(cfg.unbalanced, cfg.read_prob, cfg.write_prob);
+          end
+        join_none
+
+        // wait to confirm alert
+        wait(wait_for_alert_clear);
+        `uvm_info(`gfn, $sformatf("Waiting alert ack complete"), UVM_MEDIUM)
+        cfg.m_alert_agent_cfg["fatal_fault"].vif.wait_ack_complete();
+        wait(!cfg.clk_rst_vif.rst_n);
+        cfg.aes_ctr_fsm_fi_vif[if_num].force_signal(target, RELEASE, force_value);
+        `uvm_info(`gfn, $sformatf("Finish"), UVM_MEDIUM)
+        disable fork;
+        end // fork
+    join
+  endtask : body
+
+endclass
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv b/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
index fdf150d..e0eb7b6 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
@@ -14,3 +14,4 @@
 `include "aes_fi_vseq.sv"
 `include "aes_control_fi_vseq.sv"
 `include "aes_cipher_fi_vseq.sv"
+`include "aes_ctr_fi_vseq.sv"
diff --git a/hw/ip/aes/dv/err_injection_if/aes_err_injection.core b/hw/ip/aes/dv/err_injection_if/aes_err_injection.core
index 977de58..bdacc34 100644
--- a/hw/ip/aes/dv/err_injection_if/aes_err_injection.core
+++ b/hw/ip/aes/dv/err_injection_if/aes_err_injection.core
@@ -18,6 +18,8 @@
       - fi_control_if.sv
       - fi_cipher_fsm_wrapper.sv
       - fi_cipher_if.sv
+      - fi_ctr_fsm_wrapper.sv
+      - fi_ctr_fsm_if.sv
     file_type: systemVerilogSource
 
 targets:
diff --git a/hw/ip/aes/dv/err_injection_if/aes_err_injection_bind.sv b/hw/ip/aes/dv/err_injection_if/aes_err_injection_bind.sv
index e7eae35..7e372db 100644
--- a/hw/ip/aes/dv/err_injection_if/aes_err_injection_bind.sv
+++ b/hw/ip/aes/dv/err_injection_if/aes_err_injection_bind.sv
@@ -57,5 +57,12 @@
      .rst_ni       (rst_ni)
      );
 
-
+  bind aes_ctr_fsm fi_ctr_fsm_wrapper
+    #(.IfName("aes_ctr_fsm_fi_vif")
+      )
+  u_control_ctr_fsm_fi
+    (
+     .clk          (clk_i),
+     .rst_ni       (rst_ni)
+     );
 endmodule
diff --git a/hw/ip/aes/dv/err_injection_if/fi_ctr_fsm_if.sv b/hw/ip/aes/dv/err_injection_if/fi_ctr_fsm_if.sv
new file mode 100644
index 0000000..bbd4e3e
--- /dev/null
+++ b/hw/ip/aes/dv/err_injection_if/fi_ctr_fsm_if.sv
@@ -0,0 +1,82 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// target specific signals inside the
+interface fi_ctr_fsm_if
+  import uvm_pkg::*;
+  (
+   input logic clk_i,
+   input logic rst_ni
+   );
+
+  `include "dv_fcov_macros.svh"
+  // get bind path to module
+  string       par_hier = dv_utils_pkg::get_parent_hier($sformatf("%m"), 2);
+
+  // single bit forces
+  string intf_array[] = {
+    $sformatf("%s.%s", par_hier, "incr_i"),
+    $sformatf("%s.%s", par_hier, "ready_o"),
+    $sformatf("%s.%s", par_hier, "ctr_we_o")
+   };
+
+
+  function automatic int get_if_size();
+    return intf_array.size();
+  endfunction // get_if_size
+
+  // check which array we need to access and force or releae
+  function automatic void force_signal(int target, bit rel, bit [31:0] value);
+    if (!rel) aes_ctr_fsm_cg_inst.sample(target);
+    if (!rel) force_single_bit(target);
+    else release_single_bit(target);
+  endfunction // force_signal
+
+
+  function automatic void force_single_bit(int target);
+    bit  read;
+    $assertoff(0, "tb.dut");
+    if (!uvm_hdl_check_path(intf_array[target])) begin
+      `uvm_fatal("fi_ctr_fsm_if", $sformatf("PATH NOT EXISTING %m"))
+    end
+    // read the value currently
+    uvm_hdl_read(intf_array[target], read);
+    // always announce we are forcing something
+    `uvm_info("if_ctr_fsm_if",
+       $sformatf(" I am forcing target %d %s, value %b",target, intf_array[target], !read),UVM_LOW);
+    if (!uvm_hdl_force(intf_array[target],!read)) begin
+      `uvm_error("fi_ctr_fsm_if", $sformatf("Was not able to force %s", intf_array[target]))
+    end
+  endfunction
+
+
+  function automatic void release_single_bit(int target);
+    uvm_hdl_release(intf_array[target]);
+    $asserton(0,"tb.dut");
+  endfunction
+
+
+  ///////////////////////////////////
+  // Fault inject coverage         //
+  ///////////////////////////////////
+
+  covergroup aes_ctr_fsm_cg (int num_bins) with function sample(int target);
+    // We want to see coverage per instance,
+    // but as the code are copies of eachother
+    // we don't need every instance to achieve 100% coverage
+    // a total of 100% is enough so we set the option
+    // to merge the coverage of the instances
+    option.per_instance         = 0;
+    option.name                 = "aes_ctr_fsm_interleave_cg";
+    type_option.merge_instances = 1;
+
+    cp_target: coverpoint target
+      {
+         bins signal_target[] = {[0:num_bins-1]};
+      }
+  endgroup
+
+  //aes_ctr_fsm_cg my_cg = new(intf_array.size() + intf_mul_array.size() -1);
+  `DV_FCOV_INSTANTIATE_CG(aes_ctr_fsm_cg, 1'b1, (intf_array.size()) )
+endinterface
diff --git a/hw/ip/aes/dv/err_injection_if/fi_ctr_fsm_wrapper.sv b/hw/ip/aes/dv/err_injection_if/fi_ctr_fsm_wrapper.sv
new file mode 100644
index 0000000..d88c5cd
--- /dev/null
+++ b/hw/ip/aes/dv/err_injection_if/fi_ctr_fsm_wrapper.sv
@@ -0,0 +1,25 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+
+//wrapper module to avoid having to know/write out the path from tb to bind
+
+
+module fi_ctr_fsm_wrapper
+  import uvm_pkg::*;
+  import aes_env_pkg::*;
+  #( parameter string IfName = "vif"
+  )
+  ( input clk,
+    input rst_ni
+    );
+
+  // declare interface
+  fi_ctr_fsm_if  fi_if (.clk_i  (clk), .rst_ni (rst_ni));
+  initial begin
+    uvm_config_db#(virtual fi_ctr_fsm_if)::set(null, "*",
+      pick_if_name(IfName, $sformatf("%m")), fi_if);
+  end
+
+endmodule