3 * Copyright 2018 Jacob Lifshay
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 from migen
.fhdl
import verilog
32 from migen
.fhdl
.structure
import _Operator
34 from riscvdefs
import *
38 class CPUHandleTrap(Module
):
44 self
.clk
= ClockSignal()
45 self
.reset
= ResetSignal()
47 self
.ft_action
= Signal(fetch_action
)
48 self
.dc_action
= Signal(decode_action
)
49 self
.dc_immediate
= Signal(32)
51 self
.new_mie
= Signal()
52 self
.new_mepc
= Signal()
53 self
.new_mpie
= Signal()
54 self
.new_mcause
= Signal(32)
55 self
.ft_output_pc
= Signal(32)
56 self
.load_store_misaligned
= Signal()
58 s
= [self
.new_mpie
.eq(self
.mie
),
60 self
.new_mepc
.eq(Mux(self
.ft_action
== FA
.noerror_trap
,
61 self
.ft_output_pc
+ 4,
64 # fetch action ack trap
65 i
= If(self
.ft_action
== FA
.ack_trap
,
66 self
.new_mcause
.eq(cause_instruction_access_fault
)
70 i
= i
.Elif((self
.dc_action
& DA
.trap_ecall_ebreak
) != 0,
71 self
.new_mcause
.eq(Mux(self
.dc_immediate
[0],
72 cause_machine_environment_call
,
77 i
= i
.Elif((self
.dc_action
& DA
.load
) != 0,
78 If(self
.load_store_misaligned
,
79 self
.new_mcause
.eq(cause_load_address_misaligned
)
81 self
.new_mcause
.eq(cause_load_access_fault
)
86 i
= i
.Elif((self
.dc_action
& DA
.store
) != 0,
87 If(self
.load_store_misaligned
,
88 self
.new_mcause
.eq(cause_store_amo_address_misaligned
)
90 self
.new_mcause
.eq(cause_store_amo_access_fault
)
94 # jal/jalr -> misaligned=error, otherwise jump
95 i
= i
.Elif((self
.dc_action
& (DA
.jal | DA
.jalr | DA
.branch
)) != 0,
96 self
.new_mcause
.eq(cause_instruction_address_misaligned
)
99 # defaults to illegal instruction
100 i
= i
.Else(self
.new_mcause
.eq(cause_illegal_instruction
))
107 if __name__
== "__main__":
108 example
= CPUHandleTrap()
109 print(verilog
.convert(example
,
112 example
.dc_immediate
,
118 example
.ft_output_pc
,
119 example
.load_store_misaligned
,