1

I'm trying to port code from DML 1.2 to DML 1.4. Here is part of code that i ported:

group rx_queue [i < NQUEUES] {
    <...>
    param desctype = i < 64 #? regs.SRRCTL12[i].DESCTYPE.val #: regs.SRRCTL2[i - 64].DESCTYPE.val; // error occurs here
    <...>
}

Error says: error: non-constant expression: cast(i, int64 ) < 64 How can i specify parameter dependent on index value?

I tried to use if...else instead ternary operator, but it says that conditional parameters are not allowed in DML.

odenysex
  • 25
  • 2
  • The provided example is not sufficient to reproduce the error. If I just fill in gaps, I get a device that compiles: dml 1.4; device test; bank regs { register SRRCTL12[i<100] size 1 @ 100+i { field DESCTYPE @ [0]; } register SRRCTL2[i<100] size 1 @ 200+i { field DESCTYPE @ [0]; } } group rx_queue [i < NQUEUES] { param desctype = i < 64 #? regs.SRRCTL12[i].DESCTYPE.val #: regs.SRRCTL2[i - 64].DESCTYPE.val; } – Erik Carstensen Feb 01 '23 at 13:50
  • Oh, the problem is reproduced if you create a (non-dead) method that references desctype. Please add that to your example, so the error is more easily reproduced. – Erik Carstensen Feb 01 '23 at 14:30
  • Update the question to clarify it! – jakobengblom2 Feb 02 '23 at 10:17

1 Answers1

1

Index parameters in DML are a slightly magical expressions; when used from within parameters, they can evaluate to either a constant or a variable depending on where the parameter is used from. Consider the following example:

group g[i < 5] {
  param x = i * 4;
  method m() {
    log info: "%d", x;
    log info: "%d", g[4 - i].x;
    log info: "%d", g[2].x;
  }
}

i becomes an implicit local variable within the m method, and in params, indices are a bit like implicit macro parameters. When the compiler encounters x in the first log statement, the param will expand to i * 4 right away. In the second log statement, the x param is taken from an object indexed with the expression 4 - i, so param expansion will instead insert (5 - i) * 4. In the third log statement, the x param is taken from a constant indexed object, so it expands to 2 * 4 which collapses into the constant 8.

Most uses of desctype will likely happen from contexts where indices are variable, and the #? expression requires a constant boolean as condition, so this will likely give an error as soon as anyone tries to use it.

I would normally advise you to switch from #? to ? in the definition of the desctype param, but that fails in this particular case: DMLC will report error: array index out of bounds on the i - 64 expression. This error is much more confusing, and happens because DMLC automatically evaluates every parameter once with all zero indices, to smoke out misspelled identifiers; this will include evaluation of SRRCTL2[i-64] which collapses into SRRCTL2[-64] which annoys DMLC.

This is arguably a compiler bug; DMLC should probably be more tolerant in this corner. (Note that even if we would remove the zero-indexed validation step from the compiler, your parameter would still give the same error message if it ever would be explicitly referenced with a constant index, like log info: "%d", rx_queue[0].desctype).

The reason why you didn't get an error in DML 1.2 is that DML 1.2 had a single ternary operator ? that unified 1.4's ? and #?; when evaluated with a constant condition the dead branch would be disregarded without checking for errors. This had some strange effects in other situations, but made your particular use case work.

My concrete advise would be to replace the param with a method; this makes all index variables unconditionally non-constant which avoids the problem:

method desctype() -> (uint64) {
  return  i < 64 ? regs.SRRCTL12[i].DESCTYPE.val : regs.SRRCTL2[i - 64].DESCTYPE.val;
}
Erik Carstensen
  • 634
  • 4
  • 14