From eed4ca5d0b47989aa0891f3c1be8210a70adc9b9 Mon Sep 17 00:00:00 2001 From: Derek Hower Date: Thu, 19 Sep 2024 07:35:10 -0700 Subject: [PATCH] Add manual generator --- .github/workflows/pages.yml | 12 +- README.adoc | 2 +- arch/ext/A.yaml | 6 +- arch/ext/B.yaml | 8 +- arch/ext/C.yaml | 2 +- arch/ext/D.yaml | 4 +- arch/ext/F.yaml | 2 +- arch/ext/H.yaml | 4 +- arch/ext/I.yaml | 7 +- arch/ext/M.yaml | 2 +- arch/ext/S.yaml | 4 +- arch/ext/Smaia.yaml | 2 +- arch/ext/Smcdeleg.yaml | 28 +- arch/ext/Smcntrpmf.yaml | 2 +- arch/ext/Ssaia.yaml | 2 +- arch/ext/Ssccfg.yaml | 2 +- arch/ext/Ssccptr.yaml | 2 +- arch/ext/Sscofpmf.yaml | 2 +- arch/ext/Sscounterenw.yaml | 2 +- arch/ext/Sstc.yaml | 2 +- arch/ext/Sstvala.yaml | 2 +- arch/ext/Sstvecd.yaml | 2 +- arch/ext/Sv32.yaml | 2 +- arch/ext/Sv39.yaml | 2 +- arch/ext/Sv48.yaml | 2 +- arch/ext/Sv57.yaml | 2 +- arch/ext/Svade.yaml | 2 +- arch/ext/Svadu.yaml | 2 +- arch/ext/Svbare.yaml | 2 +- arch/ext/Svinval.yaml | 2 +- arch/ext/Svpbmt.yaml | 2 +- arch/ext/U.yaml | 2 +- arch/ext/Za128rs.yaml | 2 +- arch/ext/Zaamo.yaml | 2 +- arch/ext/Zalrsc.yaml | 2 +- arch/ext/Zba.yaml | 2 +- arch/ext/Zbb.yaml | 2 +- arch/ext/Zbc.yaml | 2 +- arch/ext/Zbs.yaml | 2 +- arch/ext/Zfhmin.yaml | 2 +- arch/ext/Zic64b.yaml | 2 +- arch/ext/Zicbom.yaml | 2 +- arch/ext/Ziccamoa.yaml | 2 +- arch/ext/Ziccif.yaml | 2 +- arch/ext/Zicclsm.yaml | 2 +- arch/ext/Ziccrse.yaml | 2 +- arch/ext/Zicfilp.yaml | 31 ++ arch/ext/Zicfiss.yaml | 33 ++ arch/ext/Zicntr.yaml | 2 +- arch/ext/Zicsr.yaml | 2 +- arch/ext/Zifencei.yaml | 2 +- arch/ext/Zihintpause.yaml | 2 +- arch/ext/Zihpm.yaml | 2 +- arch/ext/Zkt.yaml | 2 +- arch/ext/Zmmul.yaml | 2 +- arch/inst/A/amoadd.d.yaml | 2 +- arch/inst/A/lr.d.yaml | 2 +- arch/inst/A/lr.w.yaml | 2 +- arch/inst/A/sc.d.yaml | 2 +- arch/inst/A/sc.w.yaml | 2 +- arch/isa/globals.isa | 41 +- arch/isa/util.idl | 12 +- arch/manual/isa/20240411/contents.yaml | 179 ++++++++ arch/manual/isa/isa.yaml | 8 + backends/arch_gen/lib/arch_gen.rb | 2 +- backends/manual/tasks.rake | 390 ++++++++++++++++++ backends/manual/templates/func.adoc.erb | 26 ++ .../manual/templates/instruction.adoc.erb | 134 ++++++ backends/manual/templates/isa_nav.adoc.erb | 15 + .../templates/isa_version_index.adoc.erb | 10 + backends/manual/templates/playbook.yml.erb | 93 +++++ .../arch_overlay/ext/Xcustom.yaml | 2 +- cfgs/generic_rv64/implemented_exts.yaml | 44 +- lib/arch_def.rb | 3 +- lib/arch_obj_models/instruction.rb | 8 + lib/arch_obj_models/manual.rb | 174 ++++++++ lib/idl/passes/prune.rb | 4 +- lib/validate.rb | 5 +- schemas/ext_schema.json | 24 +- schemas/manual_version_schema.json | 98 +++++ schemas/schema_defs.json | 61 ++- 81 files changed, 1434 insertions(+), 136 deletions(-) create mode 100644 arch/ext/Zicfilp.yaml create mode 100644 arch/ext/Zicfiss.yaml create mode 100644 arch/manual/isa/20240411/contents.yaml create mode 100644 arch/manual/isa/isa.yaml create mode 100644 backends/manual/tasks.rake create mode 100644 backends/manual/templates/func.adoc.erb create mode 100644 backends/manual/templates/instruction.adoc.erb create mode 100644 backends/manual/templates/isa_nav.adoc.erb create mode 100644 backends/manual/templates/isa_version_index.adoc.erb create mode 100644 backends/manual/templates/playbook.yml.erb create mode 100644 lib/arch_obj_models/manual.rb create mode 100644 schemas/manual_version_schema.json diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 000b5c14c..48ac87589 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -45,10 +45,16 @@ jobs: run: ./do gen:html[generic_rv64] - name: Generate YARD docs run: ./do gen:tool_doc - - name: Create _site - run: mkdir -p _site + - name: Build manual + run: ./do gen:html_manual MANUAL_NAME=isa VERSIONS=all + - name: Create _site/example_cfg + run: mkdir -p _site/example_cfg + - name: Create _site/manual + run: mkdir -p _site/manual - name: Copy cfg html - run: cp -R gen/cfg_html_doc/generic_rv64/html _site + run: cp -R gen/cfg_html_doc/generic_rv64/html _site/example_cfg + - name: Copy manual html + run: cp -R gen/manual/top/all/html _site/manual - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact diff --git a/README.adoc b/README.adoc index d94cf0ee3..70151f556 100644 --- a/README.adoc +++ b/README.adoc @@ -15,7 +15,7 @@ This repository contains: === Working examples: - * Generate https://riscv-software-src.github.io/riscv-unified-db/html/index.html[configuration-specific documentation] taylored to the set of implemented extensions and unnamed implementation options (_e.g._, `./do gen:html[generic_rv64]`). + * Generate https://riscv-software-src.github.io/riscv-unified-db/manual/index.html[configuration-specific documentation] taylored to the set of implemented extensions and unnamed implementation options (_e.g._, `./do gen:html[generic_rv64]`). ** Only implemented extensions/instructions/CSRs are included ** Unreachable/unimplmented parts of the formal specification are pruned away ** A dedicated documentation page for every implemented instruction, including its encoding, pruned execution behavior, and what types of exceptions it may cause. diff --git a/arch/ext/A.yaml b/arch/ext/A.yaml index bba2c7f87..1ec21fd28 100644 --- a/arch/ext/A.yaml +++ b/arch/ext/A.yaml @@ -7,7 +7,7 @@ A: name: RISC-V International url: https://riscv.org versions: - - version: 2.1 + - version: "2.1.0" state: ratified ratification_date: 2019-12 contributors: @@ -15,8 +15,8 @@ A: email: unknown@void.segfault company: Unknown implies: - - [Zaamo, 1.0] - - [Zalrsc, 1.0] + - [Zaamo, "1.0.0"] + - [Zalrsc, "1.0.0"] description: | The atomic-instruction extension, named `A`, contains diff --git a/arch/ext/B.yaml b/arch/ext/B.yaml index cfa39eefe..50cb8aeeb 100644 --- a/arch/ext/B.yaml +++ b/arch/ext/B.yaml @@ -10,7 +10,7 @@ B: name: Creative Commons Attribution 4.0 International License url: https://creativecommons.org/licenses/by/4.0/ versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2024-04 contributors: @@ -19,9 +19,9 @@ B: company: Rivos, Inc. url: https://drive.google.com/file/d/1SgLoasaBjs5WboQMaU3wpHkjUwV71UZn/view implies: - - [Zba, 1.0] - - [Zbb, 1.0] - - [Zbs, 1.0] + - [Zba, "1.0.0"] + - [Zbb, "1.0.0"] + - [Zbs, "1.0.0"] description: | The B standard extension comprises instructions provided by the `Zba`, `Zbb`, and `Zbs` extensions. diff --git a/arch/ext/C.yaml b/arch/ext/C.yaml index 251ef621d..8b74dda4d 100644 --- a/arch/ext/C.yaml +++ b/arch/ext/C.yaml @@ -4,7 +4,7 @@ C: type: unprivileged long_name: Compressed instructions versions: - - version: 2.2 + - version: "2.2.0" state: ratified ratification_date: 2019-12 description: | diff --git a/arch/ext/D.yaml b/arch/ext/D.yaml index 7d7f14eae..d9d9021de 100644 --- a/arch/ext/D.yaml +++ b/arch/ext/D.yaml @@ -4,12 +4,12 @@ D: type: unprivileged long_name: Double-precision floating-point versions: - - version: 2.2 + - version: "2.2.0" state: ratified ratification_date: 2019-12 changes: - Define NaN-boxing scheme, changed definition of FMAX and FMIN - implies: [F, 2.2] + implies: [F, "2.2.0"] description: | The `D` extension adds double-precision floating-point computational instructions compliant diff --git a/arch/ext/F.yaml b/arch/ext/F.yaml index b1cb1bfe5..f88bed272 100644 --- a/arch/ext/F.yaml +++ b/arch/ext/F.yaml @@ -4,7 +4,7 @@ F: type: unprivileged long_name: Single-precision floating-point versions: - - version: 2.2 + - version: "2.2.0" state: ratified ratification_date: 2019-12 changes: diff --git a/arch/ext/H.yaml b/arch/ext/H.yaml index 100c94ac4..04124e04d 100644 --- a/arch/ext/H.yaml +++ b/arch/ext/H.yaml @@ -4,12 +4,12 @@ H: type: privileged long_name: Hypervisor versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2019-12 requires: oneOf: - - [S, '>= 1.12'] + - [S, '>= 1.12.0'] interrupt_codes: - num: 2 name: Virtual supervisor software interrupt diff --git a/arch/ext/I.yaml b/arch/ext/I.yaml index 83d1ba6c1..dd2c0ed9a 100644 --- a/arch/ext/I.yaml +++ b/arch/ext/I.yaml @@ -4,7 +4,7 @@ I: type: unprivileged long_name: Base integer ISA versions: - - version: 2.1 + - version: "2.1.0" state: ratified ratification_date: 2019-06 changes: @@ -73,6 +73,11 @@ I: - num: 15 name: Store/AMO page fault var: StoreAmoPageFault + - num: 18 + name: Software Check + var: SoftwareCheck + when: + version: ">= 2.1.0" params: XLEN: description: | diff --git a/arch/ext/M.yaml b/arch/ext/M.yaml index 27bc6b496..3578c6d53 100644 --- a/arch/ext/M.yaml +++ b/arch/ext/M.yaml @@ -4,7 +4,7 @@ M: type: unprivileged long_name: Integer multiply and divide instructions versions: - - version: 2.0 + - version: "2.0.0" state: ratified ratification_date: 2019-12 description: | diff --git a/arch/ext/S.yaml b/arch/ext/S.yaml index 3f9d055ec..4f02efdb6 100644 --- a/arch/ext/S.yaml +++ b/arch/ext/S.yaml @@ -4,10 +4,10 @@ S: type: privileged long_name: Supervisor mode versions: - - version: 1.12 + - version: "1.12.0" state: ratified ratification_date: 2019-12 - requires: [U, "= 1.12"] + requires: [U, "= 1.12.0"] description: | This chapter describes the RISC-V supervisor-level architecture, which contains a common core that is used with various supervisor-level diff --git a/arch/ext/Smaia.yaml b/arch/ext/Smaia.yaml index 7d1271c8a..2e1dfff67 100644 --- a/arch/ext/Smaia.yaml +++ b/arch/ext/Smaia.yaml @@ -5,7 +5,7 @@ Smaia: description: Advanced Interrupt Architecture, M-mode extension type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-06 url: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf diff --git a/arch/ext/Smcdeleg.yaml b/arch/ext/Smcdeleg.yaml index 97fc8258b..fa1b43f32 100644 --- a/arch/ext/Smcdeleg.yaml +++ b/arch/ext/Smcdeleg.yaml @@ -4,8 +4,32 @@ Smcdeleg: long_name: Performance counter delegation description: Performance counter delegation type: privileged + rvi_jira_issue: RVS-1005 + company: + name: RISC-V International + url: https://riscv.org + doc_license: + name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) + url: https://creativecommons.org/licenses/by/4.0/ versions: - - version: 0 + - version: "1.0.0" state: ratified ratification_date: null - url: https://docs.google.com/document/d/1s-GeH5XpHBLzbQZucA8DPA7vvF7Xvf_nrPbrU2YLBcE/edit#heading=h.yyrgtolcaczx + repositories: + - url: https://github.com/riscvarchive/riscv-smcdeleg-ssccfg + url: https://github.com/riscvarchive/riscv-smcdeleg-ssccfg/releases/download/v1.0.0/riscv-smcdeleg-ssccfg-v1.0.0.pdf + contributors: + - name: Beeman Strong + email: beeman@rivosinc.com + company: Rivos, Inc. + - name: Atish Patra + email: atishp@rivosinc.com + company: Rivos, Inc. + - name: Allen Baum + email: allen.baum@esperantotech.com + company: Rivos, Inc. + - name: Greg Favor + email: gfavor@ventanamicro.com + company: Ventana Microsystems + - name: John Hauser + email: jh.riscv@jhauser.us \ No newline at end of file diff --git a/arch/ext/Smcntrpmf.yaml b/arch/ext/Smcntrpmf.yaml index 3942f71ec..d4ffe6012 100644 --- a/arch/ext/Smcntrpmf.yaml +++ b/arch/ext/Smcntrpmf.yaml @@ -5,7 +5,7 @@ Smcntrpmf: description: Cycle and Instret Privilege Mode Filtering type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-08 url: https://github.com/riscv/riscv-smcntrpmf/releases/download/v1.0_rc4-frozen/riscv-smcntrpmf-v1.0_rc4.pdf diff --git a/arch/ext/Ssaia.yaml b/arch/ext/Ssaia.yaml index b48ca8f27..86b004f2f 100644 --- a/arch/ext/Ssaia.yaml +++ b/arch/ext/Ssaia.yaml @@ -5,7 +5,7 @@ Ssaia: description: Advanced Interrupt Architecture, S-mode extension type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-06 url: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf diff --git a/arch/ext/Ssccfg.yaml b/arch/ext/Ssccfg.yaml index ac296f723..8cbdc018c 100644 --- a/arch/ext/Ssccfg.yaml +++ b/arch/ext/Ssccfg.yaml @@ -5,7 +5,7 @@ Ssccfg: description: Supervisor-mode counter configuration type: privileged versions: - - version: 0 + - version: "1.0.0" state: ratified ratification_date: null url: https://docs.google.com/document/d/1s-GeH5XpHBLzbQZucA8DPA7vvF7Xvf_nrPbrU2YLBcE/edit#heading=h.yyrgtolcaczx diff --git a/arch/ext/Ssccptr.yaml b/arch/ext/Ssccptr.yaml index dcd4265b5..4ea276fcd 100644 --- a/arch/ext/Ssccptr.yaml +++ b/arch/ext/Ssccptr.yaml @@ -9,7 +9,7 @@ Ssccptr: This extension was ratified with the RVA20 profiles. type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: null url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 diff --git a/arch/ext/Sscofpmf.yaml b/arch/ext/Sscofpmf.yaml index df8184c06..c93882617 100644 --- a/arch/ext/Sscofpmf.yaml +++ b/arch/ext/Sscofpmf.yaml @@ -5,7 +5,7 @@ Sscofpmf: description: Counter Overflow and Privilege Mode Filtering type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-08 url: https://drive.google.com/file/d/1KcjgbLM5L1ZKY8934aJl8aQwGlMz6Cbo/view?usp=drive_link diff --git a/arch/ext/Sscounterenw.yaml b/arch/ext/Sscounterenw.yaml index f265d05a9..93a86ba70 100644 --- a/arch/ext/Sscounterenw.yaml +++ b/arch/ext/Sscounterenw.yaml @@ -9,7 +9,7 @@ Sscounterenw: This extension was ratified with the RVA22 profiles. type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-08 url: https://drive.google.com/file/d/1KcjgbLM5L1ZKY8934aJl8aQwGlMz6Cbo/view?usp=drive_link diff --git a/arch/ext/Sstc.yaml b/arch/ext/Sstc.yaml index f4baedf35..4604c75f0 100644 --- a/arch/ext/Sstc.yaml +++ b/arch/ext/Sstc.yaml @@ -5,7 +5,7 @@ Sstc: description: Superivisor mode timer interrupts type: privileged versions: - - version: 0.9 + - version: "0.9.0" state: ratified ratification_date: null url: https://drive.google.com/file/d/1m84Re2yK8m_vbW7TspvevCDR82MOBaSX/view?usp=drive_link diff --git a/arch/ext/Sstvala.yaml b/arch/ext/Sstvala.yaml index c8a418118..6b46e85cf 100644 --- a/arch/ext/Sstvala.yaml +++ b/arch/ext/Sstvala.yaml @@ -15,7 +15,7 @@ Sstvala: This extension was ratified with the RVA20 profiles. type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: null url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 diff --git a/arch/ext/Sstvecd.yaml b/arch/ext/Sstvecd.yaml index 4cdc52f2d..a75432e1f 100644 --- a/arch/ext/Sstvecd.yaml +++ b/arch/ext/Sstvecd.yaml @@ -8,7 +8,7 @@ Sstvecd: four-byte-aligned address. type: privileged versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 diff --git a/arch/ext/Sv32.yaml b/arch/ext/Sv32.yaml index b71862894..b8599866a 100644 --- a/arch/ext/Sv32.yaml +++ b/arch/ext/Sv32.yaml @@ -5,7 +5,7 @@ Sv32: description: 32-bit virtual address translation (3 level) type: privileged versions: - - version: 1.12 + - version: "1.12.0" state: ratified ratification_date: unknown url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf diff --git a/arch/ext/Sv39.yaml b/arch/ext/Sv39.yaml index 36a614d56..1782c28eb 100644 --- a/arch/ext/Sv39.yaml +++ b/arch/ext/Sv39.yaml @@ -5,7 +5,7 @@ Sv39: description: 39-bit virtual address translation (3 level) type: privileged versions: - - version: 1.12 + - version: "1.12.0" state: ratified ratification_date: unknown url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf diff --git a/arch/ext/Sv48.yaml b/arch/ext/Sv48.yaml index a9ad01860..2a735f6ee 100644 --- a/arch/ext/Sv48.yaml +++ b/arch/ext/Sv48.yaml @@ -5,7 +5,7 @@ Sv48: description: 48-bit virtual address translation (4 level) type: privileged versions: - - version: 1.12 + - version: "1.12.0" state: ratified ratification_date: unknown url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf diff --git a/arch/ext/Sv57.yaml b/arch/ext/Sv57.yaml index d111d21f2..45dac066a 100644 --- a/arch/ext/Sv57.yaml +++ b/arch/ext/Sv57.yaml @@ -5,7 +5,7 @@ Sv57: description: 57-bit virtual address translation (5 level) type: privileged versions: - - version: 1.12 + - version: "1.12.0" state: ratified ratification_date: unknown url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf diff --git a/arch/ext/Svade.yaml b/arch/ext/Svade.yaml index 955854e0b..896a393cd 100644 --- a/arch/ext/Svade.yaml +++ b/arch/ext/Svade.yaml @@ -8,7 +8,7 @@ Svade: during a page walk. Rather, encountering a PTE with the A bit clear or the D bit clear when an operation is a write will cause a Page Fault. versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-11 url: https://github.com/riscvarchive/riscv-svadu/releases/download/v1.0/riscv-svadu.pdf diff --git a/arch/ext/Svadu.yaml b/arch/ext/Svadu.yaml index f5ab44cd4..0eed00c1f 100644 --- a/arch/ext/Svadu.yaml +++ b/arch/ext/Svadu.yaml @@ -91,7 +91,7 @@ Svadu: is zero, the implementation behaves as though Svadu were not implemented for VS-stage address translation. versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2023-11 url: https://github.com/riscvarchive/riscv-svadu/releases/download/v1.0/riscv-svadu.pdf diff --git a/arch/ext/Svbare.yaml b/arch/ext/Svbare.yaml index d7005885b..1ce53d662 100644 --- a/arch/ext/Svbare.yaml +++ b/arch/ext/Svbare.yaml @@ -9,7 +9,7 @@ Svbare: [NOTE] This extension was ratified as part of the RVA22 profile. versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null requires: S diff --git a/arch/ext/Svinval.yaml b/arch/ext/Svinval.yaml index 38207d2e8..463047136 100644 --- a/arch/ext/Svinval.yaml +++ b/arch/ext/Svinval.yaml @@ -71,7 +71,7 @@ Svinval: `sfence.w.inval` and `sfence.inval.ir` instructions as no-ops. -- versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: 2021-11 requires: S diff --git a/arch/ext/Svpbmt.yaml b/arch/ext/Svpbmt.yaml index fc925bd1f..b10bc90e3 100644 --- a/arch/ext/Svpbmt.yaml +++ b/arch/ext/Svpbmt.yaml @@ -10,7 +10,7 @@ Svpbmt: This extension was ratified as part of the RVA22 profile. type: privileged versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null requires: Sv39 diff --git a/arch/ext/U.yaml b/arch/ext/U.yaml index 1808b6cc8..2847654db 100644 --- a/arch/ext/U.yaml +++ b/arch/ext/U.yaml @@ -5,7 +5,7 @@ U: description: User-level privilege mode type: privileged versions: - - version: 1.12 + - version: "1.12.0" state: ratified ratification_date: 2019-12 params: diff --git a/arch/ext/Za128rs.yaml b/arch/ext/Za128rs.yaml index 6712bbe8c..4b802cc2d 100644 --- a/arch/ext/Za128rs.yaml +++ b/arch/ext/Za128rs.yaml @@ -13,7 +13,7 @@ Za128rs: The minimum reservation set size is effectively determined by the size of atomic accesses in the A extension. versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null param_constraints: diff --git a/arch/ext/Zaamo.yaml b/arch/ext/Zaamo.yaml index df996e1ed..c5b07d9ab 100644 --- a/arch/ext/Zaamo.yaml +++ b/arch/ext/Zaamo.yaml @@ -4,7 +4,7 @@ Zaamo: long_name: Load-acquire/Store-release atomic instructions type: unprivileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2024-04 description: | diff --git a/arch/ext/Zalrsc.yaml b/arch/ext/Zalrsc.yaml index 656f82562..3f6a07fbc 100644 --- a/arch/ext/Zalrsc.yaml +++ b/arch/ext/Zalrsc.yaml @@ -4,7 +4,7 @@ Zalrsc: long_name: Atomic read-modify-write instructions type: unprivileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2024-04 description: | diff --git a/arch/ext/Zba.yaml b/arch/ext/Zba.yaml index 041c238b6..a508fc365 100644 --- a/arch/ext/Zba.yaml +++ b/arch/ext/Zba.yaml @@ -21,7 +21,7 @@ Zba: name: RISC-V International url: https://riscv.org versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2021-06 repositories: diff --git a/arch/ext/Zbb.yaml b/arch/ext/Zbb.yaml index 40e37d763..15d6b7be4 100644 --- a/arch/ext/Zbb.yaml +++ b/arch/ext/Zbb.yaml @@ -9,7 +9,7 @@ Zbb: name: RISC-V International url: https://riscv.org versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2021-06 repositories: diff --git a/arch/ext/Zbc.yaml b/arch/ext/Zbc.yaml index 6d0e0d8d1..dc8efb85c 100644 --- a/arch/ext/Zbc.yaml +++ b/arch/ext/Zbc.yaml @@ -9,7 +9,7 @@ Zbc: name: RISC-V International url: https://riscv.org versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2021-06 repositories: diff --git a/arch/ext/Zbs.yaml b/arch/ext/Zbs.yaml index db71ff349..48a39c1ee 100644 --- a/arch/ext/Zbs.yaml +++ b/arch/ext/Zbs.yaml @@ -13,7 +13,7 @@ Zbs: name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) url: https://creativecommons.org/licenses/by/4.0/ versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2021-06 url: https://drive.google.com/drive/u/0/folders/1_wqb-rXOVkGa6rqmugN3kwCftWDf1daU diff --git a/arch/ext/Zfhmin.yaml b/arch/ext/Zfhmin.yaml index fbd73f9f5..66e62775e 100644 --- a/arch/ext/Zfhmin.yaml +++ b/arch/ext/Zfhmin.yaml @@ -42,7 +42,7 @@ Zfhmin: ==== type: unprivileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2021-11 requires: [F, ">= 2.2"] diff --git a/arch/ext/Zic64b.yaml b/arch/ext/Zic64b.yaml index e00c8c184..427576097 100644 --- a/arch/ext/Zic64b.yaml +++ b/arch/ext/Zic64b.yaml @@ -9,7 +9,7 @@ Zic64b: This extension was ratified with the RVA20 profiles. type: privileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: null url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 diff --git a/arch/ext/Zicbom.yaml b/arch/ext/Zicbom.yaml index 09481acad..d0fa15e66 100644 --- a/arch/ext/Zicbom.yaml +++ b/arch/ext/Zicbom.yaml @@ -5,7 +5,7 @@ Zicbom: description: Cache block management instructions type: unprivileged versions: - - version: 1.0.1-b34ea8a + - version: "1.0.1-b34ea8a" state: ratified ratification_date: 2022-05 params: diff --git a/arch/ext/Ziccamoa.yaml b/arch/ext/Ziccamoa.yaml index 9c49e1721..0a5a334ff 100644 --- a/arch/ext/Ziccamoa.yaml +++ b/arch/ext/Ziccamoa.yaml @@ -9,6 +9,6 @@ Ziccamoa: [NOTE] This extension was ratified as part of the RVA20 profile. versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null diff --git a/arch/ext/Ziccif.yaml b/arch/ext/Ziccif.yaml index 70d7559bb..19695af57 100644 --- a/arch/ext/Ziccif.yaml +++ b/arch/ext/Ziccif.yaml @@ -11,6 +11,6 @@ Ziccif: [NOTE] This extension was ratified as part of the RVA20 profile. versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null diff --git a/arch/ext/Zicclsm.yaml b/arch/ext/Zicclsm.yaml index 95b2f37fa..f8aed3820 100644 --- a/arch/ext/Zicclsm.yaml +++ b/arch/ext/Zicclsm.yaml @@ -17,7 +17,7 @@ Zicclsm: Standard software distributions should assume their existence only for correctness, not for performance. versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null param_constraints: diff --git a/arch/ext/Ziccrse.yaml b/arch/ext/Ziccrse.yaml index 37571faaa..ba787a743 100644 --- a/arch/ext/Ziccrse.yaml +++ b/arch/ext/Ziccrse.yaml @@ -9,6 +9,6 @@ Ziccrse: [NOTE] This extension was ratified as part of the RVA20 profile. versions: - - version: "1.0" + - version: "1.0.0" state: ratified ratification_date: null diff --git a/arch/ext/Zicfilp.yaml b/arch/ext/Zicfilp.yaml new file mode 100644 index 000000000..8afd832d0 --- /dev/null +++ b/arch/ext/Zicfilp.yaml @@ -0,0 +1,31 @@ +Zicfilp: + long_name: Landing Pads + description: | + TODO + type: unprivileged + versions: + - version: "1.0.0" + state: ratified + ratification_date: 2024-07 + params: + REPORT_CAUSE_IN_MTVAL_ON_LANDING_PAD_SOFTWARE_CHECK: + description: | + When true, `mtval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into M-mode due to a landing pad error. + + When false, `mtval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_STVAL_ON_LANDING_PAD_SOFTWARE_CHECK: + description: | + When true, `stval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into S-mode due to a landing pad error. + + When false, `stval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_VSTVAL_ON_LANDING_PAD_SOFTWARE_CHECK: + description: | + When true, `vstval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into VS-mode due to a landing pad error. + + When false, `vstval` is written with 0. + schema: + type: boolean diff --git a/arch/ext/Zicfiss.yaml b/arch/ext/Zicfiss.yaml new file mode 100644 index 000000000..b9104cfcd --- /dev/null +++ b/arch/ext/Zicfiss.yaml @@ -0,0 +1,33 @@ +# yaml-language-server: $schema=../../schemas/ext_schema.json + +Zicfiss: + long_name: Shadow Stack + description: | + TODO + type: unprivileged + versions: + - version: "1.0.0" + state: ratified + ratification_date: 2024-07 + params: + REPORT_CAUSE_IN_MTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: + description: | + When true, `mtval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into M-mode due to a shadow stack pop check instruction. + + When false, `mtval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_STVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: + description: | + When true, `stval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into S-mode due to a shadow stack pop check instruction. + + When false, `stval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_VSTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: + description: | + When true, `vstval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into VS-mode due to a shadow stack pop check instruction. + + When false, `vstval` is written with 0. + schema: + type: boolean diff --git a/arch/ext/Zicntr.yaml b/arch/ext/Zicntr.yaml index 7cfdd6067..213b877bc 100644 --- a/arch/ext/Zicntr.yaml +++ b/arch/ext/Zicntr.yaml @@ -5,7 +5,7 @@ Zicntr: description: Architectural performance counters type: unprivileged versions: - - version: 2.0 + - version: "2.0.0" state: ratified ratification_date: 2019-12 requires: [Zicsr, ">= 2.0"] diff --git a/arch/ext/Zicsr.yaml b/arch/ext/Zicsr.yaml index 083b00102..b5f77717f 100644 --- a/arch/ext/Zicsr.yaml +++ b/arch/ext/Zicsr.yaml @@ -5,6 +5,6 @@ Zicsr: description: Control and status registers type: unprivileged versions: - - version: 2.0 + - version: "2.0.0" state: ratified ratification_date: null diff --git a/arch/ext/Zifencei.yaml b/arch/ext/Zifencei.yaml index b53198562..0c8616edf 100644 --- a/arch/ext/Zifencei.yaml +++ b/arch/ext/Zifencei.yaml @@ -65,6 +65,6 @@ Zifencei: ==== type: unprivileged versions: - - version: 2.0 + - version: "2.0.0" state: ratified ratification_date: null diff --git a/arch/ext/Zihintpause.yaml b/arch/ext/Zihintpause.yaml index 2445ac267..a4a8f10ef 100644 --- a/arch/ext/Zihintpause.yaml +++ b/arch/ext/Zihintpause.yaml @@ -66,6 +66,6 @@ Zihintpause: ==== type: unprivileged versions: - - version: 2.0 + - version: "2.0.0" state: ratified ratification_date: null diff --git a/arch/ext/Zihpm.yaml b/arch/ext/Zihpm.yaml index ccc96db32..37cf03406 100644 --- a/arch/ext/Zihpm.yaml +++ b/arch/ext/Zihpm.yaml @@ -5,7 +5,7 @@ Zihpm: description: Programmable hardware performance counters type: unprivileged versions: - - version: 2.0 + - version: "2.0.0" state: ratified ratification_date: unknown params: diff --git a/arch/ext/Zkt.yaml b/arch/ext/Zkt.yaml index 138de6576..5202b1e19 100644 --- a/arch/ext/Zkt.yaml +++ b/arch/ext/Zkt.yaml @@ -333,7 +333,7 @@ Zkt: type: unprivileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2021-11 contributors: diff --git a/arch/ext/Zmmul.yaml b/arch/ext/Zmmul.yaml index d6a92641b..624d10e50 100644 --- a/arch/ext/Zmmul.yaml +++ b/arch/ext/Zmmul.yaml @@ -18,6 +18,6 @@ Zmmul: implemented in soft logic. type: unprivileged versions: - - version: 1.0 + - version: "1.0.0" state: ratified ratification_date: 2022-06 diff --git a/arch/inst/A/amoadd.d.yaml b/arch/inst/A/amoadd.d.yaml index 756b48cd5..e0474cba3 100644 --- a/arch/inst/A/amoadd.d.yaml +++ b/arch/inst/A/amoadd.d.yaml @@ -11,7 +11,7 @@ amoadd.d: * Write the sum to the address in _rs1_ definedBy: [A, Zaamo] base: 64 - assembly: xd, xs2, (xrs1) + assembly: xd, xs2, (xs1) encoding: match: 00000------------011-----0101111 variables: diff --git a/arch/inst/A/lr.d.yaml b/arch/inst/A/lr.d.yaml index 2b33e72a5..d80e1694c 100644 --- a/arch/inst/A/lr.d.yaml +++ b/arch/inst/A/lr.d.yaml @@ -68,7 +68,7 @@ lr.d: XReg virtual_address = X[rs1]; - if (!is_naturally_aligned(virtual_address)) { + if (!is_naturally_aligned<64>(virtual_address)) { # can raise either LoadAddressMisaligned *or* LoadAccessFault # # from the spec: diff --git a/arch/inst/A/lr.w.yaml b/arch/inst/A/lr.w.yaml index 1b6b2892f..63b44c87a 100644 --- a/arch/inst/A/lr.w.yaml +++ b/arch/inst/A/lr.w.yaml @@ -72,7 +72,7 @@ lr.w: XReg virtual_address = X[rs1]; - if (!is_naturally_aligned(virtual_address)) { + if (!is_naturally_aligned<32>(virtual_address)) { # can raise either LoadAddressMisaligned *or* LoadAccessFault # # from the spec: diff --git a/arch/inst/A/sc.d.yaml b/arch/inst/A/sc.d.yaml index dc940ae96..ab9c6724d 100644 --- a/arch/inst/A/sc.d.yaml +++ b/arch/inst/A/sc.d.yaml @@ -126,7 +126,7 @@ sc.d: XReg virtual_address = X[rs1]; XReg value = X[rs2]; - if (!is_naturally_aligned(virtual_address)) { + if (!is_naturally_aligned<64>(virtual_address)) { # can raise either LoadAddressMisaligned *or* LoadAccessFault # # from the spec: diff --git a/arch/inst/A/sc.w.yaml b/arch/inst/A/sc.w.yaml index b78a4c4be..5e8851e26 100644 --- a/arch/inst/A/sc.w.yaml +++ b/arch/inst/A/sc.w.yaml @@ -132,7 +132,7 @@ sc.w: XReg virtual_address = X[rs1]; XReg value = X[rs2]; - if (!is_naturally_aligned(virtual_address)) { + if (!is_naturally_aligned<32>(virtual_address)) { # can raise either LoadAddressMisaligned *or* LoadAccessFault # # from the spec: diff --git a/arch/isa/globals.isa b/arch/isa/globals.isa index 8ad64a224..7a6fbd900 100644 --- a/arch/isa/globals.isa +++ b/arch/isa/globals.isa @@ -319,7 +319,8 @@ function mtval_readonly? { (implemented?(ExtensionName::Zaamo) && REPORT_VA_IN_MTVAL_ON_AMO_PAGE_FAULT) || REPORT_VA_IN_MTVAL_ON_INSTRUCTION_PAGE_FAULT || REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION || - # REPORT_CAUSE_IN_MTVAL_ON_SOFTWARE_CHECK || + REPORT_CAUSE_IN_MTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK || + REPORT_CAUSE_IN_MTVAL_ON_LANDING_PAD_SOFTWARE_CHECK || implemented?(ExtensionName::Sdext) ); } @@ -344,7 +345,8 @@ function stval_readonly? { REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT || REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT || REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION || - REPORT_CAUSE_IN_STVAL_ON_SOFTWARE_CHECK || + REPORT_CAUSE_IN_STVAL_ON_SHADOW_STACK_SOFTWARE_CHECK || + REPORT_CAUSE_IN_STVAL_ON_LANDING_PAD_SOFTWARE_CHECK || implemented?(ExtensionName::Sdext) ); } else { @@ -372,7 +374,8 @@ function vstval_readonly? { REPORT_VA_IN_VSTVAL_ON_STORE_AMO_PAGE_FAULT || REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_PAGE_FAULT || REPORT_ENCODING_IN_VSTVAL_ON_ILLEGAL_INSTRUCTION || - REPORT_CAUSE_IN_VSTVAL_ON_SOFTWARE_CHECK || + REPORT_CAUSE_IN_VSTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK || + REPORT_CAUSE_IN_VSTVAL_ON_LANDING_PAD_SOFTWARE_CHECK || implemented?(ExtensionName::Sdext) ); } else { @@ -411,8 +414,10 @@ function mtval_for { return REPORT_VA_IN_MTVAL_ON_INSTRUCTION_PAGE_FAULT ? tval : 0; } else if (exception_code == ExceptionCode::IllegalInstruction) { return REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION ? tval : 0; - # } else if (exception_code == ExceptionCode::SoftwareCheck) { - # return REPORT_CAUSE_IN_MTVAL_ON_SOFTWARE_CHECK ? tval : 0; + } else if (exception_code == ExceptionCode::SoftwareCheck) { + # software check options are more fine-grained (per-software-check type), so always use tval, + # which must be config-checked at the call site + return tval; } else { return 0; } @@ -449,8 +454,10 @@ function stval_for { return REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT ? tval : 0; } else if (exception_code == ExceptionCode::IllegalInstruction) { return REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION ? tval : 0; - # } else if (exception_code == ExceptionCode::SoftwareCheck) { - # return REPORT_CAUSE_IN_STVAL_ON_SOFTWARE_CHECK ? tval : 0; + } else if (exception_code == ExceptionCode::SoftwareCheck) { + # software checks have a fine-grained implementation option (per-software-check type), so always use tval, + # which must be config-checked at the call site + return tval; } else { return 0; } @@ -488,8 +495,10 @@ function vstval_for { return REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_PAGE_FAULT ? tval : 0; } else if (exception_code == ExceptionCode::IllegalInstruction) { return REPORT_ENCODING_IN_VSTVAL_ON_ILLEGAL_INSTRUCTION ? tval : 0; - # } else if (exception_code == ExceptionCode::SoftwareCheck) { - # return REPORT_CAUSE_IN_VSTVAL_ON_SOFTWARE_CHECK ? tval : 0; + } else if (exception_code == ExceptionCode::SoftwareCheck) { + # software checks have a fine-grained implementation option (per-software-check type), so always use tval, + # which must be config-checked at the call site + return tval; } else { return 0; } @@ -2301,16 +2310,16 @@ function misaligned_is_atomic? { return false if MAX_MISALIGNED_ATOMICITY_GRANULE_SIZE == 0; if (pma_applies?(PmaAttribute::MAG16, physical_address, N) && - in_naturally_aligned_region?(physical_address_address, N)) { + in_naturally_aligned_region?<128>(physical_address, N)) { return true; } else if (pma_applies?(PmaAttribute::MAG8, physical_address, N) && - in_naturally_aligned_region?(physical_address, N)) { + in_naturally_aligned_region?<4>(physical_address, N)) { return true; } else if (pma_applies?(PmaAttribute::MAG4, physical_address, N) && - in_naturally_aligned_region?(physical_address, N)) { + in_naturally_aligned_region?<32>(physical_address, N)) { return true; } else if (pma_applies?(PmaAttribute::MAG2, physical_address, N) && - in_naturally_aligned_region?(physical_address, N)) { + in_naturally_aligned_region?<16>(physical_address, N)) { return true; } else { # not saved by a Misaligned Atomicity Granule @@ -2355,7 +2364,7 @@ function read_memory { } body { - Boolean aligned = is_naturally_aligned(virtual_address); + Boolean aligned = is_naturally_aligned(virtual_address); XReg physical_address; if (aligned) { @@ -2601,7 +2610,7 @@ function amo { If +rl+ is 1, then the amo also acts as a memory model release. } body { - Boolean aligned = is_naturally_aligned(virtual_address); + Boolean aligned = is_naturally_aligned(virtual_address); if (!aligned && MISALIGNED_LDST_EXCEPTION_PRIORITY == "high") { raise(ExceptionCode::StoreAmoAddressMisaligned, effective_ldst_mode(), virtual_address); @@ -2678,7 +2687,7 @@ function write_memory { Write to virtual memory } body { - Boolean aligned = is_naturally_aligned(virtual_address); + Boolean aligned = is_naturally_aligned(virtual_address); XReg physical_address; if (aligned) { diff --git a/arch/isa/util.idl b/arch/isa/util.idl index 308a23305..99caf089e 100644 --- a/arch/isa/util.idl +++ b/arch/isa/util.idl @@ -117,17 +117,17 @@ function bit_length { } function is_naturally_aligned { - template U32 M, U32 N + template U32 N returns Boolean - arguments Bits value + arguments XReg value description { - Checks if M-bit value is naturally aligned to N bits. + Checks if value is naturally aligned to N bits. } body { return true if N == 8; # everything is byte aligned - Bits mask = (N/8) - 1; - return (value & ~mask) == value; + XReg Mask = (N/8) - 1; + return (value & ~Mask) == value; } } @@ -143,7 +143,7 @@ function in_naturally_aligned_region? { body { XReg Mask = (N/8) - 1; - return (address & ~mask) == ((address + length - 1) & ~mask); + return (address & ~Mask) == ((address + length - 1) & ~Mask); } } diff --git a/arch/manual/isa/20240411/contents.yaml b/arch/manual/isa/20240411/contents.yaml new file mode 100644 index 000000000..70940660f --- /dev/null +++ b/arch/manual/isa/20240411/contents.yaml @@ -0,0 +1,179 @@ +# yaml-language-server: $schema=../../../../schemas/manual_version_schema.json + +--- +manual: isa +version: "4.0.0-pre" +name: "20240411" +marketing_version: "20240411" +state: "development" +url: https://github.com/riscv/riscv-isa-manual/releases/tag/20240411 +uses_isa_manual: true +isa_manual_tree: "20240411" +volumes: +- title: "RISC-V Instruction Set Manual, Volume I: Unprivileged ISA" + description: "The RISC-V Instruction Set Manual, Volume I: Unprivileged ISA" + authors: + - name: Andrew Waterman + email: awaterman@sifive.com + organization: + name: SiFive, Inc. + url: https://www.sifive.com/ + chapters: + - riscv-isa-manual/src/colophon.adoc + - riscv-isa-manual/src/intro.adoc + - riscv-isa-manual/src/rv32.adoc + - riscv-isa-manual/src/rv32e.adoc + - riscv-isa-manual/src/rv64.adoc + - riscv-isa-manual/src/rv128.adoc + - riscv-isa-manual/src/zifencei.adoc + - riscv-isa-manual/src/zicsr.adoc + - riscv-isa-manual/src/counters.adoc + - riscv-isa-manual/src/zihintntl.adoc + - riscv-isa-manual/src/zihintpause.adoc + - riscv-isa-manual/src/zimop.adoc + - riscv-isa-manual/src/zicond.adoc + - riscv-isa-manual/src/m-st-ext.adoc + - riscv-isa-manual/src/a-st-ext.adoc + - riscv-isa-manual/src/zawrs.adoc + - riscv-isa-manual/src/zacas.adoc + - riscv-isa-manual/src/zabha.adoc + - riscv-isa-manual/src/rvwmo.adoc + - riscv-isa-manual/src/ztso-st-ext.adoc + - riscv-isa-manual/src/cmo.adoc + - riscv-isa-manual/src/f-st-ext.adoc + - riscv-isa-manual/src/d-st-ext.adoc + - riscv-isa-manual/src/q-st-ext.adoc + - riscv-isa-manual/src/zfh.adoc + - riscv-isa-manual/src/bfloat16.adoc + - riscv-isa-manual/src/zfa.adoc + - riscv-isa-manual/src/zfinx.adoc + - riscv-isa-manual/src/c-st-ext.adoc + - riscv-isa-manual/src/zc.adoc + - riscv-isa-manual/src/b-st-ext.adoc + - riscv-isa-manual/src/j-st-ext.adoc + - riscv-isa-manual/src/p-st-ext.adoc + - riscv-isa-manual/src/v-st-ext.adoc + - riscv-isa-manual/src/scalar-crypto.adoc + - riscv-isa-manual/src/vector-crypto.adoc + - riscv-isa-manual/src/unpriv-cfi.adoc + - riscv-isa-manual/src/rv-32-64g.adoc + - riscv-isa-manual/src/extending.adoc + - riscv-isa-manual/src/naming.adoc + - riscv-isa-manual/src/history.adoc + - riscv-isa-manual/src/mm-eplan.adoc + - riscv-isa-manual/src/mm-formal.adoc + #Appendices for Vector + - riscv-isa-manual/src/vector-examples.adoc + - riscv-isa-manual/src/calling-convention.adoc + #/End of Vector appendices + extensions: + - [I, "2.1.0"] + # - [E, "2.0"] + # - [RVI64, "2.1"] + # - [RVI128, "1.7"] + - [Zifencei, "2.0.0"] + - [Zicsr, "2.0.0"] + - [Zicntr, "2.0.0"] + - [Zihpm, "2.0.0"] + - [Zihintntl, "1.0.0"] + - [Zihintpause, "2.0.0"] + - [Zimop, "2.0.0"] + - [Zicond, "1.0.0"] + - [M, "2.0.0"] + - [A, "2.1.0"] + - [Zawrs, "1.0.1"] + - [Zacas, "1.0.0"] + - [Zabha, "1.0.0"] + # - [RVWMO, "2.0"] + - [Ztso, "1.0.0"] + - [Zicbom, "1.0.0"] + - [Zicboz, "1.0.0"] + - [Zicbop, "1.0.0"] + - [F, "2.2.0"] + - [D, "2.2.0"] + # - [Q, "2.2"] + - [Zfh, "1.0.0"] + - [Zfhmin, "1.0.0"] + - [Zfbfmin, "1.0.0"] + - [Zvfbfmin, "1.0.0"] + - [Zvfbfwma, "1.0.0"] + - [Zfa, "1.0.0"] + - [Zfinx, "1.0.0"] + - [Zdinx, "1.0.0"] + - [Zhinx, "1.0.0"] + - [C, "2.0.0"] + - [Zca, "1.0.0"] + - [Zcf, "1.0.0"] + - [Zcd, "1.0.0"] + - [Zcb, "1.0.0"] + - [Zcmp, "1.0.0"] + - [Zcmt, "1.0.0"] + - [B, "1.0.0"] + - [Zba, "1.0.0"] + - [Zbb, "1.0.0"] + - [Zbc, "1.0.0"] + - [Zbs, "1.0.0"] + - [Zbkb, "1.0.0"] + - [Zbkc, "1.0.0"] + - [Zbkx, "1.0.0"] + # - [J, "0.0"] + # - [P, "0.2"] + - [V, "1.0.0"] + - [Zvl32b, "1.0.0"] + - [Zvl64b, "1.0.0"] + - [Zvl128b, "1.0.0"] + - [Zvl256b, "1.0.0"] + - [Zvl512b, "1.0.0"] + - [Zvl1024b, "1.0.0"] + - [Zve32x, "1.0.0"] + - [Zve32f, "1.0.0"] + - [Zve64x, "1.0.0"] + - [Zve64f, "1.0.0"] + - [Zve64d, "1.0.0"] + - [Zvfhmin, "1.0.0"] + - [Zvfh, "1.0.0"] + - [Zvknha, "1.0.0"] + - [Zvknhb, "1.0.0"] + - [Zbkb, "1.0.0"] + - [Zbkc, "1.0.0"] + - [Zbkx, "1.0.0"] + - [Zknd, "1.0.0"] + - [Zkne, "1.0.0"] + - [Zknh, "1.0.0"] + - [Zksed, "1.0.0"] + - [Zksh, "1.0.0"] + - [Zkr, "1.0.0"] + - [Zkn, "1.0.0"] + - [Zks, "1.0.0"] + - [Zk, "1.0.0"] + - [Zkt, "1.0.0"] + - [Zvbb, "1.0.0"] + - [Zvbc, "1.0.0"] + - [Zvkb, "1.0.0"] + - [Zvkg, "1.0.0"] + - [Zvkned, "1.0.0"] + - [Zvknha, "1.0.0"] + - [Zvknhb, "1.0.0"] + - [Zvksed, "1.0.0"] + - [Zvksh, "1.0.0"] + - [Zvkn, "1.0.0"] + - [Zvknc, "1.0.0"] + - [Zvkng, "1.0.0"] + - [Zvks, "1.0.0"] + - [Zvksc, "1.0.0"] + - [Zvksg, "1.0.0"] + - [Zvkt, "1.0.0"] + - [Zicfilp, "1.0.0"] + - [Zicfiss, "1.0.0"] + # - [Zam, "0.1"] + changes: + - The inclusion of all ratified extensions through March 2024. + - The draft Zam extension has been removed, in favor of the definition of a misaligned atomicity granule PMA. + - The concept of vacant memory regions has been superseded by inaccessible memory or I/O regions. +- title: "RISC-V Instruction Set Manual, Volume II: Privileged ISA" + description: "The RISC-V Instruction Set Manual, Volume II: Privileged ISA" + authors: + - name: Andrew Waterman + email: awaterman@sifive.com + organization: SiFive, Inc. + url: https://www.sifive.com/ \ No newline at end of file diff --git a/arch/manual/isa/isa.yaml b/arch/manual/isa/isa.yaml new file mode 100644 index 000000000..ed762ec09 --- /dev/null +++ b/arch/manual/isa/isa.yaml @@ -0,0 +1,8 @@ +name: isa +marketing_name: RISC-V ISA Manual +url: https://github.com/riscv/riscv-isa-manual +license: + id: CC-BY-4.0 + name: Creative Commons Attribution 4.0 International Public License + url: https://creativecommons.org/licenses/by/4.0/legalcode +# versions are found in by search all subdirectories for "contents.yaml" \ No newline at end of file diff --git a/backends/arch_gen/lib/arch_gen.rb b/backends/arch_gen/lib/arch_gen.rb index 38b86d7f5..f1abfb3a0 100644 --- a/backends/arch_gen/lib/arch_gen.rb +++ b/backends/arch_gen/lib/arch_gen.rb @@ -884,7 +884,7 @@ def maybe_add_inst(inst_name, extra_env = {}) raise e end - inst_obj = Instruction.new(inst_data[inst_name]) + inst_obj = Instruction.new(inst_data[inst_name], nil) possible_xlens = [params["XLEN"]] if @cfg_impl_ext.any? { |e| e[0] == "S" } possible_xlens << 32 if [32, 3264].include?(params["SXLEN"]) diff --git a/backends/manual/tasks.rake b/backends/manual/tasks.rake new file mode 100644 index 000000000..c26dae796 --- /dev/null +++ b/backends/manual/tasks.rake @@ -0,0 +1,390 @@ +# frozen_string_literal: true + +require_relative "#{$lib}/arch_def" + +$root = Pathname.new(__FILE__).dirname.dirname.realpath if $root.nil? + +MANUAL_GEN_DIR = $root / "gen" / "manual" + +def versions_from_env(manual) + versions = ENV["VERSIONS"].split(",") + output_hash = nil + if versions.include?("all") + raise ArgumentError, "'all' was given as a version, so nothing else should be" unless versions.length == 1 + + versions = manual.versions + output_hash = "all" + else + versions = versions.map { |vname| manual.versions.find { |v| v.name = vname } } + if versions.any?(&:nil?) + idx = versions.index(&:nil?) + raise "No manual version '#{ENV['VERSIONS'].split(',')[idx]}' for '#{args[:manual_name]}'" + end + output_hash = versions.size == 1 ? versions[0] : versions.hash + end + + [versions, output_hash] +end + +directory MANUAL_GEN_DIR / "adoc" +directory MANUAL_GEN_DIR / "antora" +directory MANUAL_GEN_DIR / "html" + +["inst", "csr", "ext"].each do |type| + directory MANUAL_GEN_DIR / "antora" / "modules" / "#{type}s" / "pages" + + Dir.glob($root / "arch" / type / "**" / "*.yaml") do |fn| + file MANUAL_GEN_DIR / "adoc" / "#{File.basename(fn, '.yaml')}.adoc" => [ + "gen:arch", + (MANUAL_GEN_DIR / "adoc").to_s, + ($root / "backends" / "manual" / "templates" / "#{type}.adoc.erb").to_s, + __FILE__ + ] do |t| + name = File.basename(t.name, ".adoc") + + arch_def = arch_def_for("_") + erb = case type + when "inst" + inst = arch_def.instruction(name) + raise "Could not find inst '#{name}'" if inst.nil? + + ERB.new(File.read($root / "backends" / "manual" / "templates" / "inst.adoc.erb"), trim_mode: "-") + when "csr" + csr = arch_def.csr(name) + raise "Could not find inst '#{name}'" if csr.nil? + + ERB.new(File.read($root / "backends" / "manual" / "templates" / "csr.adoc.erb"), trim_mode: "-") + when "ext" + ext = arch_def.extension(name) + raise "Could not find ext '#{name}'" if ext.nil? + + ERB.new(File.read($root / "backends" / "manual" / "templates" / "ext.adoc.erb"), trim_mode: "-") + else + raise "Unhandled type '#{type}'" + end + + File.write(t.name, erb.result(binding)) + end + + file MANUAL_GEN_DIR / "antora" / "modules" / "#{type}s" / "pages" => [ + (MANUAL_GEN_DIR / "adoc" / "#{File.basename(fn, '.yaml')}.adoc").to_s, + (MANUAL_GEN_DIR / "antora" / "modules" / "#{type}s" / "pages").to_s + ] do |t| + FileUtils.cp t.prerequisites.first, t.name + end + end +end + +file MANUAL_GEN_DIR / "antora" / "antora.yml" => (MANUAL_GEN_DIR / "antora").to_s do |t| + File.write t.name, <<~ANTORA + name: riscv_manual + version: #{arch_def.manual_version?} + nav: + - modules/nav.adoc + title: RISC-V ISA Manual + ANTORA +end + +# Rule to create a chapter page in antora hierarchy +rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/chapters/pages/.*\.adoc} do |t| + parts = t.name.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_version = arch_def_for("_").manual(parts[0]).version(parts[1]) + chapter_name = File.basename(t.name, ".adoc") + + volume = manual_version.volumes.find { |v| !v.chapter(chapter_name).nil? } + raise "Can't find any volume with chapter '#{chapter_name}'" if volume.nil? + + chapter = volume.chapter(chapter_name) + + FileUtils.mkdir_p File.dirname(t.name) + FileUtils.ln_s chapter.path, t.name +end + +# Rule to create antora.yml for a manual version +rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/antora.yml} => proc { |tname| + parts = tname.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_name = parts[0] + version_name = parts[1] + + manual_yaml_path = $root / "arch" / "manual" / manual_name / "#{manual_name}.yaml" + contents_path = $root / "arch" / "manual" / manual_name / version_name / "contents.yaml" + + raise "Cannot find #{manual_yaml_path}" unless manual_yaml_path.exist? + raise "Cannot find #{contents_path}" unless contents_path.exist? + + [ + __FILE__, + manual_yaml_path.to_s, + contents_path.to_s + ] +} do |t| + parts = t.name.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_version = arch_def_for("_").manual(parts[0])&.version(parts[1]) + + raise "Can't find any manual version for '#{parts[0]}' '#{parts[1]}'" if manual_version.nil? + + File.write t.name, <<~ANTORA + name: #{manual_version.manual.name} + version: #{manual_version.name} + display_version: #{manual_version.marketing_version} + nav: + - nav.adoc + title: #{manual_version.manual.marketing_name} + ANTORA +end + +# Rule to create nav.adoc for a manual version +rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/nav.adoc} => proc { |tname| + parts = tname.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_name = parts[0] + version_name = parts[1] + + manual_yaml_path = $root / "arch" / "manual" / manual_name / "#{manual_name}.yaml" + contents_path = $root / "arch" / "manual" / manual_name / version_name / "contents.yaml" + nav_template_path = $root / "backends" / "manual" / "templates" / "#{manual_name}_nav.adoc.erb" + + raise "Cannot find #{manual_yaml_path}" unless manual_yaml_path.exist? + raise "Cannot find #{contents_path}" unless contents_path.exist? + + FileList[ + __FILE__, + manual_yaml_path.to_s, + contents_path.to_s, + nav_template_path.to_s + ] +} do |t| + parts = t.name.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_version = arch_def_for("_").manual(parts[0])&.version(parts[1]) + + raise "Can't find any manual version for '#{parts[0]}' '#{parts[1]}'" if manual_version.nil? + + nav_template_path = $root / "backends" / "manual" / "templates" / "#{parts[0]}_nav.adoc.erb" + unless nav_template_path.exist? + raise "There is no navigation file for manual '#{parts[0]}' at '#{nav_template_path}'" + end + + erb = ERB.new(nav_template_path.read, trim_mode: "-") + erb.filename = nav_template_path.to_s + puts erb.encoding + + FileUtils.mkdir_p File.dirname(t.name) + File.write t.name, erb.result(binding) +end + +# Rule to create start page for a manual version +rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/ROOT/pages/index.adoc} => proc { |tname| + parts = tname.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_name = parts[0] + version_name = parts[1] + + manual_yaml_path = $root / "arch" / "manual" / manual_name / "#{manual_name}.yaml" + contents_path = $root / "arch" / "manual" / manual_name / version_name / "contents.yaml" + version_index_template_path = $root / "backends" / "manual" / "templates" / "#{manual_name}_version_index.adoc.erb" + + raise "Cannot find #{manual_yaml_path}" unless manual_yaml_path.exist? + raise "Cannot find #{contents_path}" unless contents_path.exist? + raise "Cannot find #{version_index_template_path}" unless version_index_template_path.exist? + + FileList[ + __FILE__, + manual_yaml_path.to_s, + contents_path.to_s, + version_index_template_path.to_s + ] +} do |t| + parts = t.name.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_version = arch_def_for("_").manual(parts[0])&.version(parts[1]) + + raise "Can't find any manual version for '#{parts[0]}' '#{parts[1]}'" if manual_version.nil? + + version_index_template_path = $root / "backends" / "manual" / "templates" / "#{parts[0]}_version_index.adoc.erb" + unless version_index_template_path.exist? + raise "There is no navigation file for manual '#{parts[0]}' at '#{version_index_template_path}'" + end + + erb = ERB.new(version_index_template_path.read, trim_mode: "-") + erb.filename = version_index_template_path.to_s + puts erb.encoding + + FileUtils.mkdir_p File.dirname(t.name) + File.write t.name, erb.result(binding) +end + +# rule to create instruction appendix page +rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/insts/pages/.*.adoc} => [ + __FILE__, + "gen:arch", + ($root / "backends" / "manual" / "templates" / "instruction.adoc.erb").to_s +] do |t| + inst_name = File.basename(t.name, ".adoc") + + arch_def = arch_def_for("_") + inst = arch_def.instruction(inst_name) + raise "Can't find instruction '#{inst_name}'" if inst.nil? + + inst_template_path = $root / "backends" / "manual" / "templates" / "instruction.adoc.erb" + erb = ERB.new(inst_template_path.read, trim_mode: "-") + erb.filename = inst_template_path.to_s + + FileUtils.mkdir_p File.dirname(t.name) + File.write t.name, AntoraUtils.resolve_links(erb.result(binding)) +end + +# rule to create IDL function appendix page +rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/funcs/pages/funcs.adoc} => [ + __FILE__, + "gen:arch", + ($root / "backends" / "manual" / "templates" / "func.adoc.erb").to_s +] do |t| + arch_def = arch_def_for("_") + + funcs_template_path = $root / "backends" / "manual" / "templates" / "func.adoc.erb" + erb = ERB.new(funcs_template_path.read, trim_mode: "-") + erb.filename = funcs_template_path.to_s + + FileUtils.mkdir_p File.dirname(t.name) + File.write t.name, AntoraUtils.resolve_links(erb.result(binding)) +end + +rule %r{#{MANUAL_GEN_DIR}/.*/top/.*/antora/playbook.yml} => proc { |tname| + parts = tname.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_name = parts[0] + FileList[ + __FILE__, + ($root / "arch" / "manual" / manual_name / "#{manual_name}.yaml").to_s, + ($root / "backends" / "manual" / "templates" / "playbook.yml.erb").to_s, + ($root / "arch" / "manual" / manual_name / "**" / "contents.yaml").to_s + ] +} do |t| + parts = t.name.sub("#{MANUAL_GEN_DIR}/", "").split("/") + manual_name = parts[0] + + arch_def = arch_def_for("_") + manual = arch_def.manual(manual_name) + raise "Can't find any manual version for '#{manual_name}'" if manual.nil? + + versions, output_hash = versions_from_env(manual) + raise "unexpected mismatch" unless output_hash == parts[2] + + playbook_template_path = $root / "backends" / "manual" / "templates" / "playbook.yml.erb" + erb = ERB.new(playbook_template_path.read, trim_mode: "-") + erb.filename = playbook_template_path.to_s + + FileUtils.mkdir_p File.dirname(t.name) + File.write t.name, erb.result(binding) +end + +file $root / "ext" / "riscv-isa_manual" / "README.md" do + sh "git submodule init ext/riscv-isa-manual" +end + +Dir.glob($root / "arch" / "manual" / "**" / "contents.yaml") do |content_fn| + file "#{File.dirname(content_fn)}/riscv-isa-manual/README.md" do |t| + content_obj = YAML.load_file(content_fn) + cmd = [ + "git", + "--git-dir=#{$root}/.git/modules/ext/riscv-isa-manual", + "worktree add", + t.name, + content_obj["isa_manual_tree"] + ].join(" ") + sh cmd + end +end + +namespace :gen do + html_manual_desc = <<~DESC + Generate an HTML site for one or more versions of the manual. + + Options: + + * MANUAL_NAME: The database name (key) of the manual to generate. + * VERSIONS: A comma-separated list of versions to generate, or "all". + + Examples: + + ./do gen:html_manual MANUAL_NAME=isa VERSIONS=20191008,20240411 + ./do gen:html_manual MANUAL_NAME=isa VERSIONS=all + + Result: + + A static HTML website will be written into gen/manual/MANUAL_NAME//html + DESC + desc html_manual_desc + task :html_manual, [:manual_name, :version] => "gen:arch" do + raise ArgumentError, "Missing required environment variable MANUAL_NAME\n\n#{html_manual_desc}" if ENV["MANUAL_NAME"].nil? + raise ArgumentError, "Missing required environment variable VERSIONS\n\n#{html_manual_desc}" if ENV["VERSIONS"].nil? + + arch_def = arch_def_for("_") + manual = arch_def.manuals.find { |m| m.name == ENV["MANUAL_NAME"] } + raise "No manual '#{ENV['MANUAL_NAME']}'" if manual.nil? + + versions, output_hash = versions_from_env(manual) + + # check out the correct version of riscv-isa-manual, if needed + versions.each do |version| + next unless version.uses_isa_manual? + + unless ($root / "arch" / "manual" / ENV["MANUAL_NAME"] / version.name / "riscv-isa-manual").exist? + Rake::Task[$root / "arch" / "manual" / ENV["MANUAL_NAME"] / version.name / "riscv-isa-manual" / "README.md"].invoke + end + end + + # create chapter pages in antora + versions.each do |version| + antora_path = MANUAL_GEN_DIR / ENV["MANUAL_NAME"] / version.name / "antora" + version.volumes.each do |volume| + volume.chapters.each do |chapter| + Rake::Task[antora_path / "modules" / "chapters" / "pages" / "#{chapter.name}.adoc"].invoke + end + end + Rake::Task[antora_path / "modules" / "funcs" / "pages" / "funcs.adoc"].invoke + Rake::Task[antora_path / "modules" / "ROOT" / "pages" / "index.adoc"].invoke + Rake::Task[antora_path / "antora.yml"].invoke + Rake::Task[antora_path / "nav.adoc"].invoke + version.instructions.each do |inst| + Rake::Task[antora_path / "modules" / "insts" / "pages" / "#{inst.name}.adoc"].invoke + end + end + + playbook_path = MANUAL_GEN_DIR / ENV["MANUAL_NAME"] / "top" / output_hash / "antora" / "playbook.yml" + Rake::Task[playbook_path].invoke + + sh [ + "npm exec -- antora", + "--stacktrace", + "generate", + "--cache-dir=#{$root}/.home/.antora", + "--to-dir=#{MANUAL_GEN_DIR}/#{ENV['MANUAL_NAME']}/top/#{output_hash}/html", + "--log-level=all", + "--fetch", + playbook_path.to_s + ].join(" ") + + puts "SUCCESS: HTML site written to '#{MANUAL_GEN_DIR / ENV['MANUAL_NAME'] / output_hash / 'html'}'" + end +end + +namespace :serve do + task :html_manual do |t| + Rake::Task["gen:html_manual"].invoke + + port = ENV.key?("PORT") ? ENV["PORT"] : 8000 + + arch_def = arch_def_for("_") + manual = arch_def.manuals.find { |m| m.name == ENV["MANUAL_NAME"] } + raise "No manual '#{ENV['MANUAL_NAME']}'" if manual.nil? + + _, output_hash = versions_from_env(manual) + + html_dir = "#{MANUAL_GEN_DIR}/#{ENV['MANUAL_NAME']}/top/#{output_hash}/html" + Dir.chdir(html_dir) do + require "webrick" + + server = WEBrick::HTTPServer.new Port: port.to_i, DocumentRoot: html_dir.to_s + trap("INT") { server.shutdown } + puts "\n\nView server at http://#{`hostname`.strip}:#{port}\n\n" + server.start + end + end +end diff --git a/backends/manual/templates/func.adoc.erb b/backends/manual/templates/func.adoc.erb new file mode 100644 index 000000000..d689993b3 --- /dev/null +++ b/backends/manual/templates/func.adoc.erb @@ -0,0 +1,26 @@ +:tabs-sync-option: + +// defintions and helper functions for ISA definitions + += Functions + +<%- arch_def.functions.each do |f| -%> +[#<%= f.name %>-func-def] +== <%= f.name %><%- if f.builtin? -%> (builtin)<%- end -%> + +<%= f.description %> + +|=== +h| Return Type l| <%= f.return_type_list_str.join(', ') %> +h| Arguments l| <%= f.arguments_list_str.join (', ') %> +|=== + +<%- unless f.builtin? -%> +<%- body_ast = f.body -%> +[subs="specialchars,macros"] +---- +<%= body_ast.gen_adoc %> +---- +<%- end -%> + +<%- end -%> \ No newline at end of file diff --git a/backends/manual/templates/instruction.adoc.erb b/backends/manual/templates/instruction.adoc.erb new file mode 100644 index 000000000..c3420fc48 --- /dev/null +++ b/backends/manual/templates/instruction.adoc.erb @@ -0,0 +1,134 @@ +:tabs-sync-option: + +[[inst:<%=inst.name.gsub('.', '_')%>-def]] += <%= inst.name %> + +*<%= inst.long_name %>* + +This instruction is defined by<%- if inst.defined_by.size > 1 -%> any of the following<%- end -%>: + + <%- inst.defined_by.each do |ext| -%> + * `<%= ext.name %>`, `<%= ext.version_requirement %>` + <%- end -%> + +<%- unless inst.extension_requirements.empty? -%> +Additionally, this instruction is only defined if the following <%- if inst.extension_requirements.size == 1 -%>extension is<%- else -%>extensions are<%- end -%> also present and active: + + <%- inst.extension_requirements.each do |ext| -%> + * `<%= ext.name %>`, `<%= ext.version_requirement %>` + <%- end -%> + +<%- end -%> + +== Encoding + +<%- if inst.multi_encoding? -%> +[NOTE] +This instruction has different encodings in RV32 and RV64. + +[tabs] +==== +RV32:: ++ +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +<%= JSON.dump inst.wavedrom_desc(32) %> +.... + +RV64:: ++ +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +<%= JSON.dump inst.wavedrom_desc(64) %> +.... +==== +<%- else -%> +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +<%= JSON.dump inst.wavedrom_desc(inst.base.nil? ? 32 : inst.base) %> +.... +<%- end -%> + +== Assembly format + +`<%= inst.name %> <%= inst.assembly.gsub('x', 'r') %>` + +== Synopsis + +<%- if inst.data_independent_timing? -%> +[IMPORTANT] +This instruction must have data-independent timing when extension `Zkt` is enabled. +<%- end -%> + +<%= inst.description %> + +== Access +[cols="^,^,^,^,^"] +|=== +| M | HS | U | VS | VU + +| [.access-always]#Always# +| [.access-<%=inst.access['s']%>]#<%= inst.access['s'].capitalize %># +| [.access-<%=inst.access['u']%>]#<%= inst.access['u'].capitalize %># +| [.access-<%=inst.access['vs']%>]#<%= inst.access['vs'].capitalize %># +| [.access-<%=inst.access['vu']%>]#<%= inst.access['vu'].capitalize %># +|=== + +<%- if inst.access_detail? -%> +<%= inst.access_detail %> +<%- end -%> + +== Decode Variables + +<%- if inst.multi_encoding? -%> +[tabs] +==== +RV32:: ++ +[source.idl] +---- +<%- inst.decode_variables(32).each do |d| -%> +<%= d.sext? ? 'signed ' : '' %>Bits<<%= d.size %>> <%= d.name %> = <%= d.extract %>; +<%- end -%> +---- + +RV64:: ++ +[source,idl] +---- +<%- inst.decode_variables(64).each do |d| -%> +<%= d.sext? ? 'signed ' : '' %>Bits<<%= d.size %>> <%= d.name %> = <%= d.extract %>; +<%- end -%> +---- +==== +<%- else -%> +[source,idl] +---- +<%- inst.decode_variables(inst.base.nil? ? 32 : inst.base).each do |d| -%> +<%= d.sext? ? 'signed ' : '' %>Bits<<%= d.size %>> <%= d.name %> = <%= d.extract %>; +<%- end -%> +---- +<%- end -%> + +== Execution + +<%- if inst.key?("operation()") -%> +[source,idl,subs="specialchars,macros"] +---- +<%= inst.operation_ast(inst.arch_def.idl_compiler).gen_adoc %> +---- +==== +<%- end -%> + +<%# exception_list = inst.reachable_exceptions_str(inst.arch_def.sym_table_64, 64) -%> +<%- exception_list = [] -%> +<%- unless exception_list.empty? -%> +== Exceptions + +This instruction may result in the following synchronous exceptions: + + <%- exception_list.sort.each do |etype| -%> + * <%= etype %> + <%- end -%> + +<%- end -%> \ No newline at end of file diff --git a/backends/manual/templates/isa_nav.adoc.erb b/backends/manual/templates/isa_nav.adoc.erb new file mode 100644 index 000000000..6be07f584 --- /dev/null +++ b/backends/manual/templates/isa_nav.adoc.erb @@ -0,0 +1,15 @@ +<%- manual_version.volumes.each do |volume| -%> +.<%= volume.title %> +<%- volume.chapters.each do |chapter| -%> +* xref:chapters:<%= File.basename(chapter.path) %>[<%= chapter.title %>] +<%- end -%> + +<%- end -%> + +.Alphabetical list of instrutions +<%- manual_version.instructions.sort { |a, b| a.name <=> b.name }.each do |inst| -%> +* xref:insts:<%= inst.name %>.adoc[<%= inst.name %>] +<%- end -%> + +.Execution functions (IDL) +* xref:funcs:funcs.adoc[Functions] diff --git a/backends/manual/templates/isa_version_index.adoc.erb b/backends/manual/templates/isa_version_index.adoc.erb new file mode 100644 index 000000000..4f68f1a89 --- /dev/null +++ b/backends/manual/templates/isa_version_index.adoc.erb @@ -0,0 +1,10 @@ += <%= manual_version.manual.marketing_name %>: <%= manual_version.marketing_version %> + +// This is the landing page for a manual version + +<%- if manual_version.state == "ratified" -%> +This version is RATIFIED. It will not change. +<%- else -%> +This version is a DRAFT. It may change. +<%- end -%> + diff --git a/backends/manual/templates/playbook.yml.erb b/backends/manual/templates/playbook.yml.erb new file mode 100644 index 000000000..751bac87c --- /dev/null +++ b/backends/manual/templates/playbook.yml.erb @@ -0,0 +1,93 @@ +--- +site: + title: <%= manual.marketing_name %> + start_page: ROOT:landing.adoc +content: + sources: + <%- versions.each do |version| -%> + - url: <%= $root %> + start_path: gen/manual/<%= manual.name %>/<%= version.name %>/antora + <%- end -%> +antora: + extensions: + - '@antora/lunr-extension' +asciidoc: + extensions: + - 'asciidoctor-kroki' + - '@asciidoctor/tabs' +ui: + bundle: + url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable + snapshot: true + supplemental_files: + - path: css/vendor/tabs.css + contents: <%= $root %>/node_modules/@asciidoctor/tabs/dist/css/tabs.css + - path: js/vendor/tabs.js + contents: <%= $root %>/node_modules/@asciidoctor/tabs/dist/js/tabs.js + - path: partials/footer-scripts.hbs + contents: | + + + + {{#if env.SITE_SEARCH_PROVIDER}} + {{> search-scripts}} + {{/if}} + - path: partials/head-styles.hbs + contents: | + + + + - path: js/vendor/highlight.js + contents: <%= $root %>/backends/cfg_html_doc/ui/highlight.js + - path: css/vendor/custom.css + contents: | + .small { + font-size: 50%; + font-weight: normal; + } + + code.language-idl > a { + text-decoration: none; + } + + /* rotate text vertically */ + span.rotate { + writing-mode: vertical-lr; + } + + span.access-always { + background-color: green; + display: block; + padding: 16px; + border-radius: 8px; + text-align: center; + color: white; + font-weight: bold; + } + + span.access-sometimes { + background-color: rgb(255, 193, 7); + display: block; + padding: 16px; + border-radius: 8px; + text-align: center; + color: black; + font-weight: bold; + } + + span.access-never { + background-color: #e71324; + display: block; + padding: 16px; + border-radius: 8px; + text-align: center; + color: white; + font-weight: bold; + } + + .csr-field-info { + margin-left: 1em; + padding: 1em; + border-radius: 25px; + border: 2px solid; + } \ No newline at end of file diff --git a/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml b/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml index 4e2bfc52c..2284a6581 100644 --- a/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml +++ b/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml @@ -3,7 +3,7 @@ Xcustom: long_name: A new custom extension! type: unprivileged versions: - - version: 0.1 + - version: "0.1.0" ratification_date: null state: development description: | diff --git a/cfgs/generic_rv64/implemented_exts.yaml b/cfgs/generic_rv64/implemented_exts.yaml index f33d15710..07d74d507 100644 --- a/cfgs/generic_rv64/implemented_exts.yaml +++ b/cfgs/generic_rv64/implemented_exts.yaml @@ -1,27 +1,27 @@ # $schema=../../schemas/implemented_exts_schema.json implemented_extensions: - - [A, 2.1] - - [B, 1.0] - - [C, 2.2] - - [D, 2.2] - # - [F, 2.2] - - [I, 2.1] - - [H, 1.0] - - [M, 2.0] - - [S, 1.12] - - [U, 1.12] - - [Zicntr, 2.0] - - [Zicsr, 2.0] - - [Zihpm, 2.0] - - [Smaia, 1.0] - - [Smcdeleg, 0] - - [Smcntrpmf, 1.0] - - [Sscofpmf, 1.0] - - [Ssaia, 1.0] - - [Ssccfg, 0] - - [Sstc, 0.9] - - [Sv39, 1.12] - - [Sv48, 1.12] + - [A, "2.1.0"] + - [B, "1.0.0"] + - [C, "2.2.0"] + - [D, "2.2.0"] + - [F, "2.2.0"] + - [I, "2.1.0"] + - [H, "1.0.0"] + - [M, "2.0.0"] + - [S, "1.12.0"] + - [U, "1.12.0"] + - [Zicntr, "2.0.0"] + - [Zicsr, "2.0.0"] + - [Zihpm, "2.0.0"] + - [Smaia, "1.0.0"] + - [Smcdeleg, "1.0.0"] + - [Smcntrpmf, "1.0.0"] + - [Sscofpmf, "1.0.0"] + - [Ssaia, "1.0.0"] + - [Ssccfg, "1.0.0"] + - [Sstc, "0.9.0"] + - [Sv39, "1.12.0"] + - [Sv48, "1.12.0"] - [Zicboz, "1.0.1-b34ea8a"] - [Zicbom, "1.0.1-b34ea8a"] diff --git a/lib/arch_def.rb b/lib/arch_def.rb index 0384dcfc2..a7a190547 100644 --- a/lib/arch_def.rb +++ b/lib/arch_def.rb @@ -176,7 +176,7 @@ def instructions return @instructions unless @instructions.nil? @instructions = @arch_def["instructions"].map do |_inst_name, inst_data| - Instruction.new(inst_data) + Instruction.new(inst_data, self) end @instructions @@ -198,6 +198,7 @@ def instruction_hash def inst(inst_name) instruction_hash[inst_name.to_s] end + alias instruction inst # @return [Array] List of all functions defined by the architecture def functions diff --git a/lib/arch_obj_models/instruction.rb b/lib/arch_obj_models/instruction.rb index ab119ca47..df31a7a8f 100644 --- a/lib/arch_obj_models/instruction.rb +++ b/lib/arch_obj_models/instruction.rb @@ -30,6 +30,9 @@ def base @data["base"] end + # @return [Boolean] Whether or not the instruction must have data-independent timing when Zkt is enabled. + def data_independent_timing? = @data["data_independent_timing"] + # @param xlen [Integer] 32 or 64, the target xlen # @return [Boolean] whethen or not instruction is defined in base +xlen+ def defined_in_base?(xlen) @@ -180,6 +183,11 @@ def reachable_exceptions_str(symtab, effective_xlen=nil) # @return [ArchDef] The architecture definition attr_reader :arch_def + def initialize(data, arch_def) + super(data) + @arch_def = arch_def + end + # represents a single contiguous instruction encoding field # Multiple EncodingFields may make up a single DecodeField, e.g., when an immediate # is split across multiple locations diff --git a/lib/arch_obj_models/manual.rb b/lib/arch_obj_models/manual.rb new file mode 100644 index 000000000..3f9b7bd9b --- /dev/null +++ b/lib/arch_obj_models/manual.rb @@ -0,0 +1,174 @@ +# frozen_string_literal: true + +require "asciidoctor" + +require_relative "obj" + +class Manual < ArchDefObject + def initialize(data, arch_def) + super(data) + @arch_def = arch_def + end + + def versions + return @versions unless @versions.nil? + + @versions = [] + @data["versions"].each do |version| + @versions << ManualVersion.new(version, self, @arch_def) + end + + @versions + end + + def version(name) + versions.find { |v| v.name == name } + end + + # @return [String] The title of the manual, as used by marketing + def marketing_name = @data["marketing_name"] +end + +class ManualChapter + def initialize(volume, path) + @volume = volume + @version = volume.version + + fullpath = "#{@version.path}/#{path}" + raise "Path '#{fullpath}' does not exist" unless File.exist?(fullpath) + + @path = fullpath + end + + def name + File.basename(@path, ".adoc") + end + + def title + return @title unless @title.nil? + + @title = (Asciidoctor.load File.read(path).scrub).doctitle.encode("US-ASCII") + end + + # @return [String] The absolute path to the chapter + attr_reader :path +end + +class ManualVolume + # @return [ManualVersion] The version this volume belongs to + attr_reader :version + + # @return [ArchDef] The architecture definition + def arch_def = version.arch_def + + def initialize(data, version) + @data = data + @version = version + end + + def chapters + return @chapters unless @chapters.nil? + + @chapters = [] + return @chapters if @data["chapters"].nil? + + @data["chapters"].each do |chapter_path| + @chapters << ManualChapter.new(self, chapter_path) + end + + @chapters + end + + def chapter(name) = chapters.find { |c| c.name == name } + + def title = @data["title"] + + # @return [Array] Array of extension versions in this volume + def extensions + return @extensions unless @extensions.nil? + + @extensions = [] + return @extensions if @data["extensions"].nil? + + @data["extensions"].each do |ext| + ext_obj = arch_def.extension(ext[0]) + if ext_obj.nil? + warn "Extension '#{ext[0]}' is not in the database" + next + end + + unless ext_obj.versions.any? { |v| v["version"] == ext[1] } + warn "Extension '#{ext[0]}', version '#{ext[1]}' is not defined in the database" + next + end + + @extensions << ExtensionVersion.new(ext[0], ext[1]) + end + @extensions + end +end + +class ManualVersion < ArchDefObject + # @return [Manual] The manual this version belongs to + attr_reader :manual + + # @return [ArchDef] The architecture definition + attr_reader :arch_def + + def initialize(data, manual, arch_def) + super(data) + @manual = manual + @arch_def = arch_def + end + + # @return [String] Semantic version number + def version = @data["version"] + + # @return [String] Version name used by marketing + def marketing_version = @data["marketing_version"] + + # @return [String] Path to the directory containing contents.yaml file for this version + def path + File.dirname(@data["__source"]) + end + + # @return [Boolean] Whether or not this version is using riscv-isa-manual as a source + def uses_isa_manual? = @data["uses_isa_manual"] == true + + # @return [String] The git tree-ish of riscv-isa-manual used by this version + def isa_manual_tree = @data["isa_manual_tree"] + + # @return [Array] All volumes defined in this manual version + def volumes + return @volumes unless @volumes.nil? + + @volumes = [] + @data["volumes"].each do |volume| + @volumes << ManualVolume.new(volume, self) + end + + @volumes + end + + def state = @data["state"] + + def extensions + return @extensions unless @extensions.nil? + + @extensions = volumes.map(&:extensions).flatten.uniq + end + + # @return [Array] All instructions defined in this version + def instructions + return @instructions unless @instructions.nil? + + @instructions = [] + extensions.each do |ext| + ext_obj = @arch_def.extension(ext.name) + ext_obj.instructions.each do |inst| + @instructions << inst + end + end + @instructions + end +end diff --git a/lib/idl/passes/prune.rb b/lib/idl/passes/prune.rb index c79a770ed..768d073fc 100644 --- a/lib/idl/passes/prune.rb +++ b/lib/idl/passes/prune.rb @@ -183,13 +183,13 @@ def prune(symtab) if lhs_value == 0 # 0 & anything == 0 create_literal(0) - elsif lhs_value == ((1 << rhs.type(symtab).width) - 1) + elsif (rhs.type(symtab).width != :unknown) && lhs_value == ((1 << rhs.type(symtab).width) - 1) # rhs idenntity rhs.prune(symtab) elsif rhs_value == 0 # anything & 0 == 0 create_literal(0) - elsif rhs_value == (1 << lhs.type(symtab).width - 1) + elsif (lhs.type(symtab).width != :unknown) && rhs_value == (1 << lhs.type(symtab).width - 1) # lhs identity lhs.prune(symtab) else diff --git a/lib/validate.rb b/lib/validate.rb index 82df28505..b895245c4 100644 --- a/lib/validate.rb +++ b/lib/validate.rb @@ -18,7 +18,8 @@ class Validator inst: $root / "schemas" / "inst_schema.json", ext: $root / "schemas" / "ext_schema.json", csr: $root / "schemas" / "csr_schema.json", - cfg_impl_ext: $root / "schemas" / "implemented_exts_schema.json" + cfg_impl_ext: $root / "schemas" / "implemented_exts_schema.json", + manual_version: $root / "schemas" / "manual_version_schema.json" }.freeze # types of objects that can be validated @@ -183,6 +184,8 @@ def validate(path, type: nil) type = :ext when %r{.*arch/csr/.*\.yaml$} type = :csr + when %r{.*arch/manual/.*/.*contents\.yaml$} + type = :manual_version else warn "Cannot determine type from YAML path '#{path}'; skipping" return diff --git a/schemas/ext_schema.json b/schemas/ext_schema.json index 6592dc846..d1071745e 100644 --- a/schemas/ext_schema.json +++ b/schemas/ext_schema.json @@ -70,6 +70,10 @@ "type": "string", "description": "Full documentation of the extension" }, + "rvi_jira_issue": { + "type": "string", + "description": "JIRA issue number for the RVI issue that tracks this extension" + }, "company": { "description": "The company that developed this extension", "type": "object", @@ -112,14 +116,8 @@ "$ref": "schema_defs.json#/$defs/extension_version" }, "state": { - "description": "Current state of this version", - "enum": [ - "development", - "frozen", - "public-review", - "ratified", - "nonstandard-released" - ] + "$ref": "schema_defs.json#/$defs/spec_state", + "description": "Current state of this version" }, "repositories": { "description": "Repositories associated with this extension", @@ -223,6 +221,7 @@ "items": { "type": "object", "description": "Exceptions defined by this extension", + "required": ["num", "name", "var"], "properties": { "num": { "type": "integer" @@ -234,6 +233,15 @@ "var": { "type": "string", "description": "Field name for the InterruptCode enum in IDL" + }, + "when": { + "type": "object", + "properties": { + "version": { + "$ref": "schema_defs.json#/$defs/version_requirements" + } + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/schemas/manual_version_schema.json b/schemas/manual_version_schema.json new file mode 100644 index 000000000..08164d959 --- /dev/null +++ b/schemas/manual_version_schema.json @@ -0,0 +1,98 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + + "$defs": { + "volume": { + "type": "object", + "required": ["title", "description", "authors"], + "properties": { + "title": { + "type": "string", + "description": "Title of the volume" + }, + "description": { + "type": "string", + "description": "Description of the volume" + }, + "chapters": { + "type": "array", + "items": { + "$ref": "#/$defs/chapter" + }, + "description": "Ordered (in display order) list of chapters" + }, + "authors": { + "type": "array", + "itesm": { + "$ref": "schema_defs.json#/$defs/author" + } + }, + "extensions": { + "type": "array", + "items": { + "$ref": "schema_defs.json#/$defs/extension_name_and_version" + }, + "description": "List of extensions defined in this volume, with version numbers" + }, + "changes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of changes made since the last version" + } + } + }, + "chapter": { + "type": "string", + "description": "Relative (to the contents.yaml file) path to the chapter source" + } + }, + + "type": "object", + "required": ["manual", "version", "name", "marketing_version", "state", "volumes"], + "properties": { + "name": { + "type": "string", + "description": "Name (database key) of this version" + }, + "manual": { + "type": "string", + "description": "Name (database key) of the manual this version belongs to" + }, + "version": { + "$ref": "schema_defs.json#/$defs/semantic_version", + "description": "Semantic version number within the manual" + }, + "marketing_version": { + "type": "string", + "description": "The publically displayed version number" + }, + "state": { + "$ref": "schema_defs.json#/$defs/spec_state", + "description": "State of this version" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL to the version, if stored external to the database" + }, + "uses_isa_manual": { + "type": "boolean", + "default": false, + "description": "Whether or not this manual version is derived from riscv-isa-manual" + }, + "isa_manual_tree": { + "type": "string", + "description": "The git tree-ish of the riscv-isa-manual repository used to generate this version" + }, + "volumes": { + "type": "array", + "items": { + "$ref": "#/$defs/volume" + }, + "descriptoin": "List of volumes in this version" + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/schemas/schema_defs.json b/schemas/schema_defs.json index a396263c0..db91bdc4b 100644 --- a/schemas/schema_defs.json +++ b/schemas/schema_defs.json @@ -4,20 +4,27 @@ "title": "Common patterns used by all schemas", "$defs": { + "semantic_version": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" + }, + "spec_state": { + "type": "string", + "enum": [ + "development", + "frozen", + "public-review", + "ratification-ready", + "ratified", + "nonstandard-released" + ] + }, "extension_name": { "type": "string", "pattern": "^([A-WY])|([SXZ][a-z0-9]+)$" }, "extension_version": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "string", - "pattern": "^[0-9]+(\\.[0-9]+(\\.[0-9]+(-[a-fA-F0-9]+)?)?)?$" - } - ] + "$ref": "#/$defs/semantic_version" }, "requirement_string": { "type": "string", @@ -69,6 +76,42 @@ } ] + }, + "author": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "description": "Author's full name" + }, + "email": { + "type": "string", + "format": "email", + "description": "Author's email address" + }, + "organization": { + "$ref": "#/$defs/organization", + "description": "Author's organization, which should be an RVI member (or individual)" + } + }, + "additionalProperties": false + }, + "organization": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "description": "Organization name" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Organization URL" + } + }, + "additionalProperties": false } } } \ No newline at end of file