soundstream: load model from spi on bancha Loads the file "kelvin.bin" from the tarball that it expects to find in SPI flash. Note this only happens on bancha; on sencha the flash is owned by the SEC. Change-Id: I5c7aeb5280d053254b4c12743b08e07dbf1565ab
diff --git a/sw/device/cheriot/soundstream/ml_top.cc b/sw/device/cheriot/soundstream/ml_top.cc index bd30f55..270e9e7 100644 --- a/sw/device/cheriot/soundstream/ml_top.cc +++ b/sw/device/cheriot/soundstream/ml_top.cc
@@ -38,6 +38,9 @@ #include "compat.h" #include "hw/top_matcha/sw/autogen/top_matcha.h" #include "ml_top_regs.h" +#if DEVICE_EXISTS_spi_host +#include "spi.h" +#endif typedef uint8_t ml_top_dmem_t[TOP_MATCHA_RAM_ML_DMEM_SIZE_BYTES]; typedef uint32_t @@ -52,6 +55,9 @@ static CountingSemaphoreState startup = { 0, 1 }; void ml_top_init(void) { +#if DEVICE_EXISTS_spi_host + spi_init(); +#endif CHECK_DIF_OK(dif_ml_top_init(mmio_region_from_addr((uintptr_t)MMIO_CAPABILITY( ml_top_mmio_t, ml_top_core)), &ml_top)); @@ -138,13 +144,15 @@ } void ml_top_set_input(void* const data, size_t data_len_bytes) { - uint8_t* ml_top_dmem_base = (uint8_t*) MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); + uint8_t* ml_top_dmem_base = (uint8_t*) + MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); void* input_ptr = ml_top_dmem_base + (TOP_MATCHA_RAM_ML_DMEM_SIZE_BYTES - 4096); memcpy(input_ptr, data, data_len_bytes); } void ml_top_get_output_header(struct output_header* header) { - const uint8_t* ml_top_dmem_base = (uint8_t*) MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); + const uint8_t* ml_top_dmem_base = (uint8_t*) + MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); const struct output_header* output_header_ptr = (const struct output_header*) (ml_top_dmem_base + (TOP_MATCHA_RAM_ML_DMEM_SIZE_BYTES - 0x40)); header->return_code = output_header_ptr->return_code; @@ -160,6 +168,20 @@ } void ml_top_get_output_data(struct output_header* const header, void* buffer) { - const uint8_t* ml_top_dmem_base = (const uint8_t*) MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); + const uint8_t* ml_top_dmem_base = (const uint8_t*) + MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); memcpy(buffer, ml_top_dmem_base + header->output_ptr, header->length); } + +void ml_top_load_file_from_tar(const char* filename) { + CHECK_INIT(); +#if DEVICE_EXISTS_spi_host + uint8_t* ml_top_dmem_base = (uint8_t*) + MMIO_CAPABILITY(ml_top_dmem_t, ml_top_dmem); + spi_load_file_from_tar( + filename, ml_top_dmem_base, + TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR + TOP_MATCHA_RAM_ML_DMEM_SIZE_BYTES); +#else + Debug::log("No SPI support, expecting {} to be side-loaded", filename); +#endif +}
diff --git a/sw/device/cheriot/soundstream/ml_top.h b/sw/device/cheriot/soundstream/ml_top.h index be93516..5ef207f 100644 --- a/sw/device/cheriot/soundstream/ml_top.h +++ b/sw/device/cheriot/soundstream/ml_top.h
@@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef EXAMPLES_SOUNDSTREAM_ML_TOP_H_ -#define EXAMPLES_SOUNDSTREAM_ML_TOP_H_ +#ifndef SW_DEVICE_CHERIOT_SOUNDSTREAM_ML_TOP_H_ +#define SW_DEVICE_CHERIOT_SOUNDSTREAM_ML_TOP_H_ #include <compartment.h> @@ -46,5 +46,7 @@ ml_top_get_output_header(struct output_header* header); void __cheri_compartment("ml_top") ml_top_get_output_data(struct output_header* const header, void* buffer); +void __cheri_compartment("ml_top") + ml_top_load_file_from_tar(const char* filename); -#endif // EXAMPLES_SOUNDSTREAM_ML_TOP_H_ +#endif // SW_DEVICE_CHERIOT_SOUNDSTREAM_ML_TOP_H_
diff --git a/sw/device/cheriot/soundstream/soundstream.cc b/sw/device/cheriot/soundstream/soundstream.cc index a1c4fc6..4397831 100644 --- a/sw/device/cheriot/soundstream/soundstream.cc +++ b/sw/device/cheriot/soundstream/soundstream.cc
@@ -51,6 +51,9 @@ i2s_irq_acknowledge_all(); i2s_irq_set_enabled(kI2sIrqRxWatermark, /*enabled=*/true); + Debug::log("Loading Kelvin binary from SPI"); + ml_top_load_file_from_tar("kelvin.bin"); + // NB: the stack is 4KiB so this uses 1/4 of it int16_t samples_left[kFilterSamples] = {0}; int16_t samples_right[kFilterSamples] = {0};
diff --git a/sw/device/cheriot/soundstream/spi.cc b/sw/device/cheriot/soundstream/spi.cc new file mode 100644 index 0000000..8ca31c1 --- /dev/null +++ b/sw/device/cheriot/soundstream/spi.cc
@@ -0,0 +1,51 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Barebones SPI Flash support for reading data from SPI at startup. + */ +#include "spi.h" + +#include <fail-simulator-on-error.h> +#include <thread.h> + +#include <debug.hh> + +#include "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/spi_flash.h" + +/// Expose debugging features unconditionally for this compartment. +using Debug = ConditionalDebug<false, "SPI">; + +#include "compat.h" + +typedef uint8_t spi_host_t[TOP_MATCHA_SPI_HOST0_SIZE_BYTES]; +typedef uint8_t flash_ctrl_t[TOP_MATCHA_FLASH_CTRL_CORE_SIZE_BYTES]; +typedef uint8_t otp_t[TOP_MATCHA_OTP_CTRL_CORE_SIZE_BYTES]; + +void spi_init(void) { + Debug::log("spi_init: called from Thread {}", thread_id_get()); + CHECK_DIF_OK( + spi_flash_init((uintptr_t)MMIO_CAPABILITY(spi_host_t, spi_host), + (uintptr_t)MMIO_CAPABILITY(flash_ctrl_t, flash_ctrl), + (uintptr_t)MMIO_CAPABILITY(otp_t, otp))); +} + +void spi_load_file_from_tar(const char* filename, void* addr, + size_t max_mem_addr) { + Debug::log("Load {} at {}, max {} ", filename, addr, max_mem_addr); + CHECK_DIF_OK(load_file_from_tar(filename, addr, max_mem_addr)); +}
diff --git a/sw/device/cheriot/soundstream/spi.h b/sw/device/cheriot/soundstream/spi.h new file mode 100644 index 0000000..09278c1 --- /dev/null +++ b/sw/device/cheriot/soundstream/spi.h
@@ -0,0 +1,27 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SW_DEVICE_CHERIOT_SOUNDSTREAM_SPI_H_ +#define SW_DEVICE_CHERIOT_SOUNDSTREAM_SPI_H_ + +#include <compartment.h> + +void __cheri_compartment("spi") spi_init(void); +void __cheri_compartment("spi") + spi_load_file_from_tar(const char* filename, void* addr, + size_t max_mem_addr); + +#endif // SW_DEVICE_CHERIOT_SOUNDSTREAM_SPI_H_
diff --git a/sw/device/cheriot/soundstream/xmake.lua b/sw/device/cheriot/soundstream/xmake.lua index a99ec77..07719f7 100644 --- a/sw/device/cheriot/soundstream/xmake.lua +++ b/sw/device/cheriot/soundstream/xmake.lua
@@ -32,15 +32,27 @@ set_default("sencha") local matcha_dir = path.join(shodan_dir, "hw/matcha") -local dif_dir = path.join(matcha_dir, "sw/device/lib/dif") +local matcha_lib_dir = path.join(matcha_dir, "sw/device/lib") +local dif_dir = path.join(matcha_lib_dir, "dif") local dif_autogen_dir = path.join(dif_dir, "autogen") local opentitan_dir = path.join(shodan_dir, "hw/opentitan-upstream") +local opentitan_lib_dir = path.join(opentitan_dir, "sw/device/lib") +local opentitan_base_dir = path.join(opentitan_lib_dir, "base") +local opentitan_dif_dir = path.join(opentitan_lib_dir, "dif") +local opentitan_dif_autogen_dir = path.join(opentitan_dif_dir, "autogen") +local opentitan_runtime_dir = path.join(opentitan_lib_dir, "runtime") +local opentitan_silicon_dir = path.join(opentitan_dir, "sw/device/silicon_creator/lib") +local opentitan_silicon_drivers_dir = path.join(opentitan_silicon_dir, "drivers") +local opentitan_silicon_base_dir = path.join(opentitan_silicon_dir, "base") local matcha_gen_dir = path.join(cheriot_out_dir, "opentitan-gen/include/opentitan") -- Support libraries includes(path.join(sdkdir, "lib")) includes(path.join(sdkdir, "lib/freestanding")) +local function is_bancha() + return is_config("board", "bancha") +end local function is_sencha() return is_config("board", "sencha") end @@ -69,6 +81,29 @@ add_includedirs(matcha_dir, matcha_gen_dir, opentitan_dir) add_defines("CHERIOT_NO_AMBIENT_MALLOC") +if is_bancha() then +compartment("spi") + add_files("spi.cc") + add_files(path.join(matcha_lib_dir, "spi_flash.c"), + path.join(matcha_lib_dir, "eflash.c"), + path.join(opentitan_dif_dir, "dif_flash_ctrl.c"), + path.join(opentitan_dif_autogen_dir, "dif_flash_ctrl_autogen.c"), + path.join(opentitan_lib_dir, "testing/flash_ctrl_testutils.c"), + path.join(opentitan_silicon_base_dir, "sec_mmio.c"), + path.join(opentitan_silicon_drivers_dir, "flash_ctrl.c"), + path.join(opentitan_silicon_drivers_dir, "otp.c"), + path.join(matcha_lib_dir, "arch/device_sc_fpga_nexus.c"), + path.join(opentitan_dif_dir, "dif_spi_host.c"), + path.join(opentitan_dif_autogen_dir, "dif_spi_host_autogen.c"), + path.join(opentitan_base_dir, "status.c"), + path.join(opentitan_lib_dir, "testing/test_framework/status.c"), + path.join(opentitan_runtime_dir, "log.c"), + path.join(opentitan_runtime_dir, "print.c")) + add_includedirs(matcha_dir, matcha_gen_dir) + add_includedirs(opentitan_dir) + add_defines("CHERIOT_NO_AMBIENT_MALLOC") +end + -- Soundstream application. compartment("soundstream") add_files("soundstream.cc", "encode.cc") @@ -82,6 +117,9 @@ if is_sencha() then add_deps("mailbox") end + if is_bancha() then + add_deps("spi", "string") + end add_deps("soundstream") add_deps("freestanding", "debug") on_load(function(target)