diff --git a/cpu/riscv.c b/cpu/riscv.c index 4c7c4bd..f9f5467 100644 --- a/cpu/riscv.c +++ b/cpu/riscv.c @@ -1,12 +1,15 @@ #include "riscv.h" #include "debug.h" -#include "print.h" #include "stdio.h" #include "stdlib.h" #include "errno.h" #include "string.h" +// cpu外设 +#include "print.h" +#include "timer.h" + #include "../main.h" #define device_write(riscv,addr,value) \ @@ -194,30 +197,35 @@ void ins_auipc(riscv_t* riscv, int imm, int rd) { void ins_beq(riscv_t* riscv, int rs2, int rs1, int imm) { if (riscv->reg[rs1] == riscv->reg[rs2]) { riscv->pc += imm; + riscv->pc_modify = 1; } } void ins_bge(riscv_t* riscv, int rs2, int rs1, int imm) { if ((int)riscv->reg[rs1] >= (int)riscv->reg[rs2]) { riscv->pc += imm; + riscv->pc_modify = 1; } } void ins_bgeu(riscv_t* riscv, int rs2, int rs1, int imm) { if (riscv->reg[rs1] >= riscv->reg[rs2]) { riscv->pc += imm; + riscv->pc_modify = 1; } } void ins_blt(riscv_t* riscv, int rs2, int rs1, int imm) { if ((int)riscv->reg[rs1] < (int)riscv->reg[rs2]) { riscv->pc += imm; + riscv->pc_modify = 1; } } void ins_bltu(riscv_t* riscv, int rs2, int rs1, int imm) { if (riscv->reg[rs1] < riscv->reg[rs2]) { riscv->pc += imm; + riscv->pc_modify = 1; } } @@ -225,6 +233,7 @@ void ins_bne(riscv_t* riscv, int rs2, int rs1, int imm) { // printf("bne %d %d imm=%08x\n", rs2, rs1, imm); if (riscv->reg[rs1] != riscv->reg[rs2]) { riscv->pc += imm; + riscv->pc_modify = 1; } } @@ -276,6 +285,7 @@ void ins_ebreak(riscv_t* riscv) { void ins_jal(riscv_t* riscv, int imm, int rd) { riscv->reg[rd] = riscv->pc + 4; riscv->pc += imm; + riscv->pc_modify = 1; } void ins_jalr(riscv_t* riscv, int rs1, int imm, int rd) { @@ -283,6 +293,7 @@ void ins_jalr(riscv_t* riscv, int rs1, int imm, int rd) { t = riscv->pc + 4; riscv->pc = (riscv->reg[rs1] + imm) & (~1); riscv->reg[rd] = t; + riscv->pc_modify = 1; } void ins_lb(riscv_t* riscv, int rs1, int imm, int rd) { @@ -335,6 +346,7 @@ void ins_lui(riscv_t* riscv, int imm, int rd) { void ins_mret(riscv_t* riscv) { riscv->pc = riscv->mepc; + riscv->pc_modify = 1; if (riscv->mstatus & MSTATUS_MPIE) { riscv->mstatus &= ~MSTATUS_MPIE; riscv->mstatus |= MSTATUS_MIE; @@ -692,12 +704,33 @@ int riscv_register_device(riscv_t* riscv, const device_t* device) { return 0; } +// 跑外设(执行外设逻辑,设置中断等) +int riscv_device_run(riscv_t* riscv) { + for (int i = 0;i < riscv->device_num;i++) { + if (riscv->device_list[i] && riscv->device_list[i]->run) { + riscv->device_list[i]->run(riscv, riscv->device_list[i]); + } + } + return 0; +} + +// 外设初始化 +int riscv_device_init(riscv_t* riscv) { + for (int i = 0;i < riscv->device_num;i++) { + if (riscv->device_list[i] && riscv->device_list[i]->init) { + riscv->device_list[i]->init(riscv->device_list[i]); + } + } + return 0; + +} int riscv_init(riscv_t* riscv, uint32_t* rom, uint32_t rom_addr_base, uint32_t rom_size) { riscv->rom = rom; riscv->rom_size = rom_size; riscv->rom_addr_base = rom_addr_base; riscv->pc = riscv->rom_addr_base; + riscv->pc_modify = 0; riscv->ra = 0xffffffff; return 0; } @@ -708,6 +741,7 @@ int riscv_enter_trap(riscv_t* riscv, int is_interrupt, int irq_num) { riscv->mepc = riscv->pc; riscv->mcause = (is_interrupt << 31) | irq_num; riscv->pc = riscv->mtvec; + riscv->pc_modify = 1; // 禁用全局中断 if (riscv->mstatus & MSTATUS_MIE) { riscv->mstatus &= ~MSTATUS_MIE; @@ -745,7 +779,6 @@ int riscv_irq_check(riscv_t* riscv) { int riscv_run(riscv_t* riscv) { int ret = 0; - uint32_t pc; while (1) { if (riscv->pc == 0xfffffffe && riscv->ra == 0xffffffff) { break; @@ -763,17 +796,20 @@ int riscv_run(riscv_t* riscv) { } uint32_t instr = riscv->rom[(riscv->pc - riscv->rom_addr_base) >> 2]; // printf("pc: %08x instr: %08x\n", riscv->pc, instr); - pc = riscv->pc; ret = riscv_decode(riscv, instr); riscv->zero = 0; // 如果指令修改了pc,则以修改后的为准,如果pc未被修改,则继续执行下一条指令 - if (riscv->pc == pc) { + if (!riscv->pc_modify) { riscv->pc += 4; + } else { + // printf("pc modify=1\n"); + riscv->pc_modify = 0; } if (riscv->exc_code > 0) { riscv_enter_trap(riscv, 0, riscv->exc_code); riscv->exc_code = 0; } + riscv_device_run(riscv); riscv_irq_check(riscv); // riscv_print(riscv); if(ret){ @@ -843,7 +879,9 @@ int thread_fun(void* t) fclose(file); riscv_register_device(&riscv, print_dev()); + riscv_register_device(&riscv, timer_dev()); riscv_init(&riscv, riscv.rom, 0x80000000, riscv.rom_size); + riscv_device_init(&riscv); riscv_run(&riscv); return 0; diff --git a/cpu/riscv.h b/cpu/riscv.h index e653226..f490b3e 100644 --- a/cpu/riscv.h +++ b/cpu/riscv.h @@ -182,14 +182,17 @@ #define DEVICE_MAX_NUM 16 -typedef struct { +struct riscv_t; +typedef struct device_t{ uint32_t addr; uint32_t size; uint32_t (*read)(uint32_t addr); - void (*write)(uint32_t addr,uint32_t data); + void (*write)(uint32_t addr, uint32_t data); + void (*run)(struct riscv_t *riscv,const struct device_t* device); + void (*init)(const struct device_t* device); }device_t; -typedef struct { +typedef struct riscv_t{ uint32_t mem[MEM_SIZE]; const device_t* device_list[DEVICE_MAX_NUM]; uint32_t device_num; @@ -197,6 +200,7 @@ typedef struct { uint32_t rom_size; uint32_t rom_addr_base; uint32_t pc; + uint32_t pc_modify;// pc 指针已经被修改 不要自动递增 int32_t exc_code; uint32_t reg[32]; uint32_t csrs[4096]; diff --git a/cpu/timer.c b/cpu/timer.c new file mode 100644 index 0000000..fa8d82b --- /dev/null +++ b/cpu/timer.c @@ -0,0 +1,107 @@ + +#include "stdio.h" +#include "sys/time.h" +#include "errno.h" +#include "pthread.h" +#include "timer.h" + + +#define BASE_ADDR 0x40001000 +#define SIZE 0x4 + + +void milliseconds_sleep(unsigned long mSec){ + struct timeval tv; + tv.tv_sec=mSec/1000; + tv.tv_usec=(mSec%1000)*1000; + int err; + do{ + err=select(0,NULL,NULL,NULL,&tv); + }while(err<0 && errno==EINTR); +} + +#define dev_wr(addr) g_map[(addr-BASE_ADDR) >> 2] +#define dev_wrb(addr) ((uint8_t *)g_map)[(addr-BASE_ADDR)] +#define dev_wrh(addr) ((uint16_t *)g_map)[(addr-BASE_ADDR) >> 1] + + + +static uint32_t g_map[1]; + + +static uint32_t read(uint32_t addr) { + if (!(addr & 0x3)) { + return dev_wr(addr); + } else if (!(addr & 0x1)) { + return dev_wrh(addr); + } else { + return dev_wrb(addr); + } +} + +static void write(uint32_t addr, uint32_t data) { + // printf("print: write data=%x\n", data); + if (!(addr & 0x3)) { + dev_wr(addr) = data; + } else if (!(addr & 0x1)) { + dev_wrh(addr) = data; + } else { + dev_wrb(addr) = data; + } +} + +typedef struct { + uint32_t ins_count; + pthread_mutex_t lock; /* 互斥锁定义 */ +} mtimer_t; + +static mtimer_t g_self; + +static void run(riscv_t *riscv, const struct device_t* device) { + int irq = 0; + // printf("timer_run...\n"); + pthread_mutex_lock(&g_self.lock); + dev_wr(BASE_ADDR) += g_self.ins_count; + if (g_self.ins_count) { + irq = 1; + } + g_self.ins_count = 0; + pthread_mutex_unlock(&g_self.lock); + if (irq) { + riscv->mip |= MIP_MTIP; + } +} + + +static void *timer_thread(void *arg) { + while (1) { + milliseconds_sleep(1000); + pthread_mutex_lock(&g_self.lock); + g_self.ins_count++; + pthread_mutex_unlock(&g_self.lock); + } + return NULL; +} + +static void init(const struct device_t* device) { + pthread_t tid; + pthread_mutex_init(&g_self.lock, NULL); + dev_wr(BASE_ADDR) = 0x0; + pthread_create(&tid, NULL, timer_thread, NULL); +} + +const static device_t g_timer = { + .addr = BASE_ADDR, + .size = SIZE, + .read = read, + .write = write, + .run = run, + .init = init, +}; + + +const device_t* timer_dev() { + return &g_timer; +} + + diff --git a/cpu/timer.h b/cpu/timer.h new file mode 100644 index 0000000..c44c0b6 --- /dev/null +++ b/cpu/timer.h @@ -0,0 +1,9 @@ +#ifndef timer_h__ +#define timer_h__ + +#include "riscv.h" + + +const device_t* timer_dev(); + +#endif diff --git a/riscv/interrupt.c b/riscv/interrupt.c index f28d854..60aa6cf 100644 --- a/riscv/interrupt.c +++ b/riscv/interrupt.c @@ -66,7 +66,7 @@ void trap_entry(uint32_t irq_num, stack_context *stack) { my_printf("x31(t6): %08x\n", stack->t6); my_printf("mstatus: %08x\n", stack->mstatus); my_printf("mepc: %08x\n", stack->mepc); - my_printf("mtval: %08x\n", read_csr(mtval)); + // my_printf("mtval: %08x\n", read_csr(mtval)); // 函数调用错误,直接跳过这个函数 if(irq_num==1){