resolving imports changing over
[openpower-isa.git] / src / openpower / decoder / power_svp64_rm.py
1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Funded by NLnet http://nlnet.nl
4 """SVP64 RM (Remap) Record.
5
6 https://libre-soc.org/openpower/sv/svp64/
7
8 | Field Name | Field bits | Description |
9 |-------------|------------|----------------------------------------|
10 | MASKMODE | `0` | Execution (predication) Mask Kind |
11 | MASK | `1:3` | Execution Mask |
12 | ELWIDTH | `4:5` | Element Width |
13 | ELWIDTH_SRC | `6:7` | Element Width for Source |
14 | SUBVL | `8:9` | Sub-vector length |
15 | EXTRA | `10:18` | context-dependent extra |
16 | MODE | `19:23` | changes Vector behaviour |
17 """
18
19 from nmigen import Elaboratable, Module, Signal, Const
20 from openpower.decoder.power_enums import (SVP64RMMode, Function, SVPtype,
21 SVP64PredMode, SVP64sat)
22 from openpower.consts import EXTRA3, SVP64MODE
23 from openpower.sv.svp64 import SVP64Rec
24 from nmutil.util import sel
25
26
27 """RM Mode
28 there are three Mode variants, two for LD/ST and one for everything else
29 https://libre-soc.org/openpower/sv/svp64/
30 https://libre-soc.org/openpower/sv/ldst/
31
32 LD/ST immed:
33 00 str sz dz normal mode
34 01 inv CR-bit Rc=1: ffirst CR sel
35 01 inv els RC1 Rc=0: ffirst z/nonz
36 10 N dz els sat mode: N=0/1 u/s
37 11 inv CR-bit Rc=1: pred-result CR sel
38 11 inv els RC1 Rc=0: pred-result z/nonz
39
40 LD/ST indexed:
41 00 0 sz dz normal mode
42 00 1 rsvd reserved
43 01 inv CR-bit Rc=1: ffirst CR sel
44 01 inv dz RC1 Rc=0: ffirst z/nonz
45 10 N sz dz sat mode: N=0/1 u/s
46 11 inv CR-bit Rc=1: pred-result CR sel
47 11 inv dz RC1 Rc=0: pred-result z/nonz
48
49 Arithmetic:
50 00 0 sz dz normal mode
51 00 1 dz CRM reduce mode (mapreduce), SUBVL=1
52 00 1 SVM CRM subvector reduce mode, SUBVL>1
53 01 inv CR-bit Rc=1: ffirst CR sel
54 01 inv dz RC1 Rc=0: ffirst z/nonz
55 10 N sz dz sat mode: N=0/1 u/s
56 11 inv CR-bit Rc=1: pred-result CR sel
57 11 inv dz RC1 Rc=0: pred-result z/nonz
58 """
59
60 class SVP64RMModeDecode(Elaboratable):
61 def __init__(self, name=None):
62 self.rm_in = SVP64Rec(name=name)
63 self.fn_in = Signal(Function) # LD/ST is different
64 self.ptype_in = Signal(SVPtype)
65 self.rc_in = Signal()
66 self.ldst_idx = Signal()
67
68 # main mode (normal, reduce, saturate, ffirst, pred-result)
69 self.mode = Signal(SVP64RMMode)
70
71 # predication
72 self.predmode = Signal(SVP64PredMode)
73 self.srcpred = Signal(3) # source predicate
74 self.dstpred = Signal(3) # destination predicate
75 self.pred_sz = Signal(1) # predicate source zeroing
76 self.pred_dz = Signal(1) # predicate dest zeroing
77
78 self.saturate = Signal(SVP64sat)
79 self.RC1 = Signal()
80 self.cr_sel = Signal(2)
81 self.inv = Signal(1)
82 self.map_evm = Signal(1)
83 self.map_crm = Signal(1)
84
85 def elaborate(self, platform):
86 m = Module()
87 comb = m.d.comb
88 mode = self.rm_in.mode
89
90 # decode pieces of mode
91 is_ldst = Signal()
92 comb += is_ldst.eq(self.fn_in == Function.LDST)
93 mode2 = sel(m, mode, SVP64MODE.MOD2)
94 with m.Switch(mode2):
95 with m.Case(0): # needs further decoding (LDST no mapreduce)
96 with m.If(is_ldst):
97 comb += self.mode.eq(SVP64RMMode.NORMAL)
98 with m.Elif(mode[SVP64MODE.REDUCE]):
99 comb += self.mode.eq(SVP64RMMode.MAPREDUCE)
100 with m.Else():
101 comb += self.mode.eq(SVP64RMMode.NORMAL)
102 with m.Case(1):
103 comb += self.mode.eq(SVP64RMMode.FFIRST) # fail-first
104 with m.Case(2):
105 comb += self.mode.eq(SVP64RMMode.SATURATE) # saturate
106 with m.Case(3):
107 comb += self.mode.eq(SVP64RMMode.PREDRES) # predicate result
108
109 # extract zeroing
110 with m.Switch(mode2):
111 with m.Case(0): # needs further decoding (LDST no mapreduce)
112 with m.If(is_ldst):
113 comb += self.pred_sz.eq(mode[SVP64MODE.SZ])
114 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
115 with m.Elif(mode[SVP64MODE.REDUCE]):
116 with m.If(self.rm_in.subvl == Const(0, 2)): # no SUBVL
117 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
118 with m.Else():
119 comb += self.pred_sz.eq(mode[SVP64MODE.SZ])
120 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
121 with m.Case(1, 3):
122 with m.If(is_ldst):
123 with m.If(~self.ldst_idx):
124 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
125 with m.Elif(self.rc_in):
126 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
127 with m.Case(2):
128 with m.If(is_ldst & ~self.ldst_idx):
129 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
130 with m.Else():
131 comb += self.pred_sz.eq(mode[SVP64MODE.SZ])
132 comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
133
134 # extract src/dest predicate. use EXTRA3.MASK because EXTRA2.MASK
135 # is in exactly the same bits
136 srcmask = sel(m, self.rm_in.extra, EXTRA3.MASK)
137 dstmask = self.rm_in.mask
138 with m.If(self.ptype_in == SVPtype.P2):
139 comb += self.srcpred.eq(srcmask)
140 with m.Else():
141 comb += self.srcpred.eq(dstmask)
142 comb += self.dstpred.eq(dstmask)
143
144 # identify predicate mode
145 with m.If(self.rm_in.mmode == 1):
146 comb += self.predmode.eq(SVP64PredMode.CR) # CR Predicate
147 with m.Elif((self.srcpred == 0) & (self.dstpred == 0)):
148 comb += self.predmode.eq(SVP64PredMode.ALWAYS) # No predicate
149 with m.Else():
150 comb += self.predmode.eq(SVP64PredMode.INT) # non-zero src: INT
151
152 # TODO: detect zeroing mode, saturation mode, a few more.
153
154 return m
155