RISC-V's Zvzip is Changing
Tracking on-going Zvzip (RISC-V vector pairing/unpairing) specification changes from v0.1 to v0.2.
This quick post (it could have been a note) surveys and illustrates recent changes to a fast track specification under development: Zvzip. The post assumes basic knowledge about RISC-V Vector (if you need a refresher you may want to consider taking a look at our series RISC-V Vector In a Nutshell).
In a previous post, we presented a few new extensions to RISC-V Vector still under development:
One of them, Zvzip, has been substantially changed since we last covered it.
Let’s review those changes. The original pull request (Zvzip v0.1) was abandoned, and has been replaced by a new one which introduces Zvzip v0.2.
What is new in Zvzip land?
The extension still introduces the same 5 new instructions, vzip.vv, vunzipe.vv, vunzipo.vv, vpaire.vv, vpairo.vv, but their behavior has changed substantially, in particular when it comes to the read and write patterns.
Zvzip v0.1 allowed instructions to read more than vl elements from their sources and write more than vl destination elements.
Zvzip v0.2 gets rid of this by enforcing the following invariant: vtype fields, vl and LMUL, are used to define the scope of the interleaved datum wherever it appears in an operation (operand or result). Because, by definition the interleaved data tends to be the longest, this ensure that no element past the vl-th is accessed. (There exists a corner cases to that rule for a vpairo.vv operation with an odd vl which we will cover later in this post).
The EMUL of the deinterleaved datum is defined as EMUL=LMUL/2 and if the constraint 2*SEW > LMUL * min(ELEN, VLEN) is enforced (else illegal exception instruction is raised).
In a comment on the new version pull request, Philipp Tomsich (owner of the new version) also pointed out that the previous version violated multiple RISC-V norms:
The
vlCSR sets the number of elements written by an instruction (v0.1 ‘s instructions could write up to2*vlelements)An anomaly around
vstartwas introduced by version v0.1 (which could be set to a value larger thanvlbecause of the previous violation)
Although vstart is critical for vector memory accesses, not all vector instructions need to support a non-zero vstart. It is actually legal for an implementation to support only vstart=0 for numerous other instructions (source).
Implementations are permitted to raise illegal-instruction exceptions when attempting to execute a vector instruction with a value of vstart that the implementation can never produce when executing that same instruction with the same vtype setting.
This simply means that the implementation does not supported interrupting a vector instruction and that it will either be cancelled or complete entirely. This could be around to workaround the second violation and prevent setting vstart to a value larger than vl.
Illegal instruction exception versus reserved
The new specification takes a strong stance on the behavior on unsupported cases: rather than simply defining them as reserved (as most RISC-V specifications do), it mandates that the illegal instruction exception be raised in such cases. This stance makes sense in a lot of cases, but not in all of them (IMHO), in part because it prevents future extension from reusing encodings discarded by an extension (which would be possible if the behavior was only defined as reserved).
Zipping 2 vectors: vzip
The previous version is illustrated by the figure below:
while the new version, v0.2, is illustrated by the following figure (e.g. with vl=5):
The vzip.vv operation no longer writes 2 * vl elements: it writes only vl elements. This also impacts how many elements are read from it sources: we go from vl elements from vs2 to ceil(vl/2) elements and from vl elements for vs1 to floor(vl/2) elements.
Unzipping a vector: vunzip
The original v0.1 version is illustrated by the figure below (e.g. vl=3):
While the new v0.2 version is illustrated by the figure below (e.g. vl=5 for vunzipe and vl=7 for vunzipo)
The changes from v0.1 to v0.2 have reduced the amount of data read from vs2: from 2*vl or 2*vl-1 to simply vl. Here the vs2 source corresponds the interleaved data. The specification change impacts the number of element(s) written which gets reduced from vl to ceil(vl/2) for vunzipe.vv and to floor(vl/2) for vunzipo.vv. The number of written elements is dubbed evl, effective vector length.
Pairing a vector: vpair
The original version v0.1 is illustrated by the figure below (e.g. vl=3):
The new version v0.2 is illustrated by the figure below (e.g. vl=3):
The main change affects vpairo.vv: in the previous spec version (v0.1) , the instructions could read elements beyond vl as long as they were not beyond vlmax. If an element needed to be read beyond vlmax, it was replaced by the value 0, else the actual element value was used (even when its index exceeded vl-1). In the new version v0.2, the constraint is strengthened, no source element beyond vl can be read. If this were to happen, the element is replaced by the value 0 instead.
What’s next?
This post is rather succinct, but I wanted to publish it in a timely manner to raise awareness about the up-coming Zvzip changes and allow interested parties to comment.
Which version do you prefer? Do you think one is actually better than the other?
If you think you can bring something to the discussion, please join the conversation directly on the specification pull request.
I hope this post was informative.








