diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 3c25e3a4b..8e7e9d40a 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -3,8 +3,17 @@ name: autofix.ci +# Regenerating the normative tag reference commits back to the PR, so it only +# runs on demand: a maintainer applies the 'update-norm-rules' label when the PR +# is otherwise ready, and this pushes the fresh ref/ before merge. `labeled` +# fires on that apply; `synchronize`/`reopened` keep ref/ fresh on later pushes +# while the label remains (the job `if` below enforces the label on every event). on: pull_request: + types: + - labeled + - synchronize + - reopened # Only run on the latest commit if a PR is updated concurrency: @@ -17,6 +26,9 @@ permissions: jobs: autofix: name: Regenerate checked-in normative tag reference + # On demand only: gated behind the 'update-norm-rules' label so the bot push + # happens when a maintainer asks for it, not on every PR update. + if: contains(github.event.pull_request.labels.*.name, 'update-norm-rules') runs-on: ubuntu-latest steps: diff --git a/.github/workflows/check-normative-tags.yml b/.github/workflows/check-normative-tags.yml index 31529e910..1ceb58e3b 100644 --- a/.github/workflows/check-normative-tags.yml +++ b/.github/workflows/check-normative-tags.yml @@ -182,12 +182,15 @@ jobs: # ref/ is stale still gets to see what actually changed. # # check-ref regenerates the files, so its own advice ("commit the result") - # is aimed at someone running it locally. Here the fix has to happen on the - # contributor's machine, so say that instead. + # is aimed at someone running it locally. Here the fix has to happen either + # on the contributor's machine or via the on-demand autofix workflow, so + # point at both: a maintainer can apply the 'update-norm-rules' label to + # have autofix regenerate and commit the files, or the contributor can + # regenerate locally. - name: Verify ref/ is up to date run: | if ! make check-ref; then - echo "::error::Normative tag reference files are out of date. Run 'make update-ref' locally and commit the result." + echo "::error::Normative tag reference files are out of date. A maintainer can apply the 'update-norm-rules' label to have autofix regenerate and commit them, or run 'make update-ref' locally and commit the result." exit 1 fi diff --git a/.github/workflows/dco_check.yml b/.github/workflows/dco_check.yml index d0d9d510d..4cfa0fedd 100644 --- a/.github/workflows/dco_check.yml +++ b/.github/workflows/dco_check.yml @@ -33,8 +33,18 @@ jobs: pull_number: pr.number, }); + // Bots (e.g. autofix-ci[bot] pushing regenerated normative rules, + // dependabot) cannot sign off their commits, so exclude them from + // the DCO requirement. GitHub resolves the author to a user object + // whose type is 'Bot' and whose login ends in '[bot]'. + const isBot = (user) => + !!user && (user.type === 'Bot' || /\[bot\]$/.test(user.login || '')); + const dcoFailedCommits = commits.filter( - (commit) => !/Signed-off-by:/.test(commit.commit.message) + (commit) => + !isBot(commit.author) && + !isBot(commit.committer) && + !/Signed-off-by:/.test(commit.commit.message) ); if (dcoFailedCommits.length > 0) { diff --git a/marchid.md b/marchid.md index 30c60472a..0f143ff4c 100644 --- a/marchid.md +++ b/marchid.md @@ -66,8 +66,9 @@ rrv32 | Solra Bizna | [Solra Bizna](mailto:solra@biz VexiiRiscv | SpinalHDL | [Charles Papon](mailto:charles.papon.90@gmail.com) | 46 | https://github.com/SpinalHDL/VexiiRiscv Wildcat | Technical University of Denmark | [Martin Schoeberl](mailto:masca@dtu.dk) | 47 | https://github.com/schoeberl/wildcat CVA5 | OpenHW Group | [Lesley Shannon](mailto:lesley_shannon@sfu.ca) | 48 | https://github.com/openhwgroup/cva5 -River | Midstall Software | [Inquiry](mailto:inquire@midstall.com) | 49 | https://github.com/MidstallSoftware/river +River | Midstall | [Hello](mailto:hello@midstall.com) | 49 | https://github.com/Midstall/river Raptor | Yu Jin | [Yu Jin](mailto:lambda.jinyu@gmail.com) | 50 | https://github.com/Kingfish404/raptor-chip Sargantana | BSC-LOCA | [Narcís Rodas](mailto:narcis.rodaquiroga@bsc.es) | 51 | https://github.com/bsc-loca/sargantana KianV Stealth | Hirosh Dabui | [Hirosh Dabui](mailto:hirosh@dabui.de) | 52 | https://github.com/splinedrive/kianRiscV RVController | April Kolwey (cheapie) | [April Kolwey](mailto:cheapiephp@gmail.com) | 53 | https://cheapiesystems.com/git/rvcontroller/ +aRVern | Arvern Silicon | [Arvern Silicon](mailto:arvernsilicon@gmail.com) | 54 | https://github.com/Arvern-Silicon diff --git a/normative_rule_defs/smctr.yaml b/normative_rule_defs/smctr.yaml index 4b4dc0230..a68a5b2a9 100644 --- a/normative_rule_defs/smctr.yaml +++ b/normative_rule_defs/smctr.yaml @@ -25,10 +25,6 @@ normative_rule_definitions: summary: Recorded transfers are inserted at write pointer; overwrites on full buffer; optional RAS mode. tags: ["norm:Smctr_transfer_steps"] - - name: Smctr_CTR_CSR_interface - summary: CTR buffer accessed via indirect CSR; logical entry 0 = youngest transfer. - tags: ["norm:Smctr_CTR_CSR_interface"] - - name: Smctr_scope summary: Smctr covers machine-level CSRs, instructions, and behavior; Ssctr excludes machine-level only. tags: ["norm:Smctr_scope", "norm:Ssctr_transfer_steps"] diff --git a/normative_rule_defs/supervisor.yaml b/normative_rule_defs/supervisor.yaml index 957fbe88a..c3268d0a8 100644 --- a/normative_rule_defs/supervisor.yaml +++ b/normative_rule_defs/supervisor.yaml @@ -232,6 +232,8 @@ normative_rule_definitions: - name: senvcfg_pmm_Ssnpm tags: ["norm:senvcfg_pmm_Ssnpm"] + - name: senvcfg_pmm_immediate + tags: ["norm:senvcfg_pmm_immediate"] - names: [senvcfg_lpe_Zicfilp_acc, senvcfg_lpe_Zicfilp_op] tags: ["norm:senvcfg_lpe_Zicfilp"] diff --git a/normative_rule_defs/zvabd.yaml b/normative_rule_defs/zvabd.yaml new file mode 100644 index 000000000..0fe33190b --- /dev/null +++ b/normative_rule_defs/zvabd.yaml @@ -0,0 +1,41 @@ +--- +# yaml-language-server: $schema=../docs-resources/schemas/defs-schema.json + +$schema: "../docs-resources/schemas/defs-schema.json#" + +chapter_name: Vector Extension for Integer Absolute Difference Instructions + +normative_rule_definitions: + + - name: Zvabd_dependent_Zve32x + tags: ["norm:Zvabd_dependent_Zve32x"] + + - name: vabd_op + tags: ["norm:vabd_op"] + + - name: vabd_sew_defined + tags: ["norm:vabd_sew_defined"] + + - name: vabdu_op + tags: ["norm:vabdu_op"] + + - name: vabdu_sew_defined + tags: ["norm:vabdu_sew_defined"] + + - name: vwabda_sew_rsv + tags: ["norm:vwabda_sew_rsv"] + + - name: vwabda_op + tags: ["norm:vwabda_op"] + + - name: vwabda_sew_defined + tags: ["norm:vwabda_sew_defined"] + + - name: vwabdau_sew_rsv + tags: ["norm:vwabdau_sew_rsv"] + + - name: vwabdau_op + tags: ["norm:vwabdau_op"] + + - name: vwabdau_sew_defined + tags: ["norm:vwabdau_sew_defined"] diff --git a/ref/riscv-spec-norm-tags.json b/ref/riscv-spec-norm-tags.json index 813a0b371..caea5c800 100644 --- a/ref/riscv-spec-norm-tags.json +++ b/ref/riscv-spec-norm-tags.json @@ -441,7 +441,7 @@ "norm:fcvt_long_float_rv64_only": "insn:fcvt.l.s[], insn:fcvt.lu.s[], insn:fcvt.s.l[], and insn:fcvt.s.lu[] are RV64-only instructions", "norm:fcvt_unrepresentable_nv": "If the rounded result is not representable in the\ndestination format, it is clipped to the nearest value and the invalid\nflag is set", "norm:fcvt_int_float_valid_input": "<<int_conv>> gives the range of valid inputs\nfor insn:fcvt.w.s[], insn:fcvt.wu.s[], insn:fcvt.l.s[], and insn:fcvt.lu.s[] and\nthe behavior of these instructions for invalid inputs", - "norm:fcvt_round": "All floating-point to integer and integer to floating-point conversion instructions round according to the rm field. A floating-point register can be initialized to floating-point positive zero using insn:fcvt.s.w[rd,x0], which will never set any exception flags.", + "norm:fcvt_round": "All floating-point to integer and integer to floating-point conversion\ninstructions round according to the rm field.", "norm:fcvt_nx": "All floating-point conversion instructions set the Inexact exception flag if the rounded result differs from the operand value and the Invalid exception flag is not set.", "norm:fsgnj-s_fsgnjn-s_fsgnjx-s_op": "insn:fsgnj.s[], insn:fsgnjn.s[], and\ninsn:fsgnjx.s[] are floating-point to floating-point sign-injection instructions\nthat produce a result that takes all bits except the\nsign bit from rs1. For insn:fsgnj[], the result's sign bit is rs2's sign\nbit; for insn:fsgnjn[], the result's sign bit is the opposite of rs2's sign\nbit; and for insn:fsgnjx[], the sign bit is the XOR of the sign bits of rs1\nand rs2. Sign-injection instructions do not set floating-point\nexception flags, nor do they canonicalize NaNs", "norm:fmv-x-w_op": "insn:fmv.x.w[] moves\nthe single-precision value in floating-point register rs1 represented\nin the IEEE 754-2008 encoding to the lower 32 bits of integer register\nrd. The bits are not modified in the transfer, and in particular, the\npayloads of non-canonical NaNs are preserved. For RV64, the higher 32\nbits of the destination register are filled with copies of the\nfloating-point number's sign bit", @@ -2145,6 +2145,7 @@ "norm:cbo-inval_s-mode_op1": "", "norm:cbo-inval_s-mode_op2": "", "norm:senvcfg_pmm_Ssnpm": "If the Ssnpm extension is implemented, the PMM field enables or disables pointer masking (see ) for the next-lower privilege mode (U/VU), according to the values in . If Ssnpm is not implemented, PMM is read-only zero. The PMM field is read-only zero for RV32.", + "norm:senvcfg_pmm_immediate": "Changing senvcfg.PMM takes effect immediately, without the need to execute an SFENCE.VMA instruction.", "norm:senvcfg_lpe_Zicfilp": "The Zicfilp extension adds the LPE field in senvcfg. When the LPE field is set to 1, the Zicfilp extension is enabled in VU/U-mode. When the LPE field is 0, the Zicfilp extension is not enabled in VU/U-mode and the following rules apply to VU/U-mode:", "norm:senvcfg_sse_Zicfilp": "The Zicfiss extension adds the SSE field in senvcfg. When the SSE field is set to 1, the Zicfiss extension is activated in VU/U-mode. When the SSE field is 0, the Zicfiss extension remains inactive in VU/U-mode, and the following rules apply:", "norm:satp": "The satp CSR is an SXLEN-bit read/write register, formatted as shown in for SXLEN=32 and for SXLEN=64, which controls supervisor-mode address translation and protection. This register holds the physical page number (PPN) of the root page table, i.e., its supervisor physical address divided by 4 KiB; an address space identifier (ASID), which facilitates address-translation fences on a per-address-space basis; and the MODE field, which selects the current address-translation scheme. Further details on the access to this register are described in .", @@ -2372,7 +2373,7 @@ "norm:hlsv_vsstatus_mxr": "vsstatus.MXR affects only the first\ntranslation stage (VS-stage).", "norm:hlsv_op": "For every RV32I or RV64I load instruction, LB, LBU, LH, LHU, LW, LWU, and LD, there is a corresponding virtual-machine load instruction: HLV.B, HLV.BU, HLV.H, HLV.HU, HLV.W, HLV.WU, and HLV.D. For every RV32I or RV64I store instruction, SB, SH, SW, and SD, there is a corresponding virtual-machine store instruction: HSV.B, HSV.H, HSV.W, and HSV.D. Instructions HLV.WU, HLV.D, and HSV.D are not valid for RV32, of course.", "norm:hlsv_u_op": "Instructions HLVX.HU and HLVX.WU are the same as HLV.HU and HLV.WU, except that execute permission takes the place of read permission during address translation. That is, the memory being read must be executable in both stages of address translation, but read permission is not required. For the supervisor physical address that results from address translation, the supervisor physical memory attributes must grant both execute and read permissions. (The supervisor physical memory attributes are the machine’s physical memory attributes as modified by physical memory protection, , for supervisor level.)", - "norm:hlvx-wu_valid32": "HLVX.WU is valid for RV32, even though LWU and HLV.WU are not. (For RV32, HLVX.WU can be considered a variant of HLV.W, as sign extension is irrelevant for 32-bit values.)", + "norm:hlvx-wu_valid32": "HLVX.WU is valid for RV32, even though LWU and HLV.WU are not.", "norm:hlsv_virtinst": "Attempts to execute a virtual-machine load/store instruction (HLV, HLVX,\nor HSV) when V=1 cause a virtual-instruction exception.", "norm:hlsv_illegalinst": "Attempts to execute one of these same instructions from U-mode when hstatus.HU=0 cause an\nillegal-instruction exception.", "norm:hfence-vvma_hfence-gvma_op": "The hypervisor memory-management fence instructions, HFENCE.VVMA and HFENCE.GVMA, perform a function similar to SFENCE.VMA (), except applying to the VS-level memory-management data structures controlled by CSR vsatp (HFENCE.VVMA) or the guest-physical memory-management data structures controlled by CSR hgatp (HFENCE.GVMA). Instruction SFENCE.VMA applies only to the memory-management data structures controlled by the current satp (either the HS-level satp when V=0 or vsatp when V=1).", @@ -2402,7 +2403,7 @@ "norm:mtval2_Ssdbltrap": "The Ssdbltrap extension (See ) requires the implementation of the mtval2 CSR.", "norm:mtinst_sz_acc_op": "The mtinst register is an MXLEN-bit read/write register formatted as shown in . When a trap is taken into M-mode, mtinst is written with a value that, if nonzero, provides information about the instruction that trapped, to assist software in handling the trap. The values that may be written to mtinst on a trap are documented in .", "norm:mtinst_val": "mtinst is a WARL register that need only be able to hold the values that the implementation may automatically write to it on a trap.", - "norm:H_vm_twostage": "Whenever the current virtualization mode V is 1, two-stage address translation and protection is in effect. For any virtual memory access, the original virtual address is converted in the first stage by VS-level address translation, as controlled by the vsatp register, into a guest physical address. The guest physical address is then converted in the second stage by guest physical address translation, as controlled by the hgatp register, into a supervisor physical address. The two stages are known also as VS-stage and G-stage translation. Although there is no option to disable two-stage address translation when V=1, either stage of translation can be effectively disabled by zeroing the corresponding vsatp or hgatp register.", + "norm:H_vm_twostage": "Whenever the current virtualization mode V is 1, two-stage address\ntranslation and protection is in effect. For any virtual memory access,\nthe original virtual address is converted in the first stage by VS-level\naddress translation, as controlled by the vsatp register, into a\nguest physical address. The guest physical address is then converted\nin the second stage by guest physical address translation, as controlled\nby the hgatp register, into a supervisor physical address. The two\nstages are known also as VS-stage and G-stage translation.", "norm:vsstatus_mxr_vm": "The vsstatus field MXR, which makes execute-only pages readable by explicit loads, only\noverrides VS-stage page protection. Setting MXR at VS-level does not\noverride guest-physical page protections.", "norm:sstatus_mxr_vm": "Setting MXR at HS-level,\nhowever, overrides both VS-stage and G-stage execute-only permissions.", "norm:H_vm_gstagetrans": "When V=1, memory accesses that would normally bypass address translation are subject to G-stage address translation alone. This includes memory accesses made in support of VS-stage address translation, such as reads and writes of VS-level page tables.", @@ -2620,7 +2621,6 @@ "norm:ctr_depth": "The number of records that can be held in the buffer depends upon both the implementation (the maximum supported depth) and the CTR configuration (the software selected depth).", "norm:Smctr_recording_criteria": "Only qualified transfers are recorded. Qualified transfers are those that meet the filtering criteria, which include the privilege mode and the transfer type.", "norm:Smctr_transfer_steps": "Recorded transfers are inserted at the write pointer, which is then incremented, while older recorded transfers may be overwritten once the buffer is full. Or the user can enable RAS (Return Address Stack) emulation mode, where only function calls are recorded, and function returns pop the last call record. The source PC, target PC, and some optional metadata (transfer type, elapsed cycles) are stored for each recorded transfer.", - "norm:Smctr_CTR_CSR_interface": "The CTR buffer is accessible through an indirect CSR interface, such that software can specify which logical entry in the buffer it wishes to read or write. Logical entry 0 always corresponds to the youngest recorded transfer, followed by entry 1 as the next youngest, and so on.", "norm:Smctr_scope": "The machine-level extension, Smctr, encompasses all newly added Control Status Registers (CSRs), instructions, and behavior modifications for a hart across all privilege levels.", "norm:Ssctr_transfer_steps": "The corresponding supervisor-level extension, Ssctr, is essentially identical to Smctr, except that it excludes machine-level CSRs and behaviors not intended to be directly accessible at the supervisor level.", "norm:Smctr_Ssctr_depend": "Smctr and Ssctr depend on both the implementation of S-mode and the Sscsrind extension.", @@ -10950,6 +10950,7 @@ "norm:cbo-inval_s-mode_op1", "norm:cbo-inval_s-mode_op2", "norm:senvcfg_pmm_Ssnpm", + "norm:senvcfg_pmm_immediate", "norm:senvcfg_lpe_Zicfilp", "norm:senvcfg_sse_Zicfilp" ] @@ -12329,7 +12330,6 @@ "norm:ctr_depth", "norm:Smctr_recording_criteria", "norm:Smctr_transfer_steps", - "norm:Smctr_CTR_CSR_interface", "norm:Smctr_scope", "norm:Ssctr_transfer_steps", "norm:Smctr_Ssctr_depend" diff --git a/src/priv/hypervisor.adoc b/src/priv/hypervisor.adoc index 2f01b2ed1..670e1d7b2 100644 --- a/src/priv/hypervisor.adoc +++ b/src/priv/hypervisor.adoc @@ -1509,9 +1509,13 @@ instructions, rather than raising fetch exceptions instead. ==== [[norm:hlvx-wu_valid32]] -HLVX.WU is valid for RV32, even though LWU and HLV.WU are not. (For -RV32, HLVX.WU can be considered a variant of HLV.W, as sign extension is -irrelevant for 32-bit values.) +HLVX.WU is valid for RV32, even though LWU and HLV.WU are not. + +[NOTE] +==== +For RV32, HLVX.WU can be considered a variant of HLV.W, as sign extension is +irrelevant for 32-bit values. +==== The memory accesses performed by the `HLVX.*` instructions are not subject to pointer masking (see <>). @@ -1870,15 +1874,14 @@ the implementation may automatically write to it on a trap. [[two-stage-translation]] === Two-Stage Address Translation -[[norm:H_vm_twostage]] -Whenever the current virtualization mode V is 1, two-stage address +[#norm:H_vm_twostage]#Whenever the current virtualization mode V is 1, two-stage address translation and protection is in effect. For any virtual memory access, the original virtual address is converted in the first stage by VS-level address translation, as controlled by the `vsatp` register, into a _guest physical address_. The guest physical address is then converted in the second stage by guest physical address translation, as controlled by the `hgatp` register, into a supervisor physical address. The two -stages are known also as VS-stage and G-stage translation. Although +stages are known also as VS-stage and G-stage translation.# Although there is no option to disable two-stage address translation when V=1, either stage of translation can be effectively disabled by zeroing the corresponding `vsatp` or `hgatp` register. @@ -2135,6 +2138,9 @@ supervisor physical addresses. When running with virtualization in VS/VU mode with csr:vsatp[mode]=Bare, this means that those qty:2[bits] may be subject to pointer masking, depending on csr:hgatp[mode] and csr:senvcfg[pmm] or csr:henvcfg[pmm] (for VU/VS mode). If csr:vsatp[mode]{ne}Bare, this issue does *not* apply. +Those qty:2[bits] may likewise be subject to pointer masking according to +csr:hstatus[hupmm] for explicit memory accesses made by `HLV.\*` or `HSV.*` +instructions in U-mode as though in VU-mode. [NOTE] ==== @@ -2149,8 +2155,9 @@ entries. To support implementations where (XLEN-PMLEN) can be less than the GPA width supported by `hgatp.MODE`, hypervisors should execute an `HFENCE.GVMA` with -_rs1_=`x0` if the `henvcfg.PMM` is changed from or to a value where (XLEN-PMLEN) -is less than GPA width supported by the `hgatp` translation mode of that guest. +_rs1_=`x0` if either `henvcfg.PMM` or `hstatus.HUPMM` is changed from or to a +value where (XLEN-PMLEN) is less than GPA width supported by the `hgatp` +translation mode of that guest. Specifically, these cases are: * `PMLEN=7` and `hgatp.MODE=sv57x4` diff --git a/src/priv/smctr.adoc b/src/priv/smctr.adoc index e9f157316..6111fa8f3 100644 --- a/src/priv/smctr.adoc +++ b/src/priv/smctr.adoc @@ -12,7 +12,7 @@ CTR defines a circular (FIFO) buffer. Each buffer entry holds a record for a si [#norm:Smctr_transfer_steps]#Recorded transfers are inserted at the write pointer, which is then incremented, while older recorded transfers may be overwritten once the buffer is full. Or the user can enable RAS (Return Address Stack) emulation mode, where only function calls are recorded, and function returns pop the last call record. The source PC, target PC, and some optional metadata (transfer type, elapsed cycles) are stored for each recorded transfer.# -[#norm:Smctr_CTR_CSR_interface]#The CTR buffer is accessible through an indirect CSR interface, such that software can specify which logical entry in the buffer it wishes to read or write. Logical entry 0 always corresponds to the youngest recorded transfer, followed by entry 1 as the next youngest, and so on.# +The CTR buffer is accessible through an indirect CSR interface, such that software can specify which logical entry in the buffer it wishes to read or write. Logical entry 0 always corresponds to the youngest recorded transfer, followed by entry 1 as the next youngest, and so on. [#norm:Smctr_scope]#The machine-level extension, *Smctr*, encompasses all newly added Control Status Registers (CSRs), instructions, and behavior modifications for a hart across all privilege levels.# [#norm:Ssctr_transfer_steps]#The corresponding supervisor-level extension, *Ssctr*, is essentially identical to Smctr, except that it excludes machine-level CSRs and behaviors not intended to be directly accessible at the supervisor level.# diff --git a/src/priv/supervisor.adoc b/src/priv/supervisor.adoc index e6cee78f1..49a9e77d1 100644 --- a/src/priv/supervisor.adoc +++ b/src/priv/supervisor.adoc @@ -931,6 +931,10 @@ according to the values in <>. If Ssnpm is not implemented, `PMM` is read-only zero. The `PMM` field is read-only zero for RV32. +[[norm:senvcfg_pmm_immediate]] +Changing `senvcfg.PMM` takes effect immediately, without the need to execute an +`SFENCE.VMA` instruction. + [[senvcfg_pmm-values]] [%header, cols="25%,75%", options="header"] diff --git a/src/unpriv/f-st-ext.adoc b/src/unpriv/f-st-ext.adoc index a5c1d5603..46e83fe94 100644 --- a/src/unpriv/f-st-ext.adoc +++ b/src/unpriv/f-st-ext.adoc @@ -336,9 +336,8 @@ flag is set#. [#norm:fcvt_int_float_valid_input]#<> gives the range of valid inputs for insn:fcvt.w.s[], insn:fcvt.wu.s[], insn:fcvt.l.s[], and insn:fcvt.lu.s[] and the behavior of these instructions for invalid inputs#. -[[norm:fcvt_round]] -All floating-point to integer and integer to floating-point conversion -instructions round according to the _rm_ field. A floating-point +[#norm:fcvt_round]#All floating-point to integer and integer to floating-point conversion +instructions round according to the _rm_ field.# A floating-point register can be initialized to floating-point positive zero using insn:fcvt.s.w[rd,x0], which will never set any exception flags. diff --git a/src/unpriv/zv.adoc b/src/unpriv/zv.adoc index 0825e6f62..daa0e1365 100644 --- a/src/unpriv/zv.adoc +++ b/src/unpriv/zv.adoc @@ -38,6 +38,7 @@ include::zvfbfmin.adoc[] include::zvfbfwma.adoc[] include::zvbb.adoc[] include::zvbc.adoc[] +include::zvabd.adoc[] === Vector Instruction Listing diff --git a/src/unpriv/zvabd.adoc b/src/unpriv/zvabd.adoc new file mode 100644 index 000000000..21e5e9206 --- /dev/null +++ b/src/unpriv/zvabd.adoc @@ -0,0 +1,358 @@ +[[ext:zvabd]] +=== ext:zvabd[] Vector Extension for Integer Absolute Difference + +==== 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 +Below is a list of all of the instructions that are included in the extension. +[%autowidth] +[%header,cols="2,4"] +|=== +|Mnemonic +|Instruction + +| vabd.vv / vabd.vx | <> +| vabdu.vv / vabdu.vx | <> +| vwabda.vv / vwabda.vx | <> +| vwabdau.vv / vwabdau.vx | <> + +|=== + +NOTE: Since the targeted use cases are mostly based on 8-bit and 16-bit integer, vwabda/vwabdau are designed for only SEW=8 and SEW=16. + +[#norm:Zvabd_dependent_Zve32x]#The Zvabd extension depend upon ext:zve32x[].# + +==== 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-vabd, Vector Signed Integer Absolute Difference]] +===== insn:vabd.vv[] and insn:vabd.vx[] + +Synopsis:: +Vector Single-Width Signed Integer Absolute Difference + +Mnemonic:: +vabd.vv _vd_, _vs2_, _vs1_, _vm_ + +vabd.vx _vd_, _vs2_, _rs1_, _vm_ + +Encoding (Vector-Vector):: +[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'}, +]} +.... + +Encoding (Vector-Scalar):: +[wavedrom, , svg] +.... +{reg: [ + {bits: 7, name: 'OP-V'}, + {bits: 5, name: 'vd'}, + {bits: 3, name: 'OPMVX'}, + {bits: 5, name: 'rs1'}, + {bits: 5, name: 'vs2'}, + {bits: 1, name: 'vm', attr: 'vm'}, + {bits: 6, name: 0x15, attr: 'funct6'}, +]} +.... + +Arguments:: + +[%autowidth] +[%header,cols="4,2,2"] +|=== +|Register +|Direction +|Definition + +| _vs1_/_rs1_ | input | Op1 +| _vs2_ | input | Op2 +| _vd_ | output | Absolute difference +|=== + +Description:: +[#norm:vabd_op]#This instruction computes the absolute difference between the signed integer SEW-bit `Op1` and `Op2` elements, writing the result into the SEW-bit elements in _vd_.# + +[#norm:vabd_sew_defined]#vabd provides support for SEW of 8, 16, and 32. If ext:zve64x[] is supported, then vabd also adds support for SEW 64.# + +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] == 0b1 then { + let op1 = match suffix { + "vv" => vs1_val[i], + "vx" => sext_or_truncate_to_sew(X(rs1)) + }; + result[i] = to_bits(SEW, abs_int(signed(vs2_val[i]) - signed(op1))); + } +} +write_vreg(num_elem, SEW, LMUL_pow, vd, result); +set_vstart(zeros()); +RETIRE_SUCCESS +-- + +NOTE: A vector of integer values can have its absolute value computed using an +absolute-difference instruction with a scalar operand of `x0`. An +assembly pseudoinstruction insn:vabs.v[vd,vs2] = insn:vabd.vx[vd,vs2,x0] is provided. + +[[insns-vabdu, Vector Unsigned Integer Absolute Difference]] +===== insn:vabdu.vv[] and insn:vabdu.vx[] + +Synopsis:: +Vector Single-Width Unsigned Integer Absolute Difference + +Mnemonic:: +vabdu.vv _vd_, _vs2_, _vs1_, _vm_ + +vabdu.vx _vd_, _vs2_, _rs1_, _vm_ + +Encoding (Vector-Vector):: +[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'}, +]} +.... + +Encoding (Vector-Scalar):: +[wavedrom, , svg] +.... +{reg: [ + {bits: 7, name: 'OP-V'}, + {bits: 5, name: 'vd'}, + {bits: 3, name: 'OPMVX'}, + {bits: 5, name: 'rs1'}, + {bits: 5, name: 'vs2'}, + {bits: 1, name: 'vm', attr: 'vm'}, + {bits: 6, name: 0x16, attr: 'funct6'}, +]} +.... + +Arguments:: + +[%autowidth] +[%header,cols="4,2,2"] +|=== +|Register +|Direction +|Definition + +| _vs1_/_rs1_ | input | Op1 +| _vs2_ | input | Op2 +| _vd_ | output | Absolute difference +|=== + +Description:: +[#norm:vabdu_op]#This instruction computes the absolute difference between the unsigned integer SEW-bit `Op1` and `Op2` elements, writing the result into the SEW-bit elements in _vd_.# + +[#norm:vabdu_sew_defined]#vabdu provides support for SEW of 8, 16, and 32. If ext:zve64x[] is supported, then vabdu also adds support for SEW 64.# + +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] == 0b1 then { + result[i] = { + let op1 = match suffix { + "vv" => vs1_val[i], + "vx" => sext_or_truncate_to_sew(X(rs1)) + }; + let abs_diff = if unsigned(vs2_val[i]) >= unsigned(op1) + then unsigned(vs2_val[i] - op1) + else unsigned(op1 - vs2_val[i]); + to_bits(SEW, abs_diff); + } + }; +}; +write_vreg(num_elem, SEW, LMUL_pow, vd, result); +set_vstart(zeros()); +RETIRE_SUCCESS +-- + +[[insns-vwabda, Vector Signed Integer Absolute Difference And Accumulate]] +===== insn:vwabda.vv[] and insn:vwabda.vx[] + +Synopsis:: + Vector Widening Signed Integer Absolute Difference and Accumulate, Overwrite Addend + +Mnemonic:: +vwabda.vv _vd_, _vs2_, _vs1_, _vm_ + +vwabda.vx _vd_, _vs2_, _rs1_, _vm_ + +Encoding (Vector-Vector):: +[wavedrom, , svg] +.... +{reg: [ + {bits: 7, name: 'OP-V'}, + {bits: 5, name: 'vd'}, + {bits: 3, name: 'OPIVV'}, + {bits: 5, name: 'vs1'}, + {bits: 5, name: 'vs2'}, + {bits: 1, name: 'vm', attr: 'vm'}, + {bits: 6, name: 0x3D, attr: 'funct6'}, +]} +.... + +Encoding (Vector-Scalar):: +[wavedrom, , svg] +.... +{reg: [ + {bits: 7, name: 'OP-V'}, + {bits: 5, name: 'vd'}, + {bits: 3, name: 'OPIVX'}, + {bits: 5, name: 'rs1'}, + {bits: 5, name: 'vs2'}, + {bits: 1, name: 'vm', attr: 'vm'}, + {bits: 6, name: 0x3D, attr: 'funct6'}, +]} +.... + +Reserved Encodings:: +* [#norm:vwabda_sew_rsv]#`SEW` is neither 8 nor 16.# + +Arguments:: + +[%autowidth] +[%header,cols="4,2,2"] +|=== +|Register +|Direction +|Definition + +| _vs1_/_rs1_ | input | Op1 +| _vs2_ | input | Op2 +| _vd_ | input/output | Accumulator and result (2*SEW-bit) +|=== + +Description:: +[#norm:vwabda_op]#This instruction computes the absolute difference between the signed integer SEW-bit `Op1` and `Op2` elements, and accumulates the results into the 2*SEW-bit accumulator elements in _vd_.# + +[#norm:vwabda_sew_defined]#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] == 0b1 then { + result[i] = { + let op1 = match suffix { + "vv" => vs1_val[i], + "vx" => sext_or_truncate_to_sew(X(rs1)) + }; + let diff = signed(vs2_val[i]) - signed(op1); + to_bits_truncate(SEW_widen, signed(vd_val[i]) + abs_int(diff)); + } + } +} +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]] +===== insn:vwabdau.vv[] and insn:vwabdau.vx[] + +Synopsis:: +Vector Widening Unsigned Integer Absolute Difference and Accumulate, Overwrite Addend. + +Mnemonic:: +vwabdau.vv _vd_, _vs2_, _vs1_, _vm_ + +vwabdau.vx _vd_, _vs2_, _rs1_, _vm_ + +Encoding (Vector-Vector):: +[wavedrom, , svg] +.... +{reg: [ + {bits: 7, name: 'OP-V'}, + {bits: 5, name: 'vd'}, + {bits: 3, name: 'OPIVV'}, + {bits: 5, name: 'vs1'}, + {bits: 5, name: 'vs2'}, + {bits: 1, name: 'vm', attr: 'vm'}, + {bits: 6, name: 0x3E, attr: 'funct6'}, +]} +.... + +Encoding (Vector-Scalar):: +[wavedrom, , svg] +.... +{reg: [ + {bits: 7, name: 'OP-V'}, + {bits: 5, name: 'vd'}, + {bits: 3, name: 'OPIVX'}, + {bits: 5, name: 'rs1'}, + {bits: 5, name: 'vs2'}, + {bits: 1, name: 'vm', attr: 'vm'}, + {bits: 6, name: 0x3E, attr: 'funct6'}, +]} +.... + +Reserved Encodings:: +* [#norm:vwabdau_sew_rsv]#`SEW` is neither 8 nor 16.# + +Arguments:: + +[%autowidth] +[%header,cols="4,2,2"] +|=== +|Register +|Direction +|Definition + +| _vs1_/_rs1_ | input | Op1 +| _vs2_ | input | Op2 +| _vd_ | input/output | Accumulator and result (2*SEW-bit) +|=== + +Description:: +[#norm:vwabdau_op]#This instruction computes the absolute difference between the unsigned integer SEW-bit `Op1` and `Op2` elements, and accumulates the results into the 2*SEW-bit accumulator elements in _vd_.# + +[#norm:vwabdau_sew_defined]#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] == 0b1 then { + result[i] = { + let op1 = match suffix { + "vv" => vs1_val[i], + "vx" => sext_or_truncate_to_sew(X(rs1)) + }; + let abs_diff = if unsigned(vs2_val[i]) >= unsigned(op1) + then unsigned(vs2_val[i] - op1) + else unsigned(op1 - vs2_val[i]); + to_bits_truncate(SEW_widen, unsigned(vd_val[i]) + abs_diff); + } + } +} +write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); +set_vstart(zeros()); +RETIRE_SUCCESS +--