Minres / CoreDSL

Xtext project to parse CoreDSL files
Apache License 2.0
16 stars 3 forks source link

Add a ranged index operator for address spaces #52

Closed jopperm closed 1 year ago

jopperm commented 2 years ago

Idea: Introduce a ranged index operator

X[rd] = MEM[base + 3 : base]; // a 32-bit load

as syntactic sugar for

X[rd] = MEM[base + 3] :: MEM[base + 2] :: MEM[base + 1] :: MEM[base + 0]; // four 8-bit loads

See also https://github.com/Minres/RISCV_ISA_CoreDSL/issues/4 for context.

AtomCrafty commented 2 years ago

While I do like the idea of a ranged index operator, I don't believe this is the best approach. The way your current syntax is structured, it looks like the "start" and "end" operands are independent expressions with no known relationship, so it is impossible to determine the range size and hence the width of the concatenated type at compile time.

It could be mitigated by requiring the second operand to be an identifier name and the first to be an addition node where the first operand is the same identifier, but those are very arbitrary restrictions that will be hard to communicate clearly. I would instead suggest something like X[rd] = MEM[base : 4], where 4 is the number of elements to concatenate (a compile-time constant).

I realize my alternate syntax would only work for one endianness, so it still needs some refinement if we want to support both (i.e. allow to specifiy the order in which the elements are concatenated). Maybe switch the order if the number is negative or something like that.

jopperm commented 2 years ago

[...] it looks like the "start" and "end" operands are independent expressions with no known relationship, so it is impossible to determine the range size and hence the width of the concatenated type at compile time.

Good point, the same problem also ails the bit-range operator, which also would be more useful if it allowed variable offsets (but still fixed range sizes).

eyck commented 2 years ago

Why does it have to be a compile-time constant? And how is -in your view- compile-time defined? Just the parsing? Many other design languages have an elaboratation step to exactly determine these things and even C++ evaluates code during compilation to determine concrete values and ranges. Don't we limit ourselfs by only allowing constants? One constraint I could imagine ranges is that the size of the range has to be fixed. And this should be possible to evaluate...

jopperm commented 2 years ago

To clarify, the bit-range operator is specified to accept literals and parameters, so compile-time in that context already means "after elaboration". I would apply the same terminology to a hypothetical ranged address space access. Still, you currently cannot write a loop that sweeps over the bits of value:

for (i = 0; i < sizeof(x); i += 3)
  x[i+2:i] = ... // prohibited
jopperm commented 2 years ago

In order to not mix up the existing and proposed operator here, I filed a new issue for the extension for bit-range operator here: #57

A ranged access operator for address spaces that only allows compile-constant bounds seems impractical. In any case, the same syntax and rules should be used for both operators.

AtomCrafty commented 2 years ago

@eyck I believe you misunderstood me, I am not proposing to restrict the offset to a compile time constant. The width of the resulting type is what needs to be known at compile time. The issue with two independent expressions is that they don't necessarily have a fixed difference.

Take this example:

function void foo(int a, int b) {
    ??? x = MEM[a:b];
}

The type of x is impossible to determine because it depends on how many elements are selected, i.e. the difference between a and b, whose values are not known at compile time.

That's why I'm saying instead of the array[start:end] syntax we should use array[start:length] instead, where start is still any arbitrary (non-constant) expression, but length must be an expression that can be evaluated at compile time.

Exactly the same goes for the bit-range operator, which should in my opinion also use a length operand instead of end. Not only does that solve the beforementioned problem, but it also avoids repetition as you don't need to type the start offset twice.

And how is -in your view- compile-time defined?

A compile-time constant is any expression that can be constructed from integer literals, ISA parameter references and a limited set of arithmetic and logic operators. An expression is a compile-time constant if and only if the CoreDslConstantExpressionEvaluator (formerly CoreDslInterpreter) can determine its value.

jopperm commented 2 years ago

We settled unanimously on the [start:end] syntax in yesterday's working group meeting. This operator will be specified with a limited set of "patterns" a frontend must understand (like ID_1 + expr_1 : ID_1) to make it feasible to context-check this operator without the need for advanced partial evaluation capabilities.

jopperm commented 2 years ago

See: https://github.com/Minres/CoreDSL/wiki/Expressions#range-operator (diff)

jopperm commented 1 year ago

This was added some time ago. The contextual analysis result works great for the MLIR code generator.