I'm working on an embedded project writing some device drivers to access peripheral control registers as MMIO addresses. Due to D's lack of a `volatile` keyword, I'm trying to come up with a way to define these peripheral control register structures in a way that doesn't require the user of the structure to have to remember to call `volatileStore()` or `volatileLoad()` for each register access separately and I want the interface to be as clean as possible.

In C I would have just declared the entire structure to be `volatile` since the entire thing lives in MMIO address range, and I suppose I'm trying to achieve something close to that...

# Attempt #1

Declare a `Volatile(T)` struct template:

```d
module myproj.volatile;

import core.volatile;

struct Volatile(T)
{
    T v;

    T get()
    {
        return volatileLoad(&v);
    }

    void opAssign(T v)
    {
        volatileStore(&this.v, v);
    }
}
```

Use as:

```d
import myproj.volatile;

struct S
{
    Volatile!uint reg;
    Volatile!uint reg2;
    struct
    {
        Volatile!uint subreg;
    };
}

void vtest()
{
    S * s = cast(S *)0xDEADBEEF;
    while (s.reg.get == 0)
    {
        s.subreg = 1;
    }
}

```

This works but requires that ugly .get call rather than just accessing it directly.

# Attempt #2

```d
module myproj.volatile;

public import core.volatile;

template volatile_field(string type, string name)
{
    mixin("private "~type~" v_"~name~";");
mixin("public @property "~type~" "~name~"() { return volatileLoad(&v_"~name~"); }"); mixin("public @property void "~name~"("~type~" v) { volatileStore(&v_"~name~", v); }");
}

template volatile_ubyte(string name)
{
    mixin volatile_field!("ubyte", name);
}

template volatile_ushort(string name)
{
    mixin volatile_field!("ushort", name);
}

template volatile_uint(string name)
{
    mixin volatile_field!("uint", name);
}

template volatile_ulong(string name)
{
    mixin volatile_field!("ulong", name);
}
```

```d
import myproj.volatile;

struct S
{
    mixin volatile_uint!"reg";
    mixin volatile_uint!"reg2";
    struct
    {
        mixin volatile_uint!"subreg";
    };
}

void vtest()
{
    S * s = cast(S *)0xDEADBEEF;
    while (s.reg == 0)
    {
        s.subreg = 1;
    }
}
```

This works and I like from the user side being able to access each field as if it was just the normal field. However, declaring the fields is a bit uglier syntax.

# Questions

Between the two of these attempts I'm leaning toward #2 because of the easier user syntax to read/write the fields.

I am wondering:

1. Is there any way to improve attempt #1 to not require the .get() call? I tried with opCast() but that requires the user to do an explicit cast which I felt was even worse than the .get 1. Is there any way to improve attempt #2 to make field declaration cleaner than `mixin volatile_uint!"reg"`? 1. Is there any other way of achieving what I'm trying to achieve different from these two methods?

Reply via email to