diff --git a/cpu/print.c b/cpu/print.c index 6680dd5..b7b4fce 100644 --- a/cpu/print.c +++ b/cpu/print.c @@ -43,7 +43,7 @@ static void write(uint32_t addr, uint32_t data) { } if (data == '\n') { g_buff[g_index] = 0; - printf("%s", g_buff); + printf("\033[33m%s\033[0m", g_buff); g_index = 0; } } diff --git a/cpu/riscv.c b/cpu/riscv.c index b75b46c..ed92202 100644 --- a/cpu/riscv.c +++ b/cpu/riscv.c @@ -67,19 +67,33 @@ void mem_w_write(riscv_t * riscv, uint32_t addr, uint32_t value) { + if (addr & 0x3) { + riscv->exc_code = 6; + riscv->mtval = addr; + return; + } if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) { mem_wr(addr) = value; } else { device_write(riscv, addr, value); + riscv->exc_code = 7; + riscv->mtval = addr; } } void mem_wh_write(riscv_t* riscv, uint32_t addr, uint16_t value) { + if (addr & 0x1) { + riscv->exc_code = 6; + riscv->mtval = addr; + return; + } if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) { mem_wrh(addr) = value; } else { device_write(riscv, addr, value); + riscv->exc_code = 7; + riscv->mtval = addr; } } @@ -88,17 +102,26 @@ void mem_wb_write(riscv_t* riscv, uint32_t addr, uint8_t value) { mem_wrb(addr) = value; } else { device_write(riscv, addr, value); + riscv->exc_code = 7; + riscv->mtval = addr; } } uint32_t mem_w_read(riscv_t* riscv, uint32_t addr) { uint32_t ret = 0xaaaaaaaa; + if (addr & 0x3) { + riscv->exc_code = 4; + riscv->mtval = addr; + return ret; + } if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) { ret = mem_wr(addr); } else if (addr>=riscv->rom_addr_base && addrrom_addr_base+riscv->rom_size){ ret = rom_wr(addr); } else { device_read(riscv, addr, ret); + riscv->exc_code = 5; + riscv->mtval = addr; } return ret; } @@ -106,12 +129,19 @@ uint32_t mem_w_read(riscv_t* riscv, uint32_t addr) { uint16_t mem_wh_read(riscv_t* riscv, uint32_t addr) { uint16_t ret = 0xaaaa; + if (addr & 0x1) { + riscv->exc_code = 4; + riscv->mtval = addr; + return ret; + } if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) { ret = mem_wrh(addr); } else if (addr>=riscv->rom_addr_base && addrrom_addr_base+riscv->rom_size){ ret = rom_wrh(addr); } else { device_read(riscv, addr, ret); + riscv->exc_code = 5; + riscv->mtval = addr; } return ret; } @@ -125,6 +155,8 @@ uint8_t mem_wb_read(riscv_t* riscv, uint32_t addr) { ret = rom_wrb(addr); } else { device_read(riscv, addr, ret); + riscv->exc_code = 5; + riscv->mtval = addr; } return ret; } @@ -302,8 +334,14 @@ void ins_lui(riscv_t* riscv, int imm, int rd) { } void ins_mret(riscv_t* riscv) { - riscv->pc = riscv->csrs[0x305]; - printf("mret\n"); + riscv->pc = riscv->mepc; + if (riscv->mstatus & MSTATUS_MPIE) { + riscv->mstatus &= ~MSTATUS_MPIE; + riscv->mstatus |= MSTATUS_MIE; + } else { + riscv->mstatus &= ~MSTATUS_MIE; + } + printf("mret: pc=%08x\n", riscv->pc); } void ins_or(riscv_t* riscv, int rs2, int rs1, int rd) { @@ -467,6 +505,7 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { ins_bgeu(riscv, rs2, rs1, imm); break; default: + riscv->exc_code = 2; break; } break; @@ -490,6 +529,7 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { ins_lhu(riscv, rs1, imm, rd); break; default: + riscv->exc_code = 2; break; } break; @@ -506,6 +546,7 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { ins_sw(riscv, rs2, rs1, imm); break; default: + riscv->exc_code = 2; break; } break; @@ -544,6 +585,7 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { } break; default: + riscv->exc_code = 2; break; } break; @@ -583,6 +625,7 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { ins_and(riscv, rs2, rs1, rd); break; default: + riscv->exc_code = 2; break; } break; @@ -591,7 +634,15 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { switch (funct3) { case 0x0: - ins_ebreak(riscv); + if (imm == 1) { + ins_ebreak(riscv); + } else if (imm == 0) { + ins_ecall(riscv); + } else if (ins == 0x30200073) { + ins_mret(riscv); + } else{ + riscv->exc_code = 2; + } break; case 0x1: ins_csrrw(riscv, rs1, rd, imm); @@ -613,12 +664,17 @@ int riscv_decode(riscv_t* riscv, uint32_t ins) { ins_csrrci(riscv, rs1, rd, imm); break; default: + riscv->exc_code = 2; break; } break; default: + riscv->exc_code = 2; break; } + if (riscv->exc_code == 2) { + riscv->mtval = ins; + } return 0; } @@ -645,15 +701,67 @@ int riscv_init(riscv_t* riscv, uint32_t* rom, uint32_t rom_addr_base, uint32_t r return 0; } +// 进入中断 is_interrupt=1 进入中断 is_interrupt=0 进入异常 +// irq_num 中断号 +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; + // 禁用全局中断 + if (riscv->mstatus & MSTATUS_MIE) { + riscv->mstatus &= ~MSTATUS_MIE; + riscv->mstatus |= MSTATUS_MPIE; + } else { + riscv->mstatus &= ~MSTATUS_MPIE; + } + return 0; +} + +// 检测是否产生了中断 +int riscv_irq_check(riscv_t* riscv) { + uint32_t tmp; + int irq_num = 0; + tmp = riscv->mip & (MIP_MSIP | MIP_MTIP | MIP_MEIP); + if (tmp) { + if (riscv->mstatus & MSTATUS_MIE) { + if ((riscv->mie & MIP_MSIP) && (tmp & MIP_MSIP)) { + irq_num = 3; + } else if ((riscv->mie & MIP_MTIP) && (tmp & MIP_MTIP)) { + irq_num = 7; + } else if ((riscv->mie & MIP_MEIP) && (tmp & MIP_MEIP)) { + irq_num = 11; + } + riscv->mtval = 0; + riscv_enter_trap(riscv, 1, irq_num); + if (irq_num>0) { + riscv->mip &= ~(1 << irq_num); + irq_num = 0; + } + } + } + return 0; +} + int riscv_run(riscv_t* riscv) { int ret = 0; uint32_t pc; while (1) { - if(riscv->pc >= riscv->rom_addr_base + riscv->rom_size || riscv->pc < riscv->rom_addr_base){ - printf("riscv run out of rom pc=%08x\n",riscv->pc); + if (riscv->pc == 0) { break; } - uint32_t instr = riscv->rom[(riscv->pc-riscv->rom_addr_base) >> 2]; + if (riscv->pc >= riscv->rom_addr_base + riscv->rom_size || riscv->pc < riscv->rom_addr_base) { + // 指令访问失败 + riscv->mtval = riscv->pc; + printf("riscv run out of rom pc=%08x\n",riscv->pc); + riscv_enter_trap(riscv, 0, 1); + printf("riscv run out of rom pc=%08x\n",riscv->pc); + } + if (riscv->pc & 0x3) { + // 指令地址未对齐 + riscv->mtval = riscv->pc; + riscv_enter_trap(riscv, 0, 0); + } + 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); @@ -662,10 +770,19 @@ int riscv_run(riscv_t* riscv) { if (riscv->pc == pc) { riscv->pc += 4; } + if (riscv->exc_code > 0) { + riscv_enter_trap(riscv, 0, riscv->exc_code); + riscv->exc_code = 0; + } + riscv_irq_check(riscv); // riscv_print(riscv); if(ret){ break; } + if (riscv->mscratch == 0xffffffff) { + printf("proactively terminate\n"); + break; + } } printf("riscv run end\n"); return 0; diff --git a/cpu/riscv.h b/cpu/riscv.h index df08147..e653226 100644 --- a/cpu/riscv.h +++ b/cpu/riscv.h @@ -197,6 +197,7 @@ typedef struct { uint32_t rom_size; uint32_t rom_addr_base; uint32_t pc; + int32_t exc_code; uint32_t reg[32]; uint32_t csrs[4096]; }riscv_t; @@ -210,4 +211,37 @@ typedef struct { #define rom_wrh(addr) ((uint16_t *)(riscv->rom))[(addr-riscv->rom_addr_base) >> 1] +// trap 相关定义 +#define mstatus csrs[0x300] // 机器状态寄存器 +#define misa csrs[0x301] // ISA扩展 +#define medeleg csrs[0x302] // 异常委托寄存器 +#define mideleg csrs[0x303] // 中断委托寄存器 +#define mie csrs[0x304] // 中断使能寄存器 +#define mtvec csrs[0x305] // 异常向量寄存器 +#define mcounteren csrs[0x306] // 统计计数器使能寄存器 +#define mstatush csrs[0x310] // 添加的状态寄存器高 + +#define mscratch csrs[0x340] // 存储器 软件中可用于暂时存放一个字大小的数据 +#define mepc csrs[0x341] // 异常程序计数器 指向发生异常的指令 +#define mcause csrs[0x342] // 异常原因寄存器 +#define mtval csrs[0x343] // 异常值寄存器 地址例外出错的地址 非法指令本身 +#define mip csrs[0x344] // 中断请求寄存器 它列出正在准备处理的中断 +#define mtinst csrs[0x34a] // 存储器指令寄存器 当发生异常时,它包含异常指令 +#define mtval2 csrs[0x34b] // 坏的物理地址 +#define mcycle csrs[0xc00] // 循环计数器 +#define minstret csrs[0xc02] // 执行指令计数器 + + +// 只有机器模式的cpu只有这两个位起作用 清除这两个位表示禁用全局中断 +#define MSTATUS_MIE 0x00000008 // 中断使能位 +#define MSTATUS_MPIE 0x00000080 // 进异常时会自动清除MIE MPIE是清除之前的状态 + + +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_MEIP (1 << IRQ_M_EXT) +#define IRQ_M_SOFT 3 +#define IRQ_M_TIMER 7 +#define IRQ_M_EXT 11 + #endif \ No newline at end of file diff --git a/make_riscv.py b/make_riscv.py index 09d49cd..ce0c6d9 100644 --- a/make_riscv.py +++ b/make_riscv.py @@ -30,7 +30,9 @@ CFLAG=[ SRC=[ "riscv/main.c", "riscv/test.c", - "riscv/start.S" + "riscv/interrupt.c", + "riscv/start.S", + "riscv/trap.S" ] LD_FILE="riscv.ld" diff --git a/riscv.ld b/riscv.ld index f562070..9ebd4e2 100644 --- a/riscv.ld +++ b/riscv.ld @@ -144,10 +144,14 @@ SECTIONS PROVIDE( end = . ); PROVIDE( _heap_start = . ); - .stack ORIGIN(dram) + LENGTH(dram) - __stack_size : + .stack ORIGIN(dram) + LENGTH(dram) - __stack_size*3 : { PROVIDE( _heap_end = . ); - . = __stack_size; + . += __stack_size; PROVIDE( _sp = . ); + . += __stack_size; + PROVIDE( _irq_sp = . ); + . += __stack_size; + PROVIDE( _exc_sp = . ); } >dram AT>dram } diff --git a/riscv/context.h b/riscv/context.h new file mode 100644 index 0000000..80acb3f --- /dev/null +++ b/riscv/context.h @@ -0,0 +1,49 @@ + +#ifndef context_h__ +#define context_h__ + +#include "stdint.h" + +typedef struct { + uint32_t ra;//x1 0 + uint32_t sp;//x2 1 + uint32_t gp;//x3 2 + uint32_t tp;//x4 3 + uint32_t t0;//x5 4 + uint32_t t1;//x6 5 + uint32_t t2;//x7 6 + uint32_t t6;//x31 7 + uint32_t s1;//x9 8 + uint32_t a0;//x10 9 + uint32_t a1;//x11 10 + uint32_t a2;//x12 11 + uint32_t a3;//x13 12 + uint32_t a4;//x14 13 + uint32_t a5;//x15 14 + uint32_t a6;//x16 15 + uint32_t a7;//x17 16 + + uint32_t s2;//x18 17 + uint32_t s3;//x19 18 + uint32_t s4;//x20 19 + uint32_t s5;//x21 20 + uint32_t s6;//x22 21 + uint32_t s7;//x23 22 + uint32_t s8;//x24 23 + uint32_t s9;//x25 24 + uint32_t s10;//x26 25 + uint32_t s11;//x27 26 + uint32_t t3;//x28 27 + uint32_t t4;//x29 28 + uint32_t t5;//x30 29 + uint32_t s0;//fp(x8) 30 + + uint32_t mstatus;//31 + uint32_t mepc;//32 +} stack_context; + + + + + +#endif diff --git a/riscv/head.h b/riscv/head.h index 4c1d4af..c7b26f4 100644 --- a/riscv/head.h +++ b/riscv/head.h @@ -2,6 +2,43 @@ #ifndef head_h__ #define head_h__ + + +#define read_csr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_csr(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define swap_csr(reg, val) ({ unsigned long __tmp; \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ + else \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + __tmp; }) + +#define set_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define clear_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + + + + + int my_printf(const char* fmt, ...); void cpu_test(); diff --git a/riscv/interrupt.c b/riscv/interrupt.c new file mode 100644 index 0000000..a5e7fdf --- /dev/null +++ b/riscv/interrupt.c @@ -0,0 +1,13 @@ + + +#include "context.h" +#include "head.h" + +void interrupt_entry(uint32_t irq_num) { + my_printf("interrupt_entry %d\n", irq_num); +} + +void trap_entry(uint32_t irq_num) { + my_printf("trap_entry %d\n", irq_num); + write_csr(mscratch, 0xffffffff); +} diff --git a/riscv/main.c b/riscv/main.c index 093bc21..6b2a9a1 100644 --- a/riscv/main.c +++ b/riscv/main.c @@ -44,12 +44,19 @@ int main() { int a=1; int b=2; + // typedef void (*fun_t)(void); + // fun_t fun = (fun_t)0xffffffff; + // fun(); int c = add(a, b); my_printf("Hello World! %s\n", "Andy"); my_printf("add(%d, %d)=%d\n", a, b, c); a = 67;b = -78; my_printf("mul(%d, %d)=%d\n", a, b, a * b); my_printf("ram_val test: %s\n", g_string); + set_csr(mstatus, 0x00000008); + set_csr(mie, (1 << 3)); + set_csr(mip, (1 << 3)); cpu_test(); + return 0; } \ No newline at end of file diff --git a/riscv/start.S b/riscv/start.S index 3e1e219..ee0a0af 100644 --- a/riscv/start.S +++ b/riscv/start.S @@ -4,6 +4,7 @@ .type _start,@function .extern main +.extern trap_handler _start: la sp, _sp @@ -30,6 +31,8 @@ _start: addi a0, a0, 4 bltu a0, a1, 1b 2: + la a0, trap_handler + csrw mtvec, a0 /* Call global constructors */ # la a0, __libc_fini_array diff --git a/riscv/trap.S b/riscv/trap.S new file mode 100644 index 0000000..c83e5d7 --- /dev/null +++ b/riscv/trap.S @@ -0,0 +1,116 @@ + +.equ REGBYTES, 0x4 + + +.macro PUSH_ALL_REG + addi sp, sp, -33*REGBYTES + sw x1, 0*REGBYTES(sp) //ra + + sw x2, 1*REGBYTES(sp) //sp + sw x3, 2*REGBYTES(sp) //gp + sw x4, 3*REGBYTES(sp) //tp + + sw x5, 4*REGBYTES(sp) //t0 + sw x6, 5*REGBYTES(sp) //t1 + sw x7, 6*REGBYTES(sp) //t2 + sw x8, 30*REGBYTES(sp) + sw x9, 8*REGBYTES(sp) + sw x10, 9*REGBYTES(sp) //a0 + sw x11, 10*REGBYTES(sp) //a1 + sw x12, 11*REGBYTES(sp) //a2 + sw x13, 12*REGBYTES(sp) //a3 + sw x14, 13*REGBYTES(sp) //a4 + sw x15, 14*REGBYTES(sp) //a5 + sw x16, 15*REGBYTES(sp) //a6 + sw x17, 16*REGBYTES(sp) //a7 + sw x18, 17*REGBYTES(sp) + sw x19, 18*REGBYTES(sp) + sw x20, 19*REGBYTES(sp) + sw x21, 20*REGBYTES(sp) + sw x22, 21*REGBYTES(sp) + sw x23, 22*REGBYTES(sp) + sw x24, 23*REGBYTES(sp) + sw x25, 24*REGBYTES(sp) + sw x26, 25*REGBYTES(sp) + sw x27, 26*REGBYTES(sp) + sw x28, 27*REGBYTES(sp) //t3 + sw x29, 28*REGBYTES(sp) //t4 + sw x30, 29*REGBYTES(sp) //t5 + sw x31, 7*REGBYTES(sp) //t6 + csrr t0, mstatus + sw t0, 31*REGBYTES(sp) + csrr t0, mepc + sw t0, 32*REGBYTES(sp) +.endm + +.macro POP_ALL_REG + lw t0, 31* REGBYTES(sp) + csrw mstatus, t0 + lw t0, 32 * REGBYTES(sp) + csrw mepc, t0 + lw x1, 0*REGBYTES(sp) //ra + + lw x5, 4*REGBYTES(sp) + lw x6, 5*REGBYTES(sp) + lw x7, 6*REGBYTES(sp) + lw x8, 30*REGBYTES(sp) + lw x9, 8*REGBYTES(sp) + lw x10, 9*REGBYTES(sp) + lw x11, 10*REGBYTES(sp) + lw x12, 11*REGBYTES(sp) + lw x13, 12*REGBYTES(sp) + lw x14, 13*REGBYTES(sp) + lw x15, 14*REGBYTES(sp) + lw x16, 15*REGBYTES(sp) + lw x17, 16*REGBYTES(sp) + lw x18, 17*REGBYTES(sp) + lw x19, 18*REGBYTES(sp) + lw x20, 19*REGBYTES(sp) + lw x21, 20*REGBYTES(sp) + lw x22, 21*REGBYTES(sp) + lw x23, 22*REGBYTES(sp) + lw x24, 23*REGBYTES(sp) + lw x25, 24*REGBYTES(sp) + lw x26, 25*REGBYTES(sp) + lw x27, 26*REGBYTES(sp) + lw x28, 27*REGBYTES(sp) + lw x29, 28*REGBYTES(sp) + lw x30, 29*REGBYTES(sp) + lw x31, 7*REGBYTES(sp) + addi sp, sp, 33*REGBYTES +.endm + +# .section .interrupt.text +.extern trap_entry +.global trap_entry_ +.align 4 +trap_entry_: + csrw mscratch, sp + la sp, _exc_sp + call trap_entry + csrr sp, mscratch + POP_ALL_REG + mret + + +# .section .interrupt.text +.extern trap_entry +.extern interrupt_entry +.global trap_handler +.equ TRAP_INTERRUPT_MODE_MASK, 0x80000000 +.align 4 +trap_handler: + PUSH_ALL_REG + csrr a0, mcause + li a1, TRAP_INTERRUPT_MODE_MASK + li a2, 0x000000ff + and a1, a0, a1 + and a0, a2, a0 + beqz a1, trap_entry_ + csrw mscratch, sp + la sp, _irq_sp + call interrupt_entry + csrr sp, mscratch + + POP_ALL_REG + mret