Please consider the following experimental Ada program which attempts to create a 32-bit record with well defined bit fields, create one and output it to a file stream...
with System;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams.Stream_Io; use Ada.Streams.Stream_Io;
procedure Main is
type Bit is mod (2 ** 1);
type Opcode_Number is mod (2 ** 4);
type Condition_Number is mod (2 ** 4);
type Operand is mod (2 ** 9);
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-- ADA 2012 language reference 'full_type_declaration'
-- (page 758, margin number 8/3) for RAM_Register
pragma Atomic (RAM_Register);
-- 3 2 1 0
-- 10987654321098765432109876543210
-- OOOOzcriCONDrrDDDDDDDDDsssssssss
X : RAM_Register := (2#1000#,
2#1#,
2#1#,
2#1#,
2#1#,
2#1000#,
2#1#,
2#1#,
2#100000001#,
2#100000001#);
The_File : Ada.Streams.Stream_IO.File_Type;
The_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
begin
Open (The_File, Out_File, "test.dat");
exception
when others =>
Create (The_File, Out_File, "test.dat");
end;
The_Stream := Stream (The_File);
RAM_Register'Write (The_Stream, X);
Close (The_File);
end Main;
I used the info here: https://rosettacode.org/wiki/Object_serialization#Ada and here: https://en.wikibooks.org/wiki/Ada_Programming/Attributes/%27Bit_Order (the very last example) to create the above.
Running the code and examining the output with xxd -g1 test.dat
gives the following 12 bytes of output...
00000000: 08 01 01 01 01 08 01 01 01 01 01 01 ............
QUESTION:
How can this 32 bit record be written to, or read from, a stream as 32 bits, observing all bitfield positions? Imagine I was communicating with a microcontroller on an RS-232 port, each bit will be required to be exactly in the right place at the right time. The syntax for RAM_Register use record...
seems to have had no effect on how 'Write
arranges its output.
If I do provide my own 'Read
and 'Write
implementations, doesn't that directly contradict the 'for RAM_Register use record...` code?
You probably will have to convert the instance to an unsigned integer (via an unchecked conversion) and then write the unsigned integer to the stream. The default implementation of Write
ignores the representation clause (see also RM 13 9/3):
For composite types, the Write or Read attribute for each component is called in canonical order, [...]
So, add
with Interfaces; use Interfaces;
with Ada.Unchecked_Conversion;
and define RAM_Register
as
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record with Atomic;
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register);
for RAM_Register'Write use Write;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-----------
-- Write --
-----------
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register)
is
function To_Unsigned_32 is
new Ada.Unchecked_Conversion (RAM_Register, Unsigned_32);
U32 : Unsigned_32 := To_Unsigned_32 (Item);
begin
Unsigned_32'Write (Stream, U32);
end Write;
This yields
$ xxd -g1 test.dat
00000000: 01 03 8e 8f ....
Note: the bitorder may have been reversed as I had to comment the aspect specification for RAM_Register'Bit_Order use System.High_Order_First;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With