Forum: FPGA, VHDL & Co. VHDL speziell für die Simulation


von Matthias F. (flint)


Lesenswert?

Hallo,

nachdem ich mich bisher immer nur mit synthetisierbarem VHDL beschäftigt 
habe, darf ich mich in den nächsten Wochen/Monaten mit dem Titel 
"Verification Engineer" schmücken und bekomme jetzt also eine andere 
Sicht auf VHDL als ich bisher hatte.

Ich habe schon ein Testbench Konzept in dem auch so unsynthetisierbare 
Dinge wie File I/O, dynamische Speicherverwaltung und eine Linked List 
drin sind. Ich denke aber, dass da noch einiges zu holen ist, 
insbesondere in Bezug auf Simulationsgeschwindigkeit und 
Speicherverbauch (zb Prozesse nicht unnötig abarbeiten, etc ...).

Hat da jemand Tipps oder vielleicht Links zu guten Artikeln, die sich 
auch damit beschäftigen, wie der Simulator (in unserem Fall Modelsim) 
bestimmte Konstrukte abarbeitet?

Eine Frage die mich zb beschäft ist: Ich lese eine Datei ein in der 
viele 4-bit Werte in ASCII Zeichen kodiert sind. Wie speichere ich diese 
Daten am besten in einer internen Datenstruktur sodass der Simulator zb 
jeweils 8 4-bit Werte in eine Integer variable packt?

Eine andere Frage ist: Die klassische Form

if reset = '1' then
   ...
elsif rising_edge(clk) then
   ...
end if;

ist ja bekannt. Ist das die beste Form für die Simulation oder sind da 
andere Konstrukte besser geeignet?


Ich freue mich über alle Antworten.

Matthias

von Matthias F. (flint)


Lesenswert?

Gut, sonderlich eingeschlagen hat der Thread ja bisher nicht aber jetzt 
habe ich etwas hoffentlich halbwegs spannendes zu bieten: Mein aktuelles 
Problem ist, dass ich irgendwie sicherstellen muss, dass die Messages im 
Logfile immer in derselben Reihenfolge geschrieben werden. Das dürfte 
nicht trivial sein in VHDL, die Reihenfolge des Scheduling der aktiven 
Prozesse ist nicht fixiert. Noch dazu hängt diese Reihenfolge an Delta 
Delays, ich sehe es schon vor mir, wie ich in irgendeiner Datei eine 
Zuweisung ändere (zb aus einem Prozess herausziehe) und auf einmal dreht 
sich bei einer ganz anderen Komponente die Scheduling Order um. Auch 
innerhalb einer Komponente soll die Message Order nicht umgedreht 
werden.

Folgende Lösung kommt mir bisher am besten vor: Jede Entity, die Log 
Messages schreiben kann, hat ihre eigene Message Liste und schreibt in 
diese ihre Messages hinein. Ein eigener PRozess der auf einer Clock eine 
ps hinter den eigentlich clocks läuft, liest dann in einer fixen 
Reihenfolge diese Listen aus und schreibt die Messages. Damit habe ich 
eine fixe Reihenfolge wenigstens unter den Entities ohne an der 
Abarbeitung der Prozesse durch den Simulator etwas zu drehen.

Jetzt stellt sich aber immer noch das Problem der Reihenfolge innerhalb 
einer Entity, aber das kann ich vielleicht machen indem ich für jede 
Entity nur einen Prozess implementiere, der Log Messages schreibt.

von Izmir Übel (Gast)


Lesenswert?

Versuche es einfach nach Ostern nochmal!

von Matthias F. (flint)


Lesenswert?

Ist darum hier so wenig los?

Ist ja furchtbar heute, hier im Stockwerk sind alle auf Zeitausgleich, 
man hört nur Tastaturen klappern und langsam mache ich mir Sorgen, dass 
ich an Reizarmut eingehe :D ... schöne Ostern jedenfalls allen.

von Frank Ungermann (Gast)


Lesenswert?

Komm zur fränkischen Siemens ins Grossraumbüro, da hast Du garantiert 
keine Reizarmut!

von Matthias F. (flint)


Lesenswert?

Weiß vielleicht wer, wie man eine constant auf eine variable casten 
kann, wenn man zb an eine procedure übergibt? Man kann die constant 
problemlos einer variable zuweisen und diese dann übergeben, aber das 
muss doch auch irgendwie direkt gehen.

Noch eine Frage: Jetzt weiß ich schon, wie ich einen access type 
dereferenziere. Aber ich finde den umgekehrten Weg nicht, wie ich zu 
einem statisch angelegten Objekt einen access handle bekomme. Weiß das 
vielleicht wer?

von Matthias F. (flint)


Lesenswert?

p.s: iPod hilft wunderbar gegen Reizarmut.

von Matthias F. (flint)


Lesenswert?

Ok, das mit dem casten ist nicht sinnvoll, anscheinend einfach alle 
in-Parameter für eine procedure als constant deklarieren, dann kann beim 
Call auch ein anderer Typ eingesetzt werden. Die zweite Frage ist noch 
offen.

von A. F. (chefdesigner)


Lesenswert?

Kannst Du bitte mal ein Beispiel posten, damit man versteht, worüber Du 
genau sprichst?

von Matthias F. (flint)


Lesenswert?

Sorry, habe den Beitrag erst jetzt gesehen.

Ein Beispiel was mich beschäftigt:

Ich habe zb so eine Datenstruktur:

---
  type Message_record;
  type Message_record_ptr is access Message_record;

  type Message_record is record
    Message      : line;
    TimeStamp : time;
    Message_class : string(1 to 2);
    Message_code : string(1 to 2);
    Message_level : integer range 0 to 3;
    Next_Message : Message_record_ptr;
  end record Message_record;
---

Diese soll Messages in einer Linked List halten. Um so eine Struktur 
anzulegen muss ich folgendes aufrufen:

---
new_msg_ptr := new Message_record'(new string'("CSM is in idle state"), 
now, MCLASS_CS_INFO, MCODE_CSM_INFO, 0, null);
---

Dabei ist "CSM is in idle state" ein string, damit ich daraus eine Line 
machen kann, muss ich einen line-Konstruktor mit dem string aufrufen. 
Nach meinem Verständnis liegt der String jetzt also zwei mal bei mir im 
Speicher. Wenn ich von dem bestehenden string die Adresse bekommen 
könnte, müsste ich eine line haben. Aber ich finde nichts, wie ich in 
VHDL die Adresse von einem bestehenden Objekt bekomme.

von Matthias F. (flint)


Lesenswert?

Ein anderes meiner Probleme/Fragen hängt mit dem Verhalten von read aus 
std.textio zusammen: Soweit ich es sehe, ist das read konsumierend. 
Dadurch entsteht für mich folgendes Problem: Die Kommandos an die 
Testbench werden am Anfang geparst und in eine Linked List gelegt. Aus 
dieser holt sich dann die eigentlich State Machine die Kommandos der 
Reihe nach und exekutiert sie. Ich habe im Moment eine Loop-Anweisung 
vorgesehen. Die State Machine soll sich, wenn sie das Loop Start 
Kommando findet, einen access zu diesem Kommando merken und bei der 
Instruktion Loop End wieder zu diesem zurückspringen, solange bis ein 
Loop Counter auf 0 ist. Die Folge ist, dass es beim zweiten Abarbeiten 
der Kommandos zu Lesefehlern kommt. Anscheinend verändere ich den 
line-Zeiger dadurch, dass ich ein read darauf aufrufe.

Gibt es Standardfunktionen, die nicht konsumierend lesen oder müsste ich 
mir so etwas, wenn ich die Loops wirklich brauche, selber 
implementieren?

von Mathi (Gast)


Lesenswert?

Wieso solltest Du zweimal den String im Speicher haben? Der Typ line ist 
ein access auf einen String. Somit sollte der Konstruktor einen Pointer 
auf dieses Objekt liefern. Also sollte es diesen String nur einmal 
geben. Mal davon abgesehen das es eh ein anonymes Objekt ist.
Oder vielleicht versteh ich auch Dein Problem falsch.

Es gibt im Standard keine read-Funktion die nicht konsumierend ist.

von Xenu (Gast)


Lesenswert?

>holt sich dann die eigentlich State Machine die Kommandos der
>Reihe nach und exekutiert sie

Die armen Kommandos - warum werden die hingerichtet?

von Matthias F. (flint)


Lesenswert?

@Mathi: Ich denke schon, dass ich diesen String dann zweimal im Speicher 
habe. Ich habe folgenden Code ausprobiert (nur auszugsweise, da ich ihn 
in den Parser-Prozess in meinem design geschrieben habe):


---
    variable tmpline1 : line := new string'("if you can read this string 
it was not deallocated");
    variable tmpline2 : line;

  begin  -- process parse_tcs_file

    tmpline2 := new string'(tmpline1.all);
    deallocate(tmpline1);

    report tmpline2.all severity note;
---


Wenn ich das dann laufen lasse kommt auch wirklich dieser String heraus:

# ** Note: if you can read this string it was not deallocated

Wenn ich vor dem report noch deallocate(tmpline2) aufrufe bekomme ich 
bei report dann, wie gedacht, ein SIGSEV geliefert.


Mein Eindruck ist also, dass entweder der String wirklich im Speicher 
dupliziert wird oder aber ein reference counting implementiert ist und 
danach schauen mir die Ergebnisse meiner Google-Suche bisher nicht aus.

von Mathi (Gast)


Lesenswert?

Aber Du erzeugst in dem Beipiel ja ein neues String-Objekt in tmpline2 
mit dem Wert von tmpline1. Wenn ich das so richtig sehe. Dann ist das 
Verhalten richtig.
Ich muss aber auch erst nochmal mein VHDL-Buch zu rate ziehen.

von Matthias F. (flint)


Lesenswert?

Ich habe ja nicht gesagt, dass das Verhalten falsch ist. Aber für mich 
existiert jetzt in beiden Fällen der String zweimal im Speicher. Das 
würde ich gerne vermeiden.

Andere Frage: Hat jemand eine Ahnung wie man an eine VHDL language 
reference kommt, ohne dafür 126 dollar zu löhnen? Bei mir stapeln sich 
die Fragen und im Netz finde ich keine guten Antworten darauf.

von Matthias F. (flint)


Lesenswert?

Noch ein Codeausschnitt aus dem Modelsim Manual, der den Unterschied 
zwischen Pointer und Objekte duplizieren veranschaulicht:
1
-- Bad VHDL (because L1 and L2 both point to the same buffer):
2
READLINE (infile, L1); -- Read and allocate buffer
3
L2 := L1; -- Copy pointers
4
WRITELINE (outfile, L1); -- Deallocate buffer
5
6
-- Good VHDL (because L1 and L2 point to different buffers):
7
READLINE (infile, L1); -- Read and allocate buffer
8
L2 := new string(L1.all); -- Copy contents
9
WRITELINE (outfile, L1); -- Deallocate buffer

von Mathi (Gast)


Lesenswert?

Das kannst Du aber nur vermeiden, wenn Du es auch korrekt machst. Wenn 
Du ein neues Objekt mit dem Wert eines anderen erzeugst und dafür 
scheinbar einen Copy-Konstruktor verwendest, dann ist wirst Du auch 
einen zweiten String im Speicher bekommen.

von Klaus Falser (Gast)


Lesenswert?

Es gibt in VHDL keine Lösung für dein Problem.
1) Man kann keine Pointer auf existierende Objekte anlegen.
2) Du kannst das Konsumieren nicht vermeiden.
Es ist wie in Deinem Beispiel mit dem guten und schlechtem VHDL Stil.
Wenn Du willst dass Du den String öfter kannst, musst Du ihn vorher 
kopieren. Man kann in VHDL nicht wie in C einen Pointer auf des String 
setzen und diesen dann beliebig verschieben.

von Matthias F. (flint)


Lesenswert?

Das habe ich schon befürchtet. Danke jedenfalls.

Wenn es sich von Aufwand und Gewinn her dafür steht kann ich ja noch 
meine eigenen nicht-konsumierenden read-procedures schreiben. Ist 
jedenfalls eine gute VHDL-Übung.

von Matthias F. (flint)


Lesenswert?

Bevor ich meine Unfähigkeit der Sprache VHDL anlaste, was ist denn die 
Funktion, die man benutzen soll, wenn man einen std_logic_vector zu 
einem String konvertieren will?


Und warum quälen sie einen so mit unterschiedlichen textio packages, ich 
hab std.textio und ieee.std_logic_textio aber mit beiden bringe ich es 
nicht zusammen, einen std_logic_vector in einem String unterzubringen.


Manchmal frage ich mich, ob die Standardisierungsgremien das Thema VHDL 
und Textausgabe nur im besoffenen Zustand besprochen haben. Wenn man 
Fehlermeldungen bekommt wie "Conversion to string can not have string 
literal operand" fühlt man sich ein wenig sehr auf den Arm genommen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.