Merge "Add 3 pwrmgr tests to edacloud"
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index be83664..4452cc6 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -2175,7 +2175,6 @@
         "chip_sw_sleep_pin_retention",
         "chip_sw_sleep_pin_wake",
         "chip_sw_sleep_pwm_pulses",
-        "chip_sw_sleep_sram_ret_contents",
         "chip_sw_smc_cam_irq_test",
         "chip_sw_smc_ctrl_test",
         "chip_sw_smc_env_test",
@@ -2210,7 +2209,6 @@
         "chip_sw_uart_smoketest",
         "chip_sw_uart_tx_rx",
         "chip_tap_straps_dev",
-        "chip_tap_straps_prod",
         "chip_tap_straps_rma",
       ]
     }
diff --git a/sw/device/tests/kelvin/fpga_tests/BUILD b/sw/device/tests/kelvin/fpga_tests/BUILD
index 364d0cf..612828e 100644
--- a/sw/device/tests/kelvin/fpga_tests/BUILD
+++ b/sw/device/tests/kelvin/fpga_tests/BUILD
@@ -23,11 +23,10 @@
         "//hw/top_matcha/ip/ml_top/data:ml_top_regs",
         "//hw/top_matcha/sw/autogen:top_matcha",
         "//sw/device/lib:spi_flash",
+        "//sw/device/lib/dif:rv_plic_sec",
         "//sw/device/lib/dif:smc_ctrl",
-        "//sw/device/lib/testing/test_framework:ottf_start",
-        "//sw/device/lib/testing/test_framework:test_util",
-        "@lowrisc_opentitan//sw/device/lib/testing/test_framework:ottf_test_config",
-        "@lowrisc_opentitan//sw/device/silicon_creator/lib:manifest_def",
+        "//sw/device/lib/dif:tlul_mailbox",
+        "//sw/device/tests:test_lib",
     ],
 )
 
@@ -43,11 +42,13 @@
     per_device_deps = {
         "fpga_nexus": [NEXUS_CORE_TARGETS.get("smc")],
     },
-    var_name = "kelvin_test_smc_fpga_nexus_bin",
     deps = [
+        "//hw/top_matcha/ip/ml_top/data:ml_top_regs",
         "//hw/top_matcha/sw/autogen:top_matcha",
-        "//sw/device/lib/testing/test_framework:ottf_start_smc",
-        "//sw/device/lib/testing/test_framework:test_util",
-        "@lowrisc_opentitan//sw/device/lib/testing/test_framework:ottf_test_config",
+        "//sw/device/lib/dif:ml_top",
+        "//sw/device/lib/dif:rv_plic_smc",
+        "//sw/device/lib/dif:tlul_mailbox",
+        "//sw/device/tests:test_lib_smc",
+        "@lowrisc_opentitan//sw/device/lib/dif:rv_timer",
     ],
 )
diff --git a/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c b/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c
index 0031960..4887bd2 100644
--- a/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c
+++ b/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c
@@ -3,8 +3,11 @@
 #include "hw/top_matcha/ip/ml_top/data/ml_top_regs.h"  // Generated.
 #include "hw/top_matcha/sw/autogen/top_matcha.h"
 #include "sw/device/lib/arch/device.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
 #include "sw/device/lib/dif/dif_smc_ctrl.h"
+#include "sw/device/lib/dif/dif_tlul_mailbox.h"
 #include "sw/device/lib/dif/dif_uart.h"
+#include "sw/device/lib/runtime/irq.h"
 #include "sw/device/lib/runtime/print.h"
 #include "sw/device/lib/spi_flash.h"
 #include "sw/device/lib/testing/test_framework/check.h"
@@ -13,16 +16,31 @@
 #include "sw/device/lib/testing/test_framework/test_util.h"
 
 /*
- * Sample program to run some code on all cores in the system.
- * SC - Orchestrate the other cores, print status to UART.
- * SMC - Print to UART.
- * Kelvin - SW program built to run on Kelvin.
+ * SC - Initialize SMC, load kelvin program, and print status to UART.
+ * SMC - Print to UART and orchestrate ML core/programs.
  */
 
 OTTF_DEFINE_TEST_CONFIG();
 
 static dif_smc_ctrl_t smc_ctrl;
 static dif_uart_t uart;
+static dif_rv_plic_t plic_sec;
+static dif_tlul_mailbox_t tlul_mailbox;
+
+volatile uint32_t message;
+
+void ottf_external_isr(void) {
+  dif_rv_plic_irq_id_t plic_irq_id;
+  uint32_t rx;
+  CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic_sec, kTopMatchaPlicTargetIbex0,
+                                     &plic_irq_id));
+  CHECK_DIF_OK(
+      dif_tlul_mailbox_irq_acknowledge(&tlul_mailbox, kDifTlulMailboxIrqRtirq));
+  CHECK_DIF_OK(dif_tlul_mailbox_read_message(&tlul_mailbox, &rx));
+  message = rx;
+  CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic_sec, kTopMatchaPlicTargetIbex0,
+                                        plic_irq_id));
+}
 
 void _ottf_main(void) {
   test_status_set(kTestStatusInTest);
@@ -44,17 +62,33 @@
     mmio_region_write32(ml_dmem, i * sizeof(uint32_t), 0);
   }
 
+  // Setup mailbox.
+  CHECK_DIF_OK(dif_tlul_mailbox_init(
+      mmio_region_from_addr(TOP_MATCHA_TLUL_MAILBOX_SEC_BASE_ADDR),
+      &tlul_mailbox));
+  CHECK_DIF_OK(dif_tlul_mailbox_irq_set_enabled(
+      &tlul_mailbox, kDifTlulMailboxIrqRtirq, kDifToggleEnabled));
+  CHECK_DIF_OK(dif_tlul_mailbox_irq_set_enabled(
+      &tlul_mailbox, kDifTlulMailboxIrqWtirq, kDifToggleEnabled));
+  CHECK_DIF_OK(dif_tlul_mailbox_irq_set_enabled(
+      &tlul_mailbox, kDifTlulMailboxIrqEirq, kDifToggleEnabled));
+
+  // Set Interrupt.
+  CHECK_DIF_OK(dif_rv_plic_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic_sec));
+  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
+      &plic_sec, kTopMatchaPlicIrqIdTlulMailboxSecRtirq,
+      kTopMatchaPlicTargetIbex0, kDifToggleEnabled));
+  CHECK_DIF_OK(dif_rv_plic_irq_set_priority(
+      &plic_sec, kTopMatchaPlicIrqIdTlulMailboxSecRtirq, 1));
+  irq_global_ctrl(true);
+  irq_external_ctrl(true);
+
   // Enable SMC.
   CHECK_DIF_OK(dif_smc_ctrl_init(
       mmio_region_from_addr(TOP_MATCHA_SMC_CTRL_BASE_ADDR), &smc_ctrl));
   CHECK_DIF_OK(dif_smc_ctrl_set_en(&smc_ctrl));
 
-  // Reset and Freeze Kelvin.
-  mmio_region_t base_addr =
-      mmio_region_from_addr(TOP_MATCHA_ML_TOP_CORE_BASE_ADDR);
-  mmio_region_write32(base_addr, ML_TOP_CTRL_REG_OFFSET,
-                      ML_TOP_CTRL_REG_RESVAL | (1 << ML_TOP_CTRL_FREEZE_BIT));
-
   // Copy binary to ML_DMEM.
   char kelvin_bin_name[256] = {'\0'};
   size_t bin_offset = 0;
@@ -70,32 +104,15 @@
     CHECK_DIF_OK(kelvin_load_result, "Failed to load %s", kelvin_bin_name);
     test_num++;
     LOG_INFO("Test %d: Run kelvin binary %s", test_num, kelvin_bin_name);
-    // Start up Kelvin.
-    mmio_region_write32(base_addr, ML_TOP_CTRL_REG_OFFSET, 0x0);
-    uint32_t intr_state =
-        mmio_region_read32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET);
-    // TODO(ykwang): Change this to interrupt handler.
-    while (intr_state == 0x0) {
-      busy_spin_micros(10 * 1000);  // Wait for 10ms.
-      intr_state = mmio_region_read32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET);
-    }
-    // Received interrupts from Kelvin core, check if only FINISH asserted
-    if (intr_state != (1 << ML_TOP_INTR_STATE_FINISH_BIT)) {
-      LOG_ERROR("INTR_STATE read out: expected : 0x%x | actual: 0x%x",
-                (1 << ML_TOP_INTR_STATE_FINISH_BIT), intr_state);
+    uint32_t tx = 0;
+    // Send to smc to kickoff ML program
+    CHECK_DIF_OK(dif_tlul_mailbox_send_message(&tlul_mailbox, &tx));
+    // Wait for mailbox interrupt
+    asm volatile("wfi");
+    if (message != (1 << ML_TOP_INTR_STATE_FINISH_BIT)) {
+      LOG_ERROR("    Test finish with fault");
       failed_test++;
     }
-    // Reset and halt Kelvin
-    mmio_region_write32(base_addr, ML_TOP_CTRL_REG_OFFSET,
-                        ML_TOP_CTRL_REG_RESVAL | (1 << ML_TOP_CTRL_FREEZE_BIT));
-    // Write 1 to clear INTR_STATE
-    mmio_region_write32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET, intr_state);
-    intr_state = mmio_region_read32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET);
-    CHECK(
-        intr_state == 0,
-        "ML_TOP_Core offset 0 INTR_STATE  read  again - Expected: 0 | Actual: "
-        "0x%x",
-        intr_state);
   }
   LOG_INFO("Total test: %d, failed test: %d", test_num, failed_test);
   if (failed_test == 0) {
diff --git a/sw/device/tests/kelvin/fpga_tests/kelvin_test_smc.c b/sw/device/tests/kelvin/fpga_tests/kelvin_test_smc.c
index ec9f4a8..916b4c8 100644
--- a/sw/device/tests/kelvin/fpga_tests/kelvin_test_smc.c
+++ b/sw/device/tests/kelvin/fpga_tests/kelvin_test_smc.c
@@ -1,17 +1,167 @@
+#include "hw/top_matcha/ip/ml_top/data/ml_top_regs.h"  // Generated.
 #include "hw/top_matcha/sw/autogen/top_matcha.h"
 #include "sw/device/lib/arch/device.h"
+#include "sw/device/lib/dif/dif_ml_top.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_tlul_mailbox.h"
 #include "sw/device/lib/dif/dif_uart.h"
+#include "sw/device/lib/runtime/irq.h"
 #include "sw/device/lib/runtime/print.h"
 #include "sw/device/lib/testing/test_framework/check.h"
 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
 #include "sw/device/lib/testing/test_framework/test_util.h"
 
+/*
+ * Sample program to run some code on all cores in the system.
+ * SMC - Print to UART and orchestrate ML core/programs.
+ * Kelvin - SW program built to run on Kelvin.
+ */
+
 OTTF_DEFINE_TEST_CONFIG();
 
 static dif_uart_t smc_uart;
+static dif_tlul_mailbox_t tlul_mailbox;
+static dif_rv_plic_t plic_smc;
+static dif_rv_timer_t rv_timer;
+static dif_ml_top_t ml_top;
+
+static volatile bool ml_top_done = false;
+static volatile bool bin_loaded = false;
+static volatile uint32_t ml_result = 0;
+
+void ottf_external_isr(void) {
+  dif_rv_plic_irq_id_t plic_irq_id;
+  CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic_smc, kTopMatchaPlicTargetIbex0Smc,
+                                     &plic_irq_id));
+  top_matcha_plic_peripheral_smc_t peripheral_id =
+      top_matcha_plic_interrupt_for_peripheral_smc[plic_irq_id];
+  CHECK(peripheral_id == kTopMatchaPlicPeripheralTlulMailboxSmc ||
+            peripheral_id == kTopMatchaPlicPeripheralMlTop,
+        "Unexpected peripheral in ISR: %d", peripheral_id);
+  switch (peripheral_id) {
+    case kTopMatchaPlicPeripheralTlulMailboxSmc: {
+      uint32_t rx;
+      CHECK_DIF_OK(dif_tlul_mailbox_irq_acknowledge(&tlul_mailbox,
+                                                    kDifTlulMailboxIrqRtirq));
+      CHECK_DIF_OK(dif_tlul_mailbox_read_message(&tlul_mailbox, &rx));
+      bin_loaded = true;
+      break;
+    }
+    case kTopMatchaPlicPeripheralMlTop: {
+      mmio_region_t base_addr =
+          mmio_region_from_addr(TOP_MATCHA_ML_TOP_CORE_BASE_ADDR);
+      // Reset and halt Kelvin
+      mmio_region_write32(
+          base_addr, ML_TOP_CTRL_REG_OFFSET,
+          ML_TOP_CTRL_REG_RESVAL | (1 << ML_TOP_CTRL_FREEZE_BIT));
+      ml_result = mmio_region_read32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET);
+      // Write 1 to clear INTR_STATE
+      mmio_region_write32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET, ml_result);
+      uint32_t intr_state =
+          mmio_region_read32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET);
+      CHECK(intr_state == 0,
+            "ML Top interrupt reset failed: expect 0, actual 0x%x", intr_state);
+      ml_top_done = true;
+      break;
+    }
+    default:
+      LOG_FATAL("Peripheral is not implemented!");
+  }
+  CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic_smc, kTopMatchaPlicTargetIbex0Smc,
+                                        plic_irq_id));
+}
+
+/*
+ * Configures all the relevant interrupts in PLIC_SMC.
+ */
+static void plic_smc_configure_irqs(dif_rv_plic_t *plic) {
+  // Set ML_TOP IRQ priorities to MAX
+  CHECK_DIF_OK(dif_rv_plic_irq_set_priority(
+      plic, kTopMatchaPlicIrqIdMlTopFinish, kDifRvPlicMaxPriority));
+  CHECK_DIF_OK(dif_rv_plic_irq_set_priority(plic, kTopMatchaPlicIrqIdMlTopFault,
+                                            kDifRvPlicMaxPriority));
+  // Set Ibex IRQ priority threshold level
+  CHECK_DIF_OK(dif_rv_plic_target_set_threshold(
+      plic, kTopMatchaPlicTargetIbex0Smc, kDifRvPlicMinPriority));
+
+  // Enable Mailbox IRQs
+  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
+      plic, kTopMatchaPlicIrqIdTlulMailboxSmcRtirq,
+      kTopMatchaPlicTargetIbex0Smc, kDifToggleEnabled));
+  CHECK_DIF_OK(dif_rv_plic_irq_set_priority(
+      plic, kTopMatchaPlicIrqIdTlulMailboxSmcRtirq, 1));
+  // Enable ML core IRQs
+  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(plic, kTopMatchaPlicIrqIdMlTopFinish,
+                                           kTopMatchaPlicTargetIbex0Smc,
+                                           kDifToggleEnabled));
+  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(plic, kTopMatchaPlicIrqIdMlTopFault,
+                                           kTopMatchaPlicTargetIbex0Smc,
+                                           kDifToggleEnabled));
+}
 
 void _ottf_main(void) {
   init_uart(TOP_MATCHA_SMC_UART_BASE_ADDR, &smc_uart);
   LOG_INFO("kelvin_test_smc");
-  asm volatile("wfi");
+
+  // Configure Mailbox.
+  CHECK_DIF_OK(dif_tlul_mailbox_init(
+      mmio_region_from_addr(TOP_MATCHA_TLUL_MAILBOX_SMC_BASE_ADDR),
+      &tlul_mailbox));
+  CHECK_DIF_OK(dif_tlul_mailbox_irq_set_enabled(
+      &tlul_mailbox, kDifTlulMailboxIrqRtirq, kDifToggleEnabled));
+  CHECK_DIF_OK(dif_tlul_mailbox_irq_set_enabled(
+      &tlul_mailbox, kDifTlulMailboxIrqWtirq, kDifToggleEnabled));
+  CHECK_DIF_OK(dif_tlul_mailbox_irq_set_enabled(
+      &tlul_mailbox, kDifTlulMailboxIrqEirq, kDifToggleEnabled));
+
+  // Init ML_TOP
+  CHECK_DIF_OK(dif_ml_top_init(
+      mmio_region_from_addr(TOP_MATCHA_ML_TOP_CORE_BASE_ADDR), &ml_top));
+  CHECK_DIF_OK(dif_ml_top_irq_set_enabled(&ml_top, kDifMlTopIrqFinish,
+                                          kDifToggleEnabled));
+  CHECK_DIF_OK(dif_ml_top_irq_set_enabled(&ml_top, kDifMlTopIrqFault,
+                                          kDifToggleEnabled));
+  dif_ml_top_reset_ctrl_en(&ml_top);
+
+  // Set interrupt.
+  CHECK_DIF_OK(dif_rv_plic_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_PLIC_SMC_BASE_ADDR), &plic_smc));
+  plic_smc_configure_irqs(&plic_smc);
+  irq_global_ctrl(true);
+  irq_external_ctrl(true);
+
+  // Set timer.
+  dif_rv_timer_tick_params_t tick_params;
+  CHECK_DIF_OK(dif_rv_timer_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_TIMER_SMC_BASE_ADDR), &rv_timer));
+  CHECK_DIF_OK(dif_rv_timer_approximate_tick_params(kClockFreqPeripheralHz,
+                                                    1000, &tick_params));
+  CHECK_DIF_OK(dif_rv_timer_set_tick_params(&rv_timer, 0, tick_params));
+  CHECK_DIF_OK(
+      dif_rv_timer_counter_set_enabled(&rv_timer, 0, kDifToggleEnabled));
+
+  uint32_t bin_index = 0;
+  while (true) {
+    uint64_t timer_start, timer_end;
+    bin_loaded = false;
+    while (!bin_loaded) {
+      asm volatile("wfi");
+    }
+    // Start up Kelvin.
+    ml_top_done = false;
+    ml_result = 0;
+    CHECK_DIF_OK(dif_rv_timer_counter_read(&rv_timer, 0, &timer_start));
+    mmio_region_t base_addr =
+        mmio_region_from_addr(TOP_MATCHA_ML_TOP_CORE_BASE_ADDR);
+    mmio_region_write32(base_addr, ML_TOP_CTRL_REG_OFFSET, 0x0);
+    while (!ml_top_done) {
+      asm volatile("wfi");
+    }
+    CHECK_DIF_OK(dif_rv_timer_counter_read(&rv_timer, 0, &timer_end));
+    LOG_INFO("Test %d: Finish in %d ms", ++bin_index,
+             (uint32_t)(timer_end - timer_start));
+    uint32_t tx = ml_result;
+    CHECK_DIF_OK(dif_tlul_mailbox_send_message(&tlul_mailbox, &tx));
+  }
 }