From: Luke Kenneth Casson Leighton Date: Mon, 26 Nov 2018 23:58:55 +0000 (+0000) Subject: break out cpu load/store calculation into separate module X-Git-Url: https://git.libre-soc.org/?p=rv32.git;a=commitdiff_plain;h=6f7722f2f5a85f01d1f9ba8567e7d9cae9e0112b break out cpu load/store calculation into separate module --- diff --git a/cpu_loadstore_calc.py b/cpu_loadstore_calc.py new file mode 100644 index 0000000..1781af0 --- /dev/null +++ b/cpu_loadstore_calc.py @@ -0,0 +1,138 @@ +""" +/* + * 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 CPULoadStoreCalc(Module): + """ + """ + + def get_ls_misaligned(self, ls, funct3, load_store_address_low_2): + """ returns whether a load/store is misaligned + """ + return Case(funct3[:2], + { F3.sb: ls.eq(Constant(0)), + F3.sh: ls.eq(load_store_address_low_2[0] != 0), + F3.sw: ls.eq(load_store_address_low_2[0:2] != Constant(0, 2)), + "default": ls.eq(Constant(1)) + }) + + def __init__(self): + Module.__init__(self) + self.clk = ClockSignal() + self.reset = ResetSignal() + self.dc_immediate = Signal(32) + self.dc_funct3 = Signal(3) + self.rs1 = Signal(32) + self.rs2 = Signal(32) + self.rw_address = Signal(32) + self.rw_data_in = Signal(32) + self.rw_data_out = Signal(32) + + self.load_store_address = Signal(32) + self.load_store_address_low_2 = Signal(2) + self.load_store_misaligned = Signal() + self.loaded_value = Signal(32) + + self.comb += self.load_store_address.eq(self.dc_immediate + self.rs1) + self.comb += self.load_store_address_low_2.eq( + self.dc_immediate[:2] + self.rs1[:2]) + + lsa = self.get_ls_misaligned(self.load_store_misaligned, self.dc_funct3, + self.load_store_address_low_2) + self.comb += lsa + + # XXX rwaddr not 31:2 any more + self.comb += self.rw_address.eq(self.load_store_address[2:]) + + # XXX not obvious + b3 = Mux(self.load_store_address_low_2[1], + Mux(self.load_store_address_low_2[0], self.rs2[0:8], + self.rs2[8:16]), + Mux(self.load_store_address_low_2[0], self.rs2[16:24], + self.rs2[24:32])) + b2 = Mux(self.load_store_address_low_2[1], self.rs2[0:8], + self.rs2[16:24]) + b1 = Mux(self.load_store_address_low_2[0], self.rs2[0:8], + self.rs2[8:16]) + b0 = self.rs2[0:8] + + self.comb += self.rw_data_in.eq(Cat(b0, b1, b2, b3)) + + # XXX not obvious + unmasked_loaded_value = Signal(32) + + b0 = Mux(self.load_store_address_low_2[1], + Mux(self.load_store_address_low_2[0], self.rw_data_out[24:32], + self.rw_data_out[16:24]), + Mux(self.load_store_address_low_2[0], self.rw_data_out[15:8], + self.rw_data_out[0:8])) + b1 = Mux(self.load_store_address_low_2[1], self.rw_data_out[24:31], + self.rw_data_out[8:16]) + b23 = self.rw_data_out[16:32] + + self.comb += unmasked_loaded_value.eq(Cat(b0, b1, b23)) + + # XXX not obvious + + b0 = unmasked_loaded_value[0:8] + b1 = Mux(self.dc_funct3[0:2] == 0, + Replicate(~self.dc_funct3[2] & unmasked_loaded_value[7], 8), + unmasked_loaded_value[8:16]) + b2 = Mux(self.dc_funct3[1] == 0, + Replicate(~self.dc_funct3[2] & + Mux(self.dc_funct3[0], unmasked_loaded_value[15], + unmasked_loaded_value[7]), + 16), + unmasked_loaded_value[16:32]) + + self.comb += self.loaded_value.eq(Cat(b0, b1, b2)) + + +if __name__ == "__main__": + example = CPULoadStoreCalc() + print(verilog.convert(example, + { + example.dc_immediate, + example.dc_funct3, + example.rs1, + example.rs2, + example.rw_address, + example.rw_data_in, + example.rw_data_out, + example.load_store_address, + example.load_store_address_low_2, + example.load_store_misaligned, + example.loaded_value, + }))