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 from nmutil
.util
import rising_edge
6 from soc
.experiment
.mmu
import MMU
7 from soc
.experiment
.dcache
import DCache
9 from soc
.decoder
.power_fields
import DecodeFields
10 from soc
.decoder
.power_fieldsn
import SignalBitRange
11 from soc
.decoder
.power_decoder2
import decode_spr_num
12 from soc
.decoder
.power_enums
import MicrOp
, SPR
, XER_bits
14 from soc
.experiment
.pimem
import PortInterface
16 class FSMMMUStage(ControlBase
):
17 def __init__(self
, pspec
):
22 self
.p
.data_i
= MMUInputData(pspec
)
23 self
.n
.data_o
= MMUOutputData(pspec
)
25 # incoming PortInterface
26 self
.pi
= PortInterface("mmupi")
28 # this Function Unit is extremely unusual in that it actually stores a
29 # "thing" rather than "processes inputs and produces outputs". hence
30 # why it has to be a FSM. linking up LD/ST however is going to have
31 # to be done back in Issuer (or Core)
34 self
.dcache
= DCache()
36 # make life a bit easier in Core
37 self
.pspec
.mmu
= self
.mmu
38 self
.pspec
.dcache
= self
.dcache
40 # for SPR field number access
42 self
.fields
= DecodeFields(SignalBitRange
, [i
.ctx
.op
.insn
])
43 self
.fields
.create_specs()
45 def elaborate(self
, platform
):
46 m
= super().elaborate(platform
)
49 # link mmu and dcache together
50 m
.submodules
.dcache
= dcache
= self
.dcache
51 m
.submodules
.mmu
= mmu
= self
.mmu
52 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
)
53 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
)
54 l_in
, l_out
= mmu
.l_in
, mmu
.l_out
55 d_in
, d_out
= dcache
.d_in
, dcache
.d_out
57 data_i
, data_o
= self
.p
.data_i
, self
.n
.data_o
58 a_i
, b_i
, o
= data_i
.ra
, data_i
.rb
, data_o
.o
61 # TODO: link these SPRs somewhere
68 m
.d
.comb
+= self
.n
.valid_o
.eq(busy
& done
)
69 m
.d
.comb
+= self
.p
.ready_o
.eq(~busy
)
71 # take copy of X-Form SPR field
72 x_fields
= self
.fields
.FormXFX
73 spr
= Signal(len(x_fields
.SPR
))
74 comb
+= spr
.eq(decode_spr_num(x_fields
.SPR
))
76 # ok so we have to "pulse" the MMU (or dcache) rather than
77 # hold the valid hi permanently. guess what this does...
80 m
.d
.comb
+= blip
.eq(rising_edge(m
, valid
))
83 with m
.If(self
.p
.valid_i
):
84 m
.d
.sync
+= busy
.eq(1)
87 # based on the Micro-Op, we work out which of MMU or DCache
88 # should "action" the operation. one of MMU or DCache gets
89 # enabled ("valid") and we twiddle our thumbs until it
93 with m
.Case(MicrOp
.OP_MTSPR
):
94 # subset SPR: first check a few bits
95 with m
.If(~spr
[9] & ~spr
[5]):
97 comb
+= dsisr
.eq(a_i
[:32])
101 # pass it over to the MMU instead
103 # blip the MMU and wait for it to complete
104 comb
+= valid
.eq(1) # start "pulse"
105 comb
+= l_in
.valid
.eq(blip
) # start
106 comb
+= l_in
.mtspr
.eq(1) # mtspr mode
107 comb
+= l_in
.sprn
.eq(spr
) # which SPR
108 comb
+= l_in
.rs
.eq(a_i
) # incoming operand (RS)
109 comb
+= done
.eq(l_out
.done
) # zzzz
111 with m
.Case(MicrOp
.OP_MFSPR
):
112 # subset SPR: first check a few bits
113 with m
.If(~spr
[9] & ~spr
[5]):
115 comb
+= o
.data
.eq(dsisr
)
117 comb
+= o
.data
.eq(dar
)
120 # pass it over to the MMU instead
122 # blip the MMU and wait for it to complete
123 comb
+= valid
.eq(1) # start "pulse"
124 comb
+= l_in
.valid
.eq(blip
) # start
125 comb
+= l_in
.mtspr
.eq(1) # mtspr mode
126 comb
+= l_in
.sprn
.eq(spr
) # which SPR
127 comb
+= l_in
.rs
.eq(a_i
) # incoming operand (RS)
128 comb
+= o
.data
.eq(l_out
.sprval
) # SPR from MMU
129 comb
+= o
.ok
.eq(l_out
.done
) # only when l_out valid
130 comb
+= done
.eq(l_out
.done
) # zzzz
132 with m
.Case(MicrOp
.OP_DCBZ
):
133 # activate dcbz mode (spec: v3.0B p850)
134 comb
+= valid
.eq(1) # start "pulse"
135 comb
+= d_in
.valid
.eq(blip
) # start
136 comb
+= d_in
.dcbz
.eq(1) # dcbz mode
137 comb
+= d_in
.addr
.eq(a_i
+ b_i
) # addr is (RA|0) + RB
138 comb
+= done
.eq(l_out
.done
) # zzzz
140 with m
.Case(MicrOp
.OP_TLBIE
):
141 # pass TLBIE request to MMU (spec: v3.0B p1034)
142 # note that the spr is *not* an actual spr number, it's
143 # just that those bits happen to match with field bits
145 comb
+= valid
.eq(1) # start "pulse"
146 comb
+= l_in
.valid
.eq(blip
) # start
147 comb
+= l_in
.tlbie
.eq(1) # mtspr mode
148 comb
+= l_in
.sprn
.eq(spr
) # use sprn to send insn bits
149 comb
+= l_in
.addr
.eq(b_i
) # incoming operand (RB)
150 comb
+= done
.eq(l_out
.done
) # zzzz
152 with m
.If(self
.n
.ready_i
& self
.n
.valid_o
):
153 m
.d
.sync
+= busy
.eq(0)