(no commit message)
[libreriscv.git] / simple_v_extension / abridged_spec.mdwn
index 65e0f373d126ea7c7a4267dacca0b55106397c6e..09cbf340cd6c5dedcebcf295e2fc5a3408d37a4e 100644 (file)
@@ -1,8 +1,10 @@
+[[!tag standards]]
+
 # Simple-V (Parallelism Extension Proposal) Specification (Abridged)
 
 * Copyright (C) 2017, 2018, 2019 Luke Kenneth Casson Leighton
 * Status: DRAFTv0.6
-* Last edited: 25 jun 2019
+* Last edited: 27 jun 2019
 * See: main [[specification]] and [[appendix]]
 
 [[!toc ]]
@@ -13,6 +15,11 @@ Simple-V is a uniform parallelism API for RISC-V hardware that allows
 the Program Counter to enter "sub-contexts" in which, ultimately, standard
 RISC-V scalar opcodes are executed.
 
+Regardless of the actual amount of hardware parallelism (if any is
+added at all by the implementor),
+in direct contrast to SIMD
+hardware parallelism is entirely transparent to software.
+
 The sub-context execution is "nested" in "re-entrant" form, in the
 following order:
 
@@ -20,28 +27,35 @@ following order:
 * VBLOCK sub-execution context (PCVBLK increments whilst PC is paused).
 * VL element loops (STATE srcoffs and destoffs increment, PC and PCVBLK pause).
   Predication bits may be individually applied per element.
-* SUBVL element loops (STATE svsrcoffs/svdestoffs increment, VL pauses).
+* Optional SUBVL element loops (STATE svdestoffs increments, VL pauses).
   Individual predicate bits from VL loops apply to the *group* of SUBVL
   elements.
 
-An ancillary "SVPrefix" Format (P48/P64) [[sv_prefix_proposal]] may
-run its own VL/SUBVL "loops" and specifies its own Register and Predication
+An ancillary "SVPrefix" Format (P48/P64) [[sv_prefix_proposal]] may run
+its own VL/SUBVL "loops" and specifies its own Register and Predication
 format on the 32-bit RV scalar opcode embedded within it.
 
 The [[vblock_format]] specifies how VBLOCK sub-execution contexts
 operate.
 
-SV is never actually switched "off".  VL or SUBVL may be equal to 1, and
-Register or Predicate over-ride tables may be empty: under such circumstances
-the behaviour becomes effectively identical to standard RV execution, however
-SV is never truly actually "off".
+SV is never actually switched "off".  VL or SUBVL may be equal to 1,
+and Register or Predicate over-ride tables may be empty: under such
+circumstances the behaviour becomes effectively identical to standard
+RV execution, however SV is never truly actually "off".
 
-Note: **there are *no* new opcodes**. The scheme works *entirely*
+Note: **there are *no* new vector opcodes**. The scheme works *entirely*
 on hidden context that augments (nests) *scalar* RISC-V instructions.
 Thus it may cover existing, future and custom scalar extensions, turning
 all existing, all future and all custom scalar operations parallel,
 without requiring any special (identical, parallel variant) opcodes to do so.
 
+Associated proposals for use with 3D and HPC:
+
+* [[specification/sv.setvl]] - replaces the use of CSRs to set VL (saves
+  32 bits)
+* [[specification/mv.x]] - provides MV.swizzle and MVX (reg[rd] = reg[reg[rs]])
+* [[ztrans_proposal]] - provides trigonometric and transcendental operations
+
 # CSRs <a name="csrs"></a>
 
 There are five CSRs, available in any privilege level:
@@ -58,7 +72,7 @@ Modes respectively:
 
 * (x)ePCVBLK (a copy of the sub-execution Program Counter, that is relative
   to the start of the current VBLOCK Group, set on a trap).
-* (x) eSTATE (useful for saving and restoring during context switch,
+* (x)eSTATE (useful for saving and restoring during context switch,
   and for providing fast transitions)
 
 The u/m/s CSRs are treated and handled exactly like their (x)epc
@@ -86,13 +100,14 @@ where 1 <= MVL <= XLEN
 
 ## SUBVL - Sub Vector Length
 
-This is a "group by quantity" that effectivrly asks each iteration
+This is a "group by quantity" that effectively asks each iteration
 of the hardware loop to load SUBVL elements of width elwidth at a
 time. Effectively, SUBVL is like a SIMD multiplier: instead of just 1
 operation issued, SUBVL operations are issued.
 
 The main effect of SUBVL is that predication bits are applied per
 **group**, rather than by individual element.  Legal values are 1 to 4.
+Illegal values raise an exception.
 
 ## STATE
 
@@ -105,16 +120,14 @@ full context save/restore.  It contains (and permits setting of):
   instruction being executed
 * srcoffs - for twin-predication, the source element offset as well.
 * SUBVL
-* svdestoffs - the subvector destination element offset of the current
+* dsvoffs - the subvector destination element offset of the current
   parallel instruction being executed
-* svsrcoffs - for twin-predication, the subvector source element offset
-  as well.
 
 The format of the STATE CSR is as follows:
 
-| (29..28 | (27..26) | (25..24) | (23..18) | (17..12) | (11..6) | (5...0) |
-| ------- | -------- | -------- | -------- | -------- | ------- | ------- |
-| dsvoffs | ssvoffs  | subvl    | destoffs | srcoffs  | vl      | maxvl   |
+| (31..28) | (27..26) | (25..24) | (23..18) | (17..12) | (11..6) | (5...0) |
+| -------- | -------- | -------- | -------- | -------- | ------- | ------- |
+| rsvd     | dsvoffs  | subvl    | destoffs | srcoffs  | vl      | maxvl   |
 
 The relationship between SUBVL and the subvl field is:
 
@@ -148,36 +161,15 @@ reduced range of the 5 bit immediate.
 | SETMVLi rd, #n  | CSRRWI MVL,rd, #n-1  |
 | GETMVL rd       | CSRRW  MVL, rd, x0   |
 
-Note: CSRRC and other bitsetting may still be used, they are however not particularly useful (very obscure).
+Note: CSRRC and other bitsetting may still be used, they are however
+not particularly useful (very obscure).
 
 ## Register key-value (CAM) table <a name="regcsrtable" />
 
-The purpose of the Register table is to mark which registers change behaviour
-if used in a "Standard" (normally scalar) opcode.
-
-16 bit format:
-
-| RegCAM | 15       | (14..8)  | 7   | (6..5) | (4..0)  |
-| ------ | -        | -        | -   | ------ | ------- |
-| 0      | isvec0   | regidx0  | i/f | vew0   | regkey  |
-| 1      | isvec1   | regidx1  | i/f | vew1   | regkey  |
-| 2      | isvec2   | regidx2  | i/f | vew2   | regkey  |
-| 3      | isvec3   | regidx3  | i/f | vew3   | regkey  |
-
-8 bit format:
-
-| RegCAM | | 7   | (6..5) | (4..0)  |
-| ------ | | -   | ------ | ------- |
-| 0      | | i/f | vew0   | regnum  |
-
-Mapping the 8-bit to 16-bit format:
+The purpose of the Register table is to mark which registers change
+behaviour if used in a "Standard" (normally scalar) opcode.
 
-| RegCAM | 15      | (14..8)    | 7   | (6..5) | (4..0)  |
-| ------ | -       | -          | -   | ------ | ------- |
-| 0      | isvec=1 | regnum0<<2 | i/f | vew0   | regnum0 |
-| 1      | isvec=1 | regnum1<<2 | i/f | vew1   | regnum1 |
-| 2      | isvec=1 | regnum2<<2 | i/f | vew2   | regnum2 |
-| 3      | isvec=1 | regnum2<<2 | i/f | vew3   | regnum3 |
+[[!inline raw="yes" pages="simple_v_extension/reg_table_format" ]]
 
 Fields:
 
@@ -231,65 +223,112 @@ is an indirect lookup that allows the RV opcodes to not need modification.
   The handling of each (trap or conditional test) is slightly different:
   see Instruction sections for further details
 
-16 bit format:
+[[!inline raw="yes" pages="simple_v_extension/pred_table_format" ]]
 
-| PrCSR | (15..11) | 10     | 9     | 8   | (7..1)  | 0       |
-| ----- | -        | -      | -     | -   | ------- | ------- |
-| 0     | predidx  | zero0  | inv0  | i/f | regidx  | ffirst0 |
-| 1     | predidx  | zero1  | inv1  | i/f | regidx  | ffirst1 |
-| 2     | predidx  | zero2  | inv2  | i/f | regidx  | ffirst2 |
-| 3     | predidx  | zero3  | inv3  | i/f | regidx  | ffirst3 |
+Pseudocode for predication:
 
-Note: predidx=x0, zero=1, inv=1 is a RESERVED encoding.  Its use must
-generate an illegal instruction trap.
+[[!inline raw="yes" pages="simple_v_extension/pred_table" ]]
+[[!inline raw="yes" pages="simple_v_extension/get_pred_value" ]]
 
-8 bit format:
+## Swizzle Table <a name="swizzle_table"></a>
 
-| PrCSR | 7     | 6     | 5   | (4..0)  |
-| ----- | -     | -     | -   | ------- |
-| 0     | zero0 | inv0  | i/f | regnum  |
+The swizzle table is a key-value store that indicates (if a given
+register is used, and SUBVL is 2, 3 or 4) that the sub-elements are to
+be re-ordered according to the indices in the Swizzle format.
+Like the Predication Table, it is an indirect lookup: use of a
+source or destination register in any given operation, if that register
+occurs in the table, "activates" sub-vector element swizzling for
+that register.  Note that the target is taken from the "Register Table"
+(regidx).
 
-Mapping from 8 to 16 bit format, the table becomes:
+Source vectors are free to have the swizzle indices point to the same
+sub-vector element.  However when using swizzling on destination vectors,
+the swizzle **must** be a permutation (no two swizzle indices point to
+the same sub-element).  An illegal instruction exception must be raised
+if this occurs.
 
-| PrCSR | (15..11) | 10     | 9     | 8   | (7..1)  | 0       |
-| ----- | -        | -      | -     | -   | ------- | ------- |
-| 0     | x9       | zero0  | inv0  | i/f | regnum  | ff=0    |
-| 1     | x10      | zero1  | inv1  | i/f | regnum  | ff=0    |
-| 2     | x11      | zero2  | inv2  | i/f | regnum  | ff=0    |
-| 3     | x12      | zero3  | inv3  | i/f | regnum  | ff=0    |
+[[!inline raw="yes" pages="simple_v_extension/swizzle_table_format" ]]
 
-Pseudocode for predication:
+Simplified pseudocode example, when SUBVL=4 and swizzle is set on rd:
 
+    # default indices if no swizzling table entry present
+    x, y, z, w = 0, 1, 2, 3
 
-[[!inline raw="yes" pages="simple_v_extension/pred_table" ]]
-[[!inline raw="yes" pages="simple_v_extension/get_pred_value" ]]
+    # lookup swizzling in table for rd
+    if swizzle_table[rd].active:
+        swizzle = swizzle_table[rd].swizzle
+
+        # decode the swizzle table entry for rd
+        x = swizzle[0:1] # sub-element 0
+        y = swizzle[2:3] # sub-element 1
+        z = swizzle[4:5] # sub-element 2
+        w = swizzle[6:7] # sub-element 3
+
+    # redirect register numbers through Register Table
+    rd  = int_vec[rd ].isvector ? int_vec[rd ].regidx : rd;
+    rs1 = int_vec[rs1].isvector ? int_vec[rs1].regidx : rs1;
+    rs2 = int_vec[rs2].isvector ? int_vec[rs2].regidx : rs2;
+
+    # loop on VL: SUBVL loop is unrolled (SUBVL=4)
+    for (i in 0; i < VL; i++)
+        ireg[rd+i*4+x] = OPERATION(ireg[rs1+i*4+0], ireg[rs2+i*4+0])
+        ireg[rd+i*4+y] = OPERATION(ireg[rs1+i*4+1], ireg[rs2+i*4+1])
+        ireg[rd+i*4+z] = OPERATION(ireg[rs1+i*4+2], ireg[rs2+i*4+2])
+        ireg[rd+i*4+w] = OPERATION(ireg[rs1+i*4+3], ireg[rs2+i*4+3])
+
+For more information on swizzling, see the Khronos wiki page
+<https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Swizzling>
 
 ## Fail-on-First Mode <a name="ffirst-mode"></a>
 
 ffirst is a special data-dependent predicate mode.  There are two
-variants: one is for faults: typically for LOAD/STORE operations,
-which may encounter end of page faults during a series of operations.
-The other variant is comparisons such as FEQ (or the augmented behaviour
-of Branch), and any operation that returns a result of zero (whether
-integer or floating-point).  In the FP case, this includes negative-zero.
-
-Note that the execution order must "appear" to be sequential for ffirst
-mode to work correctly.  An in-order architecture must execute the element
-operations in sequence, whilst an out-of-order architecture must *commit*
-the element operations in sequence (giving the appearance of in-order
-execution).
-
-Note also, that if ffirst mode is needed without predication, a special
-"always-on" Predicate Table Entry may be constructed by setting
-inverse-on and using x0 as the predicate register.  This
-will have the effect of creating a mask of all ones, allowing ffirst
-to be set.
+variants: one is for faults: typically for LOAD/STORE operations, which
+may encounter end of page faults during a series of operations.  The other
+variant is comparisons, and anything that returns "zero" or "fail". Note:
+no instruction may operate in both fault mode and "condition fail" mode.
+
+Fail on first critically relies on the program order being sequential,
+even for elements. Out of order designs must *commit* in-order, and are
+required to cancel elements at and beyond the fail point.
 
 See [[appendix]] for more details on fail-on-first modes.
 
+# Simplified Pseudo-code example
+
+A greatly simplified example illustrating (just) the VL hardware for-loop
+is as follows:
+
+[[!inline raw="yes" pages="simple_v_extension/simple_add_example" ]]
+
+Note that zeroing, elwidth handling, SUBVL and PCVLIW have all been
+left out, for clarity.  For examples on how to handle each, see
+[[appendix]].
+
+# Vector Block Format <a name="vliw-format"></a>
+
+The Vector Block format uses the RISC-V 80-192 bit format from Section 1.5
+of the RISC-V Spec.  It permits an optional VL/MVL/SUBVL block, up to 4
+16-bit (or 8 8-bit) Register Table entries, the same for Predicate Entries,
+and the rest of the instruction may be either standard RV opcodes or the
+SVPrefix opcodes ([[sv_prefix_proposal]])
+
+[[!inline raw="yes" pages="simple_v_extension/vblock_format_table" ]]
+
+For full details see ancillary resource: [[vblock_format]]
+
 # Exceptions
 
-TODO: expand.  
+Exception handling **MUST** be precise, in-order, and exactly
+like Standard RISC-V as far as the instruction execution order is
+concerned, regardless of whether it is PC, PCVBLK, VL or SUBVL that
+is currently being incremented.
+
+This.is extremely important. Exceptions
+**MUST** be raised one at a time and in
+strict sequential program order.
+
+No instructions are permitted to be out of
+sequence, therefore no exceptions are permitted to be, either.
 
 # Hints
 
@@ -301,10 +340,6 @@ in as a *parameter* to the HINT operation.
 
 No specific hints are yet defined in Simple-V
 
-# Vector Block Format <a name="vliw-format"></a>
-
-See ancillary resource: [[vblock_format]]
-
 # Subsets of RV functionality
 
 It is permitted to only implement SVprefix and not the VBLOCK instruction