From a36c1edd69944ad0909ee57934b535a11b6c08cd Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 28 Feb 2021 17:19:18 +0000 Subject: [PATCH] start on SVP64 RM Mode decoder --- src/soc/consts.py | 1 + src/soc/decoder/power_enums.py | 14 ++++++++ src/soc/sv/svp64.py | 59 ++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/soc/consts.py b/src/soc/consts.py index ce13b3e1..8d537cd8 100644 --- a/src/soc/consts.py +++ b/src/soc/consts.py @@ -192,6 +192,7 @@ class EXTRA3: IDX0 = [0, 1, 2] IDX1 = [3, 4, 5] IDX2 = [6, 7, 8] + MASK = [6, 7, 8] EXTRA3_SIZE = 9 diff --git a/src/soc/decoder/power_enums.py b/src/soc/decoder/power_enums.py index 10357bd7..1254534d 100644 --- a/src/soc/decoder/power_enums.py +++ b/src/soc/decoder/power_enums.py @@ -111,6 +111,7 @@ class Form(Enum): EVS = 26 Z22 = 27 Z23 = 28 + SVL = 29 # Simple-V for setvl instruction # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/ @@ -135,6 +136,12 @@ class SVEXTRA(Enum): Idx3 = 4 Idx_1_2 = 5 # due to weird BA/BB for crops +@unique +class SVP64PredMode(Enum): + ALWAYS = 0 + INT = 1 + CR = 2 + @unique class SVP64PredInt(Enum): ALWAYS = 0 @@ -179,6 +186,13 @@ class SVP64subvl(Enum): VEC3 = 2 VEC4 = 3 +@unique +class SVP64sat(Enum): + NONE = 0 + SIGNED = 1 + UNSIGNED = 2 + + # supported instructions: make sure to keep up-to-date with CSV files # just like everything else _insns = [ diff --git a/src/soc/sv/svp64.py b/src/soc/sv/svp64.py index da9d7627..f9665331 100644 --- a/src/soc/sv/svp64.py +++ b/src/soc/sv/svp64.py @@ -17,7 +17,9 @@ https://libre-soc.org/openpower/sv/svp64/ """ from nmigen import Record, Elaboratable, Module, Signal -from soc.decoder.power_enums import SVP64RMMode +from soc.decoder.power_enums import (SVP64RMMode, Function, SVPtype, + SVP64PredMode, SVP64sat) +from soc.consts import EXTRA3 # in nMigen, Record begins at the LSB and fills upwards class SVP64Rec(Record): @@ -56,4 +58,57 @@ Arithmetic: """ class SVP64RMMode(Elaboratable): - pass + def __init__(self, name=None): + self.rm_in = SVP64Rec(name=name) + self.fn_in = Signal(Function) # LD/ST is different + self.ptype_in = Signal(SVPtype) + self.mode = Signal(SVP64RMMode) + self.predmode = Signal(SVP64PredMode) + self.srcpred = Signal(3) + self.dstpred = Signal(3) + self.saturate = Signal(SVP64sat) + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + # decode pieces of mode + is_ldst = Signal() + mode2 = Signal(2) + comb += is_ldst.eq(self.fn_in == Function.LDST) + comb += mode2.eq(mode[0:2]) + with m.Switch(mode2): + with m.Case(0): # needs further decoding (LDST no mapreduce) + with m.If(is_ldst): + comb += self.mode.eq(SVP64RMMode.NORMAL) + with m.Elif(mode[3] == 1): + comb += self.mode.eq(SVP64RMMode.MAPREDUCE) + with m.Else(): + comb += self.mode.eq(SVP64RMMode.NORMAL) + with m.Case(1): + comb += self.mode.eq(SVP64RMMode.FFIRST) # fail-first + with m.Case(2): + comb += self.mode.eq(SVP64RMMode.SATURATE) # saturate + with m.Case(3): + comb += self.mode.eq(SVP64RMMode.PREDRES) # predicate result + + # identify predicate mode + with m.If(self.rm_in.mmode == 1): + comb += self.predmode.eq(SVP64PredMode.CR) # CR Predicate + with m.Elif(self.srcpred == 0): + comb += self.predmode.eq(SVP64PredMode.ALWAYS) # No predicate + with m.Else(): + comb += self.predmode.eq(SVP64PredMode.INT) # non-zero src: INT + + # extract src/dest predicate. use EXTRA3.MASK because EXTRA2.MASK + # is in exactly the same bits + srcmask = sel(m, self.rm_in.extra, EXTRA3.MASK) + dstmask = self.rm_in.mask + with m.If(self.ptype_in == SVPtype.P2): + comb += self.srcpred.eq(srcmask) + comb += self.dstpred.eq(dstmask) + + # TODO: detect zeroing mode, a few more. + + return m + -- 2.30.2