We are converting our register_alias
template from DML 1.2 to DML 1.4. After a few iterations, we were able to get this to work with the help of some helpful compiler warnings.
Here is what we got:
template register_alias {
param target default undefined;
param allocate = false;
is (_set, _get, register);
method read_register(uint64 enabled_bytes, void* aux) -> (uint64) {
local uint64 val;
val = target.read_register(enabled_bytes, aux);
log info: "register_alias read_register()";
return val;
}
method write_register(uint64 value, uint64 enabled_bytes, void *aux) {
log info: "register_alias write_register()";
target.write_register(value, enabled_bytes, aux);
}
method get() -> (uint64) {
local uint64 val;
log info: "register_alias get()";
val = target.get();
return val;
}
method set(uint64 val) {
log info: "register_alias set()";
target.set(val);
}
}
This works, but we wonder why we need to have the following in the template?
is (_set, _get, register);
We thought that when applying a template, it inherits the attributes of the objects on which the template is applied to i.e. in this case the register itself which I believe also uses the _set
, _get
and register
templates.
I assume you got _set
/_get
from the hints given by EAMBINH
. They are not documented (as the leading underscores also hints), and thus unsupported/subject to change. If you explore dml-builtins, you'll see that the register
template instantiates set
and get
, which in turn instantiate _set
and _get
, respectively. So, is register;
is in fact sufficient, and a safer choice.
To answer your question, these templates are needed to resolve overrides: E.g., a bare register
object comes with one implementation of read_register
, through the builtin register
template, and if you instantiate register_alias
in the register there will be two conflicting implementations of the method. The is register
declaration tells DML that the declaration from register_alias
takes precedence. The crucial thing here is that without is register
, the register_alias
template itself has no relation to register
objects, it can just as well be applied to e.g. group
objects. This means that the method declarations inside the register_alias
template do not have a relation to the declarations in the register
template, which results in an ambiguity.
For formal details, please see the Default Methods section of the reference manual.
The reason why this isn't needed in DML 1.2, is that non-default implementations were given precedence over default implementations in some situations. This usually worked OK when there was only one level of overrides, but could give confusing results with multiple levels of overrides. In DML 1.4, the only semantics of the default
annotation on a method is that overrides are permitted; this is more regular compared to DML 1.2, and also consistent with how other OO languages tend to work.