October 25, 2013
Am Fri, 25 Oct 2013 17:20:23 +0200
schrieb "Timo Sintonen" <t.sintonen@luukku.com>:

> On Friday, 25 October 2013 at 13:07:56 UTC, Daniel Murphy wrote:
> > "Timo Sintonen" <t.sintonen@luukku.com> wrote:
> 
> >> I have not (yet) had any problems when writing io registers but more with read access. Any operation after write should read the register back from real memory and not in processor registers.  Any repetitive read should always read the real io register in memory. The hardware may change the register value at any time.
> >>
> >> Now a very common task like
> >> while (regs.status==0) ...
> >> may be optimized to an endless loop because the memory is read
> >> only once before the loop starts.
> >>
> >> I understood from earlier posts that variables should not be volatile but the operation should. It seems it is possible to guide the compiler like above. So would the right solution be to have a volatile block, similar to synchronized? Inside that block no memory access is optimized.  This way no information of volatility is needed outside the block or in variables used there.
> >>
> >
> > Volatile blocks are already in the language, but they suck.
> > You don't want
> > to have to mark every access as volatile, because all accesses
> > to that
> > hardware register are going to be volatile.  You want it to be
> > automatic.
> >
> > I'm really starting to think intrinsics are the way to go.
> > They are safe,
> > clear, and can be inlined.  The semantics I imagine would be
> > along the lines
> > of llvm's volatile memory accesses
> > (http://llvm.org/docs/LangRef.html#volatile-memory-accesses)
> 
> It seems that it is two different things here. As far as I understand, sharing means something like 'somebody may change my data' and volatility is something like 'I have to know immediately if the data is changed'. It has become obvious that these two are not easy to fit together and make a working model.
> 
> The original question in this thread was to have a proper way to access hardware registers. So far, even the top people have offered only workarounds. I wonder how long D can be marketed as system language if it does not have a defined and reliable way to access system hardware.
> 
> Register access occurs often in time critical places like interrupt routines. A library routine or external function is not a choice. Whatever the feature is, it has to be built in the language. I don't care if it is related to variables, blocks or files as long as I do not have to put these files in a separate directory like I do now.
> 
> I would like to hear more what would be the options. Then we could make a decision what is the right way to go.

What's wrong with the solution Iain mentioned, i.e the way shared is implemented in GDC?

http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2475.1382646532.1719.digitalmars-d:40puremagic.com
http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2480.1382655175.1719.digitalmars-d:40puremagic.com
October 25, 2013
On Friday, 25 October 2013 at 18:12:40 UTC, Johannes Pfau wrote:
> Am Fri, 25 Oct 2013 17:20:23 +0200
> schrieb "Timo Sintonen" <t.sintonen@luukku.com>:
>> It seems that it is two different things here. As far as I understand, sharing means something like 'somebody may change my data' and volatility is something like 'I have to know immediately if the data is changed'. It has become obvious that these two are not easy to fit together and make a working model.
>> 
>> The original question in this thread was to have a proper way to access hardware registers. So far, even the top people have offered only workarounds. I wonder how long D can be marketed as system language if it does not have a defined and reliable way to access system hardware.
>> 
>> Register access occurs often in time critical places like interrupt routines. A library routine or external function is not a choice. Whatever the feature is, it has to be built in the language. I don't care if it is related to variables, blocks or files as long as I do not have to put these files in a separate  directory like I do now.
>> 
>> I would like to hear more what would be the options. Then we could make a decision what is the right way to go.
>
> What's wrong with the solution Iain mentioned, i.e the way shared
> is implemented in GDC?
>
> http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2475.1382646532.1719.digitalmars-d:40puremagic.com
> http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2480.1382655175.1719.digitalmars-d:40puremagic.com

There is nothing wrong if it works.
When I last time discussed about this with you and Iain, I do not remember if this was mentioned. I have been on belief that gdc has no solution.

The second thing is, as I mentioned, that register access is such an important feature in system language that it should be in language specs.

A quick search did not bring any documentation about shared in general and how gdc version is different. TDPL mentions only that shared guarantees the order of operations but does not mention anything about volatility.
Can anybody point to any documentation?
October 25, 2013
On 10/24/2013 9:30 PM, Mike wrote:
> Using peek and poke functions is, well, nah... Better methods exist.  Using
> inline assembly is a reasonable alternative, as is linking to an external C
> library, but why use D then?  Is low-level/embedded software development a
> design goal of the D language?

I've written device drivers and embedded systems. The quantity of code that deals with memory-mapped I/O is a very, very small part of those programs. The subset of that code that needs to exactly control the read and write cycles is tinier still. (For example, when writing to a memory-mapped video buffer, such control is quite unnecessary.)

Any of the methods I presented are not a significant burden.

Adding two lines of inline assembler to get exactly what you want isn't hard, and you can hide it behind a mixin if you like.

And, of course, you'll still need inline assembler to deal with the other system-type operations needed for embedded systems work. For example, setting up the program stack, setting the segment registers, etc. No language provides support for them outside of inline assembler or assembler intrinsics.
October 25, 2013
On 10/24/2013 4:13 AM, eles wrote:
> Anyway, poke's and peek's are a bit more cumbersome than volatile variables,
> since they do not cope so well, for example, with arithmetic expressions.

Why wouldn't they work with arithmetic expressions?

    poke(0x888777, peek(0x12345678) + 1);


> Anyway, still better than nothing. *If* they would exist.

    T peek(T)(T* addr) { return *addr; }

    void poke(T)(T* addr, T value) { *addr = value; }


> IMHO, the embedded and hardware interfacing should get more attention.

D's most excellent support for inline assembler should do nicely.

October 26, 2013
Am Fri, 25 Oct 2013 21:16:29 +0200
schrieb "Timo Sintonen" <t.sintonen@luukku.com>:

> On Friday, 25 October 2013 at 18:12:40 UTC, Johannes Pfau wrote:
> > What's wrong with the solution Iain mentioned, i.e the way
> > shared
> > is implemented in GDC?
> >
> > http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2475.1382646532.1719.digitalmars-d:40puremagic.com
> > http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2480.1382655175.1719.digitalmars-d:40puremagic.com
> 
> There is nothing wrong if it works.
> When I last time discussed about this with you and Iain, I do not
> remember if this was mentioned. I have been on belief that gdc
> has no solution.

Yes, this was news to me as well.
> 
> The second thing is, as I mentioned, that register access is such an important feature in system language that it should be in language specs.
> 
> A quick search did not bring any documentation about shared in
> general and how gdc version is different. TDPL mentions only that
> shared guarantees the order of operations but does not mention
> anything about volatility.
> Can anybody point to any documentation?

Well to be honest I don't think there's any kind of spec related to shared. This is still a very unspecified / fragile part of the language.

(I totally agree though that it should be specified)
October 26, 2013
On 26 October 2013 12:41, Johannes Pfau <nospam@example.com> wrote:
> Am Fri, 25 Oct 2013 21:16:29 +0200
> schrieb "Timo Sintonen" <t.sintonen@luukku.com>:
>
>> On Friday, 25 October 2013 at 18:12:40 UTC, Johannes Pfau wrote:
>> > What's wrong with the solution Iain mentioned, i.e the way
>> > shared
>> > is implemented in GDC?
>> >
>> > http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2475.1382646532.1719.digitalmars-d:40puremagic.com
>> > http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2480.1382655175.1719.digitalmars-d:40puremagic.com
>>
>> There is nothing wrong if it works.
>> When I last time discussed about this with you and Iain, I do not
>> remember if this was mentioned. I have been on belief that gdc
>> has no solution.
>
> Yes, this was news to me as well.

Was added about 3 years ago...

https://github.com/D-Programming-GDC/GDC/commit/f87a03aa2dc619caf076174f857d4e299ce2bd8d

And the type qualifier only got propagated to the declaration just over a year ago.

https://github.com/D-Programming-GDC/GDC/commit/ce3e42c7283616e49728dac050f9fb090c94bfd0


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 26, 2013
On Saturday, 26 October 2013 at 11:43:02 UTC, Johannes Pfau wrote:
> Am Fri, 25 Oct 2013 21:16:29 +0200
> schrieb "Timo Sintonen" <t.sintonen@luukku.com>:
>
>> On Friday, 25 October 2013 at 18:12:40 UTC, Johannes Pfau wrote:
>> > What's wrong with the solution Iain mentioned, i.e the way shared
>> > is implemented in GDC?
>> >
>> > http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2475.1382646532.1719.digitalmars-d:40puremagic.com
>> > http://forum.dlang.org/thread/bifrvifzrhgocrejepvc@forum.dlang.org?page=4#post-mailman.2480.1382655175.1719.digitalmars-d:40puremagic.com
>> 
>> There is nothing wrong if it works.
>> When I last time discussed about this with you and Iain, I do not remember if this was mentioned. I have been on belief that gdc has no solution.
>
> Yes, this was news to me as well.
>> 
>> The second thing is, as I mentioned, that register access is such an important feature in system language that it should be in language specs.
>> 
>> A quick search did not bring any documentation about shared in general and how gdc version is different. TDPL mentions only that shared guarantees the order of operations but does not mention anything about volatility.
>> Can anybody point to any documentation?
>
> Well to be honest I don't think there's any kind of spec related to
> shared. This is still a very unspecified / fragile part of the language.
>
> (I totally agree though that it should be specified)

Seems to work. I can make every member as shared or the whole struct. Not yet tested how it works with property functions or when there are tables or structs as members, but now I get forward in my work.

A little bit sad that the honored leader of the language still thinks that the right way to go is what we did with Commodore 64...
October 26, 2013
On Friday, 25 October 2013 at 20:10:13 UTC, Walter Bright wrote:
> On 10/24/2013 4:13 AM, eles wrote:
>> Anyway, poke's and peek's are a bit more cumbersome than volatile variables,
>> since they do not cope so well, for example, with arithmetic expressions.
>
> Why wouldn't they work with arithmetic expressions?
>
>     poke(0x888777, peek(0x12345678) + 1);
>
>
>> Anyway, still better than nothing. *If* they would exist.
>
>     T peek(T)(T* addr) { return *addr; }
>
>     void poke(T)(T* addr, T value) { *addr = value; }

Frankly, if it is not a big deal, why don't you put those in a std.hardware or std.directaccess module?

If I have to compile those in D outside of main program, why don't allow me to disable the optimizer *for a part* of my D program? Or for a variable?

And if I have to compile those in C, should I go entirely with it and only let the D program to be an "extern int main()"?

OOH you show me it is not a big deal, OTOH you make a big deal from it refusing every support inside the compiler or the standard library.

Should I one day define my own "int plus(int a, int b) { return a+b; }"?
October 27, 2013
On Sat, 2013-10-26 at 14:49 +0200, Timo Sintonen wrote: […]
> A little bit sad that the honored leader of the language still thinks that the right way to go is what we did with Commodore 64...

Not a good style of argument, since the way of the Commodore 64 might be a good one. It isn't, but it might have been.

The core problem with peek and poke for writing device drivers is that hardware controllers do not just use byte structured memory for things, they use bit structures.

So for data I/O,

	device->buffer = value
	value = device->buffer

can be replaced easily with:

	poke(device->buffer, value)
	value = peek(device->buffer)

but this doesn't work when you are using bitfields, you end up having to do all the ugly bit mask manipulation explicitly. Thus, what the equivalent of:

	device->csw.enable = 1
	status = device->csw.ready

is, is left to the imagination.

-- 
Russel. ============================================================================= Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net 41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel@winder.org.uk London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder

October 27, 2013
On Sat, 2013-10-26 at 16:48 +0200, eles wrote:
[…]
> OOH you show me it is not a big deal, OTOH you make a big deal from it refusing every support inside the compiler or the standard library.

I am assuming that the C++ memory model and it's definition of volatile has in some way made the problem go away and expressions such as:

	device->csw.ready

can be constructed such that there is no caching of values and the entity is always read. Given the issues of out of order execution, compiler optimization and multicore, what is their solution?

(The above is a genuine question rather than a troll. Last time I was writing UNIX device drivers seriously was 30+ years ago, in C, and the last embedded systems work was 10 years ago using C with specialist compilers – 8051, AVR chips and the like. I would love to be able to work with the GPIO on a Raspberry Pi with D, it would get me back into all that fun stuff. I am staying away as it looks like a return to C is the only viable just now, unless I learn C++ again.)

> Should I one day define my own "int plus(int a, int b) { return a+b; }"?

Surely,

	a + b

always transforms to

	a.__add__(b)

in all quality languages (*) so that you can redefine the meaning from
the default.


(*) which rules out Java.

-- 
Russel. ============================================================================= Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net 41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel@winder.org.uk London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder