(no commit message)
[libreriscv.git] / openpower / sv / remap.mdwn
1 # REMAP <a name="remap" />
2
3 <!-- hide -->
4 * <https://bugs.libre-soc.org/show_bug.cgi?id=143> matrix multiply
5 * <https://bugs.libre-soc.org/show_bug.cgi?id=867> add svindex
6 * <https://bugs.libre-soc.org/show_bug.cgi?id=885> svindex in simulator
7 * <https://bugs.libre-soc.org/show_bug.cgi?id=911> offset svshape option
8 * <https://bugs.libre-soc.org/show_bug.cgi?id=864> parallel reduction
9 * <https://bugs.libre-soc.org/show_bug.cgi?id=930> DCT/FFT "strides"
10 * see [[sv/remap/appendix]] for examples and usage
11 * see [[sv/propagation]] for a future way to apply REMAP
12 * [[remap/discussion]]
13 <!-- show -->
14
15 REMAP is an advanced form of Vector "Structure Packing" that provides
16 hardware-level support for commonly-used *nested* loop patterns that would
17 otherwise require full inline loop unrolling. For more general reordering
18 an Indexed REMAP mode is available (an abstracted analog to `xxperm`).
19
20 REMAP allows the usual sequential vector loop `0..VL-1` to be "reshaped"
21 (re-mapped) from a linear form to a 2D or 3D transposed form, or "offset"
22 to permit arbitrary access to elements (when elwidth overrides are
23 used), independently on each Vector src or dest register. Aside from
24 Indexed REMAP this is entirely Hardware-accelerated reordering and
25 consequently not costly in terms of register access. It will however
26 place a burden on Multi-Issue systems but no more than if the equivalent
27 Scalar instructions were explicitly loop-unrolled without SVP64, and
28 some advanced implementations may even find the Deterministic nature of
29 the Scheduling to be easier on resources.
30
31 The initial primary motivation of REMAP was for Matrix Multiplication,
32 reordering of sequential data in-place: in-place DCT and FFT were
33 easily justified given the exceptionally high usage in Computer Science.
34 Four SPRs are provided which may be applied to any GPR, FPR or CR Field so
35 that for example a single FMAC may be used in a single hardware-controlled
36 100% Deterministic loop to perform 5x3 times 3x4 Matrix multiplication,
37 generating 60 FMACs *without needing explicit assembler unrolling*.
38 Additional uses include regular "Structure Packing" such as RGB pixel
39 data extraction and reforming (although less costly vec2/3/4 reshaping
40 is achievable with `PACK/UNPACK`).
41
42 REMAP, like all of SV, is abstracted out, meaning that unlike traditional
43 Vector ISAs which would typically only have a limited set of instructions
44 that can be structure-packed (LD/ST and Move operations
45 being the most common), REMAP may be applied to
46 literally any instruction: CRs, Arithmetic, Logical, LD/ST, even
47 Vectorised Branch-Conditional.
48
49 When SUBVL is greater than 1 a given group of Subvector
50 elements are kept together: effectively the group becomes the
51 element, and with REMAP applying to elements
52 (not sub-elements) each group is REMAPed together.
53 Swizzle *can* however be applied to the same
54 instruction as REMAP, providing re-sequencing of
55 Subvector elements which REMAP cannot. Also as explained in [[sv/mv.swizzle]], [[sv/mv.vec]] and the [[svp64/appendix]], Pack and Unpack Mode bits
56 can extend down into Sub-vector elements to influence vec2/vec3/vec4
57 sequential reordering, but even here, REMAP reordering is not *individually*
58 extended down to the actual sub-vector elements themselves.
59 This keeps the relevant Predicate Mask bit applicable to the Subvector
60 group, just as it does when REMAP is not active.
61
62 In its general form, REMAP is quite expensive to set up, and on some
63 implementations may introduce latency, so should realistically be used
64 only where it is worthwhile. Given that even with latency the fact
65 that up to 127 operations can be Deterministically issued (from a single
66 instruction) it should be clear that REMAP should not be dismissed
67 for *possible* latency alone. Commonly-used patterns such as Matrix
68 Multiply, DCT and FFT have helper instruction options which make REMAP
69 easier to use.
70
71 There are four types of REMAP:
72
73 * **Matrix**, also known as 2D and 3D reshaping, can perform in-place
74 Matrix transpose and rotate. The Shapes are set up for an "Outer Product"
75 Matrix Multiply.
76 * **FFT/DCT**, with full triple-loop in-place support: limited to
77 Power-2 RADIX
78 * **Indexing**, for any general-purpose reordering, also includes
79 limited 2D reshaping as well as Element "offsetting".
80 * **Parallel Reduction**, for scheduling a sequence of operations
81 in a Deterministic fashion, in a way that may be parallelised,
82 to reduce a Vector down to a single value.
83
84 Best implemented on top of a Multi-Issue Out-of-Order Micro-architecture,
85 REMAP Schedules are 100% Deterministic **including Indexing** and are
86 designed to be incorporated in between the Decode and Issue phases,
87 directly into Register Hazard Management.
88
89 As long as the SVSHAPE SPRs
90 are not written to directly, Hardware may treat REMAP as 100%
91 Deterministic: all REMAP Management instructions take static
92 operands (no dynamic register operands)
93 with the exception of Indexed Mode, and even then
94 Architectural State is permitted to assume that the Indices
95 are cacheable from the point at which the `svindex` instruction
96 is executed.
97
98 Parallel Reduction is unusual in that it requires a full vector array
99 of results (not a scalar) and uses the rest of the result Vector for
100 the purposes of storing intermediary calculations. As these intermediary
101 results are Deterministically computed they may be useful.
102 Additionally, because the intermediate results are always written out
103 it is possible to service Precise Interrupts without affecting latency
104 (a common limitation of Vector ISAs implementing explicit
105 Parallel Reduction instructions, because their Architectural State cannot
106 hold the partial results).
107
108 ## Basic principle
109
110 The following illustrates why REMAP was added.
111
112 * normal vector element read/write of operands would be sequential
113 (0 1 2 3 ....)
114 * this is not appropriate for (e.g.) Matrix multiply which requires
115 accessing elements in alternative sequences (0 3 6 1 4 7 ...)
116 * normal Vector ISAs use either Indexed-MV or Indexed-LD/ST to "cope"
117 with this. both are expensive (copy large vectors, spill through memory)
118 and very few Packed SIMD ISAs cope with non-Power-2
119 (Duplicate-data inline-loop-unrolling is the costly solution)
120 * REMAP **redefines** the order of access according to set
121 (Deterministic) "Schedules".
122 * Matrix Schedules are not at all restricted to power-of-two boundaries
123 making it unnecessary to have for example specialised 3x4 transpose
124 instructions of other Vector ISAs.
125 * DCT and FFT REMAP are RADIX-2 limited but this is the case in existing Packed/Predicated
126 SIMD ISAs anyway (and Bluestein Convolution is typically deployed to
127 solve that).
128
129 Only the most commonly-used algorithms in computer science have REMAP
130 support, due to the high cost in both the ISA and in hardware. For
131 arbitrary remapping the `Indexed` REMAP may be used.
132
133 ## Example Usage
134
135 * `svshape` to set the type of reordering to be applied to an
136 otherwise usual `0..VL-1` hardware for-loop
137 * `svremap` to set which registers a given reordering is to apply to
138 (RA, RT etc)
139 * `sv.{instruction}` where any Vectorised register marked by `svremap`
140 will have its ordering REMAPPED according to the schedule set
141 by `svshape`.
142
143 The following illustrative example multiplies a 3x4 and a 5x3
144 matrix to create
145 a 5x4 result:
146
147 ```
148 svshape 5,4,3,0,0 # Outer Product 5x4 by 4x3
149 svremap 15,1,2,3,0,0,0,0 # link Schedule to registers
150 sv.fmadds *0,*32,*64,*0 # 60 FMACs get executed here
151 ```
152
153 * svshape sets up the four SVSHAPE SPRS for a Matrix Schedule
154 * svremap activates four out of five registers RA RB RC RT RS (15)
155 * svremap requests:
156 - RA to use SVSHAPE1
157 - RB to use SVSHAPE2
158 - RC to use SVSHAPE3
159 - RT to use SVSHAPE0
160 - RS Remapping to not be activated
161 * sv.fmadds has RT=0.v, RA=8.v, RB=16.v, RC=0.v
162 * With REMAP being active each register's element index is
163 *independently* transformed using the specified SHAPEs.
164
165 Thus the Vector Loop is arranged such that the use of
166 the multiply-and-accumulate instruction executes precisely the required
167 Schedule to perform an in-place in-registers Outer Product
168 Matrix Multiply with no
169 need to perform additional Transpose or register copy instructions.
170 The example above may be executed as a unit test and demo,
171 [here](https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/test_caller_svp64_matrix.py;h=c15479db9a36055166b6b023c7495f9ca3637333;hb=a17a252e474d5d5bf34026c25a19682e3f2015c3#l94)
172
173 ## REMAP types
174
175 This section summarises the motivation for each REMAP Schedule
176 and briefly goes over their characteristics and limitations.
177 Further details on the Deterministic Precise-Interruptible algorithms
178 used in these Schedules is found in the [[sv/remap/appendix]].
179
180 ### Matrix (1D/2D/3D shaping)
181
182 Matrix Multiplication is a huge part of High-Performance Compute,
183 and 3D.
184 In many PackedSIMD as well as Scalable Vector ISAs, non-power-of-two
185 Matrix sizes are a serious challenge. PackedSIMD ISAs, in order to
186 cope with for example 3x4 Matrices, recommend rolling data-repetition and loop-unrolling.
187 Aside from the cost of the load on the L1 I-Cache, the trick only
188 works if one of the dimensions X or Y are power-two. Prime Numbers
189 (5x7, 3x5) become deeply problematic to unroll.
190
191 Even traditional Scalable Vector ISAs have issues with Matrices, often
192 having to perform data Transpose by pushing out through Memory and back,
193 or computing Transposition Indices (costly) then copying to another
194 Vector (costly).
195
196 Matrix REMAP was thus designed to solve these issues by providing Hardware
197 Assisted
198 "Schedules" that can view what would otherwise be limited to a strictly
199 linear Vector as instead being 2D (even 3D) *in-place* reordered.
200 With both Transposition and non-power-two being supported the issues
201 faced by other ISAs are mitigated.
202
203 Limitations of Matrix REMAP are that the Vector Length (VL) is currently
204 restricted to 127: up to 127 FMAs (or other operation)
205 may be performed in total.
206 Also given that it is in-registers only at present some care has to be
207 taken on regfile resource utilisation. However it is perfectly possible
208 to utilise Matrix REMAP to perform the three inner-most "kernel"
209 ("Tiling") loops of
210 the usual 6-level large Matrix Multiply, without the usual difficulties
211 associated with SIMD.
212
213 Also the `svshape` instruction only provides access to part of the
214 Matrix REMAP capability. Rotation and mirroring need to be done by
215 programming the SVSHAPE SPRs directly, which can take a lot more
216 instructions. Future versions of SVP64 will include EXT1xx prefixed
217 variants (`psvshape`) which provide more comprehensive capacity and
218 mitigate the need to write direct to the SVSHAPE SPRs.
219
220 ### FFT/DCT Triple Loop
221
222 DCT and FFT are some of the most astonishingly used algorithms in
223 Computer Science. Radar, Audio, Video, R.F. Baseband and dozens more. At least
224 two DSPs, TMS320 and Hexagon, have VLIW instructions specially tailored
225 to FFT.
226
227 An in-depth analysis showed that it is possible to do in-place in-register
228 DCT and FFT as long as twin-result "butterfly" instructions are provided.
229 These can be found in the [[openpower/isa/svfparith]] page if performing
230 IEEE754 FP transforms. *(For fixed-point transforms, equivalent 3-in 2-out
231 integer operations would be required)*. These "butterfly" instructions
232 avoid the need for a temporary register because the two array positions
233 being overwritten will be "in-flight" in any In-Order or Out-of-Order
234 micro-architecture.
235
236 DCT and FFT Schedules are currently limited to RADIX2 sizes and do not
237 accept predicate masks. Given that it is common to perform recursive
238 convolutions combining smaller Power-2 DCT/FFT to create larger DCT/FFTs
239 in practice the RADIX2 limit is not a problem. A Bluestein convolution
240 to compute arbitrary length is demonstrated by
241 [Project Nayuki](https://www.nayuki.io/res/free-small-fft-in-multiple-languages/fft.py)
242
243 ### Indexed
244
245 The purpose of Indexing is to provide a generalised version of
246 Vector ISA "Permute" instructions, such as VSX `vperm`. The
247 Indexing is abstracted out and may be applied to much more
248 than an element move/copy, and is not limited for example
249 to the number of bytes that can fit into a VSX register.
250 Indexing may be applied to LD/ST (even on Indexed LD/ST
251 instructions such as `sv.lbzx`), arithmetic operations,
252 extsw: there is no artificial limit.
253
254 The only major caveat is that the registers to be used as
255 Indices must not be modified by any instruction after Indexed Mode
256 is established, and neither must MAXVL be altered. Additionally,
257 no register used as an Index may exceed MAXVL-1.
258
259 Failure to observe
260 these conditions results in `UNDEFINED` behaviour.
261 These conditions allow a Read-After-Write (RAW) Hazard to be created on
262 the entire range of Indices to be subsequently used, but a corresponding
263 Write-After-Read Hazard by any instruction that modifies the Indices
264 **does not have to be created**. Given the large number of registers
265 involved in Indexing this is a huge resource saving and reduction
266 in micro-architectural complexity. MAXVL is likewise
267 included in the RAW Hazards because it is involved in calculating
268 how many registers are to be considered Indices.
269
270 With these Hazard Mitigations in place, high-performance implementations
271 may read-cache the Indices at the point where a given `svindex` instruction
272 is called (or SVSHAPE SPRs - and MAXVL - directly altered) by issuing
273 background GPR register file reads whilst other instructions are being
274 issued and executed.
275
276 The original motivation for Indexed REMAP was to mitigate the need to add
277 an expensive `mv.x` to the Scalar ISA, which was likely to be rejected as
278 a stand-alone instruction. Usually a Vector ISA would add a non-conflicting
279 variant (as in VSX `vperm`) but it is common to need to permute by source,
280 with the risk of conflict, that has to be resolved, for example, in AVX-512
281 with `conflictd`.
282
283 Indexed REMAP on the other hand **does not prevent conflicts** (overlapping
284 destinations), which on a superficial analysis may be perceived to be a
285 problem, until it is recalled that, firstly, Simple-V is designed specifically
286 to require Program Order to be respected, and that Matrix, DCT and FFT
287 all *already* critically depend on overlapping Reads/Writes: Matrix
288 uses overlapping registers as accumulators. Thus the Register Hazard
289 Management needed by Indexed REMAP *has* to be in place anyway.
290
291 The cost compared to Matrix and other REMAPs (and Pack/Unpack) is
292 clearly that of the additional reading of the GPRs to be used as Indices,
293 plus the setup cost associated with creating those same Indices.
294 If any Deterministic REMAP can cover the required task, clearly it
295 is adviseable to use it instead.
296
297 *Programmer's note: some algorithms may require skipping of Indices exceeding
298 VL-1, not MAXVL-1. This may be achieved programmatically by performing
299 an `sv.cmp *BF,*RA,RB` where RA is the same GPRs used in the Indexed REMAP,
300 and RB contains the value of VL returned from `setvl`. The resultant
301 CR Fields may then be used as Predicate Masks to exclude those operations
302 with an Index exceeding VL-1.*
303
304 ### Parallel Reduction
305
306 Vector Reduce Mode issues a deterministic tree-reduction schedule to the underlying micro-architecture. Like Scalar reduction, the "Scalar Base"
307 (Power ISA v3.0B) operation is leveraged, unmodified, to give the
308 *appearance* and *effect* of Reduction.
309
310 In Horizontal-First Mode, Vector-result reduction **requires**
311 the destination to be a Vector, which will be used to store
312 intermediary results.
313
314 Given that the tree-reduction schedule is deterministic,
315 Interrupts and exceptions
316 can therefore also be precise. The final result will be in the first
317 non-predicate-masked-out destination element, but due again to
318 the deterministic schedule programmers may find uses for the intermediate
319 results.
320
321 When Rc=1 a corresponding Vector of co-resultant CRs is also
322 created. No special action is taken: the result *and its CR Field*
323 are stored "as usual" exactly as all other SVP64 Rc=1 operations.
324
325 Note that the Schedule only makes sense on top of certain instructions:
326 X-Form with a Register Profile of `RT,RA,RB` is fine because two sources
327 and the destination are all the same type. Like Scalar
328 Reduction, nothing is prohibited:
329 the results of execution on an unsuitable instruction may simply
330 not make sense. With care, even 3-input instructions (madd, fmadd, ternlogi)
331 may be used, and whilst it is down to the Programmer to walk through the
332 process the Programmer can be confident that the Parallel-Reduction is
333 guaranteed 100% Deterministic.
334
335 Critical to note regarding use of Parallel-Reduction REMAP is that,
336 exactly as with all REMAP Modes, the `svshape` instruction *requests*
337 a certain Vector Length (number of elements to reduce) and then
338 sets VL and MAXVL at the number of **operations** needed to be
339 carried out. Thus, equally as importantly, like Matrix REMAP
340 the total number of operations
341 is restricted to 127. Any Parallel-Reduction requiring more operations
342 will need to be done manually in batches (hierarchical
343 recursive Reduction).
344
345 Also important to note is that the Deterministic Schedule is arranged
346 so that some implementations *may* parallelise it (as long as doing so
347 respects Program Order and Register Hazards). Performance (speed)
348 of any given
349 implementation is neither strictly defined or guaranteed. As with
350 the Vulkan(tm) Specification, strict compliance is paramount whilst
351 performance is at the discretion of Implementors.
352
353 **Parallel-Reduction with Predication**
354
355 To avoid breaking the strict RISC-paradigm, keeping the Issue-Schedule
356 completely separate from the actual element-level (scalar) operations,
357 Move operations are **not** included in the Schedule. This means that
358 the Schedule leaves the final (scalar) result in the first-non-masked
359 element of the Vector used. With the predicate mask being dynamic
360 (but deterministic) this result could be anywhere.
361
362 If that result is needed to be moved to a (single) scalar register
363 then a follow-up `sv.mv/sm=predicate rt, *ra` instruction will be
364 needed to get it, where the predicate is the exact same predicate used
365 in the prior Parallel-Reduction instruction.
366
367 * If there was only a single
368 bit in the predicate then the result will not have moved or been altered
369 from the source vector prior to the Reduction
370 * If there was more than one bit the result will be in the
371 first element with a predicate bit set.
372
373 In either case the result is in the element with the first bit set in
374 the predicate mask. Thus, no move/copy *within the Reduction itself* was needed.
375
376 Programmer's Note: For *some* hardware implementations
377 the vector-to-scalar copy may be a slow operation, as may the Predicated
378 Parallel Reduction itself.
379 It may be better to perform a pre-copy
380 of the values, compressing them (VREDUCE-style) into a contiguous block,
381 which will guarantee that the result goes into the very first element
382 of the destination vector, in which case clearly no follow-up
383 predicated vector-to-scalar MV operation is needed.
384
385 **Usage conditions**
386
387 The simplest usage is to perform an overwrite, specifying all three
388 register operands the same.
389
390 ```
391 svshape parallelreduce, 6
392 sv.add *8, *8, *8
393 ```
394
395 The Reduction Schedule will issue the Parallel Tree Reduction spanning
396 registers 8 through 13, by adjusting the offsets to RT, RA and RB as
397 necessary (see "Parallel Reduction algorithm" in a later section).
398
399 A non-overwrite is possible as well but just as with the overwrite
400 version, only those destination elements necessary for storing
401 intermediary computations will be written to: the remaining elements
402 will **not** be overwritten and will **not** be zero'd.
403
404 ```
405 svshape parallelreduce, 6
406 sv.add *0, *8, *8
407 ```
408
409 However it is critical to note that if the source and destination are
410 not the same then the trick of using a follow-up vector-scalar MV will
411 not work.
412
413 ### Sub-Vector Horizontal Reduction
414
415 To achieve Sub-Vector Horizontal Reduction, Pack/Unpack should be enabled,
416 which will turn the Schedule around such that issuing of the Scalar
417 Defined Words is done with SUBVL looping as the inner loop not the
418 outer loop. Rc=1 with Sub-Vectors (SUBVL=2,3,4) is `UNDEFINED` behaviour.
419
420 ## Determining Register Hazards
421
422 For high-performance (Multi-Issue, Out-of-Order) systems it is critical
423 to be able to statically determine the extent of Vectors in order to
424 allocate pre-emptive Hazard protection. The next task is to eliminate
425 masked-out elements using predicate bits, freeing up the associated
426 Hazards.
427
428 For non-REMAP situations `VL` is sufficient to ascertain early
429 Hazard coverage, and with SVSTATE being a high priority cached
430 quantity at the same level of MSR and PC this is not a problem.
431
432 The problems come when REMAP is enabled. Indexed REMAP must instead
433 use `MAXVL` as the earliest (simplest)
434 batch-level Hazard Reservation indicator (after taking element-width
435 overriding on the Index source into consideration),
436 but Matrix, FFT and Parallel Reduction must all use completely different
437 schemes. The reason is that VL is used to step through the total
438 number of *operations*, not the number of registers.
439 The "Saving Grace" is that all of the REMAP Schedules are 100% Deterministic.
440
441 Advance-notice Parallel computation and subsequent cacheing
442 of all of these complex Deterministic REMAP Schedules is
443 *strongly recommended*, thus allowing clear and precise multi-issue
444 batched Hazard coverage to be deployed, *even for Indexed Mode*.
445 This is only possible for Indexed due to the strict guidelines
446 given to Programmers.
447
448 In short, there exists solutions to the problem of Hazard Management,
449 with varying degrees of refinement possible at correspondingly
450 increasing levels of complexity in hardware.
451
452 A reminder: when Rc=1 each result register (element) has an associated
453 co-result CR Field (one per result element). Thus above when determining
454 the Write-Hazards for result registers the corresponding Write-Hazards for the
455 corresponding associated co-result CR Field must not be forgotten, *including* when
456 Predication is used.
457
458 ## REMAP area of SVSTATE SPR
459
460 The following bits of the SVSTATE SPR are used for REMAP:
461
462 |32.33|34.35|36.37|38.39|40.41| 42.46 | 62 |
463 | -- | -- | -- | -- | -- | ----- | ------ |
464 |mi0 |mi1 |mi2 |mo0 |mo1 | SVme | RMpst |
465
466 mi0-2 and mo0-1 each select SVSHAPE0-3 to apply to a given register.
467 mi0-2 apply to RA, RB, RC respectively, as input registers, and
468 likewise mo0-1 apply to output registers (RT/FRT, RS/FRS) respectively.
469 SVme is 5 bits (one for each of mi0-2/mo0-1) and indicates whether the
470 SVSHAPE is actively applied or not.
471
472 * bit 0 of SVme indicates if mi0 is applied to RA / FRA / BA / BFA
473 * bit 1 of SVme indicates if mi1 is applied to RB / FRB / BB
474 * bit 2 of SVme indicates if mi2 is applied to RC / FRC / BC
475 * bit 3 of SVme indicates if mo0 is applied to RT / FRT / BT / BF
476 * bit 4 of SVme indicates if mo1 is applied to Effective Address / FRS / RS
477 (LD/ST-with-update has an implicit 2nd write register, RA)
478
479 The "persistence" bit if set will result in all Active REMAPs being applied
480 indefinitely.
481
482 ----------------
483
484 \newpage{}
485
486 # svremap instruction <a name="svremap"> </a>
487
488 SVRM-Form:
489
490 svremap SVme,mi0,mi1,mi2,mo0,mo2,pst
491
492 |0 |6 |11 |13 |15 |17 |19 |21 | 22:25 |26:31 |
493 | -- | -- | -- | -- | -- | -- | -- | -- | ---- | ----- |
494 | PO | SVme |mi0 | mi1 | mi2 | mo0 | mo1 | pst | rsvd | XO |
495
496 SVRM-Form
497
498 * svremap SVme,mi0,mi1,mi2,mo0,mo1,pst
499
500 Pseudo-code:
501
502 ```
503 # registers RA RB RC RT EA/FRS SVSHAPE0-3 indices
504 SVSTATE[32:33] <- mi0
505 SVSTATE[34:35] <- mi1
506 SVSTATE[36:37] <- mi2
507 SVSTATE[38:39] <- mo0
508 SVSTATE[40:41] <- mo1
509 # enable bit for RA RB RC RT EA/FRS
510 SVSTATE[42:46] <- SVme
511 # persistence bit (applies to more than one instruction)
512 SVSTATE[62] <- pst
513 ```
514
515 Special Registers Altered:
516
517 ```
518 SVSTATE
519 ```
520
521 `svremap` determines the relationship between registers and SVSHAPE SPRs.
522 The bitmask `SVme` determines which registers have a REMAP applied, and mi0-mo1
523 determine which shape is applied to an activated register. the `pst` bit if
524 cleared indicated that the REMAP operation shall only apply to the immediately-following
525 instruction. If set then REMAP remains permanently enabled until such time as it is
526 explicitly disabled, either by `setvl` setting a new MAXVL, or with another
527 `svremap` instruction. `svindex` and `svshape2` are also capable of setting or
528 clearing persistence, as well as partially covering a subset of the capability of
529 `svremap` to set register-to-SVSHAPE relationships.
530
531 Programmer's Note: applying non-persistent `svremap` to an instruction that has
532 no REMAP enabled or is a Scalar operation will obviously have no effect but
533 the bits 32 to 46 will at least have been set in SVSTATE. This may prove useful
534 when using `svindex` or `svshape2`.
535
536 Hardware Architectural Note: when persistence is not set it is critically important
537 to treat the `svremap` and the following SVP64 instruction as an indivisible fused operation.
538 *No state* is stored in the SVSTATE SPR in order to allow continuation should an
539 Interrupt occur between the two instructions. Thus, Interrupts must be prohibited
540 from occurring or other workaround deployed. When persistence is set this issue
541 is moot.
542
543 It is critical to note that if persistence is clear then `svremap` is the *only* way
544 to activate REMAP on any given (following) instruction. If persistence is set however then
545 **all** SVP64 instructions go through REMAP as long as `SVme` is non-zero.
546
547 -------------
548
549 \newpage{}
550
551 # SHAPE Remapping SPRs
552
553 There are four "shape" SPRs, SHAPE0-3, 32-bits in each,
554 which have the same format.
555
556 Shape is 32-bits. When SHAPE is set entirely to zeros, remapping is
557 disabled: the register's elements are a linear (1D) vector.
558
559 |31.30|29..28 |27..24| 23..21 | 20..18 | 17..12 |11..6 |5..0 | Mode |
560 |---- |------ |------| ------ | ------- | ------- |----- |----- | ----- |
561 |mode |skip |offset| invxyz | permute | zdimsz |ydimsz|xdimsz|Matrix |
562 |0b00 |elwidth|offset|sk1/invxy|0b110/0b111|SVGPR|ydimsz|xdimsz|Indexed|
563 |0b01 |submode|offset| invxyz | submode2| zdimsz |mode |xdimsz|DCT/FFT|
564 |0b10 |submode|offset| invxyz | rsvd | rsvd |rsvd |xdimsz|Preduce|
565 |0b11 | | | | | | | |rsvd |
566
567 mode sets different behaviours (straight matrix multiply, FFT, DCT).
568
569 * **mode=0b00** sets straight Matrix Mode
570 * **mode=0b00** with permute=0b110 or 0b111 sets Indexed Mode
571 * **mode=0b01** sets "FFT/DCT" mode and activates submodes
572 * **mode=0b10** sets "Parallel Reduction" Schedules.
573
574 ## Parallel Reduction Mode
575
576 Creates the Schedules for Parallel Tree Reduction.
577
578 * **submode=0b00** selects the left operand index
579 * **submode=0b01** selects the right operand index
580
581 * When bit 0 of `invxyz` is set, the order of the indices
582 in the inner for-loop are reversed. This has the side-effect
583 of placing the final reduced result in the last-predicated element.
584 It also has the indirect side-effect of swapping the source
585 registers: Left-operand index numbers will always exceed
586 Right-operand indices.
587 When clear, the reduced result will be in the first-predicated
588 element, and Left-operand indices will always be *less* than
589 Right-operand ones.
590 * When bit 1 of `invxyz` is set, the order of the outer loop
591 step is inverted: stepping begins at the nearest power-of two
592 to half of the vector length and reduces by half each time.
593 When clear the step will begin at 2 and double on each
594 inner loop.
595
596 ## FFT/DCT mode
597
598 submode2=0 is for FFT. For FFT submode the following schedules may be
599 selected:
600
601 * **submode=0b00** selects the ``j`` offset of the innermost for-loop
602 of Tukey-Cooley
603 * **submode=0b10** selects the ``j+halfsize`` offset of the innermost for-loop
604 of Tukey-Cooley
605 * **submode=0b11** selects the ``k`` of exptable (which coefficient)
606
607 When submode2 is 1 or 2, for DCT inner butterfly submode the following
608 schedules may be selected. When submode2 is 1, additional bit-reversing
609 is also performed.
610
611 * **submode=0b00** selects the ``j`` offset of the innermost for-loop,
612 in-place
613 * **submode=0b010** selects the ``j+halfsize`` offset of the innermost for-loop,
614 in reverse-order, in-place
615 * **submode=0b10** selects the ``ci`` count of the innermost for-loop,
616 useful for calculating the cosine coefficient
617 * **submode=0b11** selects the ``size`` offset of the outermost for-loop,
618 useful for the cosine coefficient ``cos(ci + 0.5) * pi / size``
619
620 When submode2 is 3 or 4, for DCT outer butterfly submode the following
621 schedules may be selected. When submode is 3, additional bit-reversing
622 is also performed.
623
624 * **submode=0b00** selects the ``j`` offset of the innermost for-loop,
625 * **submode=0b01** selects the ``j+1`` offset of the innermost for-loop,
626
627 `zdimsz` is used as an in-place "Stride", particularly useful for
628 column-based in-place DCT/FFT.
629
630 ## Matrix Mode
631
632 In Matrix Mode, skip allows dimensions to be skipped from being included
633 in the resultant output index. this allows sequences to be repeated:
634 ```0 0 0 1 1 1 2 2 2 ...``` or in the case of skip=0b11 this results in
635 modulo ```0 1 2 0 1 2 ...```
636
637 * **skip=0b00** indicates no dimensions to be skipped
638 * **skip=0b01** sets "skip 1st dimension"
639 * **skip=0b10** sets "skip 2nd dimension"
640 * **skip=0b11** sets "skip 3rd dimension"
641
642 invxyz will invert the start index of each of x, y or z. If invxyz[0] is
643 zero then x-dimensional counting begins from 0 and increments, otherwise
644 it begins from xdimsz-1 and iterates down to zero. Likewise for y and z.
645
646 offset will have the effect of offsetting the result by ```offset``` elements:
647
648 ```
649 for i in 0..VL-1:
650 GPR(RT + remap(i) + SVSHAPE.offset) = ....
651 ```
652
653 this appears redundant because the register RT could simply be changed by a compiler, until element width overrides are introduced. also
654 bear in mind that unlike a static compiler SVSHAPE.offset may
655 be set dynamically at runtime.
656
657 xdimsz, ydimsz and zdimsz are offset by 1, such that a value of 0 indicates
658 that the array dimensionality for that dimension is 1. any dimension
659 not intended to be used must have its value set to 0 (dimensionality
660 of 1). A value of xdimsz=2 would indicate that in the first dimension
661 there are 3 elements in the array. For example, to create a 2D array
662 X,Y of dimensionality X=3 and Y=2, set xdimsz=2, ydimsz=1 and zdimsz=0
663
664 The format of the array is therefore as follows:
665
666 ```
667 array[xdimsz+1][ydimsz+1][zdimsz+1]
668 ```
669
670 However whilst illustrative of the dimensionality, that does not take the
671 "permute" setting into account. "permute" may be any one of six values
672 (0-5, with values of 6 and 7 indicating "Indexed" Mode). The table
673 below shows how the permutation dimensionality order works:
674
675 | permute | order | array format |
676 | ------- | ----- | ------------------------ |
677 | 000 | 0,1,2 | (xdim+1)(ydim+1)(zdim+1) |
678 | 001 | 0,2,1 | (xdim+1)(zdim+1)(ydim+1) |
679 | 010 | 1,0,2 | (ydim+1)(xdim+1)(zdim+1) |
680 | 011 | 1,2,0 | (ydim+1)(zdim+1)(xdim+1) |
681 | 100 | 2,0,1 | (zdim+1)(xdim+1)(ydim+1) |
682 | 101 | 2,1,0 | (zdim+1)(ydim+1)(xdim+1) |
683 | 110 | 0,1 | Indexed (xdim+1)(ydim+1) |
684 | 111 | 1,0 | Indexed (ydim+1)(xdim+1) |
685
686 In other words, the "permute" option changes the order in which
687 nested for-loops over the array would be done. See executable
688 python reference code for further details.
689
690 *Note: permute=0b110 and permute=0b111 enable Indexed REMAP Mode,
691 described below*
692
693 With all these options it is possible to support in-place transpose,
694 in-place rotate, Matrix Multiply and Convolutions, without being
695 limited to Power-of-Two dimension sizes.
696
697 ## Indexed Mode
698
699 Indexed Mode activates reading of the element indices from the GPR
700 and includes optional limited 2D reordering.
701 In its simplest form (without elwidth overrides or other modes):
702
703 ```
704 def index_remap(i):
705 return GPR((SVSHAPE.SVGPR<<1)+i) + SVSHAPE.offset
706
707 for i in 0..VL-1:
708 element_result = ....
709 GPR(RT + indexed_remap(i)) = element_result
710 ```
711
712 With element-width overrides included, and using the pseudocode
713 from the SVP64 [[sv/svp64/appendix#elwidth]] elwidth section
714 this becomes:
715
716 ```
717 def index_remap(i):
718 svreg = SVSHAPE.SVGPR << 1
719 srcwid = elwid_to_bitwidth(SVSHAPE.elwid)
720 offs = SVSHAPE.offset
721 return get_polymorphed_reg(svreg, srcwid, i) + offs
722
723 for i in 0..VL-1:
724 element_result = ....
725 rt_idx = indexed_remap(i)
726 set_polymorphed_reg(RT, destwid, rt_idx, element_result)
727 ```
728
729 Matrix-style reordering still applies to the indices, except limited
730 to up to 2 Dimensions (X,Y). Ordering is therefore limited to (X,Y) or
731 (Y,X) for in-place Transposition.
732 Only one dimension may optionally be skipped. Inversion of either
733 X or Y or both is possible (2D mirroring). Pseudocode for Indexed Mode (including elwidth
734 overrides) may be written in terms of Matrix Mode, specifically
735 purposed to ensure that the 3rd dimension (Z) has no effect:
736
737 ```
738 def index_remap(ISHAPE, i):
739 MSHAPE.skip = 0b0 || ISHAPE.sk1
740 MSHAPE.invxyz = 0b0 || ISHAPE.invxy
741 MSHAPE.xdimsz = ISHAPE.xdimsz
742 MSHAPE.ydimsz = ISHAPE.ydimsz
743 MSHAPE.zdimsz = 0 # disabled
744 if ISHAPE.permute = 0b110 # 0,1
745 MSHAPE.permute = 0b000 # 0,1,2
746 if ISHAPE.permute = 0b111 # 1,0
747 MSHAPE.permute = 0b010 # 1,0,2
748 el_idx = remap_matrix(MSHAPE, i)
749 svreg = ISHAPE.SVGPR << 1
750 srcwid = elwid_to_bitwidth(ISHAPE.elwid)
751 offs = ISHAPE.offset
752 return get_polymorphed_reg(svreg, srcwid, el_idx) + offs
753 ```
754
755 The most important observation above is that the Matrix-style
756 remapping occurs first and the Index lookup second. Thus it
757 becomes possible to perform in-place Transpose of Indices which
758 may have been costly to set up or costly to duplicate
759 (waste register file space).
760
761 -------------
762
763 \newpage{}
764
765 # svshape instruction <a name="svshape"> </a>
766
767 SVM-Form
768
769 svshape SVxd,SVyd,SVzd,SVRM,vf
770
771 | 0:5|6:10 |11:15 |16:20 | 21:24 | 25 | 26:31 | name |
772 | -- | -- | --- | ----- | ------ | -- | ------| -------- |
773 |PO | SVxd | SVyd | SVzd | SVRM | vf | XO | svshape |
774
775 ```
776 # for convenience, VL to be calculated and stored in SVSTATE
777 vlen <- [0] * 7
778 mscale[0:5] <- 0b000001 # for scaling MAXVL
779 itercount[0:6] <- [0] * 7
780 SVSTATE[0:31] <- [0] * 32
781 # only overwrite REMAP if "persistence" is zero
782 if (SVSTATE[62] = 0b0) then
783 SVSTATE[32:33] <- 0b00
784 SVSTATE[34:35] <- 0b00
785 SVSTATE[36:37] <- 0b00
786 SVSTATE[38:39] <- 0b00
787 SVSTATE[40:41] <- 0b00
788 SVSTATE[42:46] <- 0b00000
789 SVSTATE[62] <- 0b0
790 SVSTATE[63] <- 0b0
791 # clear out all SVSHAPEs
792 SVSHAPE0[0:31] <- [0] * 32
793 SVSHAPE1[0:31] <- [0] * 32
794 SVSHAPE2[0:31] <- [0] * 32
795 SVSHAPE3[0:31] <- [0] * 32
796
797 # set schedule up for multiply
798 if (SVrm = 0b0000) then
799 # VL in Matrix Multiply is xd*yd*zd
800 xd <- (0b00 || SVxd) + 1
801 yd <- (0b00 || SVyd) + 1
802 zd <- (0b00 || SVzd) + 1
803 n <- xd * yd * zd
804 vlen[0:6] <- n[14:20]
805 # set up template in SVSHAPE0, then copy to 1-3
806 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
807 SVSHAPE0[6:11] <- (0b0 || SVyd) # ydim
808 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim
809 SVSHAPE0[28:29] <- 0b11 # skip z
810 # copy
811 SVSHAPE1[0:31] <- SVSHAPE0[0:31]
812 SVSHAPE2[0:31] <- SVSHAPE0[0:31]
813 SVSHAPE3[0:31] <- SVSHAPE0[0:31]
814 # set up FRA
815 SVSHAPE1[18:20] <- 0b001 # permute x,z,y
816 SVSHAPE1[28:29] <- 0b01 # skip z
817 # FRC
818 SVSHAPE2[18:20] <- 0b001 # permute x,z,y
819 SVSHAPE2[28:29] <- 0b11 # skip y
820
821 # set schedule up for FFT butterfly
822 if (SVrm = 0b0001) then
823 # calculate O(N log2 N)
824 n <- [0] * 3
825 do while n < 5
826 if SVxd[4-n] = 0 then
827 leave
828 n <- n + 1
829 n <- ((0b0 || SVxd) + 1) * n
830 vlen[0:6] <- n[1:7]
831 # set up template in SVSHAPE0, then copy to 1-3
832 # for FRA and FRT
833 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
834 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim - "striding" (2D FFT)
835 mscale <- (0b0 || SVzd) + 1
836 SVSHAPE0[30:31] <- 0b01 # Butterfly mode
837 # copy
838 SVSHAPE1[0:31] <- SVSHAPE0[0:31]
839 SVSHAPE2[0:31] <- SVSHAPE0[0:31]
840 # set up FRB and FRS
841 SVSHAPE1[28:29] <- 0b01 # j+halfstep schedule
842 # FRC (coefficients)
843 SVSHAPE2[28:29] <- 0b10 # k schedule
844
845 # set schedule up for (i)DCT Inner butterfly
846 # SVrm Mode 4 (Mode 12 for iDCT) is for on-the-fly (Vertical-First Mode)
847 if ((SVrm = 0b0100) |
848 (SVrm = 0b1100)) then
849 # calculate O(N log2 N)
850 n <- [0] * 3
851 do while n < 5
852 if SVxd[4-n] = 0 then
853 leave
854 n <- n + 1
855 n <- ((0b0 || SVxd) + 1) * n
856 vlen[0:6] <- n[1:7]
857 # set up template in SVSHAPE0, then copy to 1-3
858 # set up FRB and FRS
859 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
860 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim - "striding" (2D DCT)
861 mscale <- (0b0 || SVzd) + 1
862 if (SVrm = 0b1100) then
863 SVSHAPE0[30:31] <- 0b11 # iDCT mode
864 SVSHAPE0[18:20] <- 0b011 # iDCT Inner Butterfly sub-mode
865 else
866 SVSHAPE0[30:31] <- 0b01 # DCT mode
867 SVSHAPE0[18:20] <- 0b001 # DCT Inner Butterfly sub-mode
868 SVSHAPE0[21:23] <- 0b001 # "inverse" on outer loop
869 SVSHAPE0[6:11] <- 0b000011 # (i)DCT Inner Butterfly mode 4
870 # copy
871 SVSHAPE1[0:31] <- SVSHAPE0[0:31]
872 SVSHAPE2[0:31] <- SVSHAPE0[0:31]
873 if (SVrm != 0b0100) & (SVrm != 0b1100) then
874 SVSHAPE3[0:31] <- SVSHAPE0[0:31]
875 # for FRA and FRT
876 SVSHAPE0[28:29] <- 0b01 # j+halfstep schedule
877 # for cos coefficient
878 SVSHAPE2[28:29] <- 0b10 # ci (k for mode 4) schedule
879 SVSHAPE2[12:17] <- 0b000000 # reset costable "striding" to 1
880 if (SVrm != 0b0100) & (SVrm != 0b1100) then
881 SVSHAPE3[28:29] <- 0b11 # size schedule
882
883 # set schedule up for (i)DCT Outer butterfly
884 if (SVrm = 0b0011) | (SVrm = 0b1011) then
885 # calculate O(N log2 N) number of outer butterfly overlapping adds
886 vlen[0:6] <- [0] * 7
887 n <- 0b000
888 size <- 0b0000001
889 itercount[0:6] <- (0b00 || SVxd) + 0b0000001
890 itercount[0:6] <- (0b0 || itercount[0:5])
891 do while n < 5
892 if SVxd[4-n] = 0 then
893 leave
894 n <- n + 1
895 count <- (itercount - 0b0000001) * size
896 vlen[0:6] <- vlen + count[7:13]
897 size[0:6] <- (size[1:6] || 0b0)
898 itercount[0:6] <- (0b0 || itercount[0:5])
899 # set up template in SVSHAPE0, then copy to 1-3
900 # set up FRB and FRS
901 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
902 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim - "striding" (2D DCT)
903 mscale <- (0b0 || SVzd) + 1
904 if (SVrm = 0b1011) then
905 SVSHAPE0[30:31] <- 0b11 # iDCT mode
906 SVSHAPE0[18:20] <- 0b011 # iDCT Outer Butterfly sub-mode
907 SVSHAPE0[21:23] <- 0b101 # "inverse" on outer and inner loop
908 else
909 SVSHAPE0[30:31] <- 0b01 # DCT mode
910 SVSHAPE0[18:20] <- 0b100 # DCT Outer Butterfly sub-mode
911 SVSHAPE0[6:11] <- 0b000010 # DCT Butterfly mode
912 # copy
913 SVSHAPE1[0:31] <- SVSHAPE0[0:31] # j+halfstep schedule
914 SVSHAPE2[0:31] <- SVSHAPE0[0:31] # costable coefficients
915 # for FRA and FRT
916 SVSHAPE1[28:29] <- 0b01 # j+halfstep schedule
917 # reset costable "striding" to 1
918 SVSHAPE2[12:17] <- 0b000000
919
920 # set schedule up for DCT COS table generation
921 if (SVrm = 0b0101) | (SVrm = 0b1101) then
922 # calculate O(N log2 N)
923 vlen[0:6] <- [0] * 7
924 itercount[0:6] <- (0b00 || SVxd) + 0b0000001
925 itercount[0:6] <- (0b0 || itercount[0:5])
926 n <- [0] * 3
927 do while n < 5
928 if SVxd[4-n] = 0 then
929 leave
930 n <- n + 1
931 vlen[0:6] <- vlen + itercount
932 itercount[0:6] <- (0b0 || itercount[0:5])
933 # set up template in SVSHAPE0, then copy to 1-3
934 # set up FRB and FRS
935 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
936 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim - "striding" (2D DCT)
937 mscale <- (0b0 || SVzd) + 1
938 SVSHAPE0[30:31] <- 0b01 # DCT/FFT mode
939 SVSHAPE0[6:11] <- 0b000100 # DCT Inner Butterfly COS-gen mode
940 if (SVrm = 0b0101) then
941 SVSHAPE0[21:23] <- 0b001 # "inverse" on outer loop for DCT
942 # copy
943 SVSHAPE1[0:31] <- SVSHAPE0[0:31]
944 SVSHAPE2[0:31] <- SVSHAPE0[0:31]
945 # for cos coefficient
946 SVSHAPE1[28:29] <- 0b10 # ci schedule
947 SVSHAPE2[28:29] <- 0b11 # size schedule
948
949 # set schedule up for iDCT / DCT inverse of half-swapped ordering
950 if (SVrm = 0b0110) | (SVrm = 0b1110) | (SVrm = 0b1111) then
951 vlen[0:6] <- (0b00 || SVxd) + 0b0000001
952 # set up template in SVSHAPE0
953 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
954 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim - "striding" (2D DCT)
955 mscale <- (0b0 || SVzd) + 1
956 if (SVrm = 0b1110) then
957 SVSHAPE0[18:20] <- 0b001 # DCT opposite half-swap
958 if (SVrm = 0b1111) then
959 SVSHAPE0[30:31] <- 0b01 # FFT mode
960 else
961 SVSHAPE0[30:31] <- 0b11 # DCT mode
962 SVSHAPE0[6:11] <- 0b000101 # DCT "half-swap" mode
963
964 # set schedule up for parallel reduction
965 if (SVrm = 0b0111) then
966 # calculate the total number of operations (brute-force)
967 vlen[0:6] <- [0] * 7
968 itercount[0:6] <- (0b00 || SVxd) + 0b0000001
969 step[0:6] <- 0b0000001
970 i[0:6] <- 0b0000000
971 do while step <u itercount
972 newstep <- step[1:6] || 0b0
973 j[0:6] <- 0b0000000
974 do while (j+step <u itercount)
975 j <- j + newstep
976 i <- i + 1
977 step <- newstep
978 # VL in Parallel-Reduce is the number of operations
979 vlen[0:6] <- i
980 # set up template in SVSHAPE0, then copy to 1. only 2 needed
981 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim
982 SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim - "striding" (2D DCT)
983 mscale <- (0b0 || SVzd) + 1
984 SVSHAPE0[30:31] <- 0b10 # parallel reduce submode
985 # copy
986 SVSHAPE1[0:31] <- SVSHAPE0[0:31]
987 # set up right operand (left operand 28:29 is zero)
988 SVSHAPE1[28:29] <- 0b01 # right operand
989
990 # set VL, MVL and Vertical-First
991 m[0:12] <- vlen * mscale
992 maxvl[0:6] <- m[6:12]
993 SVSTATE[0:6] <- maxvl # MAVXL
994 SVSTATE[7:13] <- vlen # VL
995 SVSTATE[63] <- vf
996 ```
997
998 Special Registers Altered:
999
1000 ```
1001 SVSTATE, SVSHAPE0-3
1002 ```
1003
1004 `svshape` is a convenience instruction that reduces instruction
1005 count for common usage patterns, particularly Matrix, DCT and FFT. It sets up
1006 (overwrites) all required SVSHAPE SPRs and also modifies SVSTATE
1007 including VL and MAXVL. Using `svshape` therefore does not also
1008 require `setvl`.
1009
1010 Fields:
1011
1012 * **SVxd** - SV REMAP "xdim"
1013 * **SVyd** - SV REMAP "ydim"
1014 * **SVzd** - SV REMAP "zdim"
1015 * **SVRM** - SV REMAP Mode (0b00000 for Matrix, 0b00001 for FFT etc.)
1016 * **vf** - sets "Vertical-First" mode
1017 * **XO** - standard 6-bit XO field
1018
1019 *Note: SVxd, SVyz and SVzd are all stored "off-by-one". In the assembler
1020 mnemonic the values `1-32` are stored in binary as `0b00000..0b11111`*
1021
1022 There are 12 REMAP Modes (2 Modes are RESERVED for `svshape2`, 2 Modes
1023 are RESERVED)
1024
1025 | SVRM | Remap Mode description |
1026 | -- | -- |
1027 | 0b0000 | Matrix 1/2/3D |
1028 | 0b0001 | FFT Butterfly |
1029 | 0b0010 | reserved |
1030 | 0b0011 | DCT Outer butterfly |
1031 | 0b0100 | DCT Inner butterfly, on-the-fly (Vertical-First Mode) |
1032 | 0b0101 | DCT COS table index generation |
1033 | 0b0110 | DCT half-swap |
1034 | 0b0111 | Parallel Reduction |
1035 | 0b1000 | reserved for svshape2 |
1036 | 0b1001 | reserved for svshape2 |
1037 | 0b1010 | reserved |
1038 | 0b1011 | iDCT Outer butterfly |
1039 | 0b1100 | iDCT Inner butterfly, on-the-fly (Vertical-First Mode) |
1040 | 0b1101 | iDCT COS table index generation |
1041 | 0b1110 | iDCT half-swap |
1042 | 0b1111 | FFT half-swap |
1043
1044 Examples showing how all of these Modes operate exists in the online
1045 [SVP64 unit tests](https://git.libre-soc.org/?p=openpower-isa.git;a=tree;f=src/openpower/decoder/isa;hb=HEAD). Explaining
1046 these Modes further in detail is beyond the scope of this document.
1047
1048 In Indexed Mode, there are only 5 bits available to specify the GPR
1049 to use, out of 128 GPRs (7 bit numbering). Therefore, only the top
1050 5 bits are given in the `SVxd` field: the bottom two implicit bits
1051 will be zero (`SVxd || 0b00`).
1052
1053 `svshape` has *limited applicability* due to being a 32-bit instruction.
1054 The full capability of SVSHAPE SPRs may be accessed by directly writing
1055 to SVSHAPE0-3 with `mtspr`. Circumstances include Matrices with dimensions
1056 larger than 32, and in-place Transpose. Potentially a future v3.1 Prefixed
1057 instruction, `psvshape`, may extend the capability here.
1058
1059 *Architectural Resource Allocation note: the SVRM field is carefully
1060 crafted to allocate two Modes, corresponding to bits 21-23 within the
1061 instruction being set to the value `0b100`, to `svshape2` (not
1062 `svshape`). These two Modes are
1063 considered "RESERVED" within the context of `svshape` but it is
1064 absolutely critical to allocate the exact same pattern in XO for
1065 both instructions in bits 26-31.*
1066
1067 -------------
1068
1069 \newpage{}
1070
1071
1072 # svindex instruction <a name="svindex"> </a>
1073
1074 SVI-Form
1075
1076 | 0:5|6:10 |11:15 |16:20 | 21:25 | 26:31 | Form |
1077 | -- | -- | --- | ---- | ----------- | ------| -------- |
1078 | PO | SVG | rmm | SVd | ew/yx/mm/sk | XO | SVI-Form |
1079
1080 * svindex SVG,rmm,SVd,ew,SVyx,mm,sk
1081
1082 Pseudo-code:
1083
1084 ```
1085 # based on nearest MAXVL compute other dimension
1086 MVL <- SVSTATE[0:6]
1087 d <- [0] * 6
1088 dim <- SVd+1
1089 do while d*dim <u ([0]*4 || MVL)
1090 d <- d + 1
1091
1092 # set up template, then copy once location identified
1093 shape <- [0]*32
1094 shape[30:31] <- 0b00 # mode
1095 if SVyx = 0 then
1096 shape[18:20] <- 0b110 # indexed xd/yd
1097 shape[0:5] <- (0b0 || SVd) # xdim
1098 if sk = 0 then shape[6:11] <- 0 # ydim
1099 else shape[6:11] <- 0b111111 # ydim max
1100 else
1101 shape[18:20] <- 0b111 # indexed yd/xd
1102 if sk = 1 then shape[6:11] <- 0 # ydim
1103 else shape[6:11] <- d-1 # ydim max
1104 shape[0:5] <- (0b0 || SVd) # ydim
1105 shape[12:17] <- (0b0 || SVG) # SVGPR
1106 shape[28:29] <- ew # element-width override
1107 shape[21] <- sk # skip 1st dimension
1108
1109 # select the mode for updating SVSHAPEs
1110 SVSTATE[62] <- mm # set or clear persistence
1111 if mm = 0 then
1112 # clear out all SVSHAPEs first
1113 SVSHAPE0[0:31] <- [0] * 32
1114 SVSHAPE1[0:31] <- [0] * 32
1115 SVSHAPE2[0:31] <- [0] * 32
1116 SVSHAPE3[0:31] <- [0] * 32
1117 SVSTATE[32:41] <- [0] * 10 # clear REMAP.mi/o
1118 SVSTATE[42:46] <- rmm # rmm exactly REMAP.SVme
1119 idx <- 0
1120 for bit = 0 to 4
1121 if rmm[4-bit] then
1122 # activate requested shape
1123 if idx = 0 then SVSHAPE0 <- shape
1124 if idx = 1 then SVSHAPE1 <- shape
1125 if idx = 2 then SVSHAPE2 <- shape
1126 if idx = 3 then SVSHAPE3 <- shape
1127 SVSTATE[bit*2+32:bit*2+33] <- idx
1128 # increment shape index, modulo 4
1129 if idx = 3 then idx <- 0
1130 else idx <- idx + 1
1131 else
1132 # refined SVSHAPE/REMAP update mode
1133 bit <- rmm[0:2]
1134 idx <- rmm[3:4]
1135 if idx = 0 then SVSHAPE0 <- shape
1136 if idx = 1 then SVSHAPE1 <- shape
1137 if idx = 2 then SVSHAPE2 <- shape
1138 if idx = 3 then SVSHAPE3 <- shape
1139 SVSTATE[bit*2+32:bit*2+33] <- idx
1140 SVSTATE[46-bit] <- 1
1141 ```
1142
1143 Special Registers Altered:
1144
1145 ```
1146 SVSTATE, SVSHAPE0-3
1147 ```
1148
1149 `svindex` is a convenience instruction that reduces instruction count
1150 for Indexed REMAP Mode. It sets up (overwrites) all required SVSHAPE
1151 SPRs and **unlike** `svshape` can modify the REMAP area of the SVSTATE
1152 SPR as well, including setting persistence. The relevant SPRs *may*
1153 be directly programmed with `mtspr` however it is laborious to do so:
1154 svindex saves instructions covering much of Indexed REMAP capability.
1155
1156 Fields:
1157
1158 * **SVd** - SV REMAP x/y dim
1159 * **rmm** - REMAP mask: sets remap mi0-2/mo0-1 and SVSHAPEs,
1160 controlled by mm
1161 * **ew** - sets element width override on the Indices
1162 * **SVG** - GPR SVG<<2 to be used for Indexing
1163 * **yx** - 2D reordering to be used if yx=1
1164 * **mm** - mask mode. determines how `rmm` is interpreted.
1165 * **sk** - Dimension skipping enabled
1166
1167 *Note: SVd, like SVxd, SVyz and SVzd of `svshape`, are all stored
1168 "off-by-one". In the assembler
1169 mnemonic the values `1-32` are stored in binary as `0b00000..0b11111`*.
1170
1171 *Note: when `yx=1,sk=0` the second dimension is calculated as
1172 `CEIL(MAXVL/SVd)`*.
1173
1174 When `mm=0`:
1175
1176 * `rmm`, like REMAP.SVme, has bit 0
1177 correspond to mi0, bit 1 to mi1, bit 2 to mi2,
1178 bit 3 to mo0 and bit 4 to mi1
1179 * all SVSHAPEs and the REMAP parts of SVSHAPE are first reset (initialised to zero)
1180 * for each bit set in the 5-bit `rmm`, in order, the first
1181 as-yet-unset SVSHAPE will be updated
1182 with the other operands in the instruction, and the REMAP
1183 SPR set.
1184 * If all 5 bits of `rmm` are set then both mi0 and mo1 use SVSHAPE0.
1185 * SVSTATE persistence bit is cleared
1186 * No other alterations to SVSTATE are carried out
1187
1188 Example 1: if rmm=0b00110 then SVSHAPE0 and SVSHAPE1 are set up,
1189 and the REMAP SPR set so that mi1 uses SVSHAPE0 and mi2
1190 uses mi2. REMAP.SVme is also set to 0b00110, REMAP.mi1=0
1191 (SVSHAPE0) and REMAP.mi2=1 (SVSHAPE1)
1192
1193 Example 2: if rmm=0b10001 then again SVSHAPE0 and SVSHAPE1
1194 are set up, but the REMAP SPR is set so that mi0 uses SVSHAPE0
1195 and mo1 uses SVSHAPE1. REMAP.SVme=0b10001, REMAP.mi0=0, REMAP.mo1=1
1196
1197 Rough algorithmic form:
1198
1199 ```
1200 marray = [mi0, mi1, mi2, mo0, mo1]
1201 idx = 0
1202 for bit = 0 to 4:
1203 if not rmm[bit]: continue
1204 setup(SVSHAPE[idx])
1205 SVSTATE{marray[bit]} = idx
1206 idx = (idx+1) modulo 4
1207 ```
1208
1209 When `mm=1`:
1210
1211 * bits 0-2 (MSB0 numbering) of `rmm` indicate an index selecting mi0-mo1
1212 * bits 3-4 (MSB0 numbering) of `rmm` indicate which SVSHAPE 0-3 shall
1213 be updated
1214 * only the selected SVSHAPE is overwritten
1215 * only the relevant bits in the REMAP area of SVSTATE are updated
1216 * REMAP persistence bit is set.
1217
1218 Example 1: if `rmm`=0b01110 then bits 0-2 (MSB0) are 0b011 and
1219 bits 3-4 are 0b10. thus, mo0 is selected and SVSHAPE2
1220 to be updated. REMAP.SVme[3] will be set high and REMAP.mo0
1221 set to 2 (SVSHAPE2).
1222
1223 Example 2: if `rmm`=0b10011 then bits 0-2 (MSB0) are 0b100 and
1224 bits 3-4 are 0b11. thus, mo1 is selected and SVSHAPE3
1225 to be updated. REMAP.SVme[4] will be set high and REMAP.mo1
1226 set to 3 (SVSHAPE3).
1227
1228 Rough algorithmic form:
1229
1230 ```
1231 marray = [mi0, mi1, mi2, mo0, mo1]
1232 bit = rmm[0:2]
1233 idx = rmm[3:4]
1234 setup(SVSHAPE[idx])
1235 SVSTATE{marray[bit]} = idx
1236 SVSTATE.pst = 1
1237 ```
1238
1239 In essence, `mm=0` is intended for use to set as much of the
1240 REMAP State SPRs as practical with a single instruction,
1241 whilst `mm=1` is intended to be a little more refined.
1242
1243 **Usage guidelines**
1244
1245 * **Disable 2D mapping**: to only perform Indexing without
1246 reordering use `SVd=1,sk=0,yx=0` (or set SVd to a value larger
1247 or equal to VL)
1248 * **Modulo 1D mapping**: to perform Indexing cycling through the
1249 first N Indices use `SVd=N,sk=0,yx=0` where `VL>N`. There is
1250 no requirement to set VL equal to a multiple of N.
1251 * **Modulo 2D transposed**: `SVd=M,sk=0,yx=1`, sets
1252 `xdim=M,ydim=CEIL(MAXVL/M)`.
1253
1254 Beyond these mappings it becomes necessary to write directly to
1255 the SVSTATE SPRs manually.
1256
1257 -------------
1258
1259 \newpage{}
1260
1261
1262 # svshape2 (offset-priority) <a name="svshape2"> </a>
1263
1264 SVM2-Form
1265
1266 | 0:5|6:9 |10|11:15 |16:20 | 21:24 | 25 | 26:31 | Form |
1267 | -- |----|--| --- | ----- | ------ | -- | ------| -------- |
1268 | PO |offs|yx| rmm | SVd | 100/mm | sk | XO | SVM2-Form |
1269
1270 * svshape2 offs,yx,rmm,SVd,sk,mm
1271
1272 Pseudo-code:
1273
1274 ```
1275 # based on nearest MAXVL compute other dimension
1276 MVL <- SVSTATE[0:6]
1277 d <- [0] * 6
1278 dim <- SVd+1
1279 do while d*dim <u ([0]*4 || MVL)
1280 d <- d + 1
1281 # set up template, then copy once location identified
1282 shape <- [0]*32
1283 shape[30:31] <- 0b00 # mode
1284 shape[0:5] <- (0b0 || SVd) # x/ydim
1285 if SVyx = 0 then
1286 shape[18:20] <- 0b000 # ordering xd/yd(/zd)
1287 if sk = 0 then shape[6:11] <- 0 # ydim
1288 else shape[6:11] <- 0b111111 # ydim max
1289 else
1290 shape[18:20] <- 0b010 # ordering yd/xd(/zd)
1291 if sk = 1 then shape[6:11] <- 0 # ydim
1292 else shape[6:11] <- d-1 # ydim max
1293 # offset (the prime purpose of this instruction)
1294 shape[24:27] <- SVo # offset
1295 if sk = 1 then shape[28:29] <- 0b01 # skip 1st dimension
1296 else shape[28:29] <- 0b00 # no skipping
1297 # select the mode for updating SVSHAPEs
1298 SVSTATE[62] <- mm # set or clear persistence
1299 if mm = 0 then
1300 # clear out all SVSHAPEs first
1301 SVSHAPE0[0:31] <- [0] * 32
1302 SVSHAPE1[0:31] <- [0] * 32
1303 SVSHAPE2[0:31] <- [0] * 32
1304 SVSHAPE3[0:31] <- [0] * 32
1305 SVSTATE[32:41] <- [0] * 10 # clear REMAP.mi/o
1306 SVSTATE[42:46] <- rmm # rmm exactly REMAP.SVme
1307 idx <- 0
1308 for bit = 0 to 4
1309 if rmm[4-bit] then
1310 # activate requested shape
1311 if idx = 0 then SVSHAPE0 <- shape
1312 if idx = 1 then SVSHAPE1 <- shape
1313 if idx = 2 then SVSHAPE2 <- shape
1314 if idx = 3 then SVSHAPE3 <- shape
1315 SVSTATE[bit*2+32:bit*2+33] <- idx
1316 # increment shape index, modulo 4
1317 if idx = 3 then idx <- 0
1318 else idx <- idx + 1
1319 else
1320 # refined SVSHAPE/REMAP update mode
1321 bit <- rmm[0:2]
1322 idx <- rmm[3:4]
1323 if idx = 0 then SVSHAPE0 <- shape
1324 if idx = 1 then SVSHAPE1 <- shape
1325 if idx = 2 then SVSHAPE2 <- shape
1326 if idx = 3 then SVSHAPE3 <- shape
1327 SVSTATE[bit*2+32:bit*2+33] <- idx
1328 SVSTATE[46-bit] <- 1
1329 ```
1330
1331 Special Registers Altered:
1332
1333 ```
1334 SVSTATE, SVSHAPE0-3
1335 ```
1336
1337 `svshape2` is an additional convenience instruction that prioritises
1338 setting `SVSHAPE.offset`. Its primary purpose is for use when
1339 element-width overrides are used. It has identical capabilities to `svindex` and
1340 in terms of both options (skip, etc.) and ability to activate REMAP
1341 (rmm, mask mode) but unlike `svindex` it does not set GPR REMAP,
1342 only a 1D or 2D `svshape`, and
1343 unlike `svshape` it can set an arbirrary `SVSHAPE.offset` immediate.
1344
1345 One of the limitations of Simple-V is that Vector elements start on the boundary
1346 of the Scalar regfile, which is fine when element-width overrides are not
1347 needed. If the starting point of a Vector with smaller elwidths must begin
1348 in the middle of a register, normally there would be no way to do so except
1349 through LD/ST. `SVSHAPE.offset` caters for this scenario and `svshape2`is
1350 makes it easier.
1351
1352 **Operand Fields**:
1353
1354 * **offs** (4 bits) - unsigned offset
1355 * **yx** (1 bit) - swap XY to YX
1356 * **SVd** dimension size
1357 * **rmm** REMAP mask
1358 * **mm** mask mode
1359 * **sk** (1 bit) skips 1st dimension if set
1360
1361 Dimensions are calculated exactly as `svindex`. `rmm` and
1362 `mm` are as per `svindex`.
1363
1364 *Programmer's Note: offsets for `svshape2` may be specified in the range
1365 0-15. Given that the principle of Simple-V is to fit on top of
1366 byte-addressable register files and that GPR and FPR are 64-bit (8 bytes)
1367 it should be clear that the offset may, when `elwidth=8`, begin an
1368 element-level operation starting element zero at any arbitrary byte.
1369 On cursory examination attempting to go beyond the range 0-7 seems
1370 unnecessary given that the **next GPR or FPR** is an
1371 alias for an offset in the range 8-15. Thus by simply increasing
1372 the starting Vector point of the operation to the next register it
1373 can be seen that the offset of 0-7 would be sufficient. Unfortunately
1374 however some operations are EXTRA2-encoded it is **not possible**
1375 to increase the GPR/FPR register number by one, because EXTRA2-encoding
1376 of GPR/FPR Vector numbers are restricted to even numbering.
1377 For CR Fields the EXTRA2 encoding is even more sparse.
1378 The additional offset range (8-15) helps overcome these limitations.*
1379
1380 *Hardware Implementor's note: with the offsets only being immediates
1381 and with register numbering being entirely immediate as well it is
1382 possible to correctly compute Register Hazards without requiring
1383 reading the contents of any SPRs. If however there are
1384 instructions that have directly written to the SVSTATE or SVSHAPE
1385 SPRs and those instructions are still in-flight then this position
1386 is clearly **invalid**. This is why Programmers are strongly
1387 discouraged from directly writing to these SPRs.*
1388
1389 *Architectural Resource Allocation note: this instruction shares
1390 the space of `svshape`. Therefore it is critical that the two
1391 instructions, `svshape` and `svshape2` have the exact same XO
1392 in bits 26 thru 31. It is also critical that for `svshape2`,
1393 bit 21 of XO is a 1, bit 22 of XO is a 0, and bit 23 of XO is a 0.*
1394
1395 [[!tag standards]]
1396
1397 -------------
1398
1399 \newpage{}
1400