-
Notifications
You must be signed in to change notification settings - Fork 4
Scoping
Julian Oppermann edited this page May 4, 2021
·
15 revisions
CoreDSL 2 defines the following three types of scopes:
-
ISA scope: Contains parameters, registers and address spaces declared in the
architectural_state
section as well as functions declared in thefunctions
section. The ISA scope of anInstructionSet
is nested in the ISA scope of the extendedInstructionSet
, if applicable. - instruction/function scope: Contains the named bitfields in the encoding specification (instructions) respectively the formal arguments (functions), and is nested in the ISA scope.
-
block scopes: Contain local variable declarations. Block scopes are nested according to the usual C rules and the control structure of the
behavior
specification. The outermost block scope is nested in the surrounding instruction/function scope.
The following rules apply to all scope types:
- Every identifier can be declared at most once per scope.
- An identifier reference binds to the first declaration that is encountered when traversing the scope hierarchy outwards. This implies that local declaration may shadow more global ones.
- Inside a particular scope, only declarations occurring before (according to the source code order) are visible.
Example
InstructionSet A {
// ISA scope: param_A, foo_A
architectural_state {
int<32> param_A;
}
instructions {
INST_A {
encoding: field_A[15:0] :: 0xABCD;
behavior:
// instruction scope: field_A + ISA scope
{
// block scope: local_A, local_A2 + instruction scope
int<32> local_A;
// visible here: local_A + instruction scope
if (field_A < 42) {
// nested block scope 1: local_AA + block scope
int<32> local_AA;
} else {
// nested block scope 2: local_A + block scope
int<32> local_A; // shadows local_A from block scope
}
int<32> local_A2;
// visible here: local_A, local_A2 + instruction scope
}
}
}
functions {
void foo_A(int<32> arg_A) {
// function scope: arg_A + ISA scope
// see instruction above for block scopes
}
}
}
InstructionSet B extends A {
// ISA scope: param_B, foo_A, param_A
architectural_state {
int<32> param_B;
}
}
CoreDef
s imply an ISA scope as described above. However, as the provides
clause can reference an arbitrary number of InstructionSet
s, there is no single super scope it could be nested in. Instead, we walk the provides
clause from left to right, put each individual ISA scope hierarchy on an imaginary stack, and remove duplicate scopes. The example below illustrates the procedure for the definition of a core supporting various RISC-V extensions.
│ ┌──────┐ │ ┌──────┐
│ │RVBase│ │ │RVBase│
│ ├──────┤ │ ├──────┤
│ │RV32I │ │ │RV32I │
┌───────────────────────────────┐ │ ├──────┤ │ ├──────┤
│ InstructionSet RVBase │ │ │RVBase│ │ │RV32M │
└───┬───────────┬───────────┬───┘ │ ├──────┤ │ ├──────┤
│extends │extends │extends │ │RV32M │ │ │RV32C │
┌───┴───┐ ┌───┴───┐ ┌───┴───┐ │ ├──────┤ │ ├──────┤
│ RV32I │ │ RV32M │ │ RV32C │ │ │RVBase│ │ │MyCore│
┌──────────────┐ └───┬───┘ └───┬───┘ └───┬───┘ │ ├──────┤ │ └──────┘
│CoreDef MyCore│provides │ │RV32C │ │
│ │─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ┘ │ ├──────┤ │
│ │ │ │MyCore│ │
└──────────────┘ │ └──────┘ │
(a) │ (b) │ (c)
core providing multiple RISC-V extensions │ linearised stack │ deduplicated
│ of scopes │ stack