Klausul representasi

Klausul representasi untuk tata letak bit-eksak menuju perangkat keras dan protokol.

Daftar isi

Klausul representasi (representation clause) menetapkan tata letak record secara bit-eksak sesuai kebutuhan perangkat keras atau protokol komunikasi. Tanpa klausul tersebut, tata letak bidang ditentukan kompilator dan boleh berbeda antar target. Topik ini membahas penulisan klausul representasi record dengan at dan range, pembuktian tata letak melalui atribut 'Size, 'Position, 'First_Bit, dan 'Last_Bit, serta bentuk klausul yang ditolak kompilator. Contoh yang digunakan adalah bingkai protokol sensor dan register 16 bit.

Klausul representasi record#

Klausul representasi record ditulis setelah deklarasi tipe dengan bentuk for Nama use record diikuti satu klausa komponen untuk setiap bidang. Klausa komponen menyebut nama bidang, offset dalam satuan penyimpanan (storage element) sejak awal record, dan rentang bit yang ditempati bidang tersebut pada satuan penyimpanan itu. Tipe bidang untuk kebutuhan perangkat keras umumnya merupakan tipe modular (modular type), yaitu tipe yang dibentuk dengan kata mod dan berukuran tetap N bit. Rentang nilainya adalah 0 .. 2**N - 1, dan aritmetikanya kembali dari batas atas ke nol.

ada Contoh: bentuk klausul representasi record
-- tidak-dijalankan
type Bita is mod 2 ** 8;

type Bingkai is record
   Alamat : Bita;
   Data   : Bita;
end record;

for Bingkai use record
   Alamat at 0 range 0 .. 7;
   Data   at 1 range 0 .. 7;
end record;

Klausa Alamat at 0 range 0 .. 7 menyatakan bidang Alamat berada pada satuan penyimpanan ke-0, tepatnya bit 0 sampai 7, sedangkan Data menempati satuan penyimpanan ke-1. Bidang yang tidak disebut pada klausul dibiarkan diatur oleh kompilator, sehingga klausul untuk protokol lazimnya menyebut seluruh bidang agar tata letaknya utuh ditetapkan. Penomoran bit di dalam satu satuan penyimpanan mengikuti aspek Bit_Order, dan GNAT menggunakan penomoran bit rendah-terlebih-dahulu (low order first) secara bawaan pada target ini.

Dua bentuk penataan tambahan melengkapi klausul record. Kata mod pada klausul menetapkan ukuran record menjadi kelipatan tertentu, misalnya mod 2 untuk kelipatan dua satuan penyimpanan, sehingga record dapat ditempatkan pada alamat yang merata sesuai kebutuhan perangkat keras. Aspek Packed memadatkan komponen tanpa menetapkan posisi bitnya, dan digunakan apabila kehematan penyimpanan lebih penting daripada posisi bidang yang eksak. Untuk register dan protokol, klausul komponen tetap menjadi pilihan karena posisinya dinyatakan secara eksplisit.

Pembuktian tata letak dengan atribut#

Klaim tentang tata letak tidak boleh berupa dugaan, karena atribut representasi dapat membuktikannya pada keluaran program. Atribut 'Size menyatakan ukuran dalam bit, 'Position menyatakan offset satuan penyimpanan sebuah bidang, sedangkan 'First_Bit dan 'Last_Bit menyatakan bit pertama dan terakhir bidang tersebut. Program berikut membuktikan tata letak dua record, yaitu bingkai protokol empat bita dan register sensor 16 bit yang bidang-bidangnya berbagi satu kata.

ada bingkai_sensor.adb
with Ada.Text_IO; use Ada.Text_IO;

procedure Bingkai_Sensor is

   type Bita is mod 2 ** 8;
   type Sampel is mod 2 ** 13;

   -- Bingkai protokol: satu bidang per bita, empat bita per bingkai.
   type Bingkai is record
      Alamat  : Bita;
      Ragam   : Bita;
      Data    : Bita;
      Paritas : Bita;
   end record;

   for Bingkai use record
      Alamat  at 0 range 0 .. 7;
      Ragam   at 1 range 0 .. 7;
      Data    at 2 range 0 .. 7;
      Paritas at 3 range 0 .. 7;
   end record;

   -- Register sensor 16 bit: penanda dan bacaan berbagi satu kata.
   type Register_Sensor is record
      Siap  : Boolean;
      Galat : Boolean;
      Nilai : Sampel;
   end record;

   for Register_Sensor use record
      Siap  at 0 range 0 .. 0;
      Galat at 0 range 1 .. 1;
      Nilai at 0 range 3 .. 15;
   end record;

   B   : Bingkai := (Alamat => 3, Ragam => 1, Data => 200, Paritas => 0);
   Reg : Register_Sensor := (Siap => True, Galat => False, Nilai => 1000);

begin
   Put_Line ("Bingkai'Size        =" & Integer'Image (Bingkai'Size));
   Put_Line ("Alamat'Position     =" & Integer'Image (B.Alamat'Position));
   Put_Line ("Ragam'Position      =" & Integer'Image (B.Ragam'Position));
   Put_Line ("Data'Position       =" & Integer'Image (B.Data'Position));
   Put_Line ("Paritas'Position    =" & Integer'Image (B.Paritas'Position));
   Put_Line ("Register_Sensor'Size=" & Integer'Image (Register_Sensor'Size));
   Put_Line ("Siap'First_Bit      =" & Integer'Image (Reg.Siap'First_Bit));
   Put_Line ("Siap'Last_Bit       =" & Integer'Image (Reg.Siap'Last_Bit));
   Put_Line ("Nilai'First_Bit     =" & Integer'Image (Reg.Nilai'First_Bit));
   Put_Line ("Nilai'Last_Bit      =" & Integer'Image (Reg.Nilai'Last_Bit));
end Bingkai_Sensor;
bash
# kompilasi program
gnatmake -q bingkai_sensor.adb
# jalankan program
./bingkai_sensor
text Keluaran
Bingkai'Size        = 32
Alamat'Position     = 0
Ragam'Position      = 1
Data'Position       = 2
Paritas'Position    = 3
Register_Sensor'Size= 16
Siap'First_Bit      = 0
Siap'Last_Bit       = 0
Nilai'First_Bit     = 3
Nilai'Last_Bit      = 15

Keluaran membuktikan tata letak keduanya tanpa perlu membuka berkas hasil kompilasi. Bingkai berukuran 32 bit dengan empat bidang pada offset 0 sampai 3, tepat sesuai klausulnya. Register_Sensor berukuran 16 bit, dengan Siap menempati bit ke-0 dan Nilai menempati bit 3 sampai 15 sejak satuan penyimpanan pertama, sehingga bidang 13 bit itu melintasi dua bita. Dua penanda dan satu bacaan berbagi satu kata 16 bit, dan pola tersebut lazim dijumpai pada register perangkat keras. Atribut-atribut tersebut diketahui pada waktu kompilasi, sehingga nilainya dapat digunakan sebagai konstanta pada deklarasi lain. Apabila pemeriksaan ini dijalankan ulang setiap kali target atau versi kompilator berganti, pergeseran tata letak terdeteksi sejak keluaran berubah, bukan setelah perangkat keras menolak datanya.

Klausul yang ditolak kompilator#

Klausa komponen yang tumpang tindih ditolak pada waktu kompilasi, sebelum program berjalan. Berkas berikut sengaja memberi rentang yang saling memotong pada dua bidangnya.

ada uji_tumpang.adb
--  Berkas ini sengaja salah: dua klausa komponen saling menumpuk.
procedure Uji_Tumpang is

   type Bita is mod 2 ** 8;

   type Register is record
      A : Bita;
      B : Bita;
   end record;

   for Register use record
      A at 0 range 0 .. 7;
      B at 0 range 4 .. 11;
   end record;

begin
   null;
end Uji_Tumpang;
bash
# kompilasi berkas yang sengaja salah
gnatmake -q uji_tumpang.adb
text Keluaran
uji_tumpang.adb:13:07: error: component "B" overlaps "A" at line 12
gnatmake: "uji_tumpang.adb" compilation error

Pesan error menyebut bidang B bertumpang tindih dengan A, lengkap dengan baris klausul yang bertabrakan. Bentuk penolakan lain terjadi apabila rentang klausul lebih kecil daripada ukuran tipe bidangnya, misalnya bidang bertipe Bita yang diberi rentang 0 .. 3. GNAT menolak rentang semacam itu dengan pesan bahwa ukuran minimum yang diizinkan adalah 8 bit. Kedua penolakan ini menunjukkan bahwa klausul representasi diperiksa konsistensinya sejak kompilasi, sehingga tata letak yang cacat tidak pernah sampai ke perangkat keras.

Penolakan pada waktu kompilasi seperti ini jauh lebih murah daripada kekeliruan tata letak yang baru terdeteksi pada perangkat keras, karena pesan errornya menunjuk baris klausul yang perlu dibereskan. Untuk protokol yang rumit, klausul ditulis bersama pengujian atribut sejak awal, sehingga setiap perubahan tata letak langsung terbaca pada keluaran program. Disiplin tersebut menjaga berkas klausul dan berkas pengujian tetap sepadan.

Kesalahan umum#

  • Menumpuk dua klausa komponen pada bit yang sama. Kompilator menolak klausulnya dengan pesan yang menyebut pasangan bidang yang bertabrakan. Perbaikannya, gambar tata letak bit terlebih dahulu, lalu susun ulang offset dan rentangnya tanpa irisan.
  • Memberi rentang klausul yang lebih kecil daripada ukuran tipe bidang. GNAT menolaknya karena nilai bidang tidak muat pada bit yang disediakan. Perbaikannya, perbesar rentang atau gunakan tipe modular yang ukurannya sesuai dengan bidang pada protokol.
  • Mengira tata letak tanpa klausul akan sama pada semua target. Tanpa klausul representasi, susunan penyimpanan sepenuhnya ditentukan kompilator. Perbaikannya, tetapkan klausul untuk setiap record yang berhadapan dengan perangkat keras atau protokol, lalu buktikan hasilnya dengan atribut representasi.
  • Mencampur bidang tipe bahasa lain ke dalam record bertata letak ketat. Ukuran Boolean dan tipe lain di Ada ditentukan kompilator, bukan konvensi bahasa C, sehingga asumsi ukurannya menyesatkan. Perbaikannya, nyatakan bidang dengan tipe modular yang ukurannya eksplisit, lalu buktikan dengan atribut 'Size.

Ringkasan#

  • Klausul representasi record dengan at dan range menetapkan offset satuan penyimpanan serta rentang bit setiap bidang secara bit-eksak.
  • Atribut 'Size, 'Position, 'First_Bit, dan 'Last_Bit membuktikan tata letak pada keluaran program, sehingga klaim ukuran tidak berupa dugaan.
  • Klausul yang tumpang tindih atau lebih kecil dari ukuran tipe bidang ditolak kompilator sebelum program berjalan.

Referensi#