1 # LDST Address Splitter. For misaligned address crossing cache line boundary
3 from nmigen
import Elaboratable
, Module
, Signal
, Record
, Array
4 from nmutil
.latch
import SRLatch
, latchregister
5 from nmigen
.compat
.sim
import run_simulation
6 from nmigen
.cli
import verilog
, rtlil
8 from soc
.scoreboard
.addr_match
import LenExpand
9 #from nmutil.queue import Queue
12 def __init__(self
, dwidth
):
13 Record
.__init
__(self
, (('err', 1), ('data', dwidth
)))
16 class LDLatch(Elaboratable
):
18 def __init__(self
, dwidth
, awidth
, mlen
):
19 self
.addr_i
= Signal(awidth
, reset_less
=True)
20 self
.mask_i
= Signal(mlen
, reset_less
=True)
21 self
.valid_i
= Signal(reset_less
=True)
22 self
.ld_i
= LDData(dwidth
)
23 self
.ld_o
= LDData(dwidth
)
24 self
.valid_o
= Signal(reset_less
=True)
26 def elaborate(self
, platform
):
29 m
.submodules
.in_l
= in_l
= SRLatch(sync
=False, name
="in_l")
31 comb
+= self
.valid_o
.eq(in_l
.q
& self
.valid_i
)
32 latchregister(m
, self
.ld_i
, self
.ld_o
, in_l
.q
& self
.valid_o
, "ld_i_r")
37 class LDSTSplitter(Elaboratable
):
39 def __init__(self
, dwidth
, awidth
, dlen
):
40 self
.dwidth
, self
.awidth
, self
.dlen
= dwidth
, awidth
, dlen
41 self
.addr_i
= Signal(awidth
, reset_less
=True)
42 self
.len_i
= Signal(dlen
, reset_less
=True)
43 self
.is_ld_i
= Signal(reset_less
=True)
44 self
.ld_data_o
= LDData(dwidth
)
45 self
.ld_valid_i
= Signal(reset_less
=True)
46 self
.valid_o
= Signal(2, reset_less
=True)
47 self
.ld_data_i
= Array((LDData(dwidth
), LDData(dwidth
)))
49 #self.is_st_i = Signal(reset_less=True)
50 #self.st_data_i = Signal(dwidth, reset_less=True)
52 def elaborate(self
, platform
):
57 m
.submodules
.ld1
= ld1
= LDLatch(self
.dwidth
, self
.awidth
-dlen
, mlen
)
58 m
.submodules
.ld2
= ld2
= LDLatch(self
.dwidth
, self
.awidth
-dlen
, mlen
)
59 m
.submodules
.lenexp
= lenexp
= LenExpand(self
.dlen
)
61 # set up len-expander, len to mask. ld1 gets first bit, ld2 gets rest
62 comb
+= lenexp
.addr_i
.eq(self
.addr_i
)
63 comb
+= lenexp
.len_i
.eq(self
.len_i
)
64 mask1
= lenexp
.lexp_o
[0:mlen
]
65 mask2
= lenexp
.lexp_o
[mlen
:]
67 # set up new address records: addr1 is "as-is", addr2 is +1
68 comb
+= ld1
.addr_i
.eq(self
.addr_i
[dlen
:])
69 comb
+= ld2
.addr_i
.eq(self
.addr_i
[dlen
:] + 1) # TODO exception if rolls
71 # set up connections to LD-split. note: not active if mask is zero
72 for i
, (ld
, mask
) in enumerate(((ld1
, mask1
),
74 comb
+= ld
.valid_i
.eq(self
.ld_valid_i
)
75 comb
+= self
.valid_o
[i
].eq(ld
.valid_o
& (mask
!= 0))
83 yield self
.ld_data_o
.err
84 yield self
.ld_data_o
.data
88 yield self
.ld_data_i
[i
].err
89 yield self
.ld_data_i
[i
].data
95 if __name__
== '__main__':
96 dut
= LDSTSplitter(32, 48, 3)
97 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
98 with
open("ldst_splitter.il", "w") as f
: