diff --git a/default.nix b/default.nix index aa0adf0..6bf39d8 100644 --- a/default.nix +++ b/default.nix @@ -5,8 +5,8 @@ { pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/25.05.tar.gz") {} }: let - py2hwsw_commit = "a3c4ccd834954e8c3404954328daa4762b3ec996"; # Replace with the desired commit. - py2hwsw_sha256 = "gFycJ1H66CulHdnH7RZN5T3l6ou1/p7iX6P2hWQUA0g="; # Replace with the actual SHA256 hash. + py2hwsw_commit = "cbecd558cbac5d2e17388d6ae14cc7120dcac2a3"; # Replace with the desired commit. + py2hwsw_sha256 = "mpMUOrDBam+9/73C24sqdUTKxxx2OetVhcJXSHfTmRw="; # Replace with the actual SHA256 hash. # Get local py2hwsw root from `PY2HWSW_ROOT` env variable py2hwswRoot = builtins.getEnv "PY2HWSW_ROOT"; diff --git a/hardware/fpga/child2_fpga_build.mk b/hardware/fpga/child2_fpga_build.mk index da4460d..ee6075f 100644 --- a/hardware/fpga/child2_fpga_build.mk +++ b/hardware/fpga/child2_fpga_build.mk @@ -8,7 +8,7 @@ UFLAGS+=CACHE_DEMO=$(CACHE_DEMO) ifeq ($(CACHE_DEMO),1) -# Override default linux minicom script to run cache demo instead +# Override default linux minicom script MINICOM_SCRIPT=minicom_cache_demo.txt endif @@ -16,7 +16,7 @@ endif UFLAGS+=UART_DEMO=$(UART_DEMO) ifeq ($(UART_DEMO),1) -# Override default linux minicom script to run cache demo instead +# Override default linux minicom script MINICOM_SCRIPT=minicom_uart_demo.txt endif @@ -29,11 +29,18 @@ MINICOM_SCRIPT=minicom_eth_demo.txt CONSOLE_CMD += && ( cd ../../software/tests/iob_eth && ./validate_eth.sh -S root -p root -s 192.168.74.2 -i $(ETH_IF) ) endif +# Pass CPU_DEMO flag to remote systems +UFLAGS+=CPU_DEMO=$(CPU_DEMO) + +ifeq ($(CPU_DEMO),1) +# Override default linux minicom script +MINICOM_SCRIPT=minicom_cpu_demo.txt +endif + # Pass VIDEO_DEMO flag to remote systems UFLAGS+=VIDEO_DEMO=$(VIDEO_DEMO) ifeq ($(VIDEO_DEMO),1) -GRAB_TIMEOUT= 1500 MINICOM_SCRIPT=minicom_video_demo.txt CONSOLE_CMD += && ( ./video_demo.sh ) endif diff --git a/hardware/fpga/minicom_cpu_demo.txt b/hardware/fpga/minicom_cpu_demo.txt new file mode 100644 index 0000000..c527c40 --- /dev/null +++ b/hardware/fpga/minicom_cpu_demo.txt @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2026 IObundle +# +# SPDX-License-Identifier: MIT + +# Script for "runscript" program of minicom, to test iob_cache (with DMA loopback) in linux + +# Set 15min timeout +# runscript has 2min timeout by default: +# check `timeout` in: https://linux.die.net/man/1/runscript +timeout 900 + +# Wait for the "buildroot login:" message +# Or jump straight to shell if we are already logged in +print "\n[minicom] Waiting for buildroot login..." +send "" +expect { + "buildroot login:" + "\n#" goto post_login + timeout 300 goto on_timeout +} + +print "\n[minicom] Detected login prompt. Logging in..." + +send "root" + +expect { + "Password:" + timeout 20 goto on_timeout +} + +send "root" + +expect { + "#" + timeout 20 goto on_timeout +} + +post_login: + +# +# Run tests +# + +print "\n[minicom] Logged in. Running tests..." + +print "\n[minicom] Print current CPU info:" +send "cat /sys/firmware/devicetree/base/model; echo; cat /proc/cpuinfo; uname -a" +expect { + "#" + timeout 20 goto on_timeout +} + +# +# Tests complete +# + +# Send test.log +send "echo 'Test passed!' > test.log" +send "sz -e test.log" +! rz --overwrite + +print "\n[minicom] Done Test" + +# Exit minicom +! kill `cut -f4 -d' ' /proc/$PPID/stat` + + +# Jump here when timeout is triggered +on_timeout: + +print "\n[minicom] Timeout reached. Exiting..." + +# Exit minicom +! kill `cut -f4 -d' ' /proc/$PPID/stat` + diff --git a/software/src/soc_linux_firmware.c b/software/src/soc_linux_firmware.c index 0fbcb54..076471c 100644 --- a/software/src/soc_linux_firmware.c +++ b/software/src/soc_linux_firmware.c @@ -50,12 +50,32 @@ static volatile uint64_t timestamp = 0; void test_cache_dma_loopback(); void test_cache_counters(); -void clear_cache() { +// Assumes 64-byte cache lines (common in VexiiRiscv/VexRiscv); adjust if +// different +#define CACHE_LINE_SIZE 64 + +// Clean and invalidate CPU data cache. Write-back dirty lines to memory and +// then discard cache contents. +void flush_cache(void *start, size_t len) { +#ifdef SOC_LINUX_CBO + char *end = (char *)start + len; + char *ptr; + + // Round start down to line boundary + ptr = (char *)((uintptr_t)start & ~(CACHE_LINE_SIZE - 1)); + + // Flush (clean + invalidate) whole lines covering the range + while (ptr < end) { + asm volatile("cbo.flush 0(%0)" ::"r"(ptr) : "memory"); + ptr += CACHE_LINE_SIZE; + } +#else // NOT SOC_LINUX_CBO // Delay to ensure all data is written to memory for (unsigned int i = 0; i < 10; i++) asm volatile("nop"); // Flush VexRiscv CPU internal cache asm volatile(".word 0x500F" ::: "memory"); +#endif // SOC_LINUX_CBO } #ifdef SOC_LINUX_USE_ETHERNET @@ -130,7 +150,7 @@ int main() { printf_init(&uart16550_putc); #ifdef SOC_LINUX_USE_ETHERNET // init eth - eth_init(ETH0_BASE, IOB_BSP_FREQ, &clear_cache, &printf_); + eth_init(ETH0_BASE, IOB_BSP_FREQ, &flush_cache, &printf_); eth_wait_phy_rst(); #endif // SOC_LINUX_USE_ETHERNET @@ -421,7 +441,7 @@ void test_cache_dma_loopback() { src_data[3]); // Flush CPU cache to write src_data to memory - clear_cache(); + flush_cache(); // DMA read: src -> AXI stream out (through cache) printf("DMA read from src (via cache) at %p...\n", src_data); @@ -439,7 +459,7 @@ void test_cache_dma_loopback() { while (dma_write_busy()) ; - clear_cache(); + flush_cache(); // printf("Flushing iob_cache\n"); // We should flush cache so that it write's (back) data to memory. However, @@ -476,7 +496,7 @@ void test_cache_counters() { printf("\n--- Cache Counter Test ---\n"); uint32_t test_buf[4] = {0xA5A5A5A5, 0x5A5A5A5A, 0x12345678, 0x87654321}; - clear_cache(); + flush_cache(); // Test 1: Cold DMA read printf("Test 1: DMA read (cold)...\n"); diff --git a/software/sw_build.mk b/software/sw_build.mk index b6c8d3d..410f57d 100644 --- a/software/sw_build.mk +++ b/software/sw_build.mk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2025 IObundle +# SPDX-FileCopyrightText: 2026 IObundle # # SPDX-License-Identifier: MIT @@ -101,7 +101,7 @@ FIRM_ADDR_W = $(call GET_SOC_LINUX_CONF_MACRO,MEM_ADDR_W) soc_linux_firmware.hex: $(FIRMWARE) ../../scripts/makehex.py $(FIRM_ARGS) $(FIRM_ADDR_W) $@ # ../../scripts/hex_split.py soc_linux_firmware . - ../../scripts/makehex.py --split $< $(call GET_SOC_LINUX_CONF_MACRO,MEM_ADDR_W) $@ + ../../scripts/makehex.py --split $(FIRM_ARGS) $(FIRM_ADDR_W) $@ soc_linux_firmware.bin: ../../software/soc_linux_firmware.bin cp $< $@ @@ -165,6 +165,7 @@ compile_device_tree: linux_build_macros.txt peripherals.dtsi nix-shell $(OS_DIR)/default.nix --run 'make -C $(OS_DIR) build-dts MACROS_FILE=$(REL_OS2ROOT)/software/linux_build_macros.txt DTS_FILE=$(REL_OS2ROOT)/software/soc_linux.dts' compile_opensbi: + $(if $(call GET_SOC_LINUX_CONF_MACRO,MSTATUSH),,$(ROOT_DIR)/scripts/patch_opensbi.sh) nix-shell $(OS_DIR)/default.nix --run 'make -C $(OS_DIR) build-opensbi MACROS_FILE=$(REL_OS2ROOT)/software/linux_build_macros.txt OPENSBI_PLATFORM_DIR=$(REL_OS2ROOT)/software/opensbi_platform/soc_linux' .PHONY: compile_device_tree compile_opensbi @@ -189,8 +190,8 @@ TEMPLATE_LDS=src/$@.lds #endif # ## Compiler FLAGS with custom architecture, including atomic instructions -#SOC_LINUX_CFLAGS ?=-Os -nostdlib -march=rv32imac -mabi=ilp32 --specs=nano.specs -Wcast-align=strict $(SIM_DEFINE) -SOC_LINUX_CFLAGS ?=-Os -nostdlib -march=rv32imac -mabi=ilp32 --specs=nano.specs -Wcast-align=strict +#SOC_LINUX_CFLAGS ?=-Os -nostdlib -march=rv32imac_zicsr_zifencei_zicbom -mabi=ilp32 --specs=nano.specs -Wcast-align=strict $(SIM_DEFINE) +#SOC_LINUX_CFLAGS ?=-Os -nostdlib -march=rv32imac_zicsr_zifencei_zicbom -mabi=ilp32 --specs=nano.specs -Wcast-align=strict SOC_LINUX_INCLUDES=-Isrc #SOC_LINUX_INCLUDES=-Isrc -Isrc/crypto/McEliece -Isrc/crypto/McEliece/common @@ -222,7 +223,7 @@ SOC_LINUX_FW_SRC+=src/iob_printf.c # UTARGETS+=crypto # # crypto: -# riscv64-unknown-linux-gnu-gcc -std=gnu99 -march=rv32imac -mabi=ilp32 -Wcast-align=strict -Os -s -ffunction-sections $(CRYPTO_SRC) -o crypto -Isrc/crypto/McEliece -Isrc/crypto/McEliece/common -Isrc/linux -Wl,-gc-sections -Wl,--strip-all +# riscv64-unknown-linux-gnu-gcc -std=gnu99 -march=rv32imac_zicsr_zifencei_zicbom -mabi=ilp32 -Wcast-align=strict -Os -s -ffunction-sections $(CRYPTO_SRC) -o crypto -Isrc/crypto/McEliece -Isrc/crypto/McEliece/common -Isrc/linux -Wl,-gc-sections -Wl,--strip-all # # .PHONY: crypto @@ -235,6 +236,7 @@ SOC_LINUX_FW_SRC+=$(addprefix src/,$(addsuffix _csrs.c,$(PERIPHERALS))) # Filter out iob_uart16550_csrs.c since it has no csrs SOC_LINUX_FW_SRC:=$(filter-out src/iob_uart16550_csrs.c,$(SOC_LINUX_FW_SRC)) + # BOOTLOADER SOURCES SOC_LINUX_BOOT_SRC+=src/soc_linux_boot.S SOC_LINUX_BOOT_SRC+=src/soc_linux_boot.c