Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
13 changes: 10 additions & 3 deletions hardware/fpga/child2_fpga_build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
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

# Pass UART_DEMO flag to remote systems
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

Expand All @@ -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
Expand Down
75 changes: 75 additions & 0 deletions hardware/fpga/minicom_cpu_demo.txt
Original file line number Diff line number Diff line change
@@ -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`

30 changes: 25 additions & 5 deletions software/src/soc_linux_firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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");
Expand Down
12 changes: 7 additions & 5 deletions software/sw_build.mk
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2025 IObundle
# SPDX-FileCopyrightText: 2026 IObundle
#
# SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -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 $< $@
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
Loading