Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASENOTES-1.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,3 +363,5 @@
- `release 7 7122`
- `release 6 6437`
- `release 7 7123`
- `note 6` The method implementations that may be incurred by instantiating the `read_field`, `write_field`, `read`, or `write` templates have all
been made overridable. See the documentation of these templates for more details.
69 changes: 46 additions & 23 deletions lib/1.4/dml-builtins.dml
Original file line number Diff line number Diff line change
Expand Up @@ -3563,9 +3563,16 @@ order for a method override to have effect.
in most cases, it is easier to express read operations using the
`read` template.

Note that instantiating `read_field` on a register means that
register reads behave as if the register consists of one single field; a
read access will ignore any actual field subobjects in the register.
Note that instantiating `read_field` on a register incurs a `read_register`
implementation such that reads behave as if the register consists of one single
field; a read access will ignore any actual field subobjects in the register.

This `read_register` implementation is provided by the automatically
instantiated `read_register_via_read_field` template, which you may need
to reference in order to override the implementation — for example in
order to resolve implementation conflicts (through the use of
[Template-Qualified Method Implementation
Calls](language.html#template-qualified-method-implementation-calls).
*/
template read_field {
shared method read_field(uint64 enabled_bits, void *aux) -> (uint64);
Expand All @@ -3588,36 +3595,48 @@ override to have effect. `write_field` is the interface used for
access by registers; in most cases, it is easier to express write
operations using the `write` template.

Note that instantiating `write_field` on a register means that
register writes behave as if the register consists of one single
field; a write access will ignore any actual field subobjects in the
register. This is often useful in read-only registers, as it allows
reads to propagate to fields, while a violating write can be handled
centrally for the whole register.
Note that instantiating `write_field` on a register incurs a `write_register`
implementation such that register writes behave as if the register consists
of one single field; a write access will ignore any actual field subobjects in
the register. This is often useful in read-only registers, as it allows reads
to propagate to fields, while a violating write can be handled centrally for
the whole register.

This `write_register` implementation is provided through the automatically
instantiated `write_register_via_write_field` template, which you may need
to reference in order to override the implementation — for example in
order to resolve implementation conflicts (through the use of
[Template-Qualified Method Implementation
Calls](language.html#template-qualified-method-implementation-calls).
*/
template write_field {
shared method write_field(uint64 val, uint64 enabled_bits, void *aux);
}

template _reg_read_as_field is (register, read_register, read_field) {

template read_register_via_read_field is (register, read_register,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to polish naming convention a bit. It is correct that write_register is instantiated via write_field, but the result of that is that the write_field method is called via the read_register method, i.e. an instance of "via" with reverse direction.

I haven't thought of a better name yet.

Copy link
Contributor Author

@lwaern-intel lwaern-intel Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eliminating the ambiguity can be done by read_register_impl_via_read_field or read_register_impl_from_read_field. These are long and unwieldy... but at the same time, we don't expect people to use reference these very often, and having the name be documentation on its own has its virtue. I'm leaning towards this (specifically the one using "from"). Your opinion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trying to map this to standard OO patterns, it looks a bit like Adapter Pattern, but where all three classes are the same. I.e., register needs a read_register, and we have a read_field, so we create an adapter from read_field to read_register.

Would read_field_to_read_register make sense?

read_field) {
shared method read_register(uint64 enabled_bytes, void *aux)
-> (uint64) {
-> (uint64) default {
return enabled_bytes == 0 ? 0
: this.read_field(enabled_bytes, aux) & enabled_bytes;
}
}

in each (read_field, register) { is _reg_read_as_field; }
in each (read_field, register) { is read_register_via_read_field; }

template _reg_write_as_field is (register, write_register, write_field) {
shared method write_register(uint64 val, uint64 enabled_bytes, void *aux) {
template write_register_via_write_field is (register, write_register,
write_field) {
shared method write_register(uint64 val, uint64 enabled_bytes, void *aux)
default {
if (enabled_bytes != 0) {
this.write_field(val & enabled_bytes, enabled_bytes, aux);
}
}
}

in each (write_field, register) { is _reg_write_as_field; }
in each (write_field, register) { is write_register_via_write_field; }


template _bitsize {
// Must be a multiple of 8 for registers, but not for fields.
Expand All @@ -3640,12 +3659,14 @@ The `read` template is *not* implemented by fields or registers by
default, and must be explicitly instantiated in order for a method
override to have effect.

Note that instantiating `read` on a register means that register reads
behave as if the register consists of one single field; a read access
will ignore any actual field subobjects in the register.
Note that instantiating `read` on a register incurs a `read_register`
implementation such that register reads behave as if the register consists of
one single field; a read access will ignore any actual field subobjects in the
register. For more information, see [`read_field`](#read_field).
*/
template read is (read_field, _get) {
shared method read_field(uint64 enabled_bits, void *aux) -> (uint64) {
shared method read_field(uint64 enabled_bits, void *aux) -> (uint64)
default {
return enabled_bits == 0 ? 0 : this.read() & enabled_bits;
}
// convenience method for simple whole-field access
Expand All @@ -3671,12 +3692,14 @@ The `write` template is *not* implemented by fields or registers by
default, and must be explicitly instantiated in order for a method
override to have effect.

Note that instantiating `write` on a register means that register
writes behave as if the register consists of one single field; a write
access will ignore any actual field subobjects in the register.
Note that instantiating `write` on a register incurs a `write_register`
implementation such that register writes behave as if the register consists of
one single field; a write access will ignore any actual field subobjects in
the register. For more information, see [`write_field`](#write_field).
*/
template write is (write_field, _get, _set) {
shared method write_field(uint64 val, uint64 enabled_bits, void *aux) {
shared method write_field(uint64 val, uint64 enabled_bits, void *aux)
default {
if (enabled_bits != 0) {
local uint64 patched = this.get() & ~enabled_bits;
this.write(patched | (val & enabled_bits));
Expand Down