Question about "Alias Registers" concept from Model Builder guide. Would like to produce an error (ideally, a compile time error) when a register alias is accidentally aliased to itself :) Alias registers could be arrays.
Comparing alias parameter to "this" doesn't work :)
This is the register alias example from Model Builder guide:
bank regs {
register X size 4 @ 0x00 is (read_write) "the X register";
register Y size 4 @ 0x04 is (alias) { parameter alias_reg = $X; }
}
template alias {
parameter alias_reg;
parameter allocate = false;
parameter configuration = "none";
parameter desc = "alias of " + $alias_reg.name;
method read_access(generic_transaction_t *mop, msb1, lsb) -> (value) {
log "info", 4: "Redirecting read access to %s", $alias_reg.qname;
inline $alias_reg.read_access(mop, msb1, lsb) -> (value);
}
method write_access(generic_transaction_t *mop, msb1, lsb, value) {
log "info", 4: "Redirecting write access to %s", $alias_reg.qname;
inline $alias_reg.write_access(mop, msb1, lsb, value);
}
}
First, rephrasing your question in terms of DML 1.4 where a direct translation of the alias
template would be:
dml 1.4;
template alias is register {
param alias_reg;
param configuration = "none";
param desc = "alias of " + alias_reg.name;
method read_register(uint64 enabled_bits, void *aux) -> (uint64) {
log info, 4: "Redirecting read access to %s", alias_reg.qname;
return alias_reg.read_register(enabled_bits, aux);
}
method write_register(uint64 value, uint64 enabled_bits, void *aux) {
log info, 4: "Redirecting write access to %s", alias_reg.qname;
alias_reg.write_register(value, enabled_bits, aux);
}
}
And you want the following to give an error:
bank regs {
register Y size 4 @ 0x04 is alias { param alias_reg = Y; }
}
In fact, GCC detects the infinite recursion in generated C code if I use GCC 12.1.0:
sample-device-dml-dml.c:3548:14: error: infinite recursion detected [-Werror=infinite-recursion]
If that's not enough, then you can compare object identities by casting references to object
, something like:
method read_register(uint64 enabled_bits, void *aux) -> (uint64) {
assert cast(alias_reg, object) != cast(this, object);
log info, 4: "Redirecting read access to %s", alias_reg.qname;
return alias_reg.read_register(enabled_bits, aux);
}
This will however silence the GCC warning (GCC understands that the assertion will fail and thus break the infinite recursion)
A third alternative is a compile-time assertion:
method read_register(uint64 enabled_bits, void *aux) -> (uint64) {
#if (cast(alias_reg, object) == cast(this, object)) { error; }
log info, 4: "Redirecting read access to %s", alias_reg.qname;
return alias_reg.read_register(enabled_bits, aux);
}
This approach is nice in some ways, but does not work if you want to declare the methods as shared
.
This could have been resolved by moving the #if
outside the method; however, when I tried this I ran into a compiler bug that caused DMLC to crash; this is now reported as SIMICS-20411.