Codici operativi ISA --- Da dove vengono?


13

Quando gli ingegneri progettano un'architettura di set di istruzioni, secondo quale procedura o protocollo, se ne verificano, seguono quando designano determinati codici binari come istruzioni. Ad esempio, se ho un ISA che dice 10110 è un'istruzione di caricamento, da dove proviene quel numero binario? È stato modellato da una tabella di stato per una macchina a stati finiti che rappresenta un'operazione di caricamento?

Modifica: dopo aver fatto ulteriori ricerche, credo che ciò che sto cercando di chiedere riguardi come vengono assegnati gli opcode per le varie istruzioni della CPU. ADD potrebbe essere designato con un codice operativo di 10011; un'istruzione di caricamento potrebbe essere designata come 10110. Quale processo di pensiero passa nell'assegnazione di questi codici binari per il set di istruzioni?


8
Il "Microprocessor Design Using Verilog HDL" di Monte Dalrymple fornisce un approccio di progettazione molto dettagliato per la CPU Z80 e da esso penso che impareresti molto sulla tua domanda. Ma ci sono molte considerazioni che vanno in una scelta specifica, compresa l'analisi statistica di altri set di istruzioni, output del compilatore, ecc. Consiglio comunque di iniziare con quel libro. Anche se inizia con un design noto, ne approfondisce i dettagli e penso che raccoglieresti alcune cose. Buon libro.
Jon

O, forse, ti stai chiedendo del design del motore di esecuzione e ti stai chiedendo come potrebbero giocare i bit dell'istruzione? Non sono sicuro delle tue parole.
Jon

2
Qualcun altro pone questa domanda. Deve essere martedì
Ignacio Vazquez-Abrams,

5
@Steven Pensaci. Se si dovesse progettare un ISA, che cosa si pensare? Se le tue istruzioni non erano tutti della stessa lunghezza, come sarebbe si sceglie parole di istruzione più o meno lunghi, per i quali le istruzioni? Se è stato necessario progettare una fase di decodifica , che cosa desiderare per il vostro ISA per assomigliare? Penso che la domanda sia inutilmente ampia (e quindi, quasi impossibile rispondere completamente), ma puoi migliorarla molto mettendo un po 'più di pensiero in te e ponendo una domanda precisa che non ci richiederebbe di scrivere un libro per rispondere esso.
Marcus Müller,

4
Le specifiche RISC-V parlano delle decisioni di progettazione che hanno preso a tutti i livelli, incluso un bel po 'della codifica delle istruzioni della macchina. (Ciò è insolito per un manuale del processore; RISC-V è un esercizio accademico prima e un'architettura CPU secondo, a differenza della maggior parte.)
zwol,

Risposte:


6

In molti casi, la scelta è piuttosto arbitraria o basata su "ovunque si adatti meglio" man mano che gli ISA crescono nel tempo. Tuttavia, il MOS 6502 è un meraviglioso esempio di chip in cui il design ISA è stato fortemente influenzato dal tentativo di spremere il più possibile da transistor limitati.

Guarda questo video che spiega come il 6502 è stato progettato al contrario , in particolare da 34:20 in poi.

Il 6502 è un microprocessore a 8 bit introdotto nel 1975. Sebbene avesse il 60% di porte in meno rispetto allo Z80, era due volte più veloce e sebbene fosse più vincolato (in termini di registri, ecc.), Compensò quello con un set di istruzioni elegante.

Contiene solo 3510 transistor, che sono stati disegnati a mano da una piccola squadra di persone che strisciava su alcuni grandi fogli di plastica che successivamente sono stati ridotti otticamente, formando i vari strati del 6502.

Come puoi vedere di seguito, il 6502 passa il codice operativo dell'istruzione e i dati di temporizzazione nella ROM di decodifica, quindi li passa in un componente "logica di controllo casuale" il cui scopo è probabilmente quello di sovrascrivere l'output della ROM in determinate situazioni complesse.

6502 schema a blocchi

Alle 37:00 nel video puoi vedere una tabella della ROM di decodifica che mostra quali condizioni devono soddisfare gli ingressi per ottenere un "1" per un dato output di controllo. Puoi trovarlo anche su questa pagina .

Puoi vedere che la maggior parte delle cose in questa tabella ha X in varie posizioni. Prendiamo ad esempio

011XXXXX 2 X RORRORA

Ciò significa che i primi 3 bit del codice operativo devono essere 011 e G deve essere 2; Non importa nient'altro. In tal caso, l'uscita denominata RORRORA diventerà vera. Tutti i codici operativi ROR iniziano con 011; ma ci sono altre istruzioni che iniziano anche con 011. Questi probabilmente devono essere filtrati dall'unità "random control logic".

Quindi, in sostanza, sono stati scelti gli opcode in modo che le istruzioni che dovevano fare la stessa cosa l'una con l'altra avessero qualcosa in comune attraverso il loro modello di bit. Puoi vederlo guardando una tabella di codici operativi ; tutte le istruzioni OR iniziano con 000, tutte le istruzioni Store iniziano con 010, tutte le istruzioni che utilizzano l'indirizzamento a pagina zero sono nel formato xxxx01xx. Naturalmente, alcune istruzioni non sembrano "adattarsi", perché l'obiettivo non è di avere un formato di codice operativo completamente regolare, ma piuttosto di fornire un potente set di istruzioni. Ed è per questo che era necessaria la "logica di controllo casuale".

La pagina che ho menzionato sopra dice che alcune delle linee di output nella ROM appaiono due volte: "Supponiamo che questo sia stato fatto perché non avevano modo di instradare l'output di una linea dove volevano, quindi hanno messo la stessa linea in un altro posizione di nuovo ". Posso solo immaginare gli ingegneri che disegnano a mano quei cancelli uno per uno e improvvisamente realizzano un difetto nel design e provano a trovare un modo per evitare di riavviare l'intero processo.


22

Dipende da quanti anni ha l'ISA.

All'inizio della progettazione manuale, e ancora di più quando le CPU erano assemblate da una logica discreta, la progettazione logica sarebbe venuta prima, e sarebbe stata ampiamente minimizzata, e quindi i pattern di bit ISA sarebbero stati tutti i valori necessari per rendere quel minimo lavoro logico.

Quindi potrebbe esserci un particolare schema di segnali di controllo che consente ad alcuni multiplexer di collegare l'uscita ALU all'input del file di registro GP, alcuni segnali di controllo in più che indicano all'ALU di aggiungere, sottrarre, AND, OR ecc. E alcuni indirizzare i bit nel file di registro. Questi tre gruppi di segnali formeranno campi all'interno dell'istruzione. Ogni gruppo verrà tenuto insieme e il loro significato dettagliato deriva dal progetto per quell'unità (ALU ecc.) Ma i gruppi possono essere in qualsiasi ordine, fino a quando non si progetta il decodificatore delle istruzioni. (x86 è abbastanza vecchio da poterne rilevare un po 'se guardi nel posto giusto - non era un design totalmente nuovo, ma attingeva al vecchio 8080)

Gli ISA successivi possono essere "ripuliti" e resi più regolari e più semplici da utilizzare, con l'hardware da tradurre tra loro e i segnali di controllo a livello hardware effettivo, a volte tramite "microcodice". Questi sono chiamati "CISC" o "Codifica set di istruzioni complesse". Il prefisso dell'istruzione "Rep" x86 ne è un semplice esempio: fa sì che le seguenti istruzioni vengano ripetute più volte, per evitare di dover scrivere un ciclo FOR.

Più tardi (negli anni '80) tornò a un semplice stile di codifica diretta (RISC - Reduced Instruction Set Coding) che puoi vedere nei processori ARM. Ciò era guidato dalle dimensioni ridotte degli ASIC all'epoca e dal desiderio di mettere CPU a 32 bit su di essi, quindi non c'era spazio libero per decodificatori complessi di istruzioni, per portare la CPU completa a circa 20.000 gate. (C'è stato anche un aumento temporaneo delle prestazioni, perché le persone non avevano ancora sviluppato tecniche per rendere veloci i decodificatori CISC - questo è accaduto nel 1995 con il Pentium Pro)

E al giorno d'oggi non importa: le CPU leggono più istruzioni contemporaneamente e dedicano milioni di transistor a decodificarle, riordinarle ed eseguirne il più possibile contemporaneamente, per accelerare i programmi che potrebbero essere stati scritti per i più vecchi stile di ISA.


2
Non sono sicuro che definirei CISC "più facile da usare". Potrebbe essere stata questa l'intenzione originale, ma 30 anni dopo sono un po 'l'antitesi del "facile da usare" (rispetto almeno agli ISA RISC).
tonysdg,

2
Ci sono aspetti in cui erano più facili da usare ... o la regolarità (l'ortogonalità era un argomento importante) quando i compilatori erano programmi relativamente banali, o attraverso il supporto diretto di operazioni di livello superiore, che richiedevano meno traduzioni dal compilatore. Ma è stato TANTO tempo fa e ogni CISC sopravvissuto ha così tanti strati di revisioni in aggiunta al suo set di istruzioni originale. Anche i compilatori sono cambiati da ogni riconoscimento: i mille passaggi di ottimizzazione eseguiti da gcc sarebbero stati impensabili allora. Quindi, ciò che è stato "facile" allora e ora ha pochissime relazioni.
Brian Drummond,

4
La distinzione è stata sia erosa (insiemi "RISC" che aggiungono ulteriori istruzioni) e superata da nuove architetture ancora più complesse come VLIW; davvero l'unico consenso è che x86 (16 e 32 bit) è difficile da usare
pjc50

1
@tonysdg: ci sono RISC difficili da usare e CISC difficili da usare. Un buon confronto tra "facilità di programmazione" è quello di confrontare 68k contro ARM. ARM è stato progettato per un compilatore, pertanto è stato necessario eseguire molte operazioni manuali per ottenere dati dalla RAM e riscriverli nella RAM. Il 68k è stato progettato per programmatori di assemblaggio e consente di operare direttamente sui dati nella RAM. Se guardi 68k ISA scoprirai che assomiglia molto al moderno RISC ISA con un'eccezione: puoi operare direttamente su RAM mentre RISC ti consente solo di operare sui registri.
Slebetman,

1
Il microcodice è principalmente un attributo CISC. Tuttavia, è possibile implementare CISC senza microcodice: il decodificatore delle istruzioni sarebbe più complicato. Vedrai anche alcuni CISC dal Pentium-Pro in poi descritti come RISC internamente; tradurre ciascuna istruzione CISC in una o più operazioni RISC interne: un altro nome per microcodice (anche se le distinzioni si confondono in unità di esecuzione superscalare)
Brian Drummond,

9

Se si raggruppano istruzioni simili, emergeranno dei motivi. Questo è molto ovvio in ARM, dove il manuale ISA mostra effettivamente quale bit di una parola di istruzione corrisponde alla funzione, alla scelta del registro, ecc. Ma può anche essere dedotto per X86 .

Alla fine, la parte "funzione" degli opcode arriva in un decodificatore binario a uno che attiva effettivamente una particolare funzione o sequenza di operazioni pipeline. Di solito non sono correlati al contenuto di nessuna macchina a stati, a meno che non stiamo prendendo in considerazione istruzioni a lunghezza variabile che richiedono una macchina a stati per decodificare.


In pratica stai dicendo che stanno cercando il conteggio dei transistor più basso possibile sul chip. Sono totalmente d'accordo nel contesto della domanda di OP, in cui non possono permettersi centinaia di transistor extra per un set di istruzioni più ordinato. Le CPU a milione transistor non hanno quasi altrettanto motivo di preoccuparsene, ma ovviamente molti lo trattengono per compatibilità con le versioni precedenti.
Harper - Ripristina Monica il

@Harper C'è ancora motivo, perché mentre i transistor diventano più piccoli, hanno ancora una dimensione - e le frequenze di clock sono aumentate molto nel frattempo. Quindi un decodificatore di istruzioni troppo grande può ancora essere un collo di bottiglia per le prestazioni (uno dei motivi per cui molte CPU hanno optato per le istruzioni di pre- decodifica, in anticipo). Non si tratta (solo) del conteggio dei transistor, ma di più sulla frequenza di clock in combinazione con l'area del die. L'informazione impiega ancora tempo a propagarsi e, sebbene le moderne CPU non funzionino alla velocità della luce, non sono abbastanza lontane dal limite di velocità per aspettarsi miglioramenti significativi.
Luaan,

@Luaan: In realtà, "cosa facciamo con tutti questi transistor" è una vera domanda al giorno d'oggi. Guarda tutte le cache L2 / L3 lanciate al giorno d'oggi. Questa è un'ammissione silenziosa che non abbiamo un uso migliore per tutti quei milioni di transistor. Gli ultimi Xeon dedicano oltre 2 miliardi di transistor alla cache!
Salmi,

6

Qualcuno ad un certo punto si è seduto e li ha definiti.

Un buon ISA renderà il decoder il più semplice possibile.

Ad esempio con un'istruzione ALU è possibile inviare alcuni bit del codice operativo direttamente nelle linee di controllo dell'ALU.


Grazie a tutti per le risposte eccellenti. Mi avete aiutato tutti a capirlo molto meglio.
Steven,

4
In realtà ci sono alcuni fattori diversi dalla semplicità del decodificatore da tenere in considerazione. A seconda delle circostanze e dell'uso previsto, altri (ad es. Densità di codice) possono essere più importanti della semplicità del decodificatore. In un moderno processore, la densità del codice probabilmente supera la semplicità del decodificatore nella maggior parte dei casi.
Jerry Coffin,

5

In genere, si divide l'ISA in gruppi funzionali. Ha senso (o per l'ottimizzazione della logica o semplicemente per essere in ordine) che le coppie complementari sono differenziate da un singolo cambio di bit (carico vs archivio) e che si dispone di una gerarchia di bit che influisce sull'albero decisionale della decodifica.

Alla fine della giornata, un'allocazione arbitraria di bit per il blocco funzione (invece di posizionare i campi "dati" nell'istruzione avrà solo un piccolo impatto sull'efficienza complessiva del progetto - ma hai molte scelte su come 'ottimizza' la tua codifica ISA in base a ciò che ritieni sia un parametro importante.


1

La codifica delle istruzioni è un brutto compromesso tra.

Semplificando la decodifica, per questo si desidera un semplice insieme di campi ciascuno dei quali può essere decodificato separatamente e instradato verso una parte separata del motore di esecuzione.

Comprimendo quante più funzionalità possibile in una dimensione limitata della parola dell'istruzione. Questo porta a cose come formati costanti speciali che possono codificare una varietà di numeri comuni.

Compatibilità avanti e indietro. Se si assegna la funzionalità a ogni possibile codice operativo non si dà spazio per espandere l'architettura in un secondo momento. Se si sta aggiungendo un'architettura esistente, è necessario inserire le nuove istruzioni nei codici operativi di riserva.


1

L'eccellente (se un po 'datato) di Randy Hyde The Art of Assembly si trova nel set di istruzioni x86 in dettaglio nel capitolo 3.3.4 Unità di controllo e set di istruzioni e seguenti.

I programmi nei primi sistemi informatici (pre-Von Neumann) erano spesso "cablati" nei circuiti. Cioè, il cablaggio del computer ha determinato quale problema avrebbe risolto il computer. Uno ha dovuto ricablare i circuiti per cambiare il programma. Un compito molto difficile. Il successivo progresso nella progettazione del computer fu il sistema programmabile, che permise a un programmatore di computer di "ricablare" facilmente il sistema utilizzando una sequenza di prese e cavi. Un programma per computer consisteva in una serie di file di fori (prese), ciascuna delle quali rappresentava un'operazione durante l'esecuzione del programma. Il programmatore può selezionare una delle numerose istruzioni inserendo un filo nella presa specifica per l'istruzione desiderata.

Dimostra quindi abbastanza accattivante e alla lunga come la prima coppia di prese rappresenta l'istruzione, le prese successive codificano sorgente e destinazione. Naturalmente, oggi nessuno "si collega" più, ma per gli ISA veramente vecchi, i bit nell'opcode fanno sostanzialmente lo stesso lavoro dei plugs precedenti.

Si finisce con qualcosa del genere:

inserisci qui la descrizione dell'immagine


Grazie per il link da Hyde! È molto istruttivo e sembra avere un eccellente stile di insegnamento.
Steven,
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.