init repo

This commit is contained in:
TOKISAKIX\21168
2023-12-11 21:50:22 +08:00
commit 910ee11168
449 changed files with 41705 additions and 0 deletions

66
lab4/csrc/CMakeLists.txt Normal file
View File

@@ -0,0 +1,66 @@
# 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 paging tetris_mmu)
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()
set(PROGRAMS litenes)
# NES Emulator
include_directories(${CMAKE_SOURCE_DIR}/LiteNES/include)
add_definitions(-DYATCPU)
add_library(fce
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/common.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/cpu-addressing.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/cpu.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/fce.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/memory.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/mmc.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/ppu.c
${CMAKE_SOURCE_DIR}/LiteNES/src/fce/psg.c
)
target_compile_options(fce PRIVATE "-O3")
add_executable(litenes
${CMAKE_SOURCE_DIR}/LiteNES/src/main.c
${CMAKE_SOURCE_DIR}/LiteNES/src/hal.c
${CMAKE_SOURCE_DIR}/LiteNES/src/rom.c
)
set_target_properties(litenes PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
target_link_libraries(litenes prelude fce ${LINKER_FLAGS})
# Copy the .text and .data section to .asmbin files
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS 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
lab4/csrc/build.bat Normal file
View File

@@ -0,0 +1,3 @@
rmdir /Q /S build
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -G"NMake Makefiles" -B build .
cmake --build build

3
lab4/csrc/build.sh Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
rm -rf build
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -B build . && cmake --build build --parallel `nproc`

22
lab4/csrc/fibonacci.c Normal file
View 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);
}

175
lab4/csrc/hello.c Normal file
View 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 (;;) ;
}

117
lab4/csrc/init.S Normal file
View File

@@ -0,0 +1,117 @@
# 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, 0x10000000 # 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 enable_paging
enable_paging:
li t0, 0x80000005 # ppn << 12 = 0x005000
csrw satp, t0
ret
.globl get_mtval
get_mtval:
csrr a0, mtval
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

12
lab4/csrc/link.lds Normal file
View File

@@ -0,0 +1,12 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x00001000;
.text : { *(.text.init) *(.text.startup) *(.text) }
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
. = 0x00100000;
.bss : { *(.bss) }
_end = .;
}

43
lab4/csrc/mm.h Normal file
View File

@@ -0,0 +1,43 @@
// 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.
typedef unsigned int uint32;
typedef uint32 pte_t;
typedef uint32* pagetable_t;
#define PGSIZE 4096 // bytes per page
#define PGSHIFT 12 // bits of offset within a page
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))
#define PTE_V (1L << 0) // valid
#define PTE_R (1L << 1)
#define PTE_W (1L << 2)
#define PTE_X (1L << 3)
#define PTE_U (1L << 4) // 1 -> user can access
// shift a physical address to the right place for a PTE.
#define PA2PTE(pa) ((((uint32)pa) >> 12) << 10)
#define PTE2PA(pte) (((pte) >> 10) << 12)
#define PTE_FLAGS(pte) ((pte) & 0x3FF)
// extract the two 10-bit page table indices from a virtual address.
#define PXMASK 0x3FF // 10 bits
#define PXSHIFT(level) (PGSHIFT+(10*(level)))
#define PX(level, va) ((((uint32) (va)) >> PXSHIFT(level)) & PXMASK)
#define MAXVA (1L << (10 + 10 + 12))

24
lab4/csrc/mmio.S Normal file
View 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

33
lab4/csrc/mmio.h Normal file
View File

@@ -0,0 +1,33 @@
// 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))
//remap the mmio to reduce memory usage of page table
#define VA_VRAM_BASE 0x00100000
#define VA_VRAM ((volatile unsigned char *) VA_VRAM_BASE)
#define VA_TIMER_BASE 0x00200000
#define VA_TIMER_LIMIT ((volatile unsigned int *) (VA_TIMER_BASE + 4))
#define VA_TIMER_ENABLED ((volatile unsigned int *) (VA_TIMER_BASE + 8))
#define VA_UART_BASE 0x00300000
#define VA_UART_BAUDRATE ((volatile unsigned int *) (VA_UART_BASE + 4))
#define VA_UART_RECV ((volatile unsigned int *) (VA_UART_BASE + 12))
#define VA_UART_SEND ((volatile unsigned int *) (VA_UART_BASE + 16))

191
lab4/csrc/paging.c Normal file
View File

@@ -0,0 +1,191 @@
// # 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 "mm.h"
#include "mmio.h"
#define SCREEN_COLS 80
#define SCREEN_ROWS 30
#define INT_TIMER_LIMIT 50000000
#define PAGEDIR_BASE 0x5000
typedef unsigned int uint32;
typedef uint32 pte_t;
typedef uint32* pagetable_t;
extern void enable_paging();
extern void enable_interrupt();
extern int get_mtval();
int wk_mul(int a, int b) {
int r = 0;
for (; b; a <<= 1, b >>= 1)
if (b & 1)
r += a;
return r;
}
void memoryset(unsigned char *dest,unsigned char num, unsigned int size){
for(unsigned int i=0;i<size;i++){
dest[i]=num;
}
}
uint32 pm[8]; //板子上有32kb内存八个页
uint32 timercount=0;
void (*putch_at)(int,int,unsigned char);
void __putch_at(int x, int y, unsigned char ch) {
VRAM[wk_mul(y,SCREEN_COLS) + x] = ch;
}
void __vputch_at(int x, int y, unsigned char ch) {
VA_VRAM[wk_mul(y,SCREEN_COLS) + x] = ch;
}
int alloc(){
int index = 0;
int max = 8;
while(index < max){
if(pm[index] == 0){
pm[index] = 1;
break;
}
index++;
}
return index == max ? -1 : index;
}
void map(pagetable_t pgtbl,uint32 va,uint32 pa,int perm){
int t;
if((pgtbl[PX(1,va)] & PTE_V )!= PTE_V){ //前缀不存在
t=alloc(); //申请一个页给前缀页表
if(t>=0){
int* taddr = (int*)(t<<12);
for(int i=0;i<PGSIZE>>2;i++){
taddr[i]=0;
}
pgtbl[PX(1,va)] = PA2PTE(t<<12) | PTE_V;
}else{
while(1);
for(int i=0;i<14;i++){
putch_at(i,22,"out of memory!"[i]);
}
while(1);
}
}
pagetable_t n = (void*)PTE2PA(pgtbl[PX(1,va)]);
n[PX(0,va)] = PA2PTE(pa) | perm | PTE_V;
}
void kvminit(){
pagetable_t pgtbl = (void*)PAGEDIR_BASE;
// memoryset(pgtbl,0,PGSIZE); //后面需要读这个内存,所以先初始化
for(int i=0;i<PGSIZE>>2;i++){
pgtbl[i]=0;
}
pm[PAGEDIR_BASE >> 12] = 1;
pm[0]=1;
pm[1]=1;
pm[2]=1;
pm[3]=1;
pm[4]=1;
//create pte mmap for text
pgtbl[1023] = PA2PTE(PAGEDIR_BASE) | PTE_R | PTE_W;
map(pgtbl,PAGEDIR_BASE,PAGEDIR_BASE,PTE_R | PTE_W);
map(pgtbl,0x0,0x0, PTE_W | PTE_R ); //kernel stack
map(pgtbl,0x1000,0x1000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,0x2000,0x2000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,0x3000,0x3000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,0x4000,0x4000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,VA_VRAM_BASE,VRAM_BASE, PTE_W | PTE_R ); //
map(pgtbl,VA_VRAM_BASE + PGSIZE,VRAM_BASE + PGSIZE, PTE_W | PTE_R);
map(pgtbl,VA_UART_BASE,UART_BASE, PTE_W | PTE_R ); //
map(pgtbl,VA_TIMER_BASE,TIMER_BASE, PTE_W | PTE_R ); //
}
void clear_screen() {
int *vram = ((int *) VRAM_BASE);
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
}
void trap_handler(void *epc, unsigned int cause) {
if (cause == 10 || cause == 15 || cause == 13) {
for(int i=0;i<39;i++){
putch_at(i,4,"A not handled page fault caused by : 0x"[i]);
}
int mtval = get_mtval();
char ch;
for (int i = 0; i < 8; ++i) {
unsigned int mask = 0xF << (i * 4);
unsigned int num = (mtval & mask) >> (i * 4);
if(num >= 10){
ch = num - 10 + 'A';
}else{
ch = num + '0';
}
putch_at(39+7-i,4,ch);
}
while(1); //目前还没有处理page-fault因为还没有建立完整的映射。
} else if(cause == 0x80000007){
for(int i=0;i<16;i++){
putch_at(i,3,"timer count : 0x"[i]);
}
char ch;
for (int i = 0; i < 8; ++i) {
unsigned int mask = 0xF << (i * 4);
unsigned int num = (timercount & mask) >> (i * 4);
if(num >= 10){
ch = num - 10 + 'A';
}else{
ch = num + '0';
}
putch_at(16+7-i,3,ch);
}
timercount += 1;
}
}
int main(){
putch_at = __putch_at;
for(int i=0;i<8;i++){
pm[i] = 0;
}
timercount = 0;
clear_screen();
for(int i=0;i<19;i++){
putch_at(i,0,"print before paging"[i]);
}
kvminit();
putch_at = __vputch_at;
enable_paging();
for(int i=0;i<18;i++){
putch_at(i,1,"print after paging"[i]);
}
enable_interrupt();
*VA_TIMER_ENABLED = 1;
*VA_TIMER_LIMIT = INT_TIMER_LIMIT;
while(1){
if(timercount == 0x20){
*(int*)0x11415 = 1130;
}
}
for(;;);
}

50
lab4/csrc/quicksort.c Normal file
View 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];
}
}

44
lab4/csrc/say_goodbye.c Normal file
View File

@@ -0,0 +1,44 @@
void uart_send_char(char c)
{
*((volatile unsigned int *) (0x40000010)) = c;
// *((volatile unsigned int *) (0x40000000)) = c;
}
void waste_some_time(int cycle) {
unsigned int a = 135;
while (cycle--) {
a++;
}
}
int main() {
// const char* s = "abcd";
const char* s = "Never gonna give you up~ Never gonna let you down~\n\
Never gonna run around and~ desert you~\n";
while (1) {
// for (int i = 0; i < ; i++) {
// uart_send_char(s[i]);
// waste_some_time(100);
// }
const char *p = s;
while (*p != 0)
{
uart_send_char(*p);
p++;
waste_some_time(100);
}
waste_some_time(200);
break; // print once, but pressing CPU reset can print again
}
return 0;
}

25
lab4/csrc/sb.S Normal file
View 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
lab4/csrc/tetris.c Normal file
View 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(&current, 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(&current, 2) == 0) {
fix_block(&current);
check_clear();
init_block(&current, 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(&current, 0);
break;
case 'd':
move(&current, 1);
break;
case 'j':
rotate(&current, 0);
break;
case 'k':
rotate(&current, 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 if (cause == 0x8000000B){
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(&current, 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
}

568
lab4/csrc/tetris_mmu.c Normal file
View File

@@ -0,0 +1,568 @@
// 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"
#include "mm.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;
int pm[8]; //板子上有32kb内存八个页
int timercount=0;
// void (*putch_at)(int,int,unsigned char);
#define PAGEDIR_BASE 0x5000
#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
VA_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(&current, 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(&current, 2) == 0) {
fix_block(&current);
check_clear();
init_block(&current, 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(&current, 0);
break;
case 'd':
move(&current, 1);
break;
case 'j':
rotate(&current, 0);
break;
case 'k':
rotate(&current, 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 if (cause == 0x8000000B){
unsigned int ch = *VA_UART_RECV;
*VA_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 <= (2 << COLS | 1); ++c) {
putch_at(c, ROWS, '-');
}
int c = 8;
putch_at(c++, ROWS + 1, 'B');
putch_at(c++, ROWS + 1, 'e');
putch_at(c++, ROWS + 1, 'g');
putch_at(c++, ROWS + 1, 'i');
putch_at(c++, ROWS + 1, 'n');
putch_at(c++, ROWS + 1, ' ');
c = 6;
putch_at(c++, ROWS + 3, 'P');
putch_at(c++, ROWS + 3, 'a');
putch_at(c++, ROWS + 3, 'g');
putch_at(c++, ROWS + 3, 'i');
putch_at(c++, ROWS + 3, 'n');
putch_at(c++, ROWS + 3, 'g');
c++;
putch_at(c++, ROWS + 3, 'h');
putch_at(c++, ROWS + 3, 'r');
putch_at(c++, ROWS + 3, 'p');
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, '2');
init_block(&current, rand_type(), 4, 0);
score = 0;
draw_board();
}
int alloc(){
int index = 0;
int max = 8;
while(index < max){
if(pm[index] == 0){
pm[index] = 1;
break;
}
index++;
}
return index == max ? -1 : index;
}
int map(pagetable_t pgtbl,uint32 va,uint32 pa,int perm){
int t;
if((pgtbl[PX(1,va)] & PTE_V )!= PTE_V){ //前缀不存在
t=alloc(); //申请一个页给前缀页表
if(t>=0){
pgtbl[PX(1,va)] = PA2PTE(t<<12) | PTE_V;
}else{
return -1;
}
}
int* n = (void*)PTE2PA(pgtbl[PX(1,va)]);
n[PX(0,va)] = PA2PTE(pa) | perm | PTE_V;
return 0;
}
void kvminit(){
//init global valuable
for(int i=0;i<8;i++){
pm[i] = 0;
}
timercount = 0;
pagetable_t pgtbl = (void*)PAGEDIR_BASE;
// memoryset(pgtbl,0,PGSIZE); //后面需要读这个内存,所以先初始化
for(int i=0;i<PGSIZE>>2;i++){
pgtbl[i]=0;
}
pm[PAGEDIR_BASE >> 12] = 1;
pm[0]=1;
pm[1]=1;
pm[2]=1;
pm[3]=1;
pm[4]=1;
//create pte mmap for text
map(pgtbl,PAGEDIR_BASE,PAGEDIR_BASE,PTE_R | PTE_W);
map(pgtbl,0x0,0x0, PTE_W | PTE_R ); //kernel stack
map(pgtbl,0x1000,0x1000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,0x2000,0x2000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,0x3000,0x3000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,0x4000,0x4000, PTE_W | PTE_R | PTE_X ); //
map(pgtbl,VA_VRAM_BASE,VRAM_BASE, PTE_W | PTE_R ); //
map(pgtbl,VA_VRAM_BASE + PGSIZE,VRAM_BASE + PGSIZE, PTE_W | PTE_R);
map(pgtbl,VA_UART_BASE,UART_BASE, PTE_W | PTE_R ); //
map(pgtbl,VA_TIMER_BASE,TIMER_BASE, PTE_W | PTE_R ); //
}
void clear_screen() {
int *vram = ((int *) VA_VRAM_BASE);
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
}
extern void enable_interrupt();
extern void enable_paging();
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
kvminit();
enable_paging();
board = (unsigned char *) 16640; //0x4100
clear_screen();
init();
*((unsigned int *) 4) = 0xDEADBEEF;
enable_interrupt();
*VA_TIMER_ENABLED = 1;
*VA_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
lab4/csrc/toolchain.cmake Normal file
View 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")