Create a register alias template that produces an error when aliased to itself

52 views Asked by At

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);
    }
}
1

There are 1 answers

0
Erik Carstensen On BEST ANSWER

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.