-- One's complement signed type
type Signed_1C is new Signed;

-- Declaration of the 'Bits attribute getter/setters
-- They should be declared after the Signed_1C type is declared, in the same package.
-- Remark : I was inspired by the object methods declaration and notation in Ada
--          (see : https://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation#Object.Method_notation)

-- Getter for a case like : W := A'Bits
attribute function Bits (Self : Signed_1C) return Bit_Vector;

-- Setter for a case like : A'Bits := X
attribute procedure Bits (Self : out Signed_1C; Set : Bit_Vector);

-- Setter for a case like : A'Bits (3 downto 1) := Y
-- The 'Range_Type notation is suggested by the Extended Ranges proposal
attribute procedure Bits (Self : inout Signed_1C;
                          Rng  : Bit_Vector'Range_Type;
                          Set  : Bit_Vector);

-- Setter for a case like : A'Bits (5) := Z
attribute procedure Bits (Self : inout Signed_1C; N : Natural; Set : Bit);

(...)

-- Body for attribute getter/setters --------------------------------------------------------------------

-- Getter for a case like : W := A'Bits
attribute function Bits (Self : Signed_1C) return Bit_Vector is
   Signed_Self : Signed := Signed (Self);
begin
   if Self >= 0 then
      -- Same binary representation as 2's complement signed
      return Signed_Self'Bits;
   else
      -- Transform 2's complement signed to 1's complement signed
      return Not (-Signed_Self)'Bits;
   end if;
end Bits;

-- Setter for a case like : A'Bits := X
attribute procedure Bits (Self : out Signed_1C; Set : Bit_Vector) is
   Signed_Abs_Self : Signed;
begin
   if Set (Set'High) = '0' then
      Signed_Abs_Self'Bits := Set;
      Self := Signed_1C (Signed_Abs_Self);
   else
      Signed_Abs_Self'Bits := Not Set;
      Self := -Signed_1C (Signed_Abs_Self);
   end if;
end Bits;

-- Setter for a case like : A'Bits (3 downto 1) := Y
attribute procedure Bits (Self : inout Signed_1C;
                          Rng  : Bit_Vector'Range_Type;
                          Set  : Bit_Vector) is
   -- We call the 'bits attribute getter that was defined above
   variable Self_Bits : Bit_Vector := Self'Bits;
begin
   Self_Bits (Rng) := Set;
   -- We call the first setter defined
   Self'Bits := Self_Bits;
end Bits;

-- Setter for a case like : A'Bits (5) := Z
attribute procedure Bits (Self : inout Signed_1C; N : Natural; Set : Bit) is
   -- We call the 'bits attribute getter that was defined above
   variable Self_Bits : Bit_Vector := Self'Bits;
begin
   Self_Bits (N) := Set;
   -- We call the first setter defined
   Self'Bits := Self_Bits;
end Bits;
