From 6ceb176d723c076151346e9db06ec45d328e6d00 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 28 Feb 2021 14:47:25 +0000 Subject: [PATCH] move SVP64 Extra decoders to separate module --- src/soc/decoder/power_decoder2.py | 149 +----------------------- src/soc/decoder/power_svp64_extra.py | 167 +++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 148 deletions(-) create mode 100644 src/soc/decoder/power_svp64_extra.py diff --git a/src/soc/decoder/power_decoder2.py b/src/soc/decoder/power_decoder2.py index 490d5285..0a204904 100644 --- a/src/soc/decoder/power_decoder2.py +++ b/src/soc/decoder/power_decoder2.py @@ -19,6 +19,7 @@ from nmutil.extend import exts from soc.experiment.mem_types import LDSTException from soc.decoder.power_svp64_prefix import SVP64PrefixDecoder +from soc.decoder.power_svp64_extra import SVP64CRExtra, SVP64RegExtra from soc.decoder.power_regspec_map import regspec_decode_read from soc.decoder.power_regspec_map import regspec_decode_write from soc.decoder.power_decoder import create_pdecode @@ -82,154 +83,6 @@ class SPRMap(Elaboratable): return m -class SVP64ExtraSpec(Elaboratable): - """SVP64ExtraSpec - decodes SVP64 Extra specification. - - selects the required EXTRA2/3 field. - - see https://libre-soc.org/openpower/sv/svp64/ - """ - def __init__(self): - self.extra = Signal(9, reset_less=True) - self.etype = Signal(SVEtype, reset_less=True) # 2 or 3 bits - self.idx = Signal(SVEXTRA, reset_less=True) # which part of extra - self.spec = Signal(3) # EXTRA spec for the register - - def elaborate(self, platform): - m = Module() - comb = m.d.comb - spec = self.spec - extra = self.extra - - # back in the LDSTRM-* and RM-* files generated by sv_analysis.py - # we marked every op with an Etype: EXTRA2 or EXTRA3, and also said - # which of the 4 (or 3 for EXTRA3) sub-fields of bits 10:18 contain - # the register-extension information. extract those now - with m.Switch(self.etype): - # 2-bit index selection mode - with m.Case(SVEtype.EXTRA2): - with m.Switch(self.idx): - with m.Case(SVEXTRA.Idx0): # 1st 2 bits [0:1] - comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX0_VEC]) - comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX0_MSB]) - with m.Case(SVEXTRA.Idx1): # 2nd 2 bits [2:3] - comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX1_VEC]) - comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX1_MSB]) - with m.Case(SVEXTRA.Idx2): # 3rd 2 bits [4:5] - comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX2_VEC]) - comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX2_MSB]) - with m.Case(SVEXTRA.Idx3): # 4th 2 bits [6:7] - comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX3_VEC]) - comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX3_MSB]) - # 3-bit index selection mode - with m.Case(SVEtype.EXTRA3): - with m.Switch(self.idx): - with m.Case(SVEXTRA.Idx0): # 1st 3 bits [0:2] - extra3_idx0 = sel(m, extra, EXTRA3.IDX0) - comb += spec.eq(extra3_idx0) - with m.Case(SVEXTRA.Idx1): # 2nd 3 bits [3:5] - extra3_idx1 = sel(m, extra, EXTRA3.IDX1) - comb += spec.eq(extra3_idx1) - with m.Case(SVEXTRA.Idx2): # 3rd 3 bits [6:8] - extra3_idx2 = sel(m, extra, EXTRA3.IDX2) - comb += spec.eq(extra3_idx2) - # cannot fit more than 9 bits so there is no 4th thing - - return m - - -class SVP64RegExtra(SVP64ExtraSpec): - """SVP64RegExtra - decodes SVP64 Extra fields to determine reg extension - - incoming 5-bit GPR/FP is turned into a 7-bit and marked as scalar/vector - depending on info in one of the positions in the EXTRA field. - - designed so that "no change" to the 5-bit register number occurs if - SV either does not apply or the relevant EXTRA2/3 field bits are zero. - - see https://libre-soc.org/openpower/sv/svp64/ - """ - def __init__(self): - SVP64ExtraSpec.__init__(self) - self.reg_in = Signal(5) # incoming reg number (5 bits, RA, RB) - self.reg_out = Signal(7) # extra-augmented output (7 bits) - self.isvec = Signal(1) # reg is marked as vector if true - - def elaborate(self, platform): - m = super().elaborate(platform) # select required EXTRA2/3 - comb = m.d.comb - - # first get the spec. if not changed it's "scalar identity behaviour" - # which is zero which is ok. - spec = self.spec - - # now decode it. bit 0 is "scalar/vector". note that spec could be zero - # from above, which (by design) has the effect of "no change", below. - - # simple: isvec is top bit of spec - comb += self.isvec.eq(spec[SPEC.VEC]) - # extra bits for register number augmentation - spec_aug = Signal(SPEC_AUG_SIZE) - comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE)) - - # decode vector differently from scalar - with m.If(self.isvec): - # Vector: shifted up, extra in LSBs (RA << 2) | spec[1:2] - comb += self.reg_out.eq(Cat(spec_aug, self.reg_in)) - with m.Else(): - # Scalar: not shifted up, extra in MSBs RA | (spec[1:2] << 5) - comb += self.reg_out.eq(Cat(self.reg_in, spec_aug)) - - return m - - -class SVP64CRExtra(SVP64ExtraSpec): - """SVP64CRExtra - decodes SVP64 Extra fields to determine CR extension - - incoming 3-bit CR is turned into a 7-bit and marked as scalar/vector - depending on info in one of the positions in the EXTRA field. - - yes, really, 128 CRs. INT is 128, FP is 128, therefore CRs are 128. - - designed so that "no change" to the 3-bit CR register number occurs if - SV either does not apply or the relevant EXTRA2/3 field bits are zero. - - see https://libre-soc.org/openpower/sv/svp64/appendix - """ - def __init__(self): - SVP64ExtraSpec.__init__(self) - self.cr_in = Signal(3) # incoming CR number (3 bits, BA[0:2], BFA) - self.cr_out = Signal(7) # extra-augmented CR output (7 bits) - self.isvec = Signal(1) # reg is marked as vector if true - - def elaborate(self, platform): - m = super().elaborate(platform) # select required EXTRA2/3 - comb = m.d.comb - - # first get the spec. if not changed it's "scalar identity behaviour" - # which is zero which is ok. - spec = self.spec - - # now decode it. bit 0 is "scalar/vector". note that spec could be zero - # from above, which (by design) has the effect of "no change", below. - - # simple: isvec is top bit of spec - comb += self.isvec.eq(spec[SPEC.VEC]) - # extra bits for register number augmentation - spec_aug = Signal(SPEC_AUG_SIZE) - comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE)) - - # decode vector differently from scalar, insert bits 1 and 2 accordingly - with m.If(self.isvec): - # Vector: shifted up, extra in LSBs (CR << 4) | (spec[1:2] << 2) - comb += self.cr_out.eq(Cat(Const(0, 2), spec_aug, self.cr_in)) - with m.Else(): - # Scalar: not shifted up, extra in MSBs CR | (spec[1:2] << 3) - comb += self.cr_out.eq(Cat(self.cr_in, spec_aug)) - - return m - - class DecodeA(Elaboratable): """DecodeA from instruction diff --git a/src/soc/decoder/power_svp64_extra.py b/src/soc/decoder/power_svp64_extra.py new file mode 100644 index 00000000..02c0bfd5 --- /dev/null +++ b/src/soc/decoder/power_svp64_extra.py @@ -0,0 +1,167 @@ +"""SVP64 EXTRA field decoder +""" + +from nmigen import Module, Elaboratable, Signal, Mux, Const, Cat +from nmigen.cli import rtlil +from nmutil.util import sel + + +from soc.decoder.power_enums import (SVEXTRA, SVEtype) +from soc.consts import (SPEC, EXTRA2, EXTRA3, SVP64P, field, + SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs) + + +class SVP64ExtraSpec(Elaboratable): + """SVP64ExtraSpec - decodes SVP64 Extra specification. + + selects the required EXTRA2/3 field. + + see https://libre-soc.org/openpower/sv/svp64/ + """ + def __init__(self): + self.extra = Signal(9, reset_less=True) + self.etype = Signal(SVEtype, reset_less=True) # 2 or 3 bits + self.idx = Signal(SVEXTRA, reset_less=True) # which part of extra + self.spec = Signal(3) # EXTRA spec for the register + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + spec = self.spec + extra = self.extra + + # back in the LDSTRM-* and RM-* files generated by sv_analysis.py + # we marked every op with an Etype: EXTRA2 or EXTRA3, and also said + # which of the 4 (or 3 for EXTRA3) sub-fields of bits 10:18 contain + # the register-extension information. extract those now + with m.Switch(self.etype): + # 2-bit index selection mode + with m.Case(SVEtype.EXTRA2): + with m.Switch(self.idx): + with m.Case(SVEXTRA.Idx0): # 1st 2 bits [0:1] + comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX0_VEC]) + comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX0_MSB]) + with m.Case(SVEXTRA.Idx1): # 2nd 2 bits [2:3] + comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX1_VEC]) + comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX1_MSB]) + with m.Case(SVEXTRA.Idx2): # 3rd 2 bits [4:5] + comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX2_VEC]) + comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX2_MSB]) + with m.Case(SVEXTRA.Idx3): # 4th 2 bits [6:7] + comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX3_VEC]) + comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX3_MSB]) + # 3-bit index selection mode + with m.Case(SVEtype.EXTRA3): + with m.Switch(self.idx): + with m.Case(SVEXTRA.Idx0): # 1st 3 bits [0:2] + extra3_idx0 = sel(m, extra, EXTRA3.IDX0) + comb += spec.eq(extra3_idx0) + with m.Case(SVEXTRA.Idx1): # 2nd 3 bits [3:5] + extra3_idx1 = sel(m, extra, EXTRA3.IDX1) + comb += spec.eq(extra3_idx1) + with m.Case(SVEXTRA.Idx2): # 3rd 3 bits [6:8] + extra3_idx2 = sel(m, extra, EXTRA3.IDX2) + comb += spec.eq(extra3_idx2) + # cannot fit more than 9 bits so there is no 4th thing + + return m + + +class SVP64RegExtra(SVP64ExtraSpec): + """SVP64RegExtra - decodes SVP64 Extra fields to determine reg extension + + incoming 5-bit GPR/FP is turned into a 7-bit and marked as scalar/vector + depending on info in one of the positions in the EXTRA field. + + designed so that "no change" to the 5-bit register number occurs if + SV either does not apply or the relevant EXTRA2/3 field bits are zero. + + see https://libre-soc.org/openpower/sv/svp64/ + """ + def __init__(self): + SVP64ExtraSpec.__init__(self) + self.reg_in = Signal(5) # incoming reg number (5 bits, RA, RB) + self.reg_out = Signal(7) # extra-augmented output (7 bits) + self.isvec = Signal(1) # reg is marked as vector if true + + def elaborate(self, platform): + m = super().elaborate(platform) # select required EXTRA2/3 + comb = m.d.comb + + # first get the spec. if not changed it's "scalar identity behaviour" + # which is zero which is ok. + spec = self.spec + + # now decode it. bit 0 is "scalar/vector". note that spec could be zero + # from above, which (by design) has the effect of "no change", below. + + # simple: isvec is top bit of spec + comb += self.isvec.eq(spec[SPEC.VEC]) + # extra bits for register number augmentation + spec_aug = Signal(SPEC_AUG_SIZE) + comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE)) + + # decode vector differently from scalar + with m.If(self.isvec): + # Vector: shifted up, extra in LSBs (RA << 2) | spec[1:2] + comb += self.reg_out.eq(Cat(spec_aug, self.reg_in)) + with m.Else(): + # Scalar: not shifted up, extra in MSBs RA | (spec[1:2] << 5) + comb += self.reg_out.eq(Cat(self.reg_in, spec_aug)) + + return m + + +class SVP64CRExtra(SVP64ExtraSpec): + """SVP64CRExtra - decodes SVP64 Extra fields to determine CR extension + + incoming 3-bit CR is turned into a 7-bit and marked as scalar/vector + depending on info in one of the positions in the EXTRA field. + + yes, really, 128 CRs. INT is 128, FP is 128, therefore CRs are 128. + + designed so that "no change" to the 3-bit CR register number occurs if + SV either does not apply or the relevant EXTRA2/3 field bits are zero. + + see https://libre-soc.org/openpower/sv/svp64/appendix + """ + def __init__(self): + SVP64ExtraSpec.__init__(self) + self.cr_in = Signal(3) # incoming CR number (3 bits, BA[0:2], BFA) + self.cr_out = Signal(7) # extra-augmented CR output (7 bits) + self.isvec = Signal(1) # reg is marked as vector if true + + def elaborate(self, platform): + m = super().elaborate(platform) # select required EXTRA2/3 + comb = m.d.comb + + # first get the spec. if not changed it's "scalar identity behaviour" + # which is zero which is ok. + spec = self.spec + + # now decode it. bit 0 is "scalar/vector". note that spec could be zero + # from above, which (by design) has the effect of "no change", below. + + # simple: isvec is top bit of spec + comb += self.isvec.eq(spec[SPEC.VEC]) + # extra bits for register number augmentation + spec_aug = Signal(SPEC_AUG_SIZE) + comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE)) + + # decode vector differently from scalar, insert bits 1 and 2 accordingly + with m.If(self.isvec): + # Vector: shifted up, extra in LSBs (CR << 4) | (spec[1:2] << 2) + comb += self.cr_out.eq(Cat(Const(0, 2), spec_aug, self.cr_in)) + with m.Else(): + # Scalar: not shifted up, extra in MSBs CR | (spec[1:2] << 3) + comb += self.cr_out.eq(Cat(self.cr_in, spec_aug)) + + return m + + +if __name__ == '__main__': + pdecode = create_pdecode() + dec2 = PowerDecode2(pdecode) + vl = rtlil.convert(dec2, ports=dec2.ports() + pdecode.ports()) + with open("dec2.il", "w") as f: + f.write(vl) -- 2.30.2