From: Luke Kenneth Casson Leighton Date: Tue, 27 Nov 2018 08:55:10 +0000 (+0000) Subject: experiment with separate cpu handle csr module X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8afa8122db9356f3f210731e8b61b1e82dd7215d;p=rv32.git experiment with separate cpu handle csr module --- diff --git a/cpu_handle_csr.py b/cpu_handle_csr.py new file mode 100644 index 0000000..f2f5788 --- /dev/null +++ b/cpu_handle_csr.py @@ -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, + }))