Varianti architetturali: Harvard, CISC e RISC – oltre Von Neumann
Dopo Von Neumann, pipeline e cache, scopriamo come l'evoluzione ha generato scelte diverse su due livelli: come è organizzata la memoria (Von Neumann vs Harvard) e come è fatta l'ISA (CISC vs RISC). Capirai perché il tuo PC e il tuo smartphone usano filosofie opposte ma entrambe vincenti.
1. Perché superare Von Neumann?
Dopo aver analizzato il modello di Von Neumann, il ciclo macchina e le ottimizzazioni come pipeline e cache, è il momento di allargare la prospettiva. L'evoluzione dei calcolatori non si è limitata a migliorare il modello originale — ha prodotto varianti architetturali basate su scelte progettuali fondamentalmente diverse.
Organizzazione memoria
Von Neumann vs Harvard — memoria condivisa o separata? Dove metto dati e istruzioni cambia tutto il flusso.
Filosofia istruzioni
CISC vs RISC — istruzioni complesse o semplici? Cambia quanto è facile fare pipeline e quanto consumi.
Efficienza complessiva
Non solo GHz: bus, cache, decode, parallelismo. Le scelte interne decidono prestazioni reali.
Variante architetturale = scelta progettuale diversa rispetto a Von Neumann puro che ottimizza un aspetto: parallelismo memoria (Harvard) o parallelismo esecuzione (RISC).
2. Il collo di bottiglia di Von Neumann
Nel modello classico, dati e istruzioni condividono la stessa memoria e lo stesso bus. Questo comporta una conseguenza strutturale precisa:
La CPU non può accedere contemporaneamente a un'istruzione e a un dato. Istruzioni e dati condividono lo stesso canale — devono transitare uno alla volta. Con l'aumento della velocità dei processori, questo limite è diventato il principale ostacolo alle prestazioni.
Pensa al bus unico come a un ponte a una corsia: o passano le istruzioni o passano i dati. Harvard invece ha due ponti. Quando a verifica ti chiedono "cos'è il collo di bottiglia?" non dire solo "lentezza": specifica "condivisione di memoria e bus tra codice e dati". Il dettaglio fa la differenza tra 6 e 8.
3. Architettura Harvard: memorie separate
Architettura in cui memoria istruzioni e memoria dati sono fisicamente separate, con bus distinti. Permette fetch dell'istruzione e accesso al dato nello stesso ciclo di clock.
L'idea nasce negli anni '40 ad Harvard (da cui il nome) e diventa centrale nei microcontrollori. Vantaggi immediati: parallelismo memoria, larghezza bus ottimizzata (es. 16 bit istruzioni, 8 bit dati), maggiore sicurezza (codice non sovrascrivibile da dati per sbaglio).
Due memorie
Program memory (Flash/ROM) + Data memory (RAM). Indirizzi indipendenti, tecnologie diverse.
Due bus
Bus istruzioni + bus dati. La CPU fa fetch e load/store contemporaneamente. Raddoppia throughput.
Dove la trovi
PIC, AVR, Arduino Uno, DSP real-time. Massima prevedibilità, tempistiche deterministiche.
Su Arduino Uno (ATmega328P) la Flash contiene lo sketch (32KB), la SRAM i dati (2KB). Se scrivi int x=5; il valore 5 sta in Flash come costante, ma a runtime viene copiato in RAM. Prova a riempire RAM con array grandi: compila ma crasha a runtime — perché? Flash ok, RAM esaurita. Harvard pura te lo mostra chiaramente.
Harvard non è CISC/RISC. Harvard riguarda dove stanno dati e istruzioni. CISC/RISC riguarda come sono fatte le istruzioni. Sono assi diversi: puoi avere Harvard + RISC (AVR) o Von Neumann + RISC (ARM vecchio).
4. Harvard modificata: il compromesso moderno
I processori moderni non usano né Von Neumann puro né Harvard pura. Usano una Harvard modificata:
- L1 Cache separate: I-cache per istruzioni, D-cache per dati, entrambe sulla CPU → accessi paralleli velocissimi
- L2/L3 e RAM condivise: oltre L1, istruzioni e dati possono risiedere nella stessa RAM → flessibilità di Von Neumann
- MMU unificata: spazio di indirizzamento unico visto dal programmatore, separazione gestita hardware
Quando in Linux usi time ./programma e vedi miss di cache, stai vedendo proprio questo: L1 separata veloce, se sbagli prediction vai in RAM condivisa lenta. Harvard modificata spiega perché codice e dati possono stare insieme in RAM ma la CPU li tratta in parallelo in L1.
5. CISC vs RISC: due filosofie dell'ISA
Secondo asse: non dove stanno, ma come sono fatte le istruzioni.
ISA con molte istruzioni complesse, lunghezza variabile, che in una singola istruzione possono fare fetch, operazione ALU e accesso memoria. Obiettivo storico: ridurre codice e semplificare compilatori (anni '70 con memoria cara).
ISA con poche istruzioni semplici, lunghezza fissa, che eseguono una sola operazione semplice per ciclo. Load/Store separati: solo istruzioni dedicate accedono alla RAM. Obiettivo: pipeline facile, CPI ~1, hardware semplice.
CISC (x86): ADD [mem], AX fa tutto: legge [mem], somma AX, riscrive [mem] — 1 istruzione, ma 5-6 cicli, decode complesso.
RISC (ARM): servono 3 istruzioni: LDR R1,[mem] poi ADD R1,R1,R0 poi STR R1,[mem] — 3 istruzioni fisse 32-bit, 1 ciclo ciascuna, pipeline perfetta. Codice più lungo ma 3 cicli totali vs 6 e zero stalli.
Dire "RISC ha meno istruzioni quindi è più lento" è sbagliato. RISC ha istruzioni più semplici, quindi ogni istruzione è più veloce e pipeline non si blocca. Un programma RISC ha più istruzioni, ma impiega meno cicli totali. È come confrontare: CISC = camion che fa tutto in un viaggio, RISC = moto che fa 3 viaggi veloci senza traffico.
6. Confronto tecnico CISC vs RISC
| Aspetto | CISC (x86, x86-64) | RISC (ARM, RISC-V) |
|---|---|---|
| Lunghezza istruzione | Variabile 1-15 byte, decode complesso | Fissa 32 bit (16 bit thumb), decode banale |
| Cicli per istruzione (CPI) | 2-12 cicli, imprevedibile | Obiettivo 1 ciclo, prevedibile |
| Accesso memoria | Qualsiasi istruzione può accedere a RAM | Solo LOAD/STORE, resto solo registri |
| Registri | Pochi (8-16), architettura storica | Molti (32+), uso intensivo compilatore |
| Pipelining | Difficile, stalli, micro-op translation | Ottimale, pipeline pulita, in-order semplice |
| Compilatore | Semplice (ISA fa lavoro) | Complesso (deve ottimizzare) |
| Efficienza energetica | Media-bassa, decode energivoro | Alta, hardware semplice, ideale mobile |
| Esempio | Intel Core i7, AMD Ryzen | Apple M3, Snapdragon, ESP32, RISC-V |
7. Combinazioni reali: cosa usano PC, smartphone e microcontrollori
I due assi sono indipendenti: memoria (Von Neumann / Harvard) e ISA (CISC / RISC). I processori moderni combinano i due livelli.
CISC esterno → RISC interno
ISA CISC per compatibilità, ma dentro traduce in micro-operazioni RISC-like (μOps) durante l'esecuzione. Front-end CISC, back-end RISC.
Harvard modificata + CISC
RISC puro ottimizzato
ISA RISC con estensioni SIMD, ottimizzata per efficienza energetica. Domina smartphone, tablet, laptop moderni. Da M1 in poi supera x86 in perf/W.
Harvard modificata + RISC
Harvard pura + RISC
PIC, AVR, ESP32, RISC-V embedded: Harvard pura con ISA ridotta, massima prevedibilità e velocità su sistemi real-time, open source.
Harvard pura + RISC
Perché il compilatore x86 è storico: non puoi rompere compatibilità con 40 anni di software. Soluzione: fuori vedi CISC, dentro la CPU spacca ADD [mem],EAX in micro-op tipo RISC: LD TMP,[mem] / ADD TMP,EAX / ST [mem],TMP. Così pipeline RISC funziona anche con ISA CISC, pagando costo extra di traduzione (più transistor, più energia).
8. Perché l'architettura conta più del clock
Le prestazioni non dipendono solo dalla velocità del clock, ma dalle scelte progettuali interne. Separare memoria e dati riduce i colli di bottiglia. Semplificare le istruzioni favorisce il parallelismo. Ottimizzare la struttura interna permette di sfruttare meglio pipeline e cache. Tempo = (Istruzioni × CPI × Tclock). Con RISC abbassi CPI, con Harvard abbassi stalli, con cache abbassi Tmemory.
9. Verifica operativa
🔬 Confronta le architetture
Hai un ESP32 per sensore temperatura (batteria) e un PC per rendering video. Rispondi motivando:
- Quale usa Harvard pura e quale Harvard modificata? Perché?
- Se il PC usa x86-64, perché traduce internamente in RISC-like? Cosa perderebbe altrimenti?
- CISC vs RISC: quale ha formato istruzione fisso? Perché questo aiuta il pipeline?
- Un programma CISC ha 1M istruzioni, CPI 3, 4GHz. Uno RISC 1.4M istruzioni, CPI 1.2, 3GHz. Quale finisce prima? Calcola.
- Perché ARM domina su mobile? Collega RISC + Harvard + energia.
1) ESP32 → Harvard pura: Flash separata da SRAM, determinismo real-time. PC → Harvard modificata: L1 separate, RAM condivisa, flessibilità OS.
2) Senza traduzione, decode CISC variabile bloccherebbe pipeline. Traducendo in μOps fissi, pipeline RISC-like funziona, recuperando IPC. Costo: area e potenza per decoder complesso.
3) RISC: lunghezza fissa 32bit → fetch sempre uguale, decode in 1 ciclo, predizione PC banale. CISC variabile → devi capire dove finisce istruzione prima di fetchare prossima.
4) T_CISC = 1e6*3/4e9=0.75ms. T_RISC=1.4e6*1.2/3e9=0.56ms → RISC vince nonostante più istruzioni.
5) RISC = hardware semplice → meno transistor → meno consumo. Harvard L1 = parallelismo → meno stalli → meno cicli persi. Mobile = batteria, quindi perf/Watt vince su GHz puri.
10. Riepilogo e concetti chiave
📚 Prossimo passo - Alternative ai microprocessori
Hai visto come ottimizzare la CPU. Ora vediamo alternative: GPU con migliaia di core, FPGA riconfigurabili, TPU per IA. Quando conviene non usare la CPU? Porta schema Von Neumann vs Harvard e CISC vs RISC — nella prossima lezione confrontiamo i modelli di calcolo parallelo.
