+"""
+/*
+ * Copyright 2018 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+`timescale 1ns / 1ps
+`include "riscv.vh"
+`include "cpu.vh"
+"""
+
+import string
+from migen import *
+from migen.fhdl import verilog
+from migen.fhdl.structure import _Operator
+
+from riscvdefs import *
+from cpudefs import *
+
+class CPUFetchAction(Module):
+ def __init__(self):
+ Module.__init__(self)
+ self.action = Signal(fetch_action)
+ self.output_state = Signal()
+ self.dc_act = Signal(decode_action)
+ self.load_store_misaligned = Signal()
+ self.mi_rw_wait = Signal()
+ self.mi_rw_address_valid = Signal()
+ self.branch_taken = Signal()
+ self.misaligned_jump_target = Signal()
+ self.csr_op_is_valid = Signal()
+
+ c = {}
+ c["default"] = self.action.eq(FA.default) # XXX should be 32'XXXXXXXX?
+ c[FOS.empty] = self.action.eq(FA.default)
+ c[FOS.trap] = self.action.eq(FA.ack_trap)
+
+ # illegal instruction -> error trap
+ i= If((self.dc_act & DA.trap_illegal_instruction) != 0,
+ self.action.eq(FA.error_trap)
+ )
+
+ # ecall / ebreak -> noerror trap
+ i = i.Elif((self.dc_act & DA.trap_ecall_ebreak) != 0,
+ self.action.eq(FA.noerror_trap))
+
+ # load/store: check alignment, check wait
+ i = i.Elif((self.dc_act & (DA.load | DA.store)) != 0,
+ If((self.load_store_misaligned | ~self.mi_rw_address_valid),
+ self.action.eq(FA.error_trap) # misaligned or invalid addr
+ ).Elif(self.mi_rw_wait,
+ self.action.eq(FA.wait) # wait
+ ).Else(
+ self.action.eq(FA.default) # ok
+ )
+ )
+
+ # fence
+ i = i.Elif((self.dc_act & DA.fence) != 0,
+ self.action.eq(FA.fence))
+
+ # branch -> misaligned=error, otherwise jump
+ i = i.Elif((self.dc_act & DA.branch) != 0,
+ If(self.branch_taken,
+ If(self.misaligned_jump_target,
+ self.action.eq(FA.error_trap)
+ ).Else(
+ self.action.eq(FA.jump)
+ )
+ ).Else(
+ self.action.eq(FA.default)
+ )
+ )
+
+ # jal/jalr -> misaligned=error, otherwise jump
+ i = i.Elif((self.dc_act & (DA.jal | DA.jalr)) != 0,
+ If(self.misaligned_jump_target,
+ self.action.eq(FA.error_trap)
+ ).Else(
+ self.action.eq(FA.jump)
+ )
+ )
+
+ # csr -> opvalid=ok, else error trap
+ i = i.Elif((self.dc_act & DA.csr) != 0,
+ If(self.csr_op_is_valid,
+ self.action.eq(FA.default)
+ ).Else(
+ self.action.eq(FA.error_trap)
+ )
+ )
+
+ c[FOS.valid] = i
+
+ self.comb += Case(self.output_state, c)
+
+
+if __name__ == "__main__":
+ example = CPUFetchAction()
+ print(verilog.convert(example,
+ {
+ example.action,
+ example.output_state,
+ example.dc_act,
+ example.load_store_misaligned,
+ example.mi_rw_wait,
+ example.mi_rw_address_valid,
+ example.branch_taken,
+ example.misaligned_jump_target,
+ example.csr_op_is_valid,
+ }))