mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
init repo
This commit is contained in:
43
lab1/csrc/CMakeLists.txt
Normal file
43
lab1/csrc/CMakeLists.txt
Normal file
@@ -0,0 +1,43 @@
|
||||
# Make CMake happy
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(yatcpu-programs C CXX ASM)
|
||||
|
||||
# Setting variables
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||
set(C_PROGRAMS tetris hello fibonacci quicksort)
|
||||
set(ASM_PROGRAMS mmio sb)
|
||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
||||
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
||||
set(OBJCOPY_ARGS -O binary -j .text -j .data)
|
||||
if(NOT DEST_DIR)
|
||||
set(DEST_DIR "../src/main/resources")
|
||||
endif()
|
||||
|
||||
# Let CMake know that there exists header files
|
||||
include_directories("${CMAKE_SOURCE_DIR}")
|
||||
|
||||
add_library(prelude init.S)
|
||||
set_target_properties(prelude PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||
|
||||
# Let's build our executables
|
||||
foreach(program IN LISTS C_PROGRAMS)
|
||||
add_executable(${program} ${program}.c)
|
||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||
target_link_libraries(${program} prelude ${LINKER_FLAGS})
|
||||
endforeach()
|
||||
|
||||
foreach(program IN LISTS ASM_PROGRAMS)
|
||||
add_executable(${program} ${program}.S)
|
||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||
endforeach()
|
||||
|
||||
# Copy the .text section to .asmbin files
|
||||
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS)
|
||||
add_custom_command(
|
||||
TARGET ${program}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} ARGS ${OBJCOPY_ARGS} $<TARGET_FILE:${program}> ${CMAKE_SOURCE_DIR}/${DEST_DIR}/${program}.asmbin
|
||||
)
|
||||
endforeach()
|
||||
|
||||
3
lab1/csrc/build.bat
Normal file
3
lab1/csrc/build.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
rmdir /Q /S build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -G"NMake Makefiles" -B build .
|
||||
cmake --build build
|
||||
3
lab1/csrc/build.sh
Normal file
3
lab1/csrc/build.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
rm -rf build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -B build . && cmake --build build --parallel `nproc`
|
||||
22
lab1/csrc/fibonacci.c
Normal file
22
lab1/csrc/fibonacci.c
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
int fib(int a) {
|
||||
if (a == 1 || a == 2) return 1;
|
||||
return fib(a - 1) + fib(a - 2);
|
||||
}
|
||||
|
||||
int main() {
|
||||
*(int *)(4) = fib(10);
|
||||
}
|
||||
29
lab1/csrc/hdmi_test.c
Normal file
29
lab1/csrc/hdmi_test.c
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2022 hrpccs
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
|
||||
|
||||
int main(){
|
||||
int *vram = ((int *) VRAM_BASE);
|
||||
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
|
||||
|
||||
for(int i = 0;i < 12;i++){
|
||||
VRAM[i] = "hello world!"[i];
|
||||
}
|
||||
|
||||
while(1);
|
||||
}
|
||||
175
lab1/csrc/hello.c
Normal file
175
lab1/csrc/hello.c
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
#define MUL80(x) (((x) << 6) + ((x) << 4))
|
||||
|
||||
struct screen {
|
||||
unsigned char row, col;
|
||||
} scr;
|
||||
|
||||
void copy_line(int prev, int cur) {
|
||||
int *prev_vram_start = ((int *) (MUL80(prev) + VRAM_BASE));
|
||||
int *cur_vram_start = ((int *) (MUL80(cur) + VRAM_BASE));
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
prev_vram_start[i] = cur_vram_start[i];
|
||||
}
|
||||
}
|
||||
|
||||
void write_char(int row, int col, unsigned char ch) {
|
||||
VRAM[MUL80(row) + col] = ch;
|
||||
}
|
||||
|
||||
void move_to(int row, int col) {
|
||||
scr.row = row;
|
||||
scr.col = col;
|
||||
}
|
||||
|
||||
void new_line() {
|
||||
scr.col = 0;
|
||||
if (scr.row == 29) {
|
||||
for (int i = 0; i < 29; ++i) {
|
||||
copy_line(i, i + 1);
|
||||
}
|
||||
int *vram = (int *) (MUL80(29) + VRAM_BASE);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
vram[i] = 0x20202020;
|
||||
}
|
||||
} else {
|
||||
++scr.row;
|
||||
}
|
||||
}
|
||||
|
||||
void putch(unsigned char ch) {
|
||||
if (ch == '\n') {
|
||||
new_line();
|
||||
} else if (ch == '\r') {
|
||||
scr.col = 0;
|
||||
} else {
|
||||
if (scr.col == 79) {
|
||||
new_line();
|
||||
}
|
||||
write_char(scr.row, scr.col, ch);
|
||||
++scr.col;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
scr.row = 0;
|
||||
scr.col = 0;
|
||||
int *vram = ((int *) VRAM_BASE);
|
||||
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
|
||||
}
|
||||
|
||||
void print_hex(unsigned int counter) {
|
||||
putch('0'); putch('x');
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
unsigned int num = (counter >> (i << 2)) & 0xF;
|
||||
if (num < 10) {
|
||||
putch('0' + num);
|
||||
} else {
|
||||
putch('A' + num - 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void putstr(const char *s) {
|
||||
while (*s) {
|
||||
putch(*(s++));
|
||||
}
|
||||
}
|
||||
|
||||
int hc = 1;
|
||||
int fast = 0;
|
||||
|
||||
void print_timer() {
|
||||
putstr("Hardware timer count limit = ");
|
||||
print_hex(*TIMER_LIMIT);
|
||||
putstr(", enabled = ");
|
||||
print_hex(*TIMER_ENABLED);
|
||||
putch('\n');
|
||||
}
|
||||
|
||||
void print_uart() {
|
||||
putstr("UART Baud rate = ");
|
||||
print_hex(*UART_BAUDRATE);
|
||||
putch('\n');
|
||||
}
|
||||
|
||||
void handle_timer() {
|
||||
putstr("Timer trigger times = ");
|
||||
print_hex(hc++);
|
||||
putch('\n');
|
||||
int mode = ((hc & 0x10) >> 4);
|
||||
if (hc == 0x40) {
|
||||
putstr("Disable timer!\n");
|
||||
*TIMER_ENABLED = 0;
|
||||
print_timer();
|
||||
return;
|
||||
}
|
||||
if (fast ^ mode) {
|
||||
putstr("Switch timer frequency\n");
|
||||
if (fast == 0) {
|
||||
*TIMER_LIMIT = 25000000;
|
||||
} else {
|
||||
|
||||
*TIMER_LIMIT = 100000000;
|
||||
}
|
||||
fast = mode;
|
||||
print_timer();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_uart() {
|
||||
unsigned int ch = *UART_RECV;
|
||||
*UART_SEND = ch;
|
||||
putstr("UART Recv hex = "); print_hex(ch); putstr(", ch = "); putch(ch); putch('\n');
|
||||
}
|
||||
|
||||
void trap_handler(void *epc, unsigned int cause) {
|
||||
putstr("Interrupt! EPC = ");
|
||||
print_hex((unsigned int) epc);
|
||||
putstr(", CAUSE = ");
|
||||
print_hex(cause);
|
||||
putch('\n');
|
||||
switch (cause) {
|
||||
case 0x8000000B:
|
||||
handle_uart();
|
||||
break;
|
||||
default:
|
||||
handle_timer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
extern void enable_interrupt();
|
||||
extern unsigned int get_epc();
|
||||
int main() {
|
||||
clear_screen();
|
||||
hc = 0;
|
||||
*TIMER_ENABLED = 1;
|
||||
putstr("YatCPU Demo Program ");
|
||||
putch(137);
|
||||
putstr("2021 Howard Lau\n");
|
||||
putstr("Hello, world!\n");
|
||||
putstr("Last EPC = ");
|
||||
print_hex(get_epc());
|
||||
putch('\n');
|
||||
print_timer();
|
||||
print_uart();
|
||||
*((int *) 0x4) = 0xDEADBEEF;
|
||||
unsigned int i = 0;
|
||||
enable_interrupt();
|
||||
for (;;) ;
|
||||
}
|
||||
107
lab1/csrc/init.S
Normal file
107
lab1/csrc/init.S
Normal file
@@ -0,0 +1,107 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.section .text.init
|
||||
.globl _start
|
||||
_start:
|
||||
li sp, 4096 # Initialize stack pointer
|
||||
call main # Jump to main function
|
||||
loop:
|
||||
j loop # Loop forever
|
||||
.globl enable_interrupt
|
||||
enable_interrupt:
|
||||
la t0, __trap_entry
|
||||
csrrw t1, mtvec, t0 # setup trap vector base
|
||||
li t0, 0x1888
|
||||
csrrw t1, mstatus, t0 # enable interrupt
|
||||
ret
|
||||
.globl get_epc
|
||||
get_epc:
|
||||
csrr a0, mepc
|
||||
ret
|
||||
.weak trap_handler
|
||||
tran_handler:
|
||||
ret
|
||||
__trap_entry:
|
||||
csrw mscratch, sp
|
||||
addi sp, sp, -128
|
||||
sw ra, 4(sp)
|
||||
|
||||
sw gp, 12(sp)
|
||||
sw tp, 16(sp)
|
||||
sw t0, 20(sp)
|
||||
sw t1, 24(sp)
|
||||
sw t2, 28(sp)
|
||||
sw tp, 32(sp)
|
||||
sw s1, 36(sp)
|
||||
sw a0, 40(sp)
|
||||
sw a1, 44(sp)
|
||||
sw a2, 48(sp)
|
||||
sw a3, 52(sp)
|
||||
sw a4, 56(sp)
|
||||
sw a5, 60(sp)
|
||||
sw a6, 64(sp)
|
||||
sw a7, 68(sp)
|
||||
sw s2, 72(sp)
|
||||
sw s3, 76(sp)
|
||||
sw s4, 80(sp)
|
||||
sw s5, 84(sp)
|
||||
sw s6, 88(sp)
|
||||
sw s7, 92(sp)
|
||||
sw s8, 96(sp)
|
||||
sw s9, 100(sp)
|
||||
sw s10, 104(sp)
|
||||
sw s11, 108(sp)
|
||||
sw t3, 112(sp)
|
||||
sw t4, 116(sp)
|
||||
sw t5, 120(sp)
|
||||
sw t6, 124(sp)
|
||||
|
||||
csrr a0, mepc
|
||||
csrr a1, mcause
|
||||
call trap_handler
|
||||
|
||||
lw ra, 4(sp)
|
||||
|
||||
lw gp, 12(sp)
|
||||
lw tp, 16(sp)
|
||||
lw t0, 20(sp)
|
||||
lw t1, 24(sp)
|
||||
lw t2, 28(sp)
|
||||
lw tp, 32(sp)
|
||||
lw s1, 36(sp)
|
||||
lw a0, 40(sp)
|
||||
lw a1, 44(sp)
|
||||
lw a2, 48(sp)
|
||||
lw a3, 52(sp)
|
||||
lw a4, 56(sp)
|
||||
lw a5, 60(sp)
|
||||
lw a6, 64(sp)
|
||||
lw a7, 68(sp)
|
||||
lw s2, 72(sp)
|
||||
lw s3, 76(sp)
|
||||
lw s4, 80(sp)
|
||||
lw s5, 84(sp)
|
||||
lw s6, 88(sp)
|
||||
lw s7, 92(sp)
|
||||
lw s8, 96(sp)
|
||||
lw s9, 100(sp)
|
||||
lw s10, 104(sp)
|
||||
lw s11, 108(sp)
|
||||
lw t3, 112(sp)
|
||||
lw t4, 116(sp)
|
||||
lw t5, 120(sp)
|
||||
lw t6, 124(sp)
|
||||
csrr sp, mscratch
|
||||
mret
|
||||
11
lab1/csrc/link.lds
Normal file
11
lab1/csrc/link.lds
Normal file
@@ -0,0 +1,11 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00001000;
|
||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
24
lab1/csrc/mmio.S
Normal file
24
lab1/csrc/mmio.S
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
li a0, 0x80000000
|
||||
lw t0, 4(a0)
|
||||
li a1, 0xBEEF
|
||||
sw a1, 4(a0)
|
||||
nop
|
||||
lw t1, 4(a0)
|
||||
loop:
|
||||
j loop
|
||||
23
lab1/csrc/mmio.h
Normal file
23
lab1/csrc/mmio.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#define VRAM_BASE 0x20000000
|
||||
#define VRAM ((volatile unsigned char *) VRAM_BASE)
|
||||
#define TIMER_BASE 0x80000000
|
||||
#define TIMER_LIMIT ((volatile unsigned int *) (TIMER_BASE + 4))
|
||||
#define TIMER_ENABLED ((volatile unsigned int *) (TIMER_BASE + 8))
|
||||
#define UART_BASE 0x40000000
|
||||
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
||||
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
||||
#define UART_SEND ((volatile unsigned int *) (UART_BASE + 16))
|
||||
50
lab1/csrc/quicksort.c
Normal file
50
lab1/csrc/quicksort.c
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
void quicksort(int *arr, int l, int r) {
|
||||
if (l >= r) return;
|
||||
int pivot = arr[l];
|
||||
int i = l, j = r;
|
||||
while (i < j) {
|
||||
while(arr[j] >= pivot && i < j) --j;
|
||||
arr[i] = arr[j];
|
||||
while(arr[i] < pivot && i < j) ++i;
|
||||
arr[j] = arr[i];
|
||||
}
|
||||
arr[i] = pivot;
|
||||
quicksort(arr, l, i - 1);
|
||||
quicksort(arr, i + 1, r);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int nums[10];
|
||||
|
||||
nums[0] = 6;
|
||||
nums[1] = 2;
|
||||
nums[2] = 4;
|
||||
nums[3] = 5;
|
||||
nums[4] = 3;
|
||||
nums[5] = 1;
|
||||
nums[6] = 0;
|
||||
nums[7] = 9;
|
||||
nums[8] = 7;
|
||||
nums[9] = 8;
|
||||
|
||||
|
||||
quicksort(nums, 0, 9);
|
||||
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
*(int *)(i * 4) = nums[i - 1];
|
||||
}
|
||||
}
|
||||
25
lab1/csrc/sb.S
Normal file
25
lab1/csrc/sb.S
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
li a0, 0x4
|
||||
li t0, 0xDEADBEEF
|
||||
sb t0, 0(a0)
|
||||
lw t1, 0(a0)
|
||||
li s2, 0x15
|
||||
sb s2, 1(a0)
|
||||
lw ra, 0(a0)
|
||||
loop:
|
||||
j loop
|
||||
498
lab1/csrc/tetris.c
Normal file
498
lab1/csrc/tetris.c
Normal file
@@ -0,0 +1,498 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
#define FALL_TIMER_LIMIT 50000000
|
||||
#define ROWS 22
|
||||
#define COLS 10
|
||||
#define OFFSET_X 28
|
||||
#define OFFSET_Y 3
|
||||
#define SCREEN_COLS 80
|
||||
#define SCREEN_ROWS 30
|
||||
|
||||
struct block {
|
||||
unsigned int shape[3];
|
||||
unsigned int xywh;
|
||||
};
|
||||
|
||||
struct block current;
|
||||
|
||||
unsigned int score;
|
||||
|
||||
unsigned char *board;
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned char screen[SCREEN_COLS * SCREEN_ROWS];
|
||||
#endif
|
||||
|
||||
int wk_mul(int a, int b) {
|
||||
int r = 0;
|
||||
for (; b; a <<= 1, b >>= 1)
|
||||
if (b & 1)
|
||||
r += a;
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned int make_xywh(unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
|
||||
return (x << 12) | (y << 4) | (w << 2) | h;
|
||||
}
|
||||
|
||||
void init_block(struct block *block, int type, int x, int y) {
|
||||
int w = 0; int h = 0;
|
||||
block->shape[0] = block->shape[1] = block->shape[2] = 0;
|
||||
switch(type) {
|
||||
case 0: // I
|
||||
block->shape[0] = 0xF;
|
||||
w = 3; h = 0;
|
||||
break;
|
||||
case 1: // O
|
||||
block->shape[0] = 0x3;
|
||||
block->shape[1] = 0x3;
|
||||
w = 1; h = 1;
|
||||
break;
|
||||
case 2: // J
|
||||
block->shape[0] = 0x4;
|
||||
block->shape[1] = 0x7;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 3: // T
|
||||
block->shape[0] = 0x2;
|
||||
block->shape[1] = 0x7;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 4: // L
|
||||
block->shape[0] = 0x1;
|
||||
block->shape[1] = 0x7;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 5: // Z
|
||||
block->shape[0] = 0x6;
|
||||
block->shape[1] = 0x3;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 6: // S
|
||||
block->shape[0] = 0x3;
|
||||
block->shape[1] = 0x6;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
}
|
||||
block->xywh = make_xywh(x, y, w, h);
|
||||
}
|
||||
|
||||
unsigned int get_shape(struct block *block, unsigned int r, unsigned int c) {
|
||||
return (block->shape[r] & (1 << c)) >> c;
|
||||
}
|
||||
|
||||
unsigned int check_bounds(struct block *block) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
if (x < 0 || x + w >= COLS) return 0;
|
||||
if (y < 0 || y + h >= ROWS) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void copy_block(struct block *dst, struct block *src) {
|
||||
dst->xywh = src->xywh;
|
||||
dst->shape[0] = src->shape[0];
|
||||
dst->shape[1] = src->shape[1];
|
||||
dst->shape[2] = src->shape[2];
|
||||
}
|
||||
|
||||
unsigned int check_collision(struct block *block) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
if (get_shape(block, r, c) &&
|
||||
board[wk_mul(y + r, COLS) + x + c])
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void putch_at(int x, int y, unsigned char ch) {
|
||||
#ifdef DEBUG
|
||||
screen[wk_mul(OFFSET_Y + y, SCREEN_COLS) + x + OFFSET_X] = ch;
|
||||
#else
|
||||
VRAM[wk_mul(OFFSET_Y + y, SCREEN_COLS) + x + OFFSET_X] = ch;
|
||||
#endif
|
||||
}
|
||||
|
||||
void block_move(struct block *block, int dir) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
switch(dir) {
|
||||
case 0: // Left
|
||||
x--;
|
||||
break;
|
||||
case 1: // Right
|
||||
x++;
|
||||
break;
|
||||
case 2: // Down
|
||||
y++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
block->xywh = (x << 12) | (y << 4) | (w << 2) | h;
|
||||
}
|
||||
|
||||
unsigned int move(struct block *block, int dir) {
|
||||
struct block moved;
|
||||
copy_block(&moved, block);
|
||||
block_move(&moved, dir);
|
||||
if (check_bounds(&moved) && check_collision(&moved)) {
|
||||
copy_block(block, &moved);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void block_rotate(struct block *block, unsigned int clock) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
unsigned int xyhw = make_xywh(x, y, h, w);
|
||||
unsigned int shape[3] = {0, 0, 0};
|
||||
if (clock) {
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
shape[c] = shape[c] | (get_shape(block, r, c) << (h - r));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
shape[w - c] = shape[w - c] | (get_shape(block, r, c) << r);
|
||||
}
|
||||
}
|
||||
}
|
||||
block->shape[0] = shape[0];
|
||||
block->shape[1] = shape[1];
|
||||
block->shape[2] = shape[2];
|
||||
block->xywh = xyhw;
|
||||
}
|
||||
|
||||
|
||||
void rotate(struct block *block, int clock) {
|
||||
struct block rotated;
|
||||
copy_block(&rotated, block);
|
||||
block_rotate(&rotated, clock);
|
||||
if (check_bounds(&rotated) && check_collision(&rotated)) {
|
||||
copy_block(block, &rotated);
|
||||
return;
|
||||
}
|
||||
unsigned int xywh = rotated.xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xc) >> 2;
|
||||
unsigned int y = (xywh & 0xff0) >> 4;
|
||||
unsigned int x = (xywh & 0xf000) >> 12;
|
||||
if (x + w >= COLS) {
|
||||
x = COLS - w - 1;
|
||||
}
|
||||
rotated.xywh = make_xywh(x, y, w, h);
|
||||
if (check_bounds(&rotated) && check_collision(&rotated)) {
|
||||
copy_block(block, &rotated);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_board() {
|
||||
for (int i = 0, s = wk_mul(ROWS, COLS); i < s; ++i) {
|
||||
board[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void fix_block(struct block *block) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xc) >> 2;
|
||||
unsigned int y = (xywh & 0xff0) >> 4;
|
||||
unsigned int x = (xywh & 0xf000) >> 12;
|
||||
#ifdef DEBUG
|
||||
printf("%d %d %d %d\n", x, y, w, h);
|
||||
#endif
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
if (get_shape(block, r, c)) {
|
||||
board[wk_mul(y + r, COLS) + x + c] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_score() {
|
||||
int c = 8;
|
||||
putch_at(c++, -2, 'S');
|
||||
putch_at(c++, -2, 'C');
|
||||
putch_at(c++, -2, 'O');
|
||||
putch_at(c++, -2, 'R');
|
||||
putch_at(c++, -2, 'E');
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
unsigned int mask = 0xF << (i * 4);
|
||||
unsigned int num = (score & mask) >> (i * 4);
|
||||
putch_at(12 - i, -1, num + '0');
|
||||
}
|
||||
}
|
||||
|
||||
void draw_board() {
|
||||
for (int r = 0; r < ROWS; ++r) {
|
||||
for (int c = 0; c < COLS; ++c) {
|
||||
if (board[wk_mul(r , COLS) + c] == 1) {
|
||||
putch_at((c << 1) + 1, r, '[');
|
||||
putch_at((c << 1) + 2, r, ']');
|
||||
} else {
|
||||
putch_at((c << 1) + 1, r, ' ');
|
||||
putch_at((c << 1)+ 2, r, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int xywh = current.xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xc) >> 2;
|
||||
unsigned int y = (xywh & 0xff0) >> 4;
|
||||
unsigned int x = (xywh & 0xf000) >> 12;
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
if (get_shape(¤t, r, c)) {
|
||||
putch_at(((c + x) << 1) + 1, r + y, '[');
|
||||
putch_at(((c + x) << 1) + 2, r + y, ']');
|
||||
}
|
||||
}
|
||||
}
|
||||
print_score();
|
||||
}
|
||||
|
||||
|
||||
void add_score(unsigned int delta) {
|
||||
score += delta;
|
||||
for (unsigned int i = 0, carry = 0; i < 32; i += 4) {
|
||||
unsigned int mask = 0xF << i;
|
||||
unsigned int num = (score & mask) >> i;
|
||||
num += carry;
|
||||
if (num >= 10) {
|
||||
carry = 1;
|
||||
num -= 10;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
score &= ~(mask);
|
||||
score |= (num << i);
|
||||
}
|
||||
}
|
||||
|
||||
void check_clear() {
|
||||
unsigned int y = (current.xywh & 0xff0) >> 4;
|
||||
unsigned int h = current.xywh & 0x3;
|
||||
for (int r = y + h; r >= y; --r) {
|
||||
unsigned int count = 0;
|
||||
for (int c = 0; c < COLS; ++c) {
|
||||
if (board[wk_mul(r , COLS) + c]) ++count;
|
||||
}
|
||||
if (count == COLS) {
|
||||
add_score(1);
|
||||
for (int nr = r - 1; nr > 0; --nr) {
|
||||
for (int c = 0; c < COLS; ++c) {
|
||||
board[wk_mul(nr + 1, COLS) + c] = board[wk_mul(nr, COLS) + c];
|
||||
}
|
||||
}
|
||||
++r; ++y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int rand() {
|
||||
static unsigned int seed = 990315;
|
||||
seed = (wk_mul(1103515245 , seed) + 12345) & 0x7FFFFFFF;
|
||||
return seed;
|
||||
}
|
||||
|
||||
unsigned int rand_type() {
|
||||
unsigned int type = rand() & 0x7;
|
||||
while (type == 7) {
|
||||
type = rand() & 0x7;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void fall() {
|
||||
if (move(¤t, 2) == 0) {
|
||||
fix_block(¤t);
|
||||
check_clear();
|
||||
init_block(¤t, rand_type(), 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void print_screen() {
|
||||
for (int r = 0; r < SCREEN_ROWS; ++r) {
|
||||
for (int c = 0; c < SCREEN_COLS; ++c) {
|
||||
printf("%c", screen[wk_mul(r, SCREEN_COLS) + c]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void on_input(unsigned int ch) {
|
||||
switch (ch) {
|
||||
case 's':
|
||||
fall();
|
||||
break;
|
||||
case 'a':
|
||||
move(¤t, 0);
|
||||
break;
|
||||
case 'd':
|
||||
move(¤t, 1);
|
||||
break;
|
||||
case 'j':
|
||||
rotate(¤t, 0);
|
||||
break;
|
||||
case 'k':
|
||||
rotate(¤t, 1);
|
||||
break;
|
||||
}
|
||||
draw_board();
|
||||
#ifdef DEBUG
|
||||
print_screen();
|
||||
#endif
|
||||
}
|
||||
|
||||
void on_timer() {
|
||||
fall();
|
||||
draw_board();
|
||||
}
|
||||
|
||||
void trap_handler(void *epc, unsigned int cause) {
|
||||
if (cause == 0x80000007) {
|
||||
on_timer();
|
||||
} else {
|
||||
unsigned int ch = *UART_RECV;
|
||||
*UART_SEND = ch;
|
||||
on_input(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
clear_board();
|
||||
// Draw border
|
||||
for (int r = 0; r < ROWS; ++r) {
|
||||
putch_at(0, r, '|');
|
||||
putch_at(COLS << 1 | 1, r, '|');
|
||||
}
|
||||
for (int c = 0; c <= (COLS << 1 | 1); ++c) {
|
||||
putch_at(c, ROWS, '-');
|
||||
}
|
||||
int c = 8;
|
||||
putch_at(c++, ROWS + 1, 'T');
|
||||
putch_at(c++, ROWS + 1, 'E');
|
||||
putch_at(c++, ROWS + 1, 'T');
|
||||
putch_at(c++, ROWS + 1, 'R');
|
||||
putch_at(c++, ROWS + 1, 'I');
|
||||
putch_at(c++, ROWS + 1, 'S');
|
||||
c = 6;
|
||||
putch_at(c++, ROWS + 3, 'H');
|
||||
putch_at(c++, ROWS + 3, 'o');
|
||||
putch_at(c++, ROWS + 3, 'w');
|
||||
putch_at(c++, ROWS + 3, 'a');
|
||||
putch_at(c++, ROWS + 3, 'r');
|
||||
putch_at(c++, ROWS + 3, 'd');
|
||||
c++;
|
||||
putch_at(c++, ROWS + 3, 'L');
|
||||
putch_at(c++, ROWS + 3, 'a');
|
||||
putch_at(c++, ROWS + 3, 'u');
|
||||
c = 9;
|
||||
putch_at(c++, ROWS + 4, '2');
|
||||
putch_at(c++, ROWS + 4, '0');
|
||||
putch_at(c++, ROWS + 4, '2');
|
||||
putch_at(c++, ROWS + 4, '1');
|
||||
init_block(¤t, rand_type(), 4, 0);
|
||||
score = 0;
|
||||
draw_board();
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
int *vram = ((int *) VRAM_BASE);
|
||||
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
|
||||
}
|
||||
|
||||
extern void enable_interrupt();
|
||||
|
||||
int main() {
|
||||
#ifdef DEBUG
|
||||
unsigned char b[ROWS * COLS] = {0};
|
||||
board = b;
|
||||
for (int i = 0; i < SCREEN_ROWS * SCREEN_COLS; ++i) screen[i] = '%';
|
||||
init();
|
||||
#else
|
||||
board = (unsigned char *) 16384;
|
||||
for (int i = 0; i < 16384; i += 4) {
|
||||
*((int*) (board + i)) = 0;
|
||||
}
|
||||
clear_screen();
|
||||
init();
|
||||
*((unsigned int *) 4) = 0xDEADBEEF;
|
||||
enable_interrupt();
|
||||
*TIMER_ENABLED = 1;
|
||||
*TIMER_LIMIT = FALL_TIMER_LIMIT;
|
||||
for (;;);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
on_input('a');
|
||||
on_input('a');
|
||||
on_input('s');
|
||||
on_input('s');
|
||||
on_input('s');
|
||||
for (int i = 21; i >= 0; --i) {
|
||||
on_timer();
|
||||
}
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
for (int i = 21; i >= 0; --i) {
|
||||
on_timer();
|
||||
}
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
for (int i = 21; i >= 0; --i) {
|
||||
on_timer();
|
||||
add_score(10);
|
||||
}
|
||||
print_score();
|
||||
print_screen();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
20
lab1/csrc/toolchain.cmake
Normal file
20
lab1/csrc/toolchain.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR riscv32)
|
||||
|
||||
set(triple riscv32-unknown-elf)
|
||||
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_C_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
set(CMAKE_CXX_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_ASM_COMPILER clang)
|
||||
set(CMAKE_ASM_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_AR llvm-ar CACHE FILEPATH "Archiver")
|
||||
set(CMAKE_OBJCOPY llvm-objcopy)
|
||||
|
||||
set(CMAKE_C_FLAGS_INIT "-mno-relax")
|
||||
set(CMAKE_CXX_FLAGS_INIT "-mno-relax")
|
||||
set(CMAKE_ASM_FLAGS_INIT "-mno-relax")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
|
||||
Reference in New Issue
Block a user