Apesar de parecer simples como conceito, a memória de um computador exibe, talvez, a mais vasta gama de: tipos, tecnologia, organização, rendimento e custos, de entre todas as especificidades de um sistema de computação. Nenhuma tecnologia pode ser considerada como óptima em termos da satisfação dos requisitos de memória de um sistema de computação. Como consequência, o sistema de computação típico está equipada com uma hierarquia de sub-sistemas de memória, alguns internos ao sistema (directamente acessíveis ao processador) e outros externos (acessíveis ao processador através de um módulo de E/S).
Este capítulo põe a ênfase nos elementos da memória interna, enquanto que o capítulo 5 é dedicado à memória externa. Para começar, a primeira secção deste capítulo examina as características principais das memórias dos computadores. A seguir, olhamos para os sub-sistemas de semi-condutores da memória principal, o que inclui as memórias ROM, DRAM e SRAM. Na continuação, ficamos em posição de poder regressar à memória DRAM e olhar para arquitecturas de memória DRAM mais avançadas.
Começamos pelo mais visível dos aspectos da memória: a sua localização. Tal como o título deste capítulo e do próximo sugerem, há memória interna e memória externa a um computador. A memória interna é muitas vezes equiparada à memória principal. Mas há outras formas de memória interna. O processador necessita da sua própria memória local, sob a forma de registos (ver Figura 2.3). Além de que, como veremos, a unidade de controlo do processador que faz parte do processador pode também necessitar da sua própria memória interna. Adiaremos a discussão destes dois últimos tipos de memória interna para capítulos mais à frente. A memória externa consiste de dispositivos de armazenamento de memória, tais como discos e leitores de banda magnética, que estão acessíveis ao processador através de controladores de E/S.
Uma característica óbvia da memória é a sua capacidade. Esta, para a memória interna, é tipicamente expressa em termos de octectos (1 octeto = 8 bits) ou palavras. Tamanhos de palavra habituais são 8, 16 e 32 bits. A capacidade de memória externa é tipicamente expressa em termos de octetos.
Um conceito relacionado é a unidade de transferência. Para a memória interna a unidade de transferência iguala o número de linhas de dados que entram e saem dos módulos de memória. Isto é muitas vezes igual ao tamanho da palavra, mas pode não ser assim. Para clarificar este ponto, consideremos três conceitos relacionados com a memória interna:
Sob o ponto de visto do utilizador, as duas mais importantes características da memória são a capacidade e o rendimento. Três parâmetros de rendimento são usados:
onde
Tempo médio de leitura ou escrita de N bits
Tempo de acesso médio
Número de bits
Taxa de transferência em bits por segundo (bps)
Várias características físicas de armazenamento são importantes. Na memória volátil, a informação extingue-se naturalmente ou perde-se quando a fonte de alimentação é desligada. Na memória não volátil, a informação uma vez registada permanece sem deterioração até ser deliberadamente modificada; não é necessária fonte de alimentação para reter a informação. As memórias de superfície magnética são não voláteis. As memória de semi-condutores podem ser tanto voláteis como não voláteis. As memória não apagáveis não podem ser alteradas, excepto através da destruição da unidade de armazenamento. As memória de semi-condutores deste tipo são conhecidas por leitura apenas (ROM). Em termos práticos, é desejável que as memórias não apagáveis sejam, também, não voláteis.
Para as memórias de acesso-aleatório, a organização é um ponto chave no projecto. Por organização queremos significar o arranjo físico dos bits para formar palavras. O arranjo óbvio não é sempre usado, como será explicado aqui.
As restrições no projecto de memória de um computador podem ser sumarizadas em três questões: Quanta? Quão rápida? A que preço?
A questão da quanta está, de alguma forma, sempre em aberto. Se a capacidade existir, com toda a certeza haverá aplicações desenvolvidas para usá-la. A questão de quão rápida é, em certo sentido, mais fácil de responder. Para atingir um elevado rendimento, a memória deve estar ao nível do processador. Isto é, à medida que o processador executa instruções, gostaríamos de não ter de esperar por instruções ou por operandos. A questão final deve, também, ser apreciada. Para sistemas de interesse prático, o custo da memória deve ser razoável em relação aos outros componentes.
Tal como poderia ser esperado, há um compromisso entre as três características da memória, nomeadamente, custo, capacidade e tempo de acesso. Em cada instante, uma variedade de tecnologias são usadas para implementar os sistemas de memória. Neste espectro de tecnologias, podem considerar-se as seguintes relações:
A solução deste dilema não está dependente de um simples componente de memória ou da tecnologia, mas no emprego de um hierarquia de memória. Uma hierarquia típica é ilustrada na fig 4.1a. À medida que progredimos no sentido descendente na hierarquia, assistimos ao seguinte:
Assim, memórias, mais pequenas, mais dispendiosas e mais rápidas são complementadas por memórias, maiores, mais baratas e mais lentas. A chave para o sucesso desta organização está no último item, redução da frequência dos acessos. Examinaremos este conceito em detalhe quando discutirmos a cache, mais à frente neste capítulo, e a memória virtual, no capítulo 7, mas avançamos, aqui, com uma breve explicação .
Se a memória poder ser organizada de acordo com os itens (a) a (c) acima e se os dados e as instruções poderem ser distribuídos por toda a memória em consonância com (d), então parece ser claro, intuitivamente, que este esquema levará à redução do custo total ao mesmo tempo que se mantém um determinado nível de rendimento. Apresentamos um exemplo simples para ilustrar este ponto.
Suponha que o processador tem acesso a dois níveis de memória. O nível 1 contém 1000 palavras e tem tempo de acesso de s. O nível 2 contém 100 000 palavras e tem um tempo de acesso de s.
Assuma que, se uma palavra a que se pretende ter acesso está no nível 1, então o processador tem-lhe acesso directo. Se está no nível 2, então a palavra é primeiramente transferida para o nível 1, podendo o processador ter-lhe acesso por aí. Por simplicidade, vamos ignorar o tempo necessário para o processador determinar se a palavra está no nível 1 ou no nível 2. A figura 4.2 mostra o tempo de acesso médio total como uma função da percentagem do tempo que a desejada palavra está já no nível 1. Como pode ser visto, para percentagens elevadas de acessos no nível 1, o tempo de acesso médio total está muito mais perto do nível 1 do que do nível 2.
Este exemplo ilustra que, em princípio, a estratégia funciona. Funciona, na prática, se as condições de (a) a (b) forem aplicáveis. As figuras 4.3 e 4.4. mostram características típicas de sistemas de memória actuais alternativos. A figura 4.3 mostra que empregando uma variedade de tecnologias, existe um espectro de sistemas de memória que satisfazem (b) e (c) e a figura 4.4 confirma que a condição (a) é satisfeita. Felizmente, a condição (d) é, também, válida em geral.
A base para a validade da condição (d) é um princípio conhecido como localidade das referências[#!denn68!#]. Durante o curso da execução de um programa, as referências à memória com origem no processador, tanto para as instruções como para os dados, tendem a aglomerar-se. Os programas contém, tipicamente, um certo número de ciclos iterativos e sub-rotinas. Uma vez entrado num ciclo ou sub-rotina há repetidas referências a um pequeno conjunto de instruções. De forma similar, as operações em tabelas e listas envolvem acessos a agrupamentos de conjunto de palavras de dados. Em períodos de tempo longos os agrupamentos em uso mudam, mas em períodos de tempo curtos o processador está predominantemente a trabalhar com agrupamentos fixos de referências à memória.
Em concordância, é possível organizar os dados ao longo da hierarquia de tal forma que a percentagem de acessos sucessivos a cada nível mais abaixo é substancialmente inferior aos níveis mais acima. Considere o exemplo de dois níveis já apresentado. Deixe a memória de nível 2 conter todo o programa e dados. Os agrupamentos correntes podem ser colocados temporariamente no nível 1.
De tempos a tempos, um dos agrupamentos no nível 1 deverá ter de ser posto, de novo, na memória de nível 2 para deixar lugar para um novo agrupamento vindo do nível 1. Em termo médios, contudo, a maior parte das referências serão para instruções e dados contidos no nível 1.
Este princípio pode ser aplicado ao longo de mais do que dois níveis de memória. Considere a hierarquia mostrada na figura 4.1a. O tipo de memória, mais rápida, mais pequena e mais cara consiste nos registos internos do processador. Tipicamente, um processador contém uma escassa dezena desses registos, embora algumas máquinas contenham centenas de registos. Saltando por cima de dois níveis, a memória principal, também referenciada como memória real, é o sistema de memória principal do computador. Cada posição na memória principal tem um único endereço e a maior parte das instruções da máquina referem-se a um ou a mais endereços na memória principal. A memória principal é habitualmente estendida com uma pequena cache de velocidade superior. A cache não é habitualmente visível ao programador nem ao processador. É um dispositivo que serve de plataforma intermédia para o movimento de dados entre a memória principal e os registos do processador para melhorar o rendimento.
As três formas de memória que acabamos de descrever são, tipicamente, voláteis e empregam tecnologia de semi-condutores. O uso de três níveis explora a variedade de tipos de memória de semi-condutores que diferem em velocidade e custo. Os dados são armazenados mais permanentemente em dispositivos de memória externa de grande capacidade de armazenamento, dos quais os mais comuns são os discos magnéticos e bandas magnéticas. A memória externa, não volátil, é também referida como secundária ou auxiliar. Esta é usada para guardar programas e ficheiros de dados e são habitualmente visíveis ao programador apenas como ficheiros e registos, por oposição aos octetos e às palavras individuais. Os discos são também usados para fornecer uma extensão à memória principal conhecida como armazenagem virtual ou memória virtual que é discutida no capítulo 7.
Outras formas de memória podem ser incluídas na hierarquia. Por exemplo, computadores IBM de grande porte incluem uma forma de memória interna conhecida como Armazenamento Expandido. Esta usa uma tecnologia de semi-condutores que é mais lenta e menos cara do que a da memória principal. Falando em termos estritos, esta memória não se enquadra na hierarquia mas é um braço lateral: os dados podem ser movidos entre a memória principal e o armazenamento expandido mas não entre o armazenamento expandido e a memória externa. Outras formas de memória secundária incluem discos ópticos e dispositivos de memória em bolha. Finalmente, níveis adicionais podem ser adicionados, efectivamente, à hierarquia por software. Uma porção de memória principal pode ser usada como tampão para conter, temporariamente, dados que deverão ser lidos para disco. Esta técnica alguma vezes referida como cache de discos4.1, melhora o rendimento de duas formas;
O apêndice 4A examina as implicações no rendimento de uma estrutura de memória multi-nível.
A tabela 4.2 lista os tipos mais importantes de memórias de semi-condutores. O mais habitual é referido por memória de acesso-aleatório (RAM). Esta é, obviamente, uma má utilização do termo uma vez que todos os tipos listados na tabela são de acesso aleatório. Uma característica distintiva da RAM é que é possível, tanto ler dados da memória como fácil e rapidamente escrever novos dados na memória. Tanto a leitura como a escrita são realizáveis com base em sinais eléctricos.
A outra característica distintiva da RAM é ser volátil. A RAM tem de ser fornecida com uma alimentação constante. Se a alimentação for interrompida, então os dados perdem-se. Assim, a RAM só pode ser usada para armazenamento temporário.
A tecnologia RAM está dividida em duas tecnologias: estática e dinâmica. A RAM dinâmica é feita com células que armazenam os dados como carga em capacidades. A presença ou ausência de carga numa capacidade é interpretada como os binários 1 ou 0. Como as capacidades tem a tendência natural para se descarregarem, as RAM dinâmicas requerem um refrescamento periódico da carga para manter a armazenagem dos dados. Numa RAM estática valores binários são armazenados usando configurações tradicionais de portas-lógicas de flip-flops (ver apêndice A para uma descrição dos flip-flops). A RAM estática mantém os seus dados enquanto estiver ligada à alimentação.
Por outro lado, uma RAM dinâmica requer o suporte de circuito de refrescamento. Para grandes quantidades de memória, o custo fixo do circuito de refrescamento é mais do que compensador face ao custo variável mais pequeno das células RAM dinâmicas. Assim, as memórias RAM dinâmicas tendem a ser favorecidas quando há requisitos de grandes quantidades de memória. Um ponto final é que a RAM estática é em geral significativamente mais rápida que as RAM dinâmicas.
Em estreito contraste com a RAM está a memória só de leitura. Tal como o nome sugere, a ROM contém um padrão permanente de dados que não pode ser alterado. Enquanto é possível ler uma ROM, não é possível escrever lá novos dados. Um aplicação importante das ROM é a micro-programação, discutida na parte IV. Outras aplicações potenciais incluem:
Uma ROM é feita como qualquer outro circuito integrado, com os dados rigidamente fixados no integrado como resultado do processo de fabrico. Isto apresenta dois problemas:
Quando apenas é necessário um pequeno número de ROMs com um conteúdo de memória particular, uma alternativa menos dispendiosa é a ROM programável (PROM). Tal com a ROM, a PROM não é volátil e só pode ser escrita uma vez. Para a PROM, o processo de gravação é feito electricamente e pode ser realizado pelo fabricante ou pelo consumidor numa altura posterior ao processo original de fabricação. É necessário equipamento específico para a gravação ou processo de `` programação''. As PROMs oferecem flexibilidade e conveniência. A ROM permanece atractiva para a produção de grandes quantidades.
Uma outra variante das memórias só de leitura são as memórias para leitura a maior parte das vezes, úteis em aplicações em que as operações de leitura são substancialmente mais frequentes do que as operações de escrita mas em que é necessário armazenamento não volátil. Há três formas habituais de memória de leitura a maior parte das vezes: EPROM, EEPROM e memória relâmpago (flash).
A memória apagável programável só de leitura (EPROM) é de leitura e escrita eléctrica, tal como as PROM. Contudo, antes de uma operação de escrita, toda as células de armazenamento devem ser conduzidas para o mesmo estado inicial por exposição do integrado a radiações ultravioleta. Este processo de apagamento pode ser realizado repetidamente; cada apagamento pode levar tanto como 20 minutos para ser concluído. Assim, a EPROM pode ser alterada múltiplas vezes e, tal com a ROM e a PROM, mantém os seus dados por tempo virtualmente infinito. Para quantidades comparáveis de armazenamento, a EPROM é mais cara do que a PROM, mas tem a vantagem da capacidade para múltiplas actualizações.
Uma forma mais atractiva de memória de leitura a maior parte das vezes é a memória electricamente apagável só de leitura programável (EEPROM). Esta é uma memória de leitura a maior parte das vezes que pode ser gravada em qualquer momento sem apagar o conteúdo anterior; só o octeto ou os octetos endereçados são actualizados. A operação de escrita leva um tempo consideravelmente maior do que a operação de leitura, na ordem das várias centenas de micro-segundos por octeto. A EEPROM combina as vantagens da não volatilidade com a flexibilidade da actualização no lugar, usando o barramento de controlo convencional, endereços e linhas de dados. A EEPROM é mais cara do que a EPROM e também menos densa, comportando menos bits por integrado.
A mais recente forma de memória de semi-condutores é a memória relâmpago ( flash) (assim chamada por causa da velocidade com que pode ser reprogramada). Introduzida em primeiro mão nos meados dos anos 80, a memória relâmpago está a meio caminho entre a EPROM e a EEPROM tanto em custo como em funcionalidade. Tal como a EPROM, a memória relâmpago usa uma tecnologia de apagamento eléctrico. Uma memória relâmpago completa pode ser pode ser apagada em um ou poucos segundos, o que é muito mais rápido do que a EPROM. Cumulativamente, a memória relâmpago não oferece apagamento ao nível do octeto. Tal como a EPROM, a memória relâmpago usa apenas um transistor por bit e por isso atinge a elevada densidade (quando comparada com a EEPROM) da EPROM.
A figura 4.5 ilustra a operação de uma célula de memória. Muito habitualmente, a célula tem três terminais funcionais capazes de transportar sinais eléctricos.
O terminal de selecção, tal como o nome sugere, selecciona uma célula de memória para uma operação de leitura ou de escrita. O terminal de controlo indica a leitura ou a escrita. Para escrever, o outro terminal fornece um sinal eléctrico que ajusta o estado da célula a 1 ou a 0. Para ler, o terminal é usado para saída do estado da célula. Os detalhes da organização interna, funcionamento e temporização da célula de memória dependem da tecnologia do circuito integrado específico usado e está para além dos objectivos deste livro. Para os nossos propósitos, tomaremos isso como assumindo que as células individuais podem ser seleccionadas para operações de leitura e de escrita.
Na hierarquia de memória como um todo, vimos que há compromissos entre velocidade, capacidade e custo. Estes compromissos também existem quando consideramos a organização das células de memória e a lógica funcional de um integrado. Para as memórias de semi-condutores, um dos pontos chave do projecto é o número de bits de dados que podem ser lidos/escritos num dado instante. Num dos extremos está uma organização em que o arranjo físico das células na matriz é igual ao arranjo lógico (tal como é visto do processador) das palavras na memória. A matriz é organizada em W palavras de B bits cada. Por exemplo, um integrado de 16-Mbits pode ser organizado em 1M palavras de 16-Mbits. No outro extremo está a organização chamada de 1-bit por integrado, na qual os dados são lidos/escritos um bit de cada vez. Ilustraremos a organização dos integrados de memória com uma DRAM; A organização da ROM é similar, embora mais simples.
A figura 4.6 mostra a organização típica de uma DRAM de 16-Mbits. Neste caso, quatro bits são lidos ou escritos em cada momento. Logicamente, a matriz de memória é organizada como quatro matrizes quadradas de 2048 por 2048 elementos. Vários arranjos físicos são possíveis. Em qualquer dos casos, os elementos da matriz são ligados tanto por linhas horizontais (fiadas) como por linhas verticais (colunas). Cada linha horizontal liga-se ao terminal Select de cada célula na respectiva fiada; cada linha vertical liga-se ao terminal de Data-In/Sense de cada célula na respectiva coluna.
As linhas de endereços disponibilizam o endereço da palavra a ser seleccionada. Um total de linhas são necessárias. No nosso exemplo, são necessárias 11 linhas para seleccionar uma das 2048 fiadas.
Estas 11 linhas vão alimentar um descodificador de fiadas que possui 11 linhas de entrada e 2048 linhas para saída. A lógica do descodificador activa simplesmente uma das 2048 saídas dependendo do padrão de bits nas () linhas de entrada.
11 linhas de endereços adicionais seleccionam uma das 2048 colunas de quatro bits por coluna. Quatro linhas de dados são usadas para a entrada e saída de quatro bits de e para o tampão de dados. Na entrada (escrita) o condutor do bit em cada linha é levado a 1 ou 0 de acordo com o valor da linha de dados correspondente. Na saída (leitura) o valor de cada bit é passado através de um sensor amplificador e apresentado as linhas de dados.
A linha da fiada selecciona a fiada de células usada na leitura ou escrita.
Uma vez que só são lidos/escritos quatro bits nesta DRAM, tem de haver múltiplas DRAMs ligadas ao controlador da memória de forma a ler/escrever uma palavra ou um dado no barramento.
Notar que há apenas 11 linhas de endereço (A0-A11), metade do número que seria esperado para uma matriz de 2048 x 2048. Isto faz-se para poupar no número de pinos. As 22 linhas de endereços necessárias são passadas através de lógica escolhida externa ao integrado e multiplexada em 11 linhas de endereços. Primeiro, 11 linhas são passadas ao integrado para definir os endereços das fiadas da matriz e então os outros 11 sinais de endereços são apresentados como endereços de colunas. Estes sinais são acompanhados pela escolha dos sinais de endereços das fiadas (RAS) e endereços das colunas (CAS) para fornecer temporização ao integrado.
Como efeito lateral, o endereçamento multiplexado mais o uso de matrizes quadradas resulta na quadriplicação do tamanho da memória com cada nova geração de integrados de memória. Um pino mais dedicado ao endereçamento duplica o número de fiadas e de colunas e consequentemente o tamanho da memória no integrado cresce por um factor de 4. Assim, temos vindo a seguir as seguintes gerações, a uma taxa, grosso modo, de um cada três anos: 1K, 4K, 16K, 64K, 256K, 1M, 4M, 16M.
A figura 4.6 também mostra a inclusão de um circuito de refrescamento. Todas as DRAM requerem uma operação de refrescamento. Uma técnica simples de refrescamento inibe, para todos os efeitos, o integrado DRAM enquanto todas as células de dados são refrescadas. O contador de refrescamento prossegue através de todos os valores das fiadas. Por cada fiada, as linhas de saída do contador de refrescamento vão alimentar o descodificador de fiadas e activar a linha de RAS. A consequência, disto, é cada célula na fiada ser refrescada.
A figura 4.7a mostra o exemplo de um invólucro de uma EPROM, que é um circuito integrado de 8M-bits organizado em 1M x 8. Neste caso, a organização faz-se numa palavra por integrado. O invólucro inclui 32 pinos, que é um dos tamanhos estandartizados de invólucros de integrados. Os pinos suportam as seguintes linhas de sinal:
Esta organização é apropriada enquanto o tamanho da memória igualar o número de bits por integrado. No caso de ser requerido uma quantidade de memória superior, é necessário uma configuração de integrados. A figura 4.9 mostra a, possível, organização de uma memória consistindo de 1M palavras, com 8 bits por palavra. Neste caso temos quatro colunas de integrados, cada columa contém 256K palavras arranjadas como na figura 4.8. Para 1M palavras, são necessárias 20 linhas de endereços. Os 18 bits menos significativos são dirigidos para todos os 32 módulos. Os 2 bits de ordem superior entram num módulo lógico de selecção de grupos que emite o sinal de habilitação de integrado para uma das quatro colunas de módulos.
A figura 4.10 ilustra em termos gerais a forma como o processo decorre. Quando os dados são lidos para a memória, um cálculo, descrito como uma função , é efectuado nos dados para gerar um código. Tanto o código como os dados são salvaguardados. Assim, se um palavra de M-bits for guardada e o código for de bits, então o tamanho efectivo das palavras guardadas é bits.
Quando a palavra previamente guardada é extraída, o código é usado para detectar e se possível corrigir erros. Um novo conjunto de bits de código é gerada a partir dos bits e comparado com os bits extraídos. A comparação produz um de três resulatdos:
O mais simples dos códigos de correcção de erros é o código de Hamming inventado por Richard Hamming dos Laboratórios Bell. A figura 4.11 usa diagrams de Venn para ilustrar o uso deste código em palavras de 4-bits (M=4). A intersecção de três círculos define sete compartimentos. Os 4 bits de dados são atribuídos aos compartimentos interiores (Figura 4.11a). Os compartimentos restantes são preenchidos com o que se chama bit de paridade. cada bit de paridade é escolhido de forma a que o número total de 1s em cada círculo é par (Figura 4.11b). Assim, uma vez que o círculo A inclui três dados a 1, o bit de paridade nesse círculo é ajustado a 1. Agora, se um erro modificar um dos bits de dados (Figura 4.11c) é facilmente detectado. Testando os bits de paridade, são encontradas discrepâncias no círculo A e no círculo C, mas não no círculo B. Só um dos setes compartimentos está em A e em C, mas não está em B. O erro pode por isso ser corrigido através da alteração daquele bit.
A figura 4.16 esquematiza a estrutura de um sistema cache/memória-principal. A memória principal consiste de endereços de palavras, tendo cada palavra um endereço único de n-bits. Para efeitos de reconhecimento, esta memória é considerada como consistindo de um número fixo de blocos cada um com palavras. Isto é, há blocos. A cache consiste de C entradas de palavras cada e o número de entradas, ou linhas é considerado inferior ao número de blocos na memória. A todo o momento, alguns sub-conjuntos de blocos de memória residem nas entradas na cache. Se for lida uma palavra num bloco de memória, esse bloco é transferido para uma das entradas na cache. Uma vez que há mais blocos do que entradas, uma entrada individual não pode ser única e permanentemente dedicada a um bloco particular. Assim, cada entrada inclui uma etiqueta que identifica qual o bloco que está no momento a ser armazenado. Esta etiqueta é, habitualmente, uma porção dos endereços da memória principal, tal como é descrito mais tarde nesta secção.
A figura 4.17 ilustra a operação de leitura. O processador gera o endereço, RA, da palavra a ler. Se a palavra está contida na cache, é enviada para o processador, tal como é descrito mais tarde nesta secção. Doutra forma, o bloco contendo a palavra é carregado para a cache e a palavra entregue ao processador.
O primeiro elemento, tamanho da cache, já foi discutido. Nós gostaríamos que o tamanho da cache pudesse ser suficientemente pequeno para que o custo médio total por bit rondasse o da memória principal tomada isoladamente e suficientemente grande parque a o tempo de acesso médio total se aproximasse do da cache isoladamente.
Há muitas outras motivações para a minimização do tamanho da cache.
Quanto maior a cache, maior o número de portas lógicas envolvidas no endereçamento da cache.
O resultado é que as caches grandes tendem a ser ligeiramente mais lentas que as pequenas - mesmo quando construídas com as mesma tecnologia de integrados e postas na mesmo localização tanto no integrado como na placa mãe.
O tamanho da cache está também limitado pela superfície disponível na placa e no integrado.
No Apêndice 4A chamamos a atenção para um certo número de estudos que sugerem que tamanhos da cache entre 1K e 512K palavras poderiam ser considerados óptimos.
Porque o rendimento da cache é muito sensível à natureza da carga, é impossível chegar a um tamanho 'óptimo' para o tamanho da cache.
onde
i = número da linha de cache
j = número do bloco da memória principal
m = número de linhas na cache
A função de correspondência é facilmente realizável usando o endereço. Para efeitos de acesso à cache, cada endereço da memória principal pode ser visto como se consistindo em três campos.
Os bits identificam uma única palavra ou octeto dentro de um bloco da memória principal; nas máquinas mais recentes, o endereço está ao nível do octeto. Os restantes bits especificam um dos blocos de memória principal. A lógica da cache interpreta estes bits como um etiqueta de bits (parte mais significativa) e um campo para linha de bits. Isto mais tarde identifica um dos linhas de cache. O efeito desta correspondência é que aos blocos de memória são atribuídas as linhas de cache da forma como se segue:
Linha de cache | Blocos de memória atribuídos |
0 | |
1 | |
. | |
. | |
. | |
m -1 |
Assim, o uso de uma porção do endereço como um número de linha oferece uma correspondência única de cada bloco de memória principal na cache. Quando um bloco é lido para a sua linha atribuída, é necessário etiquetar os dados para distingui-los dos outros blocos que podem encaixar naquela linha. Os bits mais significativos servem para isso.
A figura 4.19 mostra o nosso exemplo usando um sistema de correspondência directa4.2. No exemplo, i = j módulo .
Linha de cache | Blocos de memória atribuídos |
0 | |
1 | |
. | . |
. | . |
. | . |
3FFF |
É de notar que dois blocos com uma correspondência no mesmo número de linha nunca têm o mesmo número de etiqueta. Assim, os blocos têm números de etiqueta respectivamente.
Voltando à figura 4.18, uma operação de leitura funciona da seguinte maneira. Ao sistema de cache é apresentado um endereço de 24-bits. Os 14-bits do número da linha são usados como um índice na cache para ter acesso a uma linha particular. Se a etiqueta de 8-bits igualar o número de etiqueta presentemente guardado naquela linha, então o número de 2-bits da palavra é usado para escolher um dos quatro octetos naquela linha. Caso contrário, os 22-bits da etiqueta mais o campo da linha são usados para extrair um bloco da memória principal. O endereço efectivo que é usado para a extracção são os 22-bits da etiqueta mais a linha que são concatenados com dois bits a 0, de forma a que os quatro octetos sejam extraídos nos limites de um bloco.
A técnica de correspondência directa é simples e de realização pouco onerosa. A desvantagem principal é que há uma localização fixa na cache para um determinado bloco. Assim, se num programa acontecer uma referência repetida a palavras pertencentes a dois diferentes blocos que correspondem à mesma linha, então os blocos serão continuamente trocados na cache e o taxa de sucesso será baixa.
A figura 4.21 mostra o nosso exemplo usando correspondência associativa. Um endereço na memória principal consiste de uma etiqueta de 22-bits e um número de octeto em 2-bits.
A etiqueta de 22-bits deve ser guardada conjuntamente com o bloco de 32-bits de dados para cada linha na cache.
Com a correspondência associativa é flexibilizada a substituição de blocos quando um novo bloco é trazido para a cache. Os algoritmos de substituição, discutidos mais tarde nesta secção, são desenhados para maximizar a taxa de sucesso. A principal desvantagem da correspondência associativa está na complexidade dos circuitos lógicos necessários para examinar as etiquetas de todas as linhas da cache em paralelo.
m = v * k
i = j módulo v
onde
i = número do jogo na cache
j = número do bloco da memória principal
m = número de linhas na cache
Com a correspondência em jogos associativos, o bloco pode ter uma correspondência com qualquer uma das linhas do jogo . Neste caso, a lógica de controlo, simplesmente, interpreta um endereço da memória como constituído por três campos: etiqueta, jogo e palavra. Os bits do jogo especificam um dos jogos. Os bits dos campos da etiqueta e do jogo especificam um dos blocos de memória principal. A figura 4.22 ilustra a lógica de controlo da cache.
A figura 4.23 mostra o nosso exemplo usando correspondência em jogos associativos com duas linhas por jogo, designada por jogo associativos de duas vias. Os 13-bits do número do jogo identificam um conjunto único de duas linhas dentro da cache. Também refere o número do bloco na memória principal, módulo . Este determina a correspondência dos blocos em linhas. Assim, os blocos da memória principal estabelecem a correspondência com o jogo 0 da cache. Qualquer um daqueles blocos pode ser carregado para uma das duas entrada do jogo. É de notar que dois blocos que residem no mesmo jogo nunca poderão ter o mesmo valor na etiqueta. Para uma operação de leitura, os 13-bits do número do jogo são usados para determinar qual dos jogos de duas linhas deverá ser examinado. Ambas as linhas no mesmo jogo são examinadas para saber se há alguma com o mesmo número da etiqueta do endereço a que se pretende ter acesso.
No caso extremo de , a técnica de jogos associativos reduz-se à correspondência directa e para reduz-se à correspondência associativa. O uso de duas linhas por jogo é a mais comum das organizações por jogos associativos. Melhora significativamente a taxa de sucesso em relação a taxa de correspondência directa. Jogos associativos de quatro vias apenas introduzem um melhoramento adicional modesto para um relativamente modesto custo adicional[#!mayb84!#,#!hill89!#]. Aumentos superiores do número de linhas por jogo têm efeitos desprezáveis.
A técnica mais simples de todas é chamada escrita-imediata ( write through). Usando esta técnica, todas as operações de escrita são feitas na memória assim como na cache, assegurando que a memória principal está sempre válida. Qualquer outro módulo cache-processador pode monitorizar o tráfego para a memória principal para manter consistência com a sua própria cache. A desvantagem principal desta técnica é que é gerado tráfego substancial para a memória o que pode criar um engarrafamento.
Uma técnica alternativa, conhecida como escrita adiada ( write back), minimiza as escritas na memória. Com a escrita adiada, as actualizações são feitas apenas na cache. Quando ocorre uma actualização, faz-se uma marca num bit de ACTUALIZAÇÃO (UPDATE) associado com a entrada. Então, quando um bloco é substituído é escrito posteriormente na memória principal se, e só se, o bit de ACTUALIZAÇÃO estiver marcado. O problema com a escrita adiada é que existem porções de memória invalidadas e, por isso, os acessos através dos módulos de E/S só podem ser autorizados com o consentimento da cache. Isto obriga a circuitos complexos e a um potencial congestionamento. A experiência tem mostrado que a percentagem das referências à memória que são escritas é da ordem dos 15 porcento [#!smit82!#].
Na organização de um barramento em que mais do que um dispositivo (tipicamente um processador) tem cache e a memória é partilhada é introduzido um novo problema. Se os dados numa das caches for alterada, isto invalida não apenas a palavra correspondente na memória principal mas, também, a mesma palavra noutras caches (se por acaso alguma das outras caches contiver a mesma palavra). Mesmo quando se usa uma política de escrita-imediata, as outras podem conter dados inválidos. Um sistema que evita este problema é dito manter coerência de cache. Possíveis abordagens a coerência da cache incluem
A relação entre o tamanho do bloco e a taxa de sucesso é complexa, estando dependente nas características de localidade de um programa particular e, em definitivo, nenhum valor óptimo foi encontrado. Um tamanho de 4 a 8 unidades endereçáveis (palavras ou octetos) parece estar razoavelmente próximo do óptimo [#!smit82a!#,#!przy88!#,#!przy90!#].
Quando, originalmente, se introduziram as caches, os sistemas típicos tinham apenas uma cache. Mais recentemente, o uso de múltiplas caches transformou-se na norma. Dois aspectos do projecto deste tópico dizem respeito ao número de níveis de cache e ao uso de caches unificadas versus caches repartidas.
À medida que a densidade da lógica foi crescendo, tornou-se possível ter a cache no integrado do processador: on-chip (cache interna). Quando comparada com a cada acessível através do barramento externo, a cache interna reduz a actividade externa e dessa forma apressa os tempos de execução e aumento o rendimento global do sistema. Quando as instruções ou dados pretendidos são encontrados na cache interna, os acessos ao barramento são eliminados. Por causa dos muito curtos caminhos de dados internos ao processador, quando comparados com o comprimento dos barramentos, os acessos à cache interna podem completar-se apreciavelmente mais depressa do que, mesmo, com ciclos de barramento de zero estado de espera. Além de que, durante aquele período, o barramento fica livre para suportar outras transferências.
A inclusão da cache interna deixa em aberto a questão de saber se continua a ser desejável uma cache fora do integrado do processsador, ou externa. Tipicamente, a resposta é sim e a maior parte dos projectos actuais incluem ambas as caches, interna e externa. A organização resultante é conhecida como uma cache a dois níveis, com a cache interna designada por nível 1 (L1) e a cache externa designada por nível 2 (L2). A razão para a inclusão de uma cache L2 é a seguinte. Se não houver cache L2 e o processador fizer um pedido de acesso a uma posição de memória que não está na cache de nível 1, então o processador tem de fazer um acesso à memória DRAM ou ROM através do barramento. Devido à baixa velocidade do barramento e aos baixos tempos de acesso à memória, isto resulta num rendimento pobre. Por outro lado, se for usada uma cache L2 em SRAM, então, a informação que falha com frequência pode ser rapidamente extraída. Se a SRAM for suficientemente rápida para poder igualar a velocidade do barramento, então pode fazer-se um acesso aos dados usando transacções em zero-estados de espera, o mais rápido dos tipos de transferência pelo barramento.
O potencial de poupança devida ao uso de cache L2 depende da taxa de sucesso tanto das caches L1 como de L2. Vários estudos têm mostrado que, em geral, o uso de uma cache de segundo nível melhora, efectivamente, o rendimento (e.g, ver [#!azim92!#,#!novi93!#]).
Há um série de potenciais vantagens numa cache unificada:
A figura 4.24 mostra uma versão simplificada da organização do Pentium que destaca a colocação das duas caches. A parte mais importante das unidades de execução são duas unidades de lógica e de aritmética inteira que podem executar em paralelo e uma unidade de vírgula flutuante com os seus próprios registos e componentes próprios de multiplicação, soma e divisão. A cache de dados alimenta tanto as operações inteiras como em vírgula flutuante. A cache de dados é de porta-dupla. As duas portas de 32-bits podem ser usadas para ligar, separadamente, às duas unidades inteiras da ALU e podem ser combinadas para uma ligação de 64-bits à unidade de vírgula flutunate. A cache de instruções, apenas de leitura, alimenta um tampão para pré-extracção; a operação de encadeamento de instruções é discutida no capítulo 13.
A figura 4.25 representa os elementos chave da cache interna de dados. Os dados na cache consistem em 128 jogos de 2 linhas cada. Esta é logicamente organizada em duas vias de 4KBytes. Associada com cada entrada está uma etiqueta e dois bits de estado; estes estão logicamente organizados em dois directórios, de forma a que há uma entrada no directório para cada linha da cache. A etiqueta corresponde aos 20 bits mais significativos do endereço da memória dos dados guardados na linha correspondente. O controlador de cache usa um algoritmo de substituição LRU e um simples bit (LRU) está associado a cada jogo de duas entradas.
A cache de dados emprega uma política de escrita adiada: os dados são escritos na memória principal quando são descartados da cache, apenas, se antes tiverem sido actualizados. O processador Pentium pode ser dinamicamente configurado para suportar cache de escrita imediata.
O processador Pentium suporta o uso de uma cache externa de nível 2. Esta cache pode ser de 256 ou 512 KBytes, usando 32, 64, ou 128 octetos por linha. A cache externa é em jogos associativos de duas vias.
A cache de dados inclui dois bits de estado por etiqueta, de forma a que cada linha pode estar num de quatro estados:
A tabela 4.5 sumariza o significado dos quatro estados. Comecemos por considerar a acção no caso de um único processador4.3.
Agora suponhamos que uma das unidades de execução escreve nesta linha. A linha na cache L1 deverá ser actualizada. Neste ponto, a linha na cache L2 fica obsoleta. Para evitar a inconsistência da cache, a primeira vez que a linha é actualizada na cache L1, a operação de escrita propaga-se à cache L2 e o estado da linha em L1 passa para o (E) exclusiva. Depois disso, uma actualização posterior da linha em L1 altera o estado para (M) modificada. Nas actualizações posteriores, a linha mantém-se no estado M e para todas aquelas actualizaçõee subsequentes, não há nenhuma transferência para L2. Assim, isto é conhecido como uma política de escreve uma vez ( write-once. Finalmente, quando é necessário substituir uma linha na cache L1, esta, se está no estado S ou E, não é necessário propagar a escrita para o exterior. Se a linha está no estado M, o seu valor reverte para a cache L2 e seguidamente descartada da cache L1. Quando novos dados são lidos na linha L1, a linha é marcada com o estado (S), como antes.
A operação do ponto de vista da cache L2 é mais complexa. Quando uma linha é inicialmente lida para as caches L1 e L2, a linha da cache L2 é marcado com o estado (E), o que indica que os dados são exclusivos da cache L2 e do seu processador e cache L1 associados. Quando uma ocorre uma escrita uma vez, a cache L2 actualiza a linha e passa-a ao estado (M). A cache L2 não será avisada das subsequentes actualizações desta linha pela cache L1. Em consonância, se um outro senhor do barramento ( bus master) tentar ler os dados guardados numa linha L2 que está no estado M, a cache L2 faz o senhor de barramento retroceder ( back-off) e passa o endereço pretendido para o processador. O processador Pentium provoca um ciclo de escrita-adiada para actualizar a memória principal. A cache L2 permite, então, que o senhor do barramento efectue a respectiva operação de leitura.
Se um outro dono de barramento tenta escrever dados que estão numa linha L2 no estado M, então de novo, a lógica da cache L2 bloqueia, temporariamente, a acção. A cache L2 tem de assegurar que as operações são executadas na sequência apropriada. A cache L2 não pode descartar, simplesmente, a sua linha e deixar que a operação prossiga, porque o outro senhor do barramento pode alterar um porção da linha diferente da que tinha sido modoficada na linha da cache L2. Por isso, a linha L2 deve ser escrita para memória antes de a outra escrita se efective. Mas, antes que isso possa acontecer, a cache L2 tem de determinar se a linha correspondente na linha da cache L1 tinha sido actualizada desde a escrita uma vez. Assim, a sequência correcta de passos é a seguinte:
A tabela 4.7 mostra esta evolução. O modelo originaal, o 601, inclui uma cache simples código/dados de 32KOctetos em jogos associativos de 8-vias. O 603 emprega um desenho RISC mais sofisticado mas tem uma cache mais pequena: 16KOctetos em caches separadas para instruções e para dados, ambas usando uma organização em jogos asscociativos de 2-vias. O resultado é que o 603 atinge aproximadamente o mesmo rendimento que o 601 a mais baixo custo. O 604 e 620 duplicaram, cada um, o tamanho das caches dos modelos precedentes.
A figura 4.26 fornece uma vista simplificada da organização do PowerPc 620, realçando a colocação das duas caches; a organização dos outros membros da família é semelhante. As unidades de execução nucleares são três unidades de aritmética e lógica, que podem trabalhar em paralelo, e uma unidade de vírgula flutuante com os seus próprios registos e os seus próprios componentes para multiplicação, adição e divisão. A cache de dados alimenta tanto as operações inteiras como em vírgula-flutuante, através da unidade de carrega/armazena. A cache de instruções que é apenas de leitura, alimenta a unidade de instruções, cuja operação é discutida no capítulo 12.
As caches internas são em jogos associativos de oito-vias e usam o protocolo de coerência MESI. O protocolo foi extendido para incluir um novo estado chamado Atribuído (A) ( Alocated). Este estado é usado quando um bloco de dados numa linha é enviado para o exterior e substituído. O estado é A até que os dados antigos sejam salvaguardados e os novos dados trazidos para a cache. Nesse momento, o estado passaa para S ou E, conforma as circunstâncias (Figura 4.27).
Vimos que uma forma de atacar o problema do rendimento das DRAM da memória principal foi inserir um ou mais níveis de cache SRAM de alta-velocidade entre a DRAM da memória principal e o processador. Mas as SRAM são muito mais dispendiosas que a DRAM e a expansão do tamanho da cache a partir de um certo ponto produz uma diminuição proporcional ao crescimento.
Nos último anos, têm vindo a ser explorados um certo número de melhoramentos à arquitectura básica das DRAM e, alguns deles, estão agora no mercado. Não é claro neste ponto se algum dos melhoramento irá emergir como a única norma DRAM ou se sobrevivirão várias. Esta secção oferece uma visão geral destas novas tecnologias.
A figura 4.28 ilustra uma versão de 4-Mbit da EDRAM. A cache SRAM guarda o conteúdo total da última fiada lida que consiste em 2048 bits, ou 512 porções de 4-bits. Um comparador guarda o valor de 11-bits do mais recente endereço de fiada seleccionado. Se o próximo acesso for à mesma fiada, então o acesso apenas necessita de ser feito à cache SRAM
A EDRAM inclui outras possibilidades que melhoram o rendimento. As operações de refrescamento podem ser conduzidas em paralelo com as operações de leitura da cache, minimização do tempo em que o integrado está indisponível devido ao refrescamento. É também de notar que o caminho de leitura, desde a fiada na cache até à porta de saída, é independente do caminho de escrita do módulo de E/S até aos sensores amplificadores. Isto torna possível que um acesso subsquente de leitura à cache possa ser satisfeito em paralelo com a conclusão da operação de escrita.
Estudos feios pela Ramtron indicam que a EDRAM funciona tão bem, ou melhor, que uma DRAM convencional com uma maior SRAM exterior (à DRAM).
A cache DRAM (CDRAM) desenvovida pela Mitsubishi [#!hida90!#] é semelhante à EDRAM. A CDRAM inclui uma cache SRAM maior do que a EDRAM (16 vs 2kb).
A SRAM da CDRAM pode ser usada de duas formas. Na primeirta, esta pode ser usada como uma cache verdadeira, consistindo de um certo número de linhas de 64-bits. Isto contarsta com EDRAM, na qual a cache SRAM apenas contém um bloco, nomeadamentem, o da fiada a que mais recentemente foi feito o acesso. O modo cache dos CDRAM é efectivo para os acessos aleatórios habituais à memória .
A SRAM da CDRAM pode também ser usada como um tampão para suportar o acesso em série a um bloco de dados. Por exemplo para refrescar um ecrã bit-mapped, a CDRAM pode pré-extrair os dados da DRAM para o tampão da SRAM. Os acessos subsquentes ao integrado tem como resultado o acesso exclusivo a SRAM.
Ao contrário das DRAM típicas que são assíncronas, a SDRAM troca dados com o processador sincronizada por um sinal de relógio externo que corre à velocidade do barramento memória/processador sem impôr estados de espera.
Numa DRAM típica, o processador apresenta endereços e níveis de controlo à memória, indicando que um determinado conjunto de dados de uma localizaçãoo particular na memória deveriam ser lidos ou escritos na DRAM. Depois do retardamento provocado pelo tempo de acesso, a DRAM lê ou escreve os dados. Durante a demora do tempo de acesso, a DRAM executa várias funções interns, tais como a activação das fiadas e linhas de colunas, de elevada capacidade eleéctrica, opreendendo os dados e encaminhando-os para fora através dos tampóes de saída. O processador tem, simplesmente, de esperar durante aquele intervalo, o que reduz o rendimento do sistema .
Com acessos síncronos, A DRAM move os dados para dentro e para fora sob o controlo do relógio do sistema. O processador ou outro dono do barramento envia instruções e informação endereçamento que é agarrada pelo DRAM. O integrado DRAM responde a seguir a um certo número de ciclos de relógio. Entretanto o dono pode realizar outras tarefas, em segurança, enquanto a SDRAM está a processar o pedido.
A figura 4.29 mostra a lógica interna da SDRAM. A SDRAM emprega um modo rajada para eliminar o tempo de estabelecimento do endereço e os tempos de pré-carga que se seguem ao primeiro acesso. No modo rajada, uma série de bits de dados podem ser postos rapidamente cá fora, ao ritmo do relógio, a seguir ao acesso do primeiro bit. Este modo é útil quando todos os bits a que se pretende ter acesso fazem parte de uma sequência e na mesma fiada da matriz do acesso inicial.
Adicionalmente, a SDRAM tem uma arquitectura interna de duplo-banco que aumenta as oportunidades para o paralelismo no integrado.
O registo de modo e a lógica de controlo associada é uma outra característica que distingue as SDRAMs das DRAMs convencionais. O registo de modo especifica o comprimento da rajada que é o número de unidades separadas de dados que, sincronamente, alimentam o barramento. O registo, também, permite ao programador ajustar a o tempo que decorre entre a recepção do pedido de leitura e o início da transferêcnia dos dados.
A SDRAM funciona melhor quando transfere grandes quantidades de dados em série, tal como é o caso de aplicações de processamento de texto, folhas de cálculo e multi-média.
O barramento especial da RDRAM despacha endereços e informação de controlo usando um protocolo assíncromo orientado ao bloco. Depois de de 480 nano-segundos iniciais de tempo de acesso, esta é capaz de uma taxa de transferência de dados de 500 Mbps. O que torna esta possível velocidade é o próprio barramento que define impedâncias, impulsos de relógio e e sinais de forma muito precisa. Em vez de ser controlada pelos sinais explícitos de RAS,CAS, R/W e CE, usados na DRAM convencionais, uma RDRAM obtém um pedido de memória através do barramento de alta-velocidade. Este pedido contém o endereço pretendido, o tipo de operação e o númeor de octetos a operar.
A RamLink é um interface de memória com ligações ponto a ponto organizadas em anel (figura 4.30a) O tráfego no anel é gerido por um controlador de memória que envia mensagens para os integrado DRAM que actuam como nodos do anel. Os dados são trocados sob a forma de pacotes (figura 4.30b).
Os pacotes pedidos iniciam transaccões de memória. São enviados pelo controlador e contêm um cabeçalho com o comando, o endereço, o somatório para teste de erros e no caso de um comando de escrita, os dados a escrever. O cabeçalho consiste no tipo, no tamanho e na informação de controlo e contém, ou um tempo específico para resposta, ou o tempo máximo permitido para o servo responder. A informação de controlo inclui um bit que indica se os pedidos subsequentes são para endereços sequenciais. Podem ser activadas simultaneamente até quatro transações por dispositivo; assim, todos os pacotes têm dois bits ID de identificação da transação para estabelecer a correspondência exacta entre pacotes de pedidos e pacotes de resposta.
Quando a leitura se faz com sucesso, a DRAM serva envia um pacote de resposta que inclui os dados lidos. Qaundo a leitura é mal sucedida a DRAM serva emite um pacote de retransmissão que indica quanto tempo adicional é necessário para completar a transação.
A pujança da RamLink resulta de uma abordagem asente numa arquitectura escalável que suporta um pequeno número ou grande número de DRAM que não dita a estrutura interna da DRAM. O arranjo em anel da RamLink é desenhado para coordenar a actividade de muitas DRAM e forncer um interface eficiente para o controlador de memória.