From 971bc71be1429c97a6d3cc0c66a2bb2e6d5472ff Mon Sep 17 00:00:00 2001 From: Abhinav Agarwal Date: Wed, 22 Jul 2026 13:56:22 -0700 Subject: [PATCH 1/9] Clarify PMM fence handling (#3255) Include hstatus.HUPMM in the two-stage GPA masking and HFENCE.GVMA guidance. Specify in the supervisor chapter that senvcfg.PMM changes take effect immediately without SFENCE.VMA, avoiding TLB flushes on context switches. Signed-off-by: Abhinav Agarwal --- normative_rule_defs/supervisor.yaml | 2 ++ ref/riscv-spec-norm-tags.json | 2 ++ src/priv/hypervisor.adoc | 8 ++++++-- src/priv/supervisor.adoc | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) 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/ref/riscv-spec-norm-tags.json b/ref/riscv-spec-norm-tags.json index 813a0b371..39586ef2c 100644 --- a/ref/riscv-spec-norm-tags.json +++ b/ref/riscv-spec-norm-tags.json @@ -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 .", @@ -10950,6 +10951,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" ] diff --git a/src/priv/hypervisor.adoc b/src/priv/hypervisor.adoc index 2f01b2ed1..a5139cf96 100644 --- a/src/priv/hypervisor.adoc +++ b/src/priv/hypervisor.adoc @@ -2135,6 +2135,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 +2152,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/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"] From 74010d05a61c01a73adcc79fd3d0d8da6d3cdf7e Mon Sep 17 00:00:00 2001 From: Bill Traynor Date: Thu, 23 Jul 2026 19:48:17 -0400 Subject: [PATCH 2/9] ci: gate autofix on update-norm-rules label and exempt bots from DCO (#3271) Autofix regeneration of the normative tag reference commits back to the PR, so gate it behind the 'update-norm-rules' label: a maintainer applies the label when a PR that changes normative rules is ready, and autofix regenerates ref/ and pushes it before merge, instead of running on every PR update. Because that push lands as the autofix-ci[bot] account, and bots cannot sign off their commits, exempt bot-authored/-committed commits from the DCO check so the bot commit does not fail it. Point the check-normative-tags freshness error at the label so a maintainer knows how to trigger the regeneration. Signed-off-by: Bill Traynor Co-authored-by: Claude Opus 4.8 --- .github/workflows/autofix.yml | 12 ++++++++++++ .github/workflows/check-normative-tags.yml | 9 ++++++--- .github/workflows/dco_check.yml | 12 +++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) 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) { From 4eeb192c79a47bc10747cb5ca36ab199fa1eb8b1 Mon Sep 17 00:00:00 2001 From: arvern-dev Date: Sat, 25 Jul 2026 02:01:05 +0200 Subject: [PATCH 3/9] Allocate marchid for aRVern core (#3272) Signed-off-by: arvern-dev --- marchid.md | 1 + 1 file changed, 1 insertion(+) diff --git a/marchid.md b/marchid.md index 30c60472a..7b1a0821a 100644 --- a/marchid.md +++ b/marchid.md @@ -71,3 +71,4 @@ Raptor | Yu Jin | [Yu Jin](mailto:lambda.jinyu@g 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 From f08fb2a9b22f0bd350dd61598addf7ca3193bd82 Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Sat, 25 Jul 2026 23:45:49 -0700 Subject: [PATCH 4/9] Email and GitHub change for River (#3273) Signed-off-by: Tristan Ross --- marchid.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marchid.md b/marchid.md index 7b1a0821a..0f143ff4c 100644 --- a/marchid.md +++ b/marchid.md @@ -66,7 +66,7 @@ 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 From 4757308fad67f6a8bc7235703d4bb8101ccf296a Mon Sep 17 00:00:00 2001 From: Umer Shahid Date: Mon, 27 Jul 2026 23:48:06 +0500 Subject: [PATCH 5/9] Updated manuals based on CSS WG comments 1 (#3275) Signed-off-by: umershahidengr --- normative_rule_defs/smctr.yaml | 4 ---- ref/riscv-spec-norm-tags.json | 8 +++----- src/priv/hypervisor.adoc | 15 +++++++++------ src/priv/smctr.adoc | 2 +- src/unpriv/f-st-ext.adoc | 5 ++--- 5 files changed, 15 insertions(+), 19 deletions(-) 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/ref/riscv-spec-norm-tags.json b/ref/riscv-spec-norm-tags.json index 39586ef2c..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", @@ -2373,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).", @@ -2403,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.", @@ -2621,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.", @@ -12331,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 a5139cf96..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. 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/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. From 8da5d1936a1b0d1b394d9880d030dce386dce908 Mon Sep 17 00:00:00 2001 From: qianjiayan Date: Tue, 28 Jul 2026 16:10:24 +0800 Subject: [PATCH 6/9] Add Zvabd extension and integrate with normative-rule pipeline Add the integer vector absolute difference (Zvabd) extension as a subsection of the Vector Extensions chapter, including its normative rule definitions. - src/unpriv/zvabd.adoc: Zvabd chapter content - src/unpriv/zv.adoc: include Zvabd chapter - normative_rule_defs/zvabd.yaml: Zvabd normative rules Signed-off-by: qianjiayan --- normative_rule_defs/zvabd.yaml | 53 +++++++ src/unpriv/zv.adoc | 1 + src/unpriv/zvabd.adoc | 260 +++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 normative_rule_defs/zvabd.yaml create mode 100644 src/unpriv/zvabd.adoc diff --git a/normative_rule_defs/zvabd.yaml b/normative_rule_defs/zvabd.yaml new file mode 100644 index 000000000..2191b80be --- /dev/null +++ b/normative_rule_defs/zvabd.yaml @@ -0,0 +1,53 @@ +--- +# 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: Zvabd_eew + tags: ["norm:Zvabd_eew", "norm:Zvabd_eew_Zve64x"] + + - name: vabs_op + tags: ["norm:vabs_op"] + + - name: vabd_sew_rsv + tags: ["norm:vabd_sew_rsv"] + + - name: vabd_op + tags: ["norm:vabd_op"] + + - name: vabd_sew_defined + tags: ["norm:vabd_sew_defined"] + + - name: vabdu_sew_rsv + tags: ["norm:vabdu_sew_rsv"] + + - 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/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..07aafaa96 --- /dev/null +++ b/src/unpriv/zvabd.adoc @@ -0,0 +1,260 @@ +[[ext:zvabd]] +=== ext:zvabd[] Vector 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 | <> +| vabd.vv | <> +| vabdu.vv | <> +| vwabda.vv | <> +| vwabdau.vv | <> + +|=== + +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. + +[#norm:Zvabd_dependent_Zve32x]#The Zvabd extension depend on ext:zve32x[].# + +[#norm:Zvabd_eew]#If ext:zve32x[] is supported then vabs provide support for SEW of 8, 16, and 32.# [#norm:Zvabd_eew_Zve64x]#If ext: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]] +===== insn: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:: +[#norm:vabs_op]#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 { + 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]] +===== insn: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:: +* [#norm:vabd_sew_rsv]#`SEW` is neither 8 nor 16.# + +Description:: +[#norm:vabd_op]#This instruction computes the absolute difference between the elements of two signed integer SEW-bit source operands vs1 and vs2.# + +[#norm:vabd_sew_defined]#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]] +===== insn: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:: +* [#norm:vabdu_sew_rsv]#`SEW` is neither 8 nor 16.# + +Description:: +[#norm:vabdu_op]#This instruction computes the absolute difference between the elements of two unsigned integer SEW-bit source operands vs1 and vs2.# + +[#norm:vabdu_sew_defined]#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]] +===== insn: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:: +* [#norm:vwabda_sew_rsv]#`SEW` is neither 8 nor 16.# + +Description:: +[#norm:vwabda_op]#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.# + +[#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] == 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]] +===== insn: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:: +* [#norm:vwabdau_sew_rsv]#`SEW` is neither 8 nor 16.# + +Description:: +[#norm:vwabdau_op]#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.# + +[#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] == 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 +-- From 60b6370c63416588454fe24097749609f0740668 Mon Sep 17 00:00:00 2001 From: qianjiayan Date: Fri, 7 Aug 2026 15:16:56 +0800 Subject: [PATCH 7/9] address the comments from arc 20260805 --- src/unpriv/zvabd.adoc | 49 ++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/unpriv/zvabd.adoc b/src/unpriv/zvabd.adoc index 07aafaa96..165cb8e72 100644 --- a/src/unpriv/zvabd.adoc +++ b/src/unpriv/zvabd.adoc @@ -1,5 +1,5 @@ [[ext:zvabd]] -=== ext:zvabd[] Vector Extension for Integer Vector Absolute Difference Instructions +=== 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)]. @@ -7,8 +7,6 @@ This document describes the Zvabd extension for instructions that compute the el 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"] @@ -26,9 +24,7 @@ Below is a list of all of the instructions that are included in the extension. 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. -[#norm:Zvabd_dependent_Zve32x]#The Zvabd extension depend on ext:zve32x[].# - -[#norm:Zvabd_eew]#If ext:zve32x[] is supported then vabs provide support for SEW of 8, 16, and 32.# [#norm:Zvabd_eew_Zve64x]#If ext:zve64x[] is supported then vabs also add support for SEW 64.# +[#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]. @@ -61,14 +57,15 @@ Encoding:: Description:: [#norm:vabs_op]#An absolute value operation is performed on each element of vs2# +[#norm:Zvabd_eew]#vabs provide support for SEW of 8, 16, and 32.# [#norm:Zvabd_eew_Zve64x]#If ext:zve64x[] is supported then vabs also add 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] == bitone then { - result[i] = abs(signed(vs2_val[i])); - } + if mask[i] == 0b1 then + result[i] = to_bits(SEW, abs_int(signed(vs2_val[i]))); } write_vreg(num_elem, SEW, LMUL_pow, vd, result); set_vstart(zeros()); @@ -111,8 +108,8 @@ Operation:: -- 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]); + if mask[i] == 0b1 then { + result[i] = to_bits(SEW, abs_int(signed(vs2_val[i]) - signed(vs1_val[i]))); } } write_vreg(num_elem, SEW, LMUL_pow, vd, result); @@ -156,10 +153,16 @@ Operation:: -- 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]); - } -} + if mask[i] == 0b1 then { + result[i] = { + let abs_diff = if unsigned(vs2_val[i]) >= unsigned(vs1_val[i]) + then unsigned(vs2_val[i] - vs1_val[i]) + else unsigned(vs1_val[i] - vs2_val[i]); + to_bits(SEW, abs_diff); + } + + }; +}; write_vreg(num_elem, SEW, LMUL_pow, vd, result); set_vstart(zeros()); RETIRE_SUCCESS @@ -203,8 +206,11 @@ 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]; + if mask[i] == 0b1 then { + result[i] = { + let diff = signed(vs2_val[i]) - signed(vs1_val[i]); + to_bits_unsafe(SEW_widen, signed(vd_val[i]) + abs_int(diff)); + } } } write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); @@ -250,8 +256,13 @@ 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]; + if mask[i] == 0b1 then { + result[i] = { + let abs_diff = if unsigned(vs2_val[i]) >= unsigned(vs1_val[i]) + then unsigned(vs2_val[i] - vs1_val[i]) + else unsigned(vs1_val[i] - vs2_val[i]); + to_bits_unsafe(SEW_widen, unsigned(vd_val[i]) + abs_diff); + } } } write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); From 2d4623559c60076d1f2419ed418a70af006962f1 Mon Sep 17 00:00:00 2001 From: qianjiayan Date: Wed, 19 Aug 2026 15:45:30 +0800 Subject: [PATCH 8/9] according to ARC feedback, using the new opcode and add the .vx variants --- normative_rule_defs/zvabd.yaml | 6 - src/unpriv/zvabd.adoc | 241 +++++++++++++++++++++++---------- 2 files changed, 167 insertions(+), 80 deletions(-) diff --git a/normative_rule_defs/zvabd.yaml b/normative_rule_defs/zvabd.yaml index 2191b80be..62d858b45 100644 --- a/normative_rule_defs/zvabd.yaml +++ b/normative_rule_defs/zvabd.yaml @@ -10,12 +10,6 @@ normative_rule_definitions: - name: Zvabd_dependent_Zve32x tags: ["norm:Zvabd_dependent_Zve32x"] - - name: Zvabd_eew - tags: ["norm:Zvabd_eew", "norm:Zvabd_eew_Zve64x"] - - - name: vabs_op - tags: ["norm:vabs_op"] - - name: vabd_sew_rsv tags: ["norm:vabd_sew_rsv"] diff --git a/src/unpriv/zvabd.adoc b/src/unpriv/zvabd.adoc index 165cb8e72..e0871a28a 100644 --- a/src/unpriv/zvabd.adoc +++ b/src/unpriv/zvabd.adoc @@ -14,15 +14,14 @@ Below is a list of all of the instructions that are included in the extension. |Mnemonic |Instruction -| vabs.v | <> -| vabd.vv | <> -| vabdu.vv | <> -| vwabda.vv | <> -| vwabdau.vv | <> +| 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, `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. +NOTE: Since the targeted use cases are mostly based on 8-bit and 16-bit integer, Zvabd are designed for only SEW=8 and SEW=16. [#norm:Zvabd_dependent_Zve32x]#The Zvabd extension depend upon ext:zve32x[].# @@ -31,75 +30,63 @@ The semantics of each instruction is expressed in a SAIL-like syntax, following ==== Instructions -[[insns-vabs, Vector Signed Integer Absolute]] -===== insn:vabs.v[] +[[insns-vabd, Vector Signed Integer Absolute Difference]] +===== insn:vabd.vv[] and insn:vabd.vx[] Synopsis:: -Vector Single-Width Signed Integer Absolute +Vector Single-Width Signed Integer Absolute Difference Mnemonic:: -vabs.v _vd_, _vs2_, _vm_ +vabd.vv _vd_, _vs2_, _vs1_, _vm_ + +vabd.vx _vd_, _vs2_, _rs1_, _vm_ -Encoding:: +Encoding (Vector-Vector):: [wavedrom, , svg] .... {reg: [ {bits: 7, name: 'OP-V'}, {bits: 5, name: 'vd'}, {bits: 3, name: 'OPMVV'}, - {bits: 5, name: 0x10}, + {bits: 5, name: 'vs1'}, {bits: 5, name: 'vs2'}, {bits: 1, name: 'vm', attr: 'vm'}, - {bits: 6, name: 'VXUNARY0', attr: 'funct6'}, + {bits: 6, name: 0x15, attr: 'funct6'}, ]} .... -Description:: -[#norm:vabs_op]#An absolute value operation is performed on each element of vs2# - -[#norm:Zvabd_eew]#vabs provide support for SEW of 8, 16, and 32.# [#norm:Zvabd_eew_Zve64x]#If ext:zve64x[] is supported then vabs also add 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] = to_bits(SEW, abs_int(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]] -===== insn:vabd.vv[] - -Synopsis:: -Vector Single-Width Signed Integer Absolute Difference - -Mnemonic:: -vabd.vv _vd_, _vs2_, _vs1_, _vm_ - -Encoding:: +Encoding (Vector-Scalar):: [wavedrom, , svg] .... {reg: [ {bits: 7, name: 'OP-V'}, {bits: 5, name: 'vd'}, - {bits: 3, name: 'OPMVV'}, - {bits: 5, name: 'vs1'}, + {bits: 3, name: 'OPMVX'}, + {bits: 5, name: 'rs1'}, {bits: 5, name: 'vs2'}, {bits: 1, name: 'vm', attr: 'vm'}, - {bits: 6, name: 0x11, attr: 'funct6'}, + {bits: 6, name: 0x15, attr: 'funct6'}, ]} .... Reserved Encodings:: * [#norm:vabd_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_ | output | Absolute difference +|=== + Description:: -[#norm:vabd_op]#This instruction computes the absolute difference between the elements of two signed integer SEW-bit source operands vs1 and vs2.# +[#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]#This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.# @@ -109,7 +96,11 @@ Operation:: 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] = to_bits(SEW, abs_int(signed(vs2_val[i]) - signed(vs1_val[i]))); + 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); @@ -117,16 +108,21 @@ 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[] +===== insn:vabdu.vv[] and insn:vabdu.vx[] Synopsis:: Vector Single-Width Unsigned Integer Absolute Difference Mnemonic:: -vabdu.vv _vd_, _vs2_, _vs1_, _vm_ +vabdu.vv _vd_, _vs2_, _vs1_, _vm_ + +vabdu.vx _vd_, _vs2_, _rs1_, _vm_ -Encoding:: +Encoding (Vector-Vector):: [wavedrom, , svg] .... {reg: [ @@ -136,15 +132,43 @@ Encoding:: {bits: 5, name: 'vs1'}, {bits: 5, name: 'vs2'}, {bits: 1, name: 'vm', attr: 'vm'}, - {bits: 6, name: 0x13, attr: 'funct6'}, + {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'}, ]} .... Reserved Encodings:: * [#norm:vabdu_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_ | output | Absolute difference +|=== + Description:: -[#norm:vabdu_op]#This instruction computes the absolute difference between the elements of two unsigned integer SEW-bit source operands vs1 and vs2.# +[#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]#This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.# @@ -155,12 +179,15 @@ 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 abs_diff = if unsigned(vs2_val[i]) >= unsigned(vs1_val[i]) - then unsigned(vs2_val[i] - vs1_val[i]) - else unsigned(vs1_val[i] - vs2_val[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); @@ -169,33 +196,62 @@ RETIRE_SUCCESS -- [[insns-vwabda, Vector Signed Integer Absolute Difference And Accumulate]] -===== insn:vwabda.vv[] +===== 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.vv _vd_, _vs2_, _vs1_, _vm_ + +vwabda.vx _vd_, _vs2_, _rs1_, _vm_ -Encoding:: +Encoding (Vector-Vector):: [wavedrom, , svg] .... {reg: [ {bits: 7, name: 'OP-V'}, {bits: 5, name: 'vd'}, - {bits: 3, name: 'OPMVV'}, + {bits: 3, name: 'OPIVV'}, {bits: 5, name: 'vs1'}, {bits: 5, name: 'vs2'}, {bits: 1, name: 'vm', attr: 'vm'}, - {bits: 6, name: 0x15, attr: 'funct6'}, + {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 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.# +[#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.# @@ -208,8 +264,12 @@ let (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_ foreach (i from 0 to (num_elem - 1)) { if mask[i] == 0b1 then { result[i] = { - let diff = signed(vs2_val[i]) - signed(vs1_val[i]); - to_bits_unsafe(SEW_widen, signed(vd_val[i]) + abs_int(diff)); + 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)); } } } @@ -219,33 +279,62 @@ RETIRE_SUCCESS -- [[insns-vwabdau, Vector Unsigned Integer Absolute Difference And Accumulate]] -===== insn:vwabdau.vv[] +===== 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.vv _vd_, _vs2_, _vs1_, _vm_ + +vwabdau.vx _vd_, _vs2_, _rs1_, _vm_ -Encoding:: +Encoding (Vector-Vector):: [wavedrom, , svg] .... {reg: [ {bits: 7, name: 'OP-V'}, {bits: 5, name: 'vd'}, - {bits: 3, name: 'OPMVV'}, + {bits: 3, name: 'OPIVV'}, {bits: 5, name: 'vs1'}, {bits: 5, name: 'vs2'}, {bits: 1, name: 'vm', attr: 'vm'}, - {bits: 6, name: 0x16, attr: 'funct6'}, + {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 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.# +[#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.# @@ -258,10 +347,14 @@ let (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_ foreach (i from 0 to (num_elem - 1)) { if mask[i] == 0b1 then { result[i] = { - let abs_diff = if unsigned(vs2_val[i]) >= unsigned(vs1_val[i]) - then unsigned(vs2_val[i] - vs1_val[i]) - else unsigned(vs1_val[i] - vs2_val[i]); - to_bits_unsafe(SEW_widen, unsigned(vd_val[i]) + abs_diff); + 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); } } } From 971332b7688085228d9d804995c43fa79b482b74 Mon Sep 17 00:00:00 2001 From: qianjiayan Date: Thu, 20 Aug 2026 14:41:55 +0800 Subject: [PATCH 9/9] add all SEW support for vabd/vabdu --- normative_rule_defs/zvabd.yaml | 6 ------ src/unpriv/zvabd.adoc | 12 +++--------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/normative_rule_defs/zvabd.yaml b/normative_rule_defs/zvabd.yaml index 62d858b45..0fe33190b 100644 --- a/normative_rule_defs/zvabd.yaml +++ b/normative_rule_defs/zvabd.yaml @@ -10,18 +10,12 @@ normative_rule_definitions: - name: Zvabd_dependent_Zve32x tags: ["norm:Zvabd_dependent_Zve32x"] - - name: vabd_sew_rsv - tags: ["norm:vabd_sew_rsv"] - - name: vabd_op tags: ["norm:vabd_op"] - name: vabd_sew_defined tags: ["norm:vabd_sew_defined"] - - name: vabdu_sew_rsv - tags: ["norm:vabdu_sew_rsv"] - - name: vabdu_op tags: ["norm:vabdu_op"] diff --git a/src/unpriv/zvabd.adoc b/src/unpriv/zvabd.adoc index e0871a28a..21e5e9206 100644 --- a/src/unpriv/zvabd.adoc +++ b/src/unpriv/zvabd.adoc @@ -21,7 +21,7 @@ Below is a list of all of the instructions that are included in the extension. |=== -NOTE: Since the targeted use cases are mostly based on 8-bit and 16-bit integer, Zvabd are designed for only SEW=8 and SEW=16. +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[].# @@ -68,9 +68,6 @@ Encoding (Vector-Scalar):: ]} .... -Reserved Encodings:: -* [#norm:vabd_sew_rsv]#`SEW` is neither 8 nor 16.# - Arguments:: [%autowidth] @@ -88,7 +85,7 @@ Arguments:: 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]#This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.# +[#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] @@ -150,9 +147,6 @@ Encoding (Vector-Scalar):: ]} .... -Reserved Encodings:: -* [#norm:vabdu_sew_rsv]#`SEW` is neither 8 nor 16.# - Arguments:: [%autowidth] @@ -170,7 +164,7 @@ Arguments:: 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]#This instruction is defined for SEW=8 and SEW=16, otherwise the instruction encoding is reserved.# +[#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]