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