11. Anlage
 
zurück
11.3.2 Interne Darstellung


Darstellungsattribute beschreiben maschinennahe Eigenschaften eines Typs. Ein Programmierer kann die Darstellung eines Typs und die Werte vieler dieser Attribute beeinflussen, indem er Darstellungssichten (representation items) schreibt.
Darstellungsattribute können über die Anzahl der Bits eines gegebenen Typs, die für die Werte eines Aufzählungstyps verwendeten Verschlüsselungen, die interne für einen numerischen Typ verwendete Darstellung, die Anordnung von Komponenten eines zusammengesetzten Typs und den Speicheraufwand für die Ausführung eines Prozesses Auskunft geben. Darstellungssichten können die Darstellungsattribute steuern. Eine Darstellungssicht ist entweder ein Darstellungspragma oder eine Darstellungsklausel (representation_clause <BNF>). Darstellungsklauseln enthalten eine Klausel für die Aufzählungsdarstellung (enumeration_representation_clause <BNF>), um die Verschlüsselung von Aufzählungen darzustellen, eine Klausel für die Verbunddarstellung (record_representation_clause <BNF>), um die bitweise Darstellung eines Verbundtyps zu bestimmen, eine Klausel für die Attributdefinition (at_clause <BNF>), um die Werte für einige Darstellungsattribute direkt zu steuern. Wenn ein Programmierer eine Darstellungssicht verwendet, bei der eine für die Zielmaschine unpraktische Darstellung gefordert wird, braucht der Übersetzer dem nicht zu folgen, aber der Übersetzer muß über die fehlerhafte Darstellungssicht berichten. Darstellungssichten, die die Darstellung eines gegebenen Typen steuern, müssen im gleichen Vereinbarungsteil oder der gleichen Paketvereinbarung an einem Platz hinter der Vereinbarung dieses Typs erscheinen.

Als Beispiel für die Verwendung der Darstellungsklauseln kann das Zustandsregister eines Plattenlaufwerks betrachtet werden. Dieses Register wird in der folgenden Figur dargestellt. Es wird angenommen, daß alle Felder gelesen werden können, ohne daß sich der Zustand des Gerätes
ändert.



Die einzelnen Bitpositionen der Zustandsregister Fehler (error), harter Fehler (hard error), RDY (Ready - Fertig), IDE (interrupt enable - Unterbrechung möglich) und GO sind Variable mit zwei Zuständen, die sich am besten als boolesche Werte vorstellen lassen:

type Flag is (Off, On);

(0 steht für Off, 1 steht für On (Dies ist die Standarddarstellung.)).
Für den Operationsmodus "Mode of Operation" (MD) werden 3 Bits verwendet, obwohl es nur 4 Operationen gibt:

type Modus is (Reset, Write, Read, Seek);


Die benötigten internen Codes für diese 4 Zustände sind 0, 1, 2, und 4; dies wird mit einer Aufzählungsdarstellungsklausel (enumeration_representation_clause <BNF>) wie folgt beschrieben:

for Mode use (Reset => 0, Write => 1, Read => 2, Seek => 4);


Solange die Sequenz streng steigend ist, ist jede Darstellung erlaubt. Die Speichererweiterungsbits "Memory Extension Bits" (EXT) können auf einen Typ abgebildet werden, der von einer Attributvereinbarungsklausel (attribute_definition_clause <BNF>) auf zwei Bits beschränkt wird:

type MEB is range 0..3;
for MEB’Size use 2;


Wenn jede einzelne Komponente definiert wurde, kann das Zustandsregister selbst als Verbund dargestellt werden:

type Control_Status is record
   GO  : Flag;
   MD  : Mode;
   EXT : MEB;
   IDE : Flag;
   RDY : Flag;
   Hard_Error : Flag;
   Error : Flag;
end record;

Die Darstellung des Verbundtyps kann dann beschrieben werden:

Word : constant := 2; -- 2 Bytes in einem Wort
Bits_in_Word : constant := 16; -- Bits in einem Wort

for Control_Status use
record
   GO at 0*Word range 0..0;
   -- Feld GO steht bei Wort 0 an der Position 0
   MD at 0*Word range 1..3;
   EXT at 0*Word range 4..5;
   IDE at 0*Word range 6..6;
   RDY at 0*Word range 7..7;
   Hard_Error at 0*Word range 14..14;
   Error at 0*Word range 15..15;
end record;

for Control_Status’Size use Bits_in_Word;
for Control_Status’Alignment use Word;
for Control_Status’Bit_Order use Low_Order_First;


Jede Implementierung hat eine Vorstellung von einer "Speichereinheit", um die Anordnung zu steuern. Der Wert dieser Einheit ist in dem vordefinierten Paket "System" enthalten. Jeder Komponente des Verbundes wird eine Position in einem oder mehreren Speichereinheiten gegeben; z. B. muß MD in die Speichereinheit 0 plaziert und die Bits 1, 2 und 3 verwendet werden. In diesem Beispiel hat die Speichereinheit den Wert 8, und deshalb kann Error in der Speichereinheit 1 bei Bit 7 gefunden werden (z. B. im Wort 0 bei Bit 15). Um das System zu zwingen, insgesamt nur 16 Bits für ein Objekt vom Typ Control_Status zu verwenden, wird eine Attributdefinitionsklausel (attribute_definition_clause <BNF>) verwendet. Das Attribut Alignment stellt sicher, daß der Verbund an einer geradzahligen Byte-Grenze plaziert wird, und das Attribut Bit_Order zeigt an, daß Bit 0 das am wenigsten bedeutende Bit ist. Schließlich muß ein Datenobjekt, das das Steuerregister darstellt, vereinbart und an den richtigen Speicherplatz positioniert werden. Dies ist die physikalische Adresse des Registers:
Control_Register : Control_Status;
for Control_Register’Address use 8#777404#;

Nachdem nun die abstrakte Darstellung des Registers gebildet und eine entsprechend vereinbarte Variable an die korrekte Adresse positioniert wurde, kann das Hardwareregister durch Zuweisungen an diese Variable gesetzt werden:

Control_Register := (Go => On,
                     Md => Read,
                     EXT => 0,
                     IDE => On,
                     RDY => Off,
                     Hard_Error => Off,
                     Error => Off);

Bei der Verwendung dieses Verbundaggregats (record_aggregate <BNF>) wird angenommen, daß dem ganzen Zustandsregister zur gleichen Zeit Werte zugewiesen werden. Um sicherzustellen, daß Go nicht vor den anderen Feldern des Verbundes gesetzt wird, kann das Pragma "Atomic" verwendet werden. Wenn die Werte des Zustandsregisters vom Gerät geändert werden, wird dies vom Programm als Änderungen in den Werten der Verbundkomponenten erkannt:

if Control_Register.Error = 0n then
   raise Disk_Error;
end_if;


Das Zustandsregister ist deshalb eine Sammlung von gemeinsamen Variablen, die zwischen dem Gerätesteuerprozeß und dem Gerät selbst geteilt werden. Der gegenseitige Ausschluß zwischen diesen zwei parallelen Prozessen ist für die Zuverlässigkeit und Ausführung notwendig. Dies wird in Ada durch ein geschütztes Objekt erreicht. Die Zustandssynchronisation muß sicherstellen, daß eine korrekte Folge von Ereignissen zwischen der Hardware und dem Treiber stattfindet. Die zwei üblichsten Verfahren für die Synchronisation sind

a) das Auswählen (polling)
b) die Unterbrechungssteuerung (interrupt driven)

Welche an irgendeinem bestimmten Gerät eingesetzt wird, ist sowohl eine Eigenschaft der Hardware als auch der Systemsoftware. Das Auswählen (polling) kann deshalb nicht entfernt werden, wenn es die einzige verfügbare Methode ist, um den Gerätezustand abzufragen. Wenn das Auswählen verwendet wird, dann muß die Abfrageschleife eine Verzögerungsanweisung enthalten, so daß der Geräteprozeß den Prozessor nicht beherrscht. Alternativ kann der ganze Gerätetreiberprozeß periodisch sein.


 
zurück
 Index   Ada Tour - Dokumentation  
© 2003 Förderverein Ada Deutschland e.V.