diff --git a/spec/schemas/register_file_schema.json b/spec/schemas/register_file_schema.json new file mode 100644 index 000000000..50ef23dc1 --- /dev/null +++ b/spec/schemas/register_file_schema.json @@ -0,0 +1,130 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + + "title": "Register File Schema", + "description": "Schema for describing a register file", + + "$defs": { + "register_entry": { + "type": "object", + "required": ["name"], + "additionalProperties": false, + "properties": { + "name": { + "$ref": "schema_defs.json#/$defs/register_name" + }, + "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" + }, + "when": { + "$ref": "schema_defs.json#/$defs/requires_entry" + }, + "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", + "items": { + "type": "string", + "enum": [ + "zero", + "return_address", + "stack_pointer", + "global_pointer", + "thread_pointer", + "frame_pointer", + "return_value", + "argument", + "temporary" + ] + }, + "uniqueItems": true + }, + "writable": { + "type": "boolean", + "default": true, + "description": "Whether the register is writable. If false, no sw_write() method is needed." + } + } + }, + "register_file": { + "type": "object", + "required": [ + "$schema", + "kind", + "name", + "long_name", + "description", + "register_length", + "registers" + ], + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "format": "uri-reference", + "const": "register_file_schema.json#", + "description": "Path to schema, relative to /schemas" + }, + "kind": { + "type": "string", + "const": "register_file" + }, + "name": { + "$ref": "schema_defs.json#/$defs/register_file_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"] + }, + "register_length": { + "$ref": "schema_defs.json#/$defs/bit_length_value" + }, + "registers": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/register_entry" + } + }, + "$source": { + "type": "string", + "format": "uri-reference" + } + } + } + } +} diff --git a/spec/schemas/schema_defs.json b/spec/schemas/schema_defs.json index 3b2ed7d73..a5196cd0a 100644 --- a/spec/schemas/schema_defs.json +++ b/spec/schemas/schema_defs.json @@ -43,6 +43,35 @@ ], "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, + "enum": ["MXLEN"] + } + ] + }, + "register_name": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$", + "description": "Register name" + }, + "register_file_name": { + "type": "string", + "pattern": "^[A-Za-z]$", + "description": "Register file 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 809631ea8..88e71d85f 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_, _RegFiles_, and _Control and Status Registers (CSRs)_. +Each extension/instruction/regfile/CSR has its own file. == Flow @@ -142,6 +142,40 @@ H: # <1> === Instructions +=== Register Files + +.Example register file specification +[source,yaml] +---- +$schema: register_file_schema.json# +kind: register_file +name: X +long_name: Integer General Purpose Registers +definedBy: I +register_class: general_purpose +register_length: MXLEN # <1> +registers: + - name: x0 # <2> + abi_mnemonics: [zero] # <3> + roles: [zero] + sw_read(): | # <4> + return 0; + sw_write(value): | + # x0 ignores all writes + - name: x1 + abi_mnemonics: [ra] + roles: [return_address] + - name: x8 + abi_mnemonics: [s0, fp] # <5> + roles: [callee_saved, frame_pointer] +---- + +<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). +<5> A register can have multiple ABI mnemonics (e.g., x8 is known as both s0 and fp). + [source,yaml] ---- add: # <1> diff --git a/spec/std/isa/register_file/X.yaml b/spec/std/isa/register_file/X.yaml new file mode 100644 index 000000000..33e971190 --- /dev/null +++ b/spec/std/isa/register_file/X.yaml @@ -0,0 +1,200 @@ +# Copyright (c) Animesh Agarwal +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/register_file_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. Each register + is MXLEN bits wide, unless XLEN