O Vex é uma arquitetura load/ store o que significa que apenas as operações do tipo Load e Store podem aceder à memória e que as operações de acesso à memória apenas podem ter como destino ou fonte registos de propósito geral (GR), ou seja, não existem operações do tipo memory-to-memory. Outra característica importante do VEX é o modo de endereçamento das operações de acesso à memória, o modo como é realizado o endereçamento é base-plus-offset, sendo a base um registo GR e o offset um imediato do tipo short [12].
Neste subcapítulo são definidas as especificações técnicas de acordo com o ISA escolhido, estas especificações vão influenciar a arquitetura e microarquitectura do processador.
• O microprocessador vai operar com 32 bits (tamanho das sílabas que constituem a instrução VLIW);
o O bus de dados e os registos internos têm de ser definidos para uma arquitetura de 32 bits;
• A área de implementação deve ser mínima;
• Implementação single cluster com possibilidade de expansão; • Issue width de 4 operações por cluster;
• 4 Unidades lógicas e aritméticas (ALU) por cluster; • 2 Unidades de multiplicação (MUL) por cluster; • 64 Registos internos com 32 bits cada;
o Isto constituirá o general-porpose register file (GR) do microprocessador. Cada registo é endereçado usando 6 bits (de 6’b000000 para o registo R0 até 6’b111111 para o registo R63); • 8 Registos internos com 1 bit cada;
o Isto constituirá o branch register (BR) do microprocessador. Cada registo é endereçado usando 3 bits (de 6’b000 para o registo B0 até 6’b111 para o registo B7);
• 1 Link register de 32 bits;
o Utilizado para guardar o endereço para indirect branches; • 1 Unidade memory load por cluster;
12
• 1 Unidade memory store por cluster;
• O instruction set inclui operações aritméticas, operações de load e store da memória, operações de branch e operações de comparação;
A organização VEX é baseada na arquitetura Harvard, o que implica que memória de dados e memória de código estejam separadas fisicamente, permitindo assim diferente tamanho de dados e instruções.
Figura 2.1 - Organização VEX
Caches
2.7.
A memória de um computador é organizada de forma hierárquica. As memórias de registos do processador (General Registers e Branch Registers) constituem as memórias de mais alto nível (mais próximas do processador) e o disco rígido ocupa o lugar de memória de mais baixo nivel. A cache segue-se às memórias de registos na hierarquia, podendo esta preencher mais que um nível, normalmente denominados de L1, L2 etc. O nível que se segue é preenchido pela memória principal. Todas estas
13 memórias são consideradas internas ao sistema. A hierarquia continua com as memórias externas sendo normalmente a memória RAM a ocupar o nível seguinte [14].
Com o baixar da posição hierárquica da memória, diminui o custo por bit de memória, aumenta a capacidade e diminui a velocidade de acesso. O ideal em termos de performance seria usar apenas a memória de mais alto nível, mas devido elevado custo por bit, é necessário usar também memórias de nível inferior. Uma solução para equilibrar a relação performance/custo é organizar os dados e o código para que os dados de trabalho estejam preferencialmente guardados na memória mais rápida.
O uso de Cache tem por função, não só permitir um acesso à memória a uma velocidade próxima das memórias mais rápidas, como também disponibilizar mais espaço de armazenamento a preços próximos das memórias mais baratas. A escolha das características da cache a implementar tem uma influência direta nessa função. A interação da Cache com o processador e a memória principal está ilustrada nas Figura 2.1 - Single cache [14] e Figura 2.2.
CPU Cache
Memória principal Transferência de
Word’s Transferência de blocos
Rápido Lento
Figura 2.2 - Single cache [14]
CPU Mais rápido Nivel 1 (L1) cache Rápido Nivel 2 (L2) cache Menos rápido Nivel 3 (L3) cache Lento Memória principal
Figura 2.3 – Organização de cache de 3 níveis [14]
Mapping Function 2.7.1.
O facto de existirem menos linhas de cache do que blocos de memória leva a que seja necessário o uso de um algoritmo para mapear os blocos da memória principal nas
14
linhas de cache existentes. Quando o processador pretende aceder a uma determinada linha de memória podem ocorrer os seguintes eventos:
• Miss – Significa que a linha de memória a que o processador pretende aceder não se encontra armazenada em cache, o que origina uma leitura da memória principal por parte da cache;
• Hit – Significa que a linha de memória a que o processador pretende aceder está armazenada em cache, sendo os dados disponibilizados de imediato ao processador;
Na Figura 2.3 vemos como é feito o Mapeamento de uma cache do tipo Direct
Mapped. Neste caso a técnica de mapeamento é simples e tem custo de implementação
baixo, mas devido ao facto de existir apenas uma linha de cache para alocar cada bloco da memória principal, pode ocorrer uma elevada taxa de misses. Caso o processador faça consecutivamente o pedido de words que estejam alocadas em blocos diferentes da memória principal, mas que sejam mapeadas na mesma linha de cache, irão ocorrer
misses consecutivos, o que torna o acesso à cache lento, pois será necessário realizar
leituras consecutivas de blocos da memória principal.
Memória cache Blocos da memória de dados
(tamanho igual ao da cache)
m linhas b t b L0 L m-1 B0 B m-1
b – Comprimento do bloco em bits t – Comprimento do tag em bits
Figura 2.4- Direct Mapped Cache [14]
No outro extremo temos as caches do tipo Fully Associative (Figura 2.4) que embora solucionem a desvantagem da cache Direct Mapped, pois permitem que um bloco da memória principal seja alocado em qualquer linha da cache, tem como
15 desvantagem a complexidade do circuito necessário para examinar os tags de todas as linhas da cache. Memória cache Um bloco da memória principal m linhas b t L0 L m-1
b – Comprimento do bloco em bits t – Comprimento do tag em bits b
Figura 2.5 - Fully associative cache
Por fim temos as caches do tipo n-way set associative (Figura 2.5) que, conjugando pontos fortes de cada uma das caches anteriores, consegue diminuir as suas desvantagens. Neste tipo de cache existe um número fixo de linhas (uma por set, dois
sets no mínimo) onde cada bloco da memória principal pode ser alocado, e a
complexidade necessária para verificar as tags da linha pretendida pelo processador é bastante reduzida. A sua organização está explicada na Figura 2.6.
16 m linhas b t L0 L m-1 m linhas b t L0 L m-1
Memória cache – Set v-1
Memória cache – Set 0
Bv-1
B0
Figura 2.6 - n-way set associative cache [14]
Figura 2.7 – Organização da cache n-way set associative [14]
Algoritmo de substituição 2.7.2.
O algoritmo de substituição estabelece as regras com que novos dados são escritos na cache em caso da mesma estar cheia, ou a posição pretendida ocupada. No caso de
17 uma cache do tipo direct mapped, não é usado qualquer algoritmo, pois apenas existe uma linha de cache para alocar qualquer bloco em particular. Nos restantes casos já existe necessidade de um algoritmo que determine a linha onde o bloco será escrito.
O algoritmo de substituição least recently used (LRU) consiste na substituição do bloco que está em cache há mais tempo sem ser referenciado, a implementação é feita com recurso a um contador em cada bloco de cache por forma a armazenar o histórico de utilizações, sempre que um bloco de um determinado set é referenciada o contador correspondente toma valor “0” e o contador do bloco correspondente dos restantes sets é incrementado. O algoritmo pseuso least recently used (Pseudo-LRU) substitui, tal como o LRU, o bloco de cache que está há mais tempo sem ser referenciada. A implementação deste algoritmo implica a utilização de apenas um bit em cada bloco de
cache, e identifica o bloco a substituir recorrendo a uma árvore binária.
Comparativamente ao algoritmo Pseudo-LRU o LRU tem como desvantagem o facto de ser de implementação mais complicada, necessita de mais bits e a lógica de atualização é mais complexa [24].
Existem mais exemplos de algoritmos de substituição possíveis, tal como o first-
in-first-out (FIFO), que consiste na substituição do bloco que esta há mais tempo em
cache, ou o least frequently used (LFU) que consiste na substituição do bloco de cache que menos frequentemente foi referenciado.
Política de escrita 2.7.3.
O que a cache contém é a cópia de partes da memória principal. Existem políticas de escrita para salvaguardar a coerência entre o conteúdo da cache, e o conteúdo da memória principal, ou seja, de modo a garantir que as alterações que se façam ao conteúdo de uma posição de memória em cache, sejam salvaguardadas na memória principal.
2.7.3.1. Write-through
Uma cache que use a política de escrita write-through garante a coerência entre os dados dela mesma e da memória no próximo nível hierárquico recorrendo à escrita simultânea em cache e na memória do próximo nível. Sempre que um bloco de cache é
18
alterado, é enviada uma ordem de escrita desse bloco para que a memória principal correspondente seja também alterada. Como o acesso à memória principal é lento comparativamente com o acesso à cache, estes acessos constantes à memória atrasam o funcionamento da cache, o que se pode traduzir num atraso da performance do processador [24].
2.7.3.2. Write-back
A política de escrita write-back usa um método distinto que reduz o número de acessos à memória. A escrita em memória acontece apenas quando se pretende substituir um bloco da cache que tenha sido previamente alterado, ou seja, que já não esteja coerente com o bloco de memória do qual é cópia. O bloco da cache alterado é então escrito na memória para posteriormente ser substituído pelo bloco da memória pretendido [24].