Mam następującą funkcję VHDL, która zwielokrotnia podaną macierz MXN a
przez wektor NX1b
:
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;
Działa dobrze, ale co to właściwie implementuje w sprzęcie? W szczególności chcę wiedzieć, czy jest wystarczająco inteligentny, aby zdać sobie sprawę, że może zrównoleglać wewnętrzną pętlę for, w zasadzie obliczając iloczyn iloczynu dla każdego rzędu matrycy. Jeśli nie, jaki jest najprostszy (tj. Niezła składnia) sposób na zrównoleglenie mnożenia macierzy i wektora?
Odpowiedzi:
W „sprzęcie” (VHDL lub Verilog) wszystkie pętle są rozwijane i wykonywane równolegle.
W ten sposób rozwijana jest nie tylko wewnętrzna pętla, ale również zewnętrzna pętla.
Z tego powodu rozmiar pętli musi być znany w czasie kompilacji. Gdy długość pętli jest nieznana, narzędzie do syntezy narzeka.
Jest to dobrze znana pułapka dla początkujących pochodzących z języka SW. Próbują przekonwertować:
Do sprzętu VHDL / Verilog. Problem polega na tym, że wszystko działa dobrze w symulacji. Ale narzędzie do syntezy musi generować sumatory:
c = b+b+b+b...b;
W tym celu narzędzie musi wiedzieć, ile dodatków wykonać. Gdyby
a
to jest stała grzywna! (Nawet jeśli jest to 4.000.000. Skończy mu się brama, ale spróbuje!)Ale jeśli
a
jest zmienną, zostaje utracona.źródło
Ten kod zrównolegla obie pętle, ponieważ nie zdefiniowano zdarzenia sterującego żadnym podzbiorem przetwarzania. Pętle generują tyle sprzętu, ile potrzebują do wygenerowania funkcji; potrzebujesz PROCESU .
Proces ma listę wrażliwości, która mówi VHDL (lub syntezatorowi), że proces nie jest wywoływany, chyba że zmieni się jeden z węzłów na liście. Można to wykorzystać do syntezy zatrzasków i rozszerzenia poza dziedzinę czystej implementacji kombinatorycznej.
źródło