如何声明基于继承类型的位域格式?

How do I declare a bitfield format based an inherited type?

我很难理解 Ada 的类型系统。来自 C/C++ 它是我很难掌握它的类型语法和它的多态性。我想创建一个抽象寄存器class,它可以有 2 到 8 个字节的数据存储:

package CPU is
   pragma Preelaborate;

    type Registers is array(0..4) of Register;

    type DeviceId is range 0..6;

    -- a register can be anywhere from 2 to 8 bytes
    type Byte_Array is array (1 .. 8) of Byte;
    type Register is record
        Data: Byte_Array;
    end record;

    type IORegiser is new Register(1..2) with record  
        Address : Byte;
        Busy    : Boolean;
        Error   : Boolean;
        Id      : DeviceId;
    end record;
    for IORegiser use record
        Address at 0 range 0..7;
        Busy    at 1 range 0..1;
        Error   at 1 range 2..2;
        Id      at 1 range 3..8;
    end record;
end CPU;

基于这个抽象,我想创建一个标准寄存器 class,其中的数据没有格式,另一个寄存器 class,其中的数据被格式化为字段:

A : Register := 16;  -- put the number 16 in the register.
IOReg : IORegister (Address => #16#0011#, Busy => true, Error => false, Id => #16#0011#);
B : LongRegister; -- an 8 byte register

CPURegs : Registers := (A, IOReg, B); -- Array of registers

此外,标准寄存器 classes 以几种不同的固定大小存储数据。在 C++ 中,我会使用联合,但不清楚如何在 Ada 中实现它。

编辑:删除标记类型的使用。

各种大小的未格式化记录可以实现为模块化类型,例如

type U8  is mod 2**8;
type U16 is mod 2**16;
type U32 is mod 2**32;
type U64 is mod 2**64;

因此,16 位未格式化记录的寄存器类型是

type Unformatted_16 is record with
    Data : U16 := 0;
end record;

为未格式化的 16 位寄存器使用模块化类型的优点在于分配给寄存器的值永远不会溢出寄存器。在所有 Ada 模块化类型中都发现了相同的模块化算术行为。

同样,您的 IORegister 类型在 16 位字长的机器上可能是以下类型:

type IORegister is record with record  
    Address : U8;
    Busy    : Boolean;
    Error   : Boolean;
    Id      : DeviceId;
end record;
for IORegister use record
    Address at 0 range 0..7;
    Busy    at 0 range 8..9;
    Error   at 0 range 10..10;
    Id      at 0 range 11..15;
end record;

四字节数组与 32 位整数不同。 Ada 表示子句处理字号和距字首的位偏移量。在上面的 16 位字示例中,所有偏移量都来自字 0。