Understanding and new language feature proposal

Mike none at none.com
Mon Jan 6 03:17:05 PST 2014


On Monday, 6 January 2014 at 10:31:46 UTC, Sumit Adhikari wrote:
> Again a library will not allow me to extract last drop from my 
> HW - for every library and everybody :). The internal 
> implementation of these libraries are memory hungry and not 
> embedded systems friendly.

I challenge this statement as often the code generated by 
templates can be evaluated at compile time.  This means there is 
no runtime cost except for what is absolutely necessary.  It can 
also reduce code size.

Take a look at this article by Ken Smith, "C++ Register Access 
Redux" 
(http://yogiken.files.wordpress.com/2010/02/c-register-access.pdf). 
  Specifically read pp 9 and 10.  The code generated by the C++ 
code and C code turn out to be EXACTLY the same.

I'm taking this same approach in my embedded system with D.  I 
just wrote it a few hours ago, and haven't run it yet on my 
hardware, but it looks something like this.

enum Policy
{
     Read,
     Write,
     ReadWrite
}

size_t GetValue(size_t address)
{
     return *(cast(size_t*)address);
}

void SetValue(size_t address, size_t value)
{
     *(cast(size_t*)address) = value;
}

mixin template Register(size_t address, size_t resetValue = 0)
{
     struct BitField(TReturnType, size_t msb, size_t lsb, Policy 
policy)
     {
         static @property size_t MSBIndex()
         {
             return msb >= lsb ? msb : lsb;
         }

         static @property size_t LSBIndex()
         {
             return lsb <= msb ? lsb : msb;
         }

         static @property size_t NumOfBits()
         {
             return MSBIndex - LSBIndex + 1;
         }

         @property size_t BitMask()
         {
             return ((1 << NumOfBits()) - 1) << LSBIndex();
         }

		static if (policy == Policy.Read || policy == Policy.ReadWrite)
		{
             @property TReturnType Value()
             {
                 return cast(TReturnType)((GetValue(address) & 
BitMask) >> LSBIndex);
             }
		}

         static if (policy == Policy.Write || policy == 
Policy.ReadWrite)
         {
             @property void Value(TReturnType value)
             {
                 SetValue(address, (GetValue(address) & ~BitMask) 
| ((cast(size_t)value) << LSBIndex));
             }
         }
	}

     static @property size_t ResetValue()
     {
         return resetValue;
     }

     static void Reset()
     {
         Value = resetValue;
     }

     static @property size_t Value()
     {
         return GetValue(address);
     }

     static @property void Value(size_t value)
     {
         SetValue(address, value);
     }
}

//Define your register like this
struct MyRegister
{
     mixin Register!(0x20000000, 0);

     static BitField!(uint, 31, 0, Policy.ReadWrite) Field1;
     static BitField!(ushort, 15, 0, Policy.ReadWrite) Field2;
     static BitField!(bool, 0, 0, Policy.ReadWrite) Field3;
     static BitField!(int, 31, 0, Policy.ReadWrite) Field4;
     static BitField!(int, 31, 0, Policy.ReadWrite) Field4;
}

//Use your register like this
void main()
{
     MyRegister.Field1 = 123;
     MyRegister.Field3 = true;

     ... etc..
}

Mike




More information about the Digitalmars-d mailing list