mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
add csrc
This commit is contained in:
@@ -5,7 +5,7 @@ project(yatcpu-programs C CXX ASM)
|
|||||||
# Setting variables
|
# Setting variables
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
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(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||||
set(C_PROGRAMS tetris hello fibonacci quicksort)
|
set(C_PROGRAMS tetris hello fibonacci quicksort paging tetris_mmu)
|
||||||
set(ASM_PROGRAMS mmio sb)
|
set(ASM_PROGRAMS mmio sb)
|
||||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
||||||
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
||||||
@@ -32,8 +32,8 @@ foreach(program IN LISTS ASM_PROGRAMS)
|
|||||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Copy the .text section to .asmbin files
|
# Copy the .text and .data section to .asmbin files
|
||||||
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS)
|
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS PROGRAMS)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${program}
|
TARGET ${program}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
// 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);
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
.section .text.init
|
.section .text.init
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
li sp, 4096 # Initialize stack pointer
|
li sp, 0x10000000 # Initialize stack pointer
|
||||||
call main # Jump to main function
|
call main # Jump to main function
|
||||||
loop:
|
loop:
|
||||||
j loop # Loop forever
|
j loop # Loop forever
|
||||||
@@ -26,6 +26,16 @@ enable_interrupt:
|
|||||||
li t0, 0x1888
|
li t0, 0x1888
|
||||||
csrrw t1, mstatus, t0 # enable interrupt
|
csrrw t1, mstatus, t0 # enable interrupt
|
||||||
ret
|
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
|
.globl get_epc
|
||||||
get_epc:
|
get_epc:
|
||||||
csrr a0, mepc
|
csrr a0, mepc
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ SECTIONS
|
|||||||
. = 0x00001000;
|
. = 0x00001000;
|
||||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||||
|
. = 0x00100000;
|
||||||
.bss : { *(.bss) }
|
.bss : { *(.bss) }
|
||||||
_end = .;
|
_end = .;
|
||||||
}
|
}
|
||||||
|
|||||||
43
lab1/csrc/mm.h
Normal file
43
lab1/csrc/mm.h
Normal 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))
|
||||||
@@ -21,3 +21,13 @@
|
|||||||
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
||||||
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
||||||
#define UART_SEND ((volatile unsigned int *) (UART_BASE + 16))
|
#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
lab1/csrc/paging.c
Normal file
191
lab1/csrc/paging.c
Normal 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(;;);
|
||||||
|
}
|
||||||
44
lab1/csrc/say_goodbye.c
Normal file
44
lab1/csrc/say_goodbye.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -395,7 +395,7 @@ void on_timer() {
|
|||||||
void trap_handler(void *epc, unsigned int cause) {
|
void trap_handler(void *epc, unsigned int cause) {
|
||||||
if (cause == 0x80000007) {
|
if (cause == 0x80000007) {
|
||||||
on_timer();
|
on_timer();
|
||||||
} else {
|
} else if (cause == 0x8000000B){
|
||||||
unsigned int ch = *UART_RECV;
|
unsigned int ch = *UART_RECV;
|
||||||
*UART_SEND = ch;
|
*UART_SEND = ch;
|
||||||
on_input(ch);
|
on_input(ch);
|
||||||
|
|||||||
568
lab1/csrc/tetris_mmu.c
Normal file
568
lab1/csrc/tetris_mmu.c
Normal 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(¤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 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(¤t, 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
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
BIN
lab1/src/main/resources/paging.asmbin
Normal file
BIN
lab1/src/main/resources/paging.asmbin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lab1/src/main/resources/tetris_mmu.asmbin
Normal file
BIN
lab1/src/main/resources/tetris_mmu.asmbin
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@ project(yatcpu-programs C CXX ASM)
|
|||||||
# Setting variables
|
# Setting variables
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
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(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||||
set(C_PROGRAMS tetris hello fibonacci quicksort simpletest)
|
set(C_PROGRAMS tetris hello fibonacci quicksort paging tetris_mmu)
|
||||||
set(ASM_PROGRAMS mmio sb)
|
set(ASM_PROGRAMS mmio sb)
|
||||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
||||||
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
||||||
@@ -32,8 +32,8 @@ foreach(program IN LISTS ASM_PROGRAMS)
|
|||||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Copy the .text section to .asmbin files
|
# Copy the .text and .data section to .asmbin files
|
||||||
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS)
|
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS PROGRAMS)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${program}
|
TARGET ${program}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
.section .text.init
|
.section .text.init
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
li sp, 4096 # Initialize stack pointer
|
li sp, 0x10000000 # Initialize stack pointer
|
||||||
call main # Jump to main function
|
call main # Jump to main function
|
||||||
loop:
|
loop:
|
||||||
j loop # Loop forever
|
j loop # Loop forever
|
||||||
@@ -26,6 +26,16 @@ enable_interrupt:
|
|||||||
li t0, 0x1888
|
li t0, 0x1888
|
||||||
csrrw t1, mstatus, t0 # enable interrupt
|
csrrw t1, mstatus, t0 # enable interrupt
|
||||||
ret
|
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
|
.globl get_epc
|
||||||
get_epc:
|
get_epc:
|
||||||
csrr a0, mepc
|
csrr a0, mepc
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ SECTIONS
|
|||||||
. = 0x00001000;
|
. = 0x00001000;
|
||||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||||
|
. = 0x00100000;
|
||||||
.bss : { *(.bss) }
|
.bss : { *(.bss) }
|
||||||
_end = .;
|
_end = .;
|
||||||
}
|
}
|
||||||
|
|||||||
43
lab2/csrc/mm.h
Normal file
43
lab2/csrc/mm.h
Normal 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))
|
||||||
@@ -21,3 +21,13 @@
|
|||||||
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
||||||
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
||||||
#define UART_SEND ((volatile unsigned int *) (UART_BASE + 16))
|
#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
lab2/csrc/paging.c
Normal file
191
lab2/csrc/paging.c
Normal 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(;;);
|
||||||
|
}
|
||||||
44
lab2/csrc/say_goodbye.c
Normal file
44
lab2/csrc/say_goodbye.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
|
|
||||||
extern void enable_interrupt();
|
|
||||||
|
|
||||||
void trap_handler(void *epc, unsigned int cause){
|
|
||||||
*((int*)0x4) = 0x2022;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
*((int*)0x4) = 0xDEADBEEF;
|
|
||||||
enable_interrupt();
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
2023
lab2/csrc/tetris.S
2023
lab2/csrc/tetris.S
File diff suppressed because it is too large
Load Diff
@@ -395,7 +395,7 @@ void on_timer() {
|
|||||||
void trap_handler(void *epc, unsigned int cause) {
|
void trap_handler(void *epc, unsigned int cause) {
|
||||||
if (cause == 0x80000007) {
|
if (cause == 0x80000007) {
|
||||||
on_timer();
|
on_timer();
|
||||||
} else {
|
} else if (cause == 0x8000000B){
|
||||||
unsigned int ch = *UART_RECV;
|
unsigned int ch = *UART_RECV;
|
||||||
*UART_SEND = ch;
|
*UART_SEND = ch;
|
||||||
on_input(ch);
|
on_input(ch);
|
||||||
|
|||||||
568
lab2/csrc/tetris_mmu.c
Normal file
568
lab2/csrc/tetris_mmu.c
Normal 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(¤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 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(¤t, 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
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lab2/src/main/resources/paging.asmbin
Normal file
BIN
lab2/src/main/resources/paging.asmbin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lab2/src/main/resources/tetris_mmu.asmbin
Normal file
BIN
lab2/src/main/resources/tetris_mmu.asmbin
Normal file
Binary file not shown.
@@ -5,8 +5,8 @@ project(yatcpu-programs C CXX ASM)
|
|||||||
# Setting variables
|
# Setting variables
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
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(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||||
set(C_PROGRAMS tetris hello fibonacci quicksort)
|
set(C_PROGRAMS tetris hello fibonacci quicksort paging tetris_mmu)
|
||||||
set(ASM_PROGRAMS mmio sb hazard)
|
set(ASM_PROGRAMS mmio sb)
|
||||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
||||||
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
||||||
set(OBJCOPY_ARGS -O binary -j .text -j .data)
|
set(OBJCOPY_ARGS -O binary -j .text -j .data)
|
||||||
@@ -32,8 +32,8 @@ foreach(program IN LISTS ASM_PROGRAMS)
|
|||||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Copy the .text section to .asmbin files
|
# Copy the .text and .data section to .asmbin files
|
||||||
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS)
|
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS PROGRAMS)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${program}
|
TARGET ${program}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
# Copyright 2022 Canbin Huang
|
|
||||||
#
|
|
||||||
# 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:
|
|
||||||
csrr a0, cycle
|
|
||||||
|
|
||||||
addi t0, zero, 1
|
|
||||||
sub t1, zero, t0
|
|
||||||
and t2, t0, t1
|
|
||||||
sw t2, 4(zero)
|
|
||||||
j skip1
|
|
||||||
or t2, t0, t1
|
|
||||||
xor t2, t0, t1
|
|
||||||
|
|
||||||
skip1:
|
|
||||||
addi t1, t2, 1
|
|
||||||
add t2, t1, t2
|
|
||||||
and t2, t1, t2
|
|
||||||
lw t2, 2(t2)
|
|
||||||
or t3, t1, t2
|
|
||||||
blt t2, t3, skip2
|
|
||||||
or t3, t0, t0
|
|
||||||
xor t3, t0, t1
|
|
||||||
|
|
||||||
skip2:
|
|
||||||
addi t4, zero, 3
|
|
||||||
bne t3, t4, skip1
|
|
||||||
sw t3, 8(zero)
|
|
||||||
auipc t4, 0
|
|
||||||
jalr t4, 8(t4)
|
|
||||||
jalr t4, 4(t4)
|
|
||||||
csrr a1, cycle
|
|
||||||
sub ra, a1, a0
|
|
||||||
|
|
||||||
loop:
|
|
||||||
j loop
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
.section .text.init
|
.section .text.init
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
li sp, 4096 # Initialize stack pointer
|
li sp, 0x10000000 # Initialize stack pointer
|
||||||
call main # Jump to main function
|
call main # Jump to main function
|
||||||
loop:
|
loop:
|
||||||
j loop # Loop forever
|
j loop # Loop forever
|
||||||
@@ -26,6 +26,16 @@ enable_interrupt:
|
|||||||
li t0, 0x1888
|
li t0, 0x1888
|
||||||
csrrw t1, mstatus, t0 # enable interrupt
|
csrrw t1, mstatus, t0 # enable interrupt
|
||||||
ret
|
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
|
.globl get_epc
|
||||||
get_epc:
|
get_epc:
|
||||||
csrr a0, mepc
|
csrr a0, mepc
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ SECTIONS
|
|||||||
. = 0x00001000;
|
. = 0x00001000;
|
||||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||||
|
. = 0x00100000;
|
||||||
.bss : { *(.bss) }
|
.bss : { *(.bss) }
|
||||||
_end = .;
|
_end = .;
|
||||||
}
|
}
|
||||||
|
|||||||
43
lab3/csrc/mm.h
Normal file
43
lab3/csrc/mm.h
Normal 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))
|
||||||
@@ -21,3 +21,13 @@
|
|||||||
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
||||||
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
||||||
#define UART_SEND ((volatile unsigned int *) (UART_BASE + 16))
|
#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
lab3/csrc/paging.c
Normal file
191
lab3/csrc/paging.c
Normal 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(;;);
|
||||||
|
}
|
||||||
44
lab3/csrc/say_goodbye.c
Normal file
44
lab3/csrc/say_goodbye.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -395,7 +395,7 @@ void on_timer() {
|
|||||||
void trap_handler(void *epc, unsigned int cause) {
|
void trap_handler(void *epc, unsigned int cause) {
|
||||||
if (cause == 0x80000007) {
|
if (cause == 0x80000007) {
|
||||||
on_timer();
|
on_timer();
|
||||||
} else {
|
} else if (cause == 0x8000000B){
|
||||||
unsigned int ch = *UART_RECV;
|
unsigned int ch = *UART_RECV;
|
||||||
*UART_SEND = ch;
|
*UART_SEND = ch;
|
||||||
on_input(ch);
|
on_input(ch);
|
||||||
@@ -409,7 +409,7 @@ void init() {
|
|||||||
putch_at(0, r, '|');
|
putch_at(0, r, '|');
|
||||||
putch_at(COLS << 1 | 1, r, '|');
|
putch_at(COLS << 1 | 1, r, '|');
|
||||||
}
|
}
|
||||||
for (int c = 0; c <= (2 << COLS | 1); ++c) {
|
for (int c = 0; c <= (COLS << 1 | 1); ++c) {
|
||||||
putch_at(c, ROWS, '-');
|
putch_at(c, ROWS, '-');
|
||||||
}
|
}
|
||||||
int c = 8;
|
int c = 8;
|
||||||
@@ -455,6 +455,9 @@ int main() {
|
|||||||
init();
|
init();
|
||||||
#else
|
#else
|
||||||
board = (unsigned char *) 16384;
|
board = (unsigned char *) 16384;
|
||||||
|
for (int i = 0; i < 16384; i += 4) {
|
||||||
|
*((int*) (board + i)) = 0;
|
||||||
|
}
|
||||||
clear_screen();
|
clear_screen();
|
||||||
init();
|
init();
|
||||||
*((unsigned int *) 4) = 0xDEADBEEF;
|
*((unsigned int *) 4) = 0xDEADBEEF;
|
||||||
|
|||||||
568
lab3/csrc/tetris_mmu.c
Normal file
568
lab3/csrc/tetris_mmu.c
Normal 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(¤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 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(¤t, 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
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
BIN
lab3/src/main/resources/paging.asmbin
Normal file
BIN
lab3/src/main/resources/paging.asmbin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lab3/src/main/resources/tetris_mmu.asmbin
Normal file
BIN
lab3/src/main/resources/tetris_mmu.asmbin
Normal file
Binary file not shown.
@@ -32,29 +32,6 @@ foreach(program IN LISTS ASM_PROGRAMS)
|
|||||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||||
endforeach()
|
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
|
# Copy the .text and .data section to .asmbin files
|
||||||
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS PROGRAMS)
|
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS PROGRAMS)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
lab4/src/main/resources/paging.asmbin
Normal file
BIN
lab4/src/main/resources/paging.asmbin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lab4/src/main/resources/tetris_mmu.asmbin
Normal file
BIN
lab4/src/main/resources/tetris_mmu.asmbin
Normal file
Binary file not shown.
Reference in New Issue
Block a user