Search code examples
dml-lang

DML Conditional top level "in each" statements


When trying to use in each statements like the following I get an unknown identifier error.

dml 1.4;
param MACRO = true;
#if (MACRO){
    in each bank {
        in each register {
            param something = 1;
        }
    }
}

At compile time this errors out with the following message:

/modules/test-device/test-device.dml:179:6: error: unknown identifier: 'MACRO'

Despite the MACRO value being defined in the same file.

I know conditional in each statements are not allowed under DML and there is even an specific error for it: "conditional 'in each' is not allowed [ECONDINEACH]"

But I am getting a different error and the following snippet works with no problem:

dml 1.4;
#if (dml_1_2){
    in each bank {
        in each register {
            param something = 1;
        }
    }
}

So why am I getting a different error and Is there a way to get around this?


Solution

  • As you mentioned, some statements like in each, but also others like typedef, template, import etc are generally disallowed directly inside an #if. There is a long-standing DML feature request to soften this restriction; in particular, this was critically needed during the DML 1.2 to DML 1.4 migration. The restriction was partially softened by adding a hack that permits top-level #if statements with forbidden statements, as long as the condition only refers to some known constants (true, false and dml_1_2).

    Technically, this workaround is implemented by considering top-level #if statements as completely separate constructs depending on whether the body contains forbidden statements. If it does, the condition is evaluated in a special variable scope that only contains the three symbols true, false and dml_1_2. This explains why the error message changes from conditional 'in each' is not allowed into unknown identifier.

    In your concrete #if (MACRO) example, I don't know a valid way to express that; however, in similar situations you can often solve the problem by making sure the in each statement appears in a subobject of the #if statement; e.g., if you have:

    bank regs {
        #if (MACRO) {
            // compile error: 'in each' directly inside '#if'
            in each register {
                param something = 1;
            }
        }
    }
    

    then you can change it to:

    #if (MACRO) {
        bank regs {
            // ok: 'in each' in a subobject of the '#if'
            in each register {
                param something = 1;
            }
        }
    }
    

    Another approach that sometimes is applicable, is if the MACRO param relates to the choice of code generator for bank skeletons; e.g., if you generate DML code for bank skeletons from IPXACT using two different frameworks, say X and Y, and MACRO determines which of these frameworks was used, then chances are that each of these frameworks instantiates a common template, say x_register vs y_register, on all generated registers, or a common template x_bank vs y_bank on all banks. If you can identify such a template, then you can write:

    in each (x_register, register) {
      // applied to all registers generated by the X framework
      param something = 1;
    }
    

    or:

    in each x_bank {
      in each register {
        param something = 1;
      }
    }