# SYK ### Zadanie 1 ![](https://i.imgur.com/PyNSCft.png) ![](https://i.imgur.com/wWGUnoU.png) ![](https://i.imgur.com/kIwLkWu.png) ![](https://i.imgur.com/tndVYLU.png) ![](https://i.imgur.com/u86Fbny.png) ### Zadanie 2 | C P | A | B | Komentarz | | ---- | ---- | ---- | --- | | 0 **0000** | 1001 | 1101 | | |||| ↓ Dodanie B | | 0 **1101** | 1001 | 1101 | | |||| ↓ Shift w prawo (PA) | | 0 **1110** | **1**100 | 1101 | | |||| ↓ Dodanie 0 <BR>↓ Shift w prawo (PA) | | 0 **1111** | **01**10 | 1101 | | |||| ↓ Dodanie 0 <BR>↓ Shift w prawo (PA) | | 0 **1111** | **101**1 | 1101 | | |||| ↓ Dodanie B | | 1 **1100** | **101**1 | 1101 | | |||| ↓ Shift w prawo (PA) | | 0 **1110** | **0101** | 1101 | | Rejestr ( P ) przechowuje teraz liczbę w U2 Podczas przesuwania w prawo chcemy zachować wartość części rejestru (PA) odpowiadającą wynikowi. Aby to uzyskać jedyna zmianą jest to, że, po przesunięciu najbardziej znaczący bit powinien być aktualną wartością najbardziej znaczącego bitu. ### Zadanie 3 Pomysłem stojącym za metodą "shifting over zeros" jest pominięcie operacji dodawania, jeśli najmniej znaczącycy bit A ma wartość 0 (oczywiście nie pomijamy przesunięcia). Stąd nazwa "shifting over zeros". W praktyce jednak rzadko korzysta się z tej metody, ze względu na złożoność czasową zależną od argumentów oraz brak znaczącej przewagi w porównaniu do zwykłych algorytmów. | P | A | B | Komentarz| | ---- | ---- | -----| --- | | 0000 | 1001 | 0011 | init | ||||standardowe dodanie + <br>przesunięcie| | 0001 | 1100 | 0011 | | |||| pomijamy dodawanie!<br>samo przesunięcie | | 0000 | 1110 | 0011 | | |||| pomijamy dodawanie!<br>samo przesunięcie| | 0000 | 0111 | 0011 | | |||| standardowe dodanie + <br>przesunięcie| | 0001 | 1011 | 0011 | koniec, wynik = 27| ### Zadanie 4 Kodowanie Booth'a bazuje na następującej obserwacji: ![](https://i.imgur.com/Hc7Fbju.png) Wykorzystując ją, możemy na podstawie dwóch kolejnych bitów liczby A (przyjmujemy a<sub>-1</sub>=0) decydować, czy do wyniku dodajemy B, czy -B. ![](https://i.imgur.com/PUIwUVi.png) Najwyższy bit przechodzi z poprzedniego stanu (jest duplikowany) Przykład mnożenia dla A=-9 B=3 | P | A | B | -B |Komentarz| | ---- | ---- | ----- | --- | --- | | 00000 | 10111 | 00011 |11101| init| | ||||| a<sub>0</sub>=1, a<sub>-1</sub>=0, odejmujemy B| | 11110 | 11011 | 00011 | 11101| | ||||| a<sub>1</sub>=1, a<sub>0</sub>=1, dodajemy 0| | 11111 | 01101 | 00011 | 11101| | ||||| a<sub>2</sub>=1, a<sub>1</sub>=1, dodajemy 0| | 11111 | 10110 | 00011 | 11101 | | ||||| a<sub>3</sub>=0, a<sub>2</sub>=1, dodajemy B| | 00001 | 01011 | 00011 |11101| | ||||| a<sub>4</sub>=1, a<sub>3</sub>=0, odejmujemy B| | 11111 | 00101 | 00011 |11101| | ### Zadanie 5 ![](https://i.imgur.com/bWGz87n.png) Reguły wykonywania dodawania do rejestru P korzystając z kodowania Booth'a: ![](https://i.imgur.com/0luWOcg.png) Powyższe rozważania można podsumować, że w każdym kroku mamy: $P := P + B * (a_{i-1} - a_{i})$ -> wybór znaku został przedstawiony w niebieskiej "ramce" na rysunku powyżej. Zatem rozwiązanie polega na niejawnej zamianie liczby A (ze znakiem) na postać Booth'a (1, 0 oraz -1 dla każdej pozycji bitowo). Zamiana ta odbywa się zgodnie ze wskazówkami z Appendix J - korzysta z obserwacji, że ciąg postaci k jedynek: `111...1` można zamienić na k+1 elementowy ciąg `100...0(-1)`. Podczas kolejnych kroków (tj. po kolejnych przesunięciach rejestru liczby A) gdy wirtualny bit w reprezentacji Booth'a jest równy 1 -> następuje dodanie B do rejestru P, a gdy równy -1 -> odjęcie. Bity z reprezentacji Booth'a są liczone na bieżąco -> na bazie $a_{-1}$ oraz $a_{0}$, później $a_{0}$ oraz $a_{1}$ itd. rozważając kolejne shift'y. Odpowiednie przesunięcie zostaje wykonane po każdym kroku algorytmu - wiemy więc że będziemy dodawać bity pochodzące z B na odpowiedniej pozycji. Zgodnie z obserwacjami z Appendix J. uznajemy, że $a_{-1}=0$, co jest zgodne z naturalną intuicją. Obliczanie wartości A*B dla A = -9 oraz B = -3. A w systemie U2: 10111 (-16 + 4 + 2 + 1) -> w rejestrze dopiszę 0 na końcu B w systemie U2: 11101 (-16 + 8 + 4 + 1) (w rzeczywistości podział rejestru na P i A nie istnieje - wprowadzam dla czytelności) |rejestr P|rejestr A| co się dzieje?| |-|-|-| | 00000 | 101110 | następuje wstępne wpisanie danych do rejestrów | ||| zauważmy, że B to 11101 | ||| zauważmy, że B to -B to 00010 + 00001 = 00011 - trzymamy to w pamięci | ||| rozpoczynamy obliczenia | | 00011 | 101110 | różnica ostatnich bitów w A to 0 - 1 = -1 => dodajemy -B do P | | 00001 | 1 \ 10111 | shift right | | 00000 | 11 \ 1011 | różnica ostatnich bitów w A to 1 - 1 = 0 => shift indeksów | | 00000 | 011 \ 101 | różnica ostatnich bitów w A to 1 - 1 = 0 => shift indeksów | | 11101 | 011 \ 101 | różnica ostatnich bitów w A to 1 - 0 = 1 => dodajemy B do P | | 11110 | 1011 \ 10 | shift right, na przodzie duplikuję 1 (własności U2)| | 00001 | 1011 \ 10 | różnica ostatnich bitów w A to 0 - 1 = -1 => dodajemy -B do P 11110 + 00011 = 100001 carry out pomijamy| | 00000 | 11011 \ 1 | shift right| Uzyskaliśmy 0000011011 = 1 + 2 + 8 + 16 = 27, czyli poprawny wynik Aby obsłużyć ujemne liczby w rejestrze B korzystamy z obserwacji z zadania 2: mianowicie "najbardziej znaczący bit powinien być alternatywą carry out, oraz aktualnej wartości najbardziej znaczącego bitu." ### Zadanie 6 Schemat: ![](https://i.imgur.com/zC9WBzs.png) Zwyczajowo stosuje się proporcję 3:2 dla IN:OUT. Wtedy na wejściu otrzymujemy 3 liczby, a na wyjściu zwracamy jak niżej: Używając CSA, uzyskujemy proporcję 3:2 w liczbach wierszy na wejściu OUT_1 można zdefiniować jako: $a \oplus b \oplus c$ (nie shiftujemy, ma tyle samo bitów) OUT_2 można zdefiniować jako: $ab \vee ac \vee bc$ (OUT_2 przy wyjściu jest przesuwany o jeden bit w lewo) ### Zadanie 7 <!-- ![](https://i.imgur.com/to7kwFI.png) --> ![](https://i.imgur.com/OoXKUHI.png) Koncept tego algorytmu polega na sprawdzeniu czy od liczby (po kolejnych przesunięciach) można odjąc liczbę m (dzielnik). Wynik jest konstruowany od lewej strony (zgodnie z naturalną koncepcją dzielenia liczb "na kartce") Chodzi o to, że (w przypadku liczb bez znaku) Q / m = B gdy B to największa liczba naturalna taka że Q - M*b >= 0. Zatem dla każdego bitu dzielnika sprawdzamy, czy powinien być zapalony, czy też zgaszony. Jeśli mamy po odjęciu liczby m od Q (przesuniętego odpowiednio) A[n] = 1 liczba stała się ujemna (U2), zatem próbowaliśmy "podzielić" przez zbyt dużą liczbę. Ustawiamy wtedy Q[0] na 0 (ten bit dzielnika musi być zgaszony). Należy również wykonać naprawę. Trzeba ustawić bity w A na takie, jakie były przed nieudaną próbą dzielenia/odejmowania (następuje zw. "restoring"). Jednak gdy A[n] = 0 nasz wynik wciąż jest nieujemy - zatem wiemy, że dana pozycja bitowa w dzielniku musi zawierać wartość 1. Powyższe kroki wykonujemy dopóki nasza liczba jest niepusta, ostatecznie przez magazynowanie odpowiednich wartości w Q[0] na przemian wykonując shift left dostaniemy wynik dzielenia w rejestrze Q oraz wartość reszty z dzielenia w rejestrze A. Wykonajmy następnie dzielenie przykładowych 2 liczb z treści zadania. Mamy dane: Q = 9, M = 3 Bitowo: Q = 1001 (8 + 1) Bitowo w U2: M = 00011 (2 + 1) -M = 11100 + 00001 = 11101 (-16 + 8 + 4 + 1) | n | A | Q | opis wykonywanych operacji |-|-|-|-| |4| 00000 | 1001 | wstępna inicjalizacja |4| 00001 | 001? | shift left |4| 00001 | 001? | próba odjęcia M (tj dodania -M) |4| 11110 | 001? | próba okazała się nieudana |4| 00001 | 0010 | przywróć A, na stan przed próbą, przypisz 0 do `?` |3| 00001 | 0010 | n -= 1 |3| 00010 | 010? | shift left |3| 00010 | 010? | próba odjęcia M (tj dodania -M) |3| 11111 | 010? | próba okazała się nieudana |3| 00010 | 0100 | przywróć A, na stan przed próbą, przypisz 0 do `?` |2| 00010 | 0100 | n -= 1 |2| 00100 | 100? | shift left |2| 00100 | 100? | próba odjęcia M (tj dodania -M), mamy 00100 + 11101 = 100001, ucinamy curry-out - mamy 00001 |2| 00001 | 1001 | próba okazała się udana, przypisz 1 do `?` |1| 00001 | 1001 | n -= 1 |1| 00011 | 001? | shift left |1| 00011 | 001? | próba odjęcia M (tj dodania -M) mamy 00011 + 11101 = 00001 + 11111 = 100000 |1| 00000 | 0011 | próba okazała się udana |0| 00000 | 0011 | n -= 1, skoro n==0 kończymy Wynik = 0011 => 3, reszta = 00000 => 0 (zgodnie z prawdą) ### Zadanie 8 ![](https://i.imgur.com/BFjMHSZ.png) ![](https://i.imgur.com/THZXAkl.png) <u>Algorytm:</u> Powtórz n razy: Jeśli P < 0: a) Przesuń rejestr (PA) w lewo b) Dodaj zawartość rejestru B do rejestru P. W przeciwnym razie: a) Przesuń rejestr (PA) w lewo b) Odejmij zawartość rejestru B od P Jeśli P < 0: a) Ustaw najmniej znaczący bit A na 0 W przeciwnym razie: a) Ustaw najmniej znaczący bit A na 1 Iloraz znajduje się w rejestrze A. Reszta znajduje się w rejestrze P. Jeśli reszta jest ujemna, należy dodać do niej wartość B. Różnica pomiędzy algorytmami restoring i nonrestoring polega na tym, że w wersji nonrestoring jeśli po odjęciu wartości B wartość P stanie się ujemna, to nie przywracamy poprzedniej wartości poprzez dodanie wartości B. | P | A | B | wykonana operacja| | -------- | -------- | -------- | -------- | | 00000 | 1001 | 00011 | inicjalizacja | | 00001 | 001? | 00011 | Shift w lewo | | 11110 | 001? | 00011 | odjęcie B od P | | 11110 | 0010 | 00011 | ustawienie najmniej znaczącego bitu A na 0 | | 11100 | 010? | 00011 | Shift w lewo | | 11111 | 010? | 00011 | dodanie B do P | | 11111 | 0100 | 00011 | ustawienie najmniej znaczącego bitu A na 0 | | 11110 | 100? | 00011 | Shift w lewo | | 00001 | 100? | 00011 | dodanie B do P | | 00001 | 1001 | 00011 | ustawienie najmniej znaczącego bitu A na 1 | | 00011 | 001? | 00011 | Shift w lewo | | 00000 | 001? | 00011 | odjęcie B od P | | 00000 | 0011 | 00011 | ustawienie najmniej znaczącego bitu A na 1 | *Uzasadnienie poprawności* Zauważmy, że działanie tego algorytmu jest podobne do działania algorytmu restoring division Gdy P jest dodatnie, algorytm działa tak samo jak restoring division Gdy P jest ujemne, to nie wykonujemy restore w rejestrze P, więc wartość w rejestrze P jest mniejsza o B niż w sytuacji gdybyśmy zrobili restore następnie po przesunięciu w lewo P w następnym kroku wartość w P jest mniejsza o 2B niż gdybyśmy zrobili restore, ale skoro P jest ujemne to ten algorytm doda B do P stąd otrzymamy odpowiednią wartość P, tak jak w algorytmie restoring division. ### Zadanie 9 **Przedstaw algorytm dzielenia metodą SRT (ang. SRT division).** Dzielimy **a** przez **b** obie są liczbami n bitowymi Zapisujemy a do rejestru A (długość n) Zapisujemy b do rejestru B (długość n) Rejestr P trzyma na początku 0 (długość n+1) 1. Jeśli rejestr B ma k zer wiodących w zapisie n bitowym przesuń rejestr B oraz rejestr (PA) w lewo o k bitów 2. For i=n-1 to 0: + a) Jeśli 3 najbardziej znaczące bity P są sobie równe:<BR>przesuń rejestr (PA) w lewo, ustaw najmniej znaczący bit A na 0 + b) Jeśli 3 najbardziej znaczące bity P nie są sobie równe i P jest ujemne:<BR>przesuń rejestr (PA) w lewo, ustaw najmniej znaczący bit A na -1, dodaj B do P. - c) w przeciwnym przypadku:<BR>przesuń rejestr (PA) w lewo, ustaw najmniej znaczący bit A na 1, odejmij B od P. End loop 3. Jeśli reszta ( P ) jest ujemna popraw wynik (A) odejmując od niego 1, oraz dodając B do P 4. Rejestr P musi być przesunięty o k bitów w prawo (odwracając przesunięcie z kroku 1) 5. A to iloraz P to reszta **Uzasadnij jego poprawność** <!-- Dla uproszczenia Część rejestru (PA) reprezentującą dzielnik będę oznaczał jako X, że X = P,A (przecinek rozdiela część ułamkową) Natomiast część rejestru A oznaczającą aktualną część wyniku jako Q Po wprowadzeniu danych Na początku Dzielna = X*2<sup>n</sup> Dzielnik = B Uzasadnienie niezmiennika: (X*2<sup>c</sup>)/B + Q = wynik podczas wykonywania algorytmu **1. Po wykonaniu przesunięcia o k bitów** (X\*2<sup>n</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q = wynik **2.a** m<=n (P\*2<sup>m</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q = wynik ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ (P\*2<sup>m-1</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q = wynik Przesuwamy P w lewo, więc P jest 2 razy większe,ale 2<sup>m</sup> → 2<sup>m-1</sup>, więc jest wszystko ok **2.b** (P\*2<sup>m</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q = wynik ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ((P+B)\*2<sup>m-1</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q - 2<sup>m-1</sup> = wynik Analogicznie przesunięcie P nic nie zmienia, a dodanie 2<sup>m-1</sup> wyrównane jest poprzez dodanie B do P **2.c** (P\*2<sup>m</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q = wynik ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ((P-B)\*2<sup>m-1</sup>\*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q + 2<sup>m-1</sup> = wynik **3** Ten krok działa tak jak **2.b** **4** Sytuacja przed rozpoczęciem tego kroku wygląda następująco ((P*2<sup>k</sup>)/(B\*2<sup>k</sup>) + Q = wynik Widać, że w celu uzyskania reszty z dzielenia przez B należy przesunąć P o k bitów w prawo --> x,y - liczby bez znaku dzielimy $\frac{x}{y}$ Na początku rejestr $A = x$ $B = y$ $P = 0$ Dla uproszczenia Część rejestru ( PA ) reprezentującą resztę będę oznaczał jako X, Część rejestru ( PA ) reprezentującą iloraz będę oznaczał jako Q, --- **Fakt 1.**(pokazany poźniej) Przed/po każdej iteracji pętli $P \in <-B,B)$ **Dowód Faktu 1** Przed/po każdej iteracji pętli $P \in <-B,B)$ Przed pierwszą iteracją P=0, więc teza zachodzi Jeśli dzielimy liczby n bitowe, to P $P\in<-2^n,2^n-1>$, w rejestrze B najbardziej znaczący bit jest równy 1 $B\in<2^{n-1},2^n-1>$ 2.a Gdy 3 najbardziej znaczące bity są sobie równe, to po SL 2 najbardziej znaczące bity są sobie równe, więc $P \in <-2^{n}+2^{n-1},2^{n-2}+2^{n-1}+...+1>$ $P \in <-2^{n-1},2^{n-1}-1>$ Skor B jest równe co najmniej $2^{n-1}$ , to $P\subseteq<-B,B)$ 2.b P jest ujemne, więc $P \in <-2^n,-1>$ po dodaniu B do P $P \in <-2^n+2^{n-1},-1+B>$,więc $P \in <-2^{n-1},B-1>$ $P\subseteq<-B,B)$ 3.c P jest dodanie/równe 0, więc $P \in <0,2^n-1>$ po odjęciu B od P $P \in <0-B,2^n-1-2^{n-1}>$ $P \in <-B,2^{n-1}-1>$ $P \in <-B,2^{n-1}-1>$ $P \in <-B,B)$ --- Na początku oczywiście $Q = 0$ I poprawny jest niezmiennik, przed każdą iteracją zachodzi: $\frac{X}{B} + Q*2^{i} = wynik$ gdzie i to zmienina i w pętli for danej iteracji $wynik$ - matematyczna postać dzielenia $\frac{x}{y}$ **1. Wykonanie przesunięcia o k bitów** Przesuwamy $\frac{X*2^k}{B*2^k} + Q*2^k = wynik$ Nadal nierówność będzie zachodzić, bo $\frac{X*1}{B*1} + 0*2^k = wynik$ $\frac{X}{B} + 0 = wynik$ $\frac{X}{B} + Q = wynik$ Nowe wartośći rejestrów to $X = X*2^k$ $B = B*2^k$ $Q = Q*2^k = Q$ ,bo $Q=0$ **2.a** $\frac{X-B}{B} + Q*2^i = wynik$ Przesunięcie rejestru (PA) w lewo nie zmienia wartości w X Q jest teraz o 2 większe w związku z presunięciem, ale za to i się zmniejszy o 1, więc niezmiennik zostanie zachowany $\frac{X-B}{B} + (Q*2)*2^{i-1} = wynik$ nowa wartość $Q=Q*2$ **2.b** Przesunięcie rejestru (PA) zachowuje niezmiennik, natomiast odjęcie 1 do A i dodanie B od P, to $\frac{X+B*2^{i-1}}{B} + (Q - 1)*2^{i-1} = wynik$ Działa, bo: $\frac{X+B*2^{i-1}}{B} + Q*2^{i-1} - 1*2^{i-1} = wynik$ $\frac{X}{B}+\frac{B*2^{i-1}}{B} + Q - \frac{B*2^{i-1}}{B} = wynik$ $\frac{X}{B} + Q = wynik$ Nowe wartości rejestrów $X = X+B$ $Q = Q-1$ **2.c** Przesunięcie rejestru (PA) zachowuje niezmiennik, natomiast dodanie 1 do A i odjęcie B od P, to $\frac{X-B*2^{i-1}}{B} + (Q + 1)*2^{i-1} = wynik$ Działa, bo: $\frac{X-B*2^{i-1}}{B} + Q*2^{i-1} + 1*2^{i-1} = wynik$ $\frac{X}{B}-\frac{B*2^{i-1}}{B} + Q + \frac{B*2^{i-1}}{B} = wynik$ $\frac{X}{B} + Q = wynik$ Nowe wartości rejestrów $X = X-B$ $Q = Q+1$ **3.** Niezmiennik zostaje zachowany analogicznie do 2.b Po wykonaniu pewien stan: $\frac{X}{B} + Q = wynik$ Teraz X to dokładnie rejestr P, a Q to dokładnie rejestr A, więc $\frac{P}{B} + A = wynik$ Skoro przed wykonaniem tego kroku $P \in <-B,B)$ to po wykonaniu $P \in <0, B)$ **4.** W tym kroku dzielimy $P$ przez $2^k$ wykonując przesunięcie o k bitów w prawo i wirtualnie dzielimy też $B$ $\frac{P}{2^k} \in <0, \frac{B}{2^k})$ $\frac{P}{2^k} \in <0, y)$ Nowa wartość rejestru $P=\frac{P}{2^k}$, więc $P \in <0, y)$ i wirtualnie traktujemy $B=\frac{B}{2^k}$, więc $\frac{P}{B} + A = wynik$ $\frac{P}{y} + A = wynik$ $P \in <0, y)$, więc A to iloraz, a P to reszta z dzielenia przez y --- Rejestr P zawsze przechowuje taką liczbę, że gdy jest ujemny zawsze po dodaniu P otrzymamy liczbę nieujemną, co za tym idzie dodatnią resztę. Wynika to z tego, że B zostało przesunięte w lewo, tak że najbardziej znaczący dodatni bit w B jest równy jeden. **Oraz zademonstruj działanie na wybranym przez siebie przykładzie.** A=9<sub>10</sub> B=3<sub>10</sub> 9<sub>10</sub>/3<sub>10</sub> 1001<sub>2</sub>/0011<sub>2</sub> | P | A | B | -B | Komentarz| | ----- | ---- | ----- | ---- | --- | | 00000 | 1001 | 00011 | 11101 | Początkowy stan | ||||| 1. B ma 2 bity wiodące w zapisie 4-bitowym, SL(B) o 2 bity | | 00010 | 0100 | 01100 | 10100 | | ||||| 2.a) SL(PA), nowy bit 0 | | 00100 | 100**0** | 01100 | 10100 | | ||||| 2.c) SL(PA), nowy bit 1| | 01001 | 00**01** | 01100 | 10100 | | ||||| 2.c) odejmowanie B od P| | 11101 | 0001 | 01100 | 10100 | | ||||| 2.a) SL(PA), nowy bit 0| | 11010 | 0010 | 01100 | 10100 | | ||||| 2.b) SL(PA), nowy bit $\overline{1}$| | 10100 | $010\overline{1}$ | 01100 | 10100 | | ||||| 2.b) dodawanie B do P| | 00000 | $010\overline{1}$ | 01100 | 10100 | | ||||| 4. Reszta ( P ) jest dodatnia wszystko wynik jest ok | ||||| 5. Bity reszty są przesunięte o 2 bity w prawo | | 00000 | $010\overline{1}$| 01100 | 10100 | | **Jaka motywacja stoi za wprowadzeniem tego algorytmu?** We wcześniejszych implementacjach dzielenia nie pomijamy żadnej operacji dodawania/odejmowania, ale jeżeli iloraz zawiera jakieś bity równe zero, to moglibyśmy odpowiadające tym bitom operacje dodawania/odejmowania pominąć. Stąd algorytm SRT division w podstawowej wersji działa szybciej, od poprzednich