Come progettare in modo efficiente il codice operativo per una CPU?


12

Sto costruendo una semplice CPU a 16 bit in Logisim e ho l'ALU pronto e gli opcode che desidero avere. Ora trovo davvero difficile trovare la giusta codifica per i comandi in modo che i diversi sottocircuiti (ad es. Logica, aritmetica) non abbiano bisogno di tutti i fili di controllo (che costruiscono la codifica) come input, ma il meno possibile. Ci sono strategie o metodi che aiutano con una progettazione efficiente del codice operativo?

grazie in anticipo


1
Costruisci prima il tuo ALU e vedi di quali fili di controllo ha bisogno. Quindi collegarli direttamente al registro "istruzioni correnti". Lo stesso vale per la logica di controllo dell'accesso alla memoria e per tutte le altre principali classi di codici operativi. Quindi utilizzare qualsiasi bit rimasto per selezionare quale sottocircuito è attivato.
user253751

1
C'è anche il documento originale di Ken Chapman del suo programmatore a stato a 8 bit KCPSM aka PicoBlaze. Descrive come ha scelto le istruzioni e progettato l'ISA. dc.uba.ar/materias/disfpga/2010/c2/descargas/…
Paebbels

Risposte:


9

Penso che sia un buon approccio studiare alcuni altri set di istruzioni.

Un piccolo sarebbe MSP430 di TI, è un processore a 16 bit con circa 22 istruzioni.

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

Potresti anche esaminare gli AVR Atmel che hanno anche un set di istruzioni piuttosto piccolo.

In un mio piccolo progetto ho cercato di sviluppare un semplice processore a 32 bit in VHDL con un piccolo set di istruzioni (14 istruzioni):

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

A causa del mio tempo libero attuale non è completamente finito. Le istruzioni sono implementate ma due non sono state testate e forse mancano alcuni flag di stato.


Ma non ho trovato qualcosa in cui poter vedere quale sia la codifica effettiva e perché sia ​​stata scelta per essere così.
Benjoyo,

È possibile trovare la codifica di attuall nel repository: github.com/TM90/MISC_Processor/raw/master/Documentation/… . Il motivo per cui ho scelto queste codifiche in modo tale che la logica nel decodificatore delle istruzioni sia diventata minima.
TM90,

7

Studia (ma non replicare) l'approccio ARM alla codifica delle istruzioni. È fortemente orientato ai prefissi (come l'approccio ad albero di Huffman raccomandato da Dzarda) e altamente uniforme in termini di dove il registro seleziona parte dell'istruzione.

L'approccio privo di fantasia ma affidabile è quello di enumerare tutti i segnali di controllo che hai, che probabilmente saranno più di 16 bit, e quindi tentare di minimizzare la logica in stile Karnaugh-map su di essi.


Non capisco cosa intendi per segnali di controllo.
Benjoyo,

Quello che ho trovato e che mi piace di ARM è il campo condizione, lo includerò.
Benjoyo,

I segnali di controllo sono gli ingressi ai vari multiplexer e consentono di dirigere i dati tra le parti della CPU.
pjc50,

Per un'architettura a 16 bit, non penso che la codifica delle istruzioni di ARM sia appropriata. Mayby thumb2 è meglio. Ma mi piace il modo di codifica MIPS, semplice e facile da capire, anche se un po 'dispendioso
phuclv,

4

Una volta ho provato a fare una CPU a 4 bit con core di lunghezza istruzioni a 8 bit in Logisim. Finì con una semplice macchina a stati, più che una CPU, davvero.

Cose casuali da cercare

  • Alberi di Huffman
  • Codifica a lunghezza fissa o variabile?
  • È un progetto von Neumann con spazio indirizzo singolo o stile Harvard con dati / programma separati?

Eccellente video su Computerphile sugli alberi di Huffman:

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


La codifica Huffman non funzionerà per una codifica a lunghezza fissa, giusto?
Benjoyo,

@Benjoyo Posso immaginare uno scenario con i pezzi di ricambio utilizzati per le variazioni delle istruzioni più utilizzate, fornendo così più funzionalità.
Dzarda,

Ma non capisco che tipo di ottimizzazione porti a questo. Non mi aiuta con la progettazione del circuito. Qual è l'obiettivo quando si utilizza la codifica Huffman per opcode?
Benjoyo,

4

L'ISA che ho scritto per la classe una volta aveva un codice operativo a 4 bit in questo modo: 1XXX ALU instructions 01XX jump, jump register, call etc 001X branch not equal, branch equal zero 000X 0 - load, 1 - store

Piuttosto che essere il più ottimale, questo è uno degli stili più facili per costruire / progettare gate perché il segnale di input di un singolo bit può controllare interamente quale percorso logico viene intrapreso. In alternativa, puoi Huffman Code i simboli più utilizzati e azzerarli per ottenere un codice operativo a lunghezza fissa.


Questo tipo di ottimizzazione è quello che sto cercando al momento. Ma ho un opcode a 5 bit e faccio fatica a raggruppare i comandi in modo che abbia senso nel circuito.
Benjoyo,

@Benjoyo potresti avere molte più istruzioni ALU con il bit superiore impostato. Anche la copertura delle mie condizioni di salto era piuttosto debole e la maggior parte dei rami normali avrebbe richiesto due istruzioni. In generale, ho pensato alle categorie come: Matematica / Controllo / Memoria

3

Una cosa che devi considerare è se consentire qualsiasi forma di istruzione multi-parola o qualsiasi cosa che possa "agire" come un'istruzione multi-parola; in tal caso, è possibile prendere in considerazione l'opportunità di utilizzare parole di istruzione aggiuntive seguendo le istruzioni principali o le parole prefisso prima di essa. Consentire prefissi e parole di follow-on può aumentare la complessità della gestione degli interrupt, ma può evitare la necessità di adattare le istruzioni usate raramente nello stesso spazio di codice operativo di quelle comunemente usate.

Se le istruzioni vengono recuperate sul ciclo prima che vengano eseguite, si potrebbe avere un'istruzione "ramo condizionale" che fa saltare la parola dell'istruzione successiva o che il suo contenuto viene trasferito direttamente nel contatore del programma; un tale progetto potrebbe aggiungere ulteriore complessità per interrompere il sequenziamento, ma potrebbe facilitare la necessità di utilizzare una grande porzione dello spazio del codice operativo per le istruzioni "branch", "jump" e "call", consentendo nel contempo una gamma molto più ampia di condizioni di branch di quanto sarebbe altrimenti possibile. Dal momento che una succursale che viene presa richiederà generalmente un ciclo morto dopo l'esecuzione dell'istruzione stessa indipendentemente da dove provenga l'indirizzo, avere l'indirizzo proviene dalla seguente parola che è stata recuperata ma che non verrà eseguita non costa alcun extra tempo.

Anche se lo spostamento dell'indirizzo di destinazione dalle istruzioni di filiale riduce la quantità di spazio del codice operativo che inghiottono, un formato del codice operativo a 16 bit è ancora piuttosto limitato. L'uso delle istruzioni del prefisso può essere d'aiuto. Se, ad esempio, si desidera avere 32 registri, consentendo a qualsiasi registro di essere specificato in modo indipendente come source1, source2 e destination richiederebbe 15 bit nel codice operativo, consentendo un totale enorme di due istruzioni. Non molto utile D'altra parte, essere in grado di usare uno dei 32 registri per ciascuno dei tre operandi sarebbe bello. Si potrebbero bilanciare i due obiettivi facendo in modo che qualsiasi operazione ALU che non sia preceduta da un prefisso utilizzi otto bit per effettuare due selezioni di registri uno su sedici, ma che abbia un'operazione ALU che segue immediatamente un prefisso usa alcuni bit nel prefisso lungo con otto delle seguenti istruzioni, in modo da consentire la selezione indipendente di entrambe le fonti e la destinazione dall'insieme completo di 32. Le istruzioni che utilizzano i registri superiori richiederebbero due parole / cicli anziché uno, ma in alcuni casi un tale compromesso potrebbe valere la pena. La maggiore difficoltà nell'uso dei prefissi è che si deve impedire che si verifichi un interruzione tra un prefisso e l'istruzione successiva oppure assicurarsi che se si verifica un interruzione lì l'istruzione dopo il prefisso continuerà a utilizzare i registri corretti [ad esempio, avendo il programma -counter save logic memorizza l'indirizzo dell'ultima istruzione non prefisso eseguita]. ma in alcuni casi un tale compromesso potrebbe valere la pena. La maggiore difficoltà nell'uso dei prefissi è che si deve impedire che si verifichi un interruzione tra un prefisso e l'istruzione successiva oppure assicurarsi che se si verifica un interruzione lì l'istruzione dopo il prefisso continuerà a utilizzare i registri corretti [ad esempio, avendo il programma -counter save logic memorizza l'indirizzo dell'ultima istruzione non prefisso eseguita]. ma in alcuni casi un tale compromesso potrebbe valere la pena. La maggiore difficoltà nell'uso dei prefissi è che si deve impedire che si verifichi un interruzione tra un prefisso e l'istruzione successiva oppure assicurarsi che se si verifica un interruzione lì l'istruzione dopo il prefisso continuerà a utilizzare i registri corretti [ad esempio, avendo il programma -counter save logic memorizza l'indirizzo dell'ultima istruzione non prefisso eseguita].

L'uso di istruzioni di più parole renderà più difficili alcuni aspetti del progetto, ma potrebbe ridurre la necessità di prendere altre decisioni difficili.


0

Questo ragazzo ha i migliori dettagli sulla comprensione del cablaggio fisso della parte hardcoded di un decoder, che spiega le linee di controllo per una CPU hardcoded: http://minnie.tuhs.org/CompArch/Tutes/week03.html Come puoi vedere, il tuo la scelta in Opcodes influisce davvero sulla complessità della logica di decodifica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.