The Register schema defines the layout of Arm Architecture registers. Below is a guide that represents the general concepts in a register.
A register defines a named layout of fields. For example:
{
"_type": "Register",
"state": "AArch64",
"name": "REG0",
"title": "Register 0",
"purpose": "To describe a simple register in the user guide.",
"fieldsets": [
{
"_type": "Fieldset",
"width": 32,
"values": [
{
"_type": "Fields.Reserved",
"value": "RES0",
"rangeset": [
{
"_type": "Range",
"start": 1,
"width": 31
}
]
},
{
"_type": "Fields.Field",
"name": "F0",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 1
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "Value 0.",
"value": "'0'"
},
{
"_type": "Values.Value",
"meaning": "Value 1.",
"value": "'1'"
}
]
}
}
]
}
]
}
This example shows a 32-bit register called REG0 in the AArch64
state, which has two fields:
RES0 located at bits 31:1, where RES0 is an
architecturally reserved field type which can return any value which
must be read by software as 0. You can read more about this
concept in the Arm architecture.F0 located at bit 0.Note
Field bit positions are always represented with the most
significant bit first, followed by the least significant bit.
For example: MSB:LSB, or 31:1.
Registers are uniquely qualified by the combination of the state
and name, which is denoted by joining the two with -. For
example: AArch64-REG0. Therefore, a register in the external
state which shares the name REG0, ext-REG0, is distinct from
AArch64-REG0 in MRS.
See the Register schema definition for a full list of properties and their usage.
A fieldset in MRS describes an arrangement of bits in a register. Fieldsets are children of registers, and a register can contain many Fieldsets.
{
"_type": "Register",
"state": "AArch64",
"name": "REG0",
"purpose": "To describe a register containing fieldsets.",
"fieldsets": [
{
"_type": "Fieldset",
"width": 64,
"condition": "IsFeatureImplemented(FEAT_A)",
"values": [
{
"_type": "Fields.Reserved",
"value": "RES0",
"rangeset": [
{
"_type": "Range",
"start": 4,
"width": 60
}
]
},
{
"_type": "Fields.Field",
"description": {
"_type": "Description",
"after": null,
"before": "A description of the F1 field."
},
"name": "F1",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The first defined value.",
"value": "'0000'"
},
{
"_type": "Values.Value",
"meaning": "The second defined value.",
"value": "'0011'"
}
]
}
}
]
},
{
"_type": "Fieldset",
"condition": null,
"values": [
{
"_type": "Fields.Reserved",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 64
}
],
"value": "RES1"
}
],
"width": 64
}
]
}
In this example, two fieldsets are contained within a fieldsets
array, defining two distinct layouts of the same register. Where:
FEAT_A is implemented.FEAT_A is not implemented).Note
Conditions can be defined for both Register and Fieldset
models, in addition to other models in MRS. If the condition
for a register is not met, and there is no null condition
specified, the register is absent. However, if defining
conditional fieldsets, you must also specify a null condition
fieldset.
The sum of the widths of the fields in a fieldset must equal the width of the fieldset.
A field in MRS gives the meaning of a specified range of bits
within a fieldset. Fields are children of the values property
of fieldsets. The following example demonstrates a simple field:
{
"_type": "Fields.Field",
"description": {
"_type": "Description",
"after": null,
"before": "A description of the F1 field."
},
"name": "F1",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The first defined value.",
"value": "'0000'"
},
{
"_type": "Values.Value",
"meaning": "The second defined value.",
"value": "'0011'"
},
{
"_type": "Values.Value",
"meaning": "The third defined value.",
"value": "'0100'"
},
{
"_type": "Values.Value",
"meaning": "The fourth defined value.",
"value": "'1110'"
}
]
}
}
Where:
name property is the unique name of bits 3:0, and must
be unique within the fieldset.description describes the field, written in
Arm Markdown Language (AML).values are architecturally defined bit-patterns with defined meanings
(which are also defined in AML).The above example should produce an output of the form:
F1, bits[3:0]
A description of the F1 field.
'0000': The first defined value.'0011': The second defined value.'0100': The third defined value.'1110': The fourth defined value
While different Fields schemas have different required
properties, all fields must have a specified rangeset.
The rangeset encodes the size of the field in bits, and specifies
the location of this field in the containing Fieldset.
See the Fields schema definition for a full list of properties and their usage, including optional properties and default implied values.
An architecture defines bit-patterns which are expressed as values, and which can have an architectural
meaning associated to them. Values defined in a field must fit the
range of the field, for example the field F1 is 4-bits (3:0),
therefore it can only contain values within this range.
Note
The above output shows the short form of values, The
Fields.Field.values property is fully defined as a Valuesets.Values
(a set of Values types), you can see the full canonical
usage in the next example.
You can define conditional values using a Values.ConditionalValue
model. In the example below, the conditional values only have
meaning when FEAT_A is implemented. When FEAT_A is not
implemented these values do not exist.
{
"_type": "Fields.Field",
"description": {
"_type": "Description",
"after": null,
"before": "An example field with conditional fields."
},
"name": "FS",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The first defined value.",
"value": "'0001'"
},
{
"_type": "Values.Value",
"meaning": "The second defined value.",
"value": "'0010'"
},
{
"_type": "Values.ConditionalValue",
"condition": "IsFeatureImplemented(FEAT_A)",
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The third defined value, conditioned on FEAT_A.",
"value": "'1110'"
},
{
"_type": "Values.Value",
"meaning": "The third defined value, conditioned on FEAT_A.",
"value": "'1111'"
}
]
}
}
]
}
}
F1, bits[3:0]
An example field with conditional fields.
'0000': The first defined value.'0011': The second defined value.- when
FEAT_Ais implemented,'0100': The third defined value, conditioned on FEAT_A.- when
FEAT_Ais implemented,'1110': The fourth defined value, conditioned on FEAT_A.
See the Values.ConditionalValue for more information
A field may have an architecturally defined reset value, to which it is set when
the CPU is booted or reset. This is specified using the reset property in fields.
For example:
{
"_type": "Fields.Field",
"description": {
"_type": "Description",
"after": null,
"before": "An example field with conditional fields."
},
"name": "FS",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The value that is set during reset.",
"value": "'0000'"
},
{
"_type": "Values.Value",
"meaning": "Another value set during runtime.",
"value": "'0011'"
}
]
},
"resets": {
"_type": "FieldResets",
"domains": {
"warm": {
"_type": "Values.Value",
"meaning": null,
"value": "'0000'"
}
}
}
}
Where:
domain is under which domain does a reset apply, most commonly
a warm or cold domain is defined which generally relates
a cold (power cycle) reset, vs a warm (during runtime) reset.
These domains and their meaning are defined by the
architecture and not by MRS.'0000'. Reset values may or may not be one of the architecturally
defined values that are valid for this field, but must be within the range of the field (4-bits in this
case)The resets property of a field is used to contain a FieldResets
model, which defines the reset value for the field. You must
usually specify reset behavior for each field, even if the reset
behavior of the field is the default.
As shown in the Fields.Field and Values.ConditionalValue
examples above, the resets property of the field specifies which
domain the reset is defined for (warm), and the value of the
field following a reset of that specified domain
(architecturally unknown).
A Fields.ConstantField model in MRS defines a named read-only field which holds one constant value in an implementation. Here is an example:
{
"_type": "Fields.ConstantField",
"description": {
"_type": "Description",
"after": null,
"before": "An 8-bit value set by an implementation, to define the version"
},
"name": "Version",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 8
}
],
"value": {
"_type": "Values.ImplementationDefined"
}
}
In the example above, Values.ImplementationDefined allows the implementation to specify any constant value.
In some cases, an architecture can create constraints, this is done using the constraint property on Values.ImplementationDefined:
{
"_type": "Fields.ConstantField",
"description": "An 8-bit value set by an implementation, defined by the architecture.",
"name": "Version",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 8
}
],
"value": {
"_type": "Values.ImplementationDefined",
"constraints": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "vMercury architecture.",
"value": "'00000000'"
},
{
"_type": "Values.Value",
"meaning": "vVenus architecture.",
"value": "'00000001'"
},
{
"_type": "Values.Value",
"meaning": "vEarth architecture.",
"value": "'00000010'"
},
{
"_type": "Values.Value",
"meaning": "vMars architecture.",
"value": "'00000011'"
}
]
}
}
}
Alternatively, architecture may define a constant field with a known value:
{
"_type": "Fields.ConstantField",
"description": {
"_type": "Description",
"after": null,
"before": "An 8-bit value set by the architecture."
},
"name": "Constant",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 8
}
],
"value": {
"_type": "Values.Value",
"meaning": "vEarth architecture.",
"value": "'00000010'"
}
}
A Fields.ConditionalField model allows you to define different layouts on a specific range of bits.
You can use Fields.ConditionalField, for example, in cases where a field is added by a feature and is reserved otherwise, or in cases where a field might be different depending on the properties of the implementation. For example:
{
"_type": "Fields.ConditionalField",
"fields": [
{
"condition": "IsFeatureImplemented(FEAT_A)",
"field": {
"_type": "Fields.Field",
"name": "F1",
"description": {
"_type": "Description",
"after": null,
"before": "F1 when FEAT_A is implemented"
},
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {}
}
},
{
"condition": null,
"field": {
"_type": "Fields.Field",
"name": "F2",
"description": {
"_type": "Description",
"after": null,
"before": "F2 otherwise"
},
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {}
}
}
],
"rangeset": [
{
"_type": "Range",
"start": 50,
"width": 4
}
],
"reservedtype": "RES0"
}
Where:
fields array specifies an object with two properties:condition: The condition under which this field applies.
A null condition is the way to specify an otherwise clause.field: A Fields.* type.reservedtype property is a shorthand for the otherwise clause, equivalent to defining a
Fields.ConditionalField with a null condition and containing a field with the specified reserved type.
This can be used to shorthand the otherwise clause. In our example
this property is ignored because the otherwise clause is specified
explicitly in the fields array.rangeset defined in fields is relative to the rangeset
defined in the Fields.ConditionalField, so F1 when resolved is at
53:50.A Fields.Dynamic model allows you to define different layouts of
multiple fields (unlike Fields.ConditionalField which allows you to
specify one varying field). Similar to the fields array in
Fields.ConditionalField, the fieldset that exists at any given
instant is determined by a condition, and you can specify
different properties for each fieldset and the fields it contains.
{
"_type": "Register",
"state": "AArch64",
"name": "REG0",
"purpose": "To describe a register containing a dynamic field.",
"fieldsets": [
{
"_type": "Fieldset",
"width": 32,
"condition": null,
"values": [
{
"_type": "Fields.Dynamic",
"description": {
"_type": "Description",
"after": null,
"before": "A Dynamic field called F_DYNAMIC with layout D1 and D2"
},
"name": "F_DYNAMIC",
"rangeset": [
{
"_type": "Range",
"start": 1,
"width": 31
}
],
"instances": [
{
"_type": "Fieldset",
"name": "D1",
"values": [
{
"_type": "Fields.Reserved",
"rangeset": [
{
"_type": "Range",
"start": 2,
"width": 29
}
],
"value": "RES0"
},
{
"_type": "Fields.Field",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 2
}
],
"name": "F1",
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "Value 0.",
"value": "'00'"
},
{
"_type": "Values.Value",
"meaning": "Value 1.",
"value": "'01'"
}
]
}
}
],
"width": 31
},
{
"_type": "Fieldset",
"name": "D2",
"condition": "IsFeatureImplemented(FEAT_A)",
"values": [
{
"_type": "Fields.Reserved",
"rangeset": [
{
"_type": "Range",
"start": 4,
"width": 27
}
],
"value": "RES0"
},
{
"_type": "Fields.Field",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"name": "F5",
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "Value 0.",
"value": "'0000'"
},
{
"_type": "Values.Value",
"meaning": "Value 1.",
"value": "'0001'"
}
]
}
}
],
"width": 31
}
]
},
{
"_type": "Fields.Reserved",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 1
}
],
"value": "RES0"
}
]
}
]
}
Here you see a dynamic field called F_DYNAMIC with two layouts
D1 and D2. D2 only exists when FEAT_A is implemented and
the fields D1.F1 and D2.F1 are completely different fields.
In some cases a layout may apply, given a value of another field.
For example D1 may apply if a value of FOTHER == '00000'. To
specify this behavior we use a Values.Link within the FOTHER field.
A Fields.ImplementationDefined model in MRS allocates space in a fieldset for implementation-specific fields. Use an implementation defined field to specify bits in a register that an implementation can use as required.
{
"_type": "Fields.ImplementationDefined",
"rangeset": [
{
"_type": "Range",
"start": 8,
"width": 4
}
]
}
The allocated space for implementation defined fields can be divided into as many distinct fields as the implementation requires.
A Fields.Array model defines a fixed number of fields as an array. This is a shorthand method of creating multiple similar fields, which are generated from a single Fields.Array model.
{
"_type": "Fields.Array",
"description": {
"_type": "Description",
"after": null,
"before": "Array of F<n> fields, where n = 0 to 15."
},
"index_variable": "n",
"indexes": [
{
"_type": "Range",
"start": 0,
"width": 16
}
],
"name": "F<n>",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 32
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "Value 0.",
"value": "'00'"
},
{
"_type": "Values.Value",
"meaning": "Value 1.",
"value": "'01'"
},
{
"_type": "Values.Value",
"meaning": "Value 3.",
"value": "'11'"
}
]
}
}
In the example above, the index_variable, indexes,
name, and rangeset properties determine how the array of
fields is generated. For each individual field within the array,
the rangeset is expressed in terms of the index value.
For example:
rangeset of 15:0 and indexes of 15:0 means that
index value n corresponds to bit n, and each field is 1-bit
long.rangeset of 17, 0 and indexes of 1:0 means that index
value n corresponds to bit 17n. Therefore, when the array is expanded
you will have two fields F17 at bit 17 and F0 at bit 0,
and each field is 1 bit long.rangeset of 31:0 for indexes of 15:0, as above, means
that index value n corresponds to bits 2n+1:2n, and each field
is 2 bits long.Note
In the example above, the Fields.Array model automatically
generates 16 fields, named F(0-15). This means that no other
fields within the same fieldset are permitted to share the
name of a field that would be generated from the Fields.Array
model.
A Fields.Reserved model specifies a range of bits that are reserved by Arm for future use.
{
"_type": "Fields.Reserved",
"value": "RES0",
"rangeset": [
{
"_type": "Range",
"start": 56,
"width": 8
}
]
}
The above example defines a RES0 field at bits 63:56.
A Description model in MRS allows you to add descriptive text within another model, such as a register, fieldset, or field, etc. A simple description, where text is only required before the content, can be implemented in a short-hand form as a property of a model:
{
"_type": "Fields.Field",
"description": {
"_type": "Description",
"after": null,
"before": [
"The first paragraph of the F1 field description.",
"The second paragraph of the F1 field description.",
[
"The third paragraph.",
"This line is also part of the third paragraph."
]
]
},
"name": "F1",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {}
}
An array notation is used to provide multiline support in JSON, where:
\n\n, this is due to AARCHMRS using AML, and in markdown
two \n\n denote a split in paragraph.\n break. This is useful when
defining concepts like lists (which require \n), or reduce the
very long lines when writing large paragraphs.Note
You could have used \n inside one long string explicitly and
it will result in the same output
In some cases you need to define some text that appears before values, and other text that appears after them. For example if you wanted to represent the following:
F1, bits[3:0]
My F1 fields with two values
'0000': The first defined value.'0011': The second defined value.My favourite value is '0000'
Here saying "My favourite value is '0000'" before the value
is defined may lead to confusion. Because of this, a description
object can be stored as a dictionary, with before and after
keys.
{
"_type": "Fields.Field",
"description": {
"_type": "Description",
"before": "My F1 fields with two values",
"after": "My favourite value is '0000'"
},
"name": "F1",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 4
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The first defined value.",
"value": "'0000'"
},
{
"_type": "Values.Value",
"meaning": "The second defined value.",
"value": "'0011'"
}
]
}
}
Note
You can use the array notation for multiline support within
before and after values
A mapset array in MRS captures architectural mappings between registers or register blocks, as a property of a Register model. This information automatically generates text in the Configuration section of the System register page, that states which mappings a register has, if any.
Note
When specifying a bi-directional mapping between registers, you must specify the mapsets in both registers. The appropriate mapping information is then automatically rendered as text in the Configuration of both mapped registers. Specifying a mapset in only one register represents a uni-directional mapping.
A register can be mapped to multiple registers, such as
equivalent AArch64, AArch32, and External registers which are
all mapped to each other. However, as mappings can only be
uni-directional or bi-directional, each pairwise mapping must
be individually specified, if more than two registers are
mapped to each other. For example, you must define mapsets
in both AArch64-REG0 and ext-REG0 to capture an
architectural mapping between them in MRS, even if both specify
bi-directional mappings to a AArch32-REG0 register.
Below is an example of a mapset specified in AArch64-REG0:
{
"_type": "Register",
"state": "AArch64",
"name": "REG0",
"title": "Register 0",
"purpose": "To describe a simple register in the user guide.",
"fieldsets": [
{
"_type": "Fieldset",
"width": 32,
"values": [
{
"_type": "Fields.Field",
"name": "F0",
"rangeset": [
{
"_type": "Range",
"start": 0,
"width": 32
}
],
"values": {
"_type": "Valuesets.Values",
"values": [
{
"_type": "Values.Value",
"meaning": "The only known value.",
"value": "'00000000000000000000000000000000'"
}
]
}
}
]
}
],
"mapset": [
{
"_type": "Mapping.RegisterMapping",
"condition": null,
"instance": null,
"mapping_type": "Architectural",
"maps": [
{
"_type": "AST.SquareOp",
"arguments": [
{
"_type": "AST.Slice",
"left": {
"_type": "AST.Integer",
"value": 31
},
"right": {
"_type": "AST.Integer",
"value": 0
}
}
],
"var": {
"_type": "Types.RegisterType",
"value": {
"instance": null,
"name": "REG0",
"slices": null,
"state": "ext"
}
}
}
],
"slices": [
{
"_type": "Range",
"start": 0,
"width": 32
}
]
}
]
}
Note
In ext-REG0 you would need a corresponding mapset mapping back
to AArch64-REG0
You can define a Mapping.RegisterMapping or
Mapping.RegisterBlockMapping model within a mapset array.
See the Mapping.RegisterMapping and Mapping.RegisterBlockMapping
schema definitions for a full list of properties and their usage.
A RegisterBlock encapsulates an array of Register or RegisterBlock object that occupy a contiguous range of the address map, and share a common set of accessors. The accessors define the access behaviors for each of the Registers and RegisterBlocks present in the blocks property.
For examples of the RegisterBlock and a full list of properties and their usage, refer to the RegisterBlock schema definition.