# Introduzione ai calcolatori elettronici
## Introduzione
### Il concetto di calcolatore

Il calcolatore è una macchina che risolve problemi che ammettono un algoritmo risolvente, essa è costituita da:
* variabili di ingresso, dati del problema: assumendo valori nel loro dominio, generano tutte le possibili istanze del problema;
* variabili di uscita: assumono valori, detti risultati del problema;
* algoritmo: metodo generale che specifica, mediante una sequenza di istruzioni, come produrre per ogni dato in ingresso il risultato che costituisce la soluzione dell'istanza del problema.
Il calcolatore viene anche detto esecutore universale di algoritmi. In questo corso verranno considerati i calcolatori elettronici, realizzati mediante circuiti elettronici e che usano i segnali elettrici vengono utilizzati per rappresentare cifre binarie come 0-1 oppure on-off. Il calcolatore è progettato come una sequenza di macchine a diversi livelli, ognuna costruita sulle macchine definite ai livelli sottostanti; dove ogni livello rappresenta una distinta astrazione, caratterizzata da differenti oggetti e operazioni. Le architetture descrivono il calcolatore a diversi livelli di astrazione, e sono costituite da: i tipi di dati, le operazioni e le caratteristiche di ogni livello.

### Segnale di clock

Un segnale di clock caratterizzato da una frequenza costante sincronizza i vari eventi all'interno dell'hardware, determinando in questo modo intervalli di tempo discreti che sono denominati cicli di clock. Il ciclo di clock è il tempo che trascorre tra il verificarsi di due colpi di clock successivi. La frequenza o velocità di clock è il numero di colpi di clock che vengono eseguiti in una determinata unità di tempo. L'unità di misura usata è l'hertz, ovvero il numero di cicli di clock eseguiti in un secondo. Poiché i clock sono in genere molto veloci, si usano comunemente i multipli kilohertz (kHz), megahertz (MHz) e gigahertz (GHz) per indicare rispettivamente mille, un milione e un miliardo di cicli al secondo.

## Instruction Set Architecture

Un instruction set ("insieme d'istruzioni"), o Instruction Set Architecture (ISA), descrive quegli aspetti dell'architettura di un calcolatore che sono visibili al programmatore, tra cui i tipi di dati nativi, le istruzioni, i registri, le modalità di indirizzamento, l'architettura della memoria, la gestione degli interrupt e delle eccezioni, e l'eventuale I/O esterno.
Le tipologie delle varie ISA si possono suddividere in base ai seguenti criteri:
* “Dove sono localizzati” gli operandi delle istruzioni:
** architettura a “registro accumulatore” (accumulator architecture);
** architettura a “registri specializzati” (special-purpose register architecture);
** architettura basata su stack (stack architecture);
** architettura a registri di uso generale (general purpose register architecture).
* Lunghezza delle istruzioni, fissa vs. variabile.
* Numero di istruzioni, CISC (Complex Instruction Set Computer) vs. RISC (Reduced Instruction Set Computer).

### Localizzazione degli operandi delle istruzioni
#### Architettura a “registro accumulatore”

È la prima architettura storicamente sviluppata e dati i costi dell'hardware al tempo è dotata di un solo registro, chiamato accumulatore, ed essendo l'unico registro, esso non viene indicato, né rappresentato. Nelle istruzioni aritmetico/logiche, l'accumulatore funge sia da sorgente sia da destinazione mentre l'altro operando deve essere in memoria
Pro:
* Costi dell'hardware molto bassi e quindi un notevole risparmio.
* Istruzioni macchina brevi con un risparmio di memoria.
Contro:
* Sono richiesti molti accessi alla memoria, i quali provocano tempi di inutilizzo del calcolatore data la lentezza delle operazioni in memoria.
ESEMPIO A = B+C (A, B, C in memoria):

#### Architettura a “registri specializzati”

Sono l'evoluzione della architettura a registro accumulatore, ai quali vengono aggiunti registri specializzati:
* Registri base e indice per l'accesso in memoria.
* Registri che possono contenere dati per le istruzioni aritmetiche.
* Registri che puntano all'elemento in cima allo stack.
Un esempio di microprocessore con questa architettura è l'Intel 8086

#### Architettura basata su stack

In questo tipo di architettura vengono eliminati tutti i registri, registri che vengono sostituiti da uno stack. Sono quindi previste delle istruzioni per la gestione dello stack, quali: push nello stack di un elemento dalla memoria, pop dallo stack di un elemento in memoria e istruzioni per effettuare un'operazione aritmetico-logica sui due elementi in cima allo stack.
Pro:
* Il compito dei calcolatori diventa più semplice; in quanto non devono decidere come allocare i registri.
* Istruzioni macchina piccole, poiché non si hanno gli operandi per le istruzioni aritmetico-logiche.
Contro:
* Molti accessi in memoria.
ESEMPIO A = B+C (A, B, C in memoria):

#### Architettura a registri di uso generale (general purpose registers)

Sono architetture che mettono a disposizione dei registri che possono essere utilizzati da tutte le istruzioni per qualunque scopo. Si dividono in più categorie, register-memory architecture per le quali esistono istruzioni aritmetico-logiche con un operando in memoria); register-register architecture quando le istruzioni aritmetico-logiche lavorano solo su registri e e memory-memory architecture (es. VAX della DEC).
Pro:
* Minimizzano gli accessi in memoria.
Contro:
* Istruzioni più lunghe, è necessario prevedere appositi campi con cui indicare i registri operando.
* Il lavoro dei compilatori è complesso poiché devono scegliere quali registri usare per minimizzare lo spilling.

##### Esempio:

Si supponga di voler calcolare il valore $A=B+C$, con A,B,C in memoria. Una generica sequenza di istruzioni per un architettura a registri general purpose sarebbe:

### Lunghezza delle istruzioni

Le istruzioni dell'ISA possono essere a lunghezza variabile o fissa.
Istruzioni a lunghezza variabile consentono di mantenere la lunghezza del codice scritto la più piccola possibile, d'altra parte per semplificare il compito dell'hardware alcune architetture prevedono istruzioni a lunghezza costante.
Alcuni esempi di architetture a lunghezza variabile:
* Intel IA-32: da 1 a 17 bytes.
* IBM 360 (usata nei mainframe): 2, 4, 6 bytes.
* VAX: da 1 a 54 bytes.
Alcuni esempi di architetture a lunghezza fissa:
* DLX
* ARM

### Architetture CISC e RISC

Le architetture di tipo reduced instruction set computer (RISC) sono formate da un set di istruzioni contenente istruzioni in grado di eseguire operazioni semplici che possono essere eseguite in tempi simili.
Questa filosofia di progettazione è opposta a quella alla base delle architetture complex instruction set computer (CISC) che invece predilige architetture dotati di istruzioni anche molto complesse con tempi di esecuzione molto diversi a seconda delle istruzioni.
Le architetture di tipo CISC permettono la realizzazione di programmi compatti che quindi richiedono poca memoria, una risorsa molto costosa negli anni 60. Viene inoltre minimizzato del numero di istruzioni eseguite, poiché le operazioni complesse erano “cablate” nell'hardware con un presunto miglioramento delle prestazioni e semplificando il compito del programmatore assembly.

### Le tendenze odierne

Con il diminuire dei costi dell'hardware le architetture sono state arricchite con integrazioni hardware sempre maggiori, provocando un vistoso miglioramento delle prestazioni e con vincoli minori rispetto alla memoria; mentre con l'introduzione della cache interna al processore viene limitato il ruolo della microprogrammazione, con l'eccezione del Pentium.
L'organizzazione del calcolatore viene basata su pipeline e si ha un enorme miglioramento della tecnologia dei compilatori.
Vengon create architetture RISC, con formati regolari e lunghezza costante delle istruzioni necessarie per ottenere una semplificazione del compito dell'hardware attraverso l'utilizzo di pipeline:
* più efficiente un codice con molte istruzioni elementari, che vengon eseguite in parallelo;
* compilatori hanno un compito semplificato nel contesto di una pipeline.
Adozione di architetture a registri general-purpose o “load-store” con compilatori sofisticati che possono minimizzare gli accessi in memoria:
* lunghezza del codice molto meno importante;
* per semplificare l'hardware vengono inoltre limitati i modi di indirizzamento.