600 likes | 802 Views
Krzysztof Bikonis binio@eti.pg.gda.pl p. 738 tel. 347 1326. Programowanie Procesorów Sygnałowych. Tematyka zajęć. Procesory stałoprzecinkowe rodziny ADSP-21xx Procesory zmiennoprzecinkowe rodziny ADSP-21k Środowisko programistyczne (symulacja, kompilacja, uruchamianie)
E N D
Krzysztof Bikonis binio@eti.pg.gda.pl p. 738 tel. 347 1326 Programowanie Procesorów Sygnałowych
Tematyka zajęć • Procesory stałoprzecinkowe rodziny ADSP-21xx • Procesory zmiennoprzecinkowe rodziny ADSP-21k • Środowisko programistyczne (symulacja, kompilacja, uruchamianie) • Praca w grupach z zestawami - ADSP-2181 EZ-LAB x5
Architektura procesorów stałoprzecinkowych z rodziny 21xx Jednostka arytmetyczno-logiczna • wykonywane operacje: dodawanie, dodawanie z przeniesieniem, odejmowanie, odejmowanie z „pożyczką”, zmiana znaku, operacje logiczne AND, OR, XOR, NOT • 16-bitowe rejestry AX0 i AX1 – pierwszy argument operacji, AY0 i AY1 – drugi argument operacji, AR i AF – wynik operacji (AR -> DMD BUS, AF -> drugi argument operacji) • R BUS -> wyjścia innych układów jako drugi argument operacji • rejestry mogą być odczytywane i zapisywane w jednym cyklu rozkazowym (odczyt na początku, zapis na końcu cyklu) • argumenty stałoprzecinkowymi liczbami ułamkowymi w formacie 1.15
Architektura procesorów stałoprzecinkowych z rodziny 21xx Jednostka arytmetyczno-logiczna • wykonywane operacje: dodawanie, dodawanie z przeniesieniem, odejmowanie, odejmowanie z „pożyczką”, zmiana znaku, operacje logiczne AND, OR, XOR, NOT • 16-bitowe rejestry AX0 i AX1 – pierwszy argument operacji, AY0 i AY1 – drugi argument operacji, AR i AF – wynik operacji (AR -> DMD BUS, AF -> drugi argument operacji) • R BUS -> wyjścia innych układów jako drugi argument operacji • rejestry mogą być odczytywane i zapisywane w jednym cyklu rozkazowym (odczyt na początku, zapis na końcu cyklu) • argumenty stałoprzecinkowymi liczbami ułamkowymi w formacie 1.15 10000000000000000B = -1 11000000000000000B = -0.5 00000000000000000B = 0 00111111111111111B = 0.5 01111111111111111B = 1
Architektura procesorów stałoprzecinkowych z rodziny 21xx Jednostka arytmetyczno-logiczna • wykonywane operacje: dodawanie, dodawanie z przeniesieniem, odejmowanie, odejmowanie z „pożyczką”, zmiana znaku, operacje logiczne AND, OR, XOR, NOT • 16-bitowe rejestry AX0 i AX1 – pierwszy argument operacji, AY0 i AY1 – drugi argument operacji, AR i AF – wynik operacji (AR -> DMD BUS, AF -> drugi argument operacji) • R BUS -> wyjścia innych układów jako drugi argument operacji • rejestry mogą być odczytywane i zapisywane w jednym cyklu rozkazowym (odczyt na początku, zapis na końcu cyklu) • argumenty stałoprzecinkowymi liczbami ułamkowymi w formacie 1.15 Znaczenie bitów rejestru stanu ASTAT • AZ – oznacza AR=0 • AN – oznacza AR ujemne • AC – oznacza przeniesienie z najbardziej znaczącej pozycji wyniku dodawania • AV – oznacza przepełnienie AR • AS – znak argumentu pierwszego (X) dla ALU • AQ – bit wyniku generowany podczas dzielenia Znaczenie bitów rejestru trybu MSTAT • 3 – ALU przechodzi do pracy z „nasyceniem” (gdy wystąpi przepełnienie -> AR największa/najmniejsza możliwa liczba dla tego rej.) • 2 – zatrzaskiwanie stanu przepełnienia • 0 – wybór zbioru rejestrów ALU 0 = pierwszy 1 = drugi 10000000000000000B = -1 11000000000000000B = -0.5 11111111111111111B = 0 00111111111111111B = 0.5 01111111111111111B = 1
Architektura procesorów stałoprzecinkowych z rodziny 21xx Układ mnożąco-akumulujący • wykonywane operacje: mnożenie liczb stałoprzecinkowych oraz mnożenie i akumulacja (dodawanie lub odejmowanie) • 16-bitowe rejestry MX0 i MX1 – pierwszy argument operacji, MY0 i MY1 – drugi argument operacji, 40-bitowy rejestr MR (MR2 8 bitów, MR1 i MR0 16 bitów) – rejestr wyjściowy • rejestr MR ma własność „nasycenia”, czyli jeśli zostanie wykryte przepełnienie to do MR zostanie zapisana największa/najmniejsza 32-bitowa liczba (Czy rejestr MR zostanie „nasycony”, czy nie, jest częścią kodu instrukcji) • możliwość zaokrąglania 40-bitowego wyniku obliczeń do 16 bitów, wynik zaokrąglenia do rejestru MF, lub MR1 (znak powielony w rejestrze MR2) • 16-bitowy rejestr MF – rejestr pośredniczący, można go wykorzystać w następnym rozkazie mnożenia przez podanie na wejście Y układu mnożącego • rejestry mogą być odczytywane i zapisywane w jednym cyklu rozkazowym (odczyt na początku, zapis na końcu cyklu)
Architektura procesorów stałoprzecinkowych z rodziny 21xx Układ mnożąco-akumulujący • wykonywane operacje: mnożenie liczb stałoprzecinkowych oraz mnożenie i akumulacja (dodawanie lub odejmowanie) • 16-bitowe rejestry MX0 i MX1 – pierwszy argument operacji, MY0 i MY1 – drugi argument operacji, 40-bitowy rejestr MR (MR2 8 bitów, MR1 i MR0 16 bitów) – rejestr wyjściowy • rejestr MR ma własność „nasycenia”, czyli jeśli zostanie wykryte przepełnienie to do MR zostanie zapisana największa/najmniejsza 32-bitowa liczba (Czy rejestr MR zostanie „nasycony”, czy nie, jest częścią kodu instrukcji) • możliwość zaokrąglania 40 bitowego wyniku obliczeń do 16 bitów, wynik zaokrąglenia do rejestru MF, lub MR1 (znak powielony w rejestrze MR2) • 16-bitowy rejestr MF – rejestr pośredniczący, można go wykorzystać w następnym rozkazie mnożenia przez podanie na wejście Y układu mnożącego • rejestry mogą być odczytywane i zapisywane w jednym cyklu rozkazowym (odczyt na początku, zapis na końcu cyklu) Znaczenie bitów rejestru stanu ASTAT • MV – oznacza przepełnienie MR Jeśli wynik operacji mnożenia i akumulacji nie mieści się w parze rejestrów MR1, MR0, to najbardziej znaczący bity wyniku znajdują się w rejestrze MR2 i ustawiana jest flaga MV przepełnienia akumulatora MR Znaczenie bitów rejestru trybu MSTAT • 0 – wybór zbioru rejestrów 0 = pierwszy 1 = drugi • 4 – tryb pracy 0 = liczby ułamkowe (1.15) 1 = liczby całkowite (16.0) Dla liczb 1.15 32-bitowy wynik mnożenia jest rozszerzany do 40 bitów poprzez powielenie bitu znaku, przesuwany w lewo o jeden bit i podawany na wejście układu sumatora Dla liczb 16.0 rozszerzony do 40 bitów wynik jest bezpośrednio podawany na wejście układu sumatora
Architektura procesorów stałoprzecinkowych z rodziny 21xx Przesuwnik • pozwala jednym rozkazem umieścić 16-bitowy argument w dowolnym miejscu 32-bitowego rejestru wyjściowego, łącznie z sytuacją gdy argument pozostaje poza rejestrem wyjściowym (49 położeń w rejestrze wyjściowym) • 16-bitowy rejestr wejściowy SI – przesuwana liczba, 8-bitowy rejestr SE – liczba pozycji binarnych do przesunięcia (SE dodatnie – w lewo, SE ujemne – w prawo), 8-bitowy rejestr SB – argument w przypadku normalizacji lub denormalizacji bloku liczb, 32-bitowy rejestr SR (SR1 i SR0 po 16 bitów) – wynik operacji • rejestry mogą być odczytywane i zapisywane w jednym cyklu rozkazowym (odczyt na początku, zapis na końcu cyklu), są zdublowane (wybór poprzez bit 0 rejestru MSTAT)
Architektura procesorów stałoprzecinkowych z rodziny 21xx Generatory adresowe • I – rejestry indeksowe, M – rejestry modyfikacji, L – rejestry długości • wykorzystując rejestr długości L można zorganizować w pamięci bufor kołowy, wtedy rejestr indeksowy I jest używany jako wskaźnik, natomiast rejestr L przechowuje długość bufora, a kiedy wskaźnik I przekroczy górną granicę bufora, to do rejestru I zostanie załadowany adres bazowy bufora
Architektura procesorów stałoprzecinkowych z rodziny 21xx Sterowanie procesorem • instrukcje są pobierane z kolejnych komórek pamięci programu wskazywanych przez licznik programu PC • każda instrukcja jest wykonywana w jednym cyklu zegarowym • zmiana kolejności realizacji instrukcji dokonuje się w wyniku wykonania instrukcji skoku, instrukcji skoku ze śladem (wywołanie podprogramu) lub instrukcji organizującej pętlę DO UNTIL (możliwość zagnieżdżania do czterech poziomów) • przerwania w sposób sztywny mają przypisany priorytet, mogą być maskowane (IMASK) • STATUS STACK stos sprzętowy, w trakcie obsługi przerwania są tam przechowywane rejestry ASTAT,MSTAT, IMASK • PC STACK stos sprzętowy, w trakcie obsługi przerwania przechowuje licznik rozkazów • tablica wektorów przerwań zaczyna się od adresu 0x0000, a program obsługi przerwania nie może przekraczać czterech instrukcji • powrót z obsługi przerwania za pomocą instrukcji RTI • ICNTL rejestr konfiguracji trybu pracy systemu przerwań, w ten sposób można uzyskać przerwania zewnętrzne czułe na wartość poziomu sygnału lub na jego zbocze lub zagnieżdżania przerwań • IFC rejestr za pomocą którego można programowo wymusić przerwanie sprzętowe lub wyzerować zamaskowane przerwanie oczekujące na obsługę
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx Początek modułu .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD; Koniec programu
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Definicja stałej start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Definicja zmiennych start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Inicjalizacja zmiennych start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Powiązanie portu ze zmienną start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD; Tablica wektorów przerwań
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Inicjalizacja rejestrów indeksowych start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Inicjalizacja rejestrów długości start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; Inicjalizacja rejestrów modyfikacji start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD; Inicjalizacja rejestru licznika
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD; Wykorzystanie możliwościwykonywania kilku operacjijednocześnie
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD; KonstrukcjaDO etykieta UNTIL warunek
Symulator procesorów stałoprzecinkowych z rodziny 21xx .MODULE vector_add; .CONST n=10; .VAR/DM/RAM x_input[n]; .VAR/PM/RAM/ABS=100 y_input[n]; .INIT x_input: <xin.dat>; .INIT y_input: <yin.dat>; .PORT z_out; JUMP start; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; RTI; NOP; NOP; NOP; start: I2=^x_input; L2=0; I6=^y_input; L6=0; M0=1; L0=0; M5=1; L5=0; CNTR=n-1; AX0=DM(I2,M0), AY0=PM(I6,M5); DO add_loop UNTIL CE; AR=AX0+AY0, AX0=DM(I2,M0), AY0=PM(I6,M5); add_loop: DM(z_out)=AR; AR=AX0+AY0; DM(z_out)=AR; IDLE; .ENDMOD; Wprowadzenie procesoraw stan bezczynności
Symulator procesorów stałoprzecinkowych z rodziny 21xx X_INPUT 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A Y_INPUT 000B 000C 000D 000E 000F 0010 0011 0012 0013 0014 Z_OUT 000C 000E 0010 0012 0014 0016 0018 001A 001C 001E
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} Definicja bufora kołowego gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} Inicjalizacja rejestrówindeksowego (I), modyfikacji (M) i długości (L) gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} Generowanie sinusa gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
64k 0 – 0000H, pi – 7FFFH, 2pi – FFFFH 0100 0001 1000 1001B = 4189H 2-1 2-7 2-8 2-12 2-15 0.5 + 0.0078 + 0.0039 + 0.00024414 + 0.000030518 = 0.512 Symulator procesorów stałoprzecinkowych z rodziny 21xx sin(t) 440Hz ≈ 2.27ms t 8kHz 125μs
Symulator procesorów stałoprzecinkowych z rodziny 21xx Arithmetic shift 00000001 10111000 00000000 00000000 00001101 11000000 00000000 00000000 .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} SR1 SR0 gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx Dwa przykłady zaokrąglania. Pierwszy to typowa operacja zaokrąglania (x=0 lub1). Przykład 1 MR2 MR1 MR0Przed: xxxxxxxx xxxxxxxx00100101 1xxxxxxxxxxxxxxxBit 15 = 1. Dodajemy 1 do bitu 15 1Po: xxxxxxxx xxxxxxxx00100110 0xxxxxxxxxxxxxxx Drugi, gdy 15 najmłodszych bitów to zera. Przykład 2 MR2 MR1 MR0 Przed: xxxxxxxx xxxxxxxx00100110 1000000000000000 Bit 15 = 1, bity 0-14 = 0. Dodajemy 1 do bitu 15 1 xxxxxxxx xxxxxxxx00100111 0000000000000000 Bit 16 = 1, wymuszone na tym bicie 0 Po: xxxxxxxx xxxxxxxx00100110 0000000000000000
Symulator procesorów stałoprzecinkowych z rodziny 21xx Arithmetic shift dddddddd dddddddd 00000000 00000000 dddddddd dddddddd d0000000 00000000 .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=sr1; wait: idle; jump wait; {-------------------------------} SR1 SR0 gen_sin: si=440; { freq stored as Hz } sr=ashift si by 3 (hi); my0=h#4189; { mult Hz by .512 * 2 } mr=sr1*my0(rnd); { i.e. mult by 1.024 } sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .var/dm theta; .var/dm/ram/circ buf[N]; .init theta: 0; jump start; start: i0=^buf;m0=1;l0=%buf; cntr=%buf; do gen until ce; call gen_sin; gen: dm(i0,m0)=ar; wait: idle; jump wait; gen_sin: si=100; sr=ashift si by 3 (hi); my0=h#4189; mr=sr1*my0(rnd); sr=ashift mr1 by 1 (hi); ay0=dm(theta); ar=sr1+ay0; dm(theta)=ar; ax0=ar; call boot_sin; ar=abs ar; rts; #include "sin.dsp" .endmod;
Symulator procesorów stałoprzecinkowych z rodziny 21xx .module/RAM/ABS=0 ex; .const N=0x100; .const freq1=440; .const freq2=220; .var/dm theta1; .var/dm theta2; .var/dm dtheta1; .var/dm dtheta2; .var/dm/ram/circ buf1[N]; .var/dm/ram/circ buf2[N]; .var/dm/ram/circ buf3[N]; .init theta1: 0; .init theta2: 0; jump start; start: si=freq1; sr=ashift si by 3 (hi); my0=h#4189; mr=sr1*my0(rnd); sr=ashift mr1 by 1 (hi); dm(dtheta1)=sr1; si=freq2; sr=ashift si by 3 (hi); my0=h#4189; mr=sr1*my0(rnd); sr=ashift mr1 by 1 (hi); dm(dtheta2)=sr1; i0=^buf1;m0=1;l0=%buf1; i1=^buf2;m1=1;l1=%buf2; i2=^buf3;m2=1;l2=%buf3; m3=0; cntr=%buf1; do gen until ce; call gen_sin; gen: nop; wait: idle; jump wait; gen_sin: ax0=dm(dtheta1); ay0=dm(theta1); ar=ax0+ay0; dm(theta1)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); dm(i0,m3)=sr1; ax0=dm(dtheta2); ay0=dm(theta2); ar=ax0+ay0; dm(theta2)=ar; ax0=ar; call boot_sin; sr=ashift ar by -1 (hi); dm(i1,m3)=sr1; ax0=dm(i0,m0); ay0=dm(i1,m1); ar=ax0+ay0; dm(i2,m2)=ar; rts; #include "sin.dsp" .endmod;