-
Notifications
You must be signed in to change notification settings - Fork 3
Introduction: Arithmetic and type conversion rules
Despite the syntactic similarity, CoreDSL 2 uses different integer arithmetic semantics than the C language, inspired by the arbitrary-precision (AP) integer types common in HLS environments. The basic idea is that operations never implicitly loose precision or sign-information. For example, the result of an addition of a signed value with 5 bits and and an unsigned value with 5 bits will be signed and 7 bits wide.
The code snippet in below imagines an instruction that computes the luminance of an RGB pixel, which is stored with 10 bits per channel and packed into a general-purpose register. After extracting the individual channels, we need to scale each value with a fractional value, in order to imitate the human colour perception. Lastly, the mean over the channels represents the luminance value. The example highlights how these steps can be expressed naturally at the minimally required precision, without worrying about unnoticed overflows.
This choice of semantics simplifies all CoreDSL 2-based code generators, as fewer corner cases need to be considered. Additionally, it contributes to the generation of resource-efficient hardware in the aforementioned ISAX-HLS use case.
instructions {
LUMINANCE {
encoding: 7'b0 :: rs2[4:0] :: rs1[4:0] :: 3'b011 :: rd[4:0] :: 7'b0010111;
behavior: {
unsigned<10> r, g, b;
// Extract a 10-bit-per-channel RGB pixel from GP register file `X`
r = X[rs1][29:20];
g = X[rs1][19:10];
b = X[rs1][ 9: 0];
// scale for human perception, using 10-bit fractional values
r = (unsigned<10>) (r * 218 >> 10); // 18-bit multiplication and shift
g = (unsigned<10>) (g * 732 >> 10); // 20-bit multiplication and shift
b = (unsigned<10>) (b * 74 >> 10); // 17-bit multiplication and shift
// compute luminance
X[rd] = (r + g + b) / 3;
// ^ ^ ^ 12-bit division
// 12-bit addition
// 11-bit addition
}
}
}