Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / fu / spr / main_stage.py
1 """SPR Pipeline
2
3 * https://bugs.libre-soc.org/show_bug.cgi?id=348
4 * https://libre-soc.org/openpower/isa/sprset/
5 """
6
7 from nmigen import (Module, Signal, Cat)
8 from nmutil.pipemodbase import PipeModBase
9 from soc.fu.spr.pipe_data import SPRInputData, SPROutputData
10 from openpower.decoder.power_enums import MicrOp, SPRfull, SPRreduced, XER_bits
11
12 from openpower.decoder.power_fields import DecodeFields
13 from openpower.decoder.power_fieldsn import SignalBitRange
14 from openpower.decoder.power_decoder2 import decode_spr_num
15
16
17 class SPRMainStage(PipeModBase):
18 def __init__(self, pspec):
19 super().__init__(pspec, "spr_main")
20 # test if regfiles are reduced
21 self.regreduce_en = (hasattr(pspec, "regreduce") and
22 (pspec.regreduce == True))
23
24 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
25 self.fields.create_specs()
26
27 def ispec(self):
28 return SPRInputData(self.pspec)
29
30 def ospec(self):
31 return SPROutputData(self.pspec)
32
33 def elaborate(self, platform):
34 if self.regreduce_en:
35 SPR = SPRreduced
36 else:
37 SPR = SPRfull
38 m = Module()
39 comb = m.d.comb
40 op = self.i.ctx.op
41
42 # convenience variables
43 a_i, spr1_i, fast1_i = self.i.a, self.i.spr1, self.i.fast1
44 so_i, ov_i, ca_i = self.i.xer_so, self.i.xer_ov, self.i.xer_ca
45 so_o, ov_o, ca_o = self.o.xer_so, self.o.xer_ov, self.o.xer_ca
46 o, spr1_o, fast1_o = self.o.o, self.o.spr1, self.o.fast1
47 state1_i, state1_o = self.i.state1, self.o.state1
48
49 # take copy of D-Form TO field
50 x_fields = self.fields.FormXFX
51 spr = Signal(len(x_fields.SPR))
52 comb += spr.eq(decode_spr_num(x_fields.SPR))
53
54 # TODO: some #defines for the bits n stuff.
55 with m.Switch(op.insn_type):
56 #### MTSPR ####
57 with m.Case(MicrOp.OP_MTSPR):
58 with m.Switch(spr):
59 # State SPRs first
60 with m.Case(SPR.DEC, SPR.TB):
61 comb += state1_o.data.eq(a_i)
62 comb += state1_o.ok.eq(1)
63
64 # Fast SPRs second: anything in FAST regs
65 with m.Case(SPR.CTR, SPR.LR, SPR.TAR, SPR.SRR0,
66 SPR.SRR1, SPR.XER, SPR.HSRR0, SPR.HSRR1,
67 SPR.SPRG0_priv, SPR.SPRG1_priv,
68 SPR.SPRG2_priv, SPR.SPRG3,
69 SPR.HSPRG0, SPR.HSPRG1, SPR.SVSRR0):
70 comb += fast1_o.data.eq(a_i)
71 comb += fast1_o.ok.eq(1)
72 # XER is constructed
73 with m.If(spr == SPR.XER):
74 # sticky
75 comb += so_o.data.eq(a_i[63-XER_bits['SO']])
76 comb += so_o.ok.eq(1)
77 # overflow
78 comb += ov_o.data[0].eq(a_i[63-XER_bits['OV']])
79 comb += ov_o.data[1].eq(a_i[63-XER_bits['OV32']])
80 comb += ov_o.ok.eq(1)
81 # carry
82 comb += ca_o.data[0].eq(a_i[63-XER_bits['CA']])
83 comb += ca_o.data[1].eq(a_i[63-XER_bits['CA32']])
84 comb += ca_o.ok.eq(1)
85
86 # slow SPRs TODO
87 with m.Default():
88 comb += spr1_o.data.eq(a_i)
89 comb += spr1_o.ok.eq(1)
90
91 # move from SPRs
92 with m.Case(MicrOp.OP_MFSPR):
93 comb += o.ok.eq(1)
94 with m.Switch(spr):
95 # state SPRs first
96 with m.Case(SPR.DEC, SPR.TB):
97 comb += o.data.eq(state1_i)
98 # TBU is upper 32-bits of State Reg
99 with m.Case(SPR.TBU):
100 comb += o.data[0:32].eq(state1_i[32:64])
101
102 # fast SPRs second
103 with m.Case(SPR.CTR, SPR.LR, SPR.TAR, SPR.SRR0,
104 SPR.SRR1, SPR.XER, SPR.HSRR0, SPR.HSRR1,
105 SPR.SPRG0_priv, SPR.SPRG1_priv,
106 SPR.SPRG2_priv, SPR.SPRG3,
107 SPR.HSPRG0, SPR.HSPRG1, SPR.SVSRR0):
108 comb += o.data.eq(fast1_i)
109 with m.If(spr == SPR.XER):
110 # bits 0:31 and 35:43 are treated as reserved
111 # and return 0s when read using mfxer
112 comb += o[32:64].eq(0) # MBS0 bits 0-31
113 comb += o[63-43:64-35].eq(0) # MSB0 bits 35-43
114 # sticky
115 comb += o[63-XER_bits['SO']].eq(so_i)
116 # overflow
117 comb += o[63-XER_bits['OV']].eq(ov_i[0])
118 comb += o[63-XER_bits['OV32']].eq(ov_i[1])
119 # carry
120 comb += o[63-XER_bits['CA']].eq(ca_i[0])
121 comb += o[63-XER_bits['CA32']].eq(ca_i[1])
122 # slow SPRs TODO
123 with m.Default():
124 comb += o.data.eq(spr1_i)
125
126 comb += self.o.ctx.eq(self.i.ctx)
127
128 return m