Klasse aufbauen

Die Klasse dient zum spezifischen Verarbeiten eines Objektes.

Das Objekt wird mit em Konstruktor gebildet Klasse::Klasse()

klasse

Um auf das Objekt zuzugreifen, es zu verändern oder den Zustand seiner Variablen zu kennen braucht man Klassen-Funktionen Klasse::funktion() .

Auf alle Klassenvariablen kann man nur über das Objekt zugreifen objekt.variable .

Bsp Huffman Map
– Konstruktor bildet die Map- hm.readToken(„stream.txt“)  Daten werden von aussen eingegeben und lokal im Objekt gespeichert
– hm.getBitValue()    Lokale Varibale wird verarbeitet und ausgegeben
– hm.getZeros()         Andere Variable wird verabeitet und ausgegeben

 

VHDL: natural, unsigned, integer

Operiert man mit Indexes, Adressen, etc. so ist dies am einfachsten mit dez. Zahlen:12 + 100 = 112;
Das selbe gilt auch für die Zähler.
VHDL hat dafür 3 Types: integer, unsigned, natural .

 

  1. Integer
signal addr:        integer range 0 to 15;
addr <= to_integer(value_a);

Adresse kann Werte von  0, 1, 2, … 15 annehmen.

cnt: integer range 0 to 3;

Der Zähler zählt 0, 1, 2, 3 und beginnt wieder bei 0.
.

2. Unsigned

-- 5 Werte
signal count:       unsigned(4 downto 0); 
signal value_a:     unsigned(15 downto 0);
signal  value_b:     unsigned(15 downto 0);

Der Zähler kann die Werte 4, 3, 2, 1, und 0 annahmen. Er besitzt 5 Zustände.

value_b <= to_unsigned(max_value,  4); ????? not shure

.

3. Natural

CONSTANT    max_value:        natural := 200;
signal      s_reg_index:      natural;
signal      s_next_reg_indes: natural;
s_next_reg_index := s_reg_index + 1;

Zuweisung braucht ein : vor dem =   line_cnt := line_cnt + 1;     reset := 1;

C++ Geltungsbereich (Scope) von Variablen

lokale Variabeln überschreiben globale 8.4

Bjarne nennt in 8.4 unterschiedlichen Geltungsbereiche von Variablen
– global
– lokal
– in Klasse allein (siehe vektor unten)
– in Namensgebeit (z. B. struct, enum, …)
– in Aussagen (z. B. innerhalb eines for)

Der Geltungsbereich hat mit dem Datentyp etwas zu tun, und auf welchem RAM-Segment der Code abgelegt wird.

extern

extern int aktuelle_Version;

Die Variable wird nur deklariert und ist überall sichtbar.
Sie kann (theoretisch) in jedem File neu definiert und mit neuen Werten zugewiesen werden, das ist jedoch gefährlich. Besser ist es, nur in 1 File die Variable zu definieren und dann für alle anderen Files nur sichtbar zu machen.

Klasse

class MyVector{
.    // Klassenvariable. Gültigkeit in der Klasse 
.    vector <int> v      
.
.    public:
.          // öffentliche Funktion
.          int largest(){
.             int max = 0;
.             for (int i = 0; i < v.size(); i++) {
.               max = max( x, abs(v[i]) );
.             return max;  
.          }
.         // öffentliche Variable
.         int i;
.
};

Der Vektor v ist nur in der Klasse sichtbar. Ausserhalb exstiert er nicht und kann auch nicht angesprochen werden.

Argumente sind lokal

int funcition_b (int value_1){  
.  
.    //
}

Die Funktion ist global, aber der Parameter value_1  ist lokal bezüglich der function_b .

 

constexpr <function>
Lokale Variablen liegen FIFO im Stack. Man kann nicht auf sie zugreifen (Bjarne 8.5.9). Soll eine Funktion während dem Kompilieren definiert werden, braucht sie das Schlüsselwort constexpr bei all ihren Variablen und für die Funktion.

constexpr int scale_x = 3;
constexpr int scale_y = 2;
constexpr Point scale( Point P){
.
.     return { scale_x * P.x, scale_y * P.y };
}

C++ Datenypen

Vektor
Es gibt den Datentyp Vektor in C++. Im <- Link ist einiges Hilfreiche notiert.

std::vector <type> <name>

 

let: Deklaration und nicht Zuweisung
Let ist ein altes Keyword und will den Vorgang der Deklaration von der Wertzuweisung unterscheiden

let value_1 = 3;

 

Globale Variable

extern int value_b;

Extern stehet in allen Files, die auf diese Variable zugreifen müssen.
Definiert wird die Variable nur in einem File. In diesem muss die Variable auch extern gesetzt werden.

extern  ist formal eine Deklaration (und darf keinen Wert erhalten). Ermöglicht dadurch, dass die Variable in vielen Files deklariert werden kann.

const
Hat in C++ eine vielseitige Bedeutung. Const als Argument  (Bjarne 8.5.4) verhindert, dass die Funktion print() die Werte versehentlich ändert.

void print( const vektor <int>& messungen){
.   // code
}

statische <-> dynamische Variablen

statische Variablen

<type> <name> [<value>]

– Sie haben eine fixe Grösse
– Sie werden über den Namen aufgerufen
– Ihre Gültigkeit hängt von ihrem Definitionsort ab:
.  lokal: nur in Funktion gültig
.  global (extern): im ganzen Programm
Haben nichts mit dem Keywort static zu tun
Sie liegen im Datensegment

.   <<Statische Variablen hängen von der
.        (statischen) Programmstruktur ab.>>

dynamische Variablen
– Haben keinen fixen Namen: Es gibt keine Variablenvereinbarung (Definition)
– Können nur über den Return-Pointer der Funktion malloc() bearbeitet werden
– Sie kennen keine Funktions- oder Dateigrenzen, sondern sind überall sichtbar
– Eine dynamische Variable ist durch das Programmende oder durch die Funktion free( Variablen-Pointer) vernichtbar
– Speicherort ist der HEAP

Dynamische Speicherzuweisung C: „Allocation“

Nicht dynamisch
Definiert man eine Variable, Konstante oder ein Array mit fixer Länge char array[5] , so ist die Länge des Speicherplatzes klar und die Speicherzuweisung ist nicht dynamisch.
Nicht dynamische Speicherzuweisungen werden im STACK abgelegt.

Grund für dynamisch
Die Grösse des Arrays ändert sich während der Verarbeitung. Man kann das Array nicht auf eine fixe Grösse initialisieren.
Eine dynmische Speicherzuweisung nennt man Allozierung. Die Daten werden im HEAP abgelegt.

Vorgehen
1. Speicherplatz reservieren
Dies geschieht über die Funktion malloc().  Es ist zwingend, dass man die Anzahl Bytes nennt.  int *buffer1 = malloc(n * sizeof(data));.  N bezeichnet die Anzahl daten, data bezeichnet die Grösse eines Datenpackets.
Die Funktion sizeof( )  gibt immer die Anzahl Bytes der Variable zurück.
2. Auf dynamische Daten zugreiffen
Die Funktion malloc() gibt als Returnwert die Adresse zurück. Auf dynamische Daten kann nur über den Pointer zugegriffen werden. Ein direkter Zugriff über den Variablennamen auf die Daten ist nicht möglich. data1 = buffer1[0];
3. Speicherplatz freigebe
free(buffer1); Wird Speicherplatz nicht mehr freigegeben, so entsteht ein Memory Leak. Ohne free() verkleinert sich die Speicherkapazität des RAMs.

Speicherorte: Die „Segmente“ im RAM

Grundstruktur Datenablage
Ein ausführbares Programm (*.exe) teilt seine Daten in vier Segmente ein: *.code, *.data, *, heap und Stack.

code_data_heap code_data_heap_chinese

Codesegment
Liegt bei der tiefsten Adresse. Hier liegt der Maschinencode. Häufig liegen hier auch die Konstanten. Das Codesegment kann mit einem Schreibschutz versehen werden, also nur gelesen werden.

Datensegment
Hier liegen die initialisierten globalen Variablen sowie wenn eine lokale Variable als static definiert wurde. Sind Variablen nicht initialisiert, so liegen sie im BSS Segment.

Heap
Enthält nur dynamische Variablen, die mit malloc() zur Laufzeit generiert und wieder gelöscht werden.

Stack
Legt alle sich ändernden Daten zur Laufzeit ab und holt sie permanent wieder. Ständiges Wechseln der Daten. Deshalb braucht es einen Stack Pointer, der jeweils die aktuelle Speicherstelle weiss.
Der Stack liegt an der höchsten Adresse.
Im Stack liegen alle lokalen Variablen.

 

 

Pointers in C

Durch das Setzen eines Asterisk vor einer Variable, definiert man, dass die Variable keinen Wert, sondern eine Adresse beinhaltet:

  • Zeigen auf eine Speicheradresse
  • Sie beinhalten eine Adresse
    <type> *<name>, *<name>;

    Adresse übergeben (referenzieren)

    int *pointer;
    pointer = &variable_a;
    

    Die Variable_a wird gelesen, aber nur ihre Adresse wird übergeben.

    Wert übergeben (dereferenzieren, per value)

    *pointer = 10;
       // oder
    var1 = *pointer_b;
    printf(" %d ",  *pointer)

    Der Wert wird ebenfalls über einen Stern zurückgegeben. Das ist verwirrlich, zeigt aber auch, dass es ein Wert von einem Pointer ist…

    —————————————————————————–

    Pointer a

    int *a;
    int b;

    Wohin zeigt a ?

    b = &a;  // b hat die Adresse

    a soll einen Wert erhalten

    *a = 10;

State Machine VHDL

states bitweise definieren

constant s0         : std_logic_vector(2 downto 0) := "000";
constant s1         : std_logic_vector(2 downto 0) := "100";
constant s2         : std_logic_vector(2 downto 0) := "110";
constant s3         : std_logic_vector(2 downto 0) := "011";
constant s4         : std_logic_vector(2 downto 0) := "001";
constant s5         : std_logic_vector(2 downto 0) := "111";

signal state :        std_logic_vector(2 downto 0);
signal next_state:    std_logic_vector(2 downto 0);

states als type

type actual_state is (s0, s1, s2, s3, s4, s5, s6, s7);
        
signal state:          actual_state  := s0;  
signal next_state:     actual_state  ;


Enumeriter Type

type actual_state is (s0, s1, s2, s3);

attribute enum_encoding : string;
attribute enum_encoding of actual_state: type is "00 01 10 11";  

// nicht sicher:     
signal state:          actual_state  := s0;  
signal next_state:     actual_state  ;


State-Zuweisung

fsm: process (all)
    begin
        if (KEY_1 = '0') then
            state <= s0;
        elsif (rising_edge(CLOCK_27)) then
          state <= next_state;
        end if;
    end process;


Logik Events

fsm_input: process (all)        
begin     
    case state is
       when s0 =>
          if(pulse ='1') then
            next_state <= s1;
          else
            next_state <= s0;
          end if;           
       when s1 =>    
          if(pulse ='1') then
             if SW_17 = '1' the
                next_state <= s2;  
             else
                next_state <= s0;
             end if;
          else
             next_state <= s1;
          end if;
       when s2 =>   next_state <= s3;
       when s3 =>   next_state <= s4;
       when s4 =>   next_state <= s5;
       when s5 =>   next_state <= s6;
       when s6 =>   next_state <= s7
       when s7 =>   next_state <= s7;    
    end case;        
 end process;

Output Action

fsm_output: process (all)
begin   
    case state is
            when s0 =>   out     <= "001"; 
            when s1 =>   out     <= "011"; GPIO_0_0 <= '1';
            when s2 =>   LEDR_2  <= '1';
            when s3 =>   LEDR_3  <= '1';
   
            when OTHERS =>   NULL;
      end case;
end process;