add in MMU and DCache into MMU FSM
[soc.git] / src / soc / fu / mmu / fsm.py
1 from nmigen import Elaboratable, Module, Signal, Shape, unsigned, Cat, Mux
2 from soc.fu.mmu.pipe_data import MMUInputData, MMUOutputData, MMUPipeSpec
3 from nmutil.singlepipe import ControlBase
4
5 from soc.experiment.mmu import MMU
6 from soc.experiment.dcache import DCache
7
8
9 class FSMMMUStage(ControlBase):
10 def __init__(self, pspec):
11 super().__init__()
12 self.pspec = pspec
13 # set up p/n data
14 self.p.data_i = MMUInputData(pspec)
15 self.n.data_o = MMUOutputData(pspec)
16
17 # this Function Unit is extremely unusual in that it actually stores a
18 # "thing" rather than "processes inputs and produces outputs". hence
19 # why it has to be a FSM. linking up LD/ST however is going to have
20 # to be done back in Issuer (or Core)
21
22 self.mmu = MMU()
23 self.dcache = DCache()
24
25
26 def elaborate(self, platform):
27 m = super().elaborate(platform)
28
29 # link mmu and dcache together
30 m.submodules.dcache = dcache = self.dcache
31 m.submodules.mmu = mmu = self.mmu
32 m.d.comb += dcache.m_in.eq(mmu.d_out)
33 m.d.comb += mmu.d_in.eq(dcache.m_out)
34
35 data_i = self.p.data_i
36 data_o = self.n.data_o
37
38 m.d.comb += self.n.valid_o.eq(~self.empty & self.div_state_next.o.done)
39 m.d.comb += self.p.ready_o.eq(self.empty)
40 m.d.sync += self.saved_state.eq(self.div_state_next.o)
41
42 with m.If(self.empty):
43 with m.If(self.p.valid_i):
44 m.d.sync += self.empty.eq(0)
45 m.d.sync += self.saved_input_data.eq(data_i)
46 with m.Else():
47 m.d.comb += [
48 with m.If(self.n.ready_i & self.n.valid_o):
49 m.d.sync += self.empty.eq(1)
50
51 return m
52
53 def __iter__(self):
54 yield from self.p
55 yield from self.n
56
57 def ports(self):
58 return list(self)