add handle_trap
[rv32.git] / cpu.py
diff --git a/cpu.py b/cpu.py
index f2561f14e7bc8794cdcb09897c39f6d2034668b7..e0a6881c9248769e328e73ed1498ec4cf0bd49e3 100644 (file)
--- a/cpu.py
+++ b/cpu.py
@@ -153,6 +153,7 @@ class M:
         self.sync += self.mepc.eq(0) # 32'hXXXXXXXX;
         self.sync += self.mscratch.eq(0) # 32'hXXXXXXXX;
 
+
 class Misa:
     def __init__(self, comb, sync):
         self.comb = comb
@@ -246,6 +247,8 @@ class CPU(Module):
     """
 
     def get_ls_misaligned(self, ls, funct3, load_store_address_low_2):
+        """ returns whether a load/store is misaligned
+        """
         return Case(funct3[:2],
                 { F3.sb: ls.eq(Constant(0)),
                   F3.sh: ls.eq(load_store_address_low_2[0] != 0),
@@ -277,6 +280,91 @@ class CPU(Module):
         for f in [F3.csrrc, F3.csrrci]: c[f] = ~written_value & previous_value
         return Case(funct3, c)
 
+    def handle_trap(self, m, ms, ft, dc, load_store_misaligned):
+        s = [ms.mpie.eq(ms.mie),
+             ms.mie.eq(0),
+             m.mepc.eq(Mux(ft.action == FA.noerror_trap,
+                           ft.output_pc + 4,
+                           ft.output_pc))]
+
+        # fetch action ack trap
+        i = If(ft.action == FA.ack_trap,
+                m.mcause.eq(cause_instruction_access_fault)
+              )
+
+        # ecall/ebreak
+        i = i.Elif((dc.act & DA.trap_ecall_ebreak) != 0,
+                m.mcause.eq(Mux(dc.immediate[0],
+                                cause_machine_environment_call,
+                                cause_breakpoint))
+              )
+
+        # load
+        i = i.Elif((dc.act & DA.load) != 0,
+                If(load_store_misaligned,
+                    m.mcause.eq(cause_load_address_misaligned)
+                ).Else(
+                    m.mcause.eq(cause_load_access_fault)
+                )
+              )
+
+        # store
+        i = i.Elif((dc.act & DA.store) != 0,
+                If(load_store_misaligned,
+                    m.mcause.eq(cause_store_amo_address_misaligned)
+                ).Else(
+                    m.mcause.eq(cause_store_amo_access_fault)
+                )
+              )
+
+        # jal/jalr -> misaligned=error, otherwise jump
+        i = i.Elif((dc.act & (DA.jal | DA.jalr | DA.branch)) != 0,
+                m.mcause.eq(cause_instruction_address_misaligned)
+              )
+
+        # defaults to illegal instruction
+        i = i.Else(m.mcause.eq(cause_illegal_instruction))
+
+        s.append(i)
+        return s
+
+    """
+    task handle_trap;
+    begin
+        mstatus_mpie = mstatus_mie;
+        mstatus_mie = 0;
+        mepc = (fetch_action == `fetch_action_noerror_trap) ? fetch_output_pc + 4 : fetch_output_pc;
+        if(fetch_action == `fetch_action_ack_trap) begin
+            mcause = `cause_instruction_access_fault;
+        end
+        else if((decode_action & `decode_action_trap_illegal_instruction) != 0) begin
+            mcause = `cause_illegal_instruction;
+        end
+        else if((decode_action & `decode_action_trap_ecall_ebreak) != 0) begin
+            mcause = decoder_immediate[0] ? `cause_machine_environment_call : `cause_breakpoint;
+        end
+        else if((decode_action & `decode_action_load) != 0) begin
+            if(load_store_misaligned)
+                mcause = `cause_load_address_misaligned;
+            else
+                mcause = `cause_load_access_fault;
+        end
+        else if((decode_action & `decode_action_store) != 0) begin
+            if(load_store_misaligned)
+                mcause = `cause_store_amo_address_misaligned;
+            else
+                mcause = `cause_store_amo_access_fault;
+        end
+        else if((decode_action & (`decode_action_branch | `decode_action_jal | `decode_action_jalr)) != 0) begin
+            mcause = `cause_instruction_address_misaligned;
+        end
+        else begin
+            mcause = `cause_illegal_instruction;
+        end
+    end
+    endtask
+    """
+
     def __init__(self):
         self.clk = ClockSignal()
         self.reset = ResetSignal()
@@ -520,6 +608,9 @@ class CPU(Module):
         self.comb += ft.get_fetch_action(dc, load_store_misaligned, mi,
                                  branch_taken, misaligned_jump_target,
                                  csr_op_is_valid)
+
+        #self.comb += self.handle_trap(m, mstatus, ft, dc, load_store_misaligned)
+
 if __name__ == "__main__":
     example = CPU()
     print(verilog.convert(example,
@@ -535,127 +626,6 @@ if __name__ == "__main__":
 
 """
 
-    function `fetch_action get_fetch_action(
-        input `fetch_output_state fetch_output_state,
-        input `decode_action decode_action,
-        input load_store_misaligned,
-        input memory_interface_rw_address_valid,
-        input memory_interface_rw_wait,
-        input branch_taken,
-        input misaligned_jump_target,
-        input csr_op_is_valid
-        );
-    begin
-        case(fetch_output_state)
-        `fetch_output_state_empty:
-            get_fetch_action = `fetch_action_default;
-        `fetch_output_state_trap:
-            get_fetch_action = `fetch_action_ack_trap;
-        `fetch_output_state_valid: begin
-            if((decode_action & `decode_action_trap_illegal_instruction) != 0) begin
-                get_fetch_action = `fetch_action_error_trap;
-            end
-            else if((decode_action & `decode_action_trap_ecall_ebreak) != 0) begin
-                get_fetch_action = `fetch_action_noerror_trap;
-            end
-            else if((decode_action & (`decode_action_load | `decode_action_store)) != 0) begin
-                if(load_store_misaligned | ~memory_interface_rw_address_valid) begin
-                    get_fetch_action = `fetch_action_error_trap;
-                end
-                else if(memory_interface_rw_wait) begin
-                    get_fetch_action = `fetch_action_wait;
-                end
-                else begin
-                    get_fetch_action = `fetch_action_default;
-                end
-            end
-            else if((decode_action & `decode_action_fence_i) != 0) begin
-                get_fetch_action = `fetch_action_fence;
-            end
-            else if((decode_action & `decode_action_branch) != 0) begin
-                if(branch_taken) begin
-                    if(misaligned_jump_target) begin
-                        get_fetch_action = `fetch_action_error_trap;
-                    end
-                    else begin
-                        get_fetch_action = `fetch_action_jump;
-                    end
-                end
-                else
-                begin
-                    get_fetch_action = `fetch_action_default;
-                end
-            end
-            else if((decode_action & (`decode_action_jal | `decode_action_jalr)) != 0) begin
-                if(misaligned_jump_target) begin
-                    get_fetch_action = `fetch_action_error_trap;
-                end
-                else begin
-                    get_fetch_action = `fetch_action_jump;
-                end
-            end
-            else if((decode_action & `decode_action_csr) != 0) begin
-                if(csr_op_is_valid)
-                    get_fetch_action = `fetch_action_default;
-                else
-                    get_fetch_action = `fetch_action_error_trap;
-            end
-            else begin
-                get_fetch_action = `fetch_action_default;
-            end
-        end
-        default:
-            get_fetch_action = 32'hXXXXXXXX;
-        endcase
-    end
-    endfunction
-
-    assign fetch_action = get_fetch_action(
-        fetch_output_state,
-        decode_action,
-        load_store_misaligned,
-        memory_interface_rw_address_valid,
-        memory_interface_rw_wait,
-        branch_taken,
-        misaligned_jump_target,
-        csr_op_is_valid
-        );
-
-    task handle_trap;
-    begin
-        mstatus_mpie = mstatus_mie;
-        mstatus_mie = 0;
-        mepc = (fetch_action == `fetch_action_noerror_trap) ? fetch_output_pc + 4 : fetch_output_pc;
-        if(fetch_action == `fetch_action_ack_trap) begin
-            mcause = `cause_instruction_access_fault;
-        end
-        else if((decode_action & `decode_action_trap_illegal_instruction) != 0) begin
-            mcause = `cause_illegal_instruction;
-        end
-        else if((decode_action & `decode_action_trap_ecall_ebreak) != 0) begin
-            mcause = decoder_immediate[0] ? `cause_machine_environment_call : `cause_breakpoint;
-        end
-        else if((decode_action & `decode_action_load) != 0) begin
-            if(load_store_misaligned)
-                mcause = `cause_load_address_misaligned;
-            else
-                mcause = `cause_load_access_fault;
-        end
-        else if((decode_action & `decode_action_store) != 0) begin
-            if(load_store_misaligned)
-                mcause = `cause_store_amo_address_misaligned;
-            else
-                mcause = `cause_store_amo_access_fault;
-        end
-        else if((decode_action & (`decode_action_branch | `decode_action_jal | `decode_action_jalr)) != 0) begin
-            mcause = `cause_instruction_address_misaligned;
-        end
-        else begin
-            mcause = `cause_illegal_instruction;
-        end
-    end
-    endtask
-
     wire [11:0] csr_number = decoder_immediate;
     wire [31:0] csr_input_value = decoder_funct3[2] ? decoder_rs1 : register_rs1;
     wire csr_reads = decoder_funct3[1] | (decoder_rd != 0);