From 8326c1f169030a416d81a4456979a721b04f7ec7 Mon Sep 17 00:00:00 2001 From: supersurviveur Date: Wed, 12 Nov 2025 22:05:25 +0100 Subject: [PATCH 1/3] Starts adding rust in the toolchain --- Makefile | 12 +++++++++--- bench/programs_rust/.cargo/config.toml | 14 ++++++++++++++ bench/programs_rust/.gitignore | 3 +++ bench/programs_rust/Cargo.toml | 13 +++++++++++++ bench/programs_rust/fpga_lib/Cargo.toml | 6 ++++++ bench/programs_rust/fpga_lib/src/lib.rs | 11 +++++++++++ bench/programs_rust/hello_rust/Cargo.toml | 7 +++++++ bench/programs_rust/hello_rust/src/main.rs | 18 ++++++++++++++++++ bench/programs_rust/riscv64i.json | 21 +++++++++++++++++++++ bench/programs_rust/rust-toolchain.toml | 2 ++ src/main/scala/projet/op/OpRW.scala | 1 - 11 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 bench/programs_rust/.cargo/config.toml create mode 100644 bench/programs_rust/.gitignore create mode 100644 bench/programs_rust/Cargo.toml create mode 100644 bench/programs_rust/fpga_lib/Cargo.toml create mode 100644 bench/programs_rust/fpga_lib/src/lib.rs create mode 100644 bench/programs_rust/hello_rust/Cargo.toml create mode 100644 bench/programs_rust/hello_rust/src/main.rs create mode 100644 bench/programs_rust/riscv64i.json create mode 100644 bench/programs_rust/rust-toolchain.toml diff --git a/Makefile b/Makefile index d2a242d..6aa2bd0 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,11 @@ compile: $(MEM) $(MEM_DIR): @mkdir -p $@/tests/op @mkdir -p $@/programs + @mkdir -p $@/programs_rust +$(MEM_DIR)/programs_rust/%.elf: bench/programs_rust/% |$(MEM_DIR) + cd bench/programs_rust && cargo build --release --bin=$(basename $(notdir $@)) + cp -f bench/programs_rust/target/riscv64i/release/$(basename $(notdir $@)) $@ $(MEM_DIR)/crt.o: $(BENCH_DIR)/crt.S |$(MEM_DIR) $(CC) $(CFLAGS) -c $< -o $@ $(MEM_DIR)/%.elf: $(BENCH_DIR)/%.c $(MEM_DIR)/crt.o |$(MEM_DIR) @@ -106,14 +110,16 @@ mill: autotest: mill test-bench/mem/tests/$(PROG).mem ##! Lance la simulation automatique pour tous les tests ou juste celui fourni dans PROG -testall: mill compile - @# Limite le nombre de processeurs et la ram utilisée pour les tests parellèle +testall: mill compile ##! Lance la simulation automatique pour tous les tests en parallèle + @# Limite le nombre de processeurs et la ram utilisée pour les tests parallèle @( \ ulimit -v $(TEST_MAX_RAM); \ PROOT=$(PWD) taskset -c 0-$(TEST_MAX_PROCS) ./mill TPchisel.test.testOnly $(TOP_REP).ZzTopAllSpec \ ) -simulation: mill compile ##! Lance gtkwave sur le test fourni dans PROG +$(PROG): $(MEM_DIR)/$(PROG).mem + +simulation: mill $(PROG) ##! Lance gtkwave sur le test fourni dans PROG @$(call check_vars,PROG) @PROOT=$(PWD) PROG=$(PROG) CYCLES=$(CYCLES) ./mill TPchisel.test.testOnly $(TOP_REP).$(TOP_TEST) -- -DemitVcd=1 -z "gtkwave" @gtkwave -a common/config.gtkw ./build/chiselsim/ZzTopSpec/Simulation-pour-gtkwave/workdir-verilator/trace.vcd diff --git a/bench/programs_rust/.cargo/config.toml b/bench/programs_rust/.cargo/config.toml new file mode 100644 index 0000000..6f20977 --- /dev/null +++ b/bench/programs_rust/.cargo/config.toml @@ -0,0 +1,14 @@ +[build] +target = "riscv64i.json" + +[target.riscv64i] +linker = "riscv64-unknown-elf-ld" +# linker = "rust-lld" + +rustflags = [ + # "-C", "link-arg=-nostartfiles", + "-C", "link-arg=-T../link.ld", +] + +[unstable] +build-std = ["core", "compiler_builtins"] diff --git a/bench/programs_rust/.gitignore b/bench/programs_rust/.gitignore new file mode 100644 index 0000000..a7c787f --- /dev/null +++ b/bench/programs_rust/.gitignore @@ -0,0 +1,3 @@ +.helix/ +target/ +Cargo.lock diff --git a/bench/programs_rust/Cargo.toml b/bench/programs_rust/Cargo.toml new file mode 100644 index 0000000..8ced107 --- /dev/null +++ b/bench/programs_rust/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +resolver = "3" +members = ["fpga_lib", "hello_rust"] + +[profile.release] +panic = "abort" +codegen-units = 1 # better optimizations +lto = true # better optimizations +strip = true +opt-level = "z" + +[profile.dev] +panic = "abort" diff --git a/bench/programs_rust/fpga_lib/Cargo.toml b/bench/programs_rust/fpga_lib/Cargo.toml new file mode 100644 index 0000000..38ed478 --- /dev/null +++ b/bench/programs_rust/fpga_lib/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "fpga_lib" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/bench/programs_rust/fpga_lib/src/lib.rs b/bench/programs_rust/fpga_lib/src/lib.rs new file mode 100644 index 0000000..95815de --- /dev/null +++ b/bench/programs_rust/fpga_lib/src/lib.rs @@ -0,0 +1,11 @@ +#![no_std] + +#[macro_export] +macro_rules! panic_handler { + () => { + #[panic_handler] + fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} + } + }; +} diff --git a/bench/programs_rust/hello_rust/Cargo.toml b/bench/programs_rust/hello_rust/Cargo.toml new file mode 100644 index 0000000..5541fe6 --- /dev/null +++ b/bench/programs_rust/hello_rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "hello_rust" +version = "0.1.0" +edition = "2024" + +[dependencies] +fpga_lib = { path = "../fpga_lib" } diff --git a/bench/programs_rust/hello_rust/src/main.rs b/bench/programs_rust/hello_rust/src/main.rs new file mode 100644 index 0000000..8b4ed3c --- /dev/null +++ b/bench/programs_rust/hello_rust/src/main.rs @@ -0,0 +1,18 @@ +#![no_std] +#![no_main] + +use core::arch::asm; + +use fpga_lib::panic_handler; + +panic_handler! {} + +#[unsafe(no_mangle)] +pub extern "C" fn _start() -> ! { + unsafe { + asm! { + "li x31, 0xdead0" + } + } + loop {} +} diff --git a/bench/programs_rust/riscv64i.json b/bench/programs_rust/riscv64i.json new file mode 100644 index 0000000..b3831f4 --- /dev/null +++ b/bench/programs_rust/riscv64i.json @@ -0,0 +1,21 @@ +{ + "llvm-target": "riscv64", + "llvm-abiname": "lp64", + "abi": "lp64", + "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + "target-endian": "little", + "target-pointer-width": 64, + "arch": "riscv64", + "os": "none", + "vendor": "unknown", + "env": "", + "features": "+i", + "linker-flavor": "ld.lld", + "linker": "riscv64-unknown-elf-ld", + "executables": true, + "panic-strategy": "abort", + "relocation-model": "static", + "disable-redzone": true, + "emit-debug-gdb-scripts": false, + "eh-frame-header": false +} diff --git a/bench/programs_rust/rust-toolchain.toml b/bench/programs_rust/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/bench/programs_rust/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/main/scala/projet/op/OpRW.scala b/src/main/scala/projet/op/OpRW.scala index 2972c52..6ded8d4 100644 --- a/src/main/scala/projet/op/OpRW.scala +++ b/src/main/scala/projet/op/OpRW.scala @@ -5,7 +5,6 @@ import chisel3.util.switch import projet.CUInterface import projet.AluOpCode import chisel3.util.is -import projet.OpType object OpRW { // Implements functions for all instruction of the opImm, w kind From 3044a54a0976aa71fb3befb20519df30a911d729 Mon Sep 17 00:00:00 2001 From: supersurviveur Date: Wed, 12 Nov 2025 23:51:16 +0100 Subject: [PATCH 2/3] Add registers in rust --- .gitignore | 11 ++++-- Makefile | 5 +-- bench/programs_rust/Cargo.toml | 2 +- .../programs_rust/fpga-lib-macros/Cargo.toml | 12 +++++++ .../programs_rust/fpga-lib-macros/src/lib.rs | 34 +++++++++++++++++++ bench/programs_rust/fpga-lib/Cargo.toml | 7 ++++ .../{fpga_lib => fpga-lib}/src/lib.rs | 2 ++ bench/programs_rust/fpga-lib/src/register.rs | 3 ++ .../{fpga_lib => hello-rust}/Cargo.toml | 3 +- bench/programs_rust/hello-rust/src/main.rs | 26 ++++++++++++++ bench/programs_rust/hello_rust/Cargo.toml | 7 ---- bench/programs_rust/hello_rust/src/main.rs | 18 ---------- 12 files changed, 98 insertions(+), 32 deletions(-) create mode 100644 bench/programs_rust/fpga-lib-macros/Cargo.toml create mode 100644 bench/programs_rust/fpga-lib-macros/src/lib.rs create mode 100644 bench/programs_rust/fpga-lib/Cargo.toml rename bench/programs_rust/{fpga_lib => fpga-lib}/src/lib.rs (90%) create mode 100644 bench/programs_rust/fpga-lib/src/register.rs rename bench/programs_rust/{fpga_lib => hello-rust}/Cargo.toml (52%) create mode 100644 bench/programs_rust/hello-rust/src/main.rs delete mode 100644 bench/programs_rust/hello_rust/Cargo.toml delete mode 100644 bench/programs_rust/hello_rust/src/main.rs diff --git a/.gitignore b/.gitignore index 49b663d..4596550 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,12 @@ mill* bench/mem .metals .bloop -.rpt -.Xil +*.rpt +*.jou +*.log +*.mmi +*.Xil clockInfo.txt -.csv +*.csv +*.bit +*.dcp diff --git a/Makefile b/Makefile index 6aa2bd0..5984107 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,8 @@ TEST_MAX_PROCS := $$(($$(nproc) - 2)) ## Garde un processeur libre .PRECIOUS: $(MEM_DIR)/%.elf -.PHONY: synthese fpga clean compile autotest simulation +.PHONY: synthese fpga clean compile autotest simulation force +force: compile: $(MEM) $(MEM_DIR): @@ -69,7 +70,7 @@ $(MEM_DIR): @mkdir -p $@/programs @mkdir -p $@/programs_rust -$(MEM_DIR)/programs_rust/%.elf: bench/programs_rust/% |$(MEM_DIR) +$(MEM_DIR)/programs_rust/%.elf: bench/programs_rust/% force |$(MEM_DIR) cd bench/programs_rust && cargo build --release --bin=$(basename $(notdir $@)) cp -f bench/programs_rust/target/riscv64i/release/$(basename $(notdir $@)) $@ $(MEM_DIR)/crt.o: $(BENCH_DIR)/crt.S |$(MEM_DIR) diff --git a/bench/programs_rust/Cargo.toml b/bench/programs_rust/Cargo.toml index 8ced107..a22a47c 100644 --- a/bench/programs_rust/Cargo.toml +++ b/bench/programs_rust/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "3" -members = ["fpga_lib", "hello_rust"] +members = ["fpga-lib", "fpga-lib-macros", "hello-rust"] [profile.release] panic = "abort" diff --git a/bench/programs_rust/fpga-lib-macros/Cargo.toml b/bench/programs_rust/fpga-lib-macros/Cargo.toml new file mode 100644 index 0000000..e793a03 --- /dev/null +++ b/bench/programs_rust/fpga-lib-macros/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "fpga-lib-macros" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["full"] } diff --git a/bench/programs_rust/fpga-lib-macros/src/lib.rs b/bench/programs_rust/fpga-lib-macros/src/lib.rs new file mode 100644 index 0000000..470238d --- /dev/null +++ b/bench/programs_rust/fpga-lib-macros/src/lib.rs @@ -0,0 +1,34 @@ +extern crate proc_macro; +use proc_macro::TokenStream; +use quote::{format_ident, quote}; + +#[proc_macro] +pub fn define_regs(_input: TokenStream) -> TokenStream { + let mut tokens = proc_macro2::TokenStream::new(); + + for n in 0..32usize { + let load = format!("li x{}, {{}}", n); + let store = format!("mv {{}}, x{}", n); + let ident = format_ident!("X{}", n); + let t = quote! { + impl Reg<#n> { + pub fn write_const() { + unsafe { + core::arch::asm!(#load, const X) + } + } + pub fn read() -> u64 { + let out: u64; + unsafe { + core::arch::asm!(#store, out(reg) out) + } + out + } + } + pub type #ident = Reg<#n>; + }; + tokens.extend(t); + } + + tokens.into() +} diff --git a/bench/programs_rust/fpga-lib/Cargo.toml b/bench/programs_rust/fpga-lib/Cargo.toml new file mode 100644 index 0000000..c2ec95d --- /dev/null +++ b/bench/programs_rust/fpga-lib/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fpga-lib" +version = "0.1.0" +edition = "2024" + +[dependencies] +fpga-lib-macros = { path = "../fpga-lib-macros" } diff --git a/bench/programs_rust/fpga_lib/src/lib.rs b/bench/programs_rust/fpga-lib/src/lib.rs similarity index 90% rename from bench/programs_rust/fpga_lib/src/lib.rs rename to bench/programs_rust/fpga-lib/src/lib.rs index 95815de..9622770 100644 --- a/bench/programs_rust/fpga_lib/src/lib.rs +++ b/bench/programs_rust/fpga-lib/src/lib.rs @@ -1,5 +1,7 @@ #![no_std] +pub mod register; + #[macro_export] macro_rules! panic_handler { () => { diff --git a/bench/programs_rust/fpga-lib/src/register.rs b/bench/programs_rust/fpga-lib/src/register.rs new file mode 100644 index 0000000..6077fc8 --- /dev/null +++ b/bench/programs_rust/fpga-lib/src/register.rs @@ -0,0 +1,3 @@ +pub struct Reg {} + +fpga_lib_macros::define_regs! {} diff --git a/bench/programs_rust/fpga_lib/Cargo.toml b/bench/programs_rust/hello-rust/Cargo.toml similarity index 52% rename from bench/programs_rust/fpga_lib/Cargo.toml rename to bench/programs_rust/hello-rust/Cargo.toml index 38ed478..5e7e4cf 100644 --- a/bench/programs_rust/fpga_lib/Cargo.toml +++ b/bench/programs_rust/hello-rust/Cargo.toml @@ -1,6 +1,7 @@ [package] -name = "fpga_lib" +name = "hello-rust" version = "0.1.0" edition = "2024" [dependencies] +fpga-lib = { path = "../fpga-lib" } diff --git a/bench/programs_rust/hello-rust/src/main.rs b/bench/programs_rust/hello-rust/src/main.rs new file mode 100644 index 0000000..3e21312 --- /dev/null +++ b/bench/programs_rust/hello-rust/src/main.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] + +use core::arch::asm; + +use fpga_lib::{panic_handler, register::X31}; + +panic_handler! {} + +#[unsafe(no_mangle)] +pub extern "C" fn _start() -> ! { + X31::write_const::<0xdead1ffffffff>(); + let test = X31::read() + 10; + unsafe { + asm!( + "add x31, x0, x0", + "add x31, x0, {}", in(reg) test + ); + + const VGA: *mut u8 = 0x80000000 as *mut u8; + VGA.write_volatile(255); + // VGA.add(1).write_volatile(255); + } + + loop {} +} diff --git a/bench/programs_rust/hello_rust/Cargo.toml b/bench/programs_rust/hello_rust/Cargo.toml deleted file mode 100644 index 5541fe6..0000000 --- a/bench/programs_rust/hello_rust/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "hello_rust" -version = "0.1.0" -edition = "2024" - -[dependencies] -fpga_lib = { path = "../fpga_lib" } diff --git a/bench/programs_rust/hello_rust/src/main.rs b/bench/programs_rust/hello_rust/src/main.rs deleted file mode 100644 index 8b4ed3c..0000000 --- a/bench/programs_rust/hello_rust/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![no_std] -#![no_main] - -use core::arch::asm; - -use fpga_lib::panic_handler; - -panic_handler! {} - -#[unsafe(no_mangle)] -pub extern "C" fn _start() -> ! { - unsafe { - asm! { - "li x31, 0xdead0" - } - } - loop {} -} From 7bc23ce2111d1fd26b06a208351a7a5d76abd42f Mon Sep 17 00:00:00 2001 From: supersurviveur Date: Thu, 13 Nov 2025 10:26:37 +0100 Subject: [PATCH 3/3] Starts adding fontplate for VGA --- bench/programs_rust/fontplate.png | Bin 0 -> 1664 bytes .../programs_rust/fpga-lib-macros/Cargo.toml | 2 + .../fpga-lib-macros/src/image.rs | 106 ++++++++++++++++++ .../programs_rust/fpga-lib-macros/src/lib.rs | 8 +- bench/programs_rust/fpga-lib/src/lib.rs | 1 + bench/programs_rust/fpga-lib/src/vga.rs | 48 ++++++++ bench/programs_rust/hello-rust/src/main.rs | 10 +- 7 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 bench/programs_rust/fontplate.png create mode 100644 bench/programs_rust/fpga-lib-macros/src/image.rs create mode 100644 bench/programs_rust/fpga-lib/src/vga.rs diff --git a/bench/programs_rust/fontplate.png b/bench/programs_rust/fontplate.png new file mode 100644 index 0000000000000000000000000000000000000000..7120f476040e9611b95f3297aeba5cb4565e3c83 GIT binary patch literal 1664 zcmV-`27md9P)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007 zbV*G`2k8q92@ex=(r>r`00qQJL_t(|+U;HKj@%#&+^q8ckDT;RsVwS`8Dj{0w@6iW z2?1klW1E3JUa!~vBFb?b=DYi*nsVD>+DF=9Y5SJnQ4UW5Ji)rI>-B!W|NY;D4EZK{ z7QI8i>FY)GdCGz+tEZ&>yZgS)ajYsmO{`J+^l~DVJb~+(rzu8j!xB(WG0?s>I@#|l z1&Mv%_|xb{42M>~f37LLsNbTF~3nesONB9*DFm;Ysj+l*5viySi-MO zsK)GQ(3Yk1Xtd~l!dh8liugLRk|Xs-h55QJllLC~k$#cYjdFn)rO>RABnXWI-{LSV--)lm9<0>D-__jFYDhjSFxorV`L5S089l~Dbyq2v!6csyYod`Su(;Z z<0KjIddUMTvm=GS2W$4_j4XPTov@;QtA3QnwOkjgEeneh^{u@_F*Y)*!(ejy)MLa? zw!X(7B%9*V&pdB@@#=eu&8FRDd;PpbS))^nkfQ-;Oh@aZ+x;k*DY7yi0~o+rw9NKx zAQ`C&ej1FiyWjC4jmI09xG8Qci8R}Q!WbK<#b zvn?$vxM)1^bkNN1&@ZPiit06-#iuXtt1w55yO-tjN(`0f>a4(X%|O(?wP2yjYK#Pz zJ1E#L2V+paRnm(j53JxkqGKl+I4#X$n2q?L7AUG`7ILN_6B~Gwl!-A=BcTEN(0*A^ zU?qrcg+gce$!3JY_FfxogndhGcIs)IR;E9>5f%X^<#}q!mwwk6q4hY9;~pLKS6P03 zSq1jfc7mC@Y@Fa?fihbC#RxqsK%?`vBh+FhO=T`nX4%~ZQ94S;PEcs%EJfBm`AM#F z8`C>8iKE#D_84NT-*6s1zGal2=1)rBQoB!Qr>szwFsnK%{gjb);n1kN zlD!MkvYsB?*Sg>-LyvchLUwhqa`Yo`ars=kxj|crBK}zXoCSwQp06@QunU9;fG1=u zBfJSf@gosEk?Z2UV_hTdW($-*T7B!zP=@~+jWY@hdYf@ys5gI}Yd`gJ+?6QKUE_}x zWmhyP%jfJBD%OrULeII&tJ+DCt String { + let re = Regex::new(r"[^a-zA-Z0-9_]+").unwrap(); + re.replace_all(input, "").to_string() +} + +fn to_format(img: ImageBuffer, Vec>, width: usize, height: usize) -> Vec { + let mut output = Vec::new(); + + let mut bit: u8 = 0; + let mut byte: u8 = 0; + for y in 0..height { + for x in 0..width { + let pixel = img.get_pixel(x as u32, y as u32)[0]; + if pixel >= 127 { + byte |= 1 << bit; + } + bit += 1; + if bit == 8 { + output.push(byte); + byte = 0; + bit = 0; + } + } + } + if bit != 0 { + output.push(byte); + } + output +} + +fn path_to_image(path: &str) -> (Vec, String, usize, usize) { + let img = match image::open(path) { + Ok(img) => img.to_luma8(), + Err(e) => panic!("failed to open image {}: {}", path, e), + }; + + let width = img.width() as usize; + let height = img.height() as usize; + + let bytes = to_format(img, width, height); + + let path = path + .split('/') + .next_back() + .expect("failed to get last part of path"); + let split: Vec<_> = path.split('.').collect(); + let name = remove_non_alphanumeric(&split[0..split.len() - 1].join(".")).to_uppercase(); + + (bytes, name, width, height) +} + +struct ParsedArgs { + path: String, +} + +impl Parse for ParsedArgs { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let path: syn::LitStr = input.parse()?; + let path = path.value(); + Ok(ParsedArgs { path }) + } +} + +pub fn parse_image( + input: TokenStream, +) -> Result< + ( + u8, + u8, + proc_macro2::Ident, + usize, + Vec, + ), + syn::Error, +> { + // parse the input into a comma separated list of arguments + let parsed_args = syn::parse::(input)?; + // let parsed_args = parse_macro_input!(input as ParsedArgs); + let (bytes, name, width, height) = path_to_image(&parsed_args.path); + + let width = width as u8; + let height = height as u8; + + let byte_array = bytes.as_slice(); + let byte_count = byte_array.len(); + + let name_ident = syn::Ident::new(&name, Span::call_site().into()); + + let byte_tokens = bytes.iter().map(|b| quote! { #b }).collect::>(); + Ok((width, height, name_ident, byte_count, byte_tokens)) +} + +pub fn include_font_plate_impl(input: TokenStream) -> TokenStream { + let (_, _, _, _, byte_tokens) = parse_image(input).unwrap(); + + let output = quote! { + [#(#byte_tokens),*] + }; + output.into() +} diff --git a/bench/programs_rust/fpga-lib-macros/src/lib.rs b/bench/programs_rust/fpga-lib-macros/src/lib.rs index 470238d..59ba7d7 100644 --- a/bench/programs_rust/fpga-lib-macros/src/lib.rs +++ b/bench/programs_rust/fpga-lib-macros/src/lib.rs @@ -1,4 +1,5 @@ -extern crate proc_macro; +mod image; + use proc_macro::TokenStream; use quote::{format_ident, quote}; @@ -32,3 +33,8 @@ pub fn define_regs(_input: TokenStream) -> TokenStream { tokens.into() } + +#[proc_macro] +pub fn include_font_plate(input: TokenStream) -> TokenStream { + image::include_font_plate_impl(input) +} diff --git a/bench/programs_rust/fpga-lib/src/lib.rs b/bench/programs_rust/fpga-lib/src/lib.rs index 9622770..7c3af85 100644 --- a/bench/programs_rust/fpga-lib/src/lib.rs +++ b/bench/programs_rust/fpga-lib/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] pub mod register; +pub mod vga; #[macro_export] macro_rules! panic_handler { diff --git a/bench/programs_rust/fpga-lib/src/vga.rs b/bench/programs_rust/fpga-lib/src/vga.rs new file mode 100644 index 0000000..1957f2d --- /dev/null +++ b/bench/programs_rust/fpga-lib/src/vga.rs @@ -0,0 +1,48 @@ +use fpga_lib_macros::include_font_plate; + +pub const VGA_ADDRESS: *mut Color = 0x80000000 as *mut Color; +pub const WIDTH: usize = 320; +pub const HEIGHT: usize = 240; + +#[repr(transparent)] +pub struct Color(pub(crate) u8); + +impl Color { + pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self { + Self(((r >> 6) << 6) | ((g >> 5) << 3) | (b >> 5)) + } +} + +pub const WHITE: Color = Color::from_rgb(255, 255, 255); +pub const GRAY: Color = Color::from_rgb(128, 128, 128); +pub const LIGHT_GRAY: Color = Color::from_rgb(128, 64, 64); +pub const BLACK: Color = Color::from_rgb(0, 0, 0); +pub const RED: Color = Color::from_rgb(255, 0, 0); +pub const GREEN: Color = Color::from_rgb(0, 255, 0); +pub const BLUE: Color = Color::from_rgb(0, 0, 255); + +pub struct VGA {} + +impl VGA { + /// # Safety + /// `x` must be less than `WIDTH` and `y` must be less than `HEIGHT` + pub unsafe fn write_pixel_unsafe(x: u16, y: u16, color: Color) { + unsafe { *VGA_ADDRESS.add(x as usize + y as usize * WIDTH) = color } + } + + pub unsafe fn draw_char(x: u16, y: u16, c: char) { + let c = c as u8 - b' '; + for i in 0..FONT_HEIGHT { + for j in 0..FONT_WIDTH { + + } + } + } +} + +pub const FONT_WIDTH: usize = 6; +pub const FONT_HEIGHT: usize = 13; +pub const FONTPLATE_WIDTH: usize = 32 * FONT_WIDTH; +pub const FONTPLATE_HEIGHT: usize = 3 * FONT_HEIGHT; +pub const FONTPLATE_SIZE: usize = FONTPLATE_WIDTH * FONTPLATE_HEIGHT / 8; +pub const FONTPLATE: [u8; FONTPLATE_SIZE] = include_font_plate! {"fontplate.png"}; diff --git a/bench/programs_rust/hello-rust/src/main.rs b/bench/programs_rust/hello-rust/src/main.rs index 3e21312..2e71d73 100644 --- a/bench/programs_rust/hello-rust/src/main.rs +++ b/bench/programs_rust/hello-rust/src/main.rs @@ -3,7 +3,11 @@ use core::arch::asm; -use fpga_lib::{panic_handler, register::X31}; +use fpga_lib::{ + panic_handler, + register::X31, + vga::{VGA, WHITE}, +}; panic_handler! {} @@ -17,9 +21,7 @@ pub extern "C" fn _start() -> ! { "add x31, x0, {}", in(reg) test ); - const VGA: *mut u8 = 0x80000000 as *mut u8; - VGA.write_volatile(255); - // VGA.add(1).write_volatile(255); + VGA::write_pixel_unsafe(0, 0, WHITE); } loop {}