toffe
toffe

Reputation: 63

Field that relies on a value of a different field in the same register in DML 1.4

I have part of a register that looks something like this

register CC {
    field CSS @ [6:4] is write {
        method write(uint64 value) {
            if (CC.EN.val == 0b1) {
                log spec_viol: "Command set selection should not " +
                "occur when controller has been enabled.";
                return;
            }
            default(value);
        }
    }
    field EN @ [0];
}

How can I ensure that when CC.EN is set to 1 (for the first time) by setting the value of the register CC, that the spec-viol in CC.CSS does not occur?

I tried writing to the register for the first time and the spec-viol was triggered

Upvotes: 2

Views: 68

Answers (3)

Erik Carstensen
Erik Carstensen

Reputation: 898

For completeness I want to present the following anti-pattern that occasionally is seen:

register CC {
    session bool was_enabled;

    method write_register(uint64 value, uint64 enabled_bytes, void *aux) {
        was_enabled = EN.val;
        default(value, enabled_bytes, aux);
    }

    field CSS @ [6:4] is write_field {
        method write_field(uint64 value, uint64 enabled_bits, void *aux) {
            if ((this.val & enabled_bits) == (value & enabled_bits))
                return;  // no change, ignore
            if (was_enabled) {
                log spec_viol: "Command set selection should not " +
                "occur when controller has been enabled.";
                return;
            }
            this.val = (this.val & ~enabled_bits) | (value & enabled_bits);
        }
    }

    field EN @ [0];
}

This approach may look compelling compared to the aux approach for type safety reasons; it avoid the need to fiddle with void pointers. However, this approach is problematic both because it allocates permanent storage for a variable that is only used temporarily, and because it is not reentrant (will break if the write_field method of some field indirectly triggers another write to CC synchronously). The reentrancy problem can be resolved by restoring the old value through a local variable, but the added type safety is not worth the complexity.

Upvotes: 0

SvenAron
SvenAron

Reputation: 121

Fields in a register in DML are accessed in order of increasing least significant bit. This means that in your example, the EN field will be written before the CCS field. So to achieve this we must pass the state of EN before the write to the register. We do this by utilizing the void *aux argument in the write_register and write_field templates:

register CC {
    method write_register(uint64 value, uint64 enabled_bytes, void *aux) {
        local bool was_enabled = EN.val;
        default(value, enabled_bytes, &was_enabled);
    }

    field CSS @ [6:4] is write_field {
        method write_field(uint64 value, uint64 enabled_bits, void *aux) {
            if ((this.val & enabled_bits) == (value & enabled_bits))
                return;  // no change, ignore
            if (*cast(aux, *bool)) {
                log spec_viol: "Command set selection should not " +
                "occur when controller has been enabled.";
                return;
            }
            this.val = (this.val & ~enabled_bits) | (value & enabled_bits);
        }
    }

    field EN @ [0];
}

Upvotes: 2

Gustav Wiklander
Gustav Wiklander

Reputation: 97

Another option that does not rely on order:

register CC {
    method write_register(uint64 value, uint64 enabled_bytes, void *aux) {
        if (this.val[EN.msb] && value[EN.msb]) {
            if ((CSS.val & (enabled_bytes[CSS.msb:CSS.lsb])) != (value[CSS.msb : CSS.lsb])) {
                log spec_viol: "%s Command set selection should not " +
                "occur when controller has been enabled.", this.qname;
                value[CSS.msb : CSS.lsb] = CSS.val;
            }

        }
        default(value, enabled_bytes, aux);
    }

    field CSS @ [6:4];
    field EN @ [0] is (write) {
        method write(uint64 value) {
            // Do something...
        }
    }
}

Upvotes: 1

Related Questions