HasConstraints
a reference schema for classes with constraints.
Constraints are written in the form of:
<condition> <operation> <action>
Where:
<condition>
: Expression that defines a condition.<action>
: Expression that defines an action.<operation>
: One of -->
(implies) and <->
(if-and-only-if).Note
In this documentation for ease we write constraints as strings A --> B
, however
in the data this is stored as AST.BinaryOp.
The condition must be satisfied to apply the action. In other words:
A --> B
, A
implies that action B
is satisfied
but also if B
is false
then A
is false
(!B --> !A
).A <-> B
means that A
is satisfied if and only if B
is satisfied and vice versa.In both left and right sides we can have complex expressions. For example:
(A && B) <-> !C
(A || B) --> (D == 3 && C)
((D >= 1 && D <= 3) || (E >= 2 && E < 3)) --> (F == "somevalue" && G == 0)
...
Constraints can affect register fields. For example:
A <-> AArch64-IDREG.Xfeature != '0000'
However when doing field compares with integers you have to cast to UInt
or SInt
.
For example:
FEAT_X <-> UInt(AArch64-IDREG.Xfeature) > 0
Note
Usage of UInt
, SInt
is done to keep the syntax as close to ASL, because the
register AArch64-IDREG.Xfeature
is defined as bits, and bits must be cast to an integer in ASL before
any comparative operator (anything other than ==
and !=
) is performed.
Sometimes it is useful to express numerical constraints with register fields values
For example NUM_COUNTERS
can have an equality constraint with AArch64-IDREG.Counters
:
NUM_COUNTERS == UInt(AArch64-IDREG.Counters)
This means when the value of NUM_COUNTERS
is known (or only one value is left in
it's domain), then the value of AArch64-IDREG.Counters
is also known to be equal to
the value of NUM_COUNTERS
. The same applies in reverse.
Important
When constraints are applied the domains on both the left and the right must match!
Therefore the UInt
cast on the right (UInt(AArch64-IDREG.Counters)
)
ensures the domain consistency. Noting that writing the right hand-side without
a UInt
cast will be invalid.
Integer parameters such as NUM_CORES
start from 1
(as a cpu must have at least one core),
however to save space in the architecture AArch64-IDREG.Cores
being set to '00'
might denote 1-Core, meaning the relationship between NUM_CORES
and
AArch64-IDREG.Cores
requires more expressiveness, to achieve this you can do:
NUM_CORES == UInt(AArch64-IDREG.Cores) + 1
You can even express implication of boolean parameters using integers. For example:
MULTICORE_ENABLED <-> NUM_CORES > 1
Meaning, if NUM_CORES
is greater than 1 then MULTICORE_ENABLED
is true
, or
if MULTICORE_ENABLED
is true
, then NUM_CORES
must be greater than 1.
Definitions | Type | Description |
---|---|---|
constraints |
array [
AST.BinaryOp
]
|
List of AST describing constraints which must be satisfied. Examples
|
{
"info": [
"`HasConstraints` a reference schema for classes with constraints.",
"Constraints are written in the form of: ",
[
"```",
" ",
"```"
],
"Where:",
[
" - ``: Expression that defines a condition.",
" - ``: Expression that defines an action.",
" - ``: One of `-->` (implies) and `<->` (if-and-only-if)."
],
[
"!!! NOTE ",
" In this documentation for ease we write constraints **as strings** `A --> B`, however",
" in the data this is stored as $(AST.BinaryOp)."
],
"The condition must be satisfied to apply the action. In other words:",
[
" - `A --> B`, `A` implies that action `B` is satisfied",
" but also if `B` is `false` then `A` is `false` (`!B --> !A`).",
" - `A <-> B` means that `A` is satisfied **if and only if** `B` is satisfied and vice versa."
],
"In both left and right sides we can have complex expressions. For example:",
[
"```",
"(A && B) <-> !C",
"(A || B) --> (D == 3 && C)",
"((D >= 1 && D <= 3) || (E >= 2 && E < 3)) --> (F == \"somevalue\" && G == 0)",
"...",
"```"
],
"Constraints can affect register fields. For example:",
[
"```",
"A <-> AArch64-IDREG.Xfeature != '0000'",
"```"
],
[
"However when doing field compares with integers you have to cast to `UInt` or `SInt`. ",
"For example:"
],
[
"```",
"FEAT_X <-> UInt(AArch64-IDREG.Xfeature) > 0",
"```"
],
"!!! note",
[
" Usage of `UInt`, `SInt` is done to keep the syntax as close to ASL, because the",
" register `AArch64-IDREG.Xfeature` is defined as bits, and bits must be cast to an integer in ASL before",
" any comparative operator (anything other than `==` and `!=`) is performed."
],
[
"Sometimes it is useful to express numerical constraints with register fields values",
"For example `NUM_COUNTERS` can have an equality constraint with `AArch64-IDREG.Counters`:"
],
[
"```",
"NUM_COUNTERS == UInt(AArch64-IDREG.Counters)",
"```"
],
[
"This means when the value of `NUM_COUNTERS` is known (or only one value is left in",
"it's domain), then the value of `AArch64-IDREG.Counters` is also known to be equal to",
"the value of `NUM_COUNTERS`. The same applies in reverse."
],
"!!! important",
[
" **When constraints are applied the domains on both the left and the right must",
" match!**",
" ",
" Therefore the `UInt` cast on the right (`UInt(AArch64-IDREG.Counters)`)",
" ensures the domain consistency. Noting that writing the right hand-side without ",
" a `UInt` cast will be invalid."
],
[
"Integer parameters such as `NUM_CORES` start from `1` (as a cpu must have at least one core),",
"however to save space in the architecture `AArch64-IDREG.Cores` being set to `'00'`",
"might denote 1-Core, meaning the relationship between `NUM_CORES` and",
"`AArch64-IDREG.Cores` requires more expressiveness, to achieve this you can do:"
],
[
"```",
"NUM_CORES == UInt(AArch64-IDREG.Cores) + 1",
"```"
],
"You can even express implication of boolean parameters using integers. For example:",
[
"```",
"MULTICORE_ENABLED <-> NUM_CORES > 1",
"```"
],
[
"Meaning, if `NUM_CORES` is greater than 1 then `MULTICORE_ENABLED` is `true`, or",
"if `MULTICORE_ENABLED` is `true`, then `NUM_CORES` must be greater than 1."
]
],
"additionalProperties": false,
"definitions": {
"constraints": {
"info": [
"List of AST describing constraints which must be satisfied."
],
"type": "array",
"items": {
"$ref": "../AST/BinaryOp.json#/definitions/expression"
},
"examples": [
[
{
"_type": "AST.BinaryOp",
"left": {
"_type": "AST.Identifier",
"value": "A"
},
"op": "<->",
"right": {
"_type": "AST.Identifier",
"value": "B"
}
},
{
"_type": "AST.BinaryOp",
"left": {
"_type": "AST.BinaryOp",
"left": {
"_type": "AST.Identifier",
"value": "A"
},
"op": "&&",
"right": {
"_type": "AST.Identifier",
"value": "B"
}
},
"op": "<->",
"right": {
"_type": "AST.UnaryOp",
"expr": {
"_type": "AST.Identifier",
"value": "C"
},
"op": "!"
}
}
]
]
}
},
"title": "Traits.HasConstraints",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object"
}