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
5 from soc
.experiment
.mmu
import MMU
6 from soc
.experiment
.dcache
import DCache
8 from soc
.decoder
.power_fields
import DecodeFields
9 from soc
.decoder
.power_fieldsn
import SignalBitRange
10 from soc
.decoder
.power_decoder2
import decode_spr_num
11 from soc
.decoder
.power_enums
import MicrOp
, SPR
, XER_bits
14 class FSMMMUStage(ControlBase
):
15 def __init__(self
, pspec
):
20 self
.p
.data_i
= MMUInputData(pspec
)
21 self
.n
.data_o
= MMUOutputData(pspec
)
23 # this Function Unit is extremely unusual in that it actually stores a
24 # "thing" rather than "processes inputs and produces outputs". hence
25 # why it has to be a FSM. linking up LD/ST however is going to have
26 # to be done back in Issuer (or Core)
29 self
.dcache
= DCache()
31 # make life a bit easier in Core
32 self
.pspec
.mmu
= self
.mmu
33 self
.pspec
.dcache
= self
.dcache
35 # for SPR field number access
37 self
.fields
= DecodeFields(SignalBitRange
, [i
.ctx
.op
.insn
])
38 self
.fields
.create_specs()
40 def elaborate(self
, platform
):
41 m
= super().elaborate(platform
)
43 # link mmu and dcache together
44 m
.submodules
.dcache
= dcache
= self
.dcache
45 m
.submodules
.mmu
= mmu
= self
.mmu
46 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
)
47 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
)
49 data_i
, data_o
= self
.p
.data_i
, self
.n
.data_o
50 a_i
, b_i
= data_i
.ra
, data_i
.rb
56 m
.d
.comb
+= self
.n
.valid_o
.eq(busy
& done
)
57 m
.d
.comb
+= self
.p
.ready_o
.eq(~busy
)
59 # take copy of X-Form SPR field
60 x_fields
= self
.fields
.FormXFX
61 spr
= Signal(len(x_fields
.SPR
))
62 comb
+= spr
.eq(decode_spr_num(x_fields
.SPR
))
65 with m
.If(self
.p
.valid_i
):
66 m
.d
.sync
+= busy
.eq(1)
70 with m
.Case(OP_MTSPR
):
71 # subset SPR: first check a few bits
72 with m
.If(~spr
[9] & ~spr
[5]):
74 comb
+= dsisr
.eq(a_i
[:32])
78 # pass it over to the MMU instead
80 # kick the MMU and wait for it to complete
81 comb
+= mmu
.m_in
.valid
.eq(1) # start
82 comb
+= mmu
.m_in
.mtspr
.eq(1) # mtspr mode
83 comb
+= mmu
.m_in
.sprn
.eq(spr
) # which SPR
84 comb
+= mmu
.m_in
.rs
.eq(a_i
) # incoming operand (RS)
85 comb
+= done
.eq(mmu
.m_out
.done
) # zzzz
88 # activate dcbz mode (spec: v3.0B p850)
89 comb
+= dcache
.d_in
.valid
.eq(1) # start
90 comb
+= dcache
.d_in
.dcbz
.eq(1) # dcbz mode
91 comb
+= dcache
.d_in
.addr
.eq(a_i
+ b_i
) # addr is (RA|0) + RB
92 comb
+= done
.eq(dcache
.d_out
.done
) # zzzz
94 with m
.If(self
.n
.ready_i
& self
.n
.valid_o
):
95 m
.d
.sync
+= busy
.eq(0)