experiment with separate cpu handle csr module
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 27 Nov 2018 08:55:10 +0000 (08:55 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 27 Nov 2018 08:55:10 +0000 (08:55 +0000)
cpu_handle_csr.py [new file with mode: 0644]

diff --git a/cpu_handle_csr.py b/cpu_handle_csr.py
new file mode 100644 (file)
index 0000000..f2f5788
--- /dev/null
@@ -0,0 +1,259 @@
+"""
+/*
+ * 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 Misa:
+    def __init__(self, comb, sync):
+        self.comb = comb
+        self.sync = sync
+        self.misa = Signal(32)
+        cl = []
+        for l in list(string.ascii_lowercase):
+            value = 1 if l == 'i' else 0
+            cl.append(Constant(value))
+        cl.append(Constant(0, 4))
+        cl.append(Constant(0b01, 2))
+        self.comb += self.misa.eq(Cat(cl))
+
+class MStatus:
+    def __init__(self, comb, sync):
+        self.comb = comb
+        self.sync = sync
+        self.mpie = Signal(name="mstatus_mpie")
+        self.mie = Signal(name="mstatus_mie")
+        self.mstatus = Signal(32, name="mstatus")
+
+        self.sync += self.mie.eq(0)
+        self.sync += self.mpie.eq(0)
+        self.sync += self.mstatus.eq(0)
+
+
+class M:
+    def __init__(self, comb, sync):
+        self.comb = comb
+        self.sync = sync
+        self.mcause = Signal(32)
+        self.mepc = Signal(32)
+        self.mscratch = Signal(32)
+        self.sync += self.mcause.eq(0)
+        self.sync += self.mepc.eq(0) # 32'hXXXXXXXX;
+        self.sync += self.mscratch.eq(0) # 32'hXXXXXXXX;
+
+
+class MIE:
+    def __init__(self, comb, sync):
+        self.comb = comb
+        self.sync = sync
+        self.meie = Signal(name="mie_meie")
+        self.mtie = Signal(name="mie_mtie")
+        self.msie = Signal(name="mie_msie")
+        self.mie = Signal(32)
+
+
+class MIP:
+    def __init__(self):
+        self.mip = Signal(32)
+
+
+
+class MInfo:
+    def __init__(self, comb):
+        self.comb = comb
+        # TODO
+        self.cycle_counter   = Signal(64); # TODO: implement cycle_counter
+        self.time_counter    = Signal(64); # TODO: implement time_counter
+        self.instret_counter = Signal(64); # TODO: implement instret_counter
+
+        self.mvendorid = Signal(32)
+        self.marchid = Signal(32)
+        self.mimpid = Signal(32)
+        self.mhartid = Signal(32)
+        self.comb += self.mvendorid.eq(Constant(0, 32))
+        self.comb += self.marchid.eq(Constant(0, 32))
+        self.comb += self.mimpid.eq(Constant(0, 32))
+        self.comb += self.mhartid.eq(Constant(0, 32))
+
+
+class CPUHandleCSR(Module):
+    """
+    """
+
+    def __init__(self):
+        Module.__init__(self)
+        self.clk = ClockSignal()
+        self.reset = ResetSignal()
+
+        self.dc_funct3 = Signal(3)
+        self.mtvec = Signal(32)
+        self.csr_number = Signal(12)
+        self.csr_writes = Signal()
+
+        self.input_value = Signal(32)
+        self.output_value = Signal(32)
+
+        mstatus = MStatus(self.comb, self.sync)
+        m = M(self.comb, self.sync)
+        mie = MIE(self.comb, self.sync)
+        mip = MIP()
+        self.mie = mstatus.mie
+        self.mepc = m.mepc
+        self.mcause = m.mcause
+
+        minfo = MInfo(self.comb)
+        misa = Misa(self.comb, self.sync)
+
+        ms = Instance("CPUMStatus", name="cpu_mstatus",
+            o_mstatus = mstatus.mstatus,
+            i_mpie = mstatus.mpie,
+            i_mie = mstatus.mie)
+
+        self.specials += ms
+
+        mp = Instance("CPUMIP", name="cpu_mip",
+            o_mip = mip.mip)
+
+        self.specials += mp
+
+        mii = Instance("CPUMIE", name="cpu_mie",
+            o_mie = mie.mie,
+            i_meie = mie.meie,
+            i_mtie = mie.mtie,
+            i_msie = mie.msie)
+
+        self.specials += mii
+
+        written_value = Signal(32)
+
+        c = {}
+
+        # cycle
+        c[csr_cycle]  = self.output_value.eq(minfo.cycle_counter[0:32])
+        c[csr_cycleh] = self.output_value.eq(minfo.cycle_counter[32:64])
+        # time
+        c[csr_time]  = self.output_value.eq(minfo.time_counter[0:32])
+        c[csr_timeh] = self.output_value.eq(minfo.time_counter[32:64])
+        # instret
+        c[csr_instret]  = self.output_value.eq(minfo.instret_counter[0:32])
+        c[csr_instreth] = self.output_value.eq(minfo.instret_counter[32:64])
+        # mvendorid/march/mimpl/mhart
+        c[csr_mvendorid] = self.output_value.eq(minfo.mvendorid)
+        c[csr_marchid  ] = self.output_value.eq(minfo.marchid  )
+        c[csr_mimpid   ] = self.output_value.eq(minfo.mimpid   )
+        c[csr_mhartid  ] = self.output_value.eq(minfo.mhartid  )
+        # misa
+        c[csr_misa     ] = self.output_value.eq(misa.misa)
+        # mstatus
+        c[csr_mstatus  ] = [
+            self.output_value.eq(mstatus.mstatus),
+            self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
+                                                  written_value),
+            mstatus.mpie.eq(written_value[7]),
+            mstatus.mie.eq(written_value[3])
+        ]
+        # mie
+        c[csr_mie      ] = [
+            self.output_value.eq(mie.mie),
+            self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
+                                                  written_value),
+            mie.meie.eq(written_value[11]),
+            mie.mtie.eq(written_value[7]),
+            mie.msie.eq(written_value[3]),
+        ]
+        # mtvec
+        c[csr_mtvec    ] = self.output_value.eq(self.mtvec)
+        # mscratch
+        c[csr_mscratch ] = [
+            self.output_value.eq(m.mscratch),
+            self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
+                                                  written_value),
+            If(self.csr_writes,
+                m.mscratch.eq(written_value),
+            )
+        ]
+        # mepc
+        c[csr_mepc ] = [
+            self.output_value.eq(m.mepc),
+            self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
+                                                  written_value),
+            If(self.csr_writes,
+                m.mepc.eq(written_value),
+            )
+        ]
+
+        # mcause
+        c[csr_mcause ] = [
+            self.output_value.eq(m.mcause),
+            self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
+                                                  written_value),
+            If(self.csr_writes,
+                m.mcause.eq(written_value),
+            )
+        ]
+
+        # mip
+        c[csr_mip  ] = [
+            self.output_value.eq(mip.mip),
+            self.evaluate_csr_funct3_op(self.dc_funct3, self.output_value,
+                                                  written_value),
+        ]
+
+        self.sync += Case(self.csr_number, c)
+
+    def evaluate_csr_funct3_op(self, funct3, previous, written):
+        c = { "default": written.eq(Constant(0, 32))}
+        for f in [F3.csrrw, F3.csrrwi]:
+            c[f] = written.eq(self.input_value)
+        for f in [F3.csrrs, F3.csrrsi]:
+            c[f] = written.eq(self.input_value | previous)
+        for f in [F3.csrrc, F3.csrrci]:
+            c[f] = written.eq(~self.input_value & previous)
+        return Case(funct3, c)
+
+
+if __name__ == "__main__":
+    example = CPUHandleCSR()
+    print(verilog.convert(example,
+         {
+            example.dc_funct3,
+            example.mtvec,
+            example.csr_number,
+            example.csr_writes,
+            example.input_value,
+            example.output_value,
+            example.mie,
+            example.mepc,
+            example.mcause,
+           }))