Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Benutzeravatar
Linux-Fan
Neuling
Neuling
Beiträge: 10
Registriert: 15. Apr 2015 22:22
Kontaktdaten:

Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Linux-Fan » 19. Feb 2017 16:42

Hallo,

ich habe schon damals in der Übung 2.2.2 damit gekämpft und nachdem das jetzt auch in den Beispielaufgaben als 3d auftaucht, bin ich endgültig daran verzweifelt.

Das Problem ist folgendes:
Man will ein Bluespec-Modul haben, welches einen Zähler realisiert, dessen Zählerstand man im selben Takt schreiben und lesen kann. An sich lässt sich das mit RWires oder CRegs realisieren, allerdings habe ich eine solche Variante noch nie erfolgreich kompiliert bekommen bzw. es gab Warnungen wegen Konflikten und die gewünschte Semantik lag nicht vor.

Als ``minimum failing example'' habe ich folgendes geschrieben: http://pastebin.com/GhdTynCn.
Darin ist kein Reset/Load implementiert und der Test ist sehr einfach aufgebaut. Des weiteren habe ich Zähler auslesen und Register aktualisieren in eine Method geschrieben, um Konflikte zwischen dem Auslesen und Aktualisieren zu vermeiden.

Jetzt sagt der Compiler folgendes

Code: Alles auswählen

TU clientssh3:~/wd/cms/beispeilaufgaben$ make
bsc -sim -g mkTrivialTest -u TestTrivial.bsv
checking package dependencies
compiling TestTrivial.bsv
code generation for mkTrivialTest starts
Error: "TestTrivial.bsv", line 53, column 33: (G0004)
  Rule `RL_action_l53c33' uses methods that conflict in parallel:
    tc_ival.port0__write(...)
  and
    tc_ival.port1__read()
  For the complete expressions use the flag `-show-range-conflict'.
Error: "TestTrivial.bsv", line 58, column 33: (G0004)
  Rule `RL_action_l58c33' uses methods that conflict in parallel:
    tc_ival.port0__write(...)
  and
    tc_ival.port1__read()
  For the complete expressions use the flag `-show-range-conflict'.
Error: "TestTrivial.bsv", line 58, column 33: (G0004)
  Rule `RL_action_l58c33' uses methods that conflict in parallel:
    tc_dval.port0__write(...)
  and
    tc_dval.port1__read()
  For the complete expressions use the flag `-show-range-conflict'.
Elaborated error module file created: mkTrivialTest.ba
make: *** [trivial] Error 1
IOW: die eigentlich gewollte Möglichkeit, parallel über mehrere Ports auf das CReg zuzugreifen funktioniert nicht.

Ich vermute, dass man den Konflikt auflösen könnte, wenn man explizit ``write before read'' formalisieren können. Allerdings unterstüzt der `bsc` auf dem Poolrechner keine Scheduling Attributes für Methoden und ich konnte online nichtmal eine Testversion von einem neueren BSC finden, also nicht überprüfen, ob man damit das Problem angehen könnte.

Hat jemand es geschafft einen Zähler mit Concurrent Add + Read (wobei Lesen das NEUE Ergebnis zurückgibt) zu implementieren und ist bereit, sein Wissen zu teilen?

Edit: Erst schreiben, dann Lesen :)

JHofmann
Endlosschleifenbastler
Endlosschleifenbastler
Beiträge: 182
Registriert: 23. Apr 2015 10:43

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von JHofmann » 19. Feb 2017 16:53

Moin,

teilen Sie mal folgende Rule in auf:

Code: Alles auswählen

 action
  tc.inc(40);
  tc.dec(20);
  let rp <- tc.get();
  if(rp != 22)
    $display("[FAIL] GOT %d", rp);
  else
    $display("[ OK ]");
  endaction
Sie können nicht auf verschiedene CReg Stufen in der selben Rule zugreifen.

Viele Grüße,

Fabian Czappa
Mausschubser
Mausschubser
Beiträge: 44
Registriert: 10. Mai 2015 11:45

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Fabian Czappa » 19. Feb 2017 16:54

Hay,

das sieht ziemlich schrecklich aus :D
Versuchs doch nochmal so (Es gibt keinen Grund, sich so viel Stress zu machen, das sind 5 Zeilen Code alles in allem):
Du hast ein Register mit mehreren Ports, von dem aktualisierst du dann immer den Wert Schritt für Schritt und gibst den letzten aus.

Viele Grüße
Fabian

Benutzeravatar
Linux-Fan
Neuling
Neuling
Beiträge: 10
Registriert: 15. Apr 2015 22:22
Kontaktdaten:

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Linux-Fan » 19. Feb 2017 17:15

JHofmann hat geschrieben:teilen Sie mal folgende Rule in auf:
[...]
Sie können nicht auf verschiedene CReg Stufen in der selben Rule zugreifen.
Das war der entscheidende Hinweis! Vielen Dank, jetzt funktioniert es: http://pastebin.com/zSkSpGBx :) :)
Fabian Czappa hat geschrieben:das sieht ziemlich schrecklich aus :D
Versuchs doch nochmal so (Es gibt keinen Grund, sich so viel Stress zu machen, das sind 5 Zeilen Code alles in allem):
Du hast ein Register mit mehreren Ports, von dem aktualisierst du dann immer den Wert Schritt für Schritt und gibst den letzten aus.
Jetzt da ich es geschafft habe, dass es funktioniert (die neue Lösung ist noch hässlicher als vorher...) mache ich mich daran, das mit dem `reset` aus der Aufgabe zu versehen und stilmäßig zu verbessern :)

Soulztorm
Neuling
Neuling
Beiträge: 5
Registriert: 8. Mär 2015 20:06

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Soulztorm » 19. Feb 2017 17:48

Hi Leute,

hierzu hab ich auchmal die "5 Zeilen" (Tatsächlich exakt 5) Lösung versucht, in dem ich in einem takt über ein 4 Port CReg jeweils up, down, reset, und am letzten port getCounter ausgebe:

http://pastebin.com/4ybxD2Jp

Fehler seht ihr unten im Console dump (sowas: )

Error: "CRegCounter.bsv", line 40, column 25: (G0004)
Rule `RL_action_l40c25' uses methods that conflict in parallel:
uut_ctr.port0__write(...)
and
uut_ctr.port1__read()


Wo ist jetzt mein Denkfehler?
Ich dachte ich kann in einem takt alle aktionen auf den 4 CReg ports ausführen, und nach jedem takt steht der aktuelle wert in allen 4 ports?

Fabian Czappa
Mausschubser
Mausschubser
Beiträge: 44
Registriert: 10. Mai 2015 11:45

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Fabian Czappa » 19. Feb 2017 17:52

Wie schon so oft im Forum erwähnt:
Die Port können nicht gleichzeitig angesprochen werden (Logisch, siehe die Hardware), also auch nicht innerhalb einer Regel bzw einer Action in einer FSM.

Soulztorm
Neuling
Neuling
Beiträge: 5
Registriert: 8. Mär 2015 20:06

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Soulztorm » 19. Feb 2017 18:06

OK also wenn ich die Testbench nicht als Aktion sondern als parallele Umgebung setze funktioniert alles in einem Takt. Ist das dann auch korrekt? Oder ist bei meiner Implementation noch irgendwas falsch?

Benutzeravatar
Linux-Fan
Neuling
Neuling
Beiträge: 10
Registriert: 15. Apr 2015 22:22
Kontaktdaten:

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Linux-Fan » 19. Feb 2017 18:13

Wenn ich meine Testbench darauf ausführe, erhalte ich einen Fehler, der daher resultiert, dass `reset()` bei der Implementierung aus http://pastebin.com/4ybxD2Jp dafür sorgt, dass gleichzeitge up and down nicht berücksichtigt werden (also wird reset logisch gesehen ``nach'' up und down ausgeführt). Solange man sich dessen bewusst ist, würde ich sagen, dass die Lösung richtig ist :)

Soulztorm
Neuling
Neuling
Beiträge: 5
Registriert: 8. Mär 2015 20:06

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Soulztorm » 19. Feb 2017 18:21

Ja gut, da ich das irgendwie umgedreht hatte (Was nicht so viel Sinn gemacht hat tbh. :D) kam bei jedem reset auch 0 raus, jetzt nochmal ports getauscht, und in jeder par umgebung kann ich resetten, erhöhen und erniedrigen und der Wert stimmt.

Edit: der "Fehler" ist ne Warnung?!

Fabian Czappa
Mausschubser
Mausschubser
Beiträge: 44
Registriert: 10. Mai 2015 11:45

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Fabian Czappa » 19. Feb 2017 18:31

Ihr redet gerade an mir vorbei, falls ich eine Frage (ist da überhaupt eine) überlesen habe, dann sagt das nochmal.

Code: Alles auswählen

Error: "CRegCounter.bsv", line 40, column 25: (G0004)
  Rule `RL_action_l40c25' uses methods that conflict in parallel:
    uut_ctr.port0__write(...)
  and
    uut_ctr.port1__write(...)
Ist ein richtiger Fehler, weil es falsch ist. Um es nochmal zu sagen: Verschiedenrangige Ports können nicht gleichzeitig angesteuert werden.
Des weiteren ist es nicht spezifiziert, in welcher Reihenfolge die Methoden abgearbeitet werden müssen. Von mir auch aus up < reset < down. Nur getcounter muss am Ende sein.

Benutzeravatar
Linux-Fan
Neuling
Neuling
Beiträge: 10
Registriert: 15. Apr 2015 22:22
Kontaktdaten:

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Linux-Fan » 19. Feb 2017 18:33

Soulztorm hat geschrieben:Edit: der "Fehler" ist ne Warnung?!
Nein, der Fehler wird von meiner Testbench ausgegeben. Ich schreibe wenn möglich immer Tests, die direkt ein dickes FAIL ausgeben, wenn der Test nicht erfolgreich ausgeführt wurde :), konkret sieht meine Testbench folgendermaßen aus (natürlich fehlen noch die Module mit den Implementierungen, die oben importiert werden, um das direkt auszuführen, aber man kann mit meiner jetzt-funktionsfähigen Lösung von Aufgabe 2.2.2. testen): http://pastebin.com/RRbZy3eL

@Fabian Czappa: Ich glaube/hoffe, dass alle an diesem Thread beteiligten das Problem jetzt gelöst haben, sofern sie es einmal hatten :)

Soulztorm
Neuling
Neuling
Beiträge: 5
Registriert: 8. Mär 2015 20:06

Re: Zähleraktualisierung & Lesen in einem Takt / Übung 2.2.2 / Beispielaufgabe 3d

Beitrag von Soulztorm » 19. Feb 2017 18:40

Ok, dass ich in einer Rule oder Action nicht auf mehrere Ports zugreifen kann weiss ich jetzt.
Wenn ich jetzt also die Aktionen in einer par Umgebung habe, erstellt mir die FSM daraus Regeln, die getrennt alle zum selben Takt ausgeführt werden, in der Impliziten Ordnung durch die Ports?

Dieses Modul:

Code: Alles auswählen

module mkCounter(CRegCounter);
	Reg#(Int#(32)) ctr[4] <- mkCReg(4, 0);

	method Action up(Int#(32) v); 
		ctr[1] <= ctr[1] + v;
	endmethod
	
	method Action down(Int#(32) v);
		ctr[2] <= ctr[2] - v;
	endmethod
	
	method Action reset();
		ctr[0] <= 0;
	endmethod
	
	method Int#(32) getCounter();
		return ctr[3];	
	endmethod	
endmodule
und diese Testbench:

Code: Alles auswählen

	Stmt teststmt = {
		seq
			par
				uut.up(32);
				uut.down(11);
				$display("Counter is: %d", uut.getCounter());
				uut.reset();
			endpar	
			
			par
				uut.up(42);
				$display("Counter is: %d", uut.getCounter());
				uut.reset();
			endpar	
		endseq		
	};
führen zwar zu einer Warnung, aber zu der erwarteten Ausgabe von 21 und 42.

Antworten

Zurück zu „Archiv“