From 8d039f432777ae1e7dab57c84d254f1a07e62953 Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Wed, 25 Aug 2021 20:59:32 +0800 Subject: [PATCH] handle CpU exception --- README.md | 4 +-- src/Core/Controller.sv | 15 +++++----- src/Core/Datapath.sv | 28 +++++++++++++----- src/MyCPU.sv | 1 + src/include/defines.svh | 4 +++ tools/ctrl_maker.py | 2 +- tools/decoder.py | 1 + tools/exc.txt | 10 +++++++ tools/privilege.txt | 63 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 tools/exc.txt create mode 100644 tools/privilege.txt diff --git a/README.md b/README.md index 0bb765d..50ec979 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Our awesome `MIPS` CPU written in `SystemVerilog` for Loongson Cup - [ ] 特权模式 - [x] `CP0`寄存器`Status.UM` :heavy_check_mark: - - [ ] 访存异常(考虑`in_kernel`状态切换带来的冒险) :hourglass: - - [ ] 特权指令异常 :clock3: + - [x] 访存异常(考虑`in_kernel`状态切换带来的冒险) :heavy_check_mark: + - [ ] 特权指令异常 :hourglass: - [ ] 浮点运算单元 - [ ] ~~做一个真的`FPU`~~ :x: - [ ] 浮点运算指令报`Coprocessor Unusable`,同时`CP0`中新增`Cause.CE` :clock3: diff --git a/src/Core/Controller.sv b/src/Core/Controller.sv index c4f6768..d672375 100644 --- a/src/Core/Controller.sv +++ b/src/Core/Controller.sv @@ -29,15 +29,16 @@ module Controller ( ); assign ctrl.BJRJ = ~inst[29] & (~inst[31] & (~inst[30] & ~inst[5] & ~inst[4] & inst[3] & ~inst[2] | inst[28] | inst[26]) | inst[27] & ~inst[26]); - assign ctrl.B = ~inst[31] & ~inst[29] & (inst[28] | ~inst[27] & inst[26]); - assign ctrl.JR = ~inst[31] & ~inst[30] & ~inst[29] & ~inst[28] & ~inst[27] & ~inst[26] & ~inst[5] & ~inst[4] & inst[3] & ~inst[2]; - assign ctrl.J = ~inst[31] & ~inst[29] & ~inst[28] & inst[27]; - assign ctrl.BGO = ~inst[26] & (eq | inst[27] & ltz) | inst[26] & (~inst[27] & (~inst[28] & (inst[16] & ~ltz | ~inst[16] & ltz) | inst[28] & ~eq) | inst[27] & ~eq & ~ltz); + assign ctrl.B = ~inst[31] & ~inst[29] & (inst[28] | ~inst[27] & inst[26]); + assign ctrl.JR = ~inst[31] & ~inst[30] & ~inst[29] & ~inst[28] & ~inst[27] & ~inst[26] & ~inst[5] & ~inst[4] & inst[3] & ~inst[2]; + assign ctrl.J = ~inst[31] & ~inst[29] & ~inst[28] & inst[27]; + assign ctrl.BGO = ~inst[26] & (eq | inst[27] & ltz) | inst[26] & (~inst[27] & (~inst[28] & (inst[16] & ~ltz | ~inst[16] & ltz) | inst[28] & ~eq) | inst[27] & ~eq & ~ltz); + assign ctrl.PRV = inst[30] & ~inst[29]; assign ctrl.SYSCALL = ~inst[31] & ~inst[30] & ~inst[29] & ~inst[28] & ~inst[27] & ~inst[26] & inst[3] & inst[2] & ~inst[0]; - assign ctrl.BREAK = ~inst[31] & ~inst[30] & ~inst[29] & ~inst[28] & ~inst[27] & ~inst[26] & inst[3] & inst[2] & inst[0]; - assign ctrl.ERET = inst[30] & inst[4]; - assign ctrl.OFA = ~inst[31] & ~inst[28] & ~inst[27] & ~inst[26] & (~inst[30] & inst[5] & ~inst[3] & ~inst[2] & ~inst[0] | inst[29]); + assign ctrl.BREAK = ~inst[31] & ~inst[30] & ~inst[29] & ~inst[28] & ~inst[27] & ~inst[26] & inst[3] & inst[2] & inst[0]; + assign ctrl.ERET = inst[30] & inst[4]; + assign ctrl.OFA = ~inst[31] & ~inst[28] & ~inst[27] & ~inst[26] & (~inst[30] & inst[5] & ~inst[3] & ~inst[2] & ~inst[0] | inst[29]); assign ctrl.ES = inst[31] | ~inst[30] & ~inst[28] & ~inst[27] & ~inst[26] & (inst[5] | inst[4] & inst[3] & ~inst[2] | ~inst[3] & inst[2]) | inst[29];; assign ctrl.ET = ~inst[31] & ~inst[27] & ~inst[26] & (~inst[30] & ~inst[29] & ~inst[28] & (inst[5] | (~inst[1] & (~inst[4] & ~inst[3] & ~inst[0] | inst[4] & inst[3]) | inst[1] & (~inst[4] | inst[3]))) | inst[30] & inst[29]); diff --git a/src/Core/Datapath.sv b/src/Core/Datapath.sv index 63983df..fa984d6 100644 --- a/src/Core/Datapath.sv +++ b/src/Core/Datapath.sv @@ -33,6 +33,7 @@ module Datapath ( input word_t C0_ERETPC, input logic C0_Bev, input logic [19:0] C0_EBase, + input logic C0_kernel, //debug interface output wire [31:0] debug_wb_pc, @@ -324,7 +325,7 @@ module Datapath ( .rst(rst | rstD | rstM), .vinA(fetch_i.data_ok | F.ExcValid), - .inA ({F.pc[2] ? fetch_i.rdata1 : fetch_i.rdata0, F.pc, + .inA ({F.pc[2] ? fetch_i.rdata1 : fetch_i.rdata0, F.pc, iTLBRefill, iTLBInvalid, iAddressError}), .vinB(fetch_i.data_ok & ~F.pc[2]), @@ -437,17 +438,29 @@ module Datapath ( ); // TODO: Merge "pc[1:0] != 2'b00" into AddressError - assign D.IA_ExcValid = D_IA_valid & (D.IA_pc[1:0] != 2'b00 | D_IA_TLBRefill | D_IA_TLBInvalid | D_IA_AddressError | ~D_IA_iv | D.IA.SYSCALL | D.IA.BREAK | D.IA.ERET); + assign D.IA_ExcValid = D_IA_valid & ( D.IA_pc[1:0] != 2'b00 + | ~D_IA_iv + | D_IA_TLBRefill | D_IA_TLBInvalid + | D_IA_AddressError + | D.IA.SYSCALL | D.IA.BREAK | D.IA.ERET + | D.IA.PRV & ~C0_kernel); assign D.IA_ERET = D_IA_valid & D.IA_pc[1:0] == 2'b00 & ~D_IA_TLBRefill & ~D_IA_TLBInvalid & ~D_IA_AddressError & D_IA_iv & D.IA.ERET; assign D.IA_REFILL = D_IA_valid & D.IB_pc[1:0] == 2'b00 & D_IA_TLBRefill; assign D.IA_ExcCode = D.IA_pc[1:0] != 2'b00 | D_IA_AddressError ? `EXCCODE_ADEL : D_IA_TLBRefill ? `EXCCODE_TLBL : D_IA_TLBInvalid ? `EXCCODE_TLBL : ~D_IA_iv ? `EXCCODE_RI - : D.IA_inst[0] ? `EXCCODE_BP - : `EXCCODE_SYS; + : ~D.IA_inst[30] & D.IA_inst[0] ? `EXCCODE_BP + : ~D.IA_inst[30] & ~D.IA_inst[0] ? `EXCCODE_SYS + : `EXCCODE_CPU; - assign D.IB_ExcValid = D_IB_valid & (D.IB_pc[1:0] != 2'b00 | D_IB_TLBRefill | D_IB_TLBInvalid | D_IB_AddressError | ~D_IB_iv | D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET | D.IB_Delay & D.IB.BJRJ); + assign D.IB_ExcValid = D_IB_valid & ( D.IB_pc[1:0] != 2'b00 + | ~D_IB_iv + | D_IB_TLBRefill | D_IB_TLBInvalid + | D_IB_AddressError + | D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET + | D.IB_Delay & D.IB.BJRJ + | D.IB.PRV & ~C0_kernel); assign D.IB_ERET = D_IB_valid & D.IB_pc[1:0] == 2'b00 & ~D_IB_TLBRefill & ~D_IB_TLBInvalid & ~D_IB_AddressError & D_IB_iv & D.IB.ERET & ~D.IB_Delay; assign D.IB_REFILL = D_IB_valid & D.IB_pc[1:0] == 2'b00 & D_IB_TLBRefill; assign D.IB_ExcCode = D.IB_pc[1:0] != 2'b00 | D_IB_AddressError ? `EXCCODE_ADEL @@ -456,8 +469,9 @@ module Datapath ( : ~D_IB_iv ? `EXCCODE_RI : D.IB.ERET ? `EXCCODE_RI : D.IB_Delay & D.IB.BJRJ ? `EXCCODE_RI - : D.IB_inst[0] ? `EXCCODE_BP - : `EXCCODE_SYS; + : ~D.IB_inst[30] & D.IB_inst[0] ? `EXCCODE_BP + : ~D.IB_inst[30] & ~D.IB_inst[0] ? `EXCCODE_SYS + : `EXCCODE_CPU; assign D.IB_Delay = D.IA.BJRJ; // D.Dispatch diff --git a/src/MyCPU.sv b/src/MyCPU.sv index be4e5fb..cbae4f5 100644 --- a/src/MyCPU.sv +++ b/src/MyCPU.sv @@ -235,6 +235,7 @@ module mycpu_top ( .C0_ERETPC (C0_ERETPC), .C0_Bev (C0_Bev), .C0_EBase (C0_EBase), + .C0_kernel (in_kernel), .debug_wb_pc (debug_wb_pc), .debug_wb_rf_wen (debug_wb_rf_wen), diff --git a/src/include/defines.svh b/src/include/defines.svh index 203a1f6..e3dc049 100644 --- a/src/include/defines.svh +++ b/src/include/defines.svh @@ -24,7 +24,9 @@ `define EXCCODE_SYS 5'h08 `define EXCCODE_BP 5'h09 `define EXCCODE_RI 5'h0A +`define EXCCODE_CPU 5'h0B `define EXCCODE_OV 5'h0C +`define EXCCODE_TR 5'h0D typedef logic [31:0] word_t; @@ -101,6 +103,8 @@ typedef struct packed { } WCtrl_t; typedef struct packed { + logic PRV; + logic SYSCALL; logic BREAK; logic ERET; diff --git a/tools/ctrl_maker.py b/tools/ctrl_maker.py index 1c42741..599f083 100644 --- a/tools/ctrl_maker.py +++ b/tools/ctrl_maker.py @@ -1,4 +1,4 @@ -with open('mctrl1.txt') as f: +with open('exc.txt') as f: lines = f.readlines() title = lines[0].split() items = [x.split() for x in lines[1:]] diff --git a/tools/decoder.py b/tools/decoder.py index 6e84445..d0feb03 100644 --- a/tools/decoder.py +++ b/tools/decoder.py @@ -127,6 +127,7 @@ for inst, name in table: ctrl['MCtrl1_MX'] = ~inst[28] ctrl['MCtrl1_TLBR'] = inst[30] & ~inst[29] & inst[25] & ~inst[3] & ~inst[1] ctrl['MCtrl1_TLBWI'] = inst[30] & ~inst[29] & inst[25] & ~inst[3] & inst[1] + ctrl['MCtrl1_TLBWR'] = inst[30] & ~inst[29] & inst[25] & ~inst[3] & (inst[2] | ~inst[1]) ctrl['MCtrl1_TLBP'] = inst[30] & ~inst[4] & inst[3] ctrl['WCtrl_RW'] = (~inst[30] & (~inst[29] & (inst[31] | ~inst[28] & (~inst[27] & (~inst[26] & (~inst[3] & (~inst[4] | ~inst[0]) | inst[3] & (inst[5] | ~inst[4] & ~inst[2] & inst[0])) | inst[26] & inst[20]) | inst[27] & inst[26])) | inst[29] & ~inst[31]) | inst[30] & ~inst[25] & ~inst[23]) diff --git a/tools/exc.txt b/tools/exc.txt new file mode 100644 index 0000000..2bf4a6c --- /dev/null +++ b/tools/exc.txt @@ -0,0 +1,10 @@ +////-------------------------------- BREAK SYSCALL +32'b000000????????????????????001100 0 1 // SYSCALL +32'b000000????????????????????001101 1 0 // BREAK +32'b01000010000000000000000000011000 0 0 // ERET +32'b01000000000??????????00000000??? 0 0 // MFC0 +32'b01000000100??????????00000000??? 0 0 // MTC0 +32'b01000010000000000000000000000001 0 0 // TLBR +32'b01000010000000000000000000000010 0 0 // TLBWI +32'b01000010000000000000000000000110 0 0 // TLBWR +32'b01000010000000000000000000001000 0 0 // TLBP \ No newline at end of file diff --git a/tools/privilege.txt b/tools/privilege.txt new file mode 100644 index 0000000..3c7a8fd --- /dev/null +++ b/tools/privilege.txt @@ -0,0 +1,63 @@ +////-------------------------------- PRV +32'b00000000000???????????????000000 0 // SLL +32'b00000000000???????????????000010 0 // SRL +32'b00000000000???????????????000011 0 // SRA +32'b000000???????????????00000000100 0 // SLLV +32'b000000???????????????00000000110 0 // SRLV +32'b000000???????????????00000000111 0 // SRAV +32'b000000?????000000000000000001000 0 // JR +32'b000000?????00000?????00000001001 0 // JALR +32'b000000????????????????????001100 0 // SYSCALL +32'b000000????????????????????001101 0 // BREAK +32'b0000000000000000?????00000010000 0 // MFHI +32'b000000?????000000000000000010001 0 // MTHI +32'b0000000000000000?????00000010010 0 // MFLO +32'b000000?????000000000000000010011 0 // MTLO +32'b000000??????????0000000000011000 0 // MULT +32'b000000??????????0000000000011001 0 // MULTU +32'b000000??????????0000000000011010 0 // DIV +32'b000000??????????0000000000011011 0 // DIVU +32'b000000???????????????00000100000 0 // ADD +32'b000000???????????????00000100001 0 // ADDU +32'b000000???????????????00000100010 0 // SUB +32'b000000???????????????00000100011 0 // SUBU +32'b000000???????????????00000100100 0 // AND +32'b000000???????????????00000100101 0 // OR +32'b000000???????????????00000100110 0 // XOR +32'b000000???????????????00000100111 0 // NOR +32'b000000???????????????00000101010 0 // SLT +32'b000000???????????????00000101011 0 // SLTU +32'b000001?????00000???????????????? 0 // BLTZ +32'b000001?????10000???????????????? 0 // BLTZAL +32'b000001?????00001???????????????? 0 // BGEZ +32'b000001?????10001???????????????? 0 // BGEZAL +32'b000010?????????????????????????? 0 // J +32'b000011?????????????????????????? 0 // JAL +32'b000100?????????????????????????? 0 // BEQ +32'b000101?????????????????????????? 0 // BNE +32'b000110?????00000???????????????? 0 // BLEZ +32'b000111?????00000???????????????? 0 // BGTZ +32'b001000?????????????????????????? 0 // ADDI +32'b001001?????????????????????????? 0 // ADDIU +32'b001010?????????????????????????? 0 // SLTI +32'b001011?????????????????????????? 0 // SLTIU +32'b001100?????????????????????????? 0 // ANDI +32'b001101?????????????????????????? 0 // ORI +32'b001110?????????????????????????? 0 // XORI +32'b00111100000????????????????????? 0 // LUI +32'b01000000000??????????00000000??? 1 // MFC0 +32'b01000000100??????????00000000??? 1 // MTC0 +32'b01000010000000000000000000000001 1 // TLBR +32'b01000010000000000000000000000010 1 // TLBWI +32'b01000010000000000000000000000110 1 // TLBWR +32'b01000010000000000000000000001000 1 // TLBP +32'b01000010000000000000000000011000 1 // ERET +32'b011100???????????????00000000010 0 // MUL +32'b100000?????????????????????????? 0 // LB +32'b100001?????????????????????????? 0 // LH +32'b100011?????????????????????????? 0 // LW +32'b100100?????????????????????????? 0 // LBU +32'b100101?????????????????????????? 0 // LHU +32'b101000?????????????????????????? 0 // SB +32'b101001?????????????????????????? 0 // SH +32'b101011?????????????????????????? 0 // SW \ No newline at end of file