From 73eadb38438f5972627b7138659660c8dcf2eea8 Mon Sep 17 00:00:00 2001 From: James Ball Date: Thu, 7 Nov 2024 10:30:29 -0800 Subject: [PATCH] Renamed many CRD and Profile things and now Profiles are generated per profile release (e.g. RVA20.pdf, RVA22,pdf) --- .github/workflows/pages.yml | 32 ++- .gitignore | 1 - README.adoc | 6 +- Rakefile | 10 +- arch/certificate_class/MC.yaml | 35 +++ .../MockCertificateClass.yaml | 14 + .../MC100.yaml} | 36 +-- .../MockCertificateModel.yaml} | 26 +- arch/crd_family/Microcontroller.yaml | 82 ------ arch/crd_family/MockCRDFamily.yaml | 14 - arch/ext/Sm.yaml | 1 - arch/profile/MockProfile-1.yaml | 42 --- arch/profile/rva20s64.yaml | 69 ----- arch/profile/rva20u64.yaml | 135 --------- arch/profile/rva22s64.yaml | 106 ------- arch/profile/rva22u64.yaml | 128 --------- arch/profile_class/MockProfileClass.yaml | 15 + arch/profile_class/RVA.yaml | 28 ++ arch/profile_class/RVB.yaml | 50 ++++ arch/profile_class/RVI.yaml | 28 ++ arch/profile_family/MockProfileFamily.yaml | 15 - arch/profile_family/rva.yaml | 49 ---- arch/profile_release/MockProfileRelease.yaml | 72 +++++ arch/profile_release/RVA20.yaml | 221 +++++++++++++++ arch/profile_release/RVA22.yaml | 258 ++++++++++++++++++ arch/profile_release/RVI20.yaml | 151 ++++++++++ backends/arch_gen/lib/arch_gen.rb | 62 ++--- backends/arch_gen/tasks.rake | 62 ++--- backends/certificate_doc/tasks.rake | 123 +++++++++ .../templates/certificate.adoc.erb} | 106 ++++--- backends/crd_doc/tasks.rake | 123 --------- backends/portfolio_doc/tasks.rb | 122 --------- .../portfolio_doc/templates/family_intro.erb | 12 +- backends/profile_doc/tasks.rake | 55 ++-- .../profile_doc/templates/profile.adoc.erb | 145 +++++----- lib/arch_def.rb | 177 ++++++++---- .../{crd.rb => certificate.rb} | 35 +-- lib/arch_obj_models/portfolio.rb | 53 ++-- lib/arch_obj_models/profile.rb | 144 +++++++--- schemas/arch_schema.json | 13 +- 40 files changed, 1552 insertions(+), 1304 deletions(-) create mode 100644 arch/certificate_class/MC.yaml create mode 100644 arch/certificate_class/MockCertificateClass.yaml rename arch/{crd/MC-1.yaml => certificate_model/MC100.yaml} (88%) rename arch/{crd/MockCRD-1.yaml => certificate_model/MockCertificateModel.yaml} (91%) delete mode 100644 arch/crd_family/Microcontroller.yaml delete mode 100644 arch/crd_family/MockCRDFamily.yaml delete mode 100644 arch/profile/MockProfile-1.yaml delete mode 100644 arch/profile/rva20s64.yaml delete mode 100644 arch/profile/rva20u64.yaml delete mode 100644 arch/profile/rva22s64.yaml delete mode 100644 arch/profile/rva22u64.yaml create mode 100644 arch/profile_class/MockProfileClass.yaml create mode 100644 arch/profile_class/RVA.yaml create mode 100644 arch/profile_class/RVB.yaml create mode 100644 arch/profile_class/RVI.yaml delete mode 100644 arch/profile_family/MockProfileFamily.yaml delete mode 100644 arch/profile_family/rva.yaml create mode 100644 arch/profile_release/MockProfileRelease.yaml create mode 100644 arch/profile_release/RVA20.yaml create mode 100644 arch/profile_release/RVA22.yaml create mode 100644 arch/profile_release/RVI20.yaml create mode 100644 backends/certificate_doc/tasks.rake rename backends/{crd_doc/templates/crd.adoc.erb => certificate_doc/templates/certificate.adoc.erb} (81%) delete mode 100644 backends/crd_doc/tasks.rake delete mode 100644 backends/portfolio_doc/tasks.rb rename lib/arch_obj_models/{crd.rb => certificate.rb} (84%) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 3afb0a977f..37213d4ca9 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -57,18 +57,26 @@ jobs: run: mkdir -p _site/htmls - name: Copy cfg html run: cp -R gen/cfg_html_doc/generic_rv64/html _site/example_cfg - - name: Create RVA Family PDF Spec - run: ./do gen:profile[rva] - - name: Copy RVA Family PDF - run: cp gen/profile_doc/pdf/rva.pdf _site/pdfs/rva.pdf - - name: Create MC-1 PDF Spec - run: ./do gen:crd_pdf[MC-1] - - name: Copy MC-1 PDF - run: cp gen/crd_doc/pdf/MC-1.pdf _site/pdfs/MC-1.pdf - - name: Create MC-1 HTML Spec - run: ./do gen:crd_html[MC-1] - - name: Copy MC-1 HTML - run: cp gen/crd_doc/html/MC-1.html _site/htmls/MC-1.html + - name: Create RVA20 Profile Release PDF Spec + run: ./do gen:profile[RVA20] + - name: Copy RVA20 Profile Release PDF + run: cp gen/profile_doc/pdf/RVA20.pdf _site/pdfs/RVA20.pdf + - name: Create RVA22 Profile Release PDF Spec + run: ./do gen:profile[RVA22] + - name: Copy RVA22 Profile Release PDF + run: cp gen/profile_doc/pdf/RVA22.pdf _site/pdfs/RVA22.pdf + - name: Create RVI20 Profile Release PDF Spec + run: ./do gen:profile[RVI20] + - name: Copy RVI20 Profile Release PDF + run: cp gen/profile_doc/pdf/RVA20.pdf _site/pdfs/RVI20.pdf + - name: Create MC100 PDF Spec + run: ./do gen:cert_model_pdf[MC100] + - name: Copy MC100 PDF + run: cp gen/certificate_doc/pdf/MC100.pdf _site/pdfs/MC100.pdf + - name: Create MC100 HTML Spec + run: ./do gen:cert_model_html[MC100] + - name: Copy MC100 HTML + run: cp gen/certificate_doc/html/MC100.html _site/htmls/MC100.html - name: Copy manual html run: cp -R gen/manual/isa/top/all/html _site/manual - name: Setup Pages diff --git a/.gitignore b/.gitignore index 1d7cd45ac1..e82076dd84 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ diag-ditaa-* arch/manual/isa/**/riscv-isa-manual gen -gen_expected node_modules _site images diff --git a/README.adoc b/README.adoc index b301af906f..df004adfeb 100644 --- a/README.adoc +++ b/README.adoc @@ -8,8 +8,10 @@ The following artifacts have been generated from the top of the `main` branch: * https://riscv-software-src.github.io/riscv-unified-db/example_cfg/html/index.html[configuration-specific documentation] * https://riscv-software-src.github.io/riscv-unified-db/ruby/arch_def/index.html[Ruby API documentation (database interface)] * https://riscv-software-src.github.io/riscv-unified-db/ruby/idl/index.html[Ruby IDL API documentation (IDL compiler)] -* https://riscv-software-src.github.io/riscv-unified-db/pdfs/rva.pdf[RVA Profile Family] -* https://riscv-software-src.github.io/riscv-unified-db/pdfs/MC-1.pdf[MC-1 Certification Requirements Document] +* https://riscv-software-src.github.io/riscv-unified-db/pdfs/RVI20.pdf[RVI20 Profile Release] +* https://riscv-software-src.github.io/riscv-unified-db/pdfs/RVA20.pdf[RVA20 Profile Release] +* https://riscv-software-src.github.io/riscv-unified-db/pdfs/RVA22.pdf[RVA22 Profile Release] +* https://riscv-software-src.github.io/riscv-unified-db/pdfs/MC100.pdf[MC100 Certification Requirements Document] == Overview diff --git a/Rakefile b/Rakefile index 30498ecfe2..8abd567d9d 100644 --- a/Rakefile +++ b/Rakefile @@ -274,10 +274,12 @@ task :regress do ENV["VERSIONS"] = "all" Rake::Task["gen:html_manual"].invoke Rake::Task["gen:html"].invoke("generic_rv64") - Rake::Task["gen:crd_pdf"].invoke("MockCRD-1") - Rake::Task["gen:crd_pdf"].invoke("MC-1") - Rake::Task["gen:profile"].invoke("MockProfileFamily") - Rake::Task["gen:profile"].invoke("rva") + Rake::Task["gen:cert_model_pdf"].invoke("MockCertificateModel") + Rake::Task["gen:cert_model_pdf"].invoke("MC100") + Rake::Task["gen:profile"].invoke("MockProfileRelease") + Rake::Task["gen:profile"].invoke("RVA20") + Rake::Task["gen:profile"].invoke("RVA22") + Rake::Task["gen:profile"].invoke("RVI20") puts puts "Regression test PASSED" diff --git a/arch/certificate_class/MC.yaml b/arch/certificate_class/MC.yaml new file mode 100644 index 0000000000..923426680a --- /dev/null +++ b/arch/certificate_class/MC.yaml @@ -0,0 +1,35 @@ +MC: + name: MC + long_name: Microcontroller Certificate Class + + introduction: | + This certification class specifies requirements for microcontrollers. + It targets microcontrollers running low-level software on an RTOS or bare-metal. + This CRD is not intended for the smallest possible microcontrollers but rather for applications + benefiting from a standardized microcontroller. + See the https://docs.google.com/document/d/133SZKc18tLsQcT1o6gEmBUkjwrtg2ow63me54RQ1jiY[RISC-V CRDs] + document for information relevant to all RISC-V CRDs. + + naming_scheme: | + The MC (M = Microcontroller, C = Certificate) has the following naming scheme (suffixes after MC + are optional but in the below order): + + MC[v] + + Where: + + * Left & right square braces denote optional. + * \ is a 3 digit integer. It is changed only when mandatory extensions are added to a CRD. + ** The one's digit is incremented when a small mandatory extension is added (e.g., Zicond) + ** The ten's digit is incremented when a medium mandatory extension is addded (e.g., PMP) + ** The hundreds's digit is incremented when a large mandatory extension is addded (e.g., V or H) + * \ is a semantic version (see semver.org) formatted as [..[patch]]. If \ is omitted, the reference applies equally to all versions. + ** A release indicates support for a new optional extension. + ** A release indicates one or more of the following changes to the certification tests associated with the CRD. + *** Fix test bug or increase test coverage + *** Add more allowed parameter values + *** Support new extension version + ** A release indicates just CRD specification changes without any difference in functional behavior + + mandatory_priv_modes: + - M \ No newline at end of file diff --git a/arch/certificate_class/MockCertificateClass.yaml b/arch/certificate_class/MockCertificateClass.yaml new file mode 100644 index 0000000000..1cd6dbc0e2 --- /dev/null +++ b/arch/certificate_class/MockCertificateClass.yaml @@ -0,0 +1,14 @@ +MockCertificateClass: + name: MockCertificateClass + long_name: Mock Certificate Class Long Name + + introduction: | + Here's the Mock Certificate Class introduction. + + naming_scheme: | + Here's the Mock Certificate Class naming scheme. + + mandatory_priv_modes: + - M + + description: Here's the Mock Certificate Class description. \ No newline at end of file diff --git a/arch/crd/MC-1.yaml b/arch/certificate_model/MC100.yaml similarity index 88% rename from arch/crd/MC-1.yaml rename to arch/certificate_model/MC100.yaml index f7a5e15f40..f92f61e6cf 100644 --- a/arch/crd/MC-1.yaml +++ b/arch/certificate_model/MC100.yaml @@ -1,12 +1,17 @@ # yaml-language-server: $schema=../../schemas/testplan_schema.json -MC-1: - name: MC-1 - long_name: LONG NAME - family: Microcontroller - - # semantic version within the CRD family - version: "1.0" +MC100: + name: MC100 + long_name: Basic Microcontroller Certificate + class: MC + model: 100 + + # Semantic versions within the model + versions: + - version: "1.0.0" + + # XLEN used by rakefile + base: 32 revision_history: - revision: "0.7" @@ -14,7 +19,7 @@ MC-1: changes: - First version after moving non-microcontroller content in this document to a new document called “RISC-V CRDs (Certification Requirement Documents)” - - Change MC-1 Unpriv ISA spec from + - Change MC100 Unpriv ISA spec from “https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf[riscv-spec-v2.1], May 31, 2016” to https://github.com/riscv/riscv-isa-manual/releases/tag/Ratified-IMAFDQC since the former isn't ratified by the latter is the oldest ratified version. @@ -26,8 +31,8 @@ MC-1: - Supporting multiple MC versions to support customers wanting to certify existing microcontrollers not using the latest version of ratified standards. - Changed versioning scheme to use major.minor.patch instead of 3-digit major & minor. - Added a table showing the mapping from MC version to ISA manuals. - - Reluctantly made interrupts OUT OF SCOPE for MC-1 since only the CLINT interrupt controller - was ratified at that time and isn’t anticipated to be the interrupt controller used by MC-1 implementations. + - Reluctantly made interrupts OUT OF SCOPE for MC100 since only the CLINT interrupt controller + was ratified at that time and isn’t anticipated to be the interrupt controller used by MC100 implementations. - Clarified MANDATORY behaviors for mie and mip CSRs - Removed canonical discovery recipe because the OPT-* options directly inform the certification tests and certification reference model of the status of the various options. Also, canonical @@ -61,16 +66,13 @@ MC-1: changes: - Initial version - # XLEN used by rakefile - base: 32 - description: | - MC-1 can be though of as a minimal 32-bit RISC-V processor with M-mode support: + MC100 can be though of as minimal 32-bit RISC-V processors with M-mode support: * The Unprivileged ISA is RV32I with a few extensions suitable for a basic microcontroller - * The M-mode features are those listed as mandatory in the RISC-V Privileged ISA manual. + * The M-mode features are those listed as mandatory in the associated RISC-V Privileged ISA manual - Key features not included in MC-1 (i.e., OUT OF SCOPE): + Key features not included in MC100 (i.e., OUT OF SCOPE): * Interrupt Controller (e.g., CLIC, CLINT, PLIC) * Features for modes other than M-mode @@ -78,7 +80,7 @@ MC-1: * Debug & trace (TBD) # Specification versions - tsc_profile: null # None for MC-1 + tsc_profile: null # None for MC100 unpriv_isa_manual_revision: "20191213" priv_isa_manual_revision: "20190608-Priv-MSU-Ratified" debug_manual_revision: "0.13.2" diff --git a/arch/crd/MockCRD-1.yaml b/arch/certificate_model/MockCertificateModel.yaml similarity index 91% rename from arch/crd/MockCRD-1.yaml rename to arch/certificate_model/MockCertificateModel.yaml index 7df55f61eb..dc421c5426 100644 --- a/arch/crd/MockCRD-1.yaml +++ b/arch/certificate_model/MockCertificateModel.yaml @@ -1,16 +1,18 @@ # yaml-language-server: $schema=../../schemas/testplan_schema.json -MockCRD-1: - name: MockCRD-1 - long_name: Mock CRD Long Name - - family: MockCRDFamily +MockCertificateModel: + name: MockCertificateModel + long_name: Mock Certificate Model Long Name + class: MockCertificateClass + model: MockModel # XLEN used by rakefile base: 64 - # semantic version within the CRD family - version: "1.0" + # Semantic versions within the model + versions: + - version: "1.0.0" + - version: "1.1.0" revision_history: - revision: "0.1" @@ -135,6 +137,16 @@ MockCRD-1: M_MODE_ENDIANESS: schema: const: little + # XXX Uncomment when GitHub issue #XXX is fixed. + #schema: + #- when: + # version: "=1.0.0" + # then: + # const: little + #- when: + # version: "=1.1.0" + # then: + # enum: [little, big] XLEN: schema: const: 64 diff --git a/arch/crd_family/Microcontroller.yaml b/arch/crd_family/Microcontroller.yaml deleted file mode 100644 index 3dba4f9af7..0000000000 --- a/arch/crd_family/Microcontroller.yaml +++ /dev/null @@ -1,82 +0,0 @@ -Microcontroller: - name: Microcontroller - long_name: LONG NAME - revision_history: - - version: "0.7" - date: 2024-07-29 - changes: - - First version after moving non-microcontroller content in this document to a new document - called “RISC-V CRDs (Certification Requirement Documents)” - - Change MC-1 Unpriv ISA spec from - “https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf[riscv-spec-v2.1], May 31, - 2016” to https://github.com/riscv/riscv-isa-manual/releases/tag/Ratified-IMAFDQC since the - former isn't ratified by the latter is the oldest ratified version. - - Added requirements for WFI instruction - - Added requirements related to msip memory-mapped register - - version: "0.6" - date: 2024-07-11 - changes: - - Supporting multiple MC versions to support customers wanting to certify existing microcontrollers not using the latest version of ratified standards. - - Changed versioning scheme to use major.minor.patch instead of 3-digit major & minor. - - Added a table showing the mapping from MC version to ISA manuals. - - Reluctantly made interrupts OUT OF SCOPE for MC-1 since only the CLINT interrupt controller - was ratified at that time and isn’t anticipated to be the interrupt controller used by MC-1 implementations. - - Clarified MANDATORY behaviors for mie and mip CSRs - - Removed canonical discovery recipe because the OPT-* options directly inform the certification - tests and certification reference model of the status of the various options. Also, canonical - discovery recipes (e.g., probing for CLIC) violate the certification approach of avoiding writing - potentially illegal values to CSR fields. - - Added more options for interrupts - - Moved non-microcontroller content in this document to a new document called “RISC-V Certification Plans” - - version: "0.5" - date: 2024-06-03 - changes: - - Renamed to “RISC-V Microcontroller Certification Plan” based on Jason’s recommendation - - Added mvendorid, marchid, mimpid, and mhardid read-only priv CSRs because Allen pointed out - these are mandatory in M-mode v1.13 (probably older versions too, haven’t looked yet). - - Added table showing mapping of MC versions to associated RISC-V specifications - - version: "0.4" - date: 2024-06-03 - changes: - - Added M-mode instruction requirements - - Made Zicntr MANDATORY due to very low cost for implementations to support (in the spirit of minimizing options). - - Removed OPT-CNTR-PREC since minstret and mcycle must be a full 64 bits to be standard-compliant. - - version: "0.3" - date: 2024-05-25 - changes: - - Includes Zicntr as OPTIONAL and then has only 32-bit counters for instret and cycle. - - version: "0.2" - date: 2024-05-20 - changes: - - Very early draft - - version: "0.1" - date: 2024-05-16 - changes: - - Initial version - - introduction: | - This CRD (Certification Requirements Document) specifies requirements for microcontrollers. - It targets microcontrollers running low-level software on an RTOS or bare-metal. - This CRD is not intended for the smallest possible microcontrollers but rather for applications - benefiting from a standardized microcontroller. - See the https://docs.google.com/document/d/133SZKc18tLsQcT1o6gEmBUkjwrtg2ow63me54RQ1jiY[RISC-V CRDs] - document for information relevant to all RISC-V CRDs. - - naming_scheme: | - The MC (M = Microcontroller, C = Certificate) has the following naming scheme (suffixes after MC - are optional but in the below order): - - MC<-VERSION><-MODE><-XLEN> - - Where: - - * \<-VERSION> is formatted as -[..[patch]] where left & right square braces denote optional. If \<-VERSION> is omitted, the reference applies equally to all versions. - ** A release indicates significant new functionality covered by the release. - ** A release is an update to the initial major release that changes requirements. The initial major release has an implicit minor release value of “.0” so the first update to a major release has a minor release of “.1”. - ** A release only provides specification clarifications and doesn’t change requirements. The initial minor release has an implicit patch release value of “.0” so the first update to a minor release has a patch release of “.1”. - ** For example, the first release of MC is MC-1 (can omit the implicit “.0” minor release), its first minor release is MC-1.1, a patch release of this minor release is MC-1.1.1 and the next major release is MC-2. - * \<-MODE> is -Unpriv, -Priv, or -Debug. If \<-MODE> is omitted, the reference applies equally to all modes. - * \<-XLEN> is -32 for 32-bit microcontrollers and -64 for 64-bit microcontrollers. If \<-XLEN> is omitted, the reference applies equally to 32-bit and 64-bit microcontrollers. The term MXLEN used in the Priv ISA Manual is always equal to XLEN for MC. - - mandatory_priv_modes: - - M diff --git a/arch/crd_family/MockCRDFamily.yaml b/arch/crd_family/MockCRDFamily.yaml deleted file mode 100644 index 574329c0ed..0000000000 --- a/arch/crd_family/MockCRDFamily.yaml +++ /dev/null @@ -1,14 +0,0 @@ -MockCRDFamily: - name: MockCRDFamily - long_name: Mock CRD Family Long Name - - introduction: | - Here's the Mock CRD Family's introduction. - - naming_scheme: | - Here's the Mock CRD Family's naming scheme. - - mandatory_priv_modes: - - M - - description: Here's the Mock CRD Family's description. \ No newline at end of file diff --git a/arch/ext/Sm.yaml b/arch/ext/Sm.yaml index f49db374bf..173be9c737 100644 --- a/arch/ext/Sm.yaml +++ b/arch/ext/Sm.yaml @@ -422,7 +422,6 @@ Sm: description: | Physical address of the unified discovery configuration data structure. This address is reported in the `mconfigptr` CSR. - TODO: GitHub issue 53 schema: type: integer when: diff --git a/arch/profile/MockProfile-1.yaml b/arch/profile/MockProfile-1.yaml deleted file mode 100644 index 9f818d7599..0000000000 --- a/arch/profile/MockProfile-1.yaml +++ /dev/null @@ -1,42 +0,0 @@ -MockProfile-1: - family: MockProfileFamily - description: This is the Mock Profile description. - marketing_name: MockProfile-1 Marketing Name - mode: S - version: "1.0" - contributors: - - name: Micky Mouse - email: micky@disney.com - company: Disneyk - extensions: - - name: S - presence: mandatory - version: "= 1.11" - - name: Zifencei - presence: mandatory - version: "= 2.0" - note: | - Zifencei is mandated as it is the only standard way to support - instruction-cache coherence in RVA20 application processors. A new - instruction-cache coherence mechanism is under development which might - be added as an option in the future. - - name: Zihpm - presence: optional - version: "= 2.0" - - name: Sv48 - presence: optional - version: "= 1.11" - extra_notes: - - presence: optional - text: Here's the first extra note for the optional extensions section. - - presence: mandatory - text: | - Here's the first extra note for the mandatory extensions section. - This note is multiple lines. - - presence: optional - text: Here's the second extra note for the optional extensions section. - recommendations: - - text: | - Implementations are strongly recommended to raise illegal-instruction - exceptions on attempts to execute unimplemented opcodes. - - text: Micky should give Pluto an extra treat \ No newline at end of file diff --git a/arch/profile/rva20s64.yaml b/arch/profile/rva20s64.yaml deleted file mode 100644 index 48313c9222..0000000000 --- a/arch/profile/rva20s64.yaml +++ /dev/null @@ -1,69 +0,0 @@ - -rva20s64: - family: rva - description: | - The RVA20S64 profile specifies the ISA features available to a - supervisor-mode execution environment in 64-bit applications - processors. RVA20S64 is based on privileged architecture version - 1.11. - marketing_name: RVA20S64 - mode: S - version: "1.0" - contributors: - - name: Krste Asanovic - email: krste@sifive.com - company: SiFive - extensions: - - name: S - presence: mandatory - version: "= 1.11" - - name: Zifencei - presence: mandatory - version: "= 2.0" - note: | - Zifencei is mandated as it is the only standard way to support - instruction-cache coherence in RVA20 application processors. A new - instruction-cache coherence mechanism is under development which might - be added as an option in the future. - - name: Svbare - presence: mandatory - version: "= 1.0" - note: | - Svbare is a new extension name introduced with RVA20. - - name: Sv39 - presence: mandatory - version: "= 1.11" - - name: Svade - presence: mandatory - version: "~> 1.0" - note: | - Svbare is a new extension name introduced with RVA20. - - It is subsequently defined in more detail with the ratification of - `Svadu`. - - name: Ssccptr - presence: mandatory - version: "= 1.0" - note: | - Ssccptr is a new extension name introduced with RVA20. - - name: Sstvecd - presence: mandatory - version: "= 1.0" - note: | - Sstvecd is a new extension name introduced with RVA20. - - name: Sstvala - presence: mandatory - version: "= 1.0" - note: | - Sstvala is a new extension name introduced with RVA20. - - name: Zihpm - presence: optional - version: "= 2.0" - - name: Sv48 - presence: optional - version: "= 1.11" - - name: Ssu64xl - presence: optional - version: "= 1.0" - note: | - Ssu64xl is a new extension name introduced with RVA20. diff --git a/arch/profile/rva20u64.yaml b/arch/profile/rva20u64.yaml deleted file mode 100644 index afbbdef321..0000000000 --- a/arch/profile/rva20u64.yaml +++ /dev/null @@ -1,135 +0,0 @@ - -rva20u64: - family: rva - mode: U # privilege mode - base: 64 - version: "1.0" # semantic version of the profile within it's lineage [family, mode, base] - marketing_name: RVA20U64 # marketing name for documentation - description: | - The RVA20U64 profile specifies the ISA features available to user-mode - execution environments in 64-bit applications processors. This is the - most important profile within the application processor family in - terms of the amount of software that targets this profile. - state: ratified # current status ["ratified", "development"] - ratification_date: null # when ratified, must be present. Date the profile was ratified on - contributors: - - name: Krste Asanovic - email: krste@sifive.com - company: SiFive - extensions: - - name: I - presence: mandatory - version: "~> 2.1" - note: | - RVI is the mandatory base ISA for RVA, and is little-endian. - - As per the unprivileged architecture specification, the `ecall` - instruction causes a requested trap to the execution environment. - - The `fence.tso` instruction is mandatory. - - NOTE: The `fence.tso` instruction was incorrectly described as - optional in the 2019 ratified specifications. However, `fence.tso` is - encoded within the standard `fence` encoding such that implementations - must treat it as a simple global fence if they do not natively support - TSO-ordering optimizations. As software can always assume without any - penalty that `fence.tso` is being exploited by a hardware - implementation, there is no advantage to making the instruction a - profile option. Later versions of the unprivileged ISA - specifications correctly indicate that `fence.tso` is mandatory. - - name: A - presence: mandatory - version: "= 2.1" - - name: C - presence: mandatory - version: "= 2.2" - - name: D - presence: mandatory - version: "= 2.2" - - name: F - presence: mandatory - version: "= 2.2" - - name: M - presence: mandatory - version: "= 2.0" - - name: U - presence: mandatory - version: "~> 2.0" - param_constraints: - U_MODE_ENDIANESS: - schema: - const: little - - name: Zicntr - presence: mandatory - version: " = 2.0" - - name: Ziccif - presence: mandatory - version: "= 1.0" - note: | - Ziccif is a new extension name introduced with RVA20. - The fetch atomicity requirement facilitates runtime patching - of aligned instructions. - - name: Ziccrse - presence: mandatory - version: "= 1.0" - note: | - Ziccrse is a new extension name introduced with RVA20. - - name: Ziccamoa - presence: mandatory - version: "= 1.0" - note: | - Ziccamo is a new extension name introduced with RVA20. - - name: Za128rs - presence: mandatory - version: "= 1.0" - note: | - Za128rs is a new extension name introduced with RVA20. - The minimum reservation set size is effectively determined by the - size of atomic accesses in the `A` extension. - - name: Zicclsm - presence: mandatory - version: "= 1.0" - note: | - Zicclsm is a new extension name introduced with RVA20. - This requires misaligned support for all regular load and store - instructions (including scalar and vector) but not AMOs or other - specialized forms of memory access. Even though mandated, misaligned - loads and stores might execute extremely slowly. Standard software - distributions should assume their existence only for correctness, not - for performance. - - name: Zihpm - presence: optional - version: "= 2.0" - note: | - The number of counters is platform-specific. - extra_notes: - - presence: optional - text: | - The rationale to not make Q an optional extension is that - quad-precision floating-point is unlikely to be implemented in - hardware, and so we do not require or expect A-profile software to - expend effort optimizing use of Q instructions in case they are - present. - - presence: optional - text: | - Zifencei is not classed as a supported option in the user-mode - profile because it is not sufficient by itself to produce the desired - effect in a multiprogrammed multiprocessor environment without OS - support, and so the instruction cache flush should always be performed - using an OS call rather than using the `fence.i` instruction. - `fence.i` semantics can be expensive to implement for some hardware - memory hierarchy designs, and so alternative non-standard - instruction-cache coherence mechanisms can be used behind the OS - abstraction. A separate extension is being developed for more general - and efficient instruction cache coherence. - - presence: optional - text: | - The execution environment must provide a means to synchronize writes to - instruction memory with instruction fetches, the implementation of which - likely relies on the Zifencei extension. - For example, RISC-V Linux supplies the `__riscv_flush_icache` system call and - a corresponding vDSO call. - recommendations: - - text: | - Implementations are strongly recommended to raise illegal-instruction - exceptions on attempts to execute unimplemented opcodes. \ No newline at end of file diff --git a/arch/profile/rva22s64.yaml b/arch/profile/rva22s64.yaml deleted file mode 100644 index ee4c218efa..0000000000 --- a/arch/profile/rva22s64.yaml +++ /dev/null @@ -1,106 +0,0 @@ - -rva22s64: - family: rva - description: | - The RVA22S64 profile specifies the ISA features available to a - supervisor-mode execution environment in 64-bit applications - processors. RVA22S64 is based on privileged architecture version - 1.12. - version: "2.0" - mode: S - marketing_name: RVA22S64 - contributors: - - name: Krste Asanovic - email: krste@sifive.com - company: SiFive - extensions: - - name: S - presence: mandatory - version: "= 1.12" - - name: Sscounterenw - presence: mandatory - version: "= 1.0" - note: | - Sstvala is a new extension name introduced with RVA22. - - name: Svpbmt - presence: mandatory - version: "~> 1.0" - - name: Svinval - presence: mandatory - version: "~> 1.0" - - name: Ssstateen - presence: mandatory - version: "~> 1.0" - when: - implemented: H - note: | - Ssstateen is a new extension name introduced with RVA22. - - name: Shvstvala - presence: mandatory - version: "~> 1.0" - when: - implemented: H - note: | - Shvstvala is a new extension name introduced with RVA22. - - name: Shtvala - presence: mandatory - version: "~> 1.0" - when: - implemented: H - note: | - Shtvala is a new extension name introduced with RVA22. - - name: Shvstvecd - presence: mandatory - version: "~> 1.0" - when: - implemented: H - note: | - Shvstvecd is a new extension name introduced with RVA22. - - name: Shgatpa - presence: mandatory - version: "~> 1.0" - when: - implemented: H - note: | - Shgatpa is a new extension name introduced with RVA22. - - name: Sv57 - presence: optional - version: "~> 1.12" - - name: Svnapot - presence: optional - version: "~> 1.0" - note: | - It is expected that Svnapot will be mandatory in the next - profile release. - - name: Sstc - presence: optional - version: "~> 1.0" - note: | - Sstc was not made mandatory in RVA22S64 as it is a more - disruptive change affecting system-level architecture, and will take - longer for implementations to adopt. It is expected to be made - mandatory in the next profile release. - - name: Sscofpmf - presence: optional - version: "~> 1.0" - note: | - Platforms may choose to mandate the presence of Sscofpmf. - - name: Zkr - presence: optional - version: "~> 1.0" - note: | - Technically, Zk is also a privileged-mode option capturing that - Zkr, Zkn, and Zkt are all implemented. However, the Zk rollup is less - descriptive than specifying the individual extensions explicitly. - - name: H - presence: optional - version: "~> 1.0" - note: | - The following extensions become mandatory when H is implemented: - - * Ssstateen - * Shcounterenw - * Shvstvala - * Shtvala - * Shvstvecd - * Shgatpa \ No newline at end of file diff --git a/arch/profile/rva22u64.yaml b/arch/profile/rva22u64.yaml deleted file mode 100644 index eebd04ba05..0000000000 --- a/arch/profile/rva22u64.yaml +++ /dev/null @@ -1,128 +0,0 @@ - -rva22u64: - family: rva - description: | - The RVA22U64 profile specifies the ISA features available to user-mode - execution environments in 64-bit applications processors. This is the - most important profile within the application processor family in - terms of the amount of software that targets this profile. - inherits: rva20u64 - version: "2.0" - marketing_name: RVA22U64 - contributors: - - name: Krste Asanovic - email: krste@sifive.com - company: SiFive - extensions: - - name: Zihpm - presence: mandatory - version: "= 2.0" - - name: Zihintpause - presence: mandatory - version: "= 2.0" - note: | - While the `pause` instruction is a HINT can be implemented as a - NOP and hence trivially supported by hardware implementers, its - inclusion in the mandatory extension list signifies that software - should use the instruction whenever it would make sense and that - implementors are expected to exploit this information to optimize - hardware execution. - - name: Zba - presence: mandatory - version: "~> 1.0" - - name: Zbb - presence: mandatory - version: "~> 1.0" - - name: Zbs - presence: mandatory - version: "~> 1.0" - - name: Zic64b - presence: mandatory - version: "= 1.0" - note: | - This is a new extension name for this feature. While the general - RISC-V specifications are agnostic to cache block size, selecting a - common cache block size simplifies the specification and use of the - following cache-block extensions within the application processor - profile. Software does not have to query a discovery mechanism and/or - provide dynamic dispatch to the appropriate code. We choose 64 bytes - at it is effectively an industry standard. Implementations may use - longer cache blocks to reduce tag cost provided they use 64-byte - sub-blocks to remain compatible. Implementations may use shorter cache - blocks provided they sequence cache operations across the multiple - cache blocks comprising a 64-byte block to remain compatible. - - name: Zicbom - presence: mandatory - version: "~> 1.0" - - name: Zicbop - presence: mandatory - version: "~> 1.0" - note: | - As with other HINTS, the inclusion of prefetches in the - mandatory set of extensions indicates that software should generate - these instructions where they are expected to be useful, and hardware - is expected to exploit that information. - - name: Zicboz - presence: mandatory - version: "~> 1.0" - - name: Zfhmin - presence: mandatory - version: "~> 1.0" - note: | - Zfhmin is a small extension that adds support to load/store and convert - IEEE 754 half-precision numbers to and from the IEEE 754 single-precision - format. The hardware cost for this extension is low, and mandating the - extension avoids adding an option to the profile. - - name: Zkt - presence: mandatory - version: "~> 1.0" - note: | - Zkt requires a certain subset of integer instructions execute - with data-independent latency. Mandating this feature enables - portable libraries for safe basic cryptographic operations. It is - expected that application processors will naturally have this property - and so implementation cost is low, if not zero, in most systems that - would support RVA22. - - name: Zfh - presence: optional - version: "~> 1.0" - note: A future profile might mandate V. - - name: V - presence: optional - version: "~> 1.0" - note: | - The smaller vector extensions (Zve32f, Zve32x, Zve64d, Zve64f, - Zve64x) are not provided as separately supported profile options. The - full V extension is specified as the only supported profile option. - - A future profile might mandate V. - - name: Zkn - presence: optional - version: "~> 1.0" - - name: Zks - presence: optional - version: "~> 1.0" - extra_notes: - - presence: optional - text: | - The scalar crypto extensions are expected to be superseded by - vector crypto standards in future profiles, and the scalar extensions - may be removed as supported options once vector crypto is present. - - presence: optional - text: | - The smaller component scalar crypto extensions (Zbc, Zbkb, Zbkc, - Zbkx, Zknd, Zkne, Zknh, Zksed, Zksh) are not provided as separate - options in the profile. Profile implementers should provide all of - the instructions in a given algorithm suite as part of the Zkn or Zks - supported options. - - presence: optional - text: | - Access to the entropy source (Zkr) in a system is usually - carefully controlled. While the design supports unprivileged access - to the entropy source, this is unlikely to be commonly used in an - application processor, and so Zkr was not added as a profile option. - This also means the roll-up Zk was not added as a profile option. - - presence: optional - text: | - The Zfinx, Zdinx, Zhinx, Zhinxmin extensions are incompatible - with the profile mandates to support the F and D extensions. \ No newline at end of file diff --git a/arch/profile_class/MockProfileClass.yaml b/arch/profile_class/MockProfileClass.yaml new file mode 100644 index 0000000000..d7f2af6e7e --- /dev/null +++ b/arch/profile_class/MockProfileClass.yaml @@ -0,0 +1,15 @@ +MockProfileClass: + marketing_name: Mock Profile Class + introduction: Here's the Mock Profile Class introduction. + description: | + This is the Mock Profile Class description. + It can be longer than the introduction since it gets its own sub-heading. + naming_scheme: | + Here's the Mock Profile Class naming scheme. + company: + name: RISC-V International + url: https://riscv.org + doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ + text_url: https://creativecommons.org/licenses/by/4.0/legalcode.txt \ No newline at end of file diff --git a/arch/profile_class/RVA.yaml b/arch/profile_class/RVA.yaml new file mode 100644 index 0000000000..c74e167032 --- /dev/null +++ b/arch/profile_class/RVA.yaml @@ -0,0 +1,28 @@ +RVA: + marketing_name: RVA + introduction: | + The RVA profile class targets application processors for markets + requiring a high-degree of binary compatibility between compliant implementations. + description: | + The RVA profile class is intended to be used for 64-bit application + processors running rich OS stacks. Only user-mode and + supervisor-mode profiles are specified in this class. + naming_scheme: | + The profile class name is RVA (RISC-V Apps processor). + A profile release name is an integer (currently 2 digits, could grow in the future). + A full profile name is comprised of, in order: + + * Prefix *RVA* for RISC-V Applications + * Profile release + * Privilege mode: + ** *U* Unprivileged (available to any privilege mode, *U* is *not* User-mode) + ** *S* Supervisor mode (note that Hypervisor support is treated as an option) + ** *M* Machine mode + * A base ISA XLEN specifier (*32*, *64*) + company: + name: RISC-V International + url: https://riscv.org + doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ + text_url: https://creativecommons.org/licenses/by/4.0/legalcode.txt \ No newline at end of file diff --git a/arch/profile_class/RVB.yaml b/arch/profile_class/RVB.yaml new file mode 100644 index 0000000000..f9529ef1db --- /dev/null +++ b/arch/profile_class/RVB.yaml @@ -0,0 +1,50 @@ +RVB: + marketing_name: RVB + introduction: | + The RVB profile class targets application processors for markets + running Bespoke (AKA custom, AKA Yocto) Linux Operating Systems + in embedded applications. + description: | + The RVB profile class is intended to be used for 64-bit application + processors running rich OS stacks. Only user-mode and + supervisor-mode profiles are specified in this class. + + NOTE: There is no machine-mode profile currently defined for RVB. + A machine-mode profile for application processors would only be used in specifying platforms for + portable machine-mode software. Given the relatively low volume of + portable M-mode software in this domain, the wide variety of potential + M-mode code, and the very specific needs of each type of M-mode + software, we are not specifying individual M-mode ISA requirements in + the RVB profiles. + + NOTE: Only XLEN=64 application processor profiles are currently + defined. It would be possible to also define very similar XLEN=32 + variants. + naming_scheme: | + The profile class name is RVB (RISC-V Bespoke processor). + A profile release name is a integer (currently 2 digits, could grow in the future). + A full profile name is comprised of, in order: + + * Prefix *RVB* for RISC-V Bespoke + * Profile release + * Privilege mode: + ** *U* Unprivileged (available to any privilege mode, *U* is *not* User-mode) + ** *S* Supervisor mode (note that Hypervisor support is treated as an option) + ** *M* Machine mode + * A base ISA XLEN specifier (*32*, *64*) + + The initial profiles based on specifications ratified in 2024 are: + + * RVB23U64, RVB23S64 64-bit application-processor profiles + + NOTE: Profile names are embeddable into RISC-V ISA naming strings. + This implies that there will be no standard ISA extension with a name + that matches the profile naming convention. This allows tools that + process the RISC-V ISA naming string to parse and/or process a combined string. + company: + name: RISC-V International + url: https://riscv.org + doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ + text_url: https://creativecommons.org/licenses/by/4.0/legalcode.txt \ No newline at end of file diff --git a/arch/profile_class/RVI.yaml b/arch/profile_class/RVI.yaml new file mode 100644 index 0000000000..ed900ef3d5 --- /dev/null +++ b/arch/profile_class/RVI.yaml @@ -0,0 +1,28 @@ +RVI: + marketing_name: RVI + introduction: The RVI profile class documents the initial set of unprivileged instructions. + description: | + The RVI profile class provides a generic target for software toolchains + and represent the minimum level of compatibility with RISC-V ratified standards. + + NOTE: Profiles in this class are designated as _unprivileged_ profiles as opposed to + _user_-_mode_ profiles. Code using this profile class can run in any + privilege mode, and so requested and fatal traps may be horizontal + traps into an execution environment running in the same privilege mode. + naming_scheme: | + The profile class name is RVI (RISC-V base Integer instructions). + A profile release name is an integer (currently 2 digits, could grow in the future). + A full profile name is comprised of, in order: + + * Prefix *RVI* for RISC-V Integer + * Profile release + * Privilege mode: + ** *U* Unprivileged (available to any privilege mode, *U* is *not* User-mode) + * A base ISA XLEN specifier (*32*, *64*) + company: + name: RISC-V International + url: https://riscv.org + doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ + text_url: https://creativecommons.org/licenses/by/4.0/legalcode.txt \ No newline at end of file diff --git a/arch/profile_family/MockProfileFamily.yaml b/arch/profile_family/MockProfileFamily.yaml deleted file mode 100644 index 43c3eb58b7..0000000000 --- a/arch/profile_family/MockProfileFamily.yaml +++ /dev/null @@ -1,15 +0,0 @@ - -MockProfileFamily: - marketing_name: Mock Profile Family - description: This is the Mock Profile Family description. - company: - name: RISC-V International - url: https://riscv.org - doc_license: - name: Creative Commons Attribution 4.0 International License - url: https://creativecommons.org/licenses/by/4.0/ - text_url: https://creativecommons.org/licenses/by/4.0/legalcode.txt - introduction: | - Here's the Mock Profile Family's introduction. - naming_scheme: | - Here's the Mock Profile Family's naming scheme. \ No newline at end of file diff --git a/arch/profile_family/rva.yaml b/arch/profile_family/rva.yaml deleted file mode 100644 index 1ebf2fd411..0000000000 --- a/arch/profile_family/rva.yaml +++ /dev/null @@ -1,49 +0,0 @@ - -rva: - marketing_name: RVA - introduction: | - The RVA profiles target application processors for markets - requiring a high-degree of binary compatibility between compliant implementations. - description: | - The RVA profiles are intended to be used for 64-bit application - processors running rich OS stacks. Only user-mode and - supervisor-mode profiles are specified in this family. - - NOTE: There is no machine-mode profile currently defined for - application processor families. A machine-mode profile for - application processors would only be used in specifying platforms for - portable machine-mode software. Given the relatively low volume of - portable M-mode software in this domain, the wide variety of potential - M-mode code, and the very specific needs of each type of M-mode - software, we are not specifying individual M-mode ISA requirements in - the A-family profiles. - - NOTE: Only XLEN=64 application processor profiles are currently - defined. It would be possible to also define very similar XLEN=32 - variants. - naming_scheme: | - A profile name is a string comprised of, in order: - - * Prefix *RV* for RISC-V. - * A specific profile family name string. Initially a single letter (*I*, *M*, or *A*), but later profiles may have longer family name strings. - * A numeric string giving the first complete calendar year for which the profile is ratified, represented as number of years after year 2000, i.e., *20* for profiles built on specifications ratified during 2019. The year string will be longer than two digits in the next century. - * A privilege mode (*U*, *S*, *M*). Hypervisor support is treated as an option. - * A base ISA XLEN specifier (*32*, *64*). - - The initial profiles based on specifications ratified in 2019 are: - - * RVI20U32 basic unprivileged instructions for RV32I - * RVI20U64 basic unprivileged instructions for RV64I - * RVA20U64, RVA20S64 64-bit application-processor profiles - - NOTE: Profile names are embeddable into RISC-V ISA naming strings. - This implies that there will be no standard ISA extension with a name - that matches the profile naming convention. This allows tools that - process the RISC-V ISA naming string to parse and/or process a combined string. - company: - name: RISC-V International - url: https://riscv.org - doc_license: - name: Creative Commons Attribution 4.0 International License - url: https://creativecommons.org/licenses/by/4.0/ - text_url: https://creativecommons.org/licenses/by/4.0/legalcode.txt diff --git a/arch/profile_release/MockProfileRelease.yaml b/arch/profile_release/MockProfileRelease.yaml new file mode 100644 index 0000000000..21bbd9e1e5 --- /dev/null +++ b/arch/profile_release/MockProfileRelease.yaml @@ -0,0 +1,72 @@ +MockProfileRelease: + name: MockProfileRelease + marketing_name: MockProfileRelease Marketing Name + class: MockProfileClass + release: 20 + state: ratified # current status ["ratified", "development"] + versions: + - version: "1.0" + ratification_date: "2024-01-01" + introduction: Here's the Mock Profile Release introduction. + description: | + This is the Mock Profile Release description. + It can be longer than the introduction since it gets its own sub-heading. + contributors: + - name: Joe Blow + email: joe.blow@riscv.org + company: Acme Inc + - name: Jane Doe + email: jane.doe@gmail.com + company: Universal Imports + profiles: + - name: MockProfileUnpriv + marketing_name: MPUnpriv64 + mode: Unpriv + base: 64 + release: MockProfileRelease + extensions: + - name: I + presence: mandatory + version: "~> 2.1" + - name: MockProfileSuper + marketing_name: MPS64 + description: This is the Mock Profile Supervisor Mode description. + mode: S + base: 64 + release: MockProfileRelease + contributors: + - name: Micky Mouse + email: micky@disney.com + company: Disneyk + extensions: + - name: S + presence: mandatory + version: "= 1.11" + - name: Zifencei + presence: mandatory + version: "= 2.0" + note: | + Zifencei is mandated as it is the only standard way to support + instruction-cache coherence in RVA20 application processors. A new + instruction-cache coherence mechanism is under development which might + be added as an option in the future. + - name: Zihpm + presence: optional + version: "= 2.0" + - name: Sv48 + presence: optional + version: "= 1.11" + extra_notes: + - presence: optional + text: Here's the first extra note for the optional extensions section. + - presence: mandatory + text: | + Here's the first extra note for the mandatory extensions section. + This note is multiple lines. + - presence: optional + text: Here's the second extra note for the optional extensions section. + recommendations: + - text: | + Implementations are strongly recommended to raise illegal-instruction + exceptions on attempts to execute unimplemented opcodes. + - text: Micky should give Pluto an extra treat \ No newline at end of file diff --git a/arch/profile_release/RVA20.yaml b/arch/profile_release/RVA20.yaml new file mode 100644 index 0000000000..5bf1c063f2 --- /dev/null +++ b/arch/profile_release/RVA20.yaml @@ -0,0 +1,221 @@ +RVA20: + name: RVA20 + marketing_name: RVA20 + class: RVA + release: 20 + state: ratified # current status ["ratified", "development"] + ratification_date: "2023-04-03" + + # Semantic versions within the release + versions: + - version: "1.0.0" + + introduction: | + This profile release targets 64-bit application processors for markets + requiring a high-degree of binary compatibility between compliant implementations. + description: | + This profile release is intended to be used for 64-bit application + processors running rich OS stacks. Only user-mode and + supervisor-mode profiles are specified in this release. + + NOTE: There is no machine-mode profile currently defined for this release. + A machine-mode profile for application processors would only be used in specifying platforms for + portable machine-mode software. Given the relatively low volume of + portable M-mode software in this domain, the wide variety of potential + M-mode code, and the very specific needs of each type of M-mode + software, we are not specifying individual M-mode ISA requirements in this release. + + NOTE: Only XLEN=64 application processor profiles are currently defined. + It would be possible to also define very similar XLEN=32 variants. + contributors: + - name: Krste Asanovic + email: krste@sifive.com + company: SiFive + profiles: + - name: RVA20U64 + marketing_name: RVA20U64 + mode: Unpriv + base: 64 + release: RVA20 + introduction: | + The RVA20U64 profile specifies the ISA features available to user-mode + execution environments in 64-bit applications processors. This is the + most important profile within application processors in + terms of the amount of software that targets this profile. + extensions: + - name: I + presence: mandatory + version: "~> 2.1" + note: | + RVI is the mandatory base ISA for RVA, and is little-endian. + + As per the unprivileged architecture specification, the `ecall` + instruction causes a requested trap to the execution environment. + + The `fence.tso` instruction is mandatory. + + NOTE: The `fence.tso` instruction was incorrectly described as + optional in the 2019 ratified specifications. However, `fence.tso` is + encoded within the standard `fence` encoding such that implementations + must treat it as a simple global fence if they do not natively support + TSO-ordering optimizations. As software can always assume without any + penalty that `fence.tso` is being exploited by a hardware + implementation, there is no advantage to making the instruction a + profile option. Later versions of the unprivileged ISA + specifications correctly indicate that `fence.tso` is mandatory. + - name: A + presence: mandatory + version: "= 2.1" + - name: C + presence: mandatory + version: "= 2.2" + - name: D + presence: mandatory + version: "= 2.2" + - name: F + presence: mandatory + version: "= 2.2" + - name: M + presence: mandatory + version: "= 2.0" + - name: U + presence: mandatory + version: "~> 2.0" + param_constraints: + U_MODE_ENDIANESS: + schema: + const: little + - name: Zicntr + presence: mandatory + version: " = 2.0" + - name: Ziccif + presence: mandatory + version: "= 1.0" + note: | + Ziccif is a new extension name introduced with RVA20. + The fetch atomicity requirement facilitates runtime patching + of aligned instructions. + - name: Ziccrse + presence: mandatory + version: "= 1.0" + note: | + Ziccrse is a new extension name introduced with RVA20. + - name: Ziccamoa + presence: mandatory + version: "= 1.0" + note: | + Ziccamo is a new extension name introduced with RVA20. + - name: Za128rs + presence: mandatory + version: "= 1.0" + note: | + Za128rs is a new extension name introduced with RVA20. + The minimum reservation set size is effectively determined by the + size of atomic accesses in the `A` extension. + - name: Zicclsm + presence: mandatory + version: "= 1.0" + note: | + Zicclsm is a new extension name introduced with RVA20. + This requires misaligned support for all regular load and store + instructions (including scalar and vector) but not AMOs or other + specialized forms of memory access. Even though mandated, misaligned + loads and stores might execute extremely slowly. Standard software + distributions should assume their existence only for correctness, not + for performance. + - name: Zihpm + presence: optional + version: "= 2.0" + note: | + The number of counters is platform-specific. + extra_notes: + - presence: optional + text: | + The rationale to not make Q an optional extension is that + quad-precision floating-point is unlikely to be implemented in + hardware, and so we do not require or expect A-profile software to + expend effort optimizing use of Q instructions in case they are + present. + - presence: optional + text: | + Zifencei is not classed as a supported option in the user-mode + profile because it is not sufficient by itself to produce the desired + effect in a multiprogrammed multiprocessor environment without OS + support, and so the instruction cache flush should always be performed + using an OS call rather than using the `fence.i` instruction. + `fence.i` semantics can be expensive to implement for some hardware + memory hierarchy designs, and so alternative non-standard + instruction-cache coherence mechanisms can be used behind the OS + abstraction. A separate extension is being developed for more general + and efficient instruction cache coherence. + - presence: optional + text: | + The execution environment must provide a means to synchronize writes to + instruction memory with instruction fetches, the implementation of which + likely relies on the Zifencei extension. + For example, RISC-V Linux supplies the `__riscv_flush_icache` system call and + a corresponding vDSO call. + recommendations: + - text: | + Implementations are strongly recommended to raise illegal-instruction + exceptions on attempts to execute unimplemented opcodes. + - name: RVA20S64 + marketing_name: RVA20S64 + mode: S + base: 64 + release: RVA20 + introduction: | + The RVA20S64 profile specifies the ISA features available to a + supervisor-mode execution environment in 64-bit applications + processors. RVA20S64 is based on privileged architecture version 1.11. + extensions: + - name: S + presence: mandatory + version: "= 1.11" + - name: Zifencei + presence: mandatory + version: "= 2.0" + note: | + Zifencei is mandated as it is the only standard way to support + instruction-cache coherence in RVA20 application processors. A new + instruction-cache coherence mechanism is under development which might + be added as an option in the future. + - name: Svbare + presence: mandatory + version: "= 1.0" + note: | + Svbare is a new extension name introduced with RVA20. + - name: Sv39 + presence: mandatory + version: "= 1.11" + - name: Svade + presence: mandatory + version: "~> 1.0" + note: | + Svbare is a new extension name introduced with RVA20. + + It is subsequently defined in more detail with the ratification of + `Svadu`. + - name: Ssccptr + presence: mandatory + version: "= 1.0" + note: | + Ssccptr is a new extension name introduced with RVA20. + - name: Sstvecd + presence: mandatory + version: "= 1.0" + note: | + Sstvecd is a new extension name introduced with RVA20. + - name: Sstvala + presence: mandatory + version: "= 1.0" + note: | + Sstvala is a new extension name introduced with RVA20. + - name: Sv48 + presence: optional + version: "= 1.11" + - name: Ssu64xl + presence: optional + version: "= 1.0" + note: | + Ssu64xl is a new extension name introduced with RVA20. \ No newline at end of file diff --git a/arch/profile_release/RVA22.yaml b/arch/profile_release/RVA22.yaml new file mode 100644 index 0000000000..fd4533c0ef --- /dev/null +++ b/arch/profile_release/RVA22.yaml @@ -0,0 +1,258 @@ +RVA22: + name: RVA22 + marketing_name: RVA22 + class: RVA + release: 22 + state: ratified # current status ["ratified", "development"] + ratification_date: "2023-04-03" + + # Semantic versions within the release + versions: + - version: "1.0.0" + + introduction: | + This profile release targets 64-bit application processors for markets + requiring a high-degree of binary compatibility between compliant implementations. + description: | + This profile release is intended to be used for 64-bit application + processors running rich OS stacks. Only user-mode and + supervisor-mode profiles are specified in this release. + + NOTE: There is no machine-mode profile currently defined for this release. + A machine-mode profile for application processors would only be used in specifying platforms for + portable machine-mode software. Given the relatively low volume of + portable M-mode software in this domain, the wide variety of potential + M-mode code, and the very specific needs of each type of M-mode + software, we are not specifying individual M-mode ISA requirements in this release. + + NOTE: Only XLEN=64 application processor profiles are currently defined. + It would be possible to also define very similar XLEN=32 variants. + contributors: + - name: Krste Asanovic + email: krste@sifive.com + company: SiFive + profiles: + - name: RVA22U64 + marketing_name: RVA22U64 + mode: Unpriv + base: 64 + release: RVA22 + introduction: | + The RVA22U64 profile specifies the ISA features available to user-mode + execution environments in 64-bit applications processors. This is the + most important profile within application processors in + terms of the amount of software that targets this profile. + extensions: + - name: Zihpm + presence: mandatory + version: "= 2.0" + - name: Zihintpause + presence: mandatory + version: "= 2.0" + note: | + While the `pause` instruction is a HINT can be implemented as a + NOP and hence trivially supported by hardware implementers, its + inclusion in the mandatory extension list signifies that software + should use the instruction whenever it would make sense and that + implementors are expected to exploit this information to optimize + hardware execution. + - name: Zba + presence: mandatory + version: "~> 1.0" + - name: Zbb + presence: mandatory + version: "~> 1.0" + - name: Zbs + presence: mandatory + version: "~> 1.0" + - name: Zic64b + presence: mandatory + version: "= 1.0" + note: | + This is a new extension name for this feature. While the general + RISC-V specifications are agnostic to cache block size, selecting a + common cache block size simplifies the specification and use of the + following cache-block extensions within the application processor + profile. Software does not have to query a discovery mechanism and/or + provide dynamic dispatch to the appropriate code. We choose 64 bytes + at it is effectively an industry standard. Implementations may use + longer cache blocks to reduce tag cost provided they use 64-byte + sub-blocks to remain compatible. Implementations may use shorter cache + blocks provided they sequence cache operations across the multiple + cache blocks comprising a 64-byte block to remain compatible. + - name: Zicbom + presence: mandatory + version: "~> 1.0" + - name: Zicbop + presence: mandatory + version: "~> 1.0" + note: | + As with other HINTS, the inclusion of prefetches in the + mandatory set of extensions indicates that software should generate + these instructions where they are expected to be useful, and hardware + is expected to exploit that information. + - name: Zicboz + presence: mandatory + version: "~> 1.0" + - name: Zfhmin + presence: mandatory + version: "~> 1.0" + note: | + Zfhmin is a small extension that adds support to load/store and convert + IEEE 754 half-precision numbers to and from the IEEE 754 single-precision + format. The hardware cost for this extension is low, and mandating the + extension avoids adding an option to the profile. + - name: Zkt + presence: mandatory + version: "~> 1.0" + note: | + Zkt requires a certain subset of integer instructions execute + with data-independent latency. Mandating this feature enables + portable libraries for safe basic cryptographic operations. It is + expected that application processors will naturally have this property + and so implementation cost is low, if not zero, in most systems that + would support RVA22. + - name: Zfh + presence: optional + version: "~> 1.0" + note: A future profile might mandate V. + - name: V + presence: optional + version: "~> 1.0" + note: | + The smaller vector extensions (Zve32f, Zve32x, Zve64d, Zve64f, + Zve64x) are not provided as separately supported profile options. The + full V extension is specified as the only supported profile option. + + A future profile might mandate V. + - name: Zkn + presence: optional + version: "~> 1.0" + - name: Zks + presence: optional + version: "~> 1.0" + extra_notes: + - presence: optional + text: | + The scalar crypto extensions are expected to be superseded by + vector crypto standards in future profiles, and the scalar extensions + may be removed as supported options once vector crypto is present. + - presence: optional + text: | + The smaller component scalar crypto extensions (Zbc, Zbkb, Zbkc, + Zbkx, Zknd, Zkne, Zknh, Zksed, Zksh) are not provided as separate + options in the profile. Profile implementers should provide all of + the instructions in a given algorithm suite as part of the Zkn or Zks + supported options. + - presence: optional + text: | + Access to the entropy source (Zkr) in a system is usually + carefully controlled. While the design supports unprivileged access + to the entropy source, this is unlikely to be commonly used in an + application processor, and so Zkr was not added as a profile option. + This also means the roll-up Zk was not added as a profile option. + - presence: optional + text: | + The Zfinx, Zdinx, Zhinx, Zhinxmin extensions are incompatible + with the profile mandates to support the F and D extensions. + - name: RVA22S64 + marketing_name: RVA22S64 + mode: S + base: 64 + release: RVA22 + introduction: | + The RVA22S64 profile specifies the ISA features available to a + supervisor-mode execution environment in 64-bit applications + processors. RVA22S64 is based on privileged architecture version + 1.12. + extensions: + - name: S + presence: mandatory + version: "= 1.12" + - name: Sscounterenw + presence: mandatory + version: "= 1.0" + note: | + Sstvala is a new extension name introduced with RVA22. + - name: Svpbmt + presence: mandatory + version: "~> 1.0" + - name: Svinval + presence: mandatory + version: "~> 1.0" + - name: Ssstateen + presence: mandatory + version: "~> 1.0" + when: + implemented: H + note: | + Ssstateen is a new extension name introduced with RVA22. + - name: Shvstvala + presence: mandatory + version: "~> 1.0" + when: + implemented: H + note: | + Shvstvala is a new extension name introduced with RVA22. + - name: Shtvala + presence: mandatory + version: "~> 1.0" + when: + implemented: H + note: | + Shtvala is a new extension name introduced with RVA22. + - name: Shvstvecd + presence: mandatory + version: "~> 1.0" + when: + implemented: H + note: | + Shvstvecd is a new extension name introduced with RVA22. + - name: Shgatpa + presence: mandatory + version: "~> 1.0" + when: + implemented: H + note: | + Shgatpa is a new extension name introduced with RVA22. + - name: Sv57 + presence: optional + version: "~> 1.12" + - name: Svnapot + presence: optional + version: "~> 1.0" + note: | + It is expected that Svnapot will be mandatory in the next + profile release. + - name: Sstc + presence: optional + version: "~> 1.0" + note: | + Sstc was not made mandatory in RVA22S64 as it is a more + disruptive change affecting system-level architecture, and will take + longer for implementations to adopt. It is expected to be made + mandatory in the next profile release. + - name: Sscofpmf + presence: optional + version: "~> 1.0" + note: | + Platforms may choose to mandate the presence of Sscofpmf. + - name: Zkr + presence: optional + version: "~> 1.0" + note: | + Technically, Zk is also a privileged-mode option capturing that + Zkr, Zkn, and Zkt are all implemented. However, the Zk rollup is less + descriptive than specifying the individual extensions explicitly. + - name: H + presence: optional + version: "~> 1.0" + note: | + The following extensions become mandatory when H is implemented: + + * Ssstateen + * Shcounterenw + * Shvstvala + * Shtvala + * Shvstvecd + * Shgatpa \ No newline at end of file diff --git a/arch/profile_release/RVI20.yaml b/arch/profile_release/RVI20.yaml new file mode 100644 index 0000000000..1269cda4e6 --- /dev/null +++ b/arch/profile_release/RVI20.yaml @@ -0,0 +1,151 @@ +RVI20: + name: RVI20 + marketing_name: RVI20 + class: RVI + release: 20 + state: ratified # current status ["ratified", "development"] + ratification_date: "2023-04-03" + + # Semantic versions within the release + versions: + - version: "1.0.0" + + introduction: | + The two profiles RVI20U32 and RVI20U64 correspond to the RV32I and RV64I base ISAs respectively. + contributors: + - name: Krste Asanovic + email: krste@sifive.com + company: SiFive + profiles: + - name: RVI20U32 + marketing_name: RVI20U32 + mode: Unpriv + base: 32 + release: RVI20 + introduction: | + RVI20U32 specifies the ISA features available to generic unprivileged + execution environments. + extensions: + - name: I + presence: mandatory + version: "~> 2.1" + note: | + RVI is the mandatory base ISA for RVA, and is little-endian. + + As per the unprivileged architecture specification, the `ecall` + instruction causes a requested trap to the execution environment. + + Misaligned loads and stores might not be supported. + + The `fence.tso` instruction is mandatory. + + NOTE: The `fence.tso` instruction was incorrectly described as + optional in the 2019 ratified specifications. However, `fence.tso` is + encoded within the standard `fence` encoding such that implementations + must treat it as a simple global fence if they do not natively support + TSO-ordering optimizations. As software can always assume without any + penalty that `fence.tso` is being exploited by a hardware + implementation, there is no advantage to making the instruction a + profile option. Later versions of the unprivileged ISA specifications + correctly indicate that `fence.tso` is mandatory. + + - name: A + presence: optional + version: "= 2.1" + - name: C + presence: optional + version: "= 2.2" + - name: D + presence: optional + version: "= 2.2" + note: | + NOTE: The rationale to not include Q as a profile option is that + quad-precision floating-point is unlikely to be implemented in + hardware, and so we do not require or expect software to expend effort + optimizing use of Q instructions in case they are present. + - name: F + presence: optional + version: "= 2.2" + - name: M + presence: optional + version: "= 2.0" + - name: Zicntr + presence: optional + version: " = 2.0" + - name: Zihpm + presence: optional + version: "= 2.0" + note: | + The number of counters is platform-specific. + - name: Zifencei + presence: optional + recommendations: + - text: | + Implementations are strongly recommended to raise illegal-instruction + exceptions on attempts to execute unimplemented opcodes. + - name: RVI20U64 + marketing_name: RVI20U64 + mode: Unpriv + base: 64 + release: RVI20 + introduction: | + RVI20U64 specifies the ISA features available to generic unprivileged + execution environments. + extensions: + - name: I + presence: mandatory + version: "~> 2.1" + note: | + RVI is the mandatory base ISA for RVA, and is little-endian. + + As per the unprivileged architecture specification, the `ecall` + instruction causes a requested trap to the execution environment. + + Misaligned loads and stores might not be supported. + + The `fence.tso` instruction is mandatory. + + NOTE: The `fence.tso` instruction was incorrectly described as + optional in the 2019 ratified specifications. However, `fence.tso` is + encoded within the standard `fence` encoding such that implementations + must treat it as a simple global fence if they do not natively support + TSO-ordering optimizations. As software can always assume without any + penalty that `fence.tso` is being exploited by a hardware + implementation, there is no advantage to making the instruction a + profile option. Later versions of the unprivileged ISA specifications + correctly indicate that `fence.tso` is mandatory. + + - name: A + presence: optional + version: "= 2.1" + - name: C + presence: optional + version: "= 2.2" + - name: D + presence: optional + version: "= 2.2" + note: | + NOTE: The rationale to not include Q as a profile option is that + quad-precision floating-point is unlikely to be implemented in + hardware, and so we do not require or expect software to expend effort + optimizing use of Q instructions in case they are present. + - name: F + presence: optional + version: "= 2.2" + - name: M + presence: optional + version: "= 2.0" + - name: Zicntr + presence: optional + version: " = 2.0" + - name: Zihpm + presence: optional + version: "= 2.0" + note: | + The number of counters is platform-specific. + - name: Zifencei + presence: optional + recommendations: + - text: | + Implementations are strongly recommended to raise illegal-instruction + exceptions on attempts to execute unimplemented opcodes. \ 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 1c03e9b351..8f38fb33b9 100644 --- a/backends/arch_gen/lib/arch_gen.rb +++ b/backends/arch_gen/lib/arch_gen.rb @@ -289,19 +289,33 @@ def gen_arch_def ext_name = ext_obj.keys[0] [ext_name, ext_obj[ext_name]] end.to_h - profile_family_hash = Dir.glob($root / "arch" / "profile_family" / "**" / "*.yaml").map do |f| - profile_obj = YAML.load_file(f) - profile_name = profile_obj.keys[0] - profile_obj[profile_name]["name"] = profile_name - profile_obj[profile_name]["__source"] = f - [profile_name, profile_obj[profile_name]] + profile_class_hash = Dir.glob($root / "arch" / "profile_class" / "**" / "*.yaml").map do |f| + profile_class_obj = YAML.load_file(f, permitted_classes: [Date]) + profile_class_name = profile_class_obj.keys[0] + profile_class_obj[profile_class_name]["name"] = profile_class_name + profile_class_obj[profile_class_name]["__source"] = f + [profile_class_name, profile_class_obj[profile_class_name]] end.to_h - profile_hash = Dir.glob($root / "arch" / "profile" / "**" / "*.yaml").map do |f| - profile_obj = YAML.load_file(f) - profile_name = profile_obj.keys[0] - profile_obj[profile_name]["name"] = profile_name - profile_obj[profile_name]["__source"] = f - [profile_name, profile_obj[profile_name]] + profile_release_hash = Dir.glob($root / "arch" / "profile_release" / "**" / "*.yaml").map do |f| + profile_release_obj = YAML.load_file(f, permitted_classes: [Date]) + profile_release_name = profile_release_obj.keys[0] + profile_release_obj[profile_release_name]["name"] = profile_release_name + profile_release_obj[profile_release_name]["__source"] = f + [profile_release_name, profile_release_obj[profile_release_name]] + end.to_h + cert_class_hash = Dir.glob($root / "arch" / "certificate_class" / "**" / "*.yaml").map do |f| + cert_class_obj = YAML.load_file(f, permitted_classes: [Date]) + cert_class_name = cert_class_obj.keys[0] + cert_class_obj[cert_class_name]["name"] = cert_class_name + cert_class_obj[cert_class_name]["__source"] = f + [cert_class_name, cert_class_obj[cert_class_name]] + end.to_h + cert_model_hash = Dir.glob($root / "arch" / "certificate_model" / "**" / "*.yaml").map do |f| + cert_model_obj = YAML.load_file(f, permitted_classes: [Date]) + cert_model_name = cert_model_obj.keys[0] + cert_model_obj[cert_model_name]["name"] = cert_model_name + cert_model_obj[cert_model_name]["__source"] = f + [cert_model_name, cert_model_obj[cert_model_name]] end.to_h manual_hash = {} Dir.glob($root / "arch" / "manual" / "**" / "contents.yaml").map do |f| @@ -323,20 +337,6 @@ def gen_arch_def # TODO: schema validation manual_hash[manual_id]["versions"].last["__source"] = f end - crd_family_hash = Dir.glob($root / "arch" / "crd_family" / "**" / "*.yaml").map do |f| - family_obj = YAML.load_file(f, permitted_classes: [Date]) - family_name = family_obj.keys[0] - family_obj[family_name]["name"] = family_name - family_obj[family_name]["__source"] = f - [family_name, family_obj[family_name]] - end.to_h - crd_hash = Dir.glob($root / "arch" / "crd" / "**" / "*.yaml").map do |f| - crd_obj = YAML.load_file(f, permitted_classes: [Date]) - crd_name = crd_obj.keys[0] - crd_obj[crd_name]["name"] = crd_name - crd_obj[crd_name]["__source"] = f - [crd_name, crd_obj[crd_name]] - end.to_h arch_def = { "type" => @cfg_opts["type"], @@ -347,11 +347,11 @@ def gen_arch_def "implemented_extensions" => @implemented_extensions, "csrs" => csr_hash, "implemented_csrs" => @implemented_csrs, - "profile_families" => profile_family_hash, - "profiles" => profile_hash, - "manuals" => manual_hash, - "crd_families" => crd_family_hash, - "crds" => crd_hash + "profile_classes" => profile_class_hash, + "profile_releases" => profile_release_hash, + "certificate_classes" => cert_class_hash, + "certificate_models" => cert_model_hash, + "manuals" => manual_hash } yaml = YAML.dump(arch_def) diff --git a/backends/arch_gen/tasks.rake b/backends/arch_gen/tasks.rake index 7a0a3e373a..3f41cefa59 100644 --- a/backends/arch_gen/tasks.rake +++ b/backends/arch_gen/tasks.rake @@ -57,19 +57,33 @@ file "#{$root}/.stamps/arch-gen.stamp" => ( ext_obj[ext_name]["__source"] = f [ext_name, ext_obj[ext_name]] end.to_h - profile_family_hash = Dir.glob($root / "arch" / "profile_family" / "**" / "*.yaml").map do |f| - profile_obj = YAML.load_file(f) - profile_name = profile_obj.keys[0] - profile_obj[profile_name]["name"] = profile_name - profile_obj[profile_name]["__source"] = f - [profile_name, profile_obj[profile_name]] + profile_class_hash = Dir.glob($root / "arch" / "profile_class" / "**" / "*.yaml").map do |f| + profile_class_obj = YAML.load_file(f, permitted_classes: [Date]) + profile_class_name = profile_class_obj.keys[0] + profile_class_obj[profile_class_name]["name"] = profile_class_name + profile_class_obj[profile_class_name]["__source"] = f + [profile_class_name, profile_class_obj[profile_class_name]] end.to_h - profile_hash = Dir.glob($root / "arch" / "profile" / "**" / "*.yaml").map do |f| - profile_obj = YAML.load_file(f) - profile_name = profile_obj.keys[0] - profile_obj[profile_name]["name"] = profile_name - profile_obj[profile_name]["__source"] = f - [profile_name, profile_obj[profile_name]] + profile_release_hash = Dir.glob($root / "arch" / "profile_release" / "**" / "*.yaml").map do |f| + profile_release_obj = YAML.load_file(f, permitted_classes: [Date]) + profile_release_name = profile_release_obj.keys[0] + profile_release_obj[profile_release_name]["name"] = profile_release_name + profile_release_obj[profile_release_name]["__source"] = f + [profile_release_name, profile_release_obj[profile_release_name]] + end.to_h + cert_class_hash = Dir.glob($root / "arch" / "certificate_class" / "**" / "*.yaml").map do |f| + cert_class_obj = YAML.load_file(f, permitted_classes: [Date]) + cert_class_name = cert_class_obj.keys[0] + cert_class_obj[cert_class_name]["name"] = cert_class_name + cert_class_obj[cert_class_name]["__source"] = f + [cert_class_name, cert_class_obj[cert_class_name]] + end.to_h + cert_model_hash = Dir.glob($root / "arch" / "certificate_model" / "**" / "*.yaml").map do |f| + cert_model_obj = YAML.load_file(f, permitted_classes: [Date]) + cert_model_name = cert_model_obj.keys[0] + cert_model_obj[cert_model_name]["name"] = cert_model_name + cert_model_obj[cert_model_name]["__source"] = f + [cert_model_name, cert_model_obj[cert_model_name]] end.to_h manual_hash = {} Dir.glob($root / "arch" / "manual" / "**" / "contents.yaml").map do |f| @@ -91,31 +105,17 @@ file "#{$root}/.stamps/arch-gen.stamp" => ( # TODO: schema validation manual_hash[manual_id]["versions"].last["__source"] = f end - crd_family_hash = Dir.glob($root / "arch" / "crd_family" / "**" / "*.yaml").map do |f| - family_obj = YAML.load_file(f, permitted_classes: [Date]) - family_name = family_obj.keys[0] - family_obj[family_name]["name"] = family_name - family_obj[family_name]["__source"] = f - [family_name, family_obj[family_name]] - end.to_h - crd_hash = Dir.glob($root / "arch" / "crd" / "**" / "*.yaml").map do |f| - crd_obj = YAML.load_file(f, permitted_classes: [Date]) - crd_name = crd_obj.keys[0] - crd_obj[crd_name]["name"] = crd_name - crd_obj[crd_name]["__source"] = f - [crd_name, crd_obj[crd_name]] - end.to_h arch_def = { "type" => "unconfigured", "instructions" => inst_hash, "extensions" => ext_hash, "csrs" => csr_hash, - "profile_families" => profile_family_hash, - "profiles" => profile_hash, - "manuals" => manual_hash, - "crd_families" => crd_family_hash, - "crds" => crd_hash + "profile_classes" => profile_class_hash, + "profile_releases" => profile_release_hash, + "certificate_classes" => cert_class_hash, + "certificate_models" => cert_model_hash, + "manuals" => manual_hash } dest = "#{$root}/gen/_/arch/arch_def.yaml" diff --git a/backends/certificate_doc/tasks.rake b/backends/certificate_doc/tasks.rake new file mode 100644 index 0000000000..7001aa8e1f --- /dev/null +++ b/backends/certificate_doc/tasks.rake @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +require "pathname" + +require "asciidoctor-pdf" +require "asciidoctor-diagram" + +require_relative "#{$lib}/idl/passes/gen_adoc" + +CERT_DOC_DIR = Pathname.new "#{$root}/backends/certificate_doc" + +Dir.glob("#{$root}/arch/certificate_model/*.yaml") do |f| + cert_model_name = File.basename(f, ".yaml") + cert_model_obj = YAML.load_file(f, permitted_classes: [Date]) + raise "Ill-formed certificate model file #{f}: missing 'class' field" if cert_model_obj.dig(cert_model_name, 'class').nil? + + base = cert_model_obj[cert_model_name]["base"] + raise "Missing certificate model base" if base.nil? + + file "#{$root}/gen/certificate_doc/adoc/#{cert_model_name}.adoc" => [ + "#{$root}/arch/certificate_model/#{cert_model_name}.yaml", + "#{$root}/arch/certificate_class/#{cert_model_obj[cert_model_name]['class']}.yaml", + "#{CERT_DOC_DIR}/templates/certificate.adoc.erb", + __FILE__, + "#{$root}/.stamps/arch-gen-_#{base}.stamp" + ] do |t| + # TODO: schema validation + arch_def = arch_def_for("_#{base}") + cert_model = arch_def.cert_model(cert_model_name) + raise "No certificate model defined for #{cert_model_name}" if cert_model.nil? + + # switch to the generated certificate arch def + arch_def = cert_model.to_arch_def + cert_model = arch_def.cert_model(cert_model_name) + cert_class = cert_model.cert_class + + version = File.basename(t.name, '.adoc').split('-')[1..].join('-') + + erb = ERB.new(File.read("#{CERT_DOC_DIR}/templates/certificate.adoc.erb"), trim_mode: "-") + erb.filename = "#{CERT_DOC_DIR}/templates/certificate.adoc.erb" + + FileUtils.mkdir_p File.dirname(t.name) + File.write t.name, AsciidocUtils.resolve_links(arch_def.find_replace_links(erb.result(binding))) + puts "Generated adoc source at #{t.name}" + end + + file "#{$root}/gen/certificate_doc/pdf/#{cert_model_name}.pdf" => [ + "#{$root}/gen/certificate_doc/adoc/#{cert_model_name}.adoc" + ] do |t| + adoc_file = "#{$root}/gen/certificate_doc/adoc/#{cert_model_name}.adoc" + FileUtils.mkdir_p File.dirname(t.name) + sh [ + "asciidoctor-pdf", + "-w", + "-v", + "-a toc", + "-a compress", + "-a pdf-theme=#{$root}/ext/docs-resources/themes/riscv-pdf.yml", + "-a pdf-fontsdir=#{$root}/ext/docs-resources/fonts", + "-a imagesdir=#{$root}/ext/docs-resources/images", + "-r asciidoctor-diagram", + "-r #{$root}/backends/ext_pdf_doc/idl_lexer", + "-o #{t.name}", + adoc_file + ].join(" ") + end + + file "#{$root}/gen/certificate_doc/html/#{cert_model_name}.html" => [ + "#{$root}/gen/certificate_doc/adoc/#{cert_model_name}.adoc" + ] do |t| + adoc_file = "#{$root}/gen/certificate_doc/adoc/#{cert_model_name}.adoc" + FileUtils.mkdir_p File.dirname(t.name) + sh [ + "asciidoctor", + "-w", + "-v", + "-a toc", + "-a imagesdir=#{$root}/ext/docs-resources/images", + "-b html5", + "-r asciidoctor-diagram", + "-r #{$root}/backends/ext_pdf_doc/idl_lexer", + "-o #{t.name}", + adoc_file + ].join(" ") + end + +end + +namespace :gen do + desc <<~DESC + Generate certificate documentation for a specific version as a PDF + + Required options: + cert_model_name - The key of the certification model under arch/certificate_model + DESC + task :cert_model_pdf, [:cert_model_name] do |_t, args| + if args[:cert_model_name].nil? + warn "Missing required option: 'cert_model_name'" + exit 1 + end + + unless File.exist?("#{$root}/arch/certificate_model/#{args[:cert_model_name]}.yaml") + warn "No certification model named '#{args[:cert_model_name]}' found in arch/certificate_model" + exit 1 + end + + Rake::Task["#{$root}/gen/certificate_doc/pdf/#{args[:cert_model_name]}.pdf"].invoke + end + + task :cert_model_html, [:cert_model_name] do |_t, args| + if args[:cert_model_name].nil? + warn "Missing required option: 'cert_model_name'" + exit 1 + end + + unless File.exist?("#{$root}/arch/certificate_model/#{args[:cert_model_name]}.yaml") + warn "No certification model named '#{args[:cert_model_name]}' found in arch/certificate_model" + exit 1 + end + + Rake::Task["#{$root}/gen/certificate_doc/html/#{args[:cert_model_name]}.html"].invoke + end +end \ No newline at end of file diff --git a/backends/crd_doc/templates/crd.adoc.erb b/backends/certificate_doc/templates/certificate.adoc.erb similarity index 81% rename from backends/crd_doc/templates/crd.adoc.erb rename to backends/certificate_doc/templates/certificate.adoc.erb index c9616aaeb5..e2d61c14f9 100644 --- a/backends/crd_doc/templates/crd.adoc.erb +++ b/backends/certificate_doc/templates/certificate.adoc.erb @@ -15,9 +15,7 @@ // TODO: needs to be changed :imagesoutdir: images -<% arch_def = crd.arch_def # Set local Ruby variables -%> - -= <%= crd.name %> Certification Requirements Document += <%= cert_model.name %> Certification Requirements Document [Preface] == Revision History @@ -28,7 +26,7 @@ History of documentation changes that eventually lead to releases. |=== | Date | Revision | Changes -<% crd.revision_history.each do |rev| -%> +<% cert_model.revision_history.each do |rev| -%> | <%= rev.date %> | <%= rev.revision %> a| <% rev.changes.each do |change| %> @@ -60,31 +58,31 @@ CSR field types:: == Introduction -<%= crd_family.introduction %> +<%= cert_class.introduction %> -=== <%= crd_family.name %> Naming Scheme +=== <%= cert_class.name %> Naming Scheme -<%= crd_family.naming_scheme %> +<%= cert_class.naming_scheme %> -=== <%= crd_family.name %> Family Description +=== <%= cert_class.name %> Class Description -<%= crd_family.description %> +<%= cert_class.description %> -=== <%= crd.name %> Description +=== <%= cert_model.name %> Description -<%= crd.description %> +<%= cert_model.description %> === Related Specifications [cols="2,2,3,3,3"] |=== -| MC Version | TSC Profile | Unpriv ISA Manual | Priv ISA Manual | Debug Manual +| Certificate Model | TSC Profile | Unpriv ISA Manual | Priv ISA Manual | Debug Manual -| <%= crd.name %> -| <%= crd.tsc_profile.nil? ? "No profile" : crd.tsc_profile.marketing_name %> -| <%= crd.unpriv_isa_manual_revision %> -| <%= crd.priv_isa_manual_revision %> -| <%= crd.debug_manual_revision %> +| <%= cert_model.name %> +| <%= cert_model.tsc_profile.nil? ? "No profile" : cert_model.tsc_profile.marketing_name %> +| <%= cert_model.unpriv_isa_manual_revision %> +| <%= cert_model.priv_isa_manual_revision %> +| <%= cert_model.debug_manual_revision %> |=== === Privileged Modes @@ -92,25 +90,25 @@ CSR field types:: |=== | M | S | U | VS | VU -| <% if crd_family.mandatory_priv_modes.include?('M') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> -| <% if crd_family.mandatory_priv_modes.include?('S') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> -| <% if crd_family.mandatory_priv_modes.include?('U') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> -| <% if crd_family.mandatory_priv_modes.include?('VS') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> -| <% if crd_family.mandatory_priv_modes.include?('VU') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> +| <% if cert_class.mandatory_priv_modes.include?('M') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> +| <% if cert_class.mandatory_priv_modes.include?('S') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> +| <% if cert_class.mandatory_priv_modes.include?('U') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> +| <% if cert_class.mandatory_priv_modes.include?('VS') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> +| <% if cert_class.mandatory_priv_modes.include?('VU') -%> MANDATORY <% else -%> OUT-OF-SCOPE <% end -%> |=== <<< == Extensions -Any RISC-V extension not listed in this section is OUT-OF-SCOPE so the <%= crd.name %> +Any RISC-V extension not listed in this section is OUT-OF-SCOPE so the <%= cert_model.name %> certificate doesn't cover its associated behaviors. <% ["mandatory","optional"].each do |presence| -%> === <%= presence.capitalize %> Extensions -<% ext_reqs = crd.in_scope_ext_reqs(presence) -%> +<% ext_reqs = cert_model.in_scope_ext_reqs(presence) -%> <% if ext_reqs.empty? -%> None <% else -%> @@ -119,7 +117,7 @@ None | Requirement ID | Extension | Version | Long Name | Note <% ext_reqs.sort.each do |ext_req| -%> -<% ext_db = crd.extension_from_db(ext_req.name) -%> +<% ext_db = cert_model.extension_from_db(ext_req.name) -%> | <%= ext_req.req_id %> | <-def,<%= ext_req.name %>>> | <%= ext_req.version_requirement %> @@ -129,19 +127,19 @@ None |=== <% end # if empty ext_reqs -%> -<% crd.extra_notes_for_presence(presence)&.each do |extra_note| -%> +<% cert_model.extra_notes_for_presence(presence)&.each do |extra_note| -%> NOTE: <%= extra_note.text %> <% end # each extra_note -%> <% end # each presence -%> -<% unless crd.recommendations.empty? -%> +<% unless cert_model.recommendations.empty? -%> === Recommendations Recommendations are not strictly mandated but are included to guide implementers making design choices. -<% crd.recommendations.each do |recommendation| -%> +<% cert_model.recommendations.each do |recommendation| -%> <%= recommendation.text %> <% end # each recommendation -%> <% end # unless recommendations empty -%> @@ -159,16 +157,16 @@ These implementation-dependent options defined by MANDATORY or OPTIONAL extensio An implementation must abide by the "Allowed Value(s)" to obtain a certificate. If the "Allowed Value(s)" is "Any" then any value allowed by the type is acceptable. -<% if crd.all_in_scope_ext_params.empty? -%> +<% if cert_model.all_in_scope_ext_params.empty? -%> None <% else -%> [cols="4,2,1,1,2"] |=== | Parameter | Type | Allowed Value(s) | Extension(s) | Note -<% crd.all_in_scope_ext_params.sort.each do |in_scope_ext_param| -%> +<% cert_model.all_in_scope_ext_params.sort.each do |in_scope_ext_param| -%> <% param_db = in_scope_ext_param.param_db -%> -<% exts_db = crd.all_in_scope_exts_with_param(param_db) -%> +<% exts_db = cert_model.all_in_scope_exts_with_param(param_db) -%> | <%= param_db.name_potentially_with_link(exts_db) %> | <%= param_db.schema_type %> | <%= in_scope_ext_param.allowed_values %> @@ -184,15 +182,15 @@ These implementation-dependent options defined by MANDATORY or OPTIONAL extensio There are no restrictions on their values for certification purposes because the certificate doesn't cover the behavior of the associated RISC-V standard as a function of these parameters. -<% if crd.all_out_of_scope_params.empty? -%> +<% if cert_model.all_out_of_scope_params.empty? -%> None <% else -%> [%autowidth] |=== | Parameters | Type | Extension(s) -<% crd.all_out_of_scope_params.sort.each do |param_db| -%> -<% exts_db = crd.all_in_scope_exts_without_param(param_db) -%> +<% cert_model.all_out_of_scope_params.sort.each do |param_db| -%> +<% exts_db = cert_model.all_in_scope_exts_without_param(param_db) -%> | <%= param_db.name_potentially_with_link(exts_db) %> | <%= param_db.schema_type %> | <% exts_db.sort.each do |ext_db| -%><-param-<%= param_db.name %>-def,<%= ext_db.name %>>> <% end # do ext_db -%> @@ -204,7 +202,7 @@ None == Instruction Summary <% - insts = crd.in_scope_extensions.map { |ext_crd| ext_crd.instructions }.flatten.uniq + insts = cert_model.in_scope_extensions.map { |ext_cert_model| ext_cert_model.instructions }.flatten.uniq insts.sort_by!(&:name) -%> @@ -221,7 +219,7 @@ None == CSR Summary <% - csrs = crd.in_scope_ext_reqs.map { |ext_crd_req| ext_crd_req.csrs(crd.arch_def) }.flatten.uniq + csrs = cert_model.in_scope_ext_reqs.map { |ext_req| ext_req.csrs(cert_model.arch_def) }.flatten.uniq -%> === By Name @@ -254,13 +252,13 @@ None <% end # do -%> |=== -<% unless crd.requirement_groups.empty? -%> +<% unless cert_model.requirement_groups.empty? -%> == Additional Requirements This section contains requirements in addition to those already specified related to extensions and parameters. These additional requirements are organized as groups of related requirements. -<% crd.requirement_groups.each do |group| -%> +<% cert_model.requirement_groups.each do |group| -%> === <%= group.name %> <%= group.description %> @@ -290,8 +288,8 @@ Requirement <%= req.name %> only apply when <%= req.when_pretty %>. <<< [appendix] == Extension Details -<% crd.in_scope_ext_reqs.sort.each do |ext_req| -%> -<% ext_db = crd.extension_from_db(ext_req.name) -%> +<% cert_model.in_scope_ext_reqs.sort.each do |ext_req| -%> +<% ext_db = cert_model.extension_from_db(ext_req.name) -%> [[ext-<%= ext_req.name %>-def]] === Extension <%= ext_req.name %> + @@ -352,17 +350,17 @@ The following instructions are added by this extension: [cols="1,3"] |=== -<% insts.each do |inst| -%> +<% insts.sort.each do |inst| -%> | <%= link_to_inst(inst.name) %> | *<%= inst.long_name %>* <% end -%> |=== <% end -%> -<% unless crd.in_scope_ext_params(ext_req).empty? -%> +<% unless cert_model.in_scope_ext_params(ext_req).empty? -%> ==== IN-SCOPE Parameters -<% crd.in_scope_ext_params(ext_req).sort.each do |ext_param| -%> +<% cert_model.in_scope_ext_params(ext_req).sort.each do |ext_param| -%> [[ext-<%= ext_req.name %>-param-<%= ext_param.name %>-def]] <%= ext_param.name %> ⇒ <%= ext_param.param_db.schema_type %>:: + @@ -372,10 +370,10 @@ The following instructions are added by this extension: <% end # do ext_param -%> <% end # unless table -%> -<% unless crd.out_of_scope_params(ext_req.name).empty? -%> +<% unless cert_model.out_of_scope_params(ext_req.name).empty? -%> ==== OUT-OF-SCOPE Parameters -<% crd.out_of_scope_params(ext_req.name).sort.each do |param_db| -%> +<% cert_model.out_of_scope_params(ext_req.name).sort.each do |param_db| -%> [[ext-<%= ext_req.name %>-param-<%= param_db.name %>-def]] <%= param_db.name %> ⇒ <%= param_db.schema_type %>:: + @@ -391,7 +389,7 @@ The following instructions are added by this extension: == Instruction Details <%= - insts = crd.in_scope_extensions.map { |ext_crd| ext_crd.instructions }.flatten.uniq + insts = cert_model.in_scope_extensions.map { |ext_cert_model| ext_cert_model.instructions }.flatten.uniq insts.sort_by!(&:name) -%> @@ -439,18 +437,18 @@ RV64:: <%= inst.description %> ==== Access -<% if crd.in_scope_extensions.any? { |e| e.name == "H" } -%> +<% if cert_model.in_scope_extensions.any? { |e| e.name == "H" } -%> [cols="^,^,^,^,^"] <% else -%> [cols="^,^,^"] <% end -%> |=== -| M | <% if crd.in_scope_extensions.any? { |e| e.name == "H" } -%>HS<% else -%>S<% end -%> | U <% if crd.in_scope_extensions.any? { |e| e.name == "H" } -%> | VS | VU <% end -%> +| M | <% if cert_model.in_scope_extensions.any? { |e| e.name == "H" } -%>HS<% else -%>S<% end -%> | U <% if cert_model.in_scope_extensions.any? { |e| e.name == "H" } -%> | VS | VU <% end -%> | [.access-always]#Always# | [.access-<%=inst.access['s']%>]#<%= inst.access['s'].capitalize %># | [.access-<%=inst.access['u']%>]#<%= inst.access['u'].capitalize %># -<% if crd.in_scope_extensions.any? { |e| e.name == "H" } %> +<% if cert_model.in_scope_extensions.any? { |e| e.name == "H" } %> | [.access-<%=inst.access['vs']%>]#<%= inst.access['vs'].capitalize %># | [.access-<%=inst.access['vu']%>]#<%= inst.access['vu'].capitalize %># <% end %> @@ -524,7 +522,7 @@ This instruction may result in the following synchronous exceptions: == CSR Details <% - csrs = crd.in_scope_ext_reqs.map { |ext_crd_req| ext_crd_req.csrs(crd.arch_def) }.flatten.uniq + csrs = cert_model.in_scope_ext_reqs.map { |ext_req| ext_req.csrs(cert_model.arch_def) }.flatten.uniq csrs.sort_by!(&:name) -%> @@ -561,8 +559,8 @@ h| Privilege Mode | <%= csr.priv_mode %> |=== -==== <%= crd.name %> Format -<% unless csr.dynamic_length?(crd.arch_def) || csr.implemented_fields(arch_def).any? { |f| f.dynamic_location?(crd.arch_def) } -%> +==== <%= cert_model.name %> Format +<% unless csr.dynamic_length?(cert_model.arch_def) || csr.implemented_fields(arch_def).any? { |f| f.dynamic_location?(cert_model.arch_def) } -%> <%# CSR has a known static length, so there is only one format to display -%> .<%= csr.name %> format [wavedrom, ,svg,subs='attributes',width="100%"] @@ -589,7 +587,7 @@ This CSR format changes dynamically with XLEN. <% end # unless dynamic length -%> -==== <%= crd.name %> Field Summary +==== <%= cert_model.name %> Field Summary // use @ as a separator since IDL code can contain | [%autowidth,separator=@,float="center",align="center",cols="^,<,<,<",options="header",role="stretch"] @@ -629,7 +627,7 @@ a@ <%- end -%> |=== -==== <%= crd.name %> Fields +==== <%= cert_model.name %> Fields <%- if csr.implemented_fields(arch_def).empty? -%> This CSR has no fields. However, it must still exist (not cause an `Illegal Instruction` trap) and always return zero on a read. diff --git a/backends/crd_doc/tasks.rake b/backends/crd_doc/tasks.rake deleted file mode 100644 index 661ca67628..0000000000 --- a/backends/crd_doc/tasks.rake +++ /dev/null @@ -1,123 +0,0 @@ -# frozen_string_literal: true - -require "pathname" - -require "asciidoctor-pdf" -require "asciidoctor-diagram" - -require_relative "#{$lib}/idl/passes/gen_adoc" - -CRD_DOC_DIR = Pathname.new "#{$root}/backends/crd_doc" - -Dir.glob("#{$root}/arch/crd/*.yaml") do |f| - crd_name = File.basename(f, ".yaml") - crd_obj = YAML.load_file(f, permitted_classes: [Date]) - raise "Ill-formed CRD file #{f}: missing 'family' field" if crd_obj.dig(crd_name, 'family').nil? - - base = crd_obj[crd_name]["base"] - raise "Missing CRD base" if base.nil? - - file "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" => [ - "#{$root}/arch/crd/#{crd_name}.yaml", - "#{$root}/arch/crd_family/#{crd_obj[crd_name]['family']}.yaml", - "#{CRD_DOC_DIR}/templates/crd.adoc.erb", - __FILE__, - "#{$root}/.stamps/arch-gen-_#{base}.stamp" - ] do |t| - # TODO: schema validation - arch_def = arch_def_for("_#{base}") - crd = arch_def.crd(crd_name) - raise "No CRD defined for #{crd_name}" if crd.nil? - - # switch to the generated CRD arch def - arch_def = crd.to_arch_def - crd = arch_def.crd(crd_name) - crd_family = crd.family - - version = File.basename(t.name, '.adoc').split('-')[1..].join('-') - - erb = ERB.new(File.read("#{CRD_DOC_DIR}/templates/crd.adoc.erb"), trim_mode: "-") - erb.filename = "#{CRD_DOC_DIR}/templates/crd.adoc.erb" - - FileUtils.mkdir_p File.dirname(t.name) - File.write t.name, AsciidocUtils.resolve_links(arch_def.find_replace_links(erb.result(binding))) - puts "Generated adoc source at #{t.name}" - end - - file "#{$root}/gen/crd_doc/pdf/#{crd_name}.pdf" => [ - "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - ] do |t| - adoc_file = "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - FileUtils.mkdir_p File.dirname(t.name) - sh [ - "asciidoctor-pdf", - "-w", - "-v", - "-a toc", - "-a compress", - "-a pdf-theme=#{$root}/ext/docs-resources/themes/riscv-pdf.yml", - "-a pdf-fontsdir=#{$root}/ext/docs-resources/fonts", - "-a imagesdir=#{$root}/ext/docs-resources/images", - "-r asciidoctor-diagram", - "-r #{$root}/backends/ext_pdf_doc/idl_lexer", - "-o #{t.name}", - adoc_file - ].join(" ") - end - - file "#{$root}/gen/crd_doc/html/#{crd_name}.html" => [ - "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - ] do |t| - adoc_file = "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - FileUtils.mkdir_p File.dirname(t.name) - sh [ - "asciidoctor", - "-w", - "-v", - "-a toc", - "-a imagesdir=#{$root}/ext/docs-resources/images", - "-b html5", - "-r asciidoctor-diagram", - "-r #{$root}/backends/ext_pdf_doc/idl_lexer", - "-o #{t.name}", - adoc_file - ].join(" ") - end - -end - -namespace :gen do - desc <<~DESC - Generate CRD documentation for a specific version as a PDF - - Required options: - crd_name - The key of the CRD Family under arch/crd - DESC - task :crd_pdf, [:crd_name] do |_t, args| - if args[:crd_name].nil? - warn "Missing required option: 'crd_family_name'" - exit 1 - end - - unless File.exist?("#{$root}/arch/crd/#{args[:crd_name]}.yaml") - warn "No CRD named '#{args[:crd_name]}' found in arch/crd" - exit 1 - end - - Rake::Task["#{$root}/gen/crd_doc/pdf/#{args[:crd_name]}.pdf"].invoke - end - - task :crd_html, [:crd_name] do |_t, args| - if args[:crd_name].nil? - warn "Missing required option: 'crd_family_name'" - exit 1 - end - - unless File.exist?("#{$root}/arch/crd/#{args[:crd_name]}.yaml") - warn "No CRD named '#{args[:crd_name]}' found in arch/crd" - exit 1 - end - - Rake::Task["#{$root}/gen/crd_doc/html/#{args[:crd_name]}.html"].invoke - end -end \ No newline at end of file diff --git a/backends/portfolio_doc/tasks.rb b/backends/portfolio_doc/tasks.rb deleted file mode 100644 index 7a192bf680..0000000000 --- a/backends/portfolio_doc/tasks.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: true - -require "pathname" - -require "asciidoctor-pdf" -require "asciidoctor-diagram" - -require_relative "#{$lib}/idl/passes/gen_adoc" - -CRD_DOC_DIR = Pathname.new "#{$root}/backends/crd_doc" - -Dir.glob("#{$root}/arch/crd/*.yaml") do |f| - crd_name = File.basename(f, ".yaml") - crd_obj = YAML.load_file(f, permitted_classes: [Date]) - raise "Ill-formed CRD file #{f}: missing 'family' field" if crd_obj.dig(crd_name, 'family').nil? - - base = crd_obj[crd_name]["base"] - raise "Missing CRD base" if base.nil? - - file "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" => [ - "#{$root}/arch/crd/#{crd_name}.yaml", - "#{$root}/arch/crd_family/#{crd_obj[crd_name]['family']}.yaml", - "#{CRD_DOC_DIR}/templates/crd.adoc.erb", - __FILE__, - "#{$root}/.stamps/arch-gen-_#{base}.stamp" - ] do |t| - # TODO: schema validation - arch_def = arch_def_for("_#{base}") - crd = arch_def.crd(crd_name) - raise "No CRD defined for #{crd_name}" if crd.nil? - - # switch to the generated CRD arch def - arch_def = crd.to_arch_def - crd = arch_def.crd(crd_name) - - version = File.basename(t.name, '.adoc').split('-')[1..].join('-') - - erb = ERB.new(File.read("#{CRD_DOC_DIR}/templates/crd.adoc.erb"), trim_mode: "-") - erb.filename = "#{CRD_DOC_DIR}/templates/crd.adoc.erb" - - FileUtils.mkdir_p File.dirname(t.name) - File.write t.name, AsciidocUtils.resolve_links(arch_def.find_replace_links(erb.result(binding))) - puts "Generated adoc source at #{t.name}" - end - - file "#{$root}/gen/crd_doc/pdf/#{crd_name}.pdf" => [ - "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - ] do |t| - adoc_file = "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - FileUtils.mkdir_p File.dirname(t.name) - sh [ - "asciidoctor-pdf", - "-w", - "-v", - "-a toc", - "-a compress", - "-a pdf-theme=#{$root}/ext/docs-resources/themes/riscv-pdf.yml", - "-a pdf-fontsdir=#{$root}/ext/docs-resources/fonts", - "-a imagesdir=#{$root}/ext/docs-resources/images", - "-r asciidoctor-diagram", - "-r #{$root}/backends/ext_pdf_doc/idl_lexer", - "-o #{t.name}", - adoc_file - ].join(" ") - end - - file "#{$root}/gen/crd_doc/html/#{crd_name}.html" => [ - "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - ] do |t| - adoc_file = "#{$root}/gen/crd_doc/adoc/#{crd_name}.adoc" - FileUtils.mkdir_p File.dirname(t.name) - sh [ - "asciidoctor", - "-w", - "-v", - "-a toc", - "-a imagesdir=#{$root}/ext/docs-resources/images", - "-b html5", - "-r asciidoctor-diagram", - "-r #{$root}/backends/ext_pdf_doc/idl_lexer", - "-o #{t.name}", - adoc_file - ].join(" ") - end - -end - -namespace :gen do - desc <<~DESC - Generate CRD documentation for a specific version as a PDF - - Required options: - crd_name - The key of the CRD Family under arch/crd - DESC - task :crd_pdf, [:crd_name] do |_t, args| - if args[:crd_name].nil? - warn "Missing required option: 'crd_family_name'" - exit 1 - end - - unless File.exist?("#{$root}/arch/crd/#{args[:crd_name]}.yaml") - warn "No CRD named '#{args[:crd_name]}' found in arch/crd" - exit 1 - end - - Rake::Task["#{$root}/gen/crd_doc/pdf/#{args[:crd_name]}.pdf"].invoke - end - - task :crd_html, [:crd_name] do |_t, args| - if args[:crd_name].nil? - warn "Missing required option: 'crd_family_name'" - exit 1 - end - - unless File.exist?("#{$root}/arch/crd/#{args[:crd_name]}.yaml") - warn "No CRD named '#{args[:crd_name]}' found in arch/crd" - exit 1 - end - - Rake::Task["#{$root}/gen/crd_doc/html/#{args[:crd_name]}.html"].invoke - end -end \ No newline at end of file diff --git a/backends/portfolio_doc/templates/family_intro.erb b/backends/portfolio_doc/templates/family_intro.erb index abe0caee0d..30314419cd 100644 --- a/backends/portfolio_doc/templates/family_intro.erb +++ b/backends/portfolio_doc/templates/family_intro.erb @@ -1,11 +1,11 @@ -== <%= portfolio_family.name %> Introduction +== <%= portfolio_class.name %> Introduction -<%= portfolio_family.introduction %> +<%= portfolio_class.introduction %> -=== <%= portfolio_family.name %> Naming Scheme +=== <%= portfolio_class.name %> Naming Scheme -<%= portfolio_family.naming_scheme %> +<%= portfolio_class.naming_scheme %> -=== <%= portfolio_family.name %> Family Description +=== <%= portfolio_class.name %> Class Description -<%= portfolio_family.description %> \ No newline at end of file +<%= portfolio_class.description %> \ No newline at end of file diff --git a/backends/profile_doc/tasks.rake b/backends/profile_doc/tasks.rake index 1b005d1860..23118c741d 100644 --- a/backends/profile_doc/tasks.rake +++ b/backends/profile_doc/tasks.rake @@ -1,19 +1,20 @@ # frozen_string_literal: true rule %r{#{$root}/gen/profile_doc/adoc/.*\.adoc} => proc { |tname| - profile_family_name = Pathname.new(tname).basename(".adoc") + profile_release_name = Pathname.new(tname).basename(".adoc") [ "#{$root}/.stamps/arch-gen.stamp", __FILE__, "#{$root}/lib/arch_obj_models/profile.rb", "#{$root}/backends/profile_doc/templates/profile.adoc.erb" - ] + Dir.glob("#{$root}/arch/profile/**/*.yaml") + ] + Dir.glob("#{$root}/arch/profile_release/**/*.yaml") } do |t| - profile_family_name = Pathname.new(t.name).basename(".adoc").to_s + profile_release_name = Pathname.new(t.name).basename(".adoc").to_s - profile_family = arch_def_for("_64").profile_family(profile_family_name) - raise ArgumentError, "No profile family named '#{profile_family_name}'" if profile_family.nil? + profile_release = arch_def_for("_64").profile_release(profile_release_name) + raise ArgumentError, "No profile release named '#{profile_release_name}'" if profile_release.nil? + profile_class = profile_release.profile_class template_path = Pathname.new "#{$root}/backends/profile_doc/templates/profile.adoc.erb" erb = ERB.new(template_path.read, trim_mode: "-") @@ -27,12 +28,12 @@ rule %r{#{$root}/gen/profile_doc/adoc/.*\.adoc} => proc { |tname| end rule %r{#{$root}/gen/profile_doc/pdf/.*\.pdf} => proc { |tname| - profile_family_name = Pathname.new(tname).basename(".pdf") - [__FILE__, "#{$root}/gen/profile_doc/adoc/#{profile_family_name}.adoc"] + profile_release_name = Pathname.new(tname).basename(".pdf") + [__FILE__, "#{$root}/gen/profile_doc/adoc/#{profile_release_name}.adoc"] } do |t| - profile_family_name = Pathname.new(t.name).basename(".pdf") + profile_release_name = Pathname.new(t.name).basename(".pdf") - adoc_filename = "#{$root}/gen/profile_doc/adoc/#{profile_family_name}.adoc" + adoc_filename = "#{$root}/gen/profile_doc/adoc/#{profile_release_name}.adoc" FileUtils.mkdir_p File.dirname(t.name) sh [ @@ -55,12 +56,12 @@ rule %r{#{$root}/gen/profile_doc/pdf/.*\.pdf} => proc { |tname| end rule %r{#{$root}/gen/profile_doc/html/.*\.html} => proc { |tname| - profile_family_name = Pathname.new(tname).basename(".html") - [__FILE__, "#{$root}/gen/profile_doc/adoc/#{profile_family_name}.adoc"] + profile_release_name = Pathname.new(tname).basename(".html") + [__FILE__, "#{$root}/gen/profile_doc/adoc/#{profile_release_name}.adoc"] } do |t| - profile_family_name = Pathname.new(t.name).basename(".html") + profile_release_name = Pathname.new(t.name).basename(".html") - adoc_filename = "#{$root}/gen/profile_doc/adoc/#{profile_family_name}.adoc" + adoc_filename = "#{$root}/gen/profile_doc/adoc/#{profile_release_name}.adoc" FileUtils.mkdir_p File.dirname(t.name) sh [ @@ -80,25 +81,25 @@ rule %r{#{$root}/gen/profile_doc/html/.*\.html} => proc { |tname| end namespace :gen do - desc "Create a specification PDF for +profile_family+" - task :profile, [:profile_family] => ["#{$root}/.stamps/arch-gen-_64.stamp"] do |_t, args| - family_name = args[:profile_family] - raise ArgumentError, "Missing required option +profile_family+" if family_name.nil? + desc "Create a specification PDF for +profile_release+" + task :profile, [:profile_release] => ["#{$root}/.stamps/arch-gen-_64.stamp"] do |_t, args| + profile_release_name = args[:profile_release] + raise ArgumentError, "Missing required option +profile_release+" if profile_release_name.nil? - family = arch_def_for("_64").profile_family(family_name) - raise ArgumentError, "No profile family named '#{family_name}" if family.nil? + profile_release = arch_def_for("_64").profile_release(profile_release_name) + raise ArgumentError, "No profile release named '#{profile_release_name}" if profile_release.nil? - Rake::Task["#{$root}/gen/profile_doc/pdf/#{family_name}.pdf"].invoke + Rake::Task["#{$root}/gen/profile_doc/pdf/#{profile_release_name}.pdf"].invoke end - desc "Create a specification HTML for +profile_family+" - task :profile_html, [:profile_family] => ["#{$root}/.stamps/arch-gen-_64.stamp"] do |_t, args| - family_name = args[:profile_family] - raise ArgumentError, "Missing required option +profile_family+" if family_name.nil? + desc "Create a specification HTML for +profile_release+" + task :profile_html, [:profile_release] => ["#{$root}/.stamps/arch-gen-_64.stamp"] do |_t, args| + profile_release_name = args[:profile_release] + raise ArgumentError, "Missing required option +profile_release+" if profile_release_name.nil? - family = arch_def_for("_64").profile_family(family_name) - raise ArgumentError, "No profile family named '#{family_name}" if family.nil? + profile_release = arch_def_for("_64").profile_release(profile_release_name) + raise ArgumentError, "No profile release named '#{profile_release_name}" if profile_release.nil? - Rake::Task["#{$root}/gen/profile_doc/html/#{family_name}.html"].invoke + Rake::Task["#{$root}/gen/profile_doc/html/#{profile_release_name}.html"].invoke end end diff --git a/backends/profile_doc/templates/profile.adoc.erb b/backends/profile_doc/templates/profile.adoc.erb index f8a1f8f00a..f866bc1af5 100644 --- a/backends/profile_doc/templates/profile.adoc.erb +++ b/backends/profile_doc/templates/profile.adoc.erb @@ -1,16 +1,19 @@ [[header]] -:description: <%= profile_family.marketing_name %> Profile -:revdate: <%= profile_family.ratification_date.nil? ? Date.today : profile_family.ratification_date %> -:revnumber: <%= profile_family.profiles.map(&:version).sort.last %> +:description: <%= profile_release.marketing_name %> Profile +:revdate: <%= profile_release.ratification_date.nil? ? Date.today : profile_release.ratification_date %> + +// XXX - Figure out what we really want here - Change percent hash to percent equals. +// :revnumber: <%# profile_release.map(&:version).sort.last %> + :revmark: "TODO: revmark" -:company: <%= profile_family.company.name %> +:company: <%= profile_class.company.name %> :url-riscv: https://riscv.org :doctype: book :preface-title: Licensing and Acknowledgements :colophon: :appendix-caption: Appendix :title-logo-image: image:risc-v_logo.png["RISC-V International Logo",pdfwidth=3.25in,align=center] -<%# unless profile_family.state == "ratified" -%> +<%# unless profile_release.state == "ratified" -%> :page-background-image: image:draft.png[opacity=20%] <%# end -%> :back-cover-image: image:riscv-horizontal-color.svg[opacity=25%] @@ -51,7 +54,7 @@ endif::[] :csrname: envcfg :imagesdir: images -= <%= profile_family.name %> Profile Family += <%= profile_release.name %> Profile Release // Preamble @@ -62,32 +65,28 @@ endif::[] [preface] == Copyright and license information This document is released under the -<% if profile_family.doc_license.url.nil? -%> -<%= profile_family.doc_license.name %>. +<% if profile_class.doc_license.url.nil? -%> +<%= profile_class.doc_license.name %>. <% else -%> -<%= profile_family.doc_license.url %>[<%= profile_family.doc_license.name %>]. +<%= profile_class.doc_license.url %>[<%= profile_class.doc_license.name %>]. <% end -%> -<% if profile_family.ratification_date.nil? -%> +<% if profile_release.ratification_date.nil? -%> Copyright <%= Date.today.year %> <% else -%> -Copyright <%= profile_family.ratification_date.year %> +Copyright <%= profile_release.ratification_date.year %> <% end -%> -by <%= profile_family.company.name %>. - +by <%= profile_class.company.name %>. [preface] == Acknowledgements -<% profile_family.profiles.each do |profile| -%> -Contributors to the <%= profile.marketing_name %> Profile (in alphabetical order) include: + +Contributors to the <%= profile_release.marketing_name %> Profile (in alphabetical order) include: + -<% profile.contributors.sort.each do |c| -%> +<% profile_release.contributors.sort.each do |c| -%> * <%= c.name %> <<%= c.email %>> (<%= c.company %>) <% end -%> -<% end -%> - We express our gratitude to everyone that contributed to, reviewed or improved this specification through their comments and questions. @@ -313,56 +312,75 @@ optional profile extensions for a new profile might be prototyped as non-profile extensions on an earlier profile. // XXX - Need to create render() Ruby function. -// <%# render("#{$root}/backends/portfolio_doc/templates/family_intro.erb", portfolio_family: profile_family) %> +// <%# render("#{$root}/backends/portfolio_doc/templates/family_intro.erb", portfolio_class: profile_class) %> -== <%= profile_family.name %> Introduction +== <%= profile_class.name %> Profile Class -<%= profile_family.introduction %> +<%= profile_class.introduction %> -=== <%= profile_family.name %> Naming Scheme +=== <%= profile_class.name %> Description -<%= profile_family.naming_scheme %> +<%= profile_class.description %> -=== <%= profile_family.name %> Family Description +=== <%= profile_class.name %> Naming Scheme -<%= profile_family.description %> +<%= profile_class.naming_scheme %> -The following profiles are defined in this family: +NOTE: Profile names are embeddable into RISC-V ISA naming strings. +This implies that there will be no standard ISA extension with a name +that matches the profile naming convention. This allows tools that +process the RISC-V ISA naming string to parse and/or process a combined string. -<% profile_family.profiles.each do |profile| -%> +=== <%= profile_class.name %> Profile Releases + +The following profile releases are defined in this profile class: + +<% profile_class.profile_releases.each do |profile_release| -%> -- -Name:: <%= profile.marketing_name %> -State:: <%= profile.state %> -<% unless profile.ratification_date.nil? -%> -Ratification date:: <%= profile.ratification_date %> -<% end -%> +Name:: <%= profile_release.marketing_name %> +State:: <%= profile_release.state %> +<% unless profile_release.ratification_date.nil? -%> +Ratification date:: <%= profile_release.ratification_date %> +<% end # unless -%> -- -<% end -%> +<% end # each profile_release -%> -=== Extensions in the <%= profile_family.name %> Family +=== Extension Presence -The <%= profile_family.marketing_name %> Profile Family references -<%= profile_family.referenced_extensions.size %> extensions. +The <%= profile_class.marketing_name %> Profile Class references +<%= profile_class.referenced_extensions.size %> extensions. .Status |=== -| Extension | <%= profile_family.profiles.map(&:marketing_name).join(" | ") -%> +| Extension | <%= profile_class.profiles.map(&:marketing_name).join(" | ") -%> -<% profile_family.referenced_extensions.sort_by(&:name).each do |ext| -%> -| <%= ext.name %> | <%= profile_family.profiles.map { |profile| profile.extension_presence(ext.name) }.join(" | ") -%> +<% profile_class.referenced_extensions.sort_by(&:name).each do |ext| -%> +| <%= ext.name %> | <%= profile_class.profiles.map { |profile| profile.extension_presence(ext.name) }.join(" | ") -%> <% end -%> |=== -<% profile_family.profiles.each do |profile| -%> -<<< -== <%= profile.marketing_name %> Profile +== <%= profile_release.name %> Profile Release -<%= profile.description %> +<%= profile_release.introduction %> + +<%= profile_release.marketing_name %> has <%= profile_release.referenced_extensions.reduce(0) { |sum, ext| sum + ext.params.size } %> +associated implementation-defined parameters across all its defined profiles. + +<% unless profile_release.description.nil? -%> +=== <%= profile_release.name %> Description + +<%= profile_release.description %> + +<% end # unless -%> +<% profile_release.profiles.each do |profile| -%> +=== <%= profile.marketing_name %> Profile + +<%= profile.introduction %> <% ["mandatory","optional"].each do |presence| -%> -=== <%= presence.capitalize %> Extensions +==== <%= presence.capitalize %> Extensions <% ext_reqs = profile.in_scope_ext_reqs(presence) -%> @@ -391,23 +409,22 @@ NOTE: <%= extra_note.text %> <% end # presence -%> -<% puts("CCC profile #{profile.name}") -%> <% unless profile.recommendations.empty? -%> -=== Recommendations +==== Recommendations Recommendations are not strictly mandated but are included to guide implementers making design choices. <% profile.recommendations.each do |recommendation| -%> <%= recommendation.text %> -<% end # each recommendation %> -<% end # unless recommendations empty %> -<% end # each profile -%> +<% end # each recommendation -%> +<% end # unless recommendations empty -%> -== Profile Parameters +==== Implementation-dependencies -<%= profile_family.marketing_name %> has <%= profile_family.referenced_extensions.reduce(0) { |sum, ext| sum + ext.params.size } %> associated paramters. +<%= profile.marketing_name %> has <%= profile.referenced_extensions.reduce(0) { |sum, ext| sum + ext.params.size } %> +associated implementation-defined parameters. -<% profile_family.referenced_extensions.each do |ext| -%> +<% profile.referenced_extensions.each do |ext| -%> <% ext.params.sort_by { |p| p.name }.each do |param| -%> <%= param.name %>:: + @@ -417,11 +434,13 @@ Recommendations are not strictly mandated but are included to guide implementers <% end -%> <% end -%> +<% end # each profile -%> + <<< [appendix] -== Extension Specifications +== Extension Details -<% profile_family.referenced_extensions.each do |ext| -%> +<% profile_release.referenced_extensions.sort.each do |ext| -%> <<< === <%= ext.name %> Extension <%= ext.long_name %> @@ -430,7 +449,7 @@ Recommendations are not strictly mandated but are included to guide implementers |=== | Profile | v<%= ext.versions.map { |v| v["version"] }.join(" | v") %> -<% profile_family.profiles.each do |profile| -%> +<% profile_release.profiles.each do |profile| -%> | <%= profile.marketing_name %> | <%= ext.versions.map do |v| mandatory = profile.in_scope_ext_reqs("mandatory").any? { |req| req.satisfied_by?(ext.name, v["version"]) } optional = profile.in_scope_ext_reqs("optional").any? { |req| req.satisfied_by?(ext.name, v["version"]) } @@ -488,7 +507,7 @@ The following instructions are added by this extension: [cols="1,3"] |=== -<% insts.each do |inst| -%> +<% insts.sort.each do |inst| -%> | <%= "`#{inst.name}`" %> | *<%= inst.long_name %>* <% end -%> |=== @@ -512,10 +531,10 @@ This extension has the following implementation options: <<< [appendix] -== Instruction Specifications +== Instruction Details <%= - insts = profile_family.referenced_extensions.map { |ext| ext.instructions }.flatten.uniq + insts = profile_release.referenced_extensions.map { |ext| ext.instructions }.flatten.uniq insts.sort_by!(&:name) -%> @@ -564,18 +583,18 @@ RV64:: <%= inst.description %> ==== Access -<% if profile_family.referenced_extensions.any? { |e| e.name == "H" } -%> +<% if profile_release.referenced_extensions.any? { |e| e.name == "H" } -%> [cols="^,^,^,^,^"] <% else -%> [cols="^,^,^"] <% end -%> |=== -| M | <% if profile_family.referenced_extensions.any? { |e| e.name == "H" } -%>HS<% else -%>S<% end -%> | U <% if profile_family.referenced_extensions.any? { |e| e.name == "H" } -%> | VS | VU <% end -%> +| M | <% if profile_release.referenced_extensions.any? { |e| e.name == "H" } -%>HS<% else -%>S<% end -%> | U <% if profile_release.referenced_extensions.any? { |e| e.name == "H" } -%> | VS | VU <% end -%> | [.access-always]#Always# | [.access-<%=inst.access['s']%>]#<%= inst.access['s'].capitalize %># | [.access-<%=inst.access['u']%>]#<%= inst.access['u'].capitalize %># -<% if profile_family.referenced_extensions.any? { |e| e.name == "H" } %> +<% if profile_release.referenced_extensions.any? { |e| e.name == "H" } %> | [.access-<%=inst.access['vs']%>]#<%= inst.access['vs'].capitalize %># | [.access-<%=inst.access['vu']%>]#<%= inst.access['vu'].capitalize %># <% end %> @@ -647,10 +666,10 @@ This instruction may result in the following synchronous exceptions: <<< [appendix] -== CSR Specifications +== CSR Details <% - csrs = profile_family.referenced_extensions.map { |ext| ext.csrs }.flatten.uniq + csrs = profile_release.referenced_extensions.map { |ext| ext.csrs }.flatten.uniq csrs.sort_by!(&:name) -%> diff --git a/lib/arch_def.rb b/lib/arch_def.rb index 0426afafcb..b6fa86279a 100644 --- a/lib/arch_def.rb +++ b/lib/arch_def.rb @@ -1,5 +1,29 @@ # frozen_string_literal: true +# Many classes have an "arch_def" member which is an ArchDef (not ArchDefObject) class. +# The "arch_def" member contains the "database" of RISC-V standards including extensions, instructions, +# CSRs, Profiles, and Certificates. +# +# The arch_def member has methods such as: +# extensions() Array of all extensions known to the database (even if not implemented). +# extension(name) Extension object for "name" and nil if none. +# parameters() Array of all parameters defined in the architecture +# param(name) ExtensionParameter object for "name" and nil if none. +# csrs() Array of all CSRs defined by RISC-V, whether or not they are implemented +# csr(name) Csr object for "name" and nil if none. +# instructions() Array of all instructions, whether or not they are implemented +# inst(name) Instruction object for "name" and nil if none. +# profile_classes Array of all known profile classes. +# profile_class(class_name) ProfileClass object for "class_name" and nil if none. +# profile_releases Array of all profile releases for all profile classes +# profile_release(release_name) ProfileRelease object for "release_name" and nil if none. +# profiles Array of all profiles in all releases in all classes +# profile(name) Profile object for profile "name" and nil if none. +# cert_classes Array of all known certificate classes +# cert_class(name) CertClass object for "name" and nil if none. +# cert_models Array of all known certificate models across all classes. +# cert_model(name) CertModel object for "name" and nil if none. + require "forwardable" require "ruby-prof" @@ -18,7 +42,7 @@ require_relative "arch_obj_models/csr" require_relative "arch_obj_models/instruction" require_relative "arch_obj_models/extension" -require_relative "arch_obj_models/crd" +require_relative "arch_obj_models/certificate" require_relative "template_helpers" include TemplateHelpers @@ -601,49 +625,82 @@ def manuals_hash # @return [Manual,nil] A manual named +name+, or nil if it doesn't exist def manual(name) = manuals_hash[name] - # @return [Array] All known profile families - def profile_families - return @profile_families unless @profile_families.nil? + # @return [Array] All known profile classes (e.g. RVA) + def profile_classes + return @profile_classes unless @profile_classes.nil? - @profile_families = [] - @arch_def["profile_families"].each_value do |family_data| - @profile_families << ProfileFamily.new(family_data, self) + @profile_classes = [] + @arch_def["profile_classes"].each_value do |pc_data| + @profile_classes << ProfileClass.new(pc_data, self) end - @profile_families + @profile_classes end - # @return [Hash] Profile families, indexed by name - def profile_families_hash - return @profile_families_hash unless @profile_families_hash.nil? + # @return [Hash] Profile classes, indexed by profile class name + def profile_classes_hash + return @profile_classes_hash unless @profile_classes_hash.nil? - @profile_families_hash = {} - profile_families.each do |family| - @profile_families_hash[family.name] = family + @profile_classes_hash = {} + profile_classes.each do |pc| + @profile_classes_hash[pc.name] = pc end - @profile_families_hash + @profile_classes_hash end - # @return [ProfileFamily] The profile family named +name+ - # @return [nil] if the profile family does not exist - def profile_family(name) = profile_families_hash[name] + # @return [ProfileClass] The profile class named +name+ + # @return [nil] if the profile class does not exist + def profile_class(profile_class_name) = profile_classes_hash[profile_class_name] + + # @return [ProfileRelease] List of all profile releases (e.g. RVA20, RVA22) for all profile classes. + def profile_releases + return @profile_releases unless @profile_releases.nil? + + @profile_releases = [] + @arch_def["profile_releases"].each_value do |pr_data| + raise ArgumentError, "Expecting pr_data to be a hash" unless pr_data.is_a?(Hash) + + profile_release = ProfileRelease.new(pr_data, self) + raise ArgumentError, "ProfileRelease constructor returned nil" if profile_release.nil? + + @profile_releases << profile_release + end + @profile_releases + end - # @return [Profile] List of all defined profiles + # @return [Hash], indexed by profile release name + def profile_releases_hash + return @profile_releases_hash unless @profile_releases_hash.nil? + + @profile_releases_hash = {} + profile_releases.each do |profile_release| + @profile_releases_hash[profile_release.name] = profile_release + end + @profile_releases_hash + end + + # @return [ProfileRelease] The profile release named +profile_release_name+ + # @return [nil] if the profile release does not exist + def profile_release(profile_release_name) = profile_releases_hash[profile_release_name] + + # @return [Profile] List of all defined profiles in all releases in all classes def profiles return @profiles unless @profiles.nil? @profiles = [] - @arch_def["profiles"].each_value do |profile_data| - raise ArgumentError, "Expecting profile_data to be a hash" unless profile_data.is_a?(Hash) + @arch_def["profile_releases"].each_value do |pr_data| + raise ArgumentError, "Expecting pr_data to be a hash" unless pr_data.is_a?(Hash) - profile = Profile.new(profile_data, self) - raise ArgumentError, "Profile constructor returned nil" if profile.nil? + pr_data["profiles"].each do |profile_data| + profile = Profile.new(profile_data, self) + raise ArgumentError, "Profile constructor returned nil" if profile.nil? - @profiles << profile + @profiles << profile + end end @profiles end - # @return [Hash] Profiles, indexed by name + # @return [Hash] Profiles, indexed by profile name def profiles_hash return @profiles_hash unless @profiles_hash.nil? @@ -658,54 +715,54 @@ def profiles_hash # @return [nil] if the profile does not exist def profile(name) = profiles_hash[name] - def crd_families - return @crd_families unless @crd_families.nil? + def cert_classes + return @cert_classes unless @cert_classes.nil? - @crd_families = [] - @arch_def["crd_families"].each_value do |family_data| - @crd_families << CrdFamily.new(family_data, self) + @cert_classes = [] + @arch_def["certificate_classes"].each_value do |cc_data| + @cert_classes << CertClass.new(cc_data, self) end - @crd_families + @cert_classes end - def crd_famlies_hash - return @crd_families_hash unless @crd_families_hash.nil? + def cert_classes_hash + return @cert_classes_hash unless @cert_classes_hash.nil? - @crd_families_hash = {} - crd_families.each do |family| - @crd_families_hash[family.name] = family + @cert_classes_hash = {} + cert_classes.each do |cc| + @cert_classes_hash[cc.name] = cc end - @crd_families_hash + @cert_classes_hash end - # @return [CrdFamily] The CRD family named +name+ - # @return [nil] if the CRD family does not exist - def crd_family(name) = crd_famlies_hash[name] + # @return [CertClass] The certificate class named +name+ + # @return [nil] if the certificate class does not exist + def cert_class(name) = cert_classes_hash[name] - # @return [Crd] List of all defined CRDs - def crds - return @crds unless @crds.nil? + # @return [CertModel] List of all defined certificate models across all certificate classes + def cert_models + return @cert_models unless @cert_models.nil? - @crds = [] - @arch_def["crds"].each_value do |crd_data| - @crds << Crd.new(crd_data, self) + @cert_models = [] + @arch_def["certificate_models"].each_value do |cm_data| + @cert_models << CertModel.new(cm_data, self) end - @crds + @cert_models end - def crds_hash - return @crds_hash unless @crds_hash.nil? + def cert_models_hash + return @cert_models_hash unless @cert_models_hash.nil? - @crds_hash = {} - crds.each do |crd| - @crds_hash[crd.name] = crd + @cert_models_hash = {} + cert_models.each do |cert_model| + @cert_models_hash[cert_model.name] = cert_model end - @crds_hash + @cert_models_hash end - # @return [Crd] The CRD named +name+ - # @return [nil] if the CRD does not exist - def crd(name) = crds_hash[name] + # @return [CertModel] The CertModel named +name+ + # @return [nil] if the CertModel does not exist + def cert_model(name) = cert_models_hash[name] # @return [Array] All exception codes defined by RISC-V def exception_codes @@ -991,11 +1048,11 @@ def unconfigured_data "instructions" => instructions.map { |i| [i.name, i.data] }.to_h, "extensions" => extensions.map.map { |e| [e.name, e.data] }.to_h, "csrs" => csrs.map { |c| [c.name, c.data] }.to_h, - "profile_families" => profile_families.map { |f| [f.name, f.data] }.to_h, - "profiles" => profiles.map { |p| [p.name, p.data] }.to_h, + "profile_classes" => profile_classes.map { |f| [f.name, f.data] }.to_h, + "profile_releases" => profile_releases.map { |p| [p.name, p.data] }.to_h, "manuals" => manuals.map { |m| [m.name, m.data] }.to_h, - "crd_families" => crd_families.map { |f| [f.name, f.data] }.to_h, - "crds" => crds.map { |c| [c.name, c.data] }.to_h + "certificate_classes" => cert_classes.map { |f| [f.name, f.data] }.to_h, + "certificate_models" => cert_models.map { |c| [c.name, c.data] }.to_h } end diff --git a/lib/arch_obj_models/crd.rb b/lib/arch_obj_models/certificate.rb similarity index 84% rename from lib/arch_obj_models/crd.rb rename to lib/arch_obj_models/certificate.rb index 3fe1f961a1..6ac6d04231 100644 --- a/lib/arch_obj_models/crd.rb +++ b/lib/arch_obj_models/certificate.rb @@ -1,18 +1,15 @@ -# Classes for CRD (Certification Requirements Documents). -# Each CRD is a member of a CRD family (e.g., Microcontroller). -# -# A variable name with a "_crd" suffix indicates it is from the CRD family/member YAML file. -# A variable name with a "_db" suffix indicates it is an object reference from the arch_def database. +# Classes for certificates. +# Each certificate model is a member of a certificate class. require_relative "portfolio" ################### -# CrdFamily Class # +# CertClass Class # ################### -# Holds information from CRD family YAML file. +# Holds information from certificate class YAML file. # The inherited "data" member is the database of extensions, instructions, CSRs, etc. -class CrdFamily < PortfolioFamily +class CertClass < PortfolioClass # @param data [Hash] The data from YAML # @param arch_def [ArchDef] Architecture spec def initialize(data, arch_def) @@ -22,13 +19,13 @@ def initialize(data, arch_def) def mandatory_priv_modes = @data["mandatory_priv_modes"] end -############# -# Crd Class # -############# +################### +# CertModel Class # +################### -# Holds information about a CRD YAML file. +# Holds information about a certificate model YAML file. # The inherited "data" member is the database of extensions, instructions, CSRs, etc. -class Crd < Portfolio +class CertModel < PortfolioInstance # @param data [Hash] The data from YAML # @param arch_def [ArchDef] Architecture spec def initialize(data, arch_def) @@ -49,12 +46,12 @@ def tsc_profile profile end - # @return [CrdFamily] The CRD family specified by this profile. - def family - family = @arch_def.crd_family(@data["family"]) - raise "No CRD family named '#{@data["family"]}'" if family.nil? + # @return [CertClass] The certification class that this model belongs to. + def cert_class + cert_class = @arch_def.cert_class(@data["class"]) + raise "No certificate class named '#{@data["class"]}'" if cert_class.nil? - family + cert_class end # @return [ArchDef] A partially-configued architecture definition corresponding to this CRD @@ -161,6 +158,4 @@ def requirement_groups end @requirement_groups end - - end \ No newline at end of file diff --git a/lib/arch_obj_models/portfolio.rb b/lib/arch_obj_models/portfolio.rb index 965d5f4c29..891ac9cfa0 100644 --- a/lib/arch_obj_models/portfolio.rb +++ b/lib/arch_obj_models/portfolio.rb @@ -1,29 +1,11 @@ -# Classes for Porfolios which form a common base class for Profiles and CRDs. +# Classes for Porfolios which form a common base class for profiles and certificates. # A "Portfolio" is a named & versioned grouping of extensions (each with a name and version). -# Each Portfolio is a member of a Portfolio Family (e.g., Microcontroller). +# Each Portfolio Instance is a member of a Portfolio Class: +# RVA20U64 and MC100 are examples of portfolio instances +# RVA and MC are examples of portfolio classes # # Many classes inherit from the ArchDefObject class. This provides facilities for accessing the contents of a -# Portfolio Family YAML or Portfolio YAML file via the "data" member (hash holding releated YAML file contents). -# -# Many classes have an "arch_def" member which is an ArchDef (not ArchDefObject) class. -# The "arch_def" member contains the "database" of RISC-V standards including extensions, instructions, CSRs, Profiles, and CRDs. -# The arch_def member has methods such as: -# extensions() Array of all extensions known to the database (even if not implemented). -# extension(name) Extension object for "name" and nil if none. -# parameters() Array of all parameters defined in the architecture -# param(name) ExtensionParameter object for "name" and nil if none. -# csrs() Array of all CSRs defined by RISC-V, whether or not they are implemented -# csr(name) Csr object for "name" and nil if none. -# instructions() Array of all instructions, whether or not they are implemented -# inst(name) Instruction object for "name" and nil if none. -# profile_families Array of all known profile families -# profile_family(name) ProfileFamily object for "name" and nil if none. -# profiles Array of all known profiles. -# profile(name) Profile object for "name" and nil if none. -# crd_families Array of all known CRD families -# crd_family(name) CrdFamily object for "name" and nil if none. -# crds Array of all known CRDs. -# crd(name) Crd object for "name" and nil if none. +# Portfolio Class YAML or Portfolio Model YAML file via the "data" member (hash holding releated YAML file contents). # # A variable name with a "_portfolio" suffix indicates it is from the porfolio YAML file. # A variable name with a "_db" suffix indicates it is an object reference from the arch_def database. @@ -31,13 +13,13 @@ require_relative "obj" require_relative "schema" -######################## -# PortfolioFamily Class # -######################## +################## +# PortfolioClass # +################## -# Holds information from Portfolio family YAML file (CRD family or Profile family). +# Holds information from Portfolio class YAML file (certificate class or profile class). # The inherited "data" member is the database of extensions, instructions, CSRs, etc. -class PortfolioFamily < ArchDefObject +class PortfolioClass < ArchDefObject # @return [ArchDef] The defining ArchDef attr_reader :arch_def @@ -58,13 +40,13 @@ def eql?(other) end end -################### -# Portfolio Class # -################### +##################### +# PortfolioInstance # +##################### -# Holds information about a Portfolio YAML file (CRD or Profile). +# Holds information about a PortfolioInstance YAML file (certificate or profile). # The inherited "data" member is the database of extensions, instructions, CSRs, etc. -class Portfolio < ArchDefObject +class PortfolioInstance < ArchDefObject # @return [ArchDef] The defining ArchDef attr_reader :arch_def @@ -77,7 +59,7 @@ def initialize(data, arch_def) def description = @data["description"] - # @return [Gem::Version] Semantic version of the Portfolio + # @return [Gem::Version] Semantic version of the PortfolioInstance def version = Gem::Version.new(@data["version"]) # @return [Extension] - Returns named Extension object from database (nil if not found). @@ -201,7 +183,7 @@ def value # @return [String] - # What parameter values are allowed by the portfolio. def allowed_values if (@schema_portfolio.empty?) - # Portfolio doesn't add any constraints on parameter's value. + # PortfolioInstance doesn't add any constraints on parameter's value. return "Any" end @@ -446,7 +428,6 @@ def extra_notes_for_presence(desired_presence) class Recommendation < ArchDefObject def initialize(data) - puts "CCC: data = #{data}" super(data) end diff --git a/lib/arch_obj_models/profile.rb b/lib/arch_obj_models/profile.rb index c401b5d9fc..a83a2b48d0 100644 --- a/lib/arch_obj_models/profile.rb +++ b/lib/arch_obj_models/profile.rb @@ -2,22 +2,20 @@ require_relative "portfolio" -# A profile family is a set of profiles that share a common goal or lineage -# -# For example, the RVA family is a set of profiles for application processors -class ProfileFamily < PortfolioFamily +# A profile class consists of a number of releases each with set of profiles. +# For example, the RVA profile class has releases such as RVA20, RVA22, RVA23 +# that each include an unprivileged profile (e.g., RVA20U64) and one more +# privileged profiles (e.g., RVA20S64). +class ProfileClass < PortfolioClass # @param data [Hash] The data from YAML # @param arch_def [ArchDef] Architecture spec def initialize(data, arch_def) super(data, arch_def) end - # @return [String] Name of the family + # @return [String] Name of the class def marketing_name = @data["marketing_name"] - # @return [Array] Privilege modes that this family defines profiles for - def modes = @data["modes"] - # @return [Company] Company that created the profile def company = Company.new(@data["company"]) @@ -26,26 +24,32 @@ def doc_license License.new(@data["doc_license"]) end - # @return [Date] The most recent ratification date of any profile in the family - # @return [nil] if there are no ratified profiles in the family - def ratification_date - date = nil - profiles.each do |profile| - date = profile.ratification_date if !profile.ratification_date.nil? && profile.ratification_date < date - end - date + # @return [Array] Defined profile releases in this profile class + def profile_releases + return @profile_releases unless @profile_releases.nil? + + @profile_releases = @arch_def.profile_releases.select { |pr| pr.profile_class.name == name } + + @profile_releases end - # @return [Array] Defined profiles in this family + # @return [Array] All profiles in this profile class (for all releases). def profiles return @profiles unless @profiles.nil? - @profiles = arch_def.profiles.select { |profile| profile.data["family"] == name } + puts " 2a: profiles for class #{name} called." + + @profiles = [] + @arch_def.profiles.each do |profile| + if profile.profile_class.name == name + @profiles << profile + end + end @profiles end - # @return [Array] List of all extensions referenced by the family + # @return [Array] List of all extensions referenced by the class def referenced_extensions return @referenced_extensions unless @referenced_extensions.nil? @@ -61,26 +65,92 @@ def referenced_extensions end -# representation of a specific profile for a Family, Mode, and Base -class Profile < Portfolio +# A profile release consists of a number of releases each with one or more profiles. +# For example, the RVA20 profile release has profiles RVA20U64 and RVA20S64. +# Note there is no Portfolio* base class for a ProfileRelease to inherit from since there is no +# equivalent to a ProfileRelease in a Certificate so no potential for a shared base class. +class ProfileRelease < ArchDefObject + # @param data [Hash] The data from YAML + # @param arch_def [ArchDef] Architecture spec + def initialize(data, arch_def) + super(data) + @arch_def = arch_def + end + + def marketing_name = @data["marketing_name"] + def introduction = @data["introduction"] + def state = @data["state"] + + # @return [Date] Ratification date + # @return [nil] if the profile is not ratified + def ratification_date + return nil if @data["ratification_date"].nil? + + Date.parse(@data["ratification_date"]) + end + + # @return [Array] Contributors to the profile spec + def contributors + @data["contributors"].map { |data| Person.new(data) } + end + + # @return [ProfileClass] Profile Class that this ProfileRelease belongs to + def profile_class + profile_class = @arch_def.profile_class(@data["class"]) + raise "No profile class named '#{@data["class"]}'" if profile_class.nil? + + profile_class + end + + # @return [Array] All profiles in this profile release + def profiles + return @profiles unless @profiles.nil? + + @profiles = [] + @arch_def.profiles.each do |profile| + if profile.profile_release.name == name + @profiles << profile + end + end + @profiles + end + + # @return [Array] List of all extensions referenced by the release + def referenced_extensions + return @referenced_extensions unless @referenced_extensions.nil? + + @referenced_extensions = [] + profiles.each do |profile| + @referenced_extensions += profile.in_scope_extensions + end + + @referenced_extensions.uniq!(&:name) + + @referenced_extensions + end +end + +# Representation of a specific profile in a profile release. +class Profile < PortfolioInstance def initialize(data, arch_def) super(data, arch_def) end # @return [String] The marketing name of the Profile + def introduction = @data["introduction"] def marketing_name = @data["marketing_name"] - # @return [String] State of the profile spec - def state = @data["state"] - - # @return [ProfileFamily] The profile family specified by this profile. - def family - family = @arch_def.profile_family(@data["family"]) - raise "No profile family named '#{@data["family"]}'" if family.nil? + # @return [ProfileRelease] The profile release this profile belongs to + def profile_release + profile_release = @arch_def.profile_release(@data["release"]) + raise "No profile release named '#{@data["release"]}'" if profile_release.nil? - family + profile_release end + # @return [ProfileClass] The profile class this profile belongs to + def profile_class = profile_release.profile_class + # @return ["M", "S", "U", "VS", "VU"] Privilege mode for the profile def mode @data["mode"] @@ -91,16 +161,6 @@ def base @data["base"] end - # @return [Date] Ratification date - # @return [nil] if the profile is not ratified - def ratification_date - return nil if @data["ratification_date"].nil? - - Date.parse(@data["ratification_date"]) - end - - # @return [Array] Contributors to the profile spec - def contributors - @data["contributors"].map { |data| Person.new(data) } - end -end + # @return [Array] List of all extensions referenced by the profile + def referenced_extensions = in_scope_extensions +end \ No newline at end of file diff --git a/schemas/arch_schema.json b/schemas/arch_schema.json index 6cdedf4a5e..8753fea0ec 100644 --- a/schemas/arch_schema.json +++ b/schemas/arch_schema.json @@ -112,19 +112,22 @@ "description": "Instruction name" } }, - "profile_families": { + "profile_classes": { "type": "object" }, - "profiles": { - "type": "object" + "profile_releases": { + "type": "object", + "items": { + "type": "string" + } }, "manuals": { "type": "object" }, - "crd_families": { + "certificate_classes": { "type": "object" }, - "crds": { + "certificate_models": { "type": "object" } },