On Tuesday, 15 July 2014 at 18:47:28 UTC, bearophile wrote:
The talk was nice, and it's the chance I was waiting to ask a
question to the speaker.
I've read a very nice paper (+ slides) about using some
specialized but simple type system rules to make less bug-prone
the bit-twiddling kind of code, "Bit-Level Types for High-Level
Reasoning" by Ranjit Jhala, Rupak Majumdar:
http://goto.ucsd.edu/~rjhala/papers/bit_level_types_for_high_level_reasoning.html
I'd like to use those ideas in D, they are useful for low-level
or embedded programming.
The D type system (and D syntax) seem enough to implement most
of them without changes to the D language (or with small
changes, but you can't tell before you have tried implementing
them with the current language).
So are those things a good addition to Phobos for your kind of
programming? (additions to the language can be discussed later).
Bye,
bearophile
You may have to summarize it for me, because in my few minutes of
scanning the slides and the PDF, I don't see much difference
between what the authors are proposing and what's provided by
std.bitmanip. (But the paper is pretty researchy, and its hard to
see the forest through the trees).
I use absolute indexes in my code rather than bitwitdhs. I do
this because my datasheet uses absolute indexes, and it's
important for me to be able to cross-reference to my datasheet,
at a glance. This is why I didn't use std.bitmanip.
My other goal is to enforce mutability and access. I want to
make sure I, or my users, know, at compile time, when they are
trying to write to a read-only bitfield or otherwise access a
bitfield incorrectly.
And finally, I want to reduce code size and increase performance.
I don't want to do read-modify-write if I don't have to, not
just for threading concerns, but because that usually results in
more instructions which is detrimental to both code-size and
performance. And, for the same reason, I don't want
function-call overhead.
Anything that helps me achieve these goals is great. D's CTFE,
templates, and mixins really came through for me here.
My registers are modeled like this (enabled by my mmio.d -
https://github.com/JinShil/memory_mapped_io/blob/master/source/mmio.d):
final abstract class RCC : Peripheral!(0x00003800)
{
final abstract class CR : Register!(0x00,
Access.Byte_HalfWord_Word)
{
alias PLLI2SRDY = Bit!(27, Mutability.r);
alias PLLI2SON = Bit!(26, Mutability.rw);
alias PLLRDY = Bit!(25, Mutability.r);
alias PLLON = Bit!(24, Mutability.rw);
alias CSSON = Bit!(19, Mutability.rw);
alias HSEBYP = Bit!(18, Mutability.rw);
alias HSERDY = Bit!(17, Mutability.r);
alias HSEON = Bit!(16, Mutability.rw);
alias HSICAL = BitField!(15, 8, Mutability.r);
alias HSITRIM = BitField!(7, 3, Mutability.rw);
alias HSIRDY = Bit!(1, Mutability.r);
alias HSION = Bit!(0, Mutability.rw);
}
}
... and are used like this:
if (RCC.CR.HSIRDY)
{
RCC.CR.HSION = true;
while(!RCC.CR.HSIRDY);
}
This provides me a high-level abstraction to my bit
manipulations, named fields, no overhead, and compile-time
enforcement of constraints.
What in the authors' proposal is different than what is offered
by std.bitmanip, and how could I leverage it to achieve the goals
stated here?
Mike