Come funziona il chip di un computer? Come facciamo ad avere tutte quelle informazioni compattate su quel chip sempre più piccolo?

Un moderno microprocessore è un'entità tremendamente complicata, e ci sono voluti decenni di lavoro di migliaia di persone per arrivare al punto in cui si trova ora. È quasi impossibile coprire tutte le basi qui, ma farò un tentativo. Tenete pronto un secchio di popcorn, perché questo sarà lungo.

Ogni sistema moderno funziona sulla base di buone astrazioni, cioè moduli più semplici su cui vengono costruite cose più complesse. Secondo me, il processore moderno può essere suddiviso nei seguenti livelli molto ampi:

  1. Dispositivi (transistor)
  2. Circuiti
  3. Gate logiche
  4. Block logici semplici
  5. Processore
  6. Software

Per cominciare, partiamo da una "terra di mezzo", che non è né troppo complicata da capire né troppo lontana da un processore vero e proprio: la porta logica. Una porta logica prende un certo numero di ingressi, che sono tutti 0 o 1, e produce un bit che è di nuovo 0 o 1 secondo qualche regola. Per esempio, una porta AND produrrà 1 solo se tutti i suoi ingressi sono 1.

main-qimg-c9a369fca29afb0b1946d82199f12920.webp

Potreste ora iniziare a chiedermi "Ma cosa intendi per 0 e 1? Cosa significa in termini di elettricità?". La risposta è fantasticamente complicata. Può significare un livello di tensione (0 è 0V, 1 è 1V), un impulso elettrico (0 è nessun impulso, 1 è un impulso di 1V per 1 nanosecondo, un miliardesimo di secondo), un fotone (0 è nessun fotone, 1 è 1000 fotoni), e così via, tutto dipende da come è stato progettato il circuito. Questo è il potere delle astrazioni. Non c'è bisogno di sapere cosa significano gli 0 e gli 1 per progettare cose più in alto (ma si prenderanno cattive decisioni più in alto se non si sa questo, quindi forse l'astrazione non è perfetta).

Ora pensiamo come possiamo fare qualcosa con queste porte molto semplici. Pensiamo che state per avviare la vostra azienda di processori e volete fare un semplice blocco che aggiunga due numeri usando solo queste porte.

"Ma aspettate", direte voi, "cos'è un numero in termini di 0 e 1? Io conosco solo numeri come 57 e 42, che sono fatti di cifre da 0-9, non solo di 0 e 1". È vero, ma vedi, 57 è solo una "rappresentazione" del numero sottostante, che in realtà è 5*10+7. Puoi anche rappresentare 57 come 1*2^5+1*2^4+1*2^3+0*2^2+0*2^1+1*2^0. Ecco fatto, 57 è uguale a 111001 in questo nuovo sistema. Potete convincervi che qualsiasi numero può essere rappresentato in questa forma.

Ora, pensiamo a come costruire un sommatore. Prima di tutto, proviamo a costruire un "mezzo sommatore", uno che prende due bit e li somma per dare in uscita due bit. Così, se i due bit sono entrambi 0, uscirà 00, se solo uno di loro è 1, uscirà 01, e se entrambi sono 1 uscirà 10. Pensiamo un bit alla volta e prendiamo il primo bit all'inizio. Dopo un po' di tempo, capiamo "Oh! Quel bit è 1 solo se entrambi i bit in ingresso sono 1". Così possiamo ottenere con un cancello AND. Fantastico!". Ora abbiamo fatto metà del nostro lavoro. Rimane solo un bit.

Ora ci sediamo a pensare di nuovo. Hmm, quest'altro bit sembra più difficile. È quasi come un OR gate, ma non emette 1 se entrambi gli ingressi sono 1. Ok, non pensiamoci più e decidiamo di chiamarlo un nuovo tipo di gate, un OR gate esclusivo.

main-qimg-09a0a61f4fbfc824237c5dd48074d028.webp

"Non preoccuparti", dico, "assumeremo degli ingegneri di circuiti super fantastici che possono progettare un gate del genere ad occhi chiusi". Ora disegniamo un'immagine del nostro nuovo fantastico circuito: un half adder.

main-qimg-a2c3b3248175a9f1553f77eaa8e3aacd.webp

Ma, ora tu dici, "possiamo aggiungere solo numeri da 1 bit. La nostra azienda rivale può aggiungere numeri oltre 1 miliardo. Come facciamo?". La risposta è, sorpresa sorpresa, astrazioni. Vedete, il nostro progetto attuale può sommare solo due numeri a un bit, e l'output è una somma e un "carry", che ora deve essere aggiunto al prossimo bit superiore. Questo ha bisogno dell'aggiunta di tre bit, cosa che il nostro piccoletto non può fare.

Così dopo un'altra giornata intera a scervellarci su questo, capiamo che questo sarà un buon circuito per farlo e lo chiamiamo un adder "completo".

main-qimg-1fa4adfa89865990af5be788ba6e52c4.webp

Ora abbiamo tutto il potere di aggiungere del mondo nelle nostre mani. Vedete, ora possiamo semplicemente concatenare 32 di questi piccoletti come il seguente e abbiamo tra le mani un mostro che può aggiungere numeri più di 1 miliardo, in un batter d'occhio.

main-qimg-54510fd60b7c1fa03c10990a8f5652ed.webp

E qui c'è la meravigliosa notizia: potete semplicemente continuare a fare gate sempre migliori, e il vostro circuito diventerà sempre migliore. Questo è il potere dell'astrazione.

Ovviamente, come si è scoperto, il nostro modo di aggiungere cose non è poi così grande. Si può fare meglio, molto meglio. Ma, a causa della nostra amica astrazione, ciò può essere fatto indipendentemente dai gate. Se il tuo nuovo circuito è 2x migliore di quello vecchio, E hai 2x porte più veloci, hai un circuito 4x migliore! Questo è uno dei principali contributi a come abbiamo ottenuto migliaia di volte meglio in pochi decenni. Abbiamo costruito porte più piccole, più veloci e che consumano meno energia. E abbiamo scoperto modi sempre migliori per fare lo stesso calcolo. E poi li abbiamo uniti insieme. Ha funzionato come per magia!

Ora lavoriamo per un anno nel nostro garage e costruiamo circuiti che possono moltiplicare, aggiungere, sottrarre, dividere, confrontare e fare tutti i tipi di aritmetica, tutto in 1 nanosecondo. Facciamo persino un minuscolo circuito che può "immagazzinare" un valore, cioè il suo output dipenderà da quale valore gli è stato scritto in precedenza (qualcuno suggerisce di chiamarlo flip-flop. Sembra un nome divertente, lo teniamo ^_^ ). Ma, vedete, una cosa che tutti i nostri circuiti hanno in comune è che prendono in ingresso e fanno la stessa operazione su di essi per dare l'uscita. E se io volessi a volte fare una moltiplicazione, e altre volte un'addizione?

Ora, abbiamo un'idea! Diciamo: non consideriamo i bit solo come numeri. Proviamo a rappresentare le "azioni" stesse nei bit. Diciamo che 0 significa "aggiungere", 1 significa "moltiplicare". Ora, costruiamo un piccolo circuito che vede un bit come un "comando", e seleziona tra due ingressi, I0 e I1, e produce I0 se il comando è 0, e I1 se è 1. Questo è un multiplexer.

main-qimg-ad216c7b8568c13bc39771006310cb2a.webp

"Wow!!!", dici, "ora abbiamo solo bisogno di un multiplexer per scegliere tra le uscite di un sommatore e un moltiplicatore, e abbiamo la nostra soluzione! In effetti, perché non avere molti di questi multiplexer per scegliere tra tante uscite, e abbiamo ottenuto una macchina così sorprendente. Può fare così tante operazioni aritmetiche a seconda di ciò che le si dà come "comando"".

Ora abbiamo un'altra idea SPLENDIDA! Ricordate quei piccoli e divertenti flip-flop che abbiamo costruito prima? Pensiamo, e se inseriamo un multiplexer 1024-1 all'uscita di 1024 flip-flop? Ora abbiamo quella che viene chiamata una memoria da 1 Kilobit! Possiamo dargli un "indirizzo", e ci restituirà un bit, che era il bit memorizzato in quella posizione numerata. Non è una figata? Cosa c'è di più, questi bit ora possono essere sia "numeri" (dati) che "comandi" (istruzioni).

Sediamoci e pensiamo a quello che abbiamo fino ad ora: abbiamo tante funzioni aritmetiche, abbiamo un bel multiplexer che seleziona quale uscita scegliere, e abbiamo una memoria, che può darci qualsiasi bit se le diamo un "indirizzo".

Ecco la cosa incredibile ora. Abbiamo TUTTO quello che ci serve per costruire un processore. Vediamo come:

  • Prima di tutto, abbiamo un array di memoria MEM che contiene tutti i "comandi" (istruzioni) e i "numeri" (dati).
  • Secondo, abbiamo un numero chiamato "program counter", che usiamo per selezionare quale istruzione eseguire dalla MEM. Normalmente aumenta di 1 ad ogni passo.
  • Terzo, abbiamo un blocco aritmetico con multiplexer.
  • Quarto, generiamo entrambi gli ingressi al nostro blocco aritmetico dalla MEM.
  • Infine, ci sono due tipi di istruzioni: istruzioni dati e istruzioni di controllo. Ogni istruzione dati contiene quattro cose: due indirizzi che specificano quali due numeri prendere dalla MEM, un comando che dice quale operazione eseguire, e un'altra posizione che dice dove rimettere il risultato. Le istruzioni di controllo semplicemente rimettono un altro indirizzo nel "contatore del programma".

main-qimg-c064cfc964e90bcd16b987bbc09e6627.webp

Questa cosa che hai appena costruito si chiama macchina di Von-Neumann (sì, dei pazzi come lui hanno capito tutte queste cose nel 1945, non so come). La gente oggi comincia a chiedersi se questo sia il modo migliore di costruire le cose, ma questo è il modo standard in cui viene costruito qualsiasi processore al giorno d'oggi.

Bene, quando prima ho detto che questo è il modo in cui vengono costruiti tutti i processori, intendevo "teoricamente", e con "teoricamente", intendo "consideriamo che una mucca sia una sfera" teoricamente. Vedete, la CPU del vostro concorrente può girare intorno alla vostra CPU Von-Neumann di base. Voi avete solo 1000 Kilobit di memoria, il vostro concorrente può gestire fino a miliardi (Gb) o trilioni (Tb) di bit di memoria. Ma ora tu dici: è impossibile che quei ragazzi possano creare un multiplexer da un miliardo a uno e avere i suoi dati entro 1 nanosecondo. È vero. La loro salsa segreta è qualcosa chiamata località.

Quello che significa è che il tuo programma normalmente usa solo poche locazioni di memoria dati e istruzioni alla volta. Quindi quello che si fa è avere una grande memoria composta da GB's di dati, poi si porta una piccola parte di essa - la parte che viene utilizzata attualmente, in un array molto più piccolo (forse 1 MB) chiamato cache. Naturalmente, ora si può avere una cache ancora più piccola sotto questa cache, e così via, fino ad arrivare a qualcosa che si può leggere o scrivere in circa lo stesso tempo in cui si può fare un calcolo aritmetico.

Un'altra idea potente che si può fare è chiamata elaborazione fuori ordine. Il concetto che c'è dietro può essere illustrato dal seguente programma che calcola X = (A+B)*(C+D)

  1. Aggiungi A e B e memorizzalo in U
  2. Aggiungi C e D e memorizzalo in V
  3. Moltiplica U e V e memorizzalo in X

Nel modo normale, lo farai in sequenza, andando un'istruzione dopo l'altra e finendo l'esecuzione in 3 passi. Ma, se avete due adders nel vostro sistema, potete eseguire le istruzioni 1 e 2 in parallelo, e quindi finire in 2 passi. Così eseguite il più possibile ogni passo e finite l'esecuzione più velocemente.

Ora, ripensate al tempo in cui tutto ciò che conoscevate era una semplice porta AND. Questa cosa che avete costruito sembra così estranea a quella. Ma in realtà è solo strati su strati di blocchi, e il riutilizzo di un blocco più semplice per costruire un blocco più complesso. Questa è l'idea chiave qui. Una CPU è costruita solo rattoppando insieme delle parti, che è costruita rattoppando insieme parti più piccole. Alla fine però, se fissate la cosa, appare così:

main-qimg-f0dd23d6c9092b96d4cdc7f1499b7807.webp

  1. Adder (elettronica)
  2. architettura Von Neumann
  3. Cache della CPU
  4. Esecuzione fuori ordine
  5. ARK | Intel® Core™ i7-3960X Processor Extreme Edition (15M Cache, fino a 3.90 GHz)

Modifica: Ci sono molti dettagli che ho omesso nella risposta originale. Questa risposta equivale a rispondere a "Come funziona una macchina di F1?" con "Ha delle ruote, e uno sterzo che guida le ruote, e un motore per far funzionare le ruote". In verità, progettare e costruire una CPU è uno dei miracoli della tecnologia moderna che coinvolge un numero enorme di discipline ingegneristiche (tra cui ad esempio la fisica quantistica, la metallurgia, la fotonica ecc.) Cercherò di affrontare alcune questioni più avanti.

Fabbricazione
Una delle incredibili prodezze della tecnologia è stata la capacità di creare e collegare miliardi di minuscoli transistor, ognuno largo meno di 100 nm (sì, è nano, cioè un miliardesimo di metro), in uno schema preciso definito dai progettisti di circuiti e dagli architetti della CPU, e renderlo comunque impossibilmente economico. È chiaro che creare e collegare un numero così grande di transistor uno per uno è impossibile a mano o anche con qualsiasi forma di meccanica.

Il metodo per fabbricare un chip si chiama fotolitografia, ed è la ragione dietro il prezzo estremamente basso dei processori rispetto alla loro complessità. L'idea è simile a come veniva "sviluppata" una foto analogica (se qualcuno se ne ricorda). Per prima cosa descriverò come creare un modello di ossido di silicio su silicio (questo è usato nei gate dei transistor). Prima si deposita uno strato di ossido di silicio sul silicio. Poi uno strato di materiale fotoresistente viene applicato sopra di esso. Questo materiale è sensibile alla luce, ma è resistente all'"incisione". Anche l'inverso del modello da creare viene realizzato sotto forma di una "maschera" attraverso la quale la luce UV viene fatta passare sul photoresist. Tuttavia, questo solleva la questione di come la maschera sia stata creata in primo luogo.

Ecco la magia della fotolitografia: la maschera è in realtà molto più grande della dimensione del modello da incidere. La luce che passa attraverso la maschera viene semplicemente focalizzata da una lente per avere la giusta dimensione quando cade sul silicio. Una volta che la luce cambia il photoresist, questo viene inciso da un getto di plasma, lasciando solo il modello desiderato sull'ossido di silicio.

main-qimg-89843f9f60abf89a63559653619ae89b.webp

Per creare uno strato di metallo, invece, si segue una procedura simile. Tuttavia, ora l'inverso del modello viene inciso su SiO2, e poi il metallo viene depositato sui "solchi" creati dal SiO2.

La ragione per cui questo è così economico è che una volta che si ha la "maschera", si può creare un numero molto grande di chip da essa. Così, anche se una maschera è piuttosto costosa (pochi milioni di dollari), il suo costo è diviso in molti chip, il che rende ogni chip molto economico (gioco di parole non voluto).

Tipi di memorie
Come ho detto prima, è possibile costruire una memoria collegando flip-flop a multiplexer. Tuttavia, questo non è un modo particolarmente efficiente di fare le cose. Un flip-flop consuma circa 15-20 transistor. Comunque, in pratica ci sono due tipi di strutture di memoria: la RAM statica (o SRAM in breve), che usa 6 transistor per bit, e la RAM dinamica (o DRAM in breve), che usa solo un transistor e un condensatore per bit. Una RAM statica è essenzialmente due NOT gates collegati in un ciclo come questo.

main-qimg-8b43da0472f11ada5023fbe2589a8e45.webp

Chiaro che ci sono due possibili stati per A e B, o A = 1, B = 0, o A = 0, B = 1. L'idea è di applicare una certa tensione esterna per spingere il ciclo in uno stato o nell'altro, che è poi il bit "memorizzato", e poi semplicemente leggere la tensione su A o B per "leggere" il bit.

D'altra parte, la RAM dinamica o DRAM, è ancora più semplicistica ed è più o meno così.

main-qimg-9a153872dba528decd172fd0bc03baf0

In questo disegno, il transistor agisce semplicemente come un interruttore per immagazzinare la carica nel condensatore, nel qual caso viene letto come un 1, altrimenti come uno 0. Tuttavia, la carica nel condensatore perde dal transistor ogni tanto. Quindi ha bisogno di essere letta e riscritta a intervalli fissi, ed è per questo che viene chiamata RAM dinamica.

Le cache in un chip sono generalmente SRAM, poiché sono più veloci. Tuttavia, le memorie principali in un computer sono generalmente DRAM, poiché sono di dimensioni molto più piccole, e quindi una maggiore quantità di memoria può stare in un singolo chip.

  1. Photolithography
  2. Static random-access memory
  3. Dynamic random-access memory

P.S. Ho iniziato un blog sulle idee base dell'architettura della CPU su CPU Architecture. Nel caso questa risposta ti interessasse, potresti voler dare un'occhiata.