X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fexperiment%2Fpi2ls.py;h=f9059f05c1b6edd48c082381a06b342728b48a7c;hb=a3d71a5a5b6377d1e028131c75bc2474b117c8b3;hp=97a42c860a462b75f2e834ee431ac3bc75e1d2c0;hpb=7400c181c44d9db72b44772acbd85fa533375213;p=soc.git diff --git a/src/soc/experiment/pi2ls.py b/src/soc/experiment/pi2ls.py index 97a42c86..f9059f05 100644 --- a/src/soc/experiment/pi2ls.py +++ b/src/soc/experiment/pi2ls.py @@ -25,44 +25,116 @@ from soc.minerva.units.loadstore import LoadStoreUnitInterface from soc.experiment.pimem import PortInterface from soc.scoreboard.addr_match import LenExpand +from soc.experiment.pimem import PortInterfaceBase +from nmigen.utils import log2_int from nmigen import Elaboratable, Module, Signal -class Pi2LSUI(Elaboratable): +class Pi2LSUI(PortInterfaceBase): - def __init__(self, name, regwid=64, addrwid=48): - self.addrbits = 4 - self.pi = PortInterface(name="%s_pi", regwid, addrwid) - self.lsui = LoadStoreUnitInterface(addrwid, self.addrbits, regwid) + def __init__(self, name, lsui=None, + data_wid=64, mask_wid=8, addr_wid=48): + print ("pi2lsui reg mask addr", data_wid, mask_wid, addr_wid) + super().__init__(data_wid, addr_wid) + if lsui is None: + lsui = LoadStoreUnitInterface(addr_wid, self.addrbits, data_wid) + self.lsui = lsui + + def set_wr_addr(self, m, addr, mask): + m.d.comb += self.lsui.x_mask_i.eq(mask) + m.d.comb += self.lsui.x_addr_i.eq(addr) + + def set_rd_addr(self, m, addr, mask): + m.d.comb += self.lsui.x_mask_i.eq(mask) + m.d.comb += self.lsui.x_addr_i.eq(addr) + + def set_wr_data(self, m, data, wen): # mask already done in addr setup + m.d.comb += self.lsui.x_st_data_i.eq(data) + return ~self.lsui.x_busy_o + + def get_rd_data(self, m): + return self.lsui.m_ld_data_o, ~self.lsui.x_busy_o + + def elaborate(self, platform): + m = super().elaborate(platform) + + return m + + +class Pi2LSUI1(Elaboratable): + + def __init__(self, name, pi=None, lsui=None, + data_wid=64, mask_wid=8, addr_wid=48): + print ("pi2lsui reg mask addr", data_wid, mask_wid, addr_wid) + self.addrbits = mask_wid + if pi is None: + piname = "%s_pi" % name + pi = PortInterface(piname, regwid=data_wid, addrwid=addr_wid) + self.pi = pi + if lsui is None: + lsui = LoadStoreUnitInterface(addr_wid, self.addrbits, data_wid) + self.lsui = lsui def splitaddr(self, addr): """split the address into top and bottom bits of the memory granularity """ return addr[:self.addrbits], addr[self.addrbits:] + def connect_port(self, inport): + return self.pi.connect_port(inport) + def elaborate(self, platform): m = Module() pi, lsui, addrbits = self.pi, self.lsui, self.addrbits - m.submodules.lenexp = lenexp = LenExpand(self.addrbits, 8) + m.submodules.lenexp = lenexp = LenExpand(log2_int(self.addrbits), 8) + + ld_in_progress = Signal(reset=0) + st_in_progress = Signal(reset=0) m.d.comb += lsui.x_ld_i.eq(pi.is_ld_i) m.d.comb += lsui.x_st_i.eq(pi.is_st_i) + m.d.comb += pi.busy_o.eq(pi.is_ld_i | pi.is_st_i)#lsui.x_busy_o) + + lsbaddr, msbaddr = self.splitaddr(pi.addr.data) + m.d.comb += lenexp.len_i.eq(pi.data_len) + m.d.comb += lenexp.addr_i.eq(lsbaddr) # LSBs of addr + m.d.comb += lsui.x_addr_i.eq(pi.addr.data) # XXX hmmm... with m.If(pi.addr.ok): # expand the LSBs of address plus LD/ST len into 16-bit mask - m.d.comb += lenexp.len_i.eq(pi.data_len) - m.d.comb += lenexp.addr_i.eq(pi.addr.data[addrbits]) # LSBs of addr m.d.comb += lsui.x_mask_i.eq(lenexp.lexp_o) # pass through the address, indicate "valid" - m.d.comb += lsui.x_addr_i.eq(pi.addr.data) # full address m.d.comb += lsui.x_valid_i.eq(1) + # indicate "OK" - XXX should be checking address valid + m.d.comb += pi.addr_ok_o.eq(1) + + with m.If(~lsui.x_busy_o & pi.is_st_i & pi.addr.ok): + m.d.sync += st_in_progress.eq(1) with m.If(pi.is_ld_i): - m.d.comb += pi.ld.data.eq(lsui.m_ld_data_o) - #m.d.comb += pi.ld.ok.eq(TODO) + # shift/mask out the loaded data + m.d.comb += pi.ld.data.eq((lsui.m_ld_data_o & lenexp.rexp_o) >> + (lenexp.addr_i*8)) + # remember we're in the process of loading + with m.If(pi.addr.ok): + m.d.sync += ld_in_progress.eq(1) + + # If a load happened on the previous cycle and the memory is + # not busy, that means it returned the data from the load. In + # that case ld.ok should be set andwe can clear the + # ld_in_progress flag + with m.If(ld_in_progress & ~lsui.x_busy_o): + m.d.comb += pi.ld.ok.eq(1) + m.d.sync += ld_in_progress.eq(0) + with m.Else(): + m.d.comb += pi.ld.ok.eq(0) with m.If(pi.is_st_i & pi.st.ok): - m.d.comb += lsui.x_st_data_i.eq(pi.st.data) + m.d.comb += lsui.x_st_data_i.eq(pi.st.data << (lenexp.addr_i*8)) + with m.If(st_in_progress): + m.d.sync += st_in_progress.eq(0) + with m.Else(): + m.d.comb += pi.busy_o.eq(0) return m