Constructor C++

Eine Member-Funktion mit demselben Name wie die Klasse selbst, ist ein Constructor.

1. Konstruktor ohne Funktionen———————————————–

class MidiData {
. public: 
.     int pin;
.     double version;
.     int wait;        // in ms
.     MidiData(int pin, double version, int wait);  //Construct
.
}

Ein Objekt der Klasse kann nicht ohne Wertzuweisung definiert werden, eine Initialisierung ist zwingend notwendig beim Bilden eines Objektes. Die Initialiserung kann über eine List ober über den Constructor erfolgen:

MidireadData system_1 = { 13,  14.04, 10}  // list

MidireadData system_2 { 8, 14.04, 5 }  // constructor usually
MidireadData system_2( 8, 14.04, 5 )   // constructor old style

MidireadData system_3 = MidireadData{ 10, 14.04, 10 } //special

In der Initialisierung müssen alle Member-Variablen definiert werden.
Vgl. Bjarne Kapitel 9.4.2

2. Konstruktor für Klasse mit Funktionen ——————————-

class Date{
.      public:
.         // constructor
.         Date( int year, int month, int day);  
.         // member-functions
.         void add_day( int n);
.         int month();       // check error of number        
.
.      private:
.         int year, month, day;

};

Konstruktor mit Funktion:

Date::Date(int y_1,int m_1,int d_1)      
     : month( month1) {}

Class: public and private

Was eine Klasse ist
– Eine Klasse ist ein selbst definierter Datentyp
– Man erfindet eine Klasse nur, weil man sie für etwas braucht.
– Um das umzusetzen, braucht man Variablen und Funkitonen
– Damit man nicht alles von Hand schreiben muss, importiert
.  man oft Funktionen von Bibliotheken (oder anderen Klassen)

Struktur

class <Name> {
.     public: 
.            <type> <var>;
.            <type> <member_function>(<arguments);
.
.     private:
.            <type> <utility_functions>(<argument>);    
} ;

public:
–  Alles, warum die Classe definiert wurde. Der Public-Teil dient
.  dem direkten bearbeiten (nutzen) der Klasse.
–  Den Public-Teil nennt man auch das Interface.
–  Die Funktionen im public heissen member functions. Nur diese
.  Funktinen sind von aussen zugänglich (sichtbar)

private:
–  Hilfsfunktionen und Hilfsvaraiabeln.

Bilden eines Objektes
Eine Klasse kreierte man, weil man sie braucht. Damit man sie brauchen kann, müssen der Klasse Werte zugewiesen werden, dies geschieht im Constructor. In Python wird der Konstruktor durch die Funktion init in der Klasse definiert.

class <Name>(<argument>):

.    def __init__(self):  
.        // set variables
        
.   def <function_a> (self):
.       // Code

In C++ wird der Konstruktor nach der Klasse gebildet.

Simulationsprogramm starten (altera)

Vorbereitungen
– testbench ist in vhdl geschrieben
– compile_<projektname>.do ist in shell  und wird von der Konsole (des Simulationsprogrammes) her aufgerufen

Starten der Testbench
1. Neues Projekt anlegen
.  File/New/Project:
.  Ablegen der Simulation
2. Neue Bibliothek ein
File/New/Bibliothek.
Der Ordner wird Work genannt
3. Starten des Kompilierens und des Projekts per Konsole
4. Signale auswählen
.    Als erstes erscheinen nur die Fenster default und object (das sind die Signale).
.   Im Fenster objects auf ein Signal klicken,
.   CTRL A, alle Siganle auswählen
.   Rechte Maus: „Add waves
Ab jetzt sieht man (nach neuem Kompilieren)
.   die Signale im Wave-Fenster.
5. Speichern der Waves:
.    File/Save Format:   speichern in wave_<projektname>.do

Tipp:
In einem Projekt können mehrere testbenches bestehen. Jede erhält einen Namen: tb_midi_interface, tb_top_level, tb_uart.
Zu jeder Testbench gehört ihre eigene Kompilierungsdatei: compile_midi_interface.do, compile_top_level.do, compile_uart.do
und zu jeder Testbench gehören ihre eigene signale: wave_midi_interface.do, wave_top_level.do, wave_uart.do.

..

VHDL signal operationen

Operatoren Beschreibung

not
kann für boolean und signale gebraucht werden

std_logic_signal_1 <= not std_logic_signal_2;

if (not enable_data_1) then
    //

 

and, & , +

std_logic_signal <= signal_a and signal_b;

 

natural, unsigned, integer
Typkonversionen zwischen den logischen Signalen und den natürlichen.

 

Bit Operationen
Signale zusammensetzen
Bist aus Vektor extrahieren
Signal Bits setzen (LSB, MSB)

C++: Vektor per (const) reference

Es gibt zwei Prinzipien, wie man Vektoren (grosse Wertetabellen) übergeben kann:
1. Man will die Werte „nur“ verarbeiten. Die Tabelle bleibt gleich.
2. Man will Werte in der Tabelle ändern.

Werte nicht ändern
Wird ein Vektor per const Referenz übergeben const vector <type>& <name> , so verändert man aufgrund des Schlüsselwortes const die Einträge nicht (Bjarne 8.5.4). Anstatt per Referenz kann man die Werte auch traditionell per Pointer (per Adresse) übergeben, ebenfalls mit const.

Werte verändern (Bjarne 8.5.5)
Ist das Ziel, die Einträge zu ändern, so tut man dies z. B. so:

void init(vector <int> v){
.  //
}

————————————————————————————————————————-

Adresse erhalten

int i = 5;

// Variable für Adresse
int* adresse;

adresse = &i;      // die Adresse von i wird übergeben

Aus einer Adress-Variable einen Wert auselesen

int value_1;
value_1 = * adresse;

 

..

Nested Klassen

Wenn innerhalb einer Klasse, eine andere Klasse gebraucht wird. Es entsteht dadurch eine Verschachtelung aus Klassen.

class C{
.     public:
.           struct M {
.                      //
.           };
};

 

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 };
}

Unterscheidung Deklaration <-> Definition

Bjarne Stromkamph behandelt diesen Unterschied im Kapitel 8.2.

Deklaration

extern variable_b;
void function_a();

Deklarationen reservieren Namen. Sie reservieren keinen Platz. Sie sind für den Linker wichtig.
Die „bekannteste“ Deklaration ist die forward declaration von Funktioen oder das setzen von globalen Variablen.
Deklarationen kommen in ein Header-File.

In Deklarationen müssen die Parameter nicht zwingend angegeben werden. Man macht dies jedoch, damit der Code lesbarer ist (Bjarne 8.5.1).

Definition
Mit der Definition wird Speicherplatz alloziert. Die Variable erhält einen Platz.

int var_2= 5;

void function_a(){
.     //code
.     return 0;
}

 

 

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
}