Я новый разработчик в Аде, так что прости меня, если я не достаточно ясно.Я столкнулся с проблемой, и я не знаю, откуда может прийти ошибка.Я объясняю прежде всего контекст: у меня есть набор тестов, которые работают на QEMU (BE).Я хотел выполнить их на ПК нативный (x86) с прагмой Default_Scalar_Storage_Order (High_Order_First).Я заметил, что некоторые из моих тестов работали отлично, но это не относится к тестам, включая float.Для простоты я написал тест, включающий FLOAT и INT.
with AUNIT.ASSERTIONS; use AUNIT.ASSERTIONS;
with BASIC_TYPES;
with BASIC_TYPES.STREAM;
with INTERFACES;
with ADA.INTEGER_TEXT_IO;
with ADA.FLOAT_TEXT_IO;
with ADA.TEXT_IO;
with STREAMS;
with SYSTEM;
package body TEST.TEST is
function Integer2Hexa(Hex_Int : Integer; Bits_Nbr : Integer) return String is
Hexa : String(1..Bits_Nbr);
begin
Ada.Integer_Text_IO.Put(Hexa,Hex_Int,16);
return Hexa;
end Integer2Hexa;
function NAME (T : TEST) return AUNIT.MESSAGE_STRING is
pragma UNREFERENCED (T);
begin
return AUNIT.FORMAT ("Test package");
end NAME;
IntegerNbr : BASIC_TYPES.INT32_T;
FloatNbr : INTERFACES.IEEE_Float_32;
procedure RUN_TEST (T : in out TEST) is
PACKED_ARRAY : BASIC_TYPES.UINT8_ARRAY_NC_T (1 .. 8) := (others => 0);
MY_STREAM : STREAMS.STREAM_T;
use type BASIC_TYPES.UINT8_ARRAY_NC_T;
begin
IntegerNbr := 479037433;
FloatNbr := 2.0012151e+09;
ADA.TEXT_IO.PUT_LINE ("Default bit order: " & SYSTEM.Default_Bit_Order'IMG);
ADA.TEXT_IO.PUT_LINE ("Integer size : " & INTEGER'IMAGE (INTEGER'SIZE));
ADA.TEXT_IO.PUT ("16#4EEE903D#"); -- 2.0012151e+09 in FLOAT BIG ENDIAN
ADA.TEXT_IO.PUT (Integer2Hexa(Integer(IntegerNbr),32)); -- 16#1C8D87F9# in INT BIG ENDIAN
ADA.TEXT_IO.NEW_LINE;
-- Init the stream
STREAMS.INIT (MY_STREAM => MY_STREAM,
STREAM_ADDRESS => PACKED_ARRAY (PACKED_ARRAY'FIRST)'ADDRESS,
STREAM_SIZE => PACKED_ARRAY'LENGTH);
BASIC_TYPES.STREAM.WRITE_FLOAT_T (MY_STREAM => MY_STREAM,
ITEM => FloatNbr,
ALIGN_MODE => STREAMS.PACK);
BASIC_TYPES.STREAM.WRITE_INT32_T (MY_STREAM => MY_STREAM,
ITEM => IntegerNbr,
ALIGN_MODE => STREAMS.PACK);
if (not ASSERT(PACKED_ARRAY = (16#4e#, 16#ee#, 16#90#, 16#3d#, 16#1c#, 16#8d#, 16#87#, 16#f9#), "PACKED_ARRAY incorrect")) then
for I in PACKED_ARRAY'RANGE loop
ADA.TEXT_IO.PUT (Integer2Hexa(Integer(PACKED_ARRAY (I)),8));
end loop;
ADA.TEXT_IO.NEW_LINE;
end if;
end RUN_TEST;
end TEST.TEST;
Я заметил, что запись INT выполнена правильно, но это не относится к FLOAT (он написан на LittleEndian).Действительно, на выходе у меня должно быть
16#4e#, 16#ee#, 16#90#, 16#3d#, 16#1c#, 16#8d#, 16#87#, 16#f9#
, но я получаю
16#3d#, 16#90#, 16#ee#, 16#4e#, 16#1c#, 16#8d#, 16#87#, 16#f9#
Я использовал этот сайт, чтобы подтвердить свои результаты: https://www.scadacore.com/tools/programming-calculators/online-hex-converter/
Я не знаю, правильно ли используется преобразование благодаря прагме для FLOAT.Я называю это в моем файле gpr в пакете Compiler с этим текстом в PRAGMA.txt: pragma Default_Scalar_Storage_Order (High_Order_First);
package Compiler is
for Local_Configuration_Pragmas use "PRAGMAS.txt";
for Switches ("ada") use ("-g");
end Compiler;
Приходит ли проблема к моему использованию прагмы?
Вот так называемые процедуры:
procedure WRITE_FLOAT_T
(MY_STREAM : in out STREAMS.STREAM_T;
ITEM : in BASIC_TYPES.FLOAT_T;
ALIGN_MODE : in STREAMS.ALIGN_MODE_T)
is
pragma UNREFERENCED (ALIGN_MODE);
-- Temporary types for non pack case
type TMP_TYPE_T is new STANDARD.FLOAT;
for TMP_TYPE_T'VALUE_SIZE use FLOAT_T_SIZE_C;
TMP_TYPE : TMP_TYPE_T;
subtype BITS_FIELD_T is STREAMS.BIT_FIELD_ARR_NC_T (1 .. STREAMS.SIZE_T (FLOAT_T_SIZE_C));
function TO_BITS_ARRAY is new UNCHECKED_CONVERSION (TMP_TYPE_T,
BITS_FIELD_T);
begin
-- Convert item to a temporary type
TMP_TYPE := TMP_TYPE_T(ITEM);
STREAMS.WRITE (MY_STREAM => MY_STREAM,
DATA => TO_BITS_ARRAY(TMP_TYPE));
end WRITE_FLOAT_T;
procedure WRITE (MY_STREAM : in out STREAM_T;
DATA : in BIT_FIELD_ARR_NC_T) is
begin
if (MY_STREAM.ERROR_CODE = NO_ERROR)
and then (MY_STREAM.WRITE_OFFSET + DATA'LENGTH - 1 <= MY_STREAM.STREAM_SIZE * 8) then
if (MY_STREAM.WRITE_OFFSET mod 8 = 1) and then (DATA'LENGTH mod 8 = 0) then
-- Byte mode
WRITE_BYTES(MY_STREAM => MY_STREAM,
DATA => DATA);
else
-- Bit mode
WRITE_BITS(MY_STREAM => MY_STREAM,
DATA => DATA);
end if;
elsif (MY_STREAM.ERROR_CODE = NO_ERROR) then
-- Update ERROR_CODE on first error
MY_STREAM.ERROR_CODE := END_ERROR;
end if;
end WRITE;
procedure WRITE_BYTES (MY_STREAM : in out STREAM_T;
DATA : in BIT_FIELD_ARR_NC_T) is
BYTE_FIELD_ARR : BYTE_FIELD_ARR_NC_T (1 .. MY_STREAM.STREAM_SIZE);
for BYTE_FIELD_ARR'ADDRESS use MY_STREAM.STREAM_ADDRESS;
TMP_BYTE_FIELD_ARR : BYTE_FIELD_ARR_NC_T (1 .. DATA'LENGTH / 8);
for TMP_BYTE_FIELD_ARR'ADDRESS use DATA'ADDRESS;
begin
-- Write byte field
BYTE_FIELD_ARR ((MY_STREAM.WRITE_OFFSET + 7) / 8 .. (MY_STREAM.WRITE_OFFSET + 7) / 8 + (DATA'LENGTH / 8) - 1) := TMP_BYTE_FIELD_ARR;
MY_STREAM.WRITE_OFFSET := MY_STREAM.WRITE_OFFSET + DATA'LENGTH;
end WRITE_BYTES;
Заранее спасибо!
Q.Dherb