From: Luke Kenneth Casson Leighton Date: Sun, 22 Mar 2020 11:33:44 +0000 (+0000) Subject: start putting LDSTSplitter together X-Git-Tag: div_pipeline~1656 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f58721bc872b0e0b487a14dfa6a816774b433892;p=soc.git start putting LDSTSplitter together --- diff --git a/src/soc/scoreboard/addr_split.py b/src/soc/scoreboard/addr_split.py index ef136763..40f4569c 100644 --- a/src/soc/scoreboard/addr_split.py +++ b/src/soc/scoreboard/addr_split.py @@ -1,35 +1,100 @@ # LDST Address Splitter. For misaligned address crossing cache line boundary -from nmigen import Elaboratable, Module, Signal, Record +from nmigen import Elaboratable, Module, Signal, Record, Array from nmutil.latch import SRLatch, latchregister from nmigen.compat.sim import run_simulation from nmigen.cli import verilog, rtlil -from soc.scoreboard.addr_match import LenSplitter -from nmutil.queue import Queue +from soc.scoreboard.addr_match import LenExpand +#from nmutil.queue import Queue +class LDData(Record): + def __init__(self, dwidth): + Record.__init__(self, (('err', 1), ('data', dwidth))) -class LDQueue(Elaboratable): + +class LDLatch(Elaboratable): def __init__(self, dwidth, awidth, mlen): self.addr_i = Signal(awidth, reset_less=True) self.mask_i = Signal(mlen, reset_less=True) - self.ld_i = Record((('err', 1), ('data', dwidth)) - self.ld_o = Record((('err', 1), ('data', dwidth)) + self.valid_i = Signal(reset_less=True) + self.ld_i = LDData(dwidth) + self.ld_o = LDData(dwidth) + self.valid_o = Signal(reset_less=True) def elaborate(self, platform): m = Module() comb = m.d.comb - m.submodules.q = q = Queue(width=self.ld_o.shape()[0], 1, fwft=True) + m.submodules.in_l = in_l = SRLatch(sync=False, name="in_l") + + comb += self.valid_o.eq(in_l.q & self.valid_i) + latchregister(m, self.ld_i, self.ld_o, in_l.q & self.valid_o, "ld_i_r") + + return m class LDSTSplitter(Elaboratable): def __init__(self, dwidth, awidth, dlen): + self.dwidth, self.awidth, self.dlen = dwidth, awidth, dlen self.addr_i = Signal(awidth, reset_less=True) self.len_i = Signal(dlen, reset_less=True) self.is_ld_i = Signal(reset_less=True) - self.ld_data_o = Signal(dwidth, reset_less=True) + self.ld_data_o = LDData(dwidth) + self.ld_valid_i = Signal(reset_less=True) + self.valid_o = Signal(2, reset_less=True) + self.ld_data_i = Array((LDData(dwidth), LDData(dwidth))) + + #self.is_st_i = Signal(reset_less=True) + #self.st_data_i = Signal(dwidth, reset_less=True) + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + dlen = self.dlen + mlen = 1 << dlen + m.submodules.ld1 = ld1 = LDLatch(self.dwidth, self.awidth-dlen, mlen) + m.submodules.ld2 = ld2 = LDLatch(self.dwidth, self.awidth-dlen, mlen) + m.submodules.lenexp = lenexp = LenExpand(self.dlen) + + # set up len-expander, len to mask. ld1 gets first bit, ld2 gets rest + comb += lenexp.addr_i.eq(self.addr_i) + comb += lenexp.len_i.eq(self.len_i) + mask1 = lenexp.lexp_o[0:mlen] + mask2 = lenexp.lexp_o[mlen:] + + # set up new address records: addr1 is "as-is", addr2 is +1 + comb += ld1.addr_i.eq(self.addr_i[dlen:]) + comb += ld2.addr_i.eq(self.addr_i[dlen:] + 1) # TODO exception if rolls + + # set up connections to LD-split. note: not active if mask is zero + for i, (ld, mask) in enumerate(((ld1, mask1), + (ld2, mask2))): + comb += ld.valid_i.eq(self.ld_valid_i) + comb += self.valid_o[i].eq(ld.valid_o & (mask != 0)) + + return m + + def __iter__(self): + yield self.addr_i + yield self.len_i + yield self.is_ld_i + yield self.ld_data_o.err + yield self.ld_data_o.data + yield self.ld_valid_i + yield self.valid_o + for i in range(2): + yield self.ld_data_i[i].err + yield self.ld_data_i[i].data + + def ports(self): + return list(self) + + +if __name__ == '__main__': + dut = LDSTSplitter(32, 48, 3) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("ldst_splitter.il", "w") as f: + f.write(vl) - self.is_st_i = Signal(reset_less=True) - self.st_data_i = Signal(dwidth, reset_less=True)