Capítulo 4 – Memória Prof. Romis Attux EA075 – 2015 Obs: Os slides são parcialmente baseados nos dos autores do livro texto e do Prof. Levy Boccato Partes e Ponderações Um sistema embarcado possui três grandes categorias de funcionalidades: processamento, armazenagem e comunicação. “Processamento” abrange a atuação no sentido de modificar dados. “Armazenagem” corresponde à tarefa de guardar dados para uso posterior. “Comunicação” diz respeito à transferência de dados. Trataremos neste capítulo do problema de armazenagem, partindo de conceitos de memória. Aspectos Básicos Uma memória é capaz de armazenar uma grande quantidade de bits. Basicamente, pode-se pensar em m palavras com n bits cada, num total de m*n bits, como mostrado abaixo. Aspectos Básicos Uma memória desse tipo, “m por n”, pode ser vista na próxima figura em mais detalhe. Note que essa memória precisa de log2(m) bits para especificar o endereço de uma palavra e terá n bits para entrada e saída de dados. Por exemplo, uma memória 4096 por 8 precisará de 12 bits de endereçamento e 8 bits de dados. Aspectos Básicos Leitura e Escrita Ler a memória significa acessar o conteúdo de dados associado a determinado endereço (acessar os dados contidos numa palavra). Escrever corresponde à operação de inserir dados no endereço correspondente a uma palavra. Um acesso à memória pode ser tanto para escrita quanto para leitura. Uma memória que pode ser lida e escrita requer um sinal de controle, r/w, que indica a operação desejada. Também é usual que haja um sinal de enable. Tipos de Memória Classicamente, divide-se a memória em dois tipos fundamentais: ROM e RAM. Uma memória ROM (read-only memory) é, historicamente, uma memória que o processador apenas lê, e que é não-volátil (guarda informação sem estar ligada a uma fonte de energia). Uma memória RAM (random-acess memory) é, historicamente, vista como uma memória em que o processador pode ler e escrever com certa agilidade, mas que perde seu conteúdo se não alimentada. Hibridização Atualmente, esses conceitos não são mais tão cristalizados. É possível escrever em memórias ROM via processador (EEPROM, memória Flash) e existem RAMs não-voláteis. Discutiremos então os tipos de memória em termos de sua capacidade de escrita e da permanência do conteúdo armazenado. Possibilidade de Escrita Todas as memórias podem ser lidas e escritas. Discutiremos aqui os diferentes tipos de escrita em memórias, que definem conceitos fundamentais. Num extremo, temos as memórias em que o processador escreve com toda agilidade simplesmente especificando endereço, dados e sinais de controle. Num meio-termo, temos memórias que podem sofrer escrita pelo processador, mas num ritmo mais lento. Por fim, temos memórias que só podem ser escritas por um aparato especial denominado “programador”. Retenção dos Dados Por outro lado, temos a questão da duração dos dados armazenados. No nível mais baixo nesse quesito estão as memórias que começam a ter sua informação perdida quase imediatamente após o processo de escrita (e precisam de “refreshes” constantes). Em seguida há memórias que perdem seu conteúdo assim que deixam de ser alimentadas. Depois há memórias que podem manter seu conteúdo por dias, meses ou anos após o desligamento de sua fonte de alimentação. Por fim, existem memórias que virtualmente nunca perdem seu conteúdo (exceto em caso de dano ao chip). Categorias Volátil / Não-Volátil Programável no sistema / Nãoprogramável no sistema. Esses conceitos terminam por estabelecer um compromisso (tradeoff). permanence Storage Categorias Mask-programmed ROM OTP ROM Life of product EPROM Tens of years Battery life (10 years) Ideal memory EEPROM FLASH NVRAM Nonvolatile In-system programmable SRAM/DRAM Near zero Write ability During fabrication only External programmer, one time only External programmer, 1,000s of cycles External programmer OR in-system, 1,000s of cycles External programmer OR in-system, block-oriented writes, 1,000s of cycles Write ability and storage permanence of memories, showing relative degrees along each axis (not to scale). In-system, fast writes, unlimited cycles Memória ROM - Fundamentos Uma ROM tradicional é uma memória não-volátil que pode ser lida por um processador, mas não sofre escrita por ele. A escrita nela é feita por meios externos de programação. Portanto, uma ROM é programada antes de ser usada num sistema embarcado, e, depois, seu conteúdo não é mais modificado. A figura a seguir a seguir mostra o diagrama de uma memória ROM. Memória ROM External view 2k × n ROM enable A0 … Ak-1 … Qn-1 Q0 Algumas Funções Possíveis Guardar o programa de um sistema de propósito geral. Guardar dados relevantes para o sistema embarcado (lookup tables, por exemplo). Implementar circuitos combinacionais, caso em que a ROM guarda, em essência, a tabela-verdade do circuito. ROM – Esquema Básico Internal view 8 × 4 ROM word 0 enable 3×8 decoder word 1 word 2 A0 word line A1 A2 data line programmable connection wired-OR Q3 Q2 Q1 Q0 ROM – Esquema Básico Nesta memória, o conteúdo é programado fisicamente pela presença e ausência de conexões. Por exemplo, se o enable estiver habilitado e pedirmos a palavra de endereço 010, teremos como resposta o dado 1010, devido às conexões ou ausência delas. Perceba que o decodificador ativa a linha da palavra desejada e as ligações formam a informação. Programação Como programas as conexões? Há várias formas de fazer isso, o que define diferentes tipos de memórias ROM. Em ordem de crescente simplicidade de escrita, falaremos sobre maskprogrammed ROM, one-time programmable ROM, erasable programmable ROM (EPROM), electrically erasable programmable ROM (EEPROM) e memória Flash. As duas últimas talvez nem devessem ser chamadas de ROM... Mask-Programmed ROM Nesse caso, as conexões são definidas na fabricação do chip por meio de máscaras adequadamente projetadas. Não há a possibilidade de reescrita, e o conteúdo só é perdido se houver dano ao circuito. OTP ROM Trata-se de uma ROM programada pelo usuário uma única vez (OTP – one-time programmable). Para programar uma PROM, o usuário fornece um arquivo que indica o padrão de conexões desejado. Um equipamento denominado “programmer” então queima diversos fusíveis do circuito removendo as conexões que não devem existir. É por isso que essa PROM só pode ser usada uma vez. Esse tipo de memória não sofre modificações após a escrita (exceto se mais fusíveis forem queimados ou houver dano), sendo de robustez atraente para produtos finais. Veremos que outras PROMs podem sofrer modificações acidentais com maior probabilidade. EPROM – Erasable Programmable ROM EPROMs são memórias que podem ser escritas e apagadas. Elas usam transistores MOS como elementos de armazenagem, numa configuração de gate flutuante. O programmer injeta elétrons nesse gate usando tensões relativamente altas (12 a 25 V), fazendo com que os elétrons tunelem pelo isolante, como mostrado na figura a seguir. Quando se retira a tensão, os elétrons ficam presos no gate, e houve a programação de um bit “0”. Ler uma EPROM é muito mais rápido que escrever nela, já que não é preciso realizar a programação. EPROM – Erasable Programmable ROM EPROM – Erasable Programmable ROM Para apagar a memória, usa-se a incidência de luz ultravioleta sobre o chip por 5 a 30 minutos, após o que o chip pode ser reprogramado. Para que a luz UV chegue ao chip, o encapsulamento contém uma janela de quartzo (windowed device). EPROMs padrão guardam seu conteúdo por pelo menos 10 anos. EPROM – Erasable Programmable ROM Comparação Em comparação com a OTP-ROM, uma EPROM possui menor tempo de armazenagem garantida (10 anos) e há risco de que o conteúdo seja corrompido em ambientes com muito ruído elétrico ou radiação. No produto final, é recomendável cobrir as janelas dos chips para diminuir a chance de mudanças espúrias. EEPROM Uma EEPROM é uma electrically erasable PROM, ou seja, uma PROM apagável eletricamente. Portanto, não só a programação é feita de maneira elétrica, mas também o apagamento e programação. Portanto, trata-se de uma memória que pode sofrer tanto leitura quanto escrita (a escrita segue um ciclo de apagamento e escrita). EEPROMs tipicamente são munidas de um controlador de memória que provê uma interface simples ao usuário. Nesse caso, praticamente diluem-se as fronteiras entre ROM e RAM, embora a escrita numa EEPROM seja um processo mais custoso que a leitura. Memória Flash A memória flash também é baseada no princípio de gate flutuante, mas permite de maneira orgânica o apagamento de blocos de palavras. Isso é interessante, pois agiliza a operação do sistema de memória quando se lida com grandes quantidades de dados. Memória RAM - Fundamentos Memórias RAM (random-access memory) são memórias que pode ser lidas e escritas com facilidade. Escrever numa RAM envolve um custo parecido com o de uma leitura, em contraste com o que ocorre com as ROM programáveis, nas quais a escrita é bem mais custosa que a leitura. Tipicamente, RAMs são memórias voláteis. Memória RAM – Exemplo Simples A seguir apresentamos o diagrama de uma memória RAM simples. Note a presença de um sinal r/w e do fluxo bidirecional de dados. external view r/w 2k × n read and write memory enable A0 … Ak-1 … Qn-1 Q0 Memória RAM - Estrutura O nome “acesso aleatório” vem em contraste com memórias de acesso sequencial, como fitas magnéticas, por exemplo. Há dois tipos básicos de RAM – SRAM (static RAM) e DRAM (dynamic RAM). Na primeira, a informação é gravada numa estrutura equivalente à de um flip-flop, e, na segunda, a unidade de gravação básica é um capacitor. SRAM – Estrutura de Armazenagem Uma SRAM utiliza uma estrutura de flip-flop para armazenar a informação. A estrutura retém a informação enquanto é alimentada, em contraste com o que ocorre com uma DRAM. Utiliza-se tipicamente SRAM em partes da memória que requerem alto desempenho (e.g. cache). SRAM Data' Data W DRAM – Estrutura de Armazenagem Uma DRAM utiliza uma estrutura contendo um transistor MOS e um capacitor para guardar a informação. Cada bit, portanto, requer apenas um transistor, mas isso ao custo de que a informação armazenada no capacitor tende gradualmente a se perder (pelo processo de descarga). Assim, cada célula precisa sofrer periodicamente um processo de refresh. DRAM Data W DRAM – Estrutura de Armazenagem A taxa de refresh mínima de uma memória DRAM típica é de cerca de 15 microssegundos. Pela forma como DRAMs são projetadas, a leitura de uma célula já ocasiona seu refresh. DRAMs tendem a ser mais lentas que SRAMs. NVRAM – RAM Não-Volátil Uma NVRAM é uma memória RAM nãovolátil, ou seja, que é capaz de guardar seu conteúdo mesmo sob uma perda de alimentação. Uma possibilidade é ter, por exemplo, uma SRAM com uma bateria dedicada (algumas baterias podem durar até 10 anos). Outra é ter uma SRAM acoplada a uma EEPROM ou flash espelho que guarda de maneira perene o conteúdo da memória e restaura esse conteúdo em caso de perda. Exemplos – HM6264 (RAM) e 27C256 (ROM) – 8 bits Composição de Memórias O projetista de um sistema embarcado pode se deparar com a necessidade de utilizar certa configuração de memórias tendo apenas componentes de tamanho diferente. Por exemplo, ele pode precisar de 2k x 8 ROMs, mas ter apenas 4k x 16 ROMs. Por outro lado, ele pode se ver na situação contrária. Composição de Memórias Quando a memória disponível é maior que o necessário, o projetista pode usar apenas as linhas menos significativas de endereços e dados e ignorar as demais. O caso em que a memória disponível é menor que o necessário requer mais esforço. Suponhamos, primeiramente, o caso em que as memórias tem o número certo de palavras, mas as palavras têm tamanho insuficiente. Nesse caso, os chips podem ser concatenados como a seguir. Composição de Memórias Composição de Memórias Por outro lado, suponhamos que as memórias tenham o tamanho de palavra correto, mas número insuficiente de palavras. Neste caso, criam-se linhas adicionais de endereço e utilizam-se decodificadores. Por exemplo, suponhamos que precisemos de uma ROM com o dobro de palavras das presentes nos chips de que dispomos. É possível operar como mostrado a seguir (criando uma linha de endereço adicional que seleciona o chip). Composição de Memórias Composição de Memórias Se fosse preciso quadruplicar (em vez de dobrar) o tamanho da memória, poder-se-ia usar um decodificador 2 x 4 e criar duas linhas de endereço adicionais. Se tivermos uma combinação dos dois casos (palavras pequenas e poucas palavras), podemos combinar as duas técnicas. Faz-se a concatenação e, em seguida, aplica-se o método de inclusão de decodificadores. Um esboço é mostrado a seguir. Composição de Memórias Hierarquia de Memória Quando se projeta um sistema de memória, vive-se um dilema: desejase memória rápida e barata. No entanto, memória rápida tende a ser cara e memória barata tende a ser lenta. Um caminho para se atingir um compromisso é criar uma hierarquia de memória, como ilustrado a seguir. Hierarquia de Memória Hierarquia de Memória Do ponto de vista de sistemas embarcados, utiliza-se uma memória maior e mais lenta (Main Memory) para guardar o programa e os dados. Utiliza-se também uma memória menor e mais rápida (Cache), que é mais cara, para guardar blocos acessados na memória principal. Por uma questão de localidade, é provável que esses blocos sofram diversos usos antes de serem trocados. Embora o diagrama mostre apenas uma memória cache, pode-se construí-la usando, eventualmente, vários níveis. Hierarquia de Memória Alguns sistemas envolvem outras formas de memória, como discos magnéticos e fitas, mas, em sistemas embarcados, isso não é comum. Normalmente, projeta-se memória cache com tecnologia SRAM, por sua velocidade, o que explica por que a memória cache é mais cara e menor que a memória principal (por exemplo, uma DRAM). Também explica-se seu tamanho pelo fato de ela estar no mesmo chip do processador em geral. Memória Cache Tipicamente, uma memória cache opera da seguinte forma: quando se deseja acessar um endereço de memória, verifica-se primeiro se há uma cópia na cache. Se houver, tem-se um acerto (cache hit), e o acesso é rápido. Se não for o caso, tem-se uma falha (cache miss), e tipicamente se transporta o endereço e alguns vizinhos para a cache. Essa descrição levanta muita possibilidades, que buscaremos discutir a seguir. Mapeamento Direto A figura a seguir ilustra o esquema. Note que o endereço possui dois campos, index e tag. Index corresponde ao endereço no espaço da cache, e, portanto, seu número de bits é log2(tamanho_cache). O tamanho aqui quer dizer número de linhas, como veremos adiante. Perceba que vários endereços da memória principal apontarão para o mesmo endereço na cache. Por esse motivo, armazena-se na cache, juntamente com o conteúdo da memória, a tag. Se os endereços de index batem, verificase se há coincidência de tags e verifica-se um bit de validade (V), que revela se o dado corresponde a uma informação válida trazida da memória principal. Mapeamento Direto Mapeamento Direto Por fim, usa-se o campo offset para buscar, numa linha da cache, a palavra específica. Uma linha da cache (ou bloco) é um número de endereços adjacentes inseparáveis trazidos da memória principal para a cache. Tamanhos típicos vão de 4 a 8 endereços. Mapeamento Totalmente Associativo Neste caso, cada endereço de cache contém não só o conteúdo da memória, mas o endereço completo. Para verificar se determinado conteúdo está na cache, realiza a comparação da tag do endereço com todas as tags armazenadas. Em caso de cache hit, utiliza-se o offset para buscar, dentro do bloco, a palavra desejada. Note que o número de linhas da cache não é determinado pelo formato do endereço. Mapeamento Totalmente Associativo Mapeamento Associativo por Conjuntos Nesse caso, busca-se um compromisso entre os dois paradigmas vistos anteriormente. Como no mapeamento direto, o campo index mapeia cada endereço de memória num único campo da cache, mas agora esse campo contém os tags de um ou mais blocos de palavras (formando um conjunto). Para resolver essa ambiguidade, faz-se, para esses blocos, uma comparação simultânea (associativa) das tags. Uma cache com conjuntos de N blocos é chamada de N-way set-associative cache (N = 2, 4, 8 são opções comuns). Mapeamento Associativo por Conjuntos (2-way) Mapeamento Associativo por Conjuntos – Uma Ilustração Comparações O mapeamento direto é relativamente simples de implementar, mas pode levar a várias ocorrências de cache miss se duas ou mais linhas com o mesmo index são acessadas frequentemente, pois elas se expulsarão mutuamente da cache. Por outro lado, caches puramente associativas são eficientes, mas requerem uma lógica de comparação complexa. Caches associativas por conjunto representam um meio-termo entre ambos os casos. Políticas de Substituição A política de substituição de uma cache é o método para decidir qual linha substituir quando se usa um método associativo ou associativo por conjuntos. No caso direto, não há escolha. Uma primeira política é escolher aleatoriamente o bloco. Embora seja simples de implementar, a política nada faz para aproveitar um bloco que possa ser usado mais vezes. Políticas de Substituição Outra política é fazer a substituição do bloco least recently used (LRU). Isso leva a um bom desempenho, mas requer hardware complexo para manter o controle dos acessos aos blocos. Por fim, a política FIFO (First-In / FirstOut) mantém uma fila de tamanho N para regular a entrada e a saída dos blocos. Políticas de Escrita Quando se escreve num dado contido na memória cache, é preciso restaurar a coerência entre a informação contida nesta memória e na memória principal. Há duas grandes políticas para isso: write-through e write-back. Na técnica write-through, cada vez que se escreve numa palavra da cache, atualiza-se a memória principal. Isso é simples mas pode levar a escritas inúteis e lentas, já que a informação na cache poderia vir a ser reescrita antes de voltar à memória principal. Políticas de Escrita Por outro lado, na política write-back, só se atualiza a memória principal quando o bloco é substituído e se ele foi escrito. Nesse caso, é preciso dispor de um bit extra, chamado de dirty bit, em cada bloco, para indicar a necessidade de atualizar a memória principal ao se retirar o bloco da cache. Impacto no Desempenho do Sistema O projeto e configuração de caches pode ter um grande impacto no desempenho do sistema e no seu consumo de potência. Alguns parâmetros fundamentais: tamanho da cache, grau de associatividade, tamanho de bloco (ou linha). O tamanho da cache é medido diretamente pelo número de bytes que ela pode conter. Impacto no Desempenho do Sistema Aumentar a memória leva a uma diminuição em cache misses, mas o acesso a palavras pode ser mais lento. Um exemplo do livro-texto ajuda a tornar isso mais claro. Imagine que projetemos uma memória cache pequena, de 2 Kbytes, para o processador. Ela possui 15% de misses. O custo de acessar a memória principal é de 20 ciclos, e o custo de acessar apenas a cache é de 2 ciclos. Nesse caso, temos 0,85*2 + 0,15*20 = 4,7 ciclos em média. Impacto no Desempenho do Sistema Suponha agora que tenhamos uma memória de 4Kbytes. Ela tem taxa de acerto de 93,5%, mas requer um ciclo extra para acesso. Temos 3*0,935 + 0,065*20 = 4,105 ciclos. Há uma melhora. Porém suponha que usemos agora uma memória de 8Kbytes. Nesse caso, temos 94,435% de acerto, mas a um custo de um ciclo a mais para acesso à cache. Agora, teríamos 4,8904 ciclos em média, uma piora. Impacto no Desempenho do Sistema Note que um aumento indiscriminado pode levar a uma piora em termos de tempo. Usualmente os projetistas evitam isso tornando a cache associativa ou aumentando o tamanho de bloco. No entanto, também há penalidades de latência nesses casos. Para concluir, apresentamos um gráfico que mostra o efeito do grau de associatividade no desempenho da cache para um conjunto de benchmarks. Impacto no Desempenho do Sistema