Jak efektywnie zaprojektować kod operacji dla procesora?

12

Buduję prosty 16-bitowy procesor w Logisim i mam ALU gotowe i kody operacyjne, które chcę mieć. Teraz naprawdę trudno mi znaleźć odpowiednie kodowanie dla poleceń, tak aby różne obwody (np. Logika, arytmetyka) nie potrzebowały wszystkich przewodów sterujących (które budują kodowanie) jako danych wejściowych, ale jak najmniej. Czy są jakieś strategie lub metody, które pomagają w wydajnym projektowaniu kodu operacyjnego?

dzięki z góry

Benjoyo
źródło
1
Najpierw zbuduj ALU i sprawdź, jakich przewodów sterujących potrzebuje. Następnie podłącz je bezpośrednio do rejestru „bieżąca instrukcja”. To samo dotyczy logiki kontroli dostępu do pamięci i wszystkich innych głównych klas kodów. Następnie użyj resztek bitów, aby wybrać, który obwód jest aktywowany.
user253751
1
Jest też oryginalny artykuł Kena Chapmana z jego 8-bitowego programowalnego statemachine KCPSM aka PicoBlaze. Opisuje, jak wybrał instrukcje i zaprojektował ISA. dc.uba.ar/materias/disfpga/2010/c2/descargas/…
Paebbels

Odpowiedzi:

9

Myślę, że dobrym podejściem jest studiowanie innych zestawów instrukcji.

Mały byłby MSP430 od TI, jest to 16-bitowy procesor z około 22 instrukcjami.

http://www.physics.mcmaster.ca/phys3b06/MSP430/MSP430_Instruction_Set_Summary.pdf

Możesz także zajrzeć do AVR-ów Atmela, które mają również dość mały zestaw instrukcji.

W moim małym projekcie próbowałem opracować prosty 32-bitowy procesor w VHDL z małym zestawem instrukcji (14 instrukcji):

http://www.blog-tm.de/?p=80

Ze względu na mój obecny wolny czas nie jest w pełni ukończony. Instrukcje są zaimplementowane, ale dwie nie są testowane i być może brakuje niektórych flag stanu.

TM90
źródło
Ale nie znalazłem czegoś, gdzie mógłbym zobaczyć, jakie jest rzeczywiste kodowanie i dlaczego wybrano go w ten sposób.
Benjoyo
Możesz znaleźć kodowanie aktualne w repozytorium: github.com/TM90/MISC_Processor/raw/master/Documentation/… . Powód, dla którego wybrałem te kodowania w taki sposób, że logika w dekoderze instrukcji stała się minimalna.
TM90
7

Zbadaj (ale nie powielaj) podejście ARM do kodowania instrukcji. Jest mocno zorientowany na prefiks (jak podejście drzewa Huffmana zalecane przez Dzardę) i bardzo jednolity pod względem tego, gdzie rejestr wybiera część instrukcji.

Niewyobrażalne, ale niezawodne podejście polega na wyliczeniu wszystkich posiadanych sygnałów sterujących , które prawdopodobnie będą miały więcej niż 16 bitów, a następnie próbie zminimalizowania na nich logiki typu Karnaugh.

pjc50
źródło
Tak naprawdę nie rozumiem sygnałów kontrolnych.
Benjoyo
To, co znalazłem i lubię w ARM, to pole warunku, uwzględnię to.
Benjoyo
Sygnały sterujące są wejściami do różnych multiplekserów i umożliwiają bezpośrednie przesyłanie danych między częściami procesora.
pjc50
W przypadku architektury 16-bitowej nie sądzę, aby kodowanie instrukcji ARM było odpowiednie. Mayby thumb2 jest lepszy. Ale podoba mi się sposób kodowania MIPS, prosty i łatwy do zrozumienia, choć trochę marnotrawny
phuclv
4

Kiedyś próbowałem zrobić 4-bitowy procesor z rdzeniem instrukcji o długości 8 bitów w Logisim. Skończyło się na prostej maszynie stanów, więcej niż procesorze, naprawdę.

Losowe rzeczy do poszukiwania

  • Drzewa Huffmana
  • Kodowanie o stałej długości czy zmiennej?
  • Czy jest to projekt von Neumanna z pojedynczą przestrzenią adresową, czy styl Harvarda z osobnymi danymi / programem?

Doskonałe wideo na Computerphile o drzewach Huffmana:

https://www.youtube.com/watch?v=umTbivyJoiI

Dzarda
źródło
Kodowanie Huffmana nie zadziała w przypadku kodowania o stałej długości, prawda?
Benjoyo
@Benjoyo Mogę sobie wyobrazić scenariusz z zapasowymi bitami używanymi do odmian najczęściej używanych instrukcji, zapewniając w ten sposób większą funkcjonalność.
Dzarda
Ale nie rozumiem, jaki rodzaj optymalizacji to przynosi. Nie pomaga mi to w projektowaniu obwodów. Jaki jest cel korzystania z kodowania Huffmana dla opcode?
Benjoyo
4

ISA, który napisałem dla klasy, miał kiedyś 4-bitowy kod operacyjny: 1XXX ALU instructions 01XX jump, jump register, call etc 001X branch not equal, branch equal zero 000X 0 - load, 1 - store

Zamiast być najbardziej optymalnym, jest to jeden z łatwiejszych stylów do konstruowania / projektowania bramek, ponieważ sygnał wejściowy pojedynczego bitu może całkowicie kontrolować ścieżkę logiczną. Alternatywnie możesz Huffman Code najczęściej używanych symboli i zerować je, aby uzyskać kod operacji o stałej długości.


źródło
Tego rodzaju optymalizacja jest obecnie tym, czego szukam. Ale mam 5-bitowy kod operacyjny i mam problem z grupowaniem poleceń, aby miało to sens w obwodzie.
Benjoyo
@Benjoyo, możesz mieć więcej instrukcji ALU z górnym zestawem bitów. Również mój zasięg warunków skoku był dość słaby i większość normalnych gałęzi wymagałaby dwóch instrukcji. Ogólnie pomyślałem o kategoriach: Matematyka / Sterowanie / Pamięć
3

Jedną rzeczą, którą musisz wziąć pod uwagę, jest to, czy możesz zezwolić na jakąkolwiek formę instrukcji składającej się z wielu słów lub na coś, co może „działać” jak instrukcja zawierająca wiele słów; jeśli to zrobisz, możesz rozważyć, czy użyć dodatkowych słów instrukcji po głównej instrukcji, czy też poprzedzających ją słów. Zezwalanie na prefiksy i słowa następcze może zwiększyć złożoność obsługi przerwań, ale można uniknąć konieczności umieszczania rzadko używanych instrukcji w tej samej przestrzeni opcode, co często używane.

Jeśli instrukcje są pobierane w cyklu przed ich wykonaniem, można mieć instrukcję „gałęzi warunkowej”, która albo powoduje pominięcie następnego słowa instrukcji, albo przekazanie jej zawartości bezpośrednio do licznika programu; taki projekt może dodać dodatkową złożoność do przerywania sekwencjonowania, ale może złagodzić potrzebę użycia dużej części przestrzeni kodu operacyjnego dla instrukcji „rozgałęzienia”, „skoku” i „wywołania”, jednocześnie umożliwiając znacznie szerszy zakres warunków rozgałęzienia niż byłoby to możliwe. Ponieważ brana gałąź będzie na ogół wymagać martwego cyklu po wykonaniu samej instrukcji bez względu na to, skąd pochodzi adres, posiadanie adresu z następującego słowa, które zostało pobrane, ale nie zostanie wykonane, nie kosztuje dodatkowych kosztów czas.

Mimo że przeniesienie adresu docelowego poza instrukcje oddziału zmniejszy ilość zajętego miejsca w kodzie operacyjnym, 16-bitowy format kodu jest nadal dość napięty. Korzystanie z instrukcji prefiksu może w tym pomóc. Jeśli, na przykład, chcemy mieć 32 rejestry, pozwalając, aby każdy rejestr był niezależnie określony jako source1, source2 i miejsce docelowe wymagałyby 15 bitów w kodzie operacyjnym, pozwalając na uzyskanie łącznie dwóch instrukcji. Niezbyt przydatne. Z drugiej strony byłoby fajnie móc użyć dowolnego z 32 rejestrów dla każdego z trzech operandów. Można zrównoważyć te dwa cele, wykonując dowolną operację ALU, która nie jest poprzedzona przedrostkiem, używając ośmiu bitów, aby dokonać dwóch wyborów jednego z szesnastu rejestrów, ale operacja ALU, która następuje bezpośrednio po przedrostku, wykorzystuje niektóre bity w prefiksie wzdłuż z ośmioma z następującej instrukcji, aby umożliwić niezależny wybór obu źródeł i miejsca docelowego z pełnego zestawu 32. Instrukcje, które używają górnych rejestrów, zajęłyby dwa słowa / cykle zamiast jednego, ale w niektórych przypadkach taki kompromis może być opłacalny. Największą trudnością związaną z używaniem prefiksów jest to, że należy albo zapobiec wystąpieniu przerwania między prefiksem a następną instrukcją, albo też upewnić się, że jeśli wystąpi tam przerwanie, instrukcja po prefiksie będzie nadal korzystać z odpowiednich rejestrów [np. Poprzez uruchomienie programu -counter save logic zapisz adres ostatniej wykonanej instrukcji nieprefiksowej]. ale w niektórych przypadkach taki kompromis może być opłacalny. Największą trudnością związaną z używaniem prefiksów jest to, że należy albo zapobiec wystąpieniu przerwania między prefiksem a następną instrukcją, albo też upewnić się, że jeśli wystąpi tam przerwanie, instrukcja po prefiksie będzie nadal korzystać z odpowiednich rejestrów [np. Poprzez uruchomienie programu -counter save logic zapisz adres ostatniej wykonanej instrukcji nieprefiksowej]. ale w niektórych przypadkach taki kompromis może być opłacalny. Największą trudnością związaną z używaniem prefiksów jest to, że należy albo zapobiec wystąpieniu przerwania między prefiksem a następną instrukcją, albo też upewnić się, że jeśli wystąpi tam przerwanie, instrukcja po prefiksie będzie nadal korzystać z odpowiednich rejestrów [np. Poprzez uruchomienie programu -counter save logic zapisz adres ostatniej wykonanej instrukcji nieprefiksowej].

Korzystanie z instrukcji zawierających wiele słów utrudni niektóre aspekty projektu, ale może zmniejszyć potrzebę podejmowania innych trudnych decyzji.

supercat
źródło
0

Ten facet ma najlepsze szczegóły na temat rozumienia twardego okablowania zakodowanej części dekodera, która wyjaśnia linie sterujące dla zakodowanego procesora: http://minnie.tuhs.org/CompArch/Tutes/week03.html Jak widać, twój wybór w Opcodes naprawdę wpływa na złożoność logiki dekodowania.

cmacdona101
źródło