// Moved from docs/src/platform-integration/RASPBERRY_PI_BUILD.adoc to docs/working/scratch/src/platform-integration/RASPBERRY_PI_BUILD.adoc on 2026-06-16 (docs reorg Phase 2) == StarForth on Raspberry Pi 4 - Build Guide :toc: left :toc-title: Contents :toclevels: 3 xref:../README.adoc[← Back to Documentation Index] === Overview This guide covers building and optimizing StarForth for Raspberry Pi 4 with ARM64 assembly optimizations. === Hardware Specifications [cols=",",options="header",] |=== |Component |Specification |CPU |Broadcom BCM2711 (Quad-core Cortex-A72 @ 1.5GHz) |Architecture |ARMv8-A (64-bit) |L1 Cache |32KB I + 32KB D per core |L2 Cache |1MB shared |RAM |1GB/2GB/4GB/8GB LPDDR4-3200 |NEON |Yes (Advanced SIMD) |CRC32 |Yes |=== === Quick Start ==== Option 1: Build Natively on Raspberry Pi [source,bash] ---- # Install dependencies sudo apt update sudo apt install build-essential git # Clone repository git clone starforth cd starforth # Build with ARM64 optimizations make clean make CFLAGS="-std=c99 -O3 -march=armv8-a+crc+simd -mtune=cortex-a72 -DUSE_ASM_OPT=1 -DUSE_DIRECT_THREADING=1 -Iinclude -Isrc/word_source -Isrc/test_runner/include" LDFLAGS="" # Test ./build/starforth ---- ==== Option 2: Cross-Compile from x86_64 Linux [source,bash] ---- # Install cross-compiler sudo apt install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu # Build make clean make CC=aarch64-linux-gnu-gcc \ CFLAGS="-std=c99 -O3 -march=armv8-a+crc+simd -mtune=cortex-a72 -DUSE_ASM_OPT=1 -DUSE_DIRECT_THREADING=1 -Iinclude -Isrc/word_source -Isrc/test_runner/include" \ LDFLAGS="-static" # Copy to Raspberry Pi scp build/starforth pi@raspberrypi.local:~/ ---- === Makefile Integration Add ARM64-specific targets to your Makefile: [source,makefile] ---- # Raspberry Pi 4 native build rpi4: $(MAKE) CFLAGS="$(BASE_CFLAGS) -O3 -march=armv8-a+crc+simd -mtune=cortex-a72 -DUSE_ASM_OPT=1 -DARCH_ARM64=1" LDFLAGS="" # Cross-compile for Raspberry Pi 4 rpi4-cross: $(MAKE) CC=aarch64-linux-gnu-gcc \ CFLAGS="$(BASE_CFLAGS) -O3 -march=armv8-a+crc+simd -mtune=cortex-a72 -DUSE_ASM_OPT=1 -DARCH_ARM64=1 -static" \ LDFLAGS="-static" # Performance build with direct threading rpi4-perf: $(MAKE) CFLAGS="$(BASE_CFLAGS) -O3 -march=armv8-a+crc+simd -mtune=cortex-a72 -DUSE_ASM_OPT=1 -DUSE_DIRECT_THREADING=1 -DARCH_ARM64=1 -flto" LDFLAGS="-flto" ---- === Code Integration ==== 1. Architecture Detection Header Create `+include/arch_detect.h+`: [source,c] ---- #ifndef ARCH_DETECT_H #define ARCH_DETECT_H /* Detect architecture at compile time */ #if defined(__x86_64__) || defined(_M_X64) #define ARCH_X86_64 1 #define ARCH_ARM64 0 #include "vm_asm_opt.h" #include "vm_inner_interp_asm.h" #elif defined(__aarch64__) || defined(_M_ARM64) #define ARCH_X86_64 0 #define ARCH_ARM64 1 #include "vm_asm_opt_arm64.h" #include "vm_inner_interp_arm64.h" #else #define ARCH_X86_64 0 #define ARCH_ARM64 0 #warning "Unknown architecture, assembly optimizations disabled" #endif /* Architecture-agnostic wrapper macros */ #if ARCH_X86_64 #define vm_push_opt(vm, val) vm_push_asm(vm, val) #define vm_pop_opt(vm) vm_pop_asm(vm) #define NEXT_OPT() NEXT_ASM() #define PRIM_DUP_OPT() PRIM_DUP() #define PRIM_DROP_OPT() PRIM_DROP() #define PRIM_SWAP_OPT() PRIM_SWAP() #define PRIM_PLUS_OPT() PRIM_PLUS() /* ... other primitives ... */ #elif ARCH_ARM64 #define vm_push_opt(vm, val) vm_push_asm(vm, val) #define vm_pop_opt(vm) vm_pop_asm(vm) #define NEXT_OPT() NEXT_ARM64() #define PRIM_DUP_OPT() PRIM_DUP_ARM64() #define PRIM_DROP_OPT() PRIM_DROP_ARM64() #define PRIM_SWAP_OPT() PRIM_SWAP_ARM64() #define PRIM_PLUS_OPT() PRIM_PLUS_ARM64() /* ... other primitives ... */ #else #define vm_push_opt(vm, val) vm_push(vm, val) #define vm_pop_opt(vm) vm_pop(vm) #define NEXT_OPT() do {} while(0) /* ... fallback to C implementations ... */ #endif #endif /* ARCH_DETECT_H */ ---- ==== 2. Update Stack Management In `+src/stack_management.c+`: [source,c] ---- #include "../include/vm.h" #include "../include/arch_detect.h" #include "../include/log.h" #include "../include/profiler.h" void vm_push(VM *vm, cell_t value) { PROFILE_INC_STACK_OP(); #if USE_ASM_OPT vm_push_opt(vm, value); if (vm->error) { log_message(LOG_ERROR, "Stack overflow"); } #else if (vm->dsp >= STACK_SIZE - 1) { log_message(LOG_ERROR, "Stack overflow"); vm->error = 1; return; } vm->data_stack[++vm->dsp] = value; log_message(LOG_DEBUG, "PUSH: %ld (dsp=%d)", (long)value, vm->dsp); #endif } cell_t vm_pop(VM *vm) { PROFILE_INC_STACK_OP(); #if USE_ASM_OPT cell_t value = vm_pop_opt(vm); if (vm->error) { log_message(LOG_ERROR, "Stack underflow"); } return value; #else if (vm->dsp < 0) { log_message(LOG_ERROR, "Stack underflow (dsp=%d)", vm->dsp); vm->error = 1; return 0; } cell_t value = vm->data_stack[vm->dsp--]; log_message(LOG_DEBUG, "POP: %ld (dsp=%d)", (long)value, vm->dsp); return value; #endif } ---- ==== 3. Update Arithmetic Words In `+src/word_source/arithmetic_words.c+`: [source,c] ---- #include "../../include/arch_detect.h" void arithmetic_word_plus(VM *vm) { if (vm->dsp < 1) { log_message(LOG_ERROR, "+: Stack underflow"); vm->error = 1; return; } #if USE_ASM_OPT cell_t n2 = vm_pop_opt(vm); cell_t n1 = vm_pop_opt(vm); cell_t result; if (vm_add_check_overflow(n1, n2, &result)) { log_message(LOG_ERROR, "+: Overflow"); vm->error = 1; return; } vm_push_opt(vm, result); #else cell_t n2 = vm_pop(vm); cell_t n1 = vm_pop(vm); vm_push(vm, n1 + n2); #endif log_message(LOG_DEBUG, "+: %ld + %ld = %ld", (long)n1, (long)n2, (long)result); } void arithmetic_word_star_slash_mod(VM *vm) { // n1 n2 n3 -- rem quot (n1*n2/n3, remainder and quotient) if (vm->dsp < 2) { vm->error = 1; return; } #if USE_ASM_OPT cell_t n3 = vm_pop_opt(vm); cell_t n2 = vm_pop_opt(vm); cell_t n1 = vm_pop_opt(vm); if (n3 == 0) { vm->error = 1; return; } // Use double-width multiplication cell_t hi, lo; vm_mul_double(n1, n2, &hi, &lo); // Divide by n3 (simplified - assumes result fits in 64 bits) cell_t quot, rem; vm_divmod(lo, n3, ", &rem); vm_push_opt(vm, rem); vm_push_opt(vm, quot); #else cell_t n3 = vm_pop(vm); cell_t n2 = vm_pop(vm); cell_t n1 = vm_pop(vm); // ... C implementation ... #endif } ---- === Performance Optimization ==== 1. Cache Line Alignment Align VM structure to cache line (64 bytes on Cortex-A72): [source,c] ---- typedef struct VM { /* Hot data - frequently accessed */ cell_t data_stack[STACK_SIZE]; cell_t return_stack[STACK_SIZE]; int dsp; int rsp; /* Align to cache line */ char _padding[64 - ((sizeof(cell_t) * STACK_SIZE * 2 + sizeof(int) * 2) % 64)]; /* Cold data - infrequently accessed */ int error; int halted; // ... } __attribute__((aligned(64))) VM; ---- ==== 2. Prefetching Add prefetch hints in hot loops: [source,c] ---- #if ARCH_ARM64 #include "vm_asm_opt_arm64.h" DictEntry *vm_find_word(VM *vm, const char *name, size_t len) { DictEntry *entry = vm->latest; while (entry) { // Prefetch next entry while processing current if (entry->link) { vm_prefetch(entry->link); } if (entry->name_len == len) { if (vm_strcmp_asm(entry->name, name, len) == 0) { return entry; } } entry = entry->link; } return NULL; } #endif ---- ==== 3. NEON Optimizations For block copy operations: [source,c] ---- #if ARCH_ARM64 && defined(__ARM_NEON) #include void vm_block_copy_neon(void *dest, const void *src, size_t len) { // Copy 64 bytes at a time using NEON while (len >= 64) { uint8x16_t v0 = vld1q_u8((const uint8_t*)src); uint8x16_t v1 = vld1q_u8((const uint8_t*)src + 16); uint8x16_t v2 = vld1q_u8((const uint8_t*)src + 32); uint8x16_t v3 = vld1q_u8((const uint8_t*)src + 48); vst1q_u8((uint8_t*)dest, v0); vst1q_u8((uint8_t*)dest + 16, v1); vst1q_u8((uint8_t*)dest + 32, v2); vst1q_u8((uint8_t*)dest + 48, v3); src += 64; dest += 64; len -= 64; } // Handle remainder vm_memcpy_asm(dest, src, len); } #endif ---- === Benchmarking ==== 1. CPU Frequency Scaling [source,bash] ---- # Check current frequency cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq # Set to performance mode echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor # Or set fixed frequency echo 1500000 | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq ---- ==== 2. Temperature Monitoring [source,bash] ---- # Monitor temperature while benchmarking watch -n 1 vcgencmd measure_temp # Check throttling vcgencmd get_throttled # 0x0 = no throttling # Other values indicate thermal throttling occurred ---- ==== 3. Benchmark Script Create `+benchmarks/rpi4_bench.sh+`: [source,bash] ---- #!/bin/bash echo "StarForth Raspberry Pi 4 Benchmark" echo "===================================" echo "" # System info echo "CPU: $(cat /proc/cpuinfo | grep 'Model' | head -1)" echo "Frequency: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq) kHz" echo "Temperature: $(vcgencmd measure_temp)" echo "" # Set performance mode echo "Setting CPU to performance mode..." echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null # Build baseline echo "Building baseline (no optimizations)..." make clean > /dev/null 2>&1 make CFLAGS="-std=c99 -O2 -Iinclude -Isrc/word_source -Isrc/test_runner/include" LDFLAGS="" > /dev/null 2>&1 cp build/starforth build/starforth_baseline # Build optimized echo "Building optimized (ARM64 ASM)..." make clean > /dev/null 2>&1 make rpi4-perf > /dev/null 2>&1 cp build/starforth build/starforth_opt # Create benchmark cat > /tmp/bench.fth <<'EOF' : BENCH-STACK 1000000 0 DO 1 2 3 DROP DROP DROP LOOP ; : BENCH-MATH 1000000 0 DO 10 20 + 5 * 100 / DROP LOOP ; : BENCH-LOGIC 1000000 0 DO 255 DUP AND DUP OR XOR DROP LOOP ; ." Running benchmarks..." CR ." Stack operations: " BENCH-STACK ." Done" CR ." Math operations: " BENCH-MATH ." Done" CR ." Logic operations: " BENCH-LOGIC ." Done" CR BYE EOF # Run benchmarks echo "" echo "Baseline performance:" time build/starforth_baseline /tmp/bench.fth 2>&1 | grep -v "^$" echo "" echo "Optimized performance:" time build/starforth_opt /tmp/bench.fth 2>&1 | grep -v "^$" echo "" echo "Final temperature: $(vcgencmd measure_temp)" echo "Throttling status: $(vcgencmd get_throttled)" ---- Run it: [source,bash] ---- chmod +x benchmarks/rpi4_bench.sh ./benchmarks/rpi4_bench.sh ---- ==== 4. Detailed Profiling with perf [source,bash] ---- # Install perf (if not already installed) sudo apt install linux-perf # Profile with perf sudo perf record -g ./build/starforth benchmarks/test.fth sudo perf report # Cache analysis sudo perf stat -e cache-references,cache-misses,instructions,cycles ./build/starforth benchmarks/test.fth # Branch prediction sudo perf stat -e branches,branch-misses ./build/starforth benchmarks/test.fth ---- === Thermal Management ==== 1. Passive Cooling Recommended heatsink specs: * Material: Aluminum or copper * Size: Covers entire CPU * Thermal pad: 1mm thick ==== 2. Active Cooling Fan recommendations: * Size: 30mm x 30mm x 7mm * Voltage: 5V * CFM: 3-5 CFM * Connector: 2-pin JST or GPIO GPIO fan control: [source,bash] ---- # Install fan control sudo apt install fancontrol # Auto-configure sudo pwmconfig # Or manual control echo 255 > /sys/class/hwmon/hwmon0/pwm1 # Full speed echo 128 > /sys/class/hwmon/hwmon0/pwm1 # Half speed ---- ==== 3. Overclocking (Optional) ⚠️ *Warning*: Requires adequate cooling and may void warranty Add to `+/boot/config.txt+`: .... # Raspberry Pi 4 overclock over_voltage=6 arm_freq=2000 gpu_freq=750 # Additional cooling required! .... Reboot and verify: [source,bash] ---- sudo reboot cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq ---- === Power Consumption Typical power usage: * Idle: 2-3W * Light load: 4-5W * Full load (all cores): 7-8W * With peripherals: +2-3W Recommendations: * Use official 5V/3A power supply * For battery operation, use 5V/3A+ battery bank * Add power meter for monitoring === SD Card Performance Recommended SD cards: * Class: UHS-I or UHS-II * Speed: A2 or higher (Application Performance Class 2) * Size: 16GB minimum, 32GB+ recommended Brands with good random I/O: * Samsung EVO Plus * SanDisk Extreme * Kingston Canvas React Test SD card speed: [source,bash] ---- # Write test sudo dd if=/dev/zero of=/tmp/test bs=1M count=1024 conv=fdatasync # Read test sudo dd if=/tmp/test of=/dev/null bs=1M count=1024 ---- === Troubleshooting ==== Build Errors *Problem*: `+Illegal instruction+` when running [source,bash] ---- # Check CPU features cat /proc/cpuinfo | grep Features # Rebuild with more conservative flags make rpi4 CFLAGS="$(BASE_CFLAGS) -O2 -march=armv8-a -DUSE_ASM_OPT=1" ---- *Problem*: Cross-compiled binary doesn’t run [source,bash] ---- # Check if binary is static file build/starforth # Should show "statically linked" # If dynamic, rebuild with -static make rpi4-cross LDFLAGS="-static" ---- ==== Performance Issues *Problem*: Slower than expected [source,bash] ---- # Check CPU governor cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # Should be "performance", not "ondemand" # Check for thermal throttling vcgencmd get_throttled # 0x0 = no throttling # Monitor while running watch -n 1 'vcgencmd measure_clock arm; vcgencmd measure_temp' ---- ==== Memory Issues *Problem*: Out of memory [source,bash] ---- # Check available memory free -h # Reduce VM memory size in vm.h #define VM_MEMORY_SIZE (2 * 1024 * 1024) // 2MB instead of 5MB # Or increase swap sudo dphys-swapfile swapoff sudo nano /etc/dphys-swapfile # CONF_SWAPSIZE=2048 sudo dphys-swapfile setup sudo dphys-swapfile swapon ---- === Production Deployment ==== 1. Systemd Service Create `+/etc/systemd/system/starforth.service+`: [source,ini] ---- [Unit] Description=StarForth VM After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi/starforth ExecStart=/home/pi/starforth/build/starforth Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target ---- Enable and start: [source,bash] ---- sudo systemctl enable starforth sudo systemctl start starforth sudo systemctl status starforth ---- ==== 2. Boot Optimization Reduce boot time in `+/boot/config.txt+`: .... # Disable unused features dtparam=audio=off camera_auto_detect=0 display_auto_detect=0 # Faster boot boot_delay=0 disable_splash=1 .... ==== 3. Security Hardening [source,bash] ---- # Update system sudo apt update && sudo apt upgrade -y # Remove unnecessary packages sudo apt autoremove -y # Configure firewall sudo apt install ufw sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow ssh sudo ufw enable # Disable password auth (use keys) sudo nano /etc/ssh/sshd_config # PasswordAuthentication no sudo systemctl restart sshd ---- === Further Reading * https://developer.arm.com/documentation/100095/latest[ARM Cortex-A72 Technical Reference Manual] * https://developer.arm.com/architectures/instruction-sets/simd-isas/neon[ARM NEON Programmer’s Guide] * https://www.raspberrypi.org/documentation/[Raspberry Pi Documentation] * https://developer.arm.com/documentation/ddi0487/latest[ARMv8-A Architecture Reference Manual] === License Public domain / CC0. No warranty. Use at your own risk.