(no commit message)
[libreriscv.git] / simple_v_extension / abridged_spec.mdwn
index 3e184128a226b151b4abb13e54a8dc2865888dc8..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,27 +27,34 @@ 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 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.
 
-Note: **there are *no* new opcodes**. The scheme works *entirely*
-on hidden context that augments *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 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>
 
@@ -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.
+**group**, rather than by individual element.  Legal values are 1 to 4.
+Illegal values raise an exception.
 
 ## STATE
 
@@ -105,16 +120,23 @@ 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:
+
+| SUBVL | (25..24) |
+| ----- | -------- |
+| 1     | 0b00     |
+| 2     | 0b01     |
+| 3     | 0b10     |
+| 4     | 0b11     |
 
 Notes:
 
@@ -139,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:
+The purpose of the Register table is to mark which registers change
+behaviour if used in a "Standard" (normally scalar) opcode.
 
-| RegCAM | | 7   | (6..5) | (4..0)  |
-| ------ | | -   | ------ | ------- |
-| 0      | | i/f | vew0   | regnum  |
-
-Mapping the 8-bit to 16-bit format:
-
-| 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:
 
@@ -195,22 +196,7 @@ Fields:
 As the above table is a CAM (key-value store) it may be appropriate
 (faster, less gates, implementation-wise) to expand it as follows:
 
-    struct vectorised {
-        bool isvector:1; 
-        int  vew:2; 
-        bool enabled:1;
-        int  predidx:7;  
-    }
-
-    struct vectorised fp_vec[32], int_vec[32];
-
-    for (i = 0; i < len; i++) // from VBLOCK Format
-       tb = int_vec if CSRvec[i].type == 0 else fp_vec
-       idx = CSRvec[i].regkey // INT/FP src/dst reg in opcode
-       tb[idx].elwidth  = CSRvec[i].elwidth
-       tb[idx].regidx   = CSRvec[i].regidx  // indirection
-       tb[idx].isvector = CSRvec[i].isvector // 0=scalar
-       tb[idx].enabled  = true;
+[[!inline raw="yes" pages="simple_v_extension/reg_table" ]]
 
 ## Predication Table <a name="predication_csr_table"></a>
 
@@ -237,137 +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
+
+    # 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
 
-    struct pred {
-        bool zero;    // zeroing
-        bool inv;     // register at predidx is inverted
-        bool ffirst;  // fail-on-first
-        bool enabled; // use this to tell if the table-entry is active
-        int predidx;  // redirection: actual int register to use
-    }
-
-    struct pred fp_pred_reg[32];
-    struct pred int_pred_reg[32];
-
-    for (i = 0; i < len; i++) // number of Predication entries in VBLOCK
-      tb = int_pred_reg if PredicateTable[i].type == 0 else fp_pred_reg;
-      idx = VBLOCKPredicateTable[i].regidx
-      tb[idx].zero     = CSRpred[i].zero
-      tb[idx].inv      = CSRpred[i].inv
-      tb[idx].ffirst   = CSRpred[i].ffirst
-      tb[idx].predidx  = CSRpred[i].predidx
-      tb[idx].enabled  = true
-
-    def get_pred_val(bool is_fp_op, int reg):
-       tb = int_reg if is_fp_op else fp_reg
-       if (!tb[reg].enabled):
-          return ~0x0, False       // all enabled; no zeroing
-       tb = int_pred if is_fp_op else fp_pred
-       if (!tb[reg].enabled):
-          return ~0x0, False       // all enabled; no zeroing
-       predidx = tb[reg].predidx   // redirection occurs HERE
-       predicate = intreg[predidx] // actual predicate HERE
-       if (tb[reg].inv):
-          predicate = ~predicate   // invert ALL bits
-       return predicate, tb[reg].zero
+    # 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.
-
-### Fail-on-first traps
-
-Except for the first element, ffault stops sequential element processing
-when a trap occurs.  The first element is treated normally (as if ffirst
-is clear).  Should any subsequent element instruction require a trap,
-instead it and subsequent indexed elements are ignored (or cancelled in
-out-of-order designs), and VL is set to the *last* instruction that did
-not take the trap.
-
-Note that predicated-out elements (where the predicate mask bit is zero)
-are clearly excluded (i.e. the trap will not occur).  However, note that
-the loop still had to test the predicate bit: thus on return,
-VL is set to include elements that did not take the trap *and* includes
-the elements that were predicated (masked) out (not tested up to the
-point where the trap occurred).
-
-If SUBVL is being used (SUBVL!=1), the first *sub-group* of elements
-will cause a trap as normal (as if ffirst is not set); subsequently,
-the trap must not occur in the *sub-group* of elements.  SUBVL will **NOT**
-be modified.
-
-Given that predication bits apply to SUBVL groups, the same rules apply
-to predicated-out (masked-out) sub-groups in calculating the value that VL
-is set to.
-
-### Fail-on-first conditional tests
-
-ffault stops sequential element conditional testing on the first element result
-being zero.  VL is set to the number of elements that were processed before
-the fail-condition was encountered.
-
-Note that just as with traps, if SUBVL!=1, the first of any of the *sub-group*
-will cause the processing to end, and, even if there were elements within
-the *sub-group* that passed the test, that sub-group is still (entirely)
-excluded from the count (from setting VL).  i.e. VL is set to the total
-number of *sub-groups* that had no fail-condition up until execution was
-stopped.
-
-Note again that, just as with traps, predicated-out (masked-out) elements
-are included in the count leading up to the fail-condition, even though they
-were not tested.
-
-The pseudo-code for Predication makes this clearer and simpler than it is
-in words (the loop ends, VL is set to the current element index, "i").
+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
 
@@ -379,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