Search code examples
dml-lang

How can i specify parameter dependent on index value?


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.


Solution

  • 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;
    }