From c386c70f8f07ed5d95948d27c2578ff397c0fd73 Mon Sep 17 00:00:00 2001 From: Animesh Agarwal Date: Thu, 2 Oct 2025 16:43:30 +0530 Subject: [PATCH 1/5] feat: Add GPR Information to UDB Implements General Purpose Register (GPR) support in the Unified Database as requested in issue #1085. Changes: - spec/schemas/register_schema.json: New schema defining structure for register files - spec/schemas/schema_defs.json: Add register-specific schema definition - spec/std/isa/register/gpr.yaml: New register file implementing all 32 RISC-V general purpose registers with proper ABI mnemonics, calling convention roles, and conditional support for RV32E - spec/std/isa/README.adoc: Update architecture documentation to include register files - tools/ruby-gems/udb/lib/udb/obj/register_file.rb: New RegisterFile class extending TopLevelDatabaseObject - tools/ruby-gems/udb/lib/udb/obj/database_obj.rb: Add RegisterFile kind to DatabaseObject::Kind enum for type system integration - tools/ruby-gems/udb/lib/udb/architecture.rb: Add register file loading support to architecture The implementation follows RISC-V ABI specifications and provides a single source of truth for GPR information. Resolves Issue: #1085 --- spec/schemas/register_schema.json | 157 +++++++++++++ spec/schemas/schema_defs.json | 23 ++ spec/std/isa/README.adoc | 37 ++- spec/std/isa/register/gpr.yaml | 217 ++++++++++++++++++ tools/ruby-gems/udb/lib/udb/architecture.rb | 7 + .../ruby-gems/udb/lib/udb/obj/database_obj.rb | 1 + .../udb/lib/udb/obj/register_file.rb | 80 +++++++ 7 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 spec/schemas/register_schema.json create mode 100644 spec/std/isa/register/gpr.yaml create mode 100644 tools/ruby-gems/udb/lib/udb/obj/register_file.rb diff --git a/spec/schemas/register_schema.json b/spec/schemas/register_schema.json new file mode 100644 index 0000000000..1642f242d0 --- /dev/null +++ b/spec/schemas/register_schema.json @@ -0,0 +1,157 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + + "title": "Register File Schema", + "description": "Schema for describing a register file", + + "$defs": { + "count_variant": { + "type": "object", + "required": ["value", "when"], + "additionalProperties": false, + "properties": { + "value": { + "type": "integer", + "description": "Override count when condition is satisfied" + }, + "when": { + "$ref": "schema_defs.json#/$defs/requires_entry" + }, + "description": { + "$ref": "schema_defs.json#/$defs/spec_text" + } + } + }, + "register_entry": { + "type": "object", + "required": ["name", "index"], + "additionalProperties": false, + "properties": { + "name": { + "$ref": "schema_defs.json#/$defs/register_name" + }, + "abi_mnemonic": { + "$ref": "schema_defs.json#/$defs/register_alias" + }, + "index": { + "type": "integer", + "minimum": 0, + "description": "Register index" + }, + "description": { + "$ref": "schema_defs.json#/$defs/spec_text" + }, + "definedBy": { + "$ref": "schema_defs.json#/$defs/requires_entry" + }, + "when": { + "$ref": "schema_defs.json#/$defs/requires_entry" + }, + "length": { + "$ref": "schema_defs.json#/$defs/bit_length_value" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "zero", + "return_address", + "stack_pointer", + "global_pointer", + "thread_pointer", + "frame_pointer", + "return_value", + "argument", + "caller_saved", + "callee_saved", + "temporary" + ] + }, + "uniqueItems": true + } + } + }, + "register_file": { + "type": "object", + "required": [ + "$schema", + "kind", + "name", + "long_name", + "description", + "length", + "registers" + ], + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "format": "uri-reference", + "const": "register_schema.json#", + "description": "Path to schema, relative to /schemas" + }, + "kind": { + "type": "string", + "const": "register_file" + }, + "name": { + "$ref": "schema_defs.json#/$defs/register_name" + }, + "long_name": { + "type": "string" + }, + "description": { + "$ref": "schema_defs.json#/$defs/spec_text" + }, + "definedBy": { + "$ref": "schema_defs.json#/$defs/requires_entry" + }, + "register_class": { + "type": "string", + "enum": ["general_purpose", "floating_point", "vector"] + }, + "length": { + "$ref": "schema_defs.json#/$defs/bit_length_value" + }, + "count": { + "oneOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "type": "object", + "required": ["default"], + "additionalProperties": false, + "properties": { + "default": { + "type": "integer", + "minimum": 0 + }, + "variants": { + "type": "array", + "items": { + "$ref": "#/$defs/count_variant" + } + } + } + } + ] + }, + "registers": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/register_entry" + } + }, + "$source": { + "type": "string", + "format": "uri-reference" + } + } + } + }, + "$ref": "#/$defs/register_file" +} diff --git a/spec/schemas/schema_defs.json b/spec/schemas/schema_defs.json index 3b2ed7d73b..c85b0fe006 100644 --- a/spec/schemas/schema_defs.json +++ b/spec/schemas/schema_defs.json @@ -43,6 +43,29 @@ ], "description": "Location of a field in a register" }, + "bit_length_value": { + "description": "Bit width value for a register or field", + "oneOf": [ + { + "type": "integer", + "minimum": 1 + }, + { + "type": "string", + "minLength": 1 + } + ] + }, + "register_name": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", + "description": "Register name" + }, + "register_alias": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", + "description": "Register alias or ABI mnemonic" + }, "possibly_split_field_location": { "description": "Location specifier for a field", "oneOf": [ diff --git a/spec/std/isa/README.adoc b/spec/std/isa/README.adoc index 809631ea88..fe53ef42e7 100644 --- a/spec/std/isa/README.adoc +++ b/spec/std/isa/README.adoc @@ -29,8 +29,8 @@ Three standard configs are present: * `rv64`: A configuration where only `MXLEN` is known to be 64, i.e., the RV64 ISA. The architecture is specified in a series of https://en.wikipedia.org/wiki/YAML[YAML] -files for _Extensions_, _Instructions_, and _Control and Status Registers (CSRs)_. -Each extension/instruction/CSR has its own file. +files for _Extensions_, _Instructions_, _Registers_, and _Control and Status Registers (CSRs)_. +Each extension/instruction/register/CSR has its own file. == Flow @@ -142,6 +142,39 @@ H: # <1> === Instructions +=== Registers + +.Example register file specification +[source,yaml] +---- +$schema: register_schema.json# +kind: register_file +name: X +long_name: Integer General Purpose Registers +definedBy: I +register_class: general_purpose +length: XLEN # <1> +count: + default: 32 + variants: + - value: 16 + when: { name: E } # <2> +registers: + - name: x0 + index: 0 + abi_mnemonic: zero # <3> + roles: [zero] + - name: x1 + index: 1 + abi_mnemonic: ra + roles: [return_address] +---- + +<1> Register files are defined independently of the resolved XLEN; individual register entries + may override the default bit length when necessary. +<2> Conditional presence uses the same `when`/`definedBy` semantics as other database objects. +<3> Entries can record ABI mnemonics and semantic roles. + [source,yaml] ---- add: # <1> diff --git a/spec/std/isa/register/gpr.yaml b/spec/std/isa/register/gpr.yaml new file mode 100644 index 0000000000..5016400917 --- /dev/null +++ b/spec/std/isa/register/gpr.yaml @@ -0,0 +1,217 @@ +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../schemas/register_schema.json + +$schema: register_schema.json# +kind: register_file +name: X +long_name: General Purpose Registers +description: | + The 'X' register file contains the general-purpose integer registers accessible to + scalar instructions. Register widths track the current XLEN. Register 'x0' is hardwired + to zero, while the remaining registers hold architecturally visible integer state used + by the calling convention and execution environment. +definedBy: I +register_class: general_purpose +length: XLEN +count: + default: 32 + variants: + - value: 16 + when: { name: E } + description: | + The embedded base architecture (E) reduces the integer register file to 16 entries. +registers: + - name: x0 + index: 0 + abi_mnemonic: zero + roles: [zero] + description: | + Register x0 is hardwired with all bits equal to 0. + - name: x1 + index: 1 + abi_mnemonic: ra + roles: [return_address, caller_saved] + description: Return address register used by CALL/JAL instructions. + - name: x2 + index: 2 + abi_mnemonic: sp + roles: [stack_pointer, callee_saved] + description: Stack pointer. + - name: x3 + index: 3 + abi_mnemonic: gp + roles: [global_pointer] + description: Global pointer. + - name: x4 + index: 4 + abi_mnemonic: tp + roles: [thread_pointer] + description: Thread pointer or TLS base. + - name: x5 + index: 5 + abi_mnemonic: t0 + roles: [temporary, caller_saved] + description: Temporary register / linkage scratch. + - name: x6 + index: 6 + abi_mnemonic: t1 + roles: [temporary, caller_saved] + description: Temporary register. + - name: x7 + index: 7 + abi_mnemonic: t2 + roles: [temporary, caller_saved] + description: Temporary register. + - name: x8 + index: 8 + abi_mnemonic: s0 + roles: [callee_saved, frame_pointer] + description: Callee-saved register; used as frame pointer when required. + - name: x9 + index: 9 + abi_mnemonic: s1 + roles: [callee_saved] + description: Callee-saved register. + - name: x10 + index: 10 + abi_mnemonic: a0 + roles: [argument, return_value, caller_saved] + description: Function argument / return value register 0. + - name: x11 + index: 11 + abi_mnemonic: a1 + roles: [argument, return_value, caller_saved] + description: Function argument / return value register 1. + - name: x12 + index: 12 + abi_mnemonic: a2 + roles: [argument, caller_saved] + description: Function argument register 2. + - name: x13 + index: 13 + abi_mnemonic: a3 + roles: [argument, caller_saved] + description: Function argument register 3. + - name: x14 + index: 14 + abi_mnemonic: a4 + roles: [argument, caller_saved] + description: Function argument register 4. + - name: x15 + index: 15 + abi_mnemonic: a5 + roles: [argument, caller_saved] + description: Function argument register 5. + - name: x16 + index: 16 + abi_mnemonic: a6 + roles: [argument, caller_saved] + description: Function argument register 6. + when: + not: { name: E } + - name: x17 + index: 17 + abi_mnemonic: a7 + roles: [argument, caller_saved] + description: Function argument register 7 / syscall ID. + when: + not: { name: E } + - name: x18 + index: 18 + abi_mnemonic: s2 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x19 + index: 19 + abi_mnemonic: s3 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x20 + index: 20 + abi_mnemonic: s4 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x21 + index: 21 + abi_mnemonic: s5 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x22 + index: 22 + abi_mnemonic: s6 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x23 + index: 23 + abi_mnemonic: s7 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x24 + index: 24 + abi_mnemonic: s8 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x25 + index: 25 + abi_mnemonic: s9 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x26 + index: 26 + abi_mnemonic: s10 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x27 + index: 27 + abi_mnemonic: s11 + roles: [callee_saved] + description: Callee-saved register. + when: + not: { name: E } + - name: x28 + index: 28 + abi_mnemonic: t3 + roles: [temporary, caller_saved] + description: Temporary register. + when: + not: { name: E } + - name: x29 + index: 29 + abi_mnemonic: t4 + roles: [temporary, caller_saved] + description: Temporary register. + when: + not: { name: E } + - name: x30 + index: 30 + abi_mnemonic: t5 + roles: [temporary, caller_saved] + description: Temporary register. + when: + not: { name: E } + - name: x31 + index: 31 + abi_mnemonic: t6 + roles: [temporary, caller_saved] + description: Temporary register. + when: + not: { name: E } diff --git a/tools/ruby-gems/udb/lib/udb/architecture.rb b/tools/ruby-gems/udb/lib/udb/architecture.rb index 7126575fc4..7b27baa591 100644 --- a/tools/ruby-gems/udb/lib/udb/architecture.rb +++ b/tools/ruby-gems/udb/lib/udb/architecture.rb @@ -50,6 +50,7 @@ require_relative "obj/certificate" require_relative "obj/csr" require_relative "obj/csr_field" +require_relative "obj/register_file" require_relative "exception_code" require_relative "obj/extension" require_relative "obj/instruction" @@ -175,6 +176,12 @@ def self.generate_obj_methods(fn_name, arch_dir, obj_class) klass: Csr, kind: DatabaseObject::Kind::Csr }, + { + fn_name: "register_file", + arch_dir: "register", + klass: RegisterFile, + kind: DatabaseObject::Kind::RegisterFile + }, { fn_name: "proc_cert_class", arch_dir: "proc_cert_class", diff --git a/tools/ruby-gems/udb/lib/udb/obj/database_obj.rb b/tools/ruby-gems/udb/lib/udb/obj/database_obj.rb index 0ed0cea021..cbdbdc8f39 100644 --- a/tools/ruby-gems/udb/lib/udb/obj/database_obj.rb +++ b/tools/ruby-gems/udb/lib/udb/obj/database_obj.rb @@ -26,6 +26,7 @@ class Kind < T::Enum Csr = new("csr") CsrField = new("csr_field") Extension = new("extension") + RegisterFile = new("register file") Manual = new("manual") ManualVersion = new("manual version") ProcessorCertificateClass = new("processor certificate class") diff --git a/tools/ruby-gems/udb/lib/udb/obj/register_file.rb b/tools/ruby-gems/udb/lib/udb/obj/register_file.rb new file mode 100644 index 0000000000..a015789629 --- /dev/null +++ b/tools/ruby-gems/udb/lib/udb/obj/register_file.rb @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# typed: true +# frozen_string_literal: true + +require_relative "database_obj" +require_relative "../req_expression" + +module Udb + +class RegisterFile < TopLevelDatabaseObject + extend T::Sig + + class RegisterEntry + extend T::Sig + + sig { returns(T::Hash[String, T.untyped]) } + attr_reader :raw + + sig { params(file: RegisterFile, data: T::Hash[String, T.untyped]).void } + def initialize(file, data) + @file = file + @raw = data + end + + sig { returns(String) } + def name = @raw.fetch("name") + + sig { returns(T.nilable(String)) } + def abi_mnemonic = @raw["abi_mnemonic"] + + sig { returns(T.any(Integer, String)) } + def index = @raw.fetch("index") + + sig { returns(T.nilable(String)) } + def description = @raw["description"] + + sig { returns(T::Array[String]) } + def roles = @raw.fetch("roles", []) + + sig { returns(T.nilable(T.any(Integer, String))) } + def length = @raw["length"] + + sig { returns(T.nilable(ExtensionRequirementExpression)) } + def defined_by_condition + return nil unless @raw.key?("definedBy") + + @defined_by_condition ||= ExtensionRequirementExpression.new(@raw.fetch("definedBy"), @file.arch) + end + + sig { returns(T.nilable(ExtensionRequirementExpression)) } + def when_condition + return nil unless @raw.key?("when") + + @when_condition ||= ExtensionRequirementExpression.new(@raw.fetch("when"), @file.arch) + end + end + + sig { returns(T.any(Integer, String)) } + def length = @data.fetch("length") + + sig { returns(T.nilable(String)) } + def summary = @data["summary"] + + sig { returns(T.nilable(String)) } + def register_class = @data["register_class"] + + sig { returns(T.nilable(T.any(Integer, T::Hash[String, T.untyped]))) } + def count = @data["count"] + + sig { returns(T::Array[RegisterEntry]) } + def registers + @registers ||= @data.fetch("registers", []).map { |reg| RegisterEntry.new(self, reg) } + end + + sig { returns(T::Array[T::Hash[String, T.untyped]]) } + def templates = @data.fetch("templates", []) + end + +end From 2d79d0cf1c4d39cf48b40faeacc1b5ef0931aaa2 Mon Sep 17 00:00:00 2001 From: Animesh Agarwal Date: Thu, 9 Oct 2025 14:47:27 +0530 Subject: [PATCH 2/5] fix: align GPR register files with review feedback Changes: - rename schema from register_schema.json to register_file_schema.json, remove "$ref": "#/$defs/register_file" from bottom of the schema, and introduce register_file_name. - drop per-register length and index fields, make abi mnemonics an array, and add 'caller_saved'/'callee_saved' booleans with default value of 'false'. - remove the 'count' helper in favor of conditioning individual register entries directly and infer indices from position. - fix the description for XLEN behavior and remove empty role arrays. - update the register-file section of README.adoc so the example mirrors the new schema. - register_file.rb: expose register data via '#data' and return Sorbet enum values for roles. Signed-off-by: Animesh Agarwal --- ..._schema.json => register_file_schema.json} | 94 +++------ spec/schemas/schema_defs.json | 8 +- spec/std/isa/README.adoc | 39 ++-- spec/std/isa/register/gpr.yaml | 196 ++++++++---------- .../ruby-gems/udb/lib/udb/obj/database_obj.rb | 2 +- .../udb/lib/udb/obj/register_file.rb | 73 +++++-- 6 files changed, 199 insertions(+), 213 deletions(-) rename spec/schemas/{register_schema.json => register_file_schema.json} (57%) diff --git a/spec/schemas/register_schema.json b/spec/schemas/register_file_schema.json similarity index 57% rename from spec/schemas/register_schema.json rename to spec/schemas/register_file_schema.json index 1642f242d0..bfb1d284e9 100644 --- a/spec/schemas/register_schema.json +++ b/spec/schemas/register_file_schema.json @@ -5,50 +5,46 @@ "description": "Schema for describing a register file", "$defs": { - "count_variant": { - "type": "object", - "required": ["value", "when"], - "additionalProperties": false, - "properties": { - "value": { - "type": "integer", - "description": "Override count when condition is satisfied" - }, - "when": { - "$ref": "schema_defs.json#/$defs/requires_entry" - }, - "description": { - "$ref": "schema_defs.json#/$defs/spec_text" - } - } - }, "register_entry": { "type": "object", - "required": ["name", "index"], + "required": ["name"], "additionalProperties": false, "properties": { "name": { "$ref": "schema_defs.json#/$defs/register_name" }, - "abi_mnemonic": { - "$ref": "schema_defs.json#/$defs/register_alias" - }, - "index": { - "type": "integer", - "minimum": 0, - "description": "Register index" + "abi_mnemonics": { + "type": "array", + "items": { + "$ref": "schema_defs.json#/$defs/register_alias" + }, + "minItems": 1, + "uniqueItems": true, + "description": "ABI mnemonic names for the register" }, "description": { "$ref": "schema_defs.json#/$defs/spec_text" }, - "definedBy": { - "$ref": "schema_defs.json#/$defs/requires_entry" - }, "when": { "$ref": "schema_defs.json#/$defs/requires_entry" }, - "length": { - "$ref": "schema_defs.json#/$defs/bit_length_value" + "sw_read()": { + "type": "string", + "description": "Function that returns the value of the register when read by software. Use this to define special behavior for registers (e.g., x0 always reads as zero)." + }, + "sw_write(value)": { + "type": "string", + "description": "Function implementing custom write behavior for the register. Given a 'value', return either the value to be written or a modified value. Use this to define special behavior for registers (e.g., x0 ignores writes)." + }, + "caller_saved": { + "type": "boolean", + "default": false, + "description": "Whether the register is caller-saved" + }, + "callee_saved": { + "type": "boolean", + "default": false, + "description": "Whether the register is callee-saved" }, "roles": { "type": "array", @@ -63,8 +59,6 @@ "frame_pointer", "return_value", "argument", - "caller_saved", - "callee_saved", "temporary" ] }, @@ -80,7 +74,7 @@ "name", "long_name", "description", - "length", + "register_length", "registers" ], "additionalProperties": false, @@ -88,7 +82,7 @@ "$schema": { "type": "string", "format": "uri-reference", - "const": "register_schema.json#", + "const": "register_file_schema.json#", "description": "Path to schema, relative to /schemas" }, "kind": { @@ -96,7 +90,7 @@ "const": "register_file" }, "name": { - "$ref": "schema_defs.json#/$defs/register_name" + "$ref": "schema_defs.json#/$defs/register_file_name" }, "long_name": { "type": "string" @@ -111,34 +105,9 @@ "type": "string", "enum": ["general_purpose", "floating_point", "vector"] }, - "length": { + "register_length": { "$ref": "schema_defs.json#/$defs/bit_length_value" }, - "count": { - "oneOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "object", - "required": ["default"], - "additionalProperties": false, - "properties": { - "default": { - "type": "integer", - "minimum": 0 - }, - "variants": { - "type": "array", - "items": { - "$ref": "#/$defs/count_variant" - } - } - } - } - ] - }, "registers": { "type": "array", "minItems": 1, @@ -152,6 +121,5 @@ } } } - }, - "$ref": "#/$defs/register_file" + } } diff --git a/spec/schemas/schema_defs.json b/spec/schemas/schema_defs.json index c85b0fe006..badc5eed92 100644 --- a/spec/schemas/schema_defs.json +++ b/spec/schemas/schema_defs.json @@ -52,7 +52,8 @@ }, { "type": "string", - "minLength": 1 + "minLength": 1, + "enum": ["MXLEN"] } ] }, @@ -61,6 +62,11 @@ "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", "description": "Register name" }, + "register_file_name": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", + "description": "Register file name" + }, "register_alias": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", diff --git a/spec/std/isa/README.adoc b/spec/std/isa/README.adoc index fe53ef42e7..24675359e9 100644 --- a/spec/std/isa/README.adoc +++ b/spec/std/isa/README.adoc @@ -29,8 +29,8 @@ Three standard configs are present: * `rv64`: A configuration where only `MXLEN` is known to be 64, i.e., the RV64 ISA. The architecture is specified in a series of https://en.wikipedia.org/wiki/YAML[YAML] -files for _Extensions_, _Instructions_, _Registers_, and _Control and Status Registers (CSRs)_. -Each extension/instruction/register/CSR has its own file. +files for _Extensions_, _Instructions_, _RegFiles_, and _Control and Status Registers (CSRs)_. +Each extension/instruction/regfile/CSR has its own file. == Flow @@ -142,38 +142,39 @@ H: # <1> === Instructions -=== Registers +=== Register Files .Example register file specification [source,yaml] ---- -$schema: register_schema.json# +$schema: register_file_schema.json# kind: register_file name: X long_name: Integer General Purpose Registers definedBy: I register_class: general_purpose -length: XLEN # <1> -count: - default: 32 - variants: - - value: 16 - when: { name: E } # <2> +register_length: MXLEN # <1> registers: - - name: x0 - index: 0 - abi_mnemonic: zero # <3> + - name: x0 # <2> + abi_mnemonics: [zero] # <3> roles: [zero] + sw_read(): | # <4> + return 0; + sw_write(value): | + # x0 ignores all writes - name: x1 - index: 1 - abi_mnemonic: ra + abi_mnemonics: [ra] roles: [return_address] + - name: x8 + abi_mnemonics: [s0, fp] # <5> + roles: [callee_saved, frame_pointer] ---- -<1> Register files are defined independently of the resolved XLEN; individual register entries - may override the default bit length when necessary. -<2> Conditional presence uses the same `when`/`definedBy` semantics as other database objects. -<3> Entries can record ABI mnemonics and semantic roles. +<1> Registers can have either a fixed architecture width or take their width from a parameter (e.g., MXLEN, VLEN). +<2> Each register has a unique name (e.g., x0, x1, x2, etc.). The register's index is inferred from its position in the array (starting from 0). +<3> Registers can optionally have ABI mnemonics (e.g., ra, sp, fp, etc.). +<4> Individual registers can define `sw_read()` and `sw_write()` for special behavior (e.g., x0 hardwired to zero). +<5> A register can have multiple ABI mnemonics (e.g., x8 is known as both s0 and fp). [source,yaml] ---- diff --git a/spec/std/isa/register/gpr.yaml b/spec/std/isa/register/gpr.yaml index 5016400917..59a009d5f9 100644 --- a/spec/std/isa/register/gpr.yaml +++ b/spec/std/isa/register/gpr.yaml @@ -1,217 +1,201 @@ +# Copyright (c) Animesh Agarwal # SPDX-License-Identifier: BSD-3-Clause-Clear -# yaml-language-server: $schema=../../../schemas/register_schema.json +# yaml-language-server: $schema=../../../schemas/register_file_schema.json -$schema: register_schema.json# +$schema: register_file_schema.json# kind: register_file name: X long_name: General Purpose Registers description: | - The 'X' register file contains the general-purpose integer registers accessible to - scalar instructions. Register widths track the current XLEN. Register 'x0' is hardwired - to zero, while the remaining registers hold architecturally visible integer state used + The 'X' register file contains the general-purpose integer registers. Each register + is architecturally XLEN bits wide, unless XLEN Date: Tue, 28 Oct 2025 11:19:21 +0530 Subject: [PATCH 3/5] fix: add writable property to register entry and update file name pattern Changes: - Add 'writable' boolean property to register schema to indicate if a register is writable. - Update gpr.yaml to X.yaml, register directory to register_file. - Restrict regex for register_file_name to a single character. - Update README.adoc. Signed-off-by: Animesh Agarwal --- spec/schemas/register_file_schema.json | 5 +++++ spec/schemas/schema_defs.json | 2 +- spec/std/isa/README.adoc | 2 +- .../isa/{register/gpr.yaml => register_file/X.yaml} | 11 +++++------ 4 files changed, 12 insertions(+), 8 deletions(-) rename spec/std/isa/{register/gpr.yaml => register_file/X.yaml} (93%) diff --git a/spec/schemas/register_file_schema.json b/spec/schemas/register_file_schema.json index bfb1d284e9..50ef23dc1d 100644 --- a/spec/schemas/register_file_schema.json +++ b/spec/schemas/register_file_schema.json @@ -63,6 +63,11 @@ ] }, "uniqueItems": true + }, + "writable": { + "type": "boolean", + "default": true, + "description": "Whether the register is writable. If false, no sw_write() method is needed." } } }, diff --git a/spec/schemas/schema_defs.json b/spec/schemas/schema_defs.json index badc5eed92..a5196cd0af 100644 --- a/spec/schemas/schema_defs.json +++ b/spec/schemas/schema_defs.json @@ -64,7 +64,7 @@ }, "register_file_name": { "type": "string", - "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", + "pattern": "^[A-Za-z]$", "description": "Register file name" }, "register_alias": { diff --git a/spec/std/isa/README.adoc b/spec/std/isa/README.adoc index 24675359e9..88e71d85f9 100644 --- a/spec/std/isa/README.adoc +++ b/spec/std/isa/README.adoc @@ -170,7 +170,7 @@ registers: roles: [callee_saved, frame_pointer] ---- -<1> Registers can have either a fixed architecture width or take their width from a parameter (e.g., MXLEN, VLEN). +<1> The registers in a register file have identical fixed widths, either an explicit width or from a parameter (e.g. MXLEN or VLEN). <2> Each register has a unique name (e.g., x0, x1, x2, etc.). The register's index is inferred from its position in the array (starting from 0). <3> Registers can optionally have ABI mnemonics (e.g., ra, sp, fp, etc.). <4> Individual registers can define `sw_read()` and `sw_write()` for special behavior (e.g., x0 hardwired to zero). diff --git a/spec/std/isa/register/gpr.yaml b/spec/std/isa/register_file/X.yaml similarity index 93% rename from spec/std/isa/register/gpr.yaml rename to spec/std/isa/register_file/X.yaml index 59a009d5f9..33e971190d 100644 --- a/spec/std/isa/register/gpr.yaml +++ b/spec/std/isa/register_file/X.yaml @@ -1,7 +1,7 @@ # Copyright (c) Animesh Agarwal # SPDX-License-Identifier: BSD-3-Clause-Clear -# yaml-language-server: $schema=../../../schemas/register_file_schema.json +# yaml-language-server: $schema=../../../../schemas/register_file_schema.json $schema: register_file_schema.json# kind: register_file @@ -9,9 +9,9 @@ name: X long_name: General Purpose Registers description: | The 'X' register file contains the general-purpose integer registers. Each register - is architecturally XLEN bits wide, unless XLEN Date: Wed, 29 Oct 2025 11:59:51 +0530 Subject: [PATCH 4/5] fix: update description of X.yaml --- spec/std/isa/register_file/X.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/std/isa/register_file/X.yaml b/spec/std/isa/register_file/X.yaml index 33e971190d..95ada7da0e 100644 --- a/spec/std/isa/register_file/X.yaml +++ b/spec/std/isa/register_file/X.yaml @@ -9,9 +9,9 @@ name: X long_name: General Purpose Registers description: | The 'X' register file contains the general-purpose integer registers. Each register - is MXLEN bits wide, unless XLEN Date: Wed, 29 Oct 2025 18:37:41 +0530 Subject: [PATCH 5/5] fix: correct trailing spaces in description of X.yaml --- spec/std/isa/register_file/X.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/std/isa/register_file/X.yaml b/spec/std/isa/register_file/X.yaml index 95ada7da0e..73393aeb95 100644 --- a/spec/std/isa/register_file/X.yaml +++ b/spec/std/isa/register_file/X.yaml @@ -9,8 +9,8 @@ name: X long_name: General Purpose Registers description: | The 'X' register file contains the general-purpose integer registers. Each register - is MXLEN bits wide, but will appear to be XLEN bits wide if XLEN