move get_fetch_action to separate verilog file
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 26 Nov 2018 12:33:35 +0000 (12:33 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 26 Nov 2018 12:33:35 +0000 (12:33 +0000)
cpu.py
cpu_fetch_action.py [new file with mode: 0644]

diff --git a/cpu.py b/cpu.py
index ff464520b56b73f61460cabf245fe9d76a31b250..bdf234d742d833038a1cca4b209f71b5aa5093b3 100644 (file)
--- a/cpu.py
+++ b/cpu.py
@@ -190,74 +190,6 @@ class Fetch:
         self.output_instruction = Signal(32, name="fetch_ouutput_instruction")
         self.output_state = Signal(fetch_output_state,name="fetch_output_state")
 
-    def get_fetch_action(self, dc_act, load_store_misaligned, mi_rw_wait,
-                         mi_rw_address_valid,
-                         branch_taken, misaligned_jump_target,
-                         csr_op_is_valid):
-        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((dc_act & DA.trap_illegal_instruction) != 0,
-                 self.action.eq(FA.error_trap)
-              )
-
-        # ecall / ebreak -> noerror trap
-        i = i.Elif((dc_act & DA.trap_ecall_ebreak) != 0,
-                 self.action.eq(FA.noerror_trap))
-
-        # load/store: check alignment, check wait
-        i = i.Elif((dc_act & (DA.load | DA.store)) != 0,
-                If((load_store_misaligned | ~mi_rw_address_valid),
-                    self.action.eq(FA.error_trap) # misaligned or invalid addr
-                ).Elif(mi_rw_wait,
-                    self.action.eq(FA.wait) # wait
-                ).Else(
-                    self.action.eq(FA.default) # ok
-                )
-              )
-
-        # fence
-        i = i.Elif((dc_act & DA.fence) != 0,
-                 self.action.eq(FA.fence))
-
-        # branch -> misaligned=error, otherwise jump
-        i = i.Elif((dc_act & DA.branch) != 0,
-                If(branch_taken,
-                    If(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((dc_act & (DA.jal | DA.jalr)) != 0,
-                If(misaligned_jump_target,
-                    self.action.eq(FA.error_trap)
-                ).Else(
-                    self.action.eq(FA.jump)
-                )
-              )
-
-        # csr -> opvalid=ok, else error trap
-        i = i.Elif((dc_act & DA.csr) != 0,
-                If(csr_op_is_valid,
-                    self.action.eq(FA.default)
-                ).Else(
-                    self.action.eq(FA.error_trap)
-                )
-              )
-
-        c[FOS.valid] = i
-
-        return Case(self.output_state, c)
-
 class CSR:
     def __init__(self, comb, sync, dc, register_rs1):
         self.comb = comb
@@ -830,10 +762,18 @@ class CPU(Module):
         # CSR decoding
         csr = CSR(self.comb, self.sync, dc, self.regs.rs1)
 
-        self.comb += ft.get_fetch_action(dc.act, load_store_misaligned,
-                                 mi.rw_wait, mi.rw_address_valid,
-                                 branch_taken, misaligned_jump_target,
-                                 csr.op_is_valid)
+        fi = Instance("CPUFetchAction", name="cpu_fetch_action",
+            o_fetch_action = ft.action,
+            i_output_state = ft.output_state,
+            i_dc_act = dc.act,
+            i_load_store_misaligned = load_store_misaligned,
+            i_mi_rw_wait = mi.rw_wait,
+            i_mi_rw_address_valid = mi.rw_address_valid,
+            i_branch_taken = branch_taken,
+            i_misaligned_jump_target = misaligned_jump_target,
+            i_csr_op_is_valid = csr.op_is_valid)
+
+        self.specials += fi
 
         minfo = MInfo(self.comb)
 
diff --git a/cpu_fetch_action.py b/cpu_fetch_action.py
new file mode 100644 (file)
index 0000000..3b6d7b8
--- /dev/null
@@ -0,0 +1,128 @@
+"""
+/*
+ * 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,
+           }))