comp.lang.ada
 help / color / mirror / Atom feed
* Type-safe low-level programming?
@ 2003-02-18  0:06 Bernd Trog
  2003-02-18  2:04 ` David C. Hoos, Sr.
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Bernd Trog @ 2003-02-18  0:06 UTC (permalink / raw)


Hi,
lets say I've something like this:

pragma No_Run_Time;

type Bit_Number is range 0 .. 7;
type Address_Type is range 0 .. 16#ff#;

Register_A : constant Address_Type := 1;
Bit_A1 : constant Bit_Number := 4;  --Register A, Bit 4
Bit_A2 : constant Bit_Number := 1;
Bit_A3 : constant Bit_Number := 7;

Register_B : constant Address_Type = 2;
Bit_B1 : constant Bit_Number :=4;
Bit_B2 : constant Bit_Number :=2;
Bit_B3 : constant Bit_Number :=5;
[...]
Register_Z : constant Address_Type = 2;
Bit_Z1 : constant Bit_Number :=6;
Bit_Z2 : constant Bit_Number :=0;
Bit_Z3 : constant Bit_Number :=5;

procedure Set_Bit( Adr : in Address_Type; Nr : in Bit_Number );
procedure Clear_Bit( Adr : in Address_Type; Nr : in Bit_Number );

On a not-so-good day I wrote:
Set_Bit( Register_A, Bit_B3 );
and found my error days later :-(

Now I wonder, if its possible to make 'Set_Bit' type-safe *without*
increasing the program memory size for every new register?


Bernd



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Type-safe low-level programming?
  2003-02-18  0:06 Type-safe low-level programming? Bernd Trog
@ 2003-02-18  2:04 ` David C. Hoos, Sr.
  2003-02-18 10:39 ` Hans-Bernhard Broeker
  2003-02-18 14:53 ` Steve
  2 siblings, 0 replies; 6+ messages in thread
From: David C. Hoos, Sr. @ 2003-02-18  2:04 UTC (permalink / raw)
  To: comp.lang.ada mail to news gateway

You could do something like this:

pragma No_Run_Time;
subtype Bit_Number is Natural range 0 .. 7;
type Bit is mod 2;
subtype Address_Type is Natural range 0 .. 16#Ff#;
subtype Bit_Index is Natural range 0 .. (Bit_Number'Last + 1) *
    (Address_Type'Last  + 1) - 1;
type Registers is array (Bit_Index) of Bit;
pragma Pack (Registers);
Storage_Unit : constant Natural := Bit_Number'Last + 1;

Register_A : constant Address_Type := 0;
Bit_A1 : constant Bit_Index := 4 + Register_A * Storage_Unit;
Bit_A2 : constant Bit_Index := 1 + Register_A * Storage_Unit;
Bit_A3 : constant Bit_Index := 7 + Register_A * Storage_Unit;

Register_B : constant Address_Type := 1;
Bit_B1 : constant Bit_Index := 4 + Register_B * Storage_Unit;
Bit_B2 : constant Bit_Index := 2 + Register_B * Storage_Unit;
Bit_B3 : constant Bit_Index := 5 + Register_B * Storage_Unit;

Register_Z : constant Address_Type := 25;
Bit_Z1 : constant Bit_Index := 6 + Register_Z * Storage_Unit;
Bit_Z2 : constant Bit_Index := 0 + Register_Z * Storage_Unit;
Bit_Z3 : constant Bit_Index := 5 + Register_Z * Storage_Unit;

procedure Set_Bit (Regs : in Registers; Idx : in Bit_Index);
procedure Clear_Bit (Regs : in Registers; Idx : in Bit_Index);

Once all of the Bit_Index constants are correctly declared, they
contain within their values the register number as well.

This also simplifies the Set and Clear procedures, as well,
because the specific bit is accessed simply as Regs (Idx)

 
----- Original Message ----- 
From: "Bernd Trog" <berndtrog@yahoo.com>
Newsgroups: comp.lang.ada,comp.arch.embedded
To: <comp.lang.ada@ada.eu.org>
Sent: February 17, 2003 6:06 PM
Subject: Type-safe low-level programming?


> Hi,
> lets say I've something like this:
> 
> pragma No_Run_Time;
> 
> type Bit_Number is range 0 .. 7;
> type Address_Type is range 0 .. 16#ff#;
> 
> Register_A : constant Address_Type := 1;
> Bit_A1 : constant Bit_Number := 4;  --Register A, Bit 4
> Bit_A2 : constant Bit_Number := 1;
> Bit_A3 : constant Bit_Number := 7;
> 
> Register_B : constant Address_Type = 2;
> Bit_B1 : constant Bit_Number :=4;
> Bit_B2 : constant Bit_Number :=2;
> Bit_B3 : constant Bit_Number :=5;
> [...]
> Register_Z : constant Address_Type = 2;
> Bit_Z1 : constant Bit_Number :=6;
> Bit_Z2 : constant Bit_Number :=0;
> Bit_Z3 : constant Bit_Number :=5;
> 
> procedure Set_Bit( Adr : in Address_Type; Nr : in Bit_Number );
> procedure Clear_Bit( Adr : in Address_Type; Nr : in Bit_Number );
> 
> On a not-so-good day I wrote:
> Set_Bit( Register_A, Bit_B3 );
> and found my error days later :-(
> 
> Now I wonder, if its possible to make 'Set_Bit' type-safe *without*
> increasing the program memory size for every new register?
> 
> 
> Bernd
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
> 
> 




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Type-safe low-level programming?
  2003-02-18  0:06 Type-safe low-level programming? Bernd Trog
  2003-02-18  2:04 ` David C. Hoos, Sr.
@ 2003-02-18 10:39 ` Hans-Bernhard Broeker
  2003-02-18 16:21   ` Thad Smith
  2003-02-18 16:52   ` Hans-Bernhard Broeker
  2003-02-18 14:53 ` Steve
  2 siblings, 2 replies; 6+ messages in thread
From: Hans-Bernhard Broeker @ 2003-02-18 10:39 UTC (permalink / raw)


In comp.arch.embedded Bernd Trog <berndtrog@yahoo.com> wrote:

> Now I wonder, if its possible to make 'Set_Bit' type-safe *without*
> increasing the program memory size for every new register?

The only way I see is to drop the idea of passing the register and the
bit number inside that register as independent parameters --- they
aren't independent, and pretending they are is what causes your grief.
The need to introduce a comment to explain what Bit_A1 is supposed to
mean should have given you the hint.

What you need would be more like

  type Bit_Number is range 0 .. 8*16#ff#);

  Register_A : constant Address_Type := 1;

  Bit_A1 : constant Bit_Number := Register_A*8 + 4; 
  Bit_A2 : constant Bit_Number := Register_A*8 + 1;
[...]

and then

	procedure Set_Bit(Nr : in Bit_Number );

which would split up the Bit_Number in two parts, one to address a
register, the other to address bits inside that register.

Disclaimer: the above are the first lines of Ada code I ever edited in
my life, so don't trust them any further than you can throw your car
;-)
-- 
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Type-safe low-level programming?
  2003-02-18  0:06 Type-safe low-level programming? Bernd Trog
  2003-02-18  2:04 ` David C. Hoos, Sr.
  2003-02-18 10:39 ` Hans-Bernhard Broeker
@ 2003-02-18 14:53 ` Steve
  2 siblings, 0 replies; 6+ messages in thread
From: Steve @ 2003-02-18 14:53 UTC (permalink / raw)


Here is one way to get there:

  TYPE Bit_Number IS RANGE 0 .. 7;
  TYPE Address_Type IS RANGE 0 .. 16#ff#;

  TYPE Reg_A_Bit_Number IS NEW Bit_Number;
  TYPE Reg_B_Bit_Number IS NEW Bit_Number;
  TYPE Reg_Z_Bit_Number IS NEW Bit_Number;

  TYPE Reg_A_Address_Type IS NEW Address_Type;
  TYPE Reg_B_Address_Type IS NEW Address_Type;
  TYPE Reg_Z_Address_Type IS NEW Address_Type;

  Register_A : CONSTANT Reg_A_Address_Type := 1;
  Bit_A1 : CONSTANT Reg_A_Bit_Number := 4; --Register A, Bit 4
  Bit_A2 : CONSTANT Reg_A_Bit_Number := 1;
  Bit_A3 : CONSTANT Reg_A_Bit_Number := 7;

  Register_B : CONSTANT Reg_B_Address_Type := 2;
  Bit_B1 : CONSTANT Reg_B_Bit_Number :=4;
  Bit_B2 : CONSTANT Reg_B_Bit_Number :=2;
  Bit_B3 : CONSTANT Reg_B_Bit_Number :=5;

  Register_Z : CONSTANT Reg_Z_Address_Type := 2;
  Bit_Z1 : CONSTANT Reg_Z_Bit_Number :=6;
  Bit_Z2 : CONSTANT Reg_Z_Bit_Number :=0;
  Bit_Z3 : CONSTANT Reg_Z_Bit_Number :=5;

  PROCEDURE Set_Bit_Exp( Adr : IN Address_Type; Nr : IN Bit_Number );
  PRAGMA Export( Ada, Set_Bit_Exp, "Set_Bit_Exp" );

  PROCEDURE Clear_Bit_Exp( Adr : IN Address_Type; Nr : IN Bit_Number );
  PRAGMA Export( Ada, Clear_Bit_Exp, "Clear_Bit_Exp" );

  PROCEDURE Set_Bit( Adr : IN Reg_A_Address_Type; Nr : IN
Reg_A_Bit_Number );
  PROCEDURE Set_Bit( Adr : IN Reg_B_Address_Type; Nr : IN
Reg_B_Bit_Number );
  PROCEDURE Set_Bit( Adr : IN Reg_Z_Address_Type; Nr : IN
Reg_Z_Bit_Number );
  PRAGMA Import( Ada, Set_Bit, "Set_Bit_Exp" );

  PROCEDURE Clear_Bit( Adr : IN Reg_A_Address_Type; Nr : IN
Reg_A_Bit_Number );
  PROCEDURE Clear_Bit( Adr : IN Reg_B_Address_Type; Nr : IN
Reg_B_Bit_Number );
  PROCEDURE Clear_Bit( Adr : IN Reg_Z_Address_Type; Nr : IN
Reg_Z_Bit_Number );
  PRAGMA Import( Ada, Clear_Bit, "Clear_Bit_Exp" );

Using the export and import clauses only one instance of Set_Bit_Exp and
Clear_Bit_Exp are created.  This is a bit of a "trick" to have type checking
while not having type checking (if you know what I mean).

You could also try defining the different types as shown as well as separate
instances of the routines, only define them all as in-line.  I suspect the
complexity of your Set_Bit and Clear_Bit functions would be so simple that
in-line code would not increase the size.

You could also try creating the routines as generic, with a different
instance for each type.  Some compilers would share code.

Steve
(The Duck)

"Bernd Trog" <berndtrog@yahoo.com> wrote in message
news:cbdd91ae.0302171606.57d2ba77@posting.google.com...
> Hi,
> lets say I've something like this:
>
> pragma No_Run_Time;
[snip]

> On a not-so-good day I wrote:
> Set_Bit( Register_A, Bit_B3 );
> and found my error days later :-(
>
> Now I wonder, if its possible to make 'Set_Bit' type-safe *without*
> increasing the program memory size for every new register?
>
>
> Bernd





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Type-safe low-level programming?
  2003-02-18 10:39 ` Hans-Bernhard Broeker
@ 2003-02-18 16:21   ` Thad Smith
  2003-02-18 16:52   ` Hans-Bernhard Broeker
  1 sibling, 0 replies; 6+ messages in thread
From: Thad Smith @ 2003-02-18 16:21 UTC (permalink / raw)


Hans-Bernhard Broeker wrote:
> 
> In comp.arch.embedded Bernd Trog <berndtrog@yahoo.com> wrote:
> 
> > Now I wonder, if its possible to make 'Set_Bit' type-safe *without*
> > increasing the program memory size for every new register?
> 
> The only way I see is to drop the idea of passing the register and the
> bit number inside that register as independent parameters --- they
> aren't independent, and pretending they are is what causes your grief.
> The need to introduce a comment to explain what Bit_A1 is supposed to
> mean should have given you the hint.
> 
> What you need would be more like
> 
>   type Bit_Number is range 0 .. 8*16#ff#);
> 
>   Register_A : constant Address_Type := 1;
> 
>   Bit_A1 : constant Bit_Number := Register_A*8 + 4;
>   Bit_A2 : constant Bit_Number := Register_A*8 + 1;

Good point.  A note to fellow comp.arch.embedded readers: this also
works as well in other languages.  I have used a similar scheme in C and
assembly, bundling the port address and bit number and number of bits
and bit polarity into a single macro definition.  A single macro
invocation, such as 

	SetOutput (RF_ATTENUATOR, 1);

can be used to set the correct bit in the correct port.  An I/O
definition header file defines all I/O signals in terms of the
application, not port/bit names.  Changing the port assignment or
inverting the sense of an I/O signal is done in the definition file.

The code generated is close to optimal, since the compiler is working on
constant definitions, which it can optimize well and no function calls
are required.

The biggest downside is that the macro definitions (in C) look like a
bowl of Chinese Alphabet soup to handle all the details.

Thad



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Type-safe low-level programming?
  2003-02-18 10:39 ` Hans-Bernhard Broeker
  2003-02-18 16:21   ` Thad Smith
@ 2003-02-18 16:52   ` Hans-Bernhard Broeker
  1 sibling, 0 replies; 6+ messages in thread
From: Hans-Bernhard Broeker @ 2003-02-18 16:52 UTC (permalink / raw)


In comp.arch.embedded Hans-Bernhard Broeker <broeker@physik.rwth-aachen.de> wrote:
> In comp.arch.embedded Bernd Trog <berndtrog@yahoo.com> wrote:

>> Now I wonder, if its possible to make 'Set_Bit' type-safe *without*
>> increasing the program memory size for every new register?

> The only way I see is to drop the idea of passing the register and the
> bit number inside that register as independent parameters 
[...]
>   Bit_A2 : constant Bit_Number := Register_A*8 + 1;

On second thinking, a better alternative is still possible.  But I'll
have to switch to C to explain it, because I don't speak Ada, so those
of you allergic to C may want shade their eyes....

typedef unsigned short   tByteNumber;
typedef unsinged char	 tBitNumber;

typedef struct {
	tByteNumber	byte_number;
	tBitNumber 	bit_number;
} tBitDefinition;

const tByteNumber Register_A = 8;
const bit_definition WhatEverThisDoes = {Register_A, 1};

inline void 
SetBit(tBitDefinition bit)
{
	USUAL_SETBIT_MACRO(bit.byte_number, bit.bit_number);
}
-- 
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2003-02-18 16:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-18  0:06 Type-safe low-level programming? Bernd Trog
2003-02-18  2:04 ` David C. Hoos, Sr.
2003-02-18 10:39 ` Hans-Bernhard Broeker
2003-02-18 16:21   ` Thad Smith
2003-02-18 16:52   ` Hans-Bernhard Broeker
2003-02-18 14:53 ` Steve

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox