Separating Compiletime and Runtime
Requirements:
- Code that describes plain hardware should be minimal to write. One shouldn't have to 'break out' of the generative environment to write plain hardware code.
- It should be easy to write generative code mixed with plain hardware.
Differences
Compile Time
Arrays need not be bounded. Integers need not be bounded.
Runtime
Arrays that have dynamic indices must have a fixed size. Integers must be bounded.
Multiplexer inference
There is quite a significant difference between an array access with a constant, and one which should infer a multiplexer, but in both cases the syntax in other languages is exactly the same: my_arr[idx]
The constant index should infer to just a wire connection which costs nothing. In this case the different wires that are part of an array don't have any relation to each other in hardware. This allows us to bestow other properties as well. For example constant indices don't conflict with each other if they don't point to the same element. Runtime indices do. Array wires with constant indices don't enforce any latency requirements upon each other. 'dynamically sized' arrays can only be indexed with compile time indices. Etc.
With a runtime index (based on an integer wire in the design) should infer to a multiplexer. And then of course the array wires do have a relation.
An initial thought to distinguish the two was to just check for constant-ness of the array argument, which can be done at flattening time. But that wouldn't make the distinction clear enough.
Proposal: Require mux
keyword for any runtime array index which should infer to a multiplexer.
Examples:
a[5] = 1
constant index writea[mux b] = 1
multiplexed writex = a[5]
constant index readx = a[mux b]
multiplexed index write