From da6e1ea7b0d8eb2d37fce909d8ea69351d1cd25c Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Tue, 25 Nov 2025 17:16:32 +0100 Subject: [PATCH] Simple mandelbrot in rust --- bench/link.ld | 2 - bench/programs_rust/.cargo/config.toml | 1 + bench/programs_rust/hello-rust/Cargo.toml | 1 + bench/programs_rust/hello-rust/src/main.rs | 125 ++++++++++++++++----- 4 files changed, 99 insertions(+), 30 deletions(-) diff --git a/bench/link.ld b/bench/link.ld index bab7592..cc9a88a 100644 --- a/bench/link.ld +++ b/bench/link.ld @@ -34,6 +34,4 @@ SECTIONS PROVIDE(_stack_size = 1024); /* 1 KiB */ PROVIDE(_stack_start = _memory_end); PROVIDE(_stack_end = _stack_start - _stack_size); - - } diff --git a/bench/programs_rust/.cargo/config.toml b/bench/programs_rust/.cargo/config.toml index cf30495..570f2ad 100644 --- a/bench/programs_rust/.cargo/config.toml +++ b/bench/programs_rust/.cargo/config.toml @@ -14,3 +14,4 @@ rustflags = [ [unstable] build-std = ["core", "compiler_builtins"] +build-std-features = ["compiler-builtins-mem"] diff --git a/bench/programs_rust/hello-rust/Cargo.toml b/bench/programs_rust/hello-rust/Cargo.toml index 5e7e4cf..93ff39d 100644 --- a/bench/programs_rust/hello-rust/Cargo.toml +++ b/bench/programs_rust/hello-rust/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" [dependencies] fpga-lib = { path = "../fpga-lib" } +libm = "0.2.11" diff --git a/bench/programs_rust/hello-rust/src/main.rs b/bench/programs_rust/hello-rust/src/main.rs index 1d0e4ca..79fc530 100644 --- a/bench/programs_rust/hello-rust/src/main.rs +++ b/bench/programs_rust/hello-rust/src/main.rs @@ -1,51 +1,120 @@ #![no_std] #![no_main] -use core::arch::asm; +use core::{ + arch::asm, + ops::{Add, Mul}, +}; use fpga_lib::{ interface::{Buttons, Leds}, panic_handler, register::X31, - vga::{BLACK, BLUE, FONT_WIDTH, GREEN, RED, VGA, WHITE}, + vga::{BLACK, BLUE, Color, FONT_WIDTH, GREEN, HEIGHT, RED, VGA, WHITE, WIDTH}, }; +type Float = f32; +pub const ITERATIONS: usize = 100; +pub const ASPECT_RATIO: f32 = WIDTH as f32 / HEIGHT as f32; + +#[derive(Clone, Copy)] +struct Complex(Float, Float); + +impl Complex +{ + pub fn sq_mag(&self) -> Float + { + self.0 * self.0 + self.1 * self.1 + } +} + +pub fn map(x: Float, xmin: Float, xmax: Float, ymin: Float, ymax: Float) -> Float +{ + ((x - xmin) / (xmax - xmin)) * (ymax - ymin) + ymin +} + +impl Add for Complex +{ + type Output = Complex; + + fn add(self, Self(a, b): Self) -> Self::Output + { + Complex(self.0 + a, self.1 + b) + } +} + +impl Mul for Complex +{ + type Output = Complex; + + fn mul(self, Self(a, b): Self) -> Self::Output + { + Complex(self.0 * a - self.1 * b, self.0 * b + self.1 * a) + } +} + panic_handler! {} #[unsafe(no_mangle)] pub extern "C" fn main() -> ! { - loop + let color_lut: [Color; ITERATIONS] = { + let mut tab = [BLACK; _]; + for i in 0..(ITERATIONS - 1) + { + let val = ((i as Float / ITERATIONS as Float) * 255.) as u8; + tab[i] = Color::from_rgb(val, val, val); + } + + tab + }; + + let width = 2.; + for x in 0..WIDTH { - unsafe { - VGA::draw_string(10, 10, "Running RUST !", GREEN); - VGA::draw_string(10, 23, "LedIp state :", RED); + for y in 0..HEIGHT + { + let pos = Complex( + map( + x as Float, + 0., + WIDTH as Float, + -width * ASPECT_RATIO * 0.5, + width * ASPECT_RATIO * 0.5, + ) - 0.5, + map(y as Float, 0., HEIGHT as Float, -width * 0.5, width * 0.5), + ); + let mut acc = pos; + let mut iter = 0; - let clint_time: *mut u64 = 0x0200bff8 as *mut u64; - - let clocks = *clint_time; - let seconds = clocks / 80_000_000; - VGA::draw_string(100, 10, "CLint:", BLUE); - VGA::draw_u64(150, 10, clocks, BLUE, BLACK); - VGA::draw_string(100, 23, "(s)", BLUE); - VGA::draw_u64(150, 23, seconds, BLUE, BLACK); - - for i in 0..4 + // Optimisations + let p = ((pos.0 - 0.25) * (pos.0 - 0.25)) + pos.1 * pos.1; + if (pos.0 < libm::sqrtf(p) - 2. * p + 0.25) + || (pos.0 + 1.) * (pos.0 + 1.) + pos.1 * pos.1 < 1. / 16. { - VGA::draw_char(10 + i * 16, 46, 'B', RED); - VGA::draw_char(16 + i * 16, 46, (b'0' + i as u8) as char, RED); + iter = ITERATIONS - 1; + } + else + { + for i in 0..ITERATIONS + { + acc = acc * acc + pos; + if acc.sq_mag() > 1. + { + iter = i; + break; + } + } + } - if Buttons::get_button(i as u8) - { - Leds::set_led(i as u8, true); - VGA::draw_char_bg(10 + i * 16, 59, '1', GREEN, BLACK); - } - else - { - Leds::set_led(i as u8, false); - VGA::draw_char_bg(10 + i * 16, 59, '0', RED, BLACK); - } + unsafe { + VGA::write_pixel_unsafe(x as u16, y as u16, color_lut[iter]); } } } + + loop + { + core::hint::spin_loop(); + } }