DDC-I Logo

Sitemap  

DDC-I Ada Compiler System  

Ada Bit Operations

Product Family: DACS, SCORE, TADS
Target CPU: Any
Language: Ada
Host: Any

When one is first learning the Ada language, there is a noticeable absence of the common bit operations; and, or, not, xor. Having designed and developed embedded microprocessor applications for several years, I found the lack of those operators quite distressing. In this article, I will discuss a generic implementation of a bit operations package.

Consider the following hardware register definition:

         bits
 7 6 5 4 3 2 1 0          Meaning
+-+-+-+-+-+-+-+-+
|x| | | | | | | | Time Out Error
| |x| | | | | | | Transfer Shift Register Empty
| | |x| | | | | | Transfer Holding Register Empty
| | | |x| | | | | Break Detect Error
| | | | |x| | | | Framing Error
| | | | | |x| | | Parity Error
| | | | | | |x| | Data Overrun Error
| | | | | | | |x| Data Ready

There are two ways to represent each of these bits. Since the bits are really discrete values, one could represent them thusly:

Type StatusReg_t Is
   Record
      TimeOut_Error :		Boolean;
      Xfer_Shift_Empty :	Boolean;
      Xfer_Hold_Empty :	Boolean;
      Break_Detect_Error :	Boolean;
      Framing_Error :		Boolean;
      Parity_Error :		Boolean;
      Overrun_Error :		Boolean;
      Data_Ready :		Boolean;
   End Record;
For StatusReg_t Use
   Record
      TimeOut_Error		at 0 range 7..7;
      Xfer_Shift_Empty		at 0 range 6..6;
      Xfer_Hold_Empty		at 0 range 5..5;
      Break_Detect_Error	at 0 range 4..4;
      Framing_Error		at 0 range 3..3;
      Parity_Error		at 0 range 2..2;
      Overrun_Error		at 0 range 1..1;
      Data_Ready		at 0 range 0..0;
   End Record;
For StatusReg_t'Size Use 8;

UART_StatusReg :		StatusReg_t;
For UART_StatusReg Use At ... ;	   -- dependent upon System.Address definition

If ( UART_StatusReg.TimeOut_Error Or Else
      UART_StatusReg.Break_Detect_Error Or Else
      UART_StatusReg.Framing_Error Or Else
      UART_StatusReg.Parity_Error Or Else
      UART_StatusReg.Overrun_Error )
Then

      -- Perform error processing
      ...
	
End If;

Or, if the code is being translated from another language, it might make more expedient to define the error codes (and register definition) more like this:

Type Byte Is Range 0..2**8-1;
For Byte'Size Use 8;

Type StatusReg_t Is
(
      Data_Ready,
      Overrun_Error,
      Parity_Error,
      Framing_Error,
      Break_Detect_Error,
      Xfer_Hold_Reg_Empty,
      Xfer_Shift_Reg_Empty,
      Timeout_Error
);
For StatusReg_t Use
(
      Data_Ready		=> 16#01#,
      Overrun_Error		=> 16#02#,
      Parity_Error		=> 16#04#,
      Framing_Error		=> 16#08#,
      Break_Detect_Error	=> 16#10#,
      Xfer_Hold_Reg_Empty	=> 16#20#,
      Xfer_Shift_Reg_Empty	=> 16#40#,
      Timeout_Error		=> 16#80#
);
For StatusReg_t'Size Use Byte'Size;

Using a bit operations package, one could check for errors this way:

Function Check_Status Is

      Package Byte_BitOps Is New Bit_Operations( Item_t => Byte );
      Function "Or"( L, R : In Byte ) Return Byte Renames Byte_BitOps."Or";
      Function "And"( L, R : In Byte ) Return Byte Renames Byte_BitOps."And";

      Function ToByte Is New Unchecked_Conversion( StatusReg_t, Byte );

      UART_Error :		Byte := ToByte( Timeout_Error ) Or
			ToByte( Break_Detect_Error ) Or
			ToByte( Framing_Error ) Or
			ToByte( Parity_Error ) Or
			ToByte( Overrun_Error );

      UART_StatusReg :	Byte;
      For UART_StatusReg Use At ... ;  -- dependent upon address specification

Begin	-- Check_Status

      If ( ( UART_StatusReg and UART_Error ) /= 0 )
      Then

	-- An error has occurred, handle the error condition

	...
      End If;
End Check_Status;

While the code in each example provides equivalent functionality, there are clearly reasons to code using one method or another. While there are arguments both for and against each coding style, the particular style used is often dictated by a coding standards manual.

For those who would like to use the bit masking approach, a generic Bit_Operations package is provided.



--###############################################
--(c)Copyright 1999, DDC-I, Incorporated
--All Rights Reserved
--
--This code remains the property of DDC-I.  It may be distributed freely
--as long as this copyright notice remains with the code.
--
--This code is supplied without warranty.
--###############################################
--File: bitOps.ads
--
--Description:
--      This file contains the generic package Bit_Operations.  This package
--      is designed to work with all integer types, regardless of size.
--
--Disclaimer:
--      This package was written to be extremely portable, though perhaps not
--      as fast as if the functions were implemented in assembly language.
--
--Revision History:
--      1.0 rmg Wed Dec 15 22:31:37 1999
-- Original Coding
--################################################

generic
      type Item_t is private;

package Bit_Operations is
      function "and"( L, R : in Item_t ) return Item_t;
      function "or" ( L, R : in Item_t ) return Item_t;
      function "xor"( L, R : in Item_t ) return Item_t;
      function "not"( L : in Item_t ) return Item_t;
end Bit_Operations;

with System, Unchecked_Conversion;

package body Bit_Operations Is

      -- Definition of this type is completely dependent upon the size attribute
      -- of the type used to instantiate this generic package

      type BitArray_t is array( 1 .. Item_t'size ) of boolean;
      pragma pack ( BitArray_t );

      function toBool is new Unchecked_Conversion( Item_t, BitArray_t );
      function toItem is new Unchecked_Conversion( BitArray_t, Item_t );

      -- In the four functions below, the code uses the address attribute of
      -- an instance of the variable passed into the functions.  This is done
      -- on local variables so that should be no problem with the implementation
      -- of the function parameters
      -- The algorithm is actually very simple, almost brute force.  The code
      -- loops through each bit, performing the indicated operation for the
      -- corresponding bit in each parameter, storing the result for later
      -- return to the caller

      function "and"( L, R : in Item_t ) return Item_t is
      Begin -- "and"

            return ( toItem( toBool( L ) and toBool( R ) ) );
      end "and";

      function "or" ( L, R : in Item_t ) return Item_t is
      begin -- "or"

            return ( toItem( toBool( L ) or toBool( R ) ) );
      end "or";

      function "xor"( L, R : in Item_t ) return Item_t is
      begin -- "xor"

            return ( toItem( toBool( L ) or toBool( R ) ) );
      end "xor";

      function "not"( L : In Item_t ) return Item_t is
      begin -- "not"

            return ( toItem( not toBool( L ) ) );
      end "not";

end Bit_Operations;

 

Contact
602-275-7172
sales@ddci.com

IDIQ Contract Vehicles:
--------------
AMCOM Express
DESP II
F2AST
R23G

Links

Support

Members Area
    -Member Login/Return
    -Login Help

Atlas Support Packages
    -Atlas Premium
    -Atlas Advantage
    -Atlas Choice

Complimentary Support

Submit a Software Trouble Report

Customer Quote:
"While we are on the subject of support I would like to emphasize that Alex and Richard have been superb in their support of our project. We could not have gotten over our initial hurdles without them."