From 4d24d138f664791860d1c1059a2a0457046007e9 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 26 May 2020 12:44:18 +0100 Subject: [PATCH] continue virtual regfile port --- src/soc/regfile/virtual_port.py | 101 ++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/src/soc/regfile/virtual_port.py b/src/soc/regfile/virtual_port.py index 7f02ecc2..e05b9f67 100644 --- a/src/soc/regfile/virtual_port.py +++ b/src/soc/regfile/virtual_port.py @@ -1,25 +1,104 @@ +"""VirtualRegPort - terrible name for a complex register class + +This Register file has a "virtual" port on it which is effectively +the ability to read and write to absolutely every bit in the regfile +at once. This is achieved by having N actual read and write ports +if there are N registers. That results in a staggeringly high gate count +with full crossbars, so attempting to do use this for anything other +than really small registers (XER, CR) is a seriously bad idea. +""" + from nmigen.compat.sim import run_simulation from nmigen.cli import verilog, rtlil from nmigen import Cat, Const, Array, Signal, Elaboratable, Module from nmutil.iocontrol import RecordObject -from soc.regfile import RegFileArray +from soc.regfile.regfile import RegFileArray -class VirtualPort(RegFileArray): +class VirtualRegPort(RegFileArray): def __init__(self, bitwidth, n_regs): self.bitwidth = bitwidth self.nregs = n_regs - self.regwidth = bitwidth / n_regs - self.w_ports = [ self.write_port(f"{i}") for i in range(n_regs) ] - self.r_ports = [ self.read_port(f"{i}") for i in range(n_regs) ] - self.extra_wr.append(RecordObject([("ren", nregs), ("data_o", bitwidth, name="extra")])) - self.extra_rd.append(RecordObject([("ren", nregs), ("data_o", bitwidth, name="extra")])) + self.regwidth = bitwidth // n_regs + super().__init__(self.regwidth, n_regs) + + # create suite of 8 write ports + self.w_ports = [ self.write_port(f"extw_{i}") for i in range(n_regs) ] + self.r_ports = [ self.read_port(f"extr_{i}") for i in range(n_regs) ] + # now start again: one set will be internal, the other external + self._rdports = [] + self._wrports = [] + for i in range(n_regs): + self.write_port(f"intw_{i}") + self.read_port(f"intr_{i}") + # and append the "full" depth variant to the "external" ports + self.w_ports.append(RecordObject([("wen", n_regs), + ("data_i", bitwidth)], # *full* wid + name="full")) + self.r_ports.append(RecordObject([("ren", n_regs), + ("data_o", bitwidth)], # *full* wid + name="full")) def elaborate(self, platform): m = Module() - with m.If(self._get_en_sig(extra, "ren") == 0) - pass - with m.Else() - "send data through the corresponding lower indexed ports" + comb, sync = m.d.comb, m.d.sync + + # connect up: detect if read is requested on large (full) port + # nothing fancy needed because reads are same-cycle + rlast = self.r_ports[-1] + print (rlast) + with m.If(self._get_en_sig([rlast], "ren") != 0): + # wire up the enable signals and accumulate the data + l = [] + print (self._rdports) + for i, port in enumerate(self._rdports[:-1]): + print (port) + comb += port.ren.eq(1<