(no commit message)
[libreriscv.git] / simple_v_extension / specification.mdwn
1
2 # Simple-V (Parallelism Extension Proposal) Specification
3
4 * Copyright (C) 2017, 2018, 2019 Luke Kenneth Casson Leighton
5 * Status: DRAFTv0.6.1
6 * Last edited: 10 sep 2019
7 * Ancillary resource: [[opcodes]]
8 * Ancillary resource: [[sv_prefix_proposal]]
9 * Ancillary resource: [[abridged_spec]]
10 * Ancillary resource: [[vblock_format]]
11 * Ancillary resource: [[appendix]]
12
13 With thanks to:
14
15 * Allen Baum
16 * Bruce Hoult
17 * comp.arch
18 * Jacob Bachmeyer
19 * Guy Lemurieux
20 * Jacob Lifshay
21 * Terje Mathisen
22 * The RISC-V Founders, without whom this all would not be possible.
23
24 [[!toc ]]
25
26 # Summary and Background: Rationale
27
28 Simple-V is a uniform parallelism API for RISC-V hardware that has several
29 unplanned side-effects including code-size reduction, expansion of
30 HINT space and more. The reason for
31 creating it is to provide a manageable way to turn a pre-existing design
32 into a parallel one, in a step-by-step incremental fashion, without adding any new opcodes, thus allowing
33 the implementor to focus on adding hardware where it is needed and necessary.
34 The primary target is for mobile-class 3D GPUs and VPUs, with secondary
35 goals being to reduce executable size (by extending the effectiveness of RV opcodes, RVC in particular) and reduce context-switch latency.
36
37 Critically: **No new instructions are added**. The parallelism (if any
38 is implemented) is implicitly added by tagging *standard* scalar registers
39 for redirection. When such a tagged register is used in any instruction,
40 it indicates that the PC shall **not** be incremented; instead a loop
41 is activated where *multiple* instructions are issued to the pipeline
42 (as determined by a length CSR), with contiguously incrementing register
43 numbers starting from the tagged register. When the last "element"
44 has been reached, only then is the PC permitted to move on. Thus
45 Simple-V effectively sits (slots) *in between* the instruction decode phase
46 and the ALU(s).
47
48 The barrier to entry with SV is therefore very low. The minimum
49 compliant implementation is software-emulation (traps), requiring
50 only the CSRs and CSR tables, and that an exception be thrown if an
51 instruction's registers are detected to have been tagged. The looping
52 that would otherwise be done in hardware is thus carried out in software,
53 instead. Whilst much slower, it is "compliant" with the SV specification,
54 and may be suited for implementation in RV32E and also in situations
55 where the implementor wishes to focus on certain aspects of SV, without
56 unnecessary time and resources into the silicon, whilst also conforming
57 strictly with the API. A good area to punt to software would be the
58 polymorphic element width capability for example.
59
60 Hardware Parallelism, if any, is therefore added at the implementor's
61 discretion to turn what would otherwise be a sequential loop into a
62 parallel one.
63
64 To emphasise that clearly: Simple-V (SV) is *not*:
65
66 * A SIMD system
67 * A SIMT system
68 * A Vectorisation Microarchitecture
69 * A microarchitecture of any specific kind
70 * A mandatory parallel processor microarchitecture of any kind
71 * A supercomputer extension
72
73 SV does **not** tell implementors how or even if they should implement
74 parallelism: it is a hardware "API" (Application Programming Interface)
75 that, if implemented, presents a uniform and consistent way to *express*
76 parallelism, at the same time leaving the choice of if, how, how much,
77 when and whether to parallelise operations **entirely to the implementor**.
78
79 # Basic Operation
80
81 The principle of SV is as follows:
82
83 * Standard RV instructions are "prefixed" (extended) through a 48/64
84 bit format (single instruction option) or a variable
85 length VLIW-like prefix (multi or "grouped" option).
86 * The prefix(es) indicate which registers are "tagged" as
87 "vectorised". Predicates can also be added, and element widths
88 overridden on any src or dest register.
89 * A "Vector Length" CSR is set, indicating the span of any future
90 "parallel" operations.
91 * If any operation (a **scalar** standard RV opcode) uses a register
92 that has been so "marked" ("tagged"), a hardware "macro-unrolling loop"
93 is activated, of length VL, that effectively issues **multiple**
94 identical instructions using contiguous sequentially-incrementing
95 register numbers, based on the "tags".
96 * **Whether they be executed sequentially or in parallel or a
97 mixture of both or punted to software-emulation in a trap handler
98 is entirely up to the implementor**.
99
100 In this way an entire scalar algorithm may be vectorised with
101 the minimum of modification to the hardware and to compiler toolchains.
102
103 To reiterate: **There are *no* new opcodes**. The scheme works *entirely*
104 on hidden context that augments *scalar* RISCV instructions.
105
106 # CSRs <a name="csrs"></a>
107
108 * An optional "reshaping" CSR key-value table which remaps from a 1D
109 linear shape to 2D or 3D, including full transposition.
110
111 There are five additional CSRs, available in any privilege level:
112
113 * MVL (the Maximum Vector Length)
114 * VL (sets which scalar register is to be the Vector Length)
115 * SUBVL (effectively a kind of SIMD)
116 * STATE (containing copies of MVL, VL and SUBVL as well as context information)
117 * SVPSTATE (state information for SVPrefix)
118 * PCVBLK (the current operation being executed within a VBLOCK Group)
119
120 For User Mode there are the following CSRs:
121
122 * uePCVBLK (a copy of the sub-execution Program Counter, that is relative
123 to the start of the current VBLOCK Group, set on a trap).
124 * ueSTATE (useful for saving and restoring during context switch,
125 and for providing fast transitions)
126 * ueSVPSTATE when SVPrefix is implemented
127 Note: ueSVPSTATE is mirrored in the top 32 bits of ueSTATE.
128
129 There are also three additional CSRs for Supervisor-Mode:
130
131 * sePCVBLK
132 * seSTATE (which contains seSVPSTATE)
133 * seSVPSTATE
134
135 And likewise for M-Mode:
136
137 * mePCVBLK
138 * meSTATE (which contains meSVPSTATE)
139 * meSVPSTATE
140
141 The u/m/s CSRs are treated and handled exactly like their (x)epc
142 equivalents. On entry to or exit from a privilege level, the contents
143 of its (x)eSTATE are swapped with STATE.
144
145 Thus for example, a User Mode trap will end up swapping STATE and ueSTATE
146 (on both entry and exit), allowing User Mode traps to have their own
147 Vectorisation Context set up, separated from and unaffected by normal
148 user applications. If an M Mode trap occurs in the middle of the U Mode
149 trap, STATE is swapped with meSTATE, and restored on exit: the U Mode
150 trap continues unaware that the M Mode trap even occurred.
151
152 Likewise, Supervisor Mode may perform context-switches, safe in the
153 knowledge that its Vectorisation State is unaffected by User Mode.
154
155 The access pattern for these groups of CSRs in each mode follows the
156 same pattern for other CSRs that have M-Mode and S-Mode "mirrors":
157
158 * In M-Mode, the S-Mode and U-Mode CSRs are separate and distinct.
159 * In S-Mode, accessing and changing of the M-Mode CSRs is transparently
160 identical
161 to changing the S-Mode CSRs. Accessing and changing the U-Mode
162 CSRs is permitted.
163 * In U-Mode, accessing and changing of the S-Mode and U-Mode CSRs
164 is prohibited.
165
166 An interesting side effect of SV STATE being separate and distinct in S
167 Mode is that Vectorised saving of an entire register file to the stack
168 is a single instruction (through accidental provision of LOAD-MULTI
169 semantics). If the SVPrefix P64-LD-type format is used, LOAD-MULTI may
170 even be done with a single standalone 64 bit opcode (P64 may set up SVPSTATE.SUBVL,
171 SVPSTATE.VL and SVPSTATE.MVL from an immediate field, to cover the full regfile). It can
172 even be predicated, which opens up some very interesting possibilities.
173
174 (x)EPCVBLK CSRs must be treated exactly like their corresponding (x)epc
175 equivalents. See VBLOCK section for details.
176
177 ## MAXVECTORLENGTH (MVL) <a name="mvl" />
178
179 MAXVECTORLENGTH is the same concept as MVL in RVV, except that it
180 is variable length and may be dynamically set. MVL is
181 however limited to the regfile bitwidth XLEN (1-32 for RV32,
182 1-64 for RV64 and so on).
183
184 The reason for setting this limit is so that predication registers, when
185 marked as such, may fit into a single register as opposed to fanning
186 out over several registers. This keeps the hardware implementation a
187 little simpler.
188
189 The other important factor to note is that the actual MVL is internally
190 stored **offset by one**, so that it can fit into only 6 bits (for RV64)
191 and still cover a range up to XLEN bits. Attempts to set MVL to zero will
192 return an exception. This is expressed more clearly in the "pseudocode"
193 section, where there are subtle differences between CSRRW and CSRRWI.
194
195 ## Vector Length (VL) <a name="vl" />
196
197 VL is very different from RVV's VL. It contains the scalar register *number* that is to be treated as the Vector Length. It is a sub-field of STATE. When set to zero (x0) VL (vectorisation) is disabled.
198
199 Implementations realistically should keep a cached copy of the register pointed to by VL in the instruction issue and decode phases. Out of Order Engines must then, if it is not x0, add this register to Vectorised instruction Dependency Checking as an additional read/write hazard as appropriate.
200
201 Setting VL via this CSR is very unusual. It should not normally be needed except when [[specification/sv.setvl]] is not implemented. Note that unlike in sv.setvl, setting VL does not change the contents of the scalar register that it points to, although if the scalar register's contents are not within the range of MVL at the time that VL is set, an illegal instruction exception must be raised.
202
203 ## SUBVL - Sub Vector Length
204
205 This is a "group by quantity" that effectively asks each iteration
206 of the hardware loop to load SUBVL elements of width elwidth at a
207 time. Effectively, SUBVL is like a SIMD multiplier: instead of just 1
208 operation issued, SUBVL operations are issued.
209
210 Another way to view SUBVL is that each element in the VL length vector is
211 now SUBVL times elwidth bits in length and now comprises SUBVL discrete
212 sub operations. This can be viewed as an inner SUBVL hardware for-loop within a VL hardware for-loop in effect,
213 with the sub-element increased every time in the innermost loop. This
214 is best illustrated in the (simplified) pseudocode example, in the
215 [[appendix]].
216
217 The primary use case for SUBVL is for 3D FP Vectors. A Vector of 3D
218 coordinates X,Y,Z for example may be loaded and multiplied then stored, per
219 VL element iteration, rather than having to set VL to three times larger.
220
221 Setting this CSR to 0 must raise an exception. Setting it to a value
222 greater than 4 likewise. To see the relationship with STATE, see below.
223
224 The main effect of SUBVL is that predication bits are applied per
225 **group**, rather than by individual element.
226
227 This saves a not insignificant number of instructions when handling 3D
228 vectors, as otherwise a much longer predicate mask would have to be set
229 up with regularly-repeated bit patterns.
230
231 See SUBVL Pseudocode illustration in the [[appendix]], for details.
232
233 ## STATE
234
235 out of date, see <http://lists.libre-riscv.org/pipermail/libre-riscv-dev/2019-June/001896.html>
236
237 This is a standard CSR that contains sufficient information for a
238 full context save/restore. It contains (and permits setting of):
239
240 * MVL
241 * VL
242 * destoffs - the destination element offset of the current parallel
243 instruction being executed
244 * srcoffs - for twin-predication, the source element offset as well.
245 * SUBVL
246 * svdestoffs - the subvector destination element offset of the current
247 parallel instruction being executed
248
249 Interestingly STATE may hypothetically also be modified to make the
250 immediately-following instruction to skip a certain number of elements,
251 by playing with destoffs and srcoffs (and the subvector offsets as well)
252
253 Setting destoffs and srcoffs is realistically intended for saving state
254 so that exceptions (page faults in particular) may be serviced and the
255 hardware-loop that was being executed at the time of the trap, from
256 user-mode (or Supervisor-mode), may be returned to and continued from
257 exactly where it left off. The reason why this works is because setting
258 User-Mode STATE will not change (not be used) in M-Mode or S-Mode (and
259 is entirely why M-Mode and S-Mode have their own STATE CSRs, meSTATE
260 and seSTATE).
261
262 The format of the STATE CSR is as follows:
263
264 | (31..28) | (27..26) | (25..24) | (23..18) | (17..12) | (11..6) | (5...0) |
265 | -------- | -------- | -------- | -------- | -------- | ------- | ------- |
266 | rsvd | dsvoffs | subvl | destoffs | srcoffs | vl | maxvl |
267
268 Legal values of vl are between 0 and 31.
269
270 The relationship between SUBVL and the subvl field is:
271
272 | SUBVL | (25..24) |
273 | ----- | -------- |
274 | 1 | 0b00 |
275 | 2 | 0b01 |
276 | 3 | 0b10 |
277 | 4 | 0b11 |
278
279 When setting this CSR, the following characteristics will be enforced:
280
281 * **MAXVL** will be truncated (after offset) to be within the range 1 to XLEN
282 * **VL** must be set to a scalar register between 0 and 31.
283 * **SUBVL** which sets a SIMD-like quantity, has only 4 values so there
284 are no changes needed
285 * **srcoffs** will be truncated to be within the range 0 to VL-1
286 * **destoffs** will be truncated to be within the range 0 to VL-1
287 * **dsvoffs** will be truncated to be within the range 0 to SUBVL-1
288
289 NOTE: if the following instruction is not a twin predicated instruction,
290 and destoffs or dsvoffs has been set to non-zero, subsequent execution
291 behaviour is undefined. **USE WITH CARE**.
292
293 NOTE: sub-vector looping does not require a twin-predicate corresponding
294 index, because sub-vectors use the *main* (VL) loop predicate bit.
295
296 When SVPrefix is implemented, it can have its own VL, MVL and SUBVL, as well as element offsets. SVSTATE.VL acts slightly differently in that it is no longer a pointer to a scalar register but is an actual value just like RVV's VL.
297
298 The format of SVSTATE, which fits into *both* the top bits of STATE and also into a separate CSR, is as follows:
299
300 | (31..28) | (27..26) | (25..24) | (23..18) | (17..12) | (11..6) | (5...0) |
301 | -------- | -------- | -------- | -------- | -------- | ------- | ------- |
302 | rsvd | dsvoffs | subvl | destoffs | srcoffs | vl | maxvl |
303
304 ### Hardware rules for when to increment STATE offsets
305
306 The offsets inside STATE are like the indices in a loop, except
307 in hardware. They are also partially (conceptually) similar to a
308 "sub-execution Program Counter". As such, and to allow proper context
309 switching and to define correct exception behaviour, the following rules
310 must be observed:
311
312 * When the VL CSR is set, srcoffs and destoffs are reset to zero.
313 * Each instruction that contains a "tagged" register shall start
314 execution at the *current* value of srcoffs (and destoffs in the case
315 of twin predication)
316 * Unpredicated bits (in nonzeroing mode) shall cause the element operation
317 to skip, incrementing the srcoffs (or destoffs)
318 * On execution of an element operation, Exceptions shall **NOT** cause
319 srcoffs or destoffs to increment.
320 * On completion of the full Vector Loop (srcoffs = VL-1 or destoffs =
321 VL-1 after the last element is executed), both srcoffs and destoffs
322 shall be reset to zero.
323
324 This latter is why srcoffs and destoffs may be stored as values from
325 0 to XLEN-1 in the STATE CSR, because as loop indices they refer to
326 elements. srcoffs and destoffs never need to be set to VL: their maximum
327 operating values are limited to 0 to VL-1.
328
329 The same corresponding rules apply to SUBVL, svsrcoffs and svdestoffs.
330
331 ## MVL and VL Pseudocode
332
333 The pseudo-code for get and set of VL and MVL use the following internal
334 functions as follows:
335
336 set_mvl_csr(value, rd):
337 STATE.MVL = MIN(value, STATE.MVL)
338
339 get_mvl_csr(rd):
340 regs[rd] = STATE.VL
341
342 set_vl_csr(value, rd):
343 STATE.VL = rd
344 return STATE.VL
345
346 get_vl_csr(rd):
347 return STATE.VL
348
349 Note that where setting MVL behaves as a normal CSR (returns the old
350 value), unlike standard CSR behaviour, setting VL will return the **new**
351 value of VL **not** the old one.
352
353 For CSRRWI, the range of the immediate is restricted to 5 bits. In order to
354 maximise the effectiveness, an immediate of 0 is used to set VL=1,
355 an immediate of 1 is used to set VL=2 and so on:
356
357 CSRRWI_Set_MVL(value):
358 set_mvl_csr(value+1, x0)
359
360 CSRRWI_Set_VL(value):
361 set_vl_csr(value+1, x0)
362
363 However for CSRRW the following pseudocode is used for MVL and VL,
364 where setting the value to zero will cause an exception to be raised.
365 The reason is that if VL or MVL are set to zero, the STATE CSR is
366 not capable of storing that value.
367
368 CSRRW_Set_MVL(rs1, rd):
369 value = regs[rs1]
370 if value == 0 or value > XLEN:
371 raise Exception
372 set_mvl_csr(value, rd)
373
374 CSRRW_Set_VL(rs1, rd):
375 value = regs[rs1]
376 if value == 0 or value > XLEN:
377 raise Exception
378 set_vl_csr(value, rd)
379
380 In this way, when CSRRW is utilised with a loop variable, the value
381 that goes into VL (and into the destination register) may be used
382 in an instruction-minimal fashion:
383
384 CSRvect1 = {type: F, key: a3, val: a3, elwidth: dflt}
385 CSRvect2 = {type: F, key: a7, val: a7, elwidth: dflt}
386 CSRRWI MVL, 3 # sets MVL == **4** (not 3)
387 j zerotest # in case loop counter a0 already 0
388 loop:
389 CSRRW VL, t0, a0 # vl = t0 = min(mvl, a0)
390 ld a3, a1 # load 4 registers a3-6 from x
391 slli t1, t0, 3 # t1 = vl * 8 (in bytes)
392 ld a7, a2 # load 4 registers a7-10 from y
393 add a1, a1, t1 # increment pointer to x by vl*8
394 fmadd a7, a3, fa0, a7 # v1 += v0 * fa0 (y = a * x + y)
395 sub a0, a0, t0 # n -= vl (t0)
396 st a7, a2 # store 4 registers a7-10 to y
397 add a2, a2, t1 # increment pointer to y by vl*8
398 zerotest:
399 bnez a0, loop # repeat if n != 0
400
401 With the STATE CSR, just like with CSRRWI, in order to maximise the
402 utilisation of the limited bitspace, "000000" in binary represents
403 VL==1, "00001" represents VL==2 and so on (likewise for MVL):
404
405 CSRRW_Set_SV_STATE(rs1, rd):
406 value = regs[rs1]
407 get_state_csr(rd)
408 STATE.MVL = set_mvl_csr(value[11:6]+1)
409 STATE.VL = set_vl_csr(value[5:0]+1)
410 STATE.destoffs = value[23:18]>>18
411 STATE.srcoffs = value[23:18]>>12
412
413 get_state_csr(rd):
414 regs[rd] = (STATE.MVL-1) | (STATE.VL-1)<<6 | (STATE.srcoffs)<<12 |
415 (STATE.destoffs)<<18
416 return regs[rd]
417
418 In both cases, whilst CSR read of VL and MVL return the exact values
419 of VL and MVL respectively, reading and writing the STATE CSR returns
420 those values **minus one**. This is absolutely critical to implement
421 if the STATE CSR is to be used for fast context-switching.
422
423 ## VL, MVL and SUBVL instruction aliases
424
425 This table contains pseudo-assembly instruction aliases. Note the
426 subtraction of 1 from the CSRRWI pseudo variants, to compensate for the
427 reduced range of the 5 bit immediate.
428
429 | alias | CSR |
430 | - | - |
431 | SETVL rd, rs | CSRRW VL, rd, rs |
432 | SETVLi rd, #n | CSRRWI VL, rd, #n-1 |
433 | GETVL rd | CSRRW VL, rd, x0 |
434 | SETMVL rd, rs | CSRRW MVL, rd, rs |
435 | SETMVLi rd, #n | CSRRWI MVL,rd, #n-1 |
436 | GETMVL rd | CSRRW MVL, rd, x0 |
437
438 Note: CSRRC and other bitsetting may still be used, they are however not particularly useful (very obscure).
439
440 ## Register key-value (CAM) table <a name="regcsrtable" />
441
442 *NOTE: in prior versions of SV, this table used to be writable and
443 accessible via CSRs. It is now stored in the VBLOCK instruction format. Note
444 that this table does *not* get applied to the SVPrefix P48/64 format,
445 only to scalar opcodes*
446
447 The purpose of the Register table is three-fold:
448
449 * To mark integer and floating-point registers as requiring "redirection"
450 if it is ever used as a source or destination in any given operation.
451 This involves a level of indirection through a 5-to-7-bit lookup table,
452 such that **unmodified** operands with 5 bits (3 for some RVC ops) may
453 access up to **128** registers.
454 * To indicate whether, after redirection through the lookup table, the
455 register is a vector (or remains a scalar).
456 * To over-ride the implicit or explicit bitwidth that the operation would
457 normally give the register.
458
459 Note: clearly, if an RVC operation uses a 3 bit spec'd register (x8-x15)
460 and the Register table contains entried that only refer to registerd
461 x1-x14 or x16-x31, such operations will *never* activate the VL hardware
462 loop!
463
464 If however the (16 bit) Register table does contain such an entry (x8-x15
465 or x2 in the case of LWSP), that src or dest reg may be redirected
466 anywhere to the *full* 128 register range. Thus, RVC becomes far more
467 powerful and has many more opportunities to reduce code size that in
468 Standard RV32/RV64 executables.
469
470 [[!inline raw="yes" pages="simple_v_extension/reg_table_format" ]]
471
472 i/f is set to "1" to indicate that the redirection/tag entry is to
473 be applied to integer registers; 0 indicates that it is relevant to
474 floating-point registers.
475
476 The 8 bit format is used for a much more compact expression. "isvec"
477 is implicit and, similar to [[sv_prefix_proposal]], the target vector
478 is "regnum<<2", implicitly. Contrast this with the 16-bit format where
479 the target vector is *explicitly* named in bits 8 to 14, and bit 15 may
480 optionally set "scalar" mode.
481
482 Note that whilst SVPrefix adds one extra bit to each of rd, rs1 etc.,
483 and thus the "vector" mode need only shift the (6 bit) regnum by 1 to
484 get the actual (7 bit) register number to use, there is not enough space
485 in the 8 bit format (only 5 bits for regnum) so "regnum<<2" is required.
486
487 vew has the following meanings, indicating that the instruction's
488 operand size is "over-ridden" in a polymorphic fashion:
489
490 | vew | bitwidth |
491 | --- | ------------------- |
492 | 00 | default (XLEN/FLEN) |
493 | 01 | 8 bit |
494 | 10 | 16 bit |
495 | 11 | 32 bit |
496
497 As the above table is a CAM (key-value store) it may be appropriate
498 (faster, implementation-wise) to expand it as follows:
499
500 [[!inline raw="yes" pages="simple_v_extension/reg_table" ]]
501
502 ## Predication Table <a name="predication_csr_table"></a>
503
504 *NOTE: in prior versions of SV, this table used to be writable and
505 accessible via CSRs. It is now stored in the VBLOCK instruction format.
506 The table does **not** apply to SVPrefix opcodes*
507
508 The Predication Table is a key-value store indicating whether, if a
509 given destination register (integer or floating-point) is referred to
510 in an instruction, it is to be predicated. Like the Register table, it
511 is an indirect lookup that allows the RV opcodes to not need modification.
512
513 It is particularly important to note
514 that the *actual* register used can be *different* from the one that is
515 in the instruction, due to the redirection through the lookup table.
516
517 * regidx is the register that in combination with the
518 i/f flag, if that integer or floating-point register is referred to in a
519 (standard RV) instruction results in the lookup table being referenced
520 to find the predication mask to use for this operation.
521 * predidx is the *actual* (full, 7 bit) register to be used for the
522 predication mask.
523 * inv indicates that the predication mask bits are to be inverted
524 prior to use *without* actually modifying the contents of the
525 register from which those bits originated.
526 * zeroing is either 1 or 0, and if set to 1, the operation must
527 place zeros in any element position where the predication mask is
528 set to zero. If zeroing is set to 0, unpredicated elements *must*
529 be left alone. Some microarchitectures may choose to interpret
530 this as skipping the operation entirely. Others which wish to
531 stick more closely to a SIMD architecture may choose instead to
532 interpret unpredicated elements as an internal "copy element"
533 operation (which would be necessary in SIMD microarchitectures
534 that perform register-renaming)
535 * ffirst is a special mode that stops sequential element processing when
536 a data-dependent condition occurs, whether a trap or a conditional test.
537 The handling of each (trap or conditional test) is slightly different:
538 see Instruction sections for further details
539
540 [[!inline raw="yes" pages="simple_v_extension/pred_table_format" ]]
541
542 The 8 bit format is a compact and less expressive variant of the full
543 16 bit format. Using the 8 bit format is very different: the predicate
544 register to use is implicit, and numbering begins inplicitly from x9. The
545 regnum is still used to "activate" predication, in the same fashion as
546 described above.
547
548 The 16 bit Predication CSR Table is a key-value store, so
549 implementation-wise it will be faster to turn the table around (maintain
550 topologically equivalent state). Opportunities then exist to access
551 registers in unary form instead of binary, saving gates and power by
552 only activating "redirection" with a single AND gate, instead of
553 multiple multi-bit XORs (a CAM):
554
555 [[!inline raw="yes" pages="simple_v_extension/pred_table" ]]
556
557 So when an operation is to be predicated, it is the internal state that
558 is used. In Section 6.4.2 of Hwacha's Manual (EECS-2015-262) the following
559 pseudo-code for operations is given, where p is the explicit (direct)
560 reference to the predication register to be used:
561
562 for (int i=0; i<vl; ++i)
563 if ([!]preg[p][i])
564 (d ? vreg[rd][i] : sreg[rd]) =
565 iop(s1 ? vreg[rs1][i] : sreg[rs1],
566 s2 ? vreg[rs2][i] : sreg[rs2]); // for insts with 2 inputs
567
568 This instead becomes an *indirect* reference using the *internal* state
569 table generated from the Predication CSR key-value store, which is used
570 as follows.
571
572 if type(iop) == INT:
573 preg = int_pred_reg[rd]
574 else:
575 preg = fp_pred_reg[rd]
576
577 for (int i=0; i<vl; ++i)
578 predicate, zeroing = get_pred_val(type(iop) == INT, rd):
579 if (predicate && (1<<i))
580 result = iop(s1 ? regfile[rs1+i] : regfile[rs1],
581 s2 ? regfile[rs2+i] : regfile[rs2]);
582 (d ? regfile[rd+i] : regfile[rd]) = result
583 if preg.ffirst and result == 0:
584 VL = i # result was zero, end loop early, return VL
585 return
586 else if (zeroing)
587 (d ? regfile[rd+i] : regfile[rd]) = 0
588
589 Note:
590
591 * d, s1 and s2 are booleans indicating whether destination,
592 source1 and source2 are vector or scalar
593 * key-value CSR-redirection of rd, rs1 and rs2 have NOT been included
594 above, for clarity. rd, rs1 and rs2 all also must ALSO go through
595 register-level redirection (from the Register table) if they are
596 vectors.
597 * fail-on-first mode stops execution early whenever an operation
598 returns a zero value. floating-point results count both
599 positive-zero as well as negative-zero as "fail".
600
601 If written as a function, obtaining the predication mask (and whether
602 zeroing takes place) may be done as follows:
603
604 [[!inline raw="yes" pages="simple_v_extension/get_pred_value" ]]
605
606 Note here, critically, that **only** if the register is marked
607 in its **register** table entry as being "active" does the testing
608 proceed further to check if the **predicate** table entry is
609 also active.
610
611 Note also that this is in direct contrast to branch operations
612 for the storage of comparisions: in these specific circumstances
613 the requirement for there to be an active *register* entry
614 is removed.
615
616 ## Fail-on-First Mode <a name="ffirst-mode"></a>
617
618 ffirst is a special data-dependent predicate mode. There are two
619 variants: one is for faults: typically for LOAD/STORE operations,
620 which may encounter end of page faults during a series of operations.
621 The other variant is comparisons such as FEQ (or the augmented behaviour
622 of Branch), and any operation that returns a result of zero (whether
623 integer or floating-point). In the FP case, this includes negative-zero.
624
625 ffirst interacts with zero- and non-zero predication. In non-zeroing
626 mode, masked-out operations are simply excluded from testing (can never
627 fail). However for fail-comparisons (not faults) in zeroing mode, the
628 result will be zero: this *always* "fails", thus on the very first
629 masked-out element ffirst will always terminate.
630
631 Note that ffirst mode works because the execution order must "appear" to be
632 (in "program order"). An in-order architecture must execute the element
633 operations in sequence, whilst an out-of-order architecture must *commit*
634 the element operations in sequence and cancel speculatively-executed
635 ones (giving the appearance of in-order execution).
636
637 Note also, that if ffirst mode is needed without predication, a special
638 "always-on" Predicate Table Entry may be constructed by setting
639 inverse-on and using x0 as the predicate register. This
640 will have the effect of creating a mask of all ones, allowing ffirst
641 to be set.
642
643 See [[appendix]] for more details on fail-on-first modes, as well as
644 pseudo-code, below.
645
646 ## REMAP and SHAPE CSRs <a name="remap" />
647
648 See optional [[remap]] section.
649
650 # Instruction Execution Order
651
652 Simple-V behaves as if it is a hardware-level "macro expansion system",
653 substituting and expanding a single instruction into multiple sequential
654 instructions with contiguous and sequentially-incrementing registers.
655 As such, it does **not** modify - or specify - the behaviour and semantics of
656 the execution order: that may be deduced from the **existing** RV
657 specification in each and every case.
658
659 So for example if a particular micro-architecture permits out-of-order
660 execution, and it is augmented with Simple-V, then wherever instructions
661 may be out-of-order then so may the "post-expansion" SV ones.
662
663 If on the other hand there are memory guarantees which specifically
664 prevent and prohibit certain instructions from being re-ordered
665 (such as the Atomicity Axiom, or FENCE constraints), then clearly
666 those constraints **MUST** also be obeyed "post-expansion".
667
668 It should be absolutely clear that SV is **not** about providing new
669 functionality or changing the existing behaviour of a micro-architetural
670 design, or about changing the RISC-V Specification.
671 It is **purely** about compacting what would otherwise be contiguous
672 instructions that use sequentially-increasing register numbers down
673 to the **one** instruction.
674
675 # Instructions <a name="instructions" />
676
677 See [[appendix]] for specific cases where instruction behaviour is
678 augmented. A greatly simplified example is below. Note that this
679 is the ADD implementation, not a separate VADD instruction:
680
681 [[!inline raw="yes" pages="simple_v_extension/simple_add_example" ]]
682
683 Note that several things have been left out of this example.
684 See [[appendix]] for additional examples that show how to add
685 support for additional features (twin predication, elwidth,
686 zeroing, SUBVL etc.)
687
688 Branches in particular have been transparently augmented to include
689 "collation" of comparison results into a tagged register.
690
691 # Exceptions
692
693 Exceptions may occur at any time, in any given underlying scalar
694 operation. This implies that context-switching (traps) may occur, and
695 operation must be returned to where it left off. That in turn implies
696 that the full state - including the current parallel element being
697 processed - has to be saved and restored. This is what the **STATE**
698 and **PCVBLK** CSRs are for.
699
700 The implications are that all underlying individual scalar operations
701 "issued" by the parallelisation have to appear to be executed sequentially.
702 The further implications are that if two or more individual element
703 operations are underway, and one with an earlier index causes an exception,
704 it will be necessary for the microarchitecture to **discard** or terminate
705 operations with higher indices. Optimisated microarchitectures could
706 hypothetically store (cache) results, for subsequent replay if appropriate.
707
708 In short: exception handling **MUST** be precise, in-order, and exactly
709 like Standard RISC-V as far as the instruction execution order is
710 concerned, regardless of whether it is PC, PCVBLK, VL or SUBVL that
711 is currently being incremented.
712
713 # Hints
714
715 A "HINT" is an operation that has no effect on architectural state,
716 where its use may, by agreed convention, give advance notification
717 to the microarchitecture: branch prediction notification would be
718 a good example. Usually HINTs are where rd=x0.
719
720 With Simple-V being capable of issuing *parallel* instructions where
721 rd=x0, the space for possible HINTs is expanded considerably. VL
722 could be used to indicate different hints. In addition, if predication
723 is set, the predication register itself could hypothetically be passed
724 in as a *parameter* to the HINT operation.
725
726 No specific hints are yet defined in Simple-V
727
728 # Vector Block Format <a name="vliw-format"></a>
729
730 The VBLOCK Format allows Register, Predication and Vector Length to be contextually associated with a group of RISC-V scalar opcodes. The format is as follows:
731
732 [[!inline raw="yes" pages="simple_v_extension/vblock_format_table" ]]
733
734 For more details, including the CSRs, see ancillary resource: [[vblock_format]]
735
736 # Under consideration <a name="issues"></a>
737
738 See [[discussion]]
739