L’architettura di Hack è pensata in modo da essere la più semplice realizzabile ma allo stesso tempo in grado di eseguire programmi di complessità variabile.

Il risultato non è altro che un’architettura di Von Neumann costruita con i dispositivi sviluppati nelle lezioni affrontate fino a questo punto.

Se nella puntata precedente, dunque, abbiamo analizzato l’importanza del linguaggio assembly, in questa puntata ci concentriamo invece sull’ultimo tassello hardware fondamentale: la realizzazione della CPU e del PC nella sua interezza.

Von Neumann

La caratteristica fondamentale dei calcolatori moderni è la loro enorme flessibilità che si traduce nella capacità di eseguire programmi di qualsiasi natura: da videogiochi a elaboratori testuali.

Il concetto alla base di questa capacità è quello di programma memorizzato. L’hardware infatti è progettato così da poter eseguire un set di istruzioni generiche, combinabili tra loro in infiniti modi a formare programmi di varia complessità e natura, salvabili come dati in memoria.

Nasce qui il concetto di software, ovvero quell’elemento che fa sì che un computer possa essere usato in molteplici scenari (general purpose), a differenza dei primi calcolatori in cui tutto era fatto ad hoc per lo scopo prefisso (embedded).

E’ proprio Von Neumann a teorizzare per la prima volta un’architettura di questo tipo in cui i programmi altro non sono che dati memorizzati in memoria. Più nello specifico i componenti coinvolti sono:

Memoria

Sezione dedicata all’immagazinamento dati che a loro volta possono essere di 2 categorie:

  • Dati.
  • Instruction memory: programmi scritti in linguaggio macchina e salvati. Ciascuna delle istruzioni salvate viene poi caricata, decodificata ed eseguita dalla CPU.

CPU

Esegue l’istruzione corrente. E’ il cuore di tutta l’architettura. A sua volta composta da:

  • ALU: si occupa di eseguire operazioni aritmetiche.
  • Registri: memoria ad accesso rapido presente in qualsiasi CPU.
  • Unità di controllo: si occupa di decodificare l’istruzione corrente da eseguire e calcola la prossima.

Input/Output

Ogni calcolatore che si rispetti deve avere la possibilità di interfacciarsi con elementi esterni quali ad esempio, schermi, tastiere, mouse, etc…

La cosa interessante da considerare è indipendentemente dal dispositivo che andiamo considerando, la standardizzazione ha fatto sì che tutti questi componenti vengano visti dalla CPU nella stessa e identica maniera.

Grazie al concetto di Memory Map infatti, ogni dispositivo è gestito attraverso una parte di memoria dedicata e che fa da interfaccia di comunicazione. Settare il colore di un pixel o leggere la posizione di un mouse diventano rispettivamente banali operazioni di scrittura e lettura in memoria.

L’Architettura di Hack

La piattaforma Hack è una macchina di Von Neumann a 16 bit così composta:

Come abbiamo già avuto modo di accennare negli articoli precedenti, la nostra architettura dispone di 2 registri rispettivamente chiamati D e A. In particolare:

  • (D) Data register: registro usato per memorizzare unicamente dati.
  • (A) Address register: registro usato per dati ma anche per memorizzare indirizzi di memoria.

Il sistema può essere poi programmato attraverso 2 tipologie di istruzioni:

  • Istruzione indirizzo: 0vvvvvvvvvvvvvvv
    Il PC carica la costante a 15 bit codificata in vvvvvvvvvvvvvvv.
  • Istruzione di calcolo: 111accccccdddjjj
    a e c selezionano la funzione da eseguire, d identifica dove salvare il risultato della ALU e j una eventuale condizione di salto.

Per maggiori dettagli sul linguaggio pensato per questa piattaforma, fai riferimento alla lezione dedicata al linguaggio macchina.

Un ciclo di esecuzione completo è così gestito:

Execute:
i bit dell’istruzione corrente vengono divisi tra i vari chip presenti. Nel caso di un’istruzione indirizzo, il registro A viene settato al valore contenuto nei 15 bit v. Nel caso di un’istruzione di calcolo, le varie parti a, c, d e j vengono gestite come bit di controllo per far sì che la CPU possa comportarsi di conseguenza.

Fetch:
la prossima istruzione da fetchare è determinata dai bit j di salto e dall’output della ALU. Il risultato di questa fase è passato al PC così che, al ciclo successivo, possa essere caricata l’istruzione corretta.

Il Progetto

Partendo dall’archivio nandt2tetris.zip scompattato nella lezione iniziale, nella cartelle projects, troverai una serie di sottocartelle numerate. Per questa lezione ci concentriamo sulla cartella 05, al cui interno troverai una serie di file pronti ad essere caricati nel simulatore.

L’obiettivo di questo capitolo è quello di progettare Hack nella sua interezza. L’architettura finale dovrà risultare in questo modo:

Partendo dal preupposto che la ROM32K è un dispositivo molto simile a quanto abbiamo già avuto modo di sviluppare nella lezione dedicata alle memorie, gli unici ingredienti veramente mancanti sono la CPU e la Memoria.

Come già fatto in precedenza, il capitolo propone di sviluppare le proprie soluzioni testandole poi con il simulatore hardware gratuito.

Le modalità sono esattamente le stesse, per cui se non lo avessi fatto, ti consiglio di leggere il primo articolo di questa serie dove viene spiegato come scaricare ed installare i tool necessari.

Le specifiche di ciascuno di questi componenti sono riportate all’interno dei rispettivi file .hdl.

Per motivi di brevità in questa lezione non mi soffermerò nell’analizzare alcuna soluzione specifica. Ti consiglio di cimentarti da te nella progettazione utilizzando il simulatore hardware liberamente scaricabile.

Se vuoi confrontarti con una possibile soluzione ai problemi puoi scaricare lo zip da questo link.

La CPU

Per realizzare la CPU di Hack gli autori ci vengono in aiuto presentando una bozza di soluzione da cui possiamo partire:

Partendo da questo diagramma, è necessario sviluppare tutta la logica di controllo rappresentata dai punti C in figura in modo che le istruzioni di tipo indirizzo e quelle di calcolo possano essere decodificate ed eseguite correttamente.

Per questo esercizio, ti consiglio di tenere di conto:

  • la tabella 2.6 a pagina 37 del capitolo 2;
  • le specifiche del linguaggio macchina di Hack spiegate nel paragrafo 4.2 a pagina 62 del capitolo 4.

La Memoria

Per quanto riguarda la memoria, Hack dovrà averne una ripartita in 3 parti fondamentali:

  • da 0 fino a 16.383 abbiamo indirizzi dedicati all’accesso in RAM.
  • da 16.384 a 24.575, la memoria è dedicata alla mappatura dello schermo.
  • 24.576 infine è dedicato alla mappatura dell’output della tastiera.

Conclusioni

Abbiamo analizzato più a fondo l’architettura di Hack e ci siamo cimentati nel realizzare i componenti mancanti, si conclude quindi lo sviluppo hardware del nostro sistema.

Dalla prossima lezione in poi andremo ad analizzare l’architettura software: partiremo dallo sviluppo di un assembler per poter scrivere codice in linguaggio macchina, salendo poi via via strato dopo strato a definire il sistema operativo e linguaggi ad alto livello.

Come sempre, puoi scaricare le soluzioni a questa lezione da qui.