How to use in each statement with mixed version dml devices?

54 views Asked by At

Got a device with some common code in DML 1.4 where I want to verify a parameter is properly set on all fields of all registers by using and in each statement:

dml 1.4;
//import "each-bank.dml";
template stop_template {
    param stop default true;
}
template dont_stop is stop_template{
    param stop = false;
}
in each bank {
    in each register {
        in each field {
            is stop_template;
            #if (this.stop)
            {
                error "Stop here";
            }
        }
    }
}

For a device in dml 1.2 my error statements triggers on d.o even if I add the template or parameter myself:

dml 1.2;
device each_device;
import "each-import.dml"
bank a {
    register x size 4 @0x0 {
        field alpha @[2:0] {
            is dont_stop;
        }
    }
}
bank d {
    register o size 4 @0x0 is stop_template;
}     
DML-DEP each-device.dmldep
DEP     each-device-dml.d
DMLC    each-device-dml.c
Using the Simics 5 API for test-device module
/modules/test-device/each-device.dml:15:5: In d.o
/modules/test-device/each-import.dml:18:17: error: Stop here
...
gmake: *** [test-device] Error 2

Running the same code with an 1.4 device works as intended. Does the in each statement does not work with mixed devices?

2

There are 2 answers

0
Jonatan Waern On BEST ANSWER

Your issue is that in dml 1.2 registers with no declared fields get one whole-register-covering field implicitly defined by the compilator. This is then picked up by your each-statement, correctly.

To work around this, you need your template to check if it is actually being applied to an explicit field (part of the unfortunate pain that comes with writing common-code for both 1.2 and 1.4).

To do this: use the 1.2 parameter 'explicit' which is set by the compiler, which is 'true' for declared fields only. This parameter is however not present in 1.4, so you need to additionally guard this check with a check on the 'dml_1_2' parameter.

Something along the lines of:

in each bank {
    in each register {
        in each field {
            // We cannot put this inside the hashif, despite wanting to,
            // because DML does not (yet) allow conditional templating on
            // parameters
            is stop_template;
            // This _does_ mean we can check this.stop first, saving us
            // a little bit of code
            #if (this.stop) {
                // It is generally considered good practice to keep
                // dml_1_2 checks in their own #if branch, so that they
                // can be removed wholesale once 1.2 is no longer supported
                #if (dml_1_2) {
                    #if (explicit) {
                        error "Stop here";
                    }
                } #else {
                    error "Stop here";
                }
            }
        }
    }
}

0
Erik Carstensen On

In your case, the problematic code is a consistency check that's not strictly necessary for the device to function, so one option is to just skip this check for DML 1.2, assuming that most remaining DML 1.2 devices are legacy things where not much development is happening. So you can just put the problematic definitions inside #if (!dml_1_2) { } and it will compile again. Note that the compiler has a special case for the dml_1_2 parameter, which allows a top-level #if to contain any kind of top-level statement, including template definitions and typedefs.