redo formatting
[libreriscv.git] / simple_v_extension / specification.mdwn
index ccf4d55fef0f848a9a6251ca2f8fbee48f0ca59d..2eb60764fa4f6abcbd32e52a77d56c6ebb405d2e 100644 (file)
@@ -1,9 +1,9 @@
 # Simple-V (Parallelism Extension Proposal) Specification
 
-* Copyright (C) 2017, 2018 Luke Kenneth Casson Leighton
-* Status: DRAFTv0.4
-* Last edited: 14 nov 2018
-* Ancillary resource: [[opcodes]]
+* Copyright (C) 2017, 2018, 3029 Luke Kenneth Casson Leighton
+* Status: DRAFTv0.6
+* Last edited: 21 jun 2019
+* Ancillary resource: [[opcodes]] [[sv_prefix_proposal]]
 
 With thanks to:
 
@@ -24,7 +24,7 @@ Simple-V is a uniform parallelism API for RISC-V hardware that has several
 unplanned side-effects including code-size reduction, expansion of
 HINT space and more.  The reason for
 creating it is to provide a manageable way to turn a pre-existing design
-into a parallel one, in a step-by-step incremental fashion, allowing
+into a parallel one, in a step-by-step incremental fashion, without adding any new opcodes, thus allowing
 the implementor to focus on adding hardware where it is needed and necessary.
 The primary target is for mobile-class 3D GPUs and VPUs, with secondary
 goals being to reduce executable size and reduce context-switch latency.
@@ -75,65 +75,69 @@ when and whether to parallelise operations **entirely to the implementor**.
 
 The principle of SV is as follows:
 
-* CSRs indicating which registers are "tagged" as "vectorised"
-  (potentially parallel, depending on the microarchitecture)
-  must be set up
+* Standard RV instructions are "prefixed" (extended) through a 48/64
+  bit format (single instruction option) or a variable
+ length VLIW-like prefix (multi or "grouped" option).
+* The prefix(es) indicate which registers are "tagged" as
+  "vectorised". Predicates can also be added.
 * A "Vector Length" CSR is set, indicating the span of any future
   "parallel" operations.
-* A **scalar** operation, just after the decode phase and before the
-  execution phase, checks the CSR register tables to see if any of
-  its registers have been marked as "vectorised"
-* If so, a hardware "macro-unrolling loop" is activated, of length
-  VL, that effectively issues **multiple** identical instructions
-  using contiguous sequentially-incrementing registers.
-  **Whether they be executed sequentially or in parallel or a
+* If any operation (a **scalar** standard RV opcode) uses a register
+  that has been so "marked" ("tagged"), a hardware "macro-unrolling loop"
+  is activated, of length VL, that effectively issues **multiple**
+  identical instructions using contiguous sequentially-incrementing
+  register numbers, based on the "tags".
+* **Whether they be executed sequentially or in parallel or a
   mixture of both or punted to software-emulation in a trap handler
   is entirely up to the implementor**.
 
 In this way an entire scalar algorithm may be vectorised with
 the minimum of modification to the hardware and to compiler toolchains.
-There are **no** new opcodes.
 
-# CSRs <a name="csrs"></a>
+To reiterate: **There are *no* new opcodes**. The scheme works *entirely*
+on hidden context that augments *scalar* RISCV instructions.
 
-For U-Mode there are two CSR key-value stores needed to create lookup
-tables which are used at the register decode phase.
+# CSRs <a name="csrs"></a>
 
-* A register CSR key-value table (typically 8 32-bit CSRs of 2 16-bits each)
-* A predication CSR key-value table (again, 8 32-bit CSRs of 2 16-bits each)
-* Small U-Mode and S-Mode register and predication CSR key-value tables
-  (2 32-bit CSRs of 2x 16-bit entries each).
 * An optional "reshaping" CSR key-value table which remaps from a 1D
   linear shape to 2D or 3D, including full transposition.
 
-There are also four additional CSRs for User-Mode:
+There are also five additional User mode CSRs :
 
-* CFG subsets the CSR tables
-* MVL (the Maximum Vector Length)
-* VL (which has different characteristics from standard CSRs)
-* STATE (useful for saving and restoring during context switch,
+* uMVL (the Maximum Vector Length)
+* uVL (which has different characteristics from standard CSRs)
+* uSUBVL (effectively a kind of SIMD)
+* uEPCVLIW (a copy of the sub-execution Program Counter, that is relative
+  to the start of the current VLIW Group, set on a trap).
+* uSTATE (useful for saving and restoring during context switch,
   and for providing fast transitions)
 
-There are also three additional CSRs for Supervisor-Mode:
+There are also five additional CSRs for Supervisor-Mode:
 
 * SMVL
 * SVL
+* SSUBVL
+* SEPCVLIW
 * SSTATE
 
 And likewise for M-Mode:
 
 * MMVL
 * MVL
+* MSUBVL
+* MEPCVLIW
 * MSTATE
 
-Both Supervisor and M-Mode have their own (small) CSR register and
-predication tables of only 4 entries each.
+Both Supervisor and M-Mode have their own CSR registers, independent
+of the other privilege levels, in order to make it easier to use
+Vectorisation in each level without affecting other privilege levels.
 
 The access pattern for these groups of CSRs in each mode follows the
 same pattern for other CSRs that have M-Mode and S-Mode "mirrors":
 
 * In M-Mode, the S-Mode and U-Mode CSRs are separate and distinct.
-* In S-Mode, accessing and changing of the M-Mode CSRs is identical
+* In S-Mode, accessing and changing of the M-Mode CSRs is transparently
+  identical
   to changing the S-Mode CSRs.  Accessing and changing the U-Mode
   CSRs is permitted.
 * In U-Mode, accessing and changing of the S-Mode and U-Mode CSRs
@@ -143,60 +147,21 @@ In M-Mode, only the M-Mode CSRs are in effect, i.e. it is only the
 M-Mode MVL, the M-Mode STATE and so on that influences the processor
 behaviour.  Likewise for S-Mode, and likewise for U-Mode.
 
-This has the interesting benefit of allowing M-Mode (or S-Mode)
-to be set up, for context-switching to take place, and, on return
-back to the higher privileged mode, the CSRs of that mode will be
-exactly as they were.  Thus, it becomes possible for example to
-set up CSRs suited best to aiding and assisting low-latency fast
-context-switching *once and only once*, without the need for
-re-initialising the CSRs needed to do so.
-
-## CFG
-
-This CSR may be used to switch between subsets of the CSR Register and
-Predication Tables: it is kept to 5 bits so that a single CSRRWI instruction
-can be used.  A setting of all ones is reserved to indicate that SimpleV
-is disabled.
-
-| (4..3) | (2...0) |
-| ------ | ------- |
-| size   | bank    |
-
-Bank is 3 bits in size, and indicates the starting index of the CSR
-Register and Predication Table entries that are "enabled".  Given that
-each CSR table row is 16 bits and contains 2 CAM entries each, there
-are only 8 CSRs to cover in each table, so 8 bits is sufficient.
-
-Size is 2 bits.  With the exception of when bank == 7 and size == 3,
-the number of elements enabled is taken by right-shifting 2 by size:
-
-| size   | elements |
-| ------ | -------- |
-| 0      | 2        |
-| 1      | 4        |
-| 2      | 8        |
-| 3      | 16       |
-
-Given that there are 2 16-bit CAM entries per CSR table row, this
-may also be viewed as the number of CSR rows to enable, by raising size to
-the power of 2.
-
-Examples:
-
-* When bank = 0 and size = 3, SVREGCFG0 through to SVREGCFG7 are
-  enabled, and SVPREDCFG0 through to SVPREGCFG7 are enabled.
-* When bank = 1 and size = 3, SVREGCFG1 through to SVREGCFG7 are
-  enabled, and SVPREDCFG1 through to SVPREGCFG7 are enabled.
-* When bank = 3 and size = 0, SVREGCFG3 and SVPREDCFG3 are enabled.
-* When bank = 3 and size = 1, SVREGCFG3-4 and SVPREDCFG3-4 are enabled.
-* When bank = 7 and size = 1, SVREGCFG7 and SVPREDCFG7 are enabled
-  (because there are only 8 32-bit CSRs there does not exist a
-  SVREGCFG8 or SVPREDCFG8 to enable).
-* When bank = 7 and size = 3, SimpleV is entirely disabled.
-
-In this way it is possible to enable and disable SimpleV with a
-single instruction, and, furthermore, on context-switching the quantity
-of CSRs to be saved and restored is greatly reduced.
+This has the interesting benefit of allowing M-Mode (or S-Mode) to be set
+up, for context-switching to take place, and, on return back to the higher
+privileged mode, the CSRs of that mode will be exactly as they were.
+Thus, it becomes possible for example to set up CSRs suited best to aiding
+and assisting low-latency fast context-switching *once and only once*
+(for example at boot time), without the need for re-initialising the
+CSRs needed to do so.
+
+Another interesting side effect of separate S Mode CSRs is that Vectorised
+saving of the entire register file to the stack is a single instruction
+(accidental provision of LOAD-MULTI semantics). It can even be predicated,
+which opens up some very interesting possibilities.
+
+The xEPCVLIW CSRs must be treated exactly like their corresponding xepc
+equivalents. See VLIW section for details.
 
 ## MAXVECTORLENGTH (MVL) <a name="mvl" />
 
@@ -209,16 +174,15 @@ The reason for setting this limit is so that predication registers, when
 marked as such, may fit into a single register as opposed to fanning out
 over several registers.  This keeps the implementation a little simpler.
 
-The other important factor to note is that the actual MVL is **offset
-by one**, so that it can fit into only 6 bits (for RV64) and still cover
-a range up to XLEN bits.  So, when setting the MVL CSR to 0, this actually
-means that MVL==1.  When setting the MVL CSR to 3, this actually means
-that MVL==4, and so on.  This is expressed more clearly in the "pseudocode"
+The other important factor to note is that the actual MVL is internally
+stored **offset by one**, so that it can fit into only 6 bits (for RV64)
+and still cover a range up to XLEN bits.  Attempts to set MVL to zero will
+return an exception.  This is expressed more clearly in the "pseudocode"
 section, where there are subtle differences between CSRRW and CSRRWI.
 
 ## Vector Length (VL) <a name="vl" />
 
-VSETVL is slightly different from RVV.  Like RVV, VL is set to be within
+VSETVL is slightly different from RVV.  Similar to RVV, VL is set to be within
 the range 1 <= VL <= MVL (where MVL in turn is limited to 1 <= MVL <= XLEN)
 
     VL = rd = MIN(vlen, MVL)
@@ -276,21 +240,44 @@ is limited to 0-31 (representing VL=1-32).
 Note that when VL is set to 1, all parallel operations cease: the
 hardware loop is reduced to a single element: scalar operations.
 
+## SUBVL - Sub Vector Length
+
+This is a "group by quantity" that effectively divides VL into groups
+of elements of length SUBVL. VL itself must therefore be set in advance
+to a multiple of SUBVL.
+
+Legal values are 1, 2, 3 and 4, and the STATE CSR must hold the 2 bit values 0b00 thru 0b11.
+
+Setting this CSR to 0 must raise an exception.  Setting it to a value
+greater than 4 likewise.
+
+The main effect of SUBVL is that predication bits are applied per **group**, 
+rather than by individual element.
+
+This saves a not insignificant number of instructions when handling 3D
+vectors, as otherwise a much longer predicate mask would have to be set
+up with regularly-repeated bit patterns.
+
 ## STATE
 
 This is a standard CSR that contains sufficient information for a
-full context save/restore.  It contains (and permits setting of)
-MVL, VL, CFG, the destination element offset of the current parallel
-instruction being executed, and, for twin-predication, the source
-element offset as well.  Interestingly it may hypothetically
-also be used to make the immediately-following instruction to skip a
-certain number of elements, however the recommended method to do
-this is predication or using the offset mode of the REMAP CSRs.
+full context save/restore.  It contains (and permits setting of):
+
+* MVL
+* VL
+* SUBVL
+* the destination element offset of the current parallel instruction
+  being executed
+* and, for twin-predication, the source element offset as well.
+
+Interestingly STATE may hypothetically also be used to make the
+immediately-following instruction to skip a certain number of elements,
+by playing with destoffs and srcoffs.
 
 Setting destoffs and srcoffs is realistically intended for saving state
 so that exceptions (page faults in particular) may be serviced and the
 hardware-loop that was being executed at the time of the trap, from
-user-mode (or Supervisor-mode), may be returned to and continued from
+user-mode (or Supervisor-mode), may be returned to and continued from exactly
 where it left off.  The reason why this works is because setting
 User-Mode STATE will not change (not be used) in M-Mode or S-Mode
 (and is entirely why M-Mode and S-Mode have their own STATE CSRs).
@@ -299,18 +286,21 @@ The format of the STATE CSR is as follows:
 
 | (28..27) | (26..24) | (23..18) | (17..12) | (11..6) | (5...0) |
 | -------- | -------- | -------- | -------- | ------- | ------- |
-| size     | bank     | destoffs | srcoffs  | vl      | maxvl   |
+| rsvd     | subvl    | destoffs | srcoffs  | vl      | maxvl   |
 
 When setting this CSR, the following characteristics will be enforced:
 
 * **MAXVL** will be truncated (after offset) to be within the range 1 to XLEN
 * **VL** will be truncated (after offset) to be within the range 1 to MAXVL
+* **SUBVL** which sets a SIMD-like quantity, has only 4 values however
+  if VL is not a multiple of SUBVL an exception will be raised.
 * **srcoffs** will be truncated to be within the range 0 to VL-1
 * **destoffs** will be truncated to be within the range 0 to VL-1
 
-## MVL, VL and CSR Pseudocode
+## MVL and VL  Pseudocode
 
-The pseudo-code for get and set of VL and MVL are as follows:
+The pseudo-code for get and set of VL and MVL use the following internal
+functions as follows:
 
     set_mvl_csr(value, rd):
         regs[rd] = MVL
@@ -322,13 +312,15 @@ The pseudo-code for get and set of VL and MVL are as follows:
     set_vl_csr(value, rd):
         VL = MIN(value, MVL)
         regs[rd] = VL # yes returning the new value NOT the old CSR
+        return VL
 
     get_vl_csr(rd):
         regs[rd] = VL
+        return VL
 
-Note that where setting MVL behaves as a normal CSR, unlike standard CSR
-behaviour, setting VL will return the **new** value of VL **not** the old
-one.
+Note that where setting MVL behaves as a normal CSR (returns the old
+value), unlike standard CSR behaviour, setting VL will return the **new**
+value of VL **not** the old one.
 
 For CSRRWI, the range of the immediate is restricted to 5 bits.  In order to
 maximise the effectiveness, an immediate of 0 is used to set VL=1,
@@ -340,20 +332,20 @@ an immediate of 1 is used to set VL=2 and so on:
     CSRRWI_Set_VL(value):
         set_vl_csr(value+1, x0)
 
-However for CSRRW the following pseudocide is used for MVL and VL,
+However for CSRRW the following pseudocode is used for MVL and VL,
 where setting the value to zero will cause an exception to be raised.
 The reason is that if VL or MVL are set to zero, the STATE CSR is
 not capable of returning that value.
 
     CSRRW_Set_MVL(rs1, rd):
         value = regs[rs1]
-        if value == 0:
+        if value == 0 or value > XLEN:
             raise Exception
         set_mvl_csr(value, rd)
 
     CSRRW_Set_VL(rs1, rd):
         value = regs[rs1]
-        if value == 0:
+        if value == 0 or value > XLEN:
             raise Exception
         set_vl_csr(value, rd)
 
@@ -387,13 +379,12 @@ VL==1, "00001" represents VL==2 and so on (likewise for MVL):
         get_state_csr(rd)
         MVL = set_mvl_csr(value[11:6]+1)
         VL = set_vl_csr(value[5:0]+1)
-        CFG = value[28:24]>>24
         destoffs = value[23:18]>>18
         srcoffs = value[23:18]>>12
 
     get_state_csr(rd):
         regs[rd] = (MVL-1) | (VL-1)<<6 | (srcoffs)<<12 |
-                   (destoffs)<<18 | (CFG)<<24
+                   (destoffs)<<18
         return regs[rd]
 
 In both cases, whilst CSR read of VL and MVL return the exact values
@@ -401,9 +392,13 @@ of VL and MVL respectively, reading and writing the STATE CSR returns
 those values **minus one**.  This is absolutely critical to implement
 if the STATE CSR is to be used for fast context-switching.
 
-## Register CSR key-value (CAM) table <a name="regcsrtable" />
+## Register key-value (CAM) table <a name="regcsrtable" />
 
-The purpose of the Register CSR table is four-fold:
+*NOTE: in prior versions of SV, this table used to be writable and
+accessible via CSRs. It is now stored in the VLIW instruction format,
+and entries may be overridden by the SVPrefix format*
+
+The purpose of the Register table is four-fold:
 
 * To mark integer and floating-point registers as requiring "redirection"
   if it is ever used as a source or destination in any given operation.
@@ -434,7 +429,16 @@ i/f is set to "1" to indicate that the redirection/tag entry is to be applied
 to integer registers; 0 indicates that it is relevant to floating-point
 registers.
 
-The 8 bit format is used for a much more compact expression. "isvec" is implicit and, as in [[sv-prefix-proposal]], the target vector is "regnum<<2", implicitly. Contrast this with the 16-bit format where the target vector is *explicitly* named in bits 8 to 14, and bit 15 may optionally set "scalar" mode.
+The 8 bit format is used for a much more compact expression. "isvec"
+is implicit and, similar to [[sv-prefix-proposal]], the target vector
+is "regnum<<2", implicitly. Contrast this with the 16-bit format where
+the target vector is *explicitly* named in bits 8 to 14, and bit 15 may
+optionally set "scalar" mode.
+
+Note that whilst SVPrefis adds one extra bit to each of rd, rs1 etc.,
+and thus the "vector" mode need only shift the (6 bit) regnum by 1 to
+get the actual (7 bit) register number to use, there is not enough space
+in the 8 bit format so "regnum<<2" is required.
 
 vew has the following meanings, indicating that the instruction's
 operand size is "over-ridden" in a polymorphic fashion:
@@ -459,123 +463,33 @@ As the above table is a CAM (key-value store) it may be appropriate
        tb[idx].isvector = CSRvec[i].isvector // 0=scalar
        tb[idx].packed   = CSRvec[i].packed  // SIMD or not
 
-The actual size of the CSR Register table depends on the platform
-and on whether other Extensions are present (RV64G, RV32E, etc.).
-For details see "Subsets" section.
-
-There are two CSRs (per privilege level) for adding to and removing
-entries from the table, which, conceptually may be viewed as either
-a register window (similar to SPARC) or as the "top of a stack".
-
-* SVREGTOP will push or pop entries onto the top of the "stack"
-  (highest non-zero indexed entry in the table)
-* SVREGBOT will push or pop entries from the bottom (always
-  element indexed as zero.
-
-In addition, note that CSRRWI behaviour is completely different
-from CSRRW when writing to these two CSR registers.  The CSRRW
-behaviour: the src register is subdivided into 16-bit chunks,
-and each non-zero chunk is pushed/popped separately.  The
-CSRRWI behaviour: the immediate indicates the number of
-entries in the table to be popped.
-
-CSRRWI:
-
-* The src register indicates how many entries to pop from the
-  CAM table.
-* "CSRRWI SVREGTOP, 3" indicates that the top 3
-  entries are to be zero'd and returned as the CSR return
-  result.  The top entry is returned in bits 0-15, the
-  next entry down in bits 16-31, and when XLEN==64, an
-  extra 2 entries are also returned.
-* "CSRRWI SVREGBOT, 3" indicates that the bottom 3 entries are
-  to be returned, and the entries with indices above 3 are
-  to be shuffled down.  The first entry to be popped off the
-  bottom is returned in bits 0-15, the second entry as bits
-  16-31 and so on.
-* If XLEN==32, only a maximum of 2 entries may be returned
-  (and shuffled).  If XLEN==64, only a maximum of 4 entries
-  may be returned
-* If however the destination register is x0 (zero), then
-  the exact number of entries requested will be removed
-  (shuffled down).
-
-CSRRW when src == 0:
-
-* When the src register is all zeros, this is a request to
-  pop one and only one 16-bit element from the table.
-* "CSRRW SVREGTOP, 0" will return (and clear) the highest
-  non-zero 16-bit entry in the table
-* "CSRRW SVREGBOT, 0" will return (and clear) the zero'th
-  16-bit entry in the table, and will shuffle down all
-  other entries (if any) by one index.
-
-CSRRW when src != 0:
-
-All other CSRRW behaviours are a "loop", taking 16-bits
-at a time from the src register.  Obviously, for XLEN=32
-that can only be up to 2 16-bit entries, however for XLEN=64
-it can be up to 4.
-
-* When the src 16-bit chunk is non-zero and there already exists
-  an entry with the exact same "regkey" (bits 0-4), the
-  entry is **updated**.  No other modifications are made.
-* When the 16-bit chunk is non-zero and there does not exist
-  an entry, the new value will be placed at the end
-  (in the highest non-zero slot), or at the beginning
-  (shuffling up all other entries to make room).
-* If there is not enough room, the entry at the opposite
-  end will become part of the CSR return result.
-* The process is repeated for the next 16-bit chunk (starting
-  with bits 0-15 and moving next to 16-31 and so on), until
-  the limit of XLEN is reached or a chunk is all-zeros, at
-  which point the looping stops.
-* Any 16-bit entries that are pushed out of the stack
-  (from either end) are concatenated in order (first entry
-  pushed out is bits 0-15 of the return result).
-
-What this behaviour basically does is allow the CAM table to
-effectively be like the top entries of a stack.  Entries that
-get returned from CSRRW SVREGTOP can be *actually* stored on the stack,
-such that after a function call exits, CSRRWI SVREGTOP may be used
-to delete the callee's CAM entries, and the caller's entries may then
-be pushed *back*, using CSRRW SVREGBOT.
-
-Context-switching may be carried out in a loop, where CSRRWI may
-be called to "pop" values that are tested for being non-zero, and
-transferred onto the stack with C.SWSP using only around 4-5 instructions.
-CSRRW may then be used in combination with C.LWSP to get the CAM entries
-off the stack and back into the CAM table, again with a loop using
-only around 4-5 instructions.
-
-Contrast this with needing around 6-7 instructions (8-9 without SV on
-RV64, and 16-17 on RV32) to do a context-switch of fixed-address CSRs:
-a sequence of fixed-address C.LWSP with fixed offsets plus fixed-address
-CSRRWs, and that is without testing if any of the entries are zero
-or not.
-
-## Predication CSR <a name="predication_csr_table"></a>
-
-TODO: update CSR tables, now 7-bit for regidx
-
-The Predication CSR is a key-value store indicating whether, if a given
-destination register (integer or floating-point) is referred to in an
-instruction, it is to be predicated.  Tt is particularly important to note
+
+
+## Predication Table <a name="predication_csr_table"></a>
+
+*NOTE: in prior versions of SV, this table used to be writable and
+accessible via CSRs. It is now stored in the VLIW instruction format,
+and entries may be overridden by the SVPrefix format*
+
+The Predication Table is a key-value store indicating whether, if a
+given destination register (integer or floating-point) is referred to
+in an instruction, it is to be predicated. Like the Register table, it
+is an indirect lookup that allows the RV opcodes to not need modification.
+
+It is particularly important to note
 that the *actual* register used can be *different* from the one that is
 in the instruction, due to the redirection through the lookup table.
 
-* regidx is the actual register that in combination with the
-  i/f flag, if that integer or floating-point register is referred to,
+* regidx is the register that in combination with the
+  i/f flag, if that integer or floating-point register is referred to
+ in a (standard RV) instruction
   results in the lookup table being referenced to find the predication
-  mask to use on the operation in which that (regidx) register has
-  been used
-* predidx (in combination with the bank bit in the future) is the
-  *actual* register to be used for the predication mask.  Note:
-  in effect predidx is actually a 6-bit register address, as the bank
-  bit is the MSB (and is nominally set to zero for now).
+  mask to use for this operation.
+* predidx is the
+  *actual* (full, 7 bit) register to be used for the predication mask. 
 * inv indicates that the predication mask bits are to be inverted
   prior to use *without* actually modifying the contents of the
-  register itself.
+  registerfrom which those bits originated.
 * zeroing is either 1 or 0, and if set to 1, the operation must
   place zeros in any element position where the predication mask is
   set to zero.  If zeroing is set to 0, unpredicated elements *must*
@@ -585,21 +499,15 @@ in the instruction, due to the redirection through the lookup table.
   interpret unpredicated elements as an internal "copy element"
   operation (which would be necessary in SIMD microarchitectures
   that perform register-renaming)
-* "packed" indicates if the register is to be interpreted as SIMD
-  i.e. containing multiple contiguous elements of size equal to "bitwidth".
-  (Note: in earlier drafts this was in the Register CSR table.
-  However after extending to 7 bits there was not enough space.
-  To use "unpredicated" packed SIMD, set the predicate to x0 and
-  set "invert".  This has the effect of setting a predicate of all 1s)
 
 16 bit format:
 
 | PrCSR | (15..11) | 10     | 9     | 8   | (7..1)  | 0       |
 | ----- | -        | -      | -     | -   | ------- | ------- |
 | 0     | predkey  | zero0  | inv0  | i/f | regidx  | rsrvd |
-| 1     | predkey  | zero1  | inv1  | i/f | regidx  | packed1 |
+| 1     | predkey  | zero1  | inv1  | i/f | regidx  | rsvd |
 | ...   | predkey  | .....  | ....  | i/f | ....... | ....... |
-| 15    | predkey  | zero15 | inv15 | i/f | regidx  | packed15|
+| 15    | predkey  | zero15 | inv15 | i/f | regidx  | rsvd |
 
 
 8 bit format:
@@ -608,7 +516,11 @@ in the instruction, due to the redirection through the lookup table.
 | ----- | -     | -     | -   | ------- |
 | 0     | zero0 | inv0  | i/f | regnum  |
 
-The 8 bit format is a compact and less expressive variant of the full 16 bit format.  Using the 8 bit formatis very different: the predicate register to use is implicit, and numbering begins inplicitly from x9. The regnum is still used to "activate" predication.
+The 8 bit format is a compact and less expressive variant of the full
+16 bit format.  Using the 8 bit formatis very different: the predicate
+register to use is implicit, and numbering begins inplicitly from x9. The
+regnum is still used to "activate" predication, in the same fashion as
+described above.
 
 The 16 bit Predication CSR Table is a key-value store, so implementation-wise
 it will be faster to turn the table around (maintain topologically
@@ -667,7 +579,7 @@ Note:
   source1 and source2 are vector or scalar
 * key-value CSR-redirection of rd, rs1 and rs2 have NOT been included
   above, for clarity.  rd, rs1 and rs2 all also must ALSO go through
-  register-level redirection (from the Register CSR table) if they are
+  register-level redirection (from the Register table) if they are
   vectors.
 
 If written as a function, obtaining the predication mask (and whether
@@ -687,13 +599,13 @@ zeroing takes place) may be done as follows:
        return predicate, tb[reg].zero
 
 Note here, critically, that **only** if the register is marked
-in its CSR **register** table entry as being "active" does the testing
-proceed further to check if the CSR **predicate** table entry is
+in its **register** table entry as being "active" does the testing
+proceed further to check if the **predicate** table entry is
 also active.
 
 Note also that this is in direct contrast to branch operations
 for the storage of comparisions: in these specific circumstances
-the requirement for there to be an active CSR *register* entry
+the requirement for there to be an active *register* entry
 is removed.
 
 ## REMAP CSR <a name="remap" />
@@ -950,13 +862,12 @@ other sections.
 It is critical to appreciate that there are
 **no operations added to SV, at all**.
 
-Instead, by using CSRs to tag registers as an indication of "changed behaviour",
-SV *overloads* pre-existing branch operations into predicated
-variants, and implicitly overloads arithmetic operations, MV,
-FCVT, and LOAD/STORE depending on CSR configurations for bitwidth
-and predication.  **Everything** becomes parallelised.  *This includes
-Compressed instructions* as well as any future instructions and Custom
-Extensions.
+Instead, by using CSRs to tag registers as an indication of "changed
+behaviour", SV *overloads* pre-existing branch operations into predicated
+variants, and implicitly overloads arithmetic operations, MV, FCVT, and
+LOAD/STORE depending on CSR configurations for bitwidth and predication.
+**Everything** becomes parallelised.  *This includes Compressed
+instructions* as well as any future instructions and Custom Extensions.
 
 Note: CSR tags to change behaviour of instructions is nothing new, including
 in RISC-V.  UXL, SXL and MXL change the behaviour so that XLEN=32/64/128.
@@ -1868,19 +1779,16 @@ really actually "memory" as such.
 
 The four entries for SV element bitwidths only allows three over-rides:
 
-* default bitwidth for a given operation *divided* by two
-* default bitwidth for a given operation *multiplied* by two
-* 8-bit
+* 8 bit
+* 16 hit
+* 32 bit
 
-At first glance this seems completely inadequate: for example, RV64
-cannot possibly operate on 16-bit operations, because 64 divided by
-2 is 32.  However, the reader may have forgotten that it is possible,
-at run-time, to switch a 64-bit application into 32-bit mode, by
-setting UXL.  Once switched, opcodes that formerly had 64-bit
-meanings now have 32-bit meanings, and in this way, "default/2"
-now reaches **16-bit** where previously it meant "32-bit".
+This would seem inadequate, surely it would be better to have 3 bits or
+more and allow 64, 128 and some other options besides.  The answer here
+is, it gets too complex, no RV128 implementation yet exists, and so RV64's
+default is 64 bit, so the 4 major element widths are covered anyway.
 
-There is however an absolutely crucial aspect oF SV here that explicitly
+There is an absolutely crucial aspect oF SV here that explicitly
 needs spelling out, and it's whether the "vectorised" bit is set in
 the Register's CSR entry.
 
@@ -1895,10 +1803,26 @@ When vectorised is *set*, this indicates that the operation now treats
 the length, any parts of a given actual register that are not involved
 in the operation are **NOT** modified, but are **PRESERVED**.
 
+For example:
+
+* when the vector bit is clear and elwidth set to 16 on the destination
+  register, operations are truncated to 16 bit and then sign or zero
+  extended to the *FULL* XLEN register width.
+* when the vector bit is set, elwidth is 16 and VL=1 (or other value where
+  groups of elwidth sized elements do not fill an entire XLEN register),
+  the "top" bits of the destination register do *NOT* get modified, zero'd
+  or otherwise overwritten.
+
 SIMD micro-architectures may implement this by using predication on
 any elements in a given actual register that are beyond the end of
 multi-element operation.
 
+Other microarchitectures may choose to provide byte-level write-enable
+lines on the register file, such that each 64 bit register in an RV64
+system requires 8 WE lines.  Scalar RV64 operations would require
+activation of all 8 lines, where SV elwidth based operations would
+activate the required subset of those byte-level write lines.
+
 Example:
 
 * rs1, rs2 and rd are all set to 8-bit
@@ -2241,38 +2165,88 @@ of the RISC-V ISA, is as follows:
 
 | 15    | 14:12 | 11:10 | 9:8   | 7    | 6:0     |
 | -     | ----- | ----- | ----- | ---  | ------- |
-| rmode | 16xil | pplen | rplen | pmode| 1111111 |
+| vlset | 16xil | pplen | rplen | mode | 1111111 |
+
+An optional VL Block, optional predicate entries, optional register
+entries and finally some 16/32/48 bit standard RV or SVPrefix opcodes
+follow.
+
+The variable-length format from Section 1.5 of the RISC-V ISA:
+
+| base+4 ... base+2          | base             | number of bits             |
+| ------ -----------------   | ---------------- | -------------------------- |
+| ..xxxx  xxxxxxxxxxxxxxxx   | xnnnxxxxx1111111 | (80+16\*nnn)-bit, nnn!=111 |
+| {ops}{Pred}{Reg}{VL Block} | SV Prefix        |                            |
 
 VL/MAXVL/SubVL Block:
 
-| 31-30 | 29:28 | 27:22  | 21:16   |
-| -     | ----- | ------ | ------- |
-| rsvd  | SubVL | MAXVL  | VLEN    |
+| 31-30 | 29:28 | 27:22  | 21:17  - 16  |
+| -     | ----- | ------ | ------ - -   |
+| 0     | SubVL | VLdest | VLEN     vlt |
+| 1     | SubVL | VLdest | VLEN         |
+
+Note: this format is very similar to that used in [[sv_prefix_proposal]]
+
+If vlt is 0, VLEN is a 5 bit immediate value, offset by one (i.e
+a bit sequence of 0b00000 represents VL=1 and so on). If vlt is 1,
+it specifies the scalar register from which VL is set by this VLIW
+instruction group. VL, whether set from the register or the immediate,
+is then modified (truncated) to be MIN(VL, MAXVL), and the result stored
+in the scalar register specified in VLdest. If VLdest is zero, no store
+in the regfile occurs (however VL is still set).
+
+This option will typically be used to start vectorised loops, where
+the VLIW instruction effectively embeds an optional "SETSUBVL, SETVL"
+sequence (in compact form).
 
-Reminder of the variable-length format from Section 1.5 of the RISC-V ISA:
+When bit 15 is set to 1, MAXVL and VL are both set to the immediate,
+VLEN (again, offset by one), which is 6 bits in length, and the same
+value stored in scalar register VLdest (if that register is nonzero).
+A value of 0b000000 will set MAXVL=VL=1, a value of 0b000001 will
+set MAXVL=VL= 2 and so on.
 
-| base+4 | base+2         | base             | number of bits             |
-| ------ | ------------------- | ---------------- | -------------------------- |
-| ..xxxx | xxxxxxxxxxxxxxxx | xnnnxxxxx1111111 | (80+16\*nnn)-bit, nnn!=111 |
-| {ops}{Pred}{Reg}  | VL Block     | SV Prefix        |                            |
+This option will typically not be used so much for loops as it will be
+for one-off instructions such as saving the entire register file to the
+stack with a single one-off Vectorised and predicated LD/ST, or as a way
+to save or restore registers in a function call with a single instruction.
+
+CSRs needed:
+
+* mepcvliw
+* sepcvliw
+* uepcvliw
+* hepcvliw
 
 Notes:
 
-* Bit 7 specifies if the prefix block format is the full 16 bit format (1) or the compact less expressive format (0). In the 8 bit format, pplen is multiplied by 2.
-* NOTE: 8 bit format predicate numbering is implicit and begins from x9. Thus it is critical to put blocks in the correct order as required.
-* Bit 15 specifies if the register block format is 16 bit (1) or 8 bit (0). In the 8 bit format, rplen is multiplied by 2. If only an odd number of entries are needed the last may be set to 0x00, indicating "unused".
-* Bits 8 and 9 define how many RegCam entries (0 to 3 if bit 15 is 1, otherwise 0 to 6) follow the VL Block.
-* Bits 10 and 11 define how many PredCam entries (0 to 3) follow after
-  the (optional) RegCam entries
+* Bit 7 specifies if the prefix block format is the full 16 bit format
+  (1) or the compact less expressive format (0). In the 8 bit format,
+  pplen is multiplied by 2.
+* 8 bit format predicate numbering is implicit and begins from x9. Thus
+  it is critical to put blocks in the correct order as required.
+* Bit 7 also specifies if the register block format is 16 bit (1) or 8 bit
+  (0). In the 8 bit format, rplen is multiplied by 2. If only an odd number
+  of entries are needed the last may be set to 0x00, indicating "unused".
+* Bit 15 specifies if the VL Block is present. If set to 1, the VL Block
+  immediately follows the VLIW instruction Prefix
+* Bits 8 and 9 define how many RegCam entries (0 to 3 if bit 15 is 1,
+  otherwise 0 to 6) follow the (optional) VL Block.
+* Bits 10 and 11 define how many PredCam entries (0 to 3 if bit 7 is 1,
+  otherwise 0 to 6) follow the (optional) RegCam entries
 * Bits 14 to 12 (IL) define the actual length of the instruction: total
   number of bits is 80 + 16 times IL.  Standard RV32, RVC and also
-  SVPrefix (P48-\*-Type) instructions fit into this space, after the
-  (optional) RegCam / PredCam entries
+  SVPrefix (P48/64-\*-Type) instructions fit into this space, after the
+  (optional) VL / RegCam / PredCam entries
 * Anything - any registers - within the VLIW-prefixed format *MUST* have the
   RegCam and PredCam entries applied to it.
-* At the end of the VLIW Group, the RegCam and PredCam CSRs *no longer apply*.
-
-This would greatly reduce the amount of space utilised by Vectorised
+* At the end of the VLIW Group, the RegCam and PredCam entries
+  *no longer apply*.  VL, MAXVL and SUBVL on the other hand remain at
+  the values set by the last instruction (whether a CSRRW or the VL
+  Block header).
+* Although an inefficient use of resources, it is fine to set the MAXVL,
+  VL and SUBVL CSRs with standard CSRRW instructions, within a VLIW block.
+
+All this would greatly reduce the amount of space utilised by Vectorised
 instructions, given that 64-bit CSRRW requires 3, even 4 32-bit opcodes: the
 CSR itself, a LI, and the setting up of the value into the RS register
 of the CSR, which, again, requires a LI / LUI to get the 32 bit
@@ -2289,8 +2263,9 @@ and VL need to be set.
 
 By contrast, the VLIW prefix is only 16 bits, the VL/MAX/SubVL block is
 only 16 bits, and as long as not too many predicates and register vector
-qualifiers are specified, several 32-bit and 16-bit opcodes can fit into the
-format. If the full flexibility of the 16 bit block formats are not needed, more space is saved by using the 8 bit formats.
+qualifiers are specified, several 32-bit and 16-bit opcodes can fit into
+the format. If the full flexibility of the 16 bit block formats are not
+needed, more space is saved by using the 8 bit formats.
 
 In this light, embedding the VL/MAXVL, PredCam and RegCam CSR entries into
 a VLIW format makes a lot of sense.
@@ -2300,20 +2275,46 @@ Open Questions:
 * Is it necessary to stick to the RISC-V 1.5 format?  Why not go with
   using the 15th bit to allow 80 + 16\*0bnnnn bits?  Perhaps to be sane,
   limit to 256 bits (16 times 0-11).
+* Could a "hint" be used to set which operations are parallel and which
+  are sequential?
+* Could a new sub-instruction opcode format be used, one that does not
+  conform precisely to RISC-V rules, but *unpacks* to RISC-V opcodes?
+  no need for byte or bit-alignment
+* Could a hardware compression algorithm be deployed?  Quite likely,
+  because of the sub-execution context (sub-VLIW PC)
 
 ## Limitations on instructions.
 
-An implementation is required to treat the VLIW group as a separate sub-program with its own separate PC. The sub-pc advances separately whilst the main PC remains pointing at the beginning of the VLIW instruction.
+To greatly simplify implementations, it is required to treat the VLIW
+group as a separate sub-program with its own separate PC. The sub-pc
+advances separately whilst the main PC remains pointing at the beginning
+of the VLIW instruction (not to be confused with how VL works, which
+is exactly the same principle, except it is VStart in the STATE CSR
+that increments).
+
+This has implications, namely that a new set of CSRs identical to xepc
+(mepc, srpc, hepc and uepc) must be created and managed and respected
+as being a sub extension of the xepc set of CSRs.  Thus, xepcvliw CSRs
+must be context switched and saved / restored in traps.
+
+The VStart indices in the STATE CSR may be similarly regarded as another
+sub-execution context, giving in effect two sets of nested sub-levels
+of the RISCV Program Counter.
 
-This has implications, namely that a new set of CSRs identical to xepc (mepc, srpc, hepc and uepc) must be created and managed and respected as being a sub extension of the xepc set of CSRs.  Thus, xevliwpc CSRs must be context switched and saved / restored in traps.
+In addition, as xepcvliw CSRs are relative to the beginning of the VLIW
+block, branches MUST be restricted to within the block, i.e. addressing
+is now restricted to the start (and very short) length of the block.
 
-The VStart indices in the STATE CSR may be similarly regarded as another sub-execution context.
+Also: calling subroutines is inadviseable, unless they can be entirely
+accomplished within a block.
 
-In addition, as xevliwpc CSRs are relative to the beginning of the VLIW block, branches MUST be restricted to within the block, i.e. addressing is now restricted to the start (and very short) length of the block.
+A normal jump and a normal function call may only be taken by letting
+the VLIW end, returning to "normal" standard RV mode, using RVC, 32 bit
+or P48/64-\*-type opcodes.
 
-Also: calling subroutines is inadviseable, unless they can be entirely accomplished within a block.
+## Links
 
-A normal jump and a normal function call may only be taken by letting the VLIW end, returning to "normal" standard RV mode, using RVC, 32 bit or P48-*-type opcodes.
+* <https://groups.google.com/d/msg/comp.arch/yIFmee-Cx-c/jRcf0evSAAAJ>
 
 # Subsets of RV functionality
 
@@ -2412,18 +2413,10 @@ answer: they're not vectorised, so not a problem
 
 ---
 
-TODO: update elwidth to be default / 8 / 16 / 32
-
----
-
 TODO: document different lengths for INT / FP regfiles, and provide
 as part of info register. 00=32, 01=64, 10=128, 11=reserved.
 
 ---
 
-push/pop of vector config state:
-<https://groups.google.com/d/msg/comp.arch/bGBeaNjAKvc/z2d_cST7AgAJ>
-
-when Bank in CFG is altered, shift the "addressing" of Reg and
-Pred CSRs to match.  i.e. treat the Reg and Pred CSRs as a
-"mini stack".
+TODO, update to remove RegCam and PredCam CSRs, just use SVprefix and
+VLIW format