Workaround for Kelvin ASIC fifo issue at SC startup Change-Id: I51889f7a7f8742db5f01997d33dc8bef78c45af8
diff --git a/sw/device/lib/testing/test_framework/BUILD b/sw/device/lib/testing/test_framework/BUILD index 6f9912e..b527390 100644 --- a/sw/device/lib/testing/test_framework/BUILD +++ b/sw/device/lib/testing/test_framework/BUILD
@@ -35,9 +35,10 @@ cc_library( name = "ottf_start", srcs = [ + ":fix_kelvin.c", + "//sw/device/lib/testing/test_framework:ottf_start.S", "@lowrisc_opentitan//sw/device/lib/testing/test_framework:ottf_isrs.S", "@lowrisc_opentitan//sw/device/lib/testing/test_framework:ottf_isrs.c", - "@lowrisc_opentitan//sw/device/lib/testing/test_framework:ottf_start.S", ], hdrs = [ "@lowrisc_opentitan//sw/device/lib/testing/test_framework:ottf_isrs.h", @@ -46,6 +47,9 @@ target_compatible_with = [OPENTITAN_CPU], deps = [ ":linker_script", + "//hw/top_matcha/sw:top_matcha", + "//hw/top_matcha/ip/ml_top/data:ml_top_regs", + "//sw/device/lib/dif:ml_top", "//sw/device/lib/dif:rv_plic_sec", "@lowrisc_opentitan//sw/device/lib/base:csr", "@lowrisc_opentitan//sw/device/lib/base:macros",
diff --git a/sw/device/lib/testing/test_framework/fix_kelvin.c b/sw/device/lib/testing/test_framework/fix_kelvin.c new file mode 100644 index 0000000..64f6b63 --- /dev/null +++ b/sw/device/lib/testing/test_framework/fix_kelvin.c
@@ -0,0 +1,57 @@ +// Copyright 2024 Google LLC +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#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/dif/dif_ml_top.h" +#include "sw/device/lib/testing/test_framework/check.h" + +void fix_kelvin(void) { +#if defined(MATCHA_SPARROW) + dif_ml_top_t ml_top; + mmio_region_t ml_dmem = + mmio_region_from_addr(TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR); + + int i = 0; + for (; i < 8; ++i) { + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), + 0x4000201fU); // vdup.v.x + } + for (; i < 16; ++i) { + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), + 0x42f02c05U); // aconv.vxv + } + for (; i < 24; ++i) { + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), 0x50002c1fU); // vcget + } + for (; i < 32; ++i) { + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), 0x00002000U); // vadd + } + for (; i < 40; ++i) { + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), 0x48000c06U); // adwinit + } + for (; i < 48; ++i) { + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), 0x00002083U); // lw + } + mmio_region_write32(ml_dmem, i * sizeof(uint32_t), 0x08000073U); // mpause + + uint32_t ml_result; + do { + CHECK_DIF_OK(dif_ml_top_init( + mmio_region_from_addr(TOP_MATCHA_ML_TOP_CORE_BASE_ADDR), &ml_top)); + dif_ml_top_reset_ctrl_en(&ml_top); + 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_result = + mmio_region_read32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET)) == + ML_TOP_INTR_STATE_REG_RESVAL) { + } + mmio_region_write32(base_addr, ML_TOP_CTRL_REG_OFFSET, + ML_TOP_CTRL_REG_RESVAL); + mmio_region_write32(base_addr, ML_TOP_INTR_STATE_REG_OFFSET, ml_result); + } while (ml_result == ((1 << ML_TOP_INTR_ENABLE_FINISH_BIT) | + (1 << ML_TOP_INTR_ENABLE_FAULT_BIT))); +#endif // MATCHA_SPARROW +}
diff --git a/sw/device/lib/testing/test_framework/ottf_start.S b/sw/device/lib/testing/test_framework/ottf_start.S new file mode 100644 index 0000000..6c04afd --- /dev/null +++ b/sw/device/lib/testing/test_framework/ottf_start.S
@@ -0,0 +1,195 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * OTTF Interrupt Vector. + */ + + .section .vectors, "ax" + .option push + + // Disable RISC-V instruction compression: we need all instructions to + // be exactly word wide in the interrupt vector. + .option norvc + + // Disable RISC-V linker relaxation, as it can compress instructions at + // link-time, which we also really don't want. + .option norelax + + /** + * `_ottf_interrupt_vector` is an ibex-compatible interrupt vector. + * + * Interrupt vectors in Ibex have 32 4-byte entries for 32 possible interrupts. + * The vector must be 256-byte aligned, as Ibex's vectoring mechanism requires + * that. + * + * Only the following will be used by Ibex: + * - Exception Handler (Entry 0) + * - Machine Software Interrupt Handler (Entry 3) + * - Machine Timer Interrupt Handler (Entry 7) + * - Machine External Interrupt Handler (Entry 11) + * - Vendor Interrupt Handlers (Entries 16-31) + * + * More information about Ibex's interrupts can be found here: + * https://ibex-core.readthedocs.io/en/latest/03_reference/exception_interrupts.html + */ + .balign 256 + .global _ottf_interrupt_vector + .type _ottf_interrupt_vector, @function +_ottf_interrupt_vector: + // RISC-V Standard (Vectored) Interrupt Handlers: + + // Exception and User Software Interrupt Handler. + j handler_exception + // Supervisor Software Interrupt Handler. + unimp + // Reserved. + unimp + // Machine Software Interrupt Handler. + j handler_irq_software + + // User Timer Interrupt Handler. + unimp + // Supervisor Timer Interrupt Handler. + unimp + // Reserved. + unimp + // Machine Timer Interrupt Handler. + j handler_irq_timer + + // User External Interrupt Handler. + unimp + // Supervisor External Interrupt Handler. + unimp + // Reserved. + unimp + // Machine External Interrupt Handler. + j handler_irq_external + + // Reserved. + unimp + unimp + unimp + unimp + + // Vendor Interrupt Handlers: + + // On Ibex, interrupt IDs 16-30 are for "fast" interrupts. + .rept 15 + unimp + .endr + + // On Ibex, interrupt ID 31 is for non-maskable interrupts + j handler_irq_internal + + // Set size so vector can be disassembled. + .size _ottf_interrupt_vector, .-_ottf_interrupt_vector + + .option pop + +// ----------------------------------------------------------------------------- + +/** + * OTTF runtime initialization code. + */ + + /** + * NOTE: The "ax" flag below is necessary to ensure that this section + * is allocated executable space in ROM by the linker. + */ + .section .crt, "ax" + + /** + * Entry point. + * + * This symbol is jumped to from the test ROM or ROM using the + * `entry_point` field of the manifest. + */ + .balign 4 + .global _ottf_start + .type _ottf_start, @function +_ottf_start: + /** + * Set up the global pointer `gp`. + * + * Linker relaxations are disabled until the global pointer is setup below, + * because otherwise some sequences may be turned into `gp`-relative + * sequences, which is incorrect when `gp` is not initialized. + */ + .option push + .option norelax + la gp, __global_pointer$ + .option pop + + /** + * Set up the stack pointer. + * + * In RISC-V, the stack grows downwards, so we load the address of the highest + * word in the stack into sp. We don't load in `_stack_end`, as that points + * beyond the end of RAM, and we always want it to be valid to dereference + * `sp`, and we need this to be 128-bit (16-byte) aligned to meet the psABI. + * + * If an exception fires, the handler is conventionaly only allowed to clobber + * memory at addresses below `sp`. + */ + la sp, (_stack_end - 16) + + /** + * Set well-defined interrupt/exception handlers. + * + * The lowest two bits should be `0b01` to ensure we use vectored interrupts. + */ + la t0, (_ottf_interrupt_vector + 1) + csrw mtvec, t0 + + /** + * Setup C Runtime + */ + + /** + * Initialize the `.data` section in RAM from Flash. + */ + la a0, _data_start + la a1, _data_end + la a2, _data_init_start + call crt_section_copy + + /** + * Initialize the `.bss` section. + * + * We do this despite zeroing all of SRAM above, so that we still zero `.bss` + * once we've enabled SRAM scrambling. + */ + la a0, _bss_start + la a1, _bss_end + call crt_section_clear + + /** + * Call the functions in the `.init_array` section. + * + * This section is typically empty except for executables built with LLVM + * coverage enabled. When coverage is enabled, the compiler emits pointers to + * the functions that initialize the profile buffer in this section. These + * functions must be called before the instrumented functions in the program. + * + * We use `s0` and `s1` to represent the start and end pointers of + * `.init_array`, respectively, and `t0` to store the addresses of the + * functions to be called. + */ + la s0, _init_array_start + la s1, _init_array_end + bgeu s0, s1, init_array_loop_end +init_array_loop: + lw t0, 0(s0) + jalr t0 + addi s0, s0, 0x4 + bltu s0, s1, init_array_loop +init_array_loop_end: + + /** + * Jump into the OTTF C entry point. + */ + call fix_kelvin + tail _ottf_main + .size _ottf_start, .-_ottf_start