Compare commits
10 Commits
0d47aa0083
...
730dcec440
| Author | SHA1 | Date | |
|---|---|---|---|
| 730dcec440 | |||
| d5699f2da3 | |||
| fc2a63d7f1 | |||
| 80a78441ef | |||
| 54ec7106ed | |||
| d757633816 | |||
| a32fcea47e | |||
| 1c0ee18ba6 | |||
| 6190053330 | |||
| da6e1ea7b0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,4 +14,5 @@ bench/mem
|
|||||||
clockInfo.txt
|
clockInfo.txt
|
||||||
*.csv
|
*.csv
|
||||||
*.bit
|
*.bit
|
||||||
|
!bitstreams/*.bit
|
||||||
*.dcp
|
*.dcp
|
||||||
|
|||||||
@@ -34,6 +34,4 @@ SECTIONS
|
|||||||
PROVIDE(_stack_size = 1024); /* 1 KiB */
|
PROVIDE(_stack_size = 1024); /* 1 KiB */
|
||||||
PROVIDE(_stack_start = _memory_end);
|
PROVIDE(_stack_start = _memory_end);
|
||||||
PROVIDE(_stack_end = _stack_start - _stack_size);
|
PROVIDE(_stack_end = _stack_start - _stack_size);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ rustflags = [
|
|||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std = ["core", "compiler_builtins"]
|
build-std = ["core", "compiler_builtins"]
|
||||||
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["fpga-lib", "fpga-lib-macros", "hello-rust"]
|
members = ["fpga-lib", "fpga-lib-macros", "hello-rust", "game-2048", "rot-cube"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
pub struct Buttons {}
|
pub struct Buttons {}
|
||||||
|
|
||||||
impl Buttons
|
impl Buttons {
|
||||||
{
|
pub unsafe fn get_button(button_id: u8) -> bool {
|
||||||
pub unsafe fn get_button(button_id: u8) -> bool
|
unsafe { (core::ptr::read_volatile(LED_IP_ADDRESS) >> button_id) & 0b1 == 0b1 }
|
||||||
{
|
}
|
||||||
unsafe { *LED_IP_ADDRESS >> (button_id) & 0b1 == 0b1 }
|
pub unsafe fn is_button_pressed() -> bool {
|
||||||
|
unsafe { core::ptr::read_volatile(LED_IP_ADDRESS) != 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Leds {}
|
pub struct Leds {}
|
||||||
|
|
||||||
impl Leds
|
impl Leds {
|
||||||
{
|
pub unsafe fn set_led(led_id: u8, state: bool) {
|
||||||
pub unsafe fn set_led(led_id: u8, state: bool)
|
let value = unsafe { core::ptr::read_volatile(LED_IP_ADDRESS) };
|
||||||
{
|
if state {
|
||||||
if state
|
unsafe {
|
||||||
{
|
core::ptr::write_volatile(LED_IP_ADDRESS, value | (state as u64) << (led_id + 4))
|
||||||
unsafe { *LED_IP_ADDRESS |= (state as u32) << (led_id + 4) }
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
core::ptr::write_volatile(LED_IP_ADDRESS, value & !((state as u64) << (led_id + 4)))
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
unsafe { *LED_IP_ADDRESS &= !((state as u32) << (led_id + 4)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const LED_IP_ADDRESS: *mut u32 = 0x30000000 as *mut u32;
|
pub const LED_IP_ADDRESS: *mut u64 = 0x30000000 as *mut u64;
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ pub mod vga;
|
|||||||
macro_rules! panic_handler {
|
macro_rules! panic_handler {
|
||||||
() => {
|
() => {
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> !
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
{
|
unsafe {
|
||||||
loop
|
$crate::vga::VGA::draw_string(0, 0, "PANIC !", $crate::vga::WHITE);
|
||||||
{}
|
}
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use core::ptr::write_bytes;
|
||||||
|
|
||||||
use fpga_lib_macros::include_font_plate;
|
use fpga_lib_macros::include_font_plate;
|
||||||
|
|
||||||
pub const VGA_ADDRESS: *mut Color = 0x80000000 as *mut Color;
|
pub const VGA_ADDRESS: *mut Color = 0x80000000 as *mut Color;
|
||||||
@@ -6,12 +8,10 @@ pub const HEIGHT: usize = 240;
|
|||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Color(pub(crate) u8);
|
pub struct Color(pub u8);
|
||||||
|
|
||||||
impl Color
|
impl Color {
|
||||||
{
|
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
|
||||||
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self
|
|
||||||
{
|
|
||||||
Self(((r >> 6) << 6) | ((g >> 5) << 3) | (b >> 5))
|
Self(((r >> 6) << 6) | ((g >> 5) << 3) | (b >> 5))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,12 +26,10 @@ pub const BLUE: Color = Color::from_rgb(0, 0, 255);
|
|||||||
|
|
||||||
pub struct VGA {}
|
pub struct VGA {}
|
||||||
|
|
||||||
impl VGA
|
impl VGA {
|
||||||
{
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// `x` must be less than `WIDTH` and `y` must be less than `HEIGHT`
|
/// `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)
|
pub unsafe fn write_pixel_unsafe(x: u16, y: u16, color: Color) {
|
||||||
{
|
|
||||||
let pixel_index = x as usize + y as usize * WIDTH;
|
let pixel_index = x as usize + y as usize * WIDTH;
|
||||||
let word_index = pixel_index / 4; // Get index of the word in which the pixel is
|
let word_index = pixel_index / 4; // Get index of the word in which the pixel is
|
||||||
let byte_index = pixel_index % 4; // Get index of the byte within the word for the pixel
|
let byte_index = pixel_index % 4; // Get index of the byte within the word for the pixel
|
||||||
@@ -41,14 +39,10 @@ impl VGA
|
|||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// `x` must be less than `WIDTH` and `y` must be less than `HEIGHT`
|
/// `x` must be less than `WIDTH` and `y` must be less than `HEIGHT`
|
||||||
pub unsafe fn draw_char(x: u16, y: u16, c: char, color: Color)
|
pub unsafe fn draw_char(x: u16, y: u16, c: char, color: Color) {
|
||||||
{
|
let c = if (c as u8 > b'~') || ((c as u8) < b' ') {
|
||||||
let c = if (c as u8 > b'~') || ((c as u8) < b' ')
|
|
||||||
{
|
|
||||||
b'/' - b' '
|
b'/' - b' '
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
c as u8 - b' '
|
c as u8 - b' '
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,10 +50,8 @@ impl VGA
|
|||||||
let char_x = (c as usize % 32) * FONT_WIDTH;
|
let char_x = (c as usize % 32) * FONT_WIDTH;
|
||||||
let char_y = (c as usize / 32) * FONT_HEIGHT;
|
let char_y = (c as usize / 32) * FONT_HEIGHT;
|
||||||
|
|
||||||
for i in 0..(FONT_WIDTH as u16)
|
for i in 0..(FONT_WIDTH as u16) {
|
||||||
{
|
for j in 0..(FONT_HEIGHT as u16) {
|
||||||
for j in 0..(FONT_HEIGHT as u16)
|
|
||||||
{
|
|
||||||
let xx = x + i;
|
let xx = x + i;
|
||||||
let yy = y + j;
|
let yy = y + j;
|
||||||
|
|
||||||
@@ -73,14 +65,10 @@ impl VGA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn draw_char_bg(x: u16, y: u16, c: char, color: Color, bg_color: Color)
|
pub unsafe fn draw_char_bg(x: u16, y: u16, c: char, color: Color, bg_color: Color) {
|
||||||
{
|
let c = if (c as u8 > b'~') || ((c as u8) < b' ') {
|
||||||
let c = if (c as u8 > b'~') || ((c as u8) < b' ')
|
|
||||||
{
|
|
||||||
b'/' - b' '
|
b'/' - b' '
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
c as u8 - b' '
|
c as u8 - b' '
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,21 +76,15 @@ impl VGA
|
|||||||
let char_x = (c as usize % 32) * FONT_WIDTH;
|
let char_x = (c as usize % 32) * FONT_WIDTH;
|
||||||
let char_y = (c as usize / 32) * FONT_HEIGHT;
|
let char_y = (c as usize / 32) * FONT_HEIGHT;
|
||||||
|
|
||||||
for i in 0..(FONT_WIDTH as u16)
|
for i in 0..(FONT_WIDTH as u16) {
|
||||||
{
|
for j in 0..(FONT_HEIGHT as u16) {
|
||||||
for j in 0..(FONT_HEIGHT as u16)
|
|
||||||
{
|
|
||||||
let xx = x + i;
|
let xx = x + i;
|
||||||
let yy = y + j;
|
let yy = y + j;
|
||||||
|
|
||||||
if xx < (WIDTH as u16) && yy < (HEIGHT as u16)
|
if xx < (WIDTH as u16) && yy < (HEIGHT as u16) {
|
||||||
{
|
if unsafe { Self::font_plate_index(char_x as u16 + i, char_y as u16 + j) } {
|
||||||
if unsafe { Self::font_plate_index(char_x as u16 + i, char_y as u16 + j) }
|
|
||||||
{
|
|
||||||
unsafe { Self::write_pixel_unsafe(xx, yy, color) }
|
unsafe { Self::write_pixel_unsafe(xx, yy, color) }
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
unsafe { Self::write_pixel_unsafe(xx, yy, bg_color) }
|
unsafe { Self::write_pixel_unsafe(xx, yy, bg_color) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,18 +94,18 @@ impl VGA
|
|||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// The text must have a length that can fit within a `u16`
|
/// The text must have a length that can fit within a `u16`
|
||||||
pub unsafe fn draw_string(x: u16, y: u16, str: &str, color: Color)
|
pub unsafe fn draw_string(x: u16, y: u16, str: &str, color: Color) {
|
||||||
{
|
|
||||||
str.chars().enumerate().for_each(|(i, c)| unsafe {
|
str.chars().enumerate().for_each(|(i, c)| unsafe {
|
||||||
Self::draw_char(x + i as u16 * (FONT_WIDTH as u16), y, c as char, color)
|
Self::draw_char(x + i as u16 * (FONT_WIDTH as u16), y, c as char, color)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
pub fn clear_screen(color: Color) {
|
||||||
|
unsafe { write_bytes(VGA_ADDRESS, color.0, WIDTH * HEIGHT) };
|
||||||
|
}
|
||||||
|
|
||||||
fn digit_count(mut val: u64) -> u64
|
fn digit_count(mut val: u64) -> u64 {
|
||||||
{
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while val != 0
|
while val != 0 {
|
||||||
{
|
|
||||||
val /= 10;
|
val /= 10;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@@ -131,17 +113,14 @@ impl VGA
|
|||||||
i
|
i
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn draw_u64(x: u16, y: u16, mut val: u64, color: Color, bg_color: Color)
|
pub unsafe fn draw_u64(x: u16, y: u16, mut val: u64, color: Color, bg_color: Color) {
|
||||||
{
|
if val == 0 {
|
||||||
if val == 0
|
|
||||||
{
|
|
||||||
unsafe { Self::draw_char_bg(x, y, '0', color, bg_color) }
|
unsafe { Self::draw_char_bg(x, y, '0', color, bg_color) }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let digit_count = Self::digit_count(val) - 1;
|
let digit_count = Self::digit_count(val) - 1;
|
||||||
let mut i = digit_count as u16;
|
let mut i = digit_count as u16;
|
||||||
while val != 0
|
while val != 0 {
|
||||||
{
|
|
||||||
let digit = val % 10;
|
let digit = val % 10;
|
||||||
val /= 10;
|
val /= 10;
|
||||||
|
|
||||||
@@ -160,8 +139,7 @@ impl VGA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn font_plate_index(x: u16, y: u16) -> bool
|
unsafe fn font_plate_index(x: u16, y: u16) -> bool {
|
||||||
{
|
|
||||||
let pixel_index = (y as usize) * FONTPLATE_WIDTH + (x as usize);
|
let pixel_index = (y as usize) * FONTPLATE_WIDTH + (x as usize);
|
||||||
let byte_index = pixel_index / 8;
|
let byte_index = pixel_index / 8;
|
||||||
let bit_index = pixel_index % 8;
|
let bit_index = pixel_index % 8;
|
||||||
|
|||||||
1
bench/programs_rust/game-2048/.gitignore
vendored
Normal file
1
bench/programs_rust/game-2048/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
9
bench/programs_rust/game-2048/Cargo.toml
Normal file
9
bench/programs_rust/game-2048/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "game-2048"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
compile-rand = "1.0.0"
|
||||||
|
fpga-lib = { path = "../fpga-lib" }
|
||||||
|
rand = {version = "0.9.2", default-features = false, features = ["small_rng"]}
|
||||||
3
bench/programs_rust/game-2048/README.md
Normal file
3
bench/programs_rust/game-2048/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# 2048
|
||||||
|
|
||||||
|
A terminal version of the 2048 game.
|
||||||
324
bench/programs_rust/game-2048/src/main.rs
Normal file
324
bench/programs_rust/game-2048/src/main.rs
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
mem::MaybeUninit,
|
||||||
|
ops::{Index, IndexMut},
|
||||||
|
};
|
||||||
|
|
||||||
|
use fpga_lib::{
|
||||||
|
panic_handler,
|
||||||
|
vga::{Color, BLACK, FONT_HEIGHT, FONT_WIDTH, RED, WHITE},
|
||||||
|
};
|
||||||
|
use rand::{seq::IndexedRandom, Rng, SeedableRng};
|
||||||
|
|
||||||
|
const fn get_color(x: u64) -> Color {
|
||||||
|
match x {
|
||||||
|
2 => Color::from_rgb(238, 228, 222),
|
||||||
|
4 => Color::from_rgb(237, 224, 200),
|
||||||
|
8 => Color::from_rgb(242, 177, 120),
|
||||||
|
16 => Color::from_rgb(245, 149, 99),
|
||||||
|
32 => Color::from_rgb(246, 124, 95),
|
||||||
|
64 => Color::from_rgb(246, 94, 59),
|
||||||
|
128 => Color::from_rgb(237, 207, 114),
|
||||||
|
256 => Color::from_rgb(237, 204, 97),
|
||||||
|
512 => Color::from_rgb(237, 200, 80),
|
||||||
|
1024 => Color::from_rgb(237, 197, 63),
|
||||||
|
2048 => Color::from_rgb(237, 194, 46),
|
||||||
|
4096 => Color::from_rgb(238, 102, 106),
|
||||||
|
8192 => Color::from_rgb(238, 78, 90),
|
||||||
|
16384 => Color::from_rgb(241, 65, 65),
|
||||||
|
32768 => Color::from_rgb(114, 178, 212),
|
||||||
|
65536 => Color::from_rgb(88, 159, 226),
|
||||||
|
131072 => Color::from_rgb(23, 129, 204),
|
||||||
|
_ => Color::from_rgb(255, 255, 255),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NZip<T, const N: usize> {
|
||||||
|
iters: [T; N],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Iterator, const N: usize> Iterator for NZip<T, N> {
|
||||||
|
type Item = [T::Item; N];
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut res = MaybeUninit::<[T::Item; N]>::uninit();
|
||||||
|
for (cpt, iter) in self.iters.iter_mut().enumerate() {
|
||||||
|
unsafe { *(res.as_mut_ptr() as *mut T::Item).add(cpt) = iter.next()? };
|
||||||
|
}
|
||||||
|
Some(unsafe { res.assume_init() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: DoubleEndedIterator, const N: usize> DoubleEndedIterator for NZip<T, N> {
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut res = MaybeUninit::<[T::Item; N]>::uninit();
|
||||||
|
for (cpt, iter) in self.iters.iter_mut().enumerate() {
|
||||||
|
unsafe { *(res.as_mut_ptr() as *mut T::Item).add(cpt) = iter.next_back()? };
|
||||||
|
}
|
||||||
|
Some(unsafe { res.assume_init() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Game<const SIZE: usize>
|
||||||
|
where
|
||||||
|
[(); SIZE * SIZE]:,
|
||||||
|
{
|
||||||
|
grid: [u64; SIZE * SIZE],
|
||||||
|
rng: rand::rngs::SmallRng,
|
||||||
|
score: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const SIZE: usize> Index<(usize, usize)> for Game<SIZE>
|
||||||
|
where
|
||||||
|
[(); SIZE * SIZE]:,
|
||||||
|
{
|
||||||
|
type Output = u64;
|
||||||
|
|
||||||
|
fn index(&self, index: (usize, usize)) -> &Self::Output {
|
||||||
|
&self.grid[index.1 * SIZE + index.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<const SIZE: usize> IndexMut<(usize, usize)> for Game<SIZE>
|
||||||
|
where
|
||||||
|
[(); SIZE * SIZE]:,
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
|
||||||
|
&mut self.grid[index.1 * SIZE + index.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const SIZE: usize> Game<SIZE>
|
||||||
|
where
|
||||||
|
[(); SIZE * SIZE]:,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
grid: [0; SIZE * SIZE],
|
||||||
|
rng: rand::rngs::SmallRng::seed_from_u64(compile_rand::compile_rand!(u64)),
|
||||||
|
score: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn init() -> Self {
|
||||||
|
let mut g = Self::new();
|
||||||
|
g.add();
|
||||||
|
g.add();
|
||||||
|
g
|
||||||
|
}
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
*self = Self::new()
|
||||||
|
}
|
||||||
|
pub fn add(&mut self) {
|
||||||
|
let mut pos = [(0, 0); SIZE * SIZE];
|
||||||
|
let mut cpt = 0;
|
||||||
|
for y in 0..SIZE {
|
||||||
|
for x in 0..SIZE {
|
||||||
|
if self[(x, y)] == 0 {
|
||||||
|
pos[cpt] = (x, y);
|
||||||
|
cpt += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let pos = *pos[0..cpt].choose(&mut self.rng).unwrap();
|
||||||
|
self[pos] = (self.rng.random_range(0..=1) + 1) * 2;
|
||||||
|
}
|
||||||
|
pub fn lost(&self) -> bool {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
!(copy.left() || copy.down() || copy.right() || copy.up())
|
||||||
|
}
|
||||||
|
fn rotate(&mut self) {
|
||||||
|
let mut out = self.grid;
|
||||||
|
|
||||||
|
for i in 0..SIZE {
|
||||||
|
for j in 0..SIZE {
|
||||||
|
out[j * SIZE + (SIZE - i - 1)] = self.grid[i * SIZE + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.grid = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rotate_back(&mut self) {
|
||||||
|
let mut out = self.grid;
|
||||||
|
|
||||||
|
for i in 0..SIZE {
|
||||||
|
for j in 0..SIZE {
|
||||||
|
out[(SIZE - j - 1) * SIZE + i] = self.grid[i * SIZE + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.grid = out;
|
||||||
|
}
|
||||||
|
pub fn left(&mut self) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
for y in 0..SIZE {
|
||||||
|
let mut index = 0;
|
||||||
|
let mut fixed = false;
|
||||||
|
let mut zero_found = false;
|
||||||
|
for x in 0..SIZE {
|
||||||
|
if self[(x, y)] == 0 {
|
||||||
|
zero_found = true;
|
||||||
|
continue;
|
||||||
|
} else if zero_found {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if index != 0 && self[(index - 1, y)] == (self[(x, y)]) && !fixed {
|
||||||
|
self[(index - 1, y)] = self[(x, y)] * 2;
|
||||||
|
self[(x, y)] = 0;
|
||||||
|
self.score += self[(index - 1, y)];
|
||||||
|
fixed = true;
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
self[(index, y)] = self[(x, y)];
|
||||||
|
if index != x {
|
||||||
|
self[(x, y)] = 0;
|
||||||
|
}
|
||||||
|
fixed = false;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
pub fn down(&mut self) -> bool {
|
||||||
|
self.rotate();
|
||||||
|
let res = self.left();
|
||||||
|
self.rotate_back();
|
||||||
|
res
|
||||||
|
}
|
||||||
|
pub fn right(&mut self) -> bool {
|
||||||
|
self.rotate();
|
||||||
|
self.rotate();
|
||||||
|
let res = self.left();
|
||||||
|
self.rotate_back();
|
||||||
|
self.rotate_back();
|
||||||
|
res
|
||||||
|
}
|
||||||
|
pub fn up(&mut self) -> bool {
|
||||||
|
self.rotate_back();
|
||||||
|
let res = self.left();
|
||||||
|
self.rotate();
|
||||||
|
res
|
||||||
|
}
|
||||||
|
pub fn run(&mut self) -> ! {
|
||||||
|
let mut buttons = [false; 4];
|
||||||
|
let funcs = [Self::right, Self::left, Self::up, Self::down];
|
||||||
|
let mut lost = false;
|
||||||
|
self.draw();
|
||||||
|
loop {
|
||||||
|
for direction in 0..4 {
|
||||||
|
let button = unsafe { fpga_lib::interface::Buttons::get_button(direction as u8) };
|
||||||
|
if button && !buttons[direction] {
|
||||||
|
buttons[direction] = true;
|
||||||
|
|
||||||
|
if funcs[direction](self) {
|
||||||
|
self.add();
|
||||||
|
self.draw();
|
||||||
|
if self.lost() {
|
||||||
|
lost = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !button && buttons[direction] {
|
||||||
|
buttons[direction] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lost {
|
||||||
|
unsafe {
|
||||||
|
fpga_lib::vga::VGA::draw_string(
|
||||||
|
OFFSET,
|
||||||
|
OFFSET + (SIZE as u16) * BLOCK_SIZE + FONT_HEIGHT as u16 + 10,
|
||||||
|
"Game Over !",
|
||||||
|
RED,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const SIZE: usize> Default for Game<SIZE>
|
||||||
|
where
|
||||||
|
[(); SIZE * SIZE]:,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const SIZE: usize> Game<SIZE>
|
||||||
|
where
|
||||||
|
[(); SIZE * SIZE]:,
|
||||||
|
{
|
||||||
|
fn draw(&self) {
|
||||||
|
fpga_lib::vga::VGA::clear_screen(BLACK);
|
||||||
|
for i in 0..SIZE as u16 + 1 {
|
||||||
|
for x in 0..BLOCK_SIZE * SIZE as u16 {
|
||||||
|
unsafe {
|
||||||
|
fpga_lib::vga::VGA::write_pixel_unsafe(
|
||||||
|
OFFSET + x,
|
||||||
|
OFFSET + i * BLOCK_SIZE,
|
||||||
|
WHITE,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
fpga_lib::vga::VGA::write_pixel_unsafe(
|
||||||
|
OFFSET + i * BLOCK_SIZE,
|
||||||
|
OFFSET + x,
|
||||||
|
WHITE,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for y in 0..SIZE {
|
||||||
|
for x in 0..SIZE {
|
||||||
|
if self[(x, y)] != 0 {
|
||||||
|
unsafe {
|
||||||
|
fpga_lib::vga::VGA::draw_u64(
|
||||||
|
OFFSET + x as u16 * BLOCK_SIZE + BLOCK_SIZE / 2
|
||||||
|
- (fpga_lib::vga::FONT_WIDTH as u16
|
||||||
|
* (self[(x, y)].ilog10() as u16 + 1))
|
||||||
|
/ 2,
|
||||||
|
OFFSET + y as u16 * BLOCK_SIZE + BLOCK_SIZE / 2
|
||||||
|
- fpga_lib::vga::FONT_HEIGHT as u16 / 2,
|
||||||
|
self[(x, y)],
|
||||||
|
get_color(self[(x, y)]),
|
||||||
|
BLACK,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
fpga_lib::vga::VGA::draw_string(
|
||||||
|
OFFSET,
|
||||||
|
OFFSET + (SIZE as u16) * BLOCK_SIZE + 5,
|
||||||
|
"Score :",
|
||||||
|
WHITE,
|
||||||
|
);
|
||||||
|
fpga_lib::vga::VGA::draw_u64(
|
||||||
|
OFFSET + FONT_WIDTH as u16 * 8,
|
||||||
|
OFFSET + (SIZE as u16) * BLOCK_SIZE + 5,
|
||||||
|
self.score,
|
||||||
|
WHITE,
|
||||||
|
BLACK,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic_handler! {}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn main() -> ! {
|
||||||
|
let mut g = Game::<4>::init();
|
||||||
|
g.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
const BLOCK_SIZE: u16 = 40;
|
||||||
|
const OFFSET: u16 = 20;
|
||||||
@@ -5,3 +5,4 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fpga-lib = { path = "../fpga-lib" }
|
fpga-lib = { path = "../fpga-lib" }
|
||||||
|
libm = "0.2.11"
|
||||||
|
|||||||
@@ -1,49 +1,125 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::ops::{Add, Mul};
|
||||||
|
|
||||||
use fpga_lib::{
|
use fpga_lib::{
|
||||||
interface::{Buttons, Leds},
|
interface::Buttons,
|
||||||
panic_handler,
|
panic_handler,
|
||||||
register::X31,
|
vga::{Color, BLACK, HEIGHT, VGA, WIDTH},
|
||||||
vga::{BLACK, BLUE, FONT_WIDTH, GREEN, RED, VGA, WHITE},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Float = f32;
|
||||||
|
pub const ITERATIONS_SHOWN: usize = 300;
|
||||||
|
pub const ASPECT_RATIO: f32 = WIDTH as f32 / HEIGHT as f32;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Complex(f64, f64);
|
||||||
|
|
||||||
|
impl Complex {
|
||||||
|
pub fn sq_mag(&self) -> f64 {
|
||||||
|
self.0 * self.0 + self.1 * self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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! {}
|
panic_handler! {}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn main() -> !
|
pub extern "C" fn main() -> ! {
|
||||||
{
|
let mut iterations: usize = 300;
|
||||||
loop
|
let color_lut: [Color; ITERATIONS_SHOWN] = {
|
||||||
|
let mut tab = [BLACK; _];
|
||||||
|
(0..(ITERATIONS_SHOWN - 1)).for_each(|i| {
|
||||||
|
let val = ((i as Float / ITERATIONS_SHOWN as Float) * 255.) as u8;
|
||||||
|
tab[i] = Color(val);
|
||||||
|
});
|
||||||
|
|
||||||
|
tab
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut zoom_int = 60;
|
||||||
|
const DELTA: f64 = 0.1;
|
||||||
|
let mut current_pos = Complex(1.002_674_971_219_186_5, 0.296_764_969_447_543_66);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let zoom = 1. / zoom_int as f64;
|
||||||
|
for y in 0..HEIGHT {
|
||||||
|
if unsafe { Buttons::is_button_pressed() } {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for x in 0..WIDTH {
|
||||||
|
// -0.761574,-0.0847596
|
||||||
|
let pos = Complex(
|
||||||
|
((x as i64 - WIDTH as i64 / 2) as f64 * 5. / WIDTH as f64) * zoom
|
||||||
|
- current_pos.0,
|
||||||
|
((y as i64 - HEIGHT as i64 / 2) as f64 * 5. / WIDTH as f64) * zoom
|
||||||
|
- current_pos.1,
|
||||||
|
);
|
||||||
|
let mut acc = pos;
|
||||||
|
let mut iter = 0;
|
||||||
|
|
||||||
|
let p = (pos.0 - 1. / 4.) * (pos.0 - 1. / 4.) + pos.1 * pos.1;
|
||||||
|
if pos.0 < libm::sqrt(p) - 2. * p + 1. / 4.
|
||||||
|
|| (pos.0 + 1.) * (pos.0 + 1.) + pos.1 * pos.1 < 1. / 16.
|
||||||
{
|
{
|
||||||
|
unsafe { VGA::write_pixel_unsafe(x as u16, y as u16, BLACK) };
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..iterations {
|
||||||
|
acc = Complex(
|
||||||
|
pos.0 + acc.0 * acc.0 - acc.1 * acc.1,
|
||||||
|
pos.1 + acc.1 * acc.0 + acc.1 * acc.0,
|
||||||
|
);
|
||||||
|
if acc.sq_mag() > 4. {
|
||||||
|
iter = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
VGA::draw_string(10, 10, "Running RUST !", GREEN);
|
VGA::write_pixel_unsafe(
|
||||||
VGA::draw_string(10, 23, "LedIp state :", RED);
|
x as u16,
|
||||||
|
y as u16,
|
||||||
|
color_lut
|
||||||
|
[(iter as f32 / iterations as f32 * ITERATIONS_SHOWN as f32) as usize],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'outer: loop {
|
||||||
|
for direction in 0..7 {
|
||||||
|
let button = unsafe { fpga_lib::interface::Buttons::get_button(direction as u8) };
|
||||||
|
if button {
|
||||||
|
match direction {
|
||||||
|
0 => current_pos.0 += DELTA * zoom,
|
||||||
|
1 => current_pos.0 -= DELTA * zoom,
|
||||||
|
2 => current_pos.1 += DELTA * zoom,
|
||||||
|
3 => current_pos.1 -= DELTA * zoom,
|
||||||
|
4 => zoom_int += 1,
|
||||||
|
5 => zoom_int -= 1,
|
||||||
|
6 => iterations += 50,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let clint_time: *mut u64 = 0x0200bff8 as *mut u64;
|
while unsafe { fpga_lib::interface::Buttons::get_button(direction as u8) } {}
|
||||||
|
break 'outer;
|
||||||
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
|
|
||||||
{
|
|
||||||
VGA::draw_char(10 + i * 16, 46, 'B', RED);
|
|
||||||
VGA::draw_char(16 + i * 16, 46, (b'0' + i as u8) as char, RED);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
bench/programs_rust/rot-cube/Cargo.toml
Normal file
8
bench/programs_rust/rot-cube/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "rot-cube"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
fpga-lib = { path = "../fpga-lib" }
|
||||||
|
libm = "0.2.11"
|
||||||
291
bench/programs_rust/rot-cube/src/main.rs
Normal file
291
bench/programs_rust/rot-cube/src/main.rs
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
arch::asm,
|
||||||
|
f32::consts::PI,
|
||||||
|
ops::{Add, Mul, Sub},
|
||||||
|
slice::Chunks,
|
||||||
|
};
|
||||||
|
|
||||||
|
use fpga_lib::{
|
||||||
|
interface::{Buttons, Leds},
|
||||||
|
panic_handler,
|
||||||
|
register::X31,
|
||||||
|
vga::{self, BLACK, BLUE, Color, FONT_WIDTH, GREEN, HEIGHT, RED, VGA, WHITE, WIDTH},
|
||||||
|
};
|
||||||
|
|
||||||
|
panic_handler! {}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Vec3(f32, f32, f32);
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Mat3x3([[f32; 3]; 3]);
|
||||||
|
|
||||||
|
pub fn map_float(x: f32, xmin: f32, xmax: f32, ymin: f32, ymax: f32) -> f32
|
||||||
|
{
|
||||||
|
((x - xmin) / (xmax - xmin)) * (ymax - ymin) + ymin
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mat3x3
|
||||||
|
{
|
||||||
|
fn rot_x(amount: f32) -> Self
|
||||||
|
{
|
||||||
|
Mat3x3([
|
||||||
|
[libm::cosf(amount), -libm::sinf(amount), 0.],
|
||||||
|
[libm::sinf(amount), libm::cosf(amount), 0.],
|
||||||
|
[0., 0., 1.],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rot_y(amount: f32) -> Self
|
||||||
|
{
|
||||||
|
Mat3x3([
|
||||||
|
[1., 0., 0.],
|
||||||
|
[0., libm::cosf(amount), -libm::sinf(amount)],
|
||||||
|
[0., libm::sinf(amount), libm::cosf(amount)],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rot_z(amount: f32) -> Self
|
||||||
|
{
|
||||||
|
Mat3x3([
|
||||||
|
[libm::cosf(amount), 0., -libm::sinf(amount)],
|
||||||
|
[0., 1., 0.],
|
||||||
|
[libm::sinf(amount), 0., libm::cosf(amount)],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Mat3x3> for Mat3x3
|
||||||
|
{
|
||||||
|
type Output = Mat3x3;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Mat3x3) -> Self::Output
|
||||||
|
{
|
||||||
|
Mat3x3([
|
||||||
|
[
|
||||||
|
self.0[0][0] * rhs.0[0][0]
|
||||||
|
+ self.0[0][1] * rhs.0[1][0]
|
||||||
|
+ self.0[0][2] * rhs.0[2][0],
|
||||||
|
self.0[0][0] * rhs.0[0][1]
|
||||||
|
+ self.0[0][1] * rhs.0[1][1]
|
||||||
|
+ self.0[0][2] * rhs.0[2][1],
|
||||||
|
self.0[0][0] * rhs.0[0][2]
|
||||||
|
+ self.0[0][1] * rhs.0[1][2]
|
||||||
|
+ self.0[0][2] * rhs.0[2][2],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
self.0[1][0] * rhs.0[0][0]
|
||||||
|
+ self.0[1][1] * rhs.0[1][0]
|
||||||
|
+ self.0[1][2] * rhs.0[2][0],
|
||||||
|
self.0[1][0] * rhs.0[0][1]
|
||||||
|
+ self.0[1][1] * rhs.0[1][1]
|
||||||
|
+ self.0[1][2] * rhs.0[2][1],
|
||||||
|
self.0[1][0] * rhs.0[0][2]
|
||||||
|
+ self.0[1][1] * rhs.0[1][2]
|
||||||
|
+ self.0[1][2] * rhs.0[2][2],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
self.0[2][0] * rhs.0[0][0]
|
||||||
|
+ self.0[2][1] * rhs.0[1][0]
|
||||||
|
+ self.0[2][2] * rhs.0[2][0],
|
||||||
|
self.0[2][0] * rhs.0[0][1]
|
||||||
|
+ self.0[2][1] * rhs.0[1][1]
|
||||||
|
+ self.0[2][2] * rhs.0[2][1],
|
||||||
|
self.0[2][0] * rhs.0[0][2]
|
||||||
|
+ self.0[2][1] * rhs.0[1][2]
|
||||||
|
+ self.0[2][2] * rhs.0[2][2],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Vec3> for Mat3x3
|
||||||
|
{
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Vec3) -> Self::Output
|
||||||
|
{
|
||||||
|
Vec3(
|
||||||
|
self.0[0][0] * rhs.0 + self.0[0][1] * rhs.1 + self.0[0][2] * rhs.2,
|
||||||
|
self.0[1][0] * rhs.0 + self.0[1][1] * rhs.1 + self.0[1][2] * rhs.2,
|
||||||
|
self.0[2][0] * rhs.0 + self.0[2][1] * rhs.1 + self.0[2][2] * rhs.2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<f32> for Vec3
|
||||||
|
{
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn mul(self, rhs: f32) -> Self::Output
|
||||||
|
{
|
||||||
|
Vec3(self.0 * rhs, self.1 * rhs, self.2 * rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CUBE: [Vec3; 8] = [
|
||||||
|
Vec3(1., 1., 1.),
|
||||||
|
Vec3(1., 1., -1.),
|
||||||
|
Vec3(1., -1., -1.),
|
||||||
|
Vec3(1., -1., 1.),
|
||||||
|
Vec3(-1., 1., 1.),
|
||||||
|
Vec3(-1., 1., -1.),
|
||||||
|
Vec3(-1., -1., -1.),
|
||||||
|
Vec3(-1., -1., 1.),
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const LINES: [(usize, usize); 12] = [
|
||||||
|
// Face 1
|
||||||
|
(0, 1),
|
||||||
|
(1, 2),
|
||||||
|
(2, 3),
|
||||||
|
(3, 0),
|
||||||
|
|
||||||
|
// Face 2
|
||||||
|
(4, 5),
|
||||||
|
(5, 6),
|
||||||
|
(6, 7),
|
||||||
|
(7, 4),
|
||||||
|
|
||||||
|
// Cross faces
|
||||||
|
(0, 4),
|
||||||
|
(1, 5),
|
||||||
|
(2, 6),
|
||||||
|
(3, 7)
|
||||||
|
];
|
||||||
|
|
||||||
|
const PRISM: [Vec3; 5] = [
|
||||||
|
Vec3(-1., 1., 1.),
|
||||||
|
Vec3(-1., 1., -1.),
|
||||||
|
Vec3(-1., -1., -1.),
|
||||||
|
Vec3(-1., -1., 1.),
|
||||||
|
Vec3(1., 0., 0.),
|
||||||
|
];
|
||||||
|
|
||||||
|
const PRISM_LINES: [(usize, usize); 8] = [
|
||||||
|
(0, 1),
|
||||||
|
(1, 2),
|
||||||
|
(2, 3),
|
||||||
|
(3, 0),
|
||||||
|
(0, 4),
|
||||||
|
(1, 4),
|
||||||
|
(2, 4),
|
||||||
|
(3, 4),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn draw_line(xa: u16, ya: u16, xb: u16, yb: u16, color: Color)
|
||||||
|
{
|
||||||
|
// calculate dx & dy
|
||||||
|
let dx = xb as i16 - xa as i16;
|
||||||
|
let dy = yb as i16 - ya as i16;
|
||||||
|
|
||||||
|
// calculate steps required for generating pixels
|
||||||
|
let steps = if dx.abs() > dy.abs()
|
||||||
|
{
|
||||||
|
dx.abs()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dy.abs()
|
||||||
|
};
|
||||||
|
|
||||||
|
// calculate increment in x & y for each steps
|
||||||
|
let x_inc: f32 = dx as f32 / steps as f32;
|
||||||
|
let y_inc: f32 = dy as f32 / steps as f32;
|
||||||
|
|
||||||
|
// Put pixel for each step
|
||||||
|
let mut x = xa as f32;
|
||||||
|
let mut y = ya as f32;
|
||||||
|
for _ in 0..steps
|
||||||
|
{
|
||||||
|
//putpixel(round(X), round(Y), RED); // put pixel at (X,Y)
|
||||||
|
unsafe {
|
||||||
|
VGA::write_pixel_unsafe(x as u16, y as u16, color);
|
||||||
|
}
|
||||||
|
x += x_inc; // increment in x at each step
|
||||||
|
y += y_inc; // increment in y at each step
|
||||||
|
// generation step by step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_shape(positions: &[Vec3], lines: &[(usize, usize)], color: Color)
|
||||||
|
{
|
||||||
|
for (la, lb) in lines
|
||||||
|
{
|
||||||
|
let a = positions[*la] * 0.5;
|
||||||
|
let b = positions[*lb] * 0.5;
|
||||||
|
|
||||||
|
let xa = map_float(a.0, -1., 1., 0., 320.);
|
||||||
|
let ya = map_float(a.1, -1., 1., 0., 240.);
|
||||||
|
|
||||||
|
let xb = map_float(b.0, -1., 1., 0., 320.);
|
||||||
|
let yb = map_float(b.1, -1., 1., 0., 240.);
|
||||||
|
|
||||||
|
draw_line(xa as u16, ya as u16, xb as u16, yb as u16, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CPU_FREQ: usize = 80_000_000;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn main() -> !
|
||||||
|
{
|
||||||
|
// CLEAR
|
||||||
|
for i in 0..320
|
||||||
|
{
|
||||||
|
for j in 0..240
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
VGA::write_pixel_unsafe(i, j, BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw_cube(&CUBE, WHITE);
|
||||||
|
|
||||||
|
let mut rx = 0.;
|
||||||
|
let mut ry = 0.;
|
||||||
|
let mut rz = 0.;
|
||||||
|
let mut prev_cube = CUBE;
|
||||||
|
let mut prev_prism = PRISM;
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
rx += 0.03;
|
||||||
|
ry += 0.02;
|
||||||
|
rz += 0.05;
|
||||||
|
let mut cube = CUBE;
|
||||||
|
let mut prism = PRISM;
|
||||||
|
|
||||||
|
let mc = Mat3x3::rot_x(rx) * Mat3x3::rot_y(ry) * Mat3x3::rot_z(rz);
|
||||||
|
let mp = Mat3x3::rot_x(-PI / 2.) * Mat3x3::rot_y(rx) * Mat3x3::rot_z(0.1);
|
||||||
|
for x in cube.iter_mut()
|
||||||
|
{
|
||||||
|
*x = mc * *x;
|
||||||
|
}
|
||||||
|
|
||||||
|
for x in prism.iter_mut()
|
||||||
|
{
|
||||||
|
*x = mp * *x;
|
||||||
|
*x = *x * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_shape(&prev_prism, &PRISM_LINES, BLACK);
|
||||||
|
draw_shape(&prism, &PRISM_LINES, BLUE);
|
||||||
|
|
||||||
|
draw_shape(&prev_cube, &LINES, BLACK);
|
||||||
|
draw_shape(&cube, &LINES, WHITE);
|
||||||
|
|
||||||
|
for _ in 0..(CPU_FREQ / 60)
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
asm!("nop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_cube = cube;
|
||||||
|
prev_prism = prism;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
bitstreams/cube.bit
Normal file
BIN
bitstreams/cube.bit
Normal file
Binary file not shown.
BIN
bitstreams/game-2048.bit
Normal file
BIN
bitstreams/game-2048.bit
Normal file
Binary file not shown.
BIN
bitstreams/mandelbrot-zoom.bit
Normal file
BIN
bitstreams/mandelbrot-zoom.bit
Normal file
Binary file not shown.
BIN
bitstreams/mandelbrot.bit
Normal file
BIN
bitstreams/mandelbrot.bit
Normal file
Binary file not shown.
@@ -27,7 +27,7 @@ class LedIp extends Module {
|
|||||||
when(io.bus.be.asUInt.orR) { // Écriture dans le registre des leds internes
|
when(io.bus.be.asUInt.orR) { // Écriture dans le registre des leds internes
|
||||||
dinReg := io.bus.wdata
|
dinReg := io.bus.wdata
|
||||||
}.otherwise { // Lecture des boutons poussoirs, pas de débounce car lus par le soft
|
}.otherwise { // Lecture des boutons poussoirs, pas de débounce car lus par le soft
|
||||||
btnReg := Fill(29, 0.U) ## io.button
|
btnReg := Fill(25, 0.U) ## io.switch ## io.button
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
97
tight_setup_hold_pins.txt
Normal file
97
tight_setup_hold_pins.txt
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
+====================+====================+============================================+
|
||||||
|
| Launch Setup Clock | Launch Hold Clock | Pin |
|
||||||
|
+====================+====================+============================================+
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[11]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[3]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[55]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[50]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[48]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[61]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[60]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[57]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[56]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[53]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[52]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[49]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[48]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[45]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[44]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[38]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[41]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[40]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[37]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[36]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[33]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[32]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[29]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[28]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[27]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[25]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[24]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[21]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[20]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[19]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[17]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[16]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[13]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[12]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[11]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[9]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[8]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[5]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[4]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[1]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[56]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[55]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[51]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[47]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[46]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[22]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[18]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[116]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[16]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[13]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[119]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_dividend_reg[8]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/cycles_remaining_reg[6]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[114]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[124]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[113]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[64]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[117]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[103]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[122]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[100]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[75]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[80]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[112]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[96]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[115]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[107]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[120]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[73]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[104]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[121]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[118]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[71]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[84]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[101]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[88]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[98]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[95]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[94]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[99]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/is_stalled_reg/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[92]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[79]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[85]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[83]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[77]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[86]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[82]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[81]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[72]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[66]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/divider/reg_divisor_reg[69]/D |
|
||||||
|
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/alu/in_computation_reg/D |
|
||||||
|
+--------------------+--------------------+--------------------------------------------+
|
||||||
Reference in New Issue
Block a user