-
Notifications
You must be signed in to change notification settings - Fork 3
Types
CoreDSL 2 supports arbitrary precision signed and unsigned integer types.
IntegerType ::= ('signed' | 'unsigned') '<' ConstantExpression '>'
| IntegerTypeAlias
The expression in the angle brackets denotes the width/size in bits, and may only comprise literals and implementation parameters. Implementations shall use a two's complement encoding for integer values.
The following type aliases are built-in:
Alias | ... | Maps to |
---|---|---|
char |
signed char |
signed<8> |
short |
signed short |
signed<16> |
int |
signed int |
signed<32> |
long |
signed long |
signed<64> |
bool |
unsigned<1> |
|
unsigned char |
unsigned<8> |
|
unsigned short |
unsigned<16> |
|
unsigned int |
unsigned<32> |
|
unsigned long |
unsigned<64> |
Note that unsigned
/signed
without a size specification is not allowed.
CoreDSL 2 does not offer language support for floating-point types and arithmetic at this time.
Instead, users are encouraged to integrate an external library (software, or IP cores) via the blackbox mechanism.
The keywords float
and double
are reserved for future extensions of CoreDSL.
CoreDSL 2 adopts the C language's array, structure (keyword struct
), union and enumeration (enum
) types, which must be declared in the architectural_state
section.
The bit-field notation in struct
s and union
s is not supported; use the native CoreDSL 2's integer types instead.
struct foo { int bar : 3; unsigned baz : 17; }; // NOT supported
struct foo { signed<3> bar; unsigned<17> baz; }; // <-- use this!
Pointer types and typedef
s are unsupported.
- Ground rule: Never loose precision or sign-information in implicit casts!
- Casting to a wider type results in a zero- or sign-extension, depending on the signedness of the source type.
- Casting to a narrower type results in a truncation of the two's complement-encoded value.
- Casting a signed type to an unsigned type with different size first changes size and then converts to unsigned
- Casting an unsigned type to a signed type with different size first changes size and then converts to signed
- Special casts:
-
(signed)
makes signed data type without changing size -
(unsigned)
makes unsigned data type without changing size
-
unsigned<2> u2; unsigned<3> u3; unsigned<4> u4;
signed<2> s2; signed<3> s3; signed<4> s4;
u3 = u2; // ok, u2 is zero-extended
u3 = u4; // error, prevent implicit truncation
s3 = s2; // ok, s2 is sign-extended
s3 = s4; // error, prevent implicit truncation
u3 = s3; // error, negative values potentially lost
s3 = u3; // error, signed<3> cannot represent value range of unsigned<3>
s3 = u2; // ok, signed<3> can represent unsigned<2> completely
u3 = (unsigned<3>) u4; // explicit truncation
s3 = (signed<3>) s4; // dito
u3 = (unsigned) s3; // sign-bit loses special meaning
s3 = (signed) u3; // u3's MSB will become the sign-bit
u4 = (unsigned<4>) s2; // equivalent to (unsigned) ((signed<4>) s2), s2 is sign-extended
s4 = (signed<4>) u2; // equivalent to (signed) ((unsigned<4>) u2), u2 is zero-extended
// ( ^^ explicit cast is optional here)
u2 = (unsigned<2>) s4; // equivalent to (unsigned) ((signed<2>) s4), s4 is truncated
// (no special handling for sign bit)
s2 = (signed<2>) u4; // equivalent to (signed) ((unsigned<2>) u4), u4 is truncated
NB: In order to sign-extend an unsigned value, e.g. an encoding field that represents a signed immediate, an explicit cast to the same-size signed type is required.
LUI {
encoding: imm[31:12] :: rd[4:0] :: 7'b0110111;
behavior: {
if (rd != 0) {
// WRONG: Zero-extends `imm` to XLEN, then makes it signed. Additionally,
// this results in a type error, because you cannot assign
// `signed<XLEN>` to `unsigned<XLEN>` without an explicit cast.
X[rd] = (signed<XLEN>) imm;
// CORRECT: Sign-extends `imm` to XLEN, then makes it unsigned again.
X[rd] = (unsigned<XLEN>) ((signed) imm));
}
}
}