Introdução à Arquitetura de Computadores/Arquiteturas RISC e CISC
RISC
Reduced Instruction Set Computer ou Computador com um Conjunto Reduzido de Instruções (RISC), é uma linha de arquitetura de processadores que favorece um conjunto simples e pequeno de instruções que levam aproximadamente a mesma quantidade de tempo para serem executadas. A maioria dos microprocessadores modernos são RISCs, por exemplo DEC Alpha, SPARC, MIPS, e PowerPC. O tipo de microprocessador mais largamente usado em desktops, o x86, é mais CISC do que RISC, embora chips mais novos traduzam instruções x86 baseadas em arquitetura CISC em formas baseadas em arquitetura RISC mais simples, utilizando prioridade de execução.
Os processadores baseados na computação de conjunto de instruções reduzido não tem micro-programação, as instruções são executadas diretamente pelo hardware. Como característica, esta arquitetura, além de não ter microcódigo, tem o conjunto de instruções reduzido, bem como baixo nível de complexidade.
A idéia foi inspirada pela descoberta de que muitas das características incluídas na arquitetura tradicional de processadores para ganho de desempenho foram ignoradas pelos programas que foram executados neles. Mas o desempenho do processador em relação à memória que ele acessava era crescente. Isto resultou num número de técnicas para otimização do processo dentro do processador, enquanto ao mesmo tempo tentando reduzir o número total de acessos à memória.
RISC é também a arquitetura adotada para os processadores dos videogames modernos, que proporcionam um hardware extremamente dedicado somente à execução do jogo, tornando-o muito mais rápido em relação a micro computadores com mais recursos, embora com processador x86.
História
Desde os primeiros momentos da indústria de computadores que os cientistas dos principais fabricantes têm estudado métodos e técnicas que possam aperfeiçoar o desempenho e a capacidade dos sistemas de computação. Alguns aspectos atribuídos ao primeiro-RISC: projetos marcados por volta de 1975 incluem as observações que os compiladores de memória restritos da época eram freqüentemente incapazes de tirar proveito dos recursos destinados a facilitar a montagem manual de codificação, e que os modos de endereçamento complexos levavam muitos ciclos para executar devido aos exigidos acessos à memória adicional. Foi alegado que tais funções seriam melhor executadas por sequências de instruções mais simples se isso poderia render implementações pequenas o suficiente para deixar espaço para muitos registros , reduzindo o número de acessos à memória lenta. Nestes projetos simples, a maioria das instruções são de tamanho uniforme e estrutura semelhante, as operações aritméticas são restritas a registros de CPU e instruções a carregar apenas separam e armazenam a memória de acesso. Essas propriedades permitem um melhor balanceamento de estágios no pipeline do que antes, fazendo gasodutos RISC significativamente mais eficientes e permitindo que as freqüências de clock fossem mais altas.
No inicio da década de 1980, surgiram várias pesquisas cujo desejo era de aumentar o desempenho do sistema de computação. Se o desejo era esse, deve-se procurar aperfeiçoar o emprego das instruções que consomem mais tempo de execução, e não se preocupar tanto com instruções mais complexas que raramente são usadas.
Ao longo das décadas em que é usado o computador, observa-se que o hardware em geral, os processadores e a memória, tem evoluído mais rapidamente que o software.
Por outro lado, a manutenção e desenvolvimento de programas não evoluíram em custo/benefício. Apesar de a todo o momento surgirem novas criações e lançamentos, isso acarreta um custo muito elevado. A manutenção também pode ser um problema, pois os programas oferecidos pelos fabricantes estão longe da ausência de falhas(bugs).
Entre as pesquisas realizadas nessa época, podemos citar a de David Patterson. Juntamente com Carlos Séquin, ele publicou em 1982 [PATT82] um estudo mostrando o desempenho, os parâmetros e elementos de linguagens de alto nível quando compiladas e executadas. Esse artigo descrevia uma nova arquitetura para um processador, propondo solucionar os problemas de desempenho e custo existentes nas arquiteturas complexas vigentes (CISC). Esta arquitetura foi chamada de RISC, porque criava um processador com pequeno conjunto de instruções.
Esse trabalho é usado como referência para a avaliação do comportamento dos programas de alto nível e seu desempenho dinâmico, no qual os autores apresentaram resultados da compilação e da execução de oito programas diferentes, quatro em linguagem Pascal e quatro em linguagem C.
As análises efetuadas de programas compilados por máquinas de arquitetura CISC, mostraram que os compiladores não eram mais tão espertos quanto os programadores assembly na busca de instruções de máquina complexas. O programa compilador utiliza pouco da grande quantidade de instruções e dos modos de endereçamento que estão disponíveis, pois parece ser difícil analisar o programa de alto nível. Por exemplo, para efetuar a soma entre dois operandos em uma máquina com arquitetura CISC, sendo que um dos valores está em um registrador e o outro na memória, levará um certo tempo gasto para calcular o endereço de acesso a memória. Já em uma máquina com arquitetura RISC, são usadas duas instruções(diferente da arquitetura CISC que utiliza uma instrução), mas como são instruções mais simples, sua execução é bem mais rápida fazendo com que seu tempo total seja menor.
É uma estratégia de desenvolvimento de CPU com base na percepção de que simplificado (em oposição ao complexo) as instruções podem proporcionar maior desempenho, se essa simplicidade permite a execução muito mais rápida de cada instrução. Um computador com base nesta estratégia é um computador com um reduzido conjunto de instruções (também RISC). Existem muitas propostas de definições precisas , mas o termo está sendo lentamente substituído pela arquitetura mais descritiva load-store. Famílias bem conhecidas incluem RISC DEC Alpha, a AMD 29k, ARC, ARM, Atmel AVR, MIPS, PA-RISC, Power (incluindo PowerPC), SuperH e SPARC.
Características das Arquiteturas CISC
O nome CISC (Complex Instruction Set Computer) advém do fato de se considerar complexo um conjunto constituído de grande quantidade de instruções, com múltiplos modos de endereçamento, entre outras críticas. Em uma época inicial da computação em que a memória era cara e pequena e, por isso, os códigos gerados pelos compiladores deveriam ser compactos e eficientes na execução. Dessa forma, os projetistas precisavam obter boa densidade do código de máquina, ou seja, cada instrução deveria fazer muito, de modo que o programa completo tivesse poucas instruções.
O surgimento, em 1951, do conceito de microprogramação facilitou o trabalho de projetar instruções complexas, implementando-as em microcódigo. O microcódigo reside em memória de controle, pode-se acelerar sua execução com essas memórias sendo rápidas. A criação de novas instruções é, na maioria das vezes, quase sem custo e sem aumento de espaço, facilitando a implementação do conceito de famílias de processadores. Um bom exemplo disso é a arquitetura x86. Outra vantagem do emprego de microcódigo reside na rapidez da execução de instruções que estão armazenadas em memória (memória ROM de controle) bem mais rápido que a memória convencional.
O primeiro sistema de computação lançado com microcódigo e que originou, também, o conceito de família de computadores foi introduzido pela IBM em 1964, o Sistema IBM/360. Posteriormente, a DEC (Digital Equipament Corporation) introduziu sua família de PDP, mais tarde substituída pelo sistema VAX, um dos melhores exemplos de máquina CISC.
Pode-se concluir que os projetistas de arquiteturas CISC consideram três aspectos básicos: - uso de microcódigo; - construção de conjuntos com instruções completas e eficientes (completeza no conjunto); - criação de instruções de máquina de “alto nível”, ou seja, com complexidade semelhante à dos comandos de alto nível.
Colocados juntos, esses elementos do projeto nortearam a filosofia de construção de processadores CISC por longo tempo, como a família Intel x86, os processadores AMD K e, anteriormente, os sistemas IBM e VAX. Assim é que existem naqueles conjuntos instruções poderosas, do tipo:
CAS - compare and swap operands (comparar valores e trocas operandos) RTR - return and restore codes (retornar e restaurar código) SWAP - swap register words (trocar palavras dos registradores)
Em geral o desenvolvimento das arquiteturas CISC tende a seguir algumas regras básicas:
a) Formato de dois operandos mais comum – instruções com campos de origem e destino, como a instrução:
ADD CX, mem (subtrair o valor na memória do valor no registrador CX e colocar resultado no registrador CX)
b) Uso de modos registrador para registrador; registrador para memória e memória para registrador.
c) Uso de múltiplos modos de endereçamento para a memória, incluindo indexação para o caso de vetores.
d) Instruções com largura variável, com a quantidade de bytes variando de acordo com o modo de endereçamento utilizado.
e) As instruções requerem múltiplos ciclos de relógio para sua complexa execução, além do que a quantidade desses ciclos varia de acordo com a largura das instruções. Por exemplo, se uma instrução realiza mais de um acesso à memória para buscar dois operandos, então gasta mais ciclos do que outra que só realiza um acesso.
f) O hardware possui poucos registradores devido ao fato de possuir muitas instruções com acesso à memória e por causa da limitação do espaço no chip usado para a memória de controle.
g) Há também registradores especializados, como o registrador de controle (flags...); de segmento para o ponteiro da pilha, para tratamento de interpretação e outros.
Como é usual acontecer em qualquer área da atividade humana, é raro que algum conceito ou tecnologia importante obtenha unanimidade entre pesquisadores, técnicos, projetistas e administradores. Este é o caso da arquitetura CISC, a qual sempre foi alvo de críticas e comentários sobre desvantagens e problemas.
Neste texto não cabe posicionamento por este ou aquele fato ou tecnologia, mas sim apresentar todos os elementos possíveis das diversas tendências, no caso entre CISC e RISC.
No entanto, para se compreender o surgimento de processadores com arquitetura RISC deve-se analisar os eventuais problemas indicados para a arquitetura CISC, que levaram pesquisadores e projetistas de sistemas a criar uma alternativa, considerada por eles mais vantajosa.
Para entender melhor as raízes do surgimento da filosofia RISC, pode-se mencionar alguns pontos das arquiteturas CISC citados como problemáticos por um dos criadores de máquinas RISC, David Petterson, em um de seus artigos, induzindo ao projeto de processadores que pudessem, com sua especificação mais simples, reduzir ou eliminar os citados problemas. Na realidade, parece ter sido Patterson quem primeiro definiu as arquiteturas com muitas e poderosas instruções de CISC e sua maquina protótipo de RISC (o nome esclhido foi RISC-1): Diferenças de velocidade entre memória e processador – no final da década de 1970, a IBM verificou que essa diferença era um problema em seus sistemas, algumas operações eram realizadas por programas, acarretando muitos acessos a uma memória lenta. A solução encontrada foi criar novas instruções de maquina para executar tais operações, podendo-se acreditar que esse foi o início do aumento da quantidade de instruções nas CISC.
Emprego de microcódigo – o surgimento e a real vantagem de custo/beneficio do emprego de micricódigo sobre programação diretamente no hardware induziram os projetistas a criar mais e mais instruções, devido a facilidade e a flexibilidade decorrentes. Desenvolvimento acelerado de linguagens de alto nível – na década de 1980, havia um crescimento acelerado do emprego de linguagens de ato nível, o que conduzia os projetistas de processadores a incluir cada vez mais instruções de máquinas em seus produtos, como o propósito de manter um suporte adequado na compilação.
Densidade de código a ser executado – as arquiteturas CISC procuram obter um código compacto após a compilação, de modo a não consumir memória em excesso. Isso era necessário em uma época em que as memórias eram caras e de reduzindo tamanho. Construindo conjuntos de instruções, cada uma delas mais próxima do significado do comando de ato nível, poder-se-ia obter códigos executáveis mais densos, mais compactos. Alega Patterson que isto acarretaria também mais bits nas instruções (códigos de operações com mais bits devido à quantidade delas, bem como mais modos de endereçamento), o que contrabalançaria aquela pretensa vantagem.
Necessidade de compatibilidade com processadores anteriores – uma das metas sempre seguida pela Intel e outros fabricantes foi a de conservar a compatibilidade entre as versões de seus processadores. Assim o processador 486 veio com apenas algumas instruções novas e todo o código do 386 junto, códigos executáveis para o 386 rodavam também no 486, e os usuários poderiam trocar de computador sem nenhum custo adicional de compilação, etc. O mesmo aconteceu com o Pentium I, II, III e 4. Mesmo isso, embora seja um notório requisito importante de marketing, acarreta uma limitação especificação de novas arquiteturas. Dessa forma, as arquiteturas novas só crescem em quantidade de instruções, visto que o fabricante nunca retira as instruções antigas devido ao problema de compatibilidade.