Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/riscv-unprivileged.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ include::scalar-crypto.adoc[]
include::vector-crypto.adoc[]
include::unpriv-cfi.adoc[]
include::zilsd.adoc[]
include::zvabd.adoc[]
include::rv-32-64g.adoc[]
include::naming.adoc[]
include::mm-eplan.adoc[]
Expand Down
270 changes: 270 additions & 0 deletions src/zvabd.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
[[zvabd]]
== "Zvabd" extension for Integer Vector Absolute Difference Instructions

=== Introduction
This document describes the Zvabd extension for instructions that compute the element-wise absolute difference of vectors. That is, given two vectors v and u, compute the vector y such that stem:[y_i = abs(v_i - u_i)] and stem:[y_i += abs(v_i - u_i)].

These operations are widely utilized in image registration, object recognition, motion estimation and loop filters for video workloads.

=== Extension Overview
The Zvabd extension follows the vector arithmetic instruction specification in "V" Standard Extension.

Below is a list of all of the instructions that are included in the extension.
[%autowidth]
[%header,cols="2,4"]
|===
|Mnemonic
|Instruction

| vabs.v | <<insns-vabs>>
| vabd.vv | <<insns-vabd>>
| vabdu.vv | <<insns-vabdu>>
| vwabda.vv | <<insns-vwabda>>
| vwabdau.vv | <<insns-vwabdau>>

|===

NOTE: Since the targeted use cases are mostly based on 8-bit and 16-bit integer, `vabd/vabdu/vwabda/vwabdau` are designed for only SEW=8 and SEW=16. Additionally, `vabs` is considered to support all the element sizes as it is quite common used and simple to implement.

The Zvabd extension depend on Zve32x.

If Zve32x is supported then vabs provide support for SEW of 8, 16, and 32. If Zve64x is supported then vabs also add support for SEW 64.

=== Pseudocode for instruction semantics
The semantics of each instruction is expressed in a SAIL-like syntax, following the link:https://github.com/riscv/sail-riscv/tree/master/model/extensions/V[RISC-V Vector Sail Model].

<<<

=== Instructions

[[insns-vabs, Vector Signed Integer Absolute]]
==== vabs.v

Synopsis::
Vector Single-Width Signed Integer Absolute

Mnemonic::
vabs.v _vd_, _vs2_, _vm_

Encoding::
[wavedrom, , svg]
....
{reg: [
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPMVV'},
{bits: 5, name: 0x10},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm', attr: 'vm'},
{bits: 6, name: 'VXUNARY0', attr: 'funct6'},
]}
....

Description::
An absolute value operation is performed on each element of vs2

Operation::
[source,sail]
--
let (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
foreach (i from 0 to (num_elem - 1)) {
if mask[i] == bitone then {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this indicate that the instruction is always masked or am I misreading the SAIL code ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It follows the RVV sail code but omit the initialization code for mask/sew/lmul since these instructions are designed as standard vector arithmetic instruction and the full sail code is too long. If this has caused a misunderstanding, we need to find a way to resolve it.

result[i] = abs(signed(vs2_val[i]));
}
}
write_vreg(num_elem, SEW, LMUL_pow, vd, result);
set_vstart(zeros());
RETIRE_SUCCESS
--

<<<

[[insns-vabd, Vector Signed Integer Absolute Difference]]
==== vabd.vv

Synopsis::
Vector Single-Width Signed Integer Absolute Difference

Mnemonic::
vabd.vv _vd_, _vs2_, _vs1_, _vm_

Encoding::
[wavedrom, , svg]
....
{reg: [
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPMVV'},
{bits: 5, name: 'vs1'},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm', attr: 'vm'},
{bits: 6, name: 0x11, attr: 'funct6'},
]}
....

Reserved Encodings::
* `SEW` is neither 8 nor 16.

Description::
This instruction computes the absolute difference between the elements of two signed integer SEW-bit source operands vs1 and vs2.

This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.

Operation::
[source,sail]
--
let (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
foreach (i from 0 to (num_elem - 1)) {
if mask[i] == bitone then {
result[i] = max(vs2_val[i], vs1_val[i]) - min(vs2_val[i], vs1_val[i]);
}
}
write_vreg(num_elem, SEW, LMUL_pow, vd, result);
set_vstart(zeros());
RETIRE_SUCCESS
--

<<<

[[insns-vabdu, Vector Unsigned Integer Absolute Difference]]
==== vabdu.vv

Synopsis::
Vector Single-Width Unsigned Integer Absolute Difference

Mnemonic::
vabdu.vv _vd_, _vs2_, _vs1_, _vm_

Encoding::
[wavedrom, , svg]
....
{reg: [
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPMVV'},
{bits: 5, name: 'vs1'},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm', attr: 'vm'},
{bits: 6, name: 0x13, attr: 'funct6'},
]}
....

Reserved Encodings::
* `SEW` is neither 8 nor 16.

Description::
This instruction computes the absolute difference between the elements of two unsigned integer SEW-bit source operands vs1 and vs2.

This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.

Operation::
[source,sail]
--
let (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
foreach (i from 0 to (num_elem - 1)) {
if mask[i] == bitone then {
result[i] = maxu(vs2_val[i], vs1_val[i]) - minu(vs2_val[i], vs1_val[i]);
}
}
write_vreg(num_elem, SEW, LMUL_pow, vd, result);
set_vstart(zeros());
RETIRE_SUCCESS
--

<<<

[[insns-vwabda, Vector Signed Integer Absolute Difference And Accumulate]]
==== vwabda.vv

Synopsis::
Vector Widening Signed Integer Absolute Difference and Accumulate, Overwrite Addend

Mnemonic::
vwabda.vv _vd_, _vs2_, _vs1_, _vm_

Encoding::
[wavedrom, , svg]
....
{reg: [
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPMVV'},
{bits: 5, name: 'vs1'},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm', attr: 'vm'},
{bits: 6, name: 0x15, attr: 'funct6'},
]}
....

Reserved Encodings::
* `SEW` is neither 8 nor 16.

Description::
This instruction computes the absolute difference between the elements of two signed integer SEW-bit source operands vs1 and vs2, and accumulates the results into the elements of a 2*SEW-bit integer operand vd.

This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.

Operation::
[source,sail]
--
let SEW_widen = SEW * 2;
let LMUL_pow_widen = LMUL_pow + 1;
let (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val);
foreach (i from 0 to (num_elem - 1)) {
if mask[i] == bitone then {
result[i] = to_bits_unsafe(SEW_widen, max(vs2_val[i], vs1_val[i]) - min(vs2_val[i], vs1_val[i]) ) + vd_val[i];
}
}
write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result);
set_vstart(zeros());
RETIRE_SUCCESS
--

<<<

[[insns-vwabdau, Vector Unsigned Integer Absolute Difference And Accumulate]]
==== vwabdau.vv

Synopsis::
Vector Widening Unsigned Integer Absolute Difference and Accumulate, Overwrite Addend.

Mnemonic::
vwabdau.vv _vd_, _vs2_, _vs1_, _vm_

Encoding::
[wavedrom, , svg]
....
{reg: [
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPMVV'},
{bits: 5, name: 'vs1'},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm', attr: 'vm'},
{bits: 6, name: 0x16, attr: 'funct6'},
]}
....

Reserved Encodings::
* `SEW` is neither 8 nor 16.

Description::
This instruction computes the absolute difference between the elements of two unsigned integer SEW-bit source operands vs1 and vs2, and accumulates the results into the elements of a 2*SEW-bit integer operand vd.

This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.

Operation::
[source,sail]
--
let SEW_widen = SEW * 2;
let LMUL_pow_widen = LMUL_pow + 1;
let (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val);
foreach (i from 0 to (num_elem - 1)) {
if mask[i] == bitone then {
result[i] = to_bits_unsafe(SEW_widen, maxu(vs2_val[i], vs1_val[i]) - minu(vs2_val[i], vs1_val[i]) ) + vd_val[i];
}
}
write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result);
set_vstart(zeros());
RETIRE_SUCCESS
--