Skip to content

Statements

Julian Oppermann edited this page Dec 13, 2022 · 10 revisions

General

CoreDSL 2 supports the following standard C constructs:

  • Branches: if / else, switch / case / default
  • Loops: for / while / do...while
  • Jumps: continue / break

Function recursion and irreducible control flow are prohibited.

Assignments

In always blocks and in the behavior specification of instructions, the constructs listed below (and compositions thereof) yield valid lvalues for assignments. In any case, the target must be writable (i.e. not marked const), and the types must be compatible with the casting rules. Lvalue ranges follow the same rules as the range operator.

Declarations for the code examples:

unsigned<13> val;
unsigned<24> arr[16];
struct { unsigned<5> a, unsigned<7> b; } rec;

Access to a scalar entity

val = 42;

Single bit access to a scalar entity

val[11] = 1;

Single element access to an array-typed entity

arr[5] = 17;

Member access to a struct-typed entity

rec.b = 33;

Bit-range access to a scalar entity

val[3:1] = 3'b101;

Element-range access to an array-typed entity

arr[3:0] = arr[12:15];

Spawn blocks

The spawn keyword marks a statement (commonly, a compound statement) for decoupled execution. We refer to this construct as a spawn block, even if only a single statement (e.g. a function call) is marked, to establish an analogy to CoreDSL's always blocks. Spawn blocks are only allowed as the last statement of an instruction's behavior specification, and cannot be nested.

Execution semantics

Instructions can contain behavior of arbitrary complexity, including loops with unknown trip counts. This is unproblematic for software execution in a simulator. In contrast, high-level synthesis tools will try to pipeline the generated hardware in order to maintain a high operating frequency for the core. Still, the tool will attempt to schedule interactions with the core (reading operations, storing values to memory, etc.) to happen in the corresponding stage of the core’s pipeline, in order to maintain the usual guarantees of program order. If the computation takes too long, the core may be stalled automatically, and other instructions cannot overtake the long-running instruction.

without-spawn Long-running custom instruction, [I1], stalling the main pipeline, but maintaining program order by accessing core resources in the corresponding stages.

A spawn block lifts the program order constraint. While it executes, other instructions may already be issued and retired in the main pipeline. The behavior in the spawn block must not make any assumptions about the execution of other instructions that follow it in the main pipeline.

A dependence resolution (DR) mechanism in the core (or in the compiler) is recommended to maintain correct execution semantics. Implementations may reject behavior that is incompatible with their DR mechanism, or could result in deadlocks.

with-spawn

Long-running custom instruction with spawn block, [I1], effectively resulting in an additional, independent pipeline. To access core resources outside the pre-allocated stages, e.g. writing the result in the custom pipeline, bubbles have to be inserted into the main pipeline.

Multiple spawn blocks may be active at runtime. Hence, the implementation must define an arbitration mechanism to access shared resources such as register files or address spaces.