convert branch pipeline to use msr/cia as immediates
[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 soc.decoder.power_enums import MicrOp, SPR, XER_bits
11
12 from soc.decoder.power_fields import DecodeFields
13 from soc.decoder.power_fieldsn import SignalBitRange
14 from soc.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 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
21 self.fields.create_specs()
22
23 def ispec(self):
24 return SPRInputData(self.pspec)
25
26 def ospec(self):
27 return SPROutputData(self.pspec)
28
29 def elaborate(self, platform):
30 m = Module()
31 comb = m.d.comb
32 op = self.i.ctx.op
33
34 # convenience variables
35 a_i, spr1_i, fast1_i = self.i.a, self.i.spr1, self.i.fast1
36 so_i, ov_i, ca_i = self.i.xer_so, self.i.xer_ov, self.i.xer_ca
37 so_o, ov_o, ca_o = self.o.xer_so, self.o.xer_ov, self.o.xer_ca
38 o, spr1_o, fast1_o = self.o.o, self.o.spr1, self.o.fast1
39
40 # take copy of D-Form TO field
41 x_fields = self.fields.FormXFX
42 spr = Signal(len(x_fields.SPR))
43 comb += spr.eq(decode_spr_num(x_fields.SPR))
44
45 # TODO: some #defines for the bits n stuff.
46 with m.Switch(op.insn_type):
47 #### MTSPR ####
48 with m.Case(MicrOp.OP_MTSPR):
49 with m.Switch(spr):
50 # fast SPRs first
51 with m.Case(SPR.CTR, SPR.LR, SPR.TAR, SPR.SRR0, SPR.SRR1):
52 comb += fast1_o.data.eq(a_i)
53 comb += fast1_o.ok.eq(1)
54 # XER is constructed
55 with m.Case(SPR.XER):
56 # sticky
57 comb += so_o.data.eq(a_i[63-XER_bits['SO']])
58 comb += so_o.ok.eq(1)
59 # overflow
60 comb += ov_o.data[0].eq(a_i[63-XER_bits['OV']])
61 comb += ov_o.data[1].eq(a_i[63-XER_bits['OV32']])
62 comb += ov_o.ok.eq(1)
63 # carry
64 comb += ca_o.data[0].eq(a_i[63-XER_bits['CA']])
65 comb += ca_o.data[1].eq(a_i[63-XER_bits['CA32']])
66 comb += ca_o.ok.eq(1)
67 # slow SPRs TODO
68
69 # move from SPRs
70 with m.Case(MicrOp.OP_MFSPR):
71 comb += o.ok.eq(1)
72 with m.Switch(spr):
73 # fast SPRs first
74 with m.Case(SPR.CTR, SPR.LR, SPR.TAR, SPR.SRR0, SPR.SRR1):
75 comb += o.data.eq(fast1_i)
76 # XER is constructed
77 with m.Case(SPR.XER):
78 # sticky
79 comb += o[63-XER_bits['SO']].eq(so_i)
80 # overflow
81 comb += o[63-XER_bits['OV']].eq(ov_i[0])
82 comb += o[63-XER_bits['OV32']].eq(ov_i[1])
83 # carry
84 comb += o[63-XER_bits['CA']].eq(ca_i[0])
85 comb += o[63-XER_bits['CA32']].eq(ca_i[1])
86 # slow SPRs TODO
87
88 comb += self.o.ctx.eq(self.i.ctx)
89
90 return m