
Wykładowca w Katedrze Zastosowań Systemów Informatycznych. Doktor nauk technicznych w dziedzinie Informatyka (Wojskowa Akademia Techniczna w Warszawie, Wydział Cybernetyki). Absolwent wydziału Elektroniki, Automatyki, Informatyki i Elektrotechniki o specjalności Informatyka w sterowaniu i zarządzaniu (Akademia Górniczo-Hutnicza w Krakowie). Odbył staż doktorski na University of Manitoba w Kanadzie. Jego zainteresowania naukowe koncentrują się wokół: przetwarzania sygnałów w szczególności obrazów, głębokich sieci neuronowych, rozpoznawania mowy.
Jak działa CPU? Wykonywanie instrukcji przez procesor na przykładach
CPU (ang. Central Processing Unit), zwany potocznie procesorem, jest obecnie najczęściej używanym układem do przetwarzania cyfrowego. Dlatego warto zapoznać się z jego tajnikami działania, które pokazują jak bardzo złożona jest jego praca.
Warto pamiętać, że dysponujemy alternatywnymi dla CPU układami służącymi do przetwarzania cyfrowego. Są to m.in.:
– ASIC (ang. Application-Specific Integrated Circuit) układy scalone zaprojektowane do wykonania jednego z góry określonego zadania. Dzięki temu mogą osiągnąć wysoką wydajność, niską cenę (gdy są wytwarzane w dużych ilościach), mały rozmiar, niski pobór energii, co przekłada się na stosunkowo niedużą generację ciepła. Układy te znalazły zastosowanie na przykład do tzw. ‘kopania’ kryptowalut oferując najlepszy stosunek ‘wydobytych’ monet do zużytej energii. Niestety ten przykład pokazuje też ich wady. Ponieważ w chwili zmiany algorytmów ‘koparek’, ich wydajność potrafi całkowicie spaść.
– Programowalne struktury logiczne (PLD) są to układy, które podobnie jak układy ASIC, realizują sprzętowo zadane funkcje. Jednak w odróżnieniu od nich można je przeprogramować, implementując nowe funkcjonalności. Mamy następujące rodzaje układów PLD:
– SPLD (ang. Simple Programmable Logic Device) w tym zawierają się układy PAL (Programmable Array Logic) programowalna matryca AND i stała matryca OR; oraz PLA (Programmable Logic Array) programowalna matryca AND i programowalna matryca OR. Obecnie jest to technologia schyłkowa.
– FPGA (ang. Field Programmable Gate Array) – bezpośrednio programowalna macierz bramek. Układy te mogą być wielokrotnie przeprogramowane po tym, jak zostały już wytworzone, zakupione i zamontowane w urządzeniu docelowym. Aby zdefiniować zachowanie układu FPGA używa się języka opisu sprzętu, takiego jak Verilog czy VHDL. Znajdują zastosowanie w wielu dziedzinach przemysłu, choć ostatnio najwięcej uwagi otrzymały przy okazji sankcji nałożonych na Rosję. Zakazany został ich eksport ze względu na używanie ich w przemyśle wojennym. Ponieważ nie da się w tym przemyśle bez nich obyć, zakaz ten obchodzi się poprzez łańcuszek firm.
CPU
Zasada działania CPU wynika bezpośrednio z architektury komputerowej zaproponowanej przez von Neumann’a w 1945 roku. Jak widzimy nasze współczesne maszyny opierają się na założeniach już osiemdziesięcioletnich. Cóż takiego zaproponował Von Neumann, co stało się podstawą współczesnych maszyn?
Aby maszyna obliczeniowa była uniwersalna, mogła realizować różne zadania zaproponowano, aby algorytmy programów nie realizować sprzętowo za pomocą funkcji logicznych, ale zapisywać je za pomocą prostszych operacji.
Przykładowo dla zadania obliczania średniej dwóch liczb można zaimplementować układ zbudowany z odpowiednich bramek logicznych, który takie obliczenie wykona za jednym zamachem. Jednak można też rozbić je na prostsze podzadania (nazywane też operacjami, instrukcjami), w tym wypadku najpierw dodajemy dwie liczby, potem dzielimy je przez dwa i otrzymujemy średnią.
Dzięki takiemu podejściu można za pomocą zestawu takich prostych operacji zrealizować dowolne zadanie algorytmiczne. Nie musimy z góry narzucać maszynie specjalistycznych funkcji, możemy je budować z tych prostszych operacji.
Takie podejście wymusza konieczność przechowywania tych prostych instrukcji, tym miejscem jest pamięć komputerowa. W pierwszych komputerach takich jak Colosus czy Eniac, była to pamięć w postaci kart perforowanych. Obecnie używamy pamięci półprzewodnikowej.
Rys 1: Eniac – pierwszy komputer. Źródło Wikipedia.
Instrukcje te należało wykonać przez specjalizowany układ nazwany właśnie CPU (ang. Central Processing Unit). Odpowiadał ona za sekwencyjne pobieranie instrukcji z pamięci, interpretowanie je i wykonywanie jako rozkazy.
– Wykonuje on ciąg wspomnianych wcześniej prostych operacji (rozkazów), wybranych ze zbioru operacji podstawowych, określonych zazwyczaj przez producenta procesora jako lista rozkazów procesora.
– Jedną z podstawowych cech procesora jest długość (liczba bitów) słowa, na którym wykonywane są podstawowe operacje obliczeniowe. Jeśli słowo ma 64 bity, mówimy, że procesor jest 64-bitowy.
– Innym ważnym parametrem określającym procesor jest szybkość z jaką wykonuje on rozkazy. Przy danej architekturze procesora, szybkość ta w znacznym stopniu zależy od czasu trwania pojedynczego taktu zegara.
Rys 2: Architektura von Neumann’a. Źródło Wikipedia.
Na powyższym schemacie przedstawiono taką architekturę z zaznaczoną jednostką centralną, która pobiera z pamięci (Memory Unit) instrukcje do wykonania. Za pobieranie i interpretację instrukcji z pamięci zapisanych, przecież nie inaczej jak za pomocą zer i jedynek w pamięci, czy pobieranie argumentów do działań, odpowiada układ kontrolny (Control Unit). Samo wykonanie operacji jest ‘zlecane’ przez układ kontrolny do jednostki arytmetycznej (Arithmetic/Logic Unit). System ten współpracuje za pomocą magistrali komunikacyjnych z urządzeniami wejścia/wyjścia, tu oznaczonych jako Input/Output Device.
Cykl rozkazowy CPU
Wiemy zatem z poprzedniego rozdziału jakie założenia musi spełniać CPU. Przyjrzyjmy się zatem, jak wygląda wspomniane wcześniej ‘wykonanie’ pojedynczej instrukcji zapisanej w pamięci. Okazuje się, że jest to dość powtarzalny proces opisany za pomocą tzw. „cyklu rozkazowego CPU”.
Cykl wykonania rozkazu odbywa się w następujących krokach:
1. Pobranie kodu rozkazu z pamięci programu do rejestru rozkazów.
2. Aktualizacja wskaźnika rozkazu by wskazywał następną instrukcję.
3. Dekodowanie rozkazu.
4. Jeśli trzeba pobiera 16bitowy argument rozkazu z pamięci.
5. Jeśli trzeba to aktualizuje wskaźnika rozkazu by wskazywał za argument.
6. Wykonanie rozkazu. Zapis obliczonej wartości do wskazanego rejestru docelowego.
Przykład
Cykl rozkazowy CPU przedstawimy na przykładzie wykonania instrukcji ADD AX, BX. Jest to jeden z rozkazów CPU, który dodaje dwie wartości AX i BX, a wynik zapisuje do AX. Rozkaz ten przechowywany jest w pamięci. Oczywiście zakodowany za pomocą zer i jedynek. W przypadku procesorów z rodziny Intel x86 ten kod tzw. opcode ma wartość 03h, co binarnie zapiszemy 00000011. Taką wartość znajdzie CPU w pamięci. Jak CPU wie skąd ma pobrać kod rozkazu z pamięci? CPU przechowuje adres komórki pamięci, skąd ma pobrać następny rozkaz do wykonania w specjalnym miejscu, tzw. rejestrze o nazwie wskaźnik rozkazu (ang. Instruction Pointer). Poniżej przedstawiono stan procesora przed wykonaniem takiego przykładowego rozkazu, gdzie w komórce pamięci o adresie 00A0:0B00 znajduje się kod rozkazu ADD:
Krok 1. Odczytanie kodu rozkazu z pamięci
Odczytanie kodu rozkazu z pamięci przez CPU i umieszczenie go w rejestrze rozkazu IR (ang. Instruction Register). Po wykonaniu tego kroku będziemy mieli taki stan CPU:
Widać teraz, że w rejestrze rozkazu IR pojawiła się wartość z pamięci spod adresu 00A0:0B00.
Krok 2. Aktualizacja wskaźnika rozkazu IP
Jest to konieczne, żeby w następnym cyklu rozkazowym można było odczytać kod rozkazu z kolejnej komórki pamięci.
Krok 3. Dekodowanie rozkazu
Na tym etapie CPU posiada w rejestrze IR jedynie kod rozkazu, w naszym przypadku wartość 00000011. Nie wie jeszcze co ten kod oznacza. Dopiero jednostka sterująca procesora oznaczona jako CU (ang. Control Unit) jest w stanie zdekodować go. Jest to konieczne, ponieważ niektóre rozkazy wymagają dostarczenia im wartości argumentów, co wiąże się dla CPU z koniecznością pobrania tych wartości z pamięci. W naszym przykładzie po zdekodowaniu rozkazu CPU wie, że jest to rozkaz ADD AX, BX. Oba argumenty rozkazu znajdują się w rejestrach procesora, przez co nie trzeba ich w tym wypadku pobierać z pamięci.
Można to zilustrować jak na rysunku powyżej.
Krok 6. Wykonanie rozkazu
W naszym wypadku jak wspomniano, nie trzeba było wykonywać kroku 4 i 5 ponieważ argumenty CPU miał już dostępne w swoich rejestrach AX i BX. Można zatem przejść do wykonania rozkazu i zapisu obliczonej wartości do wskazanego rejestru docelowego. U nas to rejestr AX. Ostatecznie otrzymamy taki stan procesora:
Po wykonaniu rozkazu w rejestrze AX pojawiła się zamiast wartości 0003, wartość sumy 0005.
Po tym kroku cykl rozkazowy się powtarza. CPU będzie realizowało odczyt z pamięci następnej wartości spod adresu 00A0:0B01, dekodowało ją i próbowało wykonać.
Podsumowanie
Powyższy przykład wykonania instrukcji pokazuje, jak nasze współczesne komputery domowe, czy telefony realizują programy zapisane w pamięci. Gdzie takowe programy składają się z tysięcy, czasami milionów, prostych instrukcji wykonywanych przez CPU. Widać, że jest to dość skomplikowany proces, pomimo jego uproszczenia w przykładzie. Ale to właśnie taka architektura, dzięki swojej elastyczności i możliwości zapisania dowolnego programu, nawet pomimo nie najlepszej wydajności, stała się dominująca. Konkurencja w postaci wspomnianych układów ASIC, PLD, czy FPGA nadal okupuje swoje nisze, ale to CPU znajdziemy w naszych urządzeniach domowych, pralkach, piekarnikach, kuchenkach, TV, audio, samochodach, kontrolerach, kotłach grzewczych, klimatyzatorach i wielu innych.