Ich habe die folgende VHDL-Funktion, die eine gegebene mxn-Matrix a
mit einem nx1-Vektor multipliziert b
:
function matrix_multiply_by_vector(a: integer_matrix; b: integer_vector; m: integer; n: integer)
return integer_vector is variable c : integer_vector(m-1 downto 0) := (others => 0);
begin
for i in 0 to m-1 loop
for j in 0 to n-1 loop
c(i) := c(i) + (a(i,j) * b(j));
end loop;
end loop;
return c;
end matrix_multiply_by_vector;
Es funktioniert gut, aber was implementiert dies tatsächlich in Hardware? Insbesondere möchte ich wissen, ob es intelligent genug ist, um zu erkennen, dass es die innere for-Schleife parallelisieren kann, wobei im Wesentlichen ein Punktprodukt für jede Zeile der Matrix berechnet wird. Wenn nicht, wie lässt sich die Matrix-Vektor-Multiplikation am einfachsten (dh mit einer schönen Syntax) parallelisieren?
Antworten:
In 'Hardware' (VHDL oder Verilog) werden alle Schleifen abgewickelt und parallel ausgeführt.
Somit wird nicht nur Ihre innere Schleife, sondern auch Ihre äußere Schleife abgerollt.
Dies ist auch der Grund, warum die Schleifengröße zur Kompilierungszeit bekannt sein muss. Wenn die Schleifenlänge unbekannt ist, beschwert sich das Synthesewerkzeug.
Es ist eine bekannte Falle für Anfänger, die aus einer SW-Sprache kommen. Sie versuchen zu konvertieren:
Zur VHDL / Verilog-Hardware. Das Problem ist, dass in der Simulation alles gut funktioniert. Das Synthesewerkzeug muss jedoch Addierer generieren:
c = b+b+b+b...b;
Dazu muss das Tool wissen, wie viele Addierer erstellt werden müssen. Wenn
a
ist eine konstante Geldstrafe! (Auch wenn es 4.000.000 ist. Es wird keine Tore mehr haben, aber es wird versuchen!)Aber wenn
a
es sich um eine Variable handelt, geht sie verloren.quelle
Dieser Code parallelisiert beide Schleifen, da Sie kein Ereignis definiert haben, um eine Teilmenge der Verarbeitung zu steuern. Schleifen generieren nur so viel Hardware, wie sie zum Generieren der Funktion benötigen. Sie brauchen einen Prozess .
Ein Prozess verfügt über eine Sensitivitätsliste, die VHDL (oder dem Synthesizer) mitteilt, dass der Prozess nur aufgerufen wird, wenn sich einer der Knoten in der Liste ändert. Dies kann verwendet werden, um Latches zu synthetisieren und über den Bereich der reinen kombinatorischen Implementierung hinaus zu expandieren.
quelle