--- /dev/null
+"""SPR Pipeline
+
+* https://bugs.libre-soc.org/show_bug.cgi?id=348
+* https://libre-soc.org/openpower/isa/sprset/
+"""
+
+from nmigen import (Module, Signal, Cat, Mux, Const, signed)
+from nmutil.pipemodbase import PipeModBase
+from nmutil.extend import exts
+from soc.fu.spr.pipe_data import SPRInputData, SPROutputData
+from soc.fu.branch.main_stage import br_ext
+from soc.decoder.power_enums import InternalOp
+
+from soc.decoder.power_fields import DecodeFields
+from soc.decoder.power_fieldsn import SignalBitRange
+
+def decode_spr_num(spr):
+ return Cat(spr[5:10], spr[0:5])
+
+
+class SPRMainStage(PipeModBase):
+ def __init__(self, pspec):
+ super().__init__(pspec, "main")
+ self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
+ self.fields.create_specs()
+
+ def ispec(self):
+ return SPRInputData(self.pspec)
+
+ def ospec(self):
+ return SPROutputData(self.pspec)
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ op = self.i.ctx.op
+
+ # convenience variables
+ a_i, spr1_i, fast1_i = self.i.a, self.i.spr1, self.i.fast1
+ so_i, ov_i, ca_i = self.i.xer_so, self.i.xer_ov, self.i.xer_ca
+ so_o, ov_o, ca_o = self.o.xer_so, self.o.xer_ov, self.o.xer_ca
+ o, spr1_o, fast1_o = self.o.o, self.o.spr1, self.o.fast1
+
+ # take copy of D-Form TO field
+ x_fields = self.fields.FormXFX
+ spr = Signal(x_fields.SPR[0:-1].shape())
+ comb += spr.eq(decode_spr_num(i_fields.SPR[0:-1]))
+
+ # TODO: some #defines for the bits n stuff.
+ with m.Switch(op.insn_type):
+ #### MTSPR ####
+ with m.Case(InternalOp.OP_MTSPR):
+ with m.Switch(spr):
+ # fast SPRs first
+ with m.Case(SPR.CTR, SPR.LR, SPR.TAR, SPR.SRR0, SPR.SRR1):
+ comb += fast1_o.data.eq(a_i)
+ comb += fast1_o.ok.eq(1)
+ # XER is constructed
+ with m.Case(SPR.XER):
+ # sticky
+ comb += so_o.data.eq(a_i[63-XER_bits['SO']])
+ comb += so_o.ok.eq(1)
+ # overflow
+ comb += ov_o.data[0].eq(a_i[63-XER_bits['OV']])
+ comb += ov_o.data[1].eq(a_i[63-XER_bits['OV32']])
+ comb += ov_o.ok.eq(1)
+ # carry
+ comb += ca_o.data[0].eq(a_i[63-XER_bits['CA']])
+ comb += ca_o.data[1].eq(a_i[63-XER_bits['CA32']])
+ comb += ca_o.ok.eq(1)
+ # slow SPRs TODO
+
+ # move from SPRs
+ with m.Case(InternalOp.OP_MFSPR):
+ comb += o.ok.eq(1)
+ with m.Switch(spr):
+ # fast SPRs first
+ with m.Case(SPR.CTR, SPR.LR, SPR.TAR, SPR.SRR0, SPR.SRR1):
+ comb += o.data.eq(fast1_i)
+ # XER is constructed
+ with m.Case(SPR.XER):
+ # sticky
+ comb += o[63-XER_bits['SO']].eq(so_i)
+ # overflow
+ comb += o[63-XER_bits['OV']].eq(ov_i[0])
+ comb += o[63-XER_bits['OV32']].eq(ov_i[1])
+ # carry
+ comb += o[63-XER_bits['CA']].eq(ca_i[0])
+ comb += o[63-XER_bits['CA32']].eq(ca_i[1])
+ # slow SPRs TODO
+
+ comb += self.o.ctx.eq(self.i.ctx)
+
+ return m
class SPRInputData(IntegerData):
regspec = [('INT', 'ra', '0:63'), # RA
('SPR', 'spr1', '0:63'), # SPR (slow)
- ('FAST', 'spr2', '0:63'), # SPR (fast: MSR, LR, CTR etc)
+ ('FAST', 'fast1', '0:63'), # SPR (fast: MSR, LR, CTR etc)
('XER', 'xer_so', '32'), # XER bit 32: SO
('XER', 'xer_ov', '33,44'), # XER bit 34/45: CA/CA32
('XER', 'xer_ca', '34,45')] # bit0: ov, bit1: ov32
class SPROutputData(IntegerData):
regspec = [('INT', 'o', '0:63'), # RT
('SPR', 'spr1', '0:63'), # SPR (slow)
- ('FAST', 'spr2', '0:63'), # SPR (fast: MSR, LR, CTR etc)
+ ('FAST', 'fast1', '0:63'), # SPR (fast: MSR, LR, CTR etc)
('XER', 'xer_so', '32'), # XER bit 32: SO
('XER', 'xer_ov', '33,44'), # XER bit 34/45: CA/CA32
('XER', 'xer_ca', '34,45')] # bit0: ov, bit1: ov32