Um microprocessador moderno é algo extremamente complicado, e exigiu décadas de trabalho por milhares de pessoas para chegar onde está hoje. É quase impossível descrevê-lo de forma completa, mas eu vou tentar mesmo assim.
>>> Cientistas preparam os processadores do futuro com nanotubos de carbono
>>> Cientistas descobrem como fazer processadores ultrarrápidos de grafeno
Todo sistema moderno funciona com base em boas abstrações, ou seja, módulos mais simples em cima dos quais são construídas coisas mais complexas. Na minha opinião, o processador moderno pode ser dividido nas seguintes camadas amplas:
- dispositivos (transistores)
- circuitos
- portas lógicas
- blocos lógicos simples
Vamos começar em um “meio-termo”, algo que não é muito complicado de se entender, nem muito longe de um processador real: a porta lógica. Uma porta lógica recebe entradas (input), que são todos 0 ou 1, e terá uma saída (output) de um bit que também será 0 ou 1, de acordo com alguma regra. Por exemplo:
- uma porta AND dará o resultado 1 se todos os valores que você inserir forem 1;
- uma porta OR dará o resultado 1 sempre que alguma das entradas for 1;
- uma porta NOT retorna 1 se você insere 0, e vice-versa.
Mas o que 0 e 1 significam? Bem, o valor pode corresponder a um nível de tensão (0 é 0V, 1 é 1V), um pulso elétrico (0 é ausência de pulsos, 1 é um pulso de 1V por 1 nanossegundo), um fóton (0 é ausência de fótons, 1 são mil fótons) e assim por diante, tudo dependendo de como o circuito foi concebido. Este é o poder de abstração: você não precisa saber o que 0 e 1 significam para usar esse conceito.
Um mais um
E essas coisas simples permitem fazer algo real. Suponha que você está prestes a iniciar sua própria empresa de processadores, e quer fazer um circuito simples que soma dois números.
Primeiro, você precisa representar números decimais em base binária, que usa apenas os dígitos 0 e 1. Ou seja, você precisa convertê-los de 0, 1, 2, 3, 4… para 0, 1, 10, 11, 100… Qualquer número pode ser representado desta forma.
Agora, vamos passar para o somador. Antes de tudo, precisamos construir um “meio somador” (half adder), que pega dois bits e os adiciona, produzindo uma saída de dois bits. Assim, se os dois bits são ambos 0, a saída é 00; se apenas um deles for 1, a saída é 01; e se ambos forem 1, a saída é 10.
Esses resultados têm dois bits. Perceba que o primeiro bit é 1 somente se ambos os bits de entrada forem 1. Ou seja, isso pode ser representado por uma porta AND, como mencionamos acima. Ótimo! Fizemos a metade do nosso trabalho; agora só falta o segundo bit.
Este parece mais difícil: é quase como uma porta OR, que explicamos acima, mas não é a mesma coisa. OK, não vamos mais pensar sobre isso: vamos simplesmente decidir que este é um novo tipo de porta – a porta XOR (eXclusive OR).
Não se preocupe, nós vamos contratar alguns engenheiros de circuito bem impressionantes que sabem projetar essa porta. Agora vamos desenhar uma imagem do meio somador, o nosso novo circuito:
Somador completo
Mas agora você diz: “nós só conseguimos adicionar números de 1 bit. Nossa empresa rival pode adicionar números de mais de 1 bilhão de bits. Como podemos fazer o mesmo?” A resposta é – surpresa! – usar mais abstrações.
O nosso circuito atual só pode adicionar dois números de um bit. Repare que, em quase todos os casos, o resultado caberia em um bit: 0+0=0, 0+1=1 e 1+0=1. O problema está em 1+1=10. O bit extra é chamado de “carry” ou vai-um: ele precisa ser adicionado ao próximo bit maior.
Isto requer a soma de três bits, algo que nosso meio somador não pode fazer. O que fazer? Unir dois meio-somadores para criar um somador completo (full adder).
Agora temos todo o poder da somatória em nossas mãos. Com isso, podemos interligar 32 meio-somadores para criar um monstro que pode, em um piscar de olhos, adicionar números superiores a 1 bilhão.
E eis algo maravilhoso: se você continuar a fazer portas cada vez melhores, seu circuito vai se tornar cada vez melhor. Esse é o poder da abstração.
Claro, nossa forma de somar não é tão boa assim. É possível usar um método melhor, na verdade. Mas, por causa da nossa amiga abstração, isso pode ser feito independentemente das portas lógicas. Se o seu circuito mais recente for duas vezes melhor do que o antigo, e se tiver portas lógicas duas vezes mais rápidas, você terá um circuito quatro vezes melhor!
É principalmente por isso que avançamos tanto em poucas décadas. Nós construímos circuitos menores, mais rápidos e que consomem menos energia. E nós descobrimos formas melhores de se fazer o mesmo cálculo. Juntando tudo isso, ele funciona como mágica!
Bits, ações e memória
É possível criar circuitos que podem multiplicar, somar, subtrair, dividir, comparar e fazer todo tipo de operação aritmética, tudo em um nanossegundo. Nós até mesmo criamos um pequeno circuito que pode “armazenar” um valor (ou seja, sua saída vai depender do valor que foi escrito nele antes). Vamos chamá-lo de circuito flip-flop.
Mas, veja você, todo circuito tem uma coisa em comum: eles pegam as entradas e fazem a mesma operação neles para fornecer a saída. E se eu quisesse multiplicar algo agora, e depois somar algo?
Neste caso, não podemos considerar bits apenas como números: vamos tentar representar as “ações” em bits. Digamos que 0 signifique “adicionar” e 1, “multiplicar”. Agora, vamos construir um pequeno circuito que veja um bit como um “comando”, selecione entre duas entradas (I0 e I1) e forneça a saída I0 se o comando for 0, e I1 se for 1. Este é um multiplexador (ou multiplexer).
Agora só precisamos de um multiplexador para escolher entre os valores gerados por um somador e um multiplicador, e temos a nossa solução! Na verdade, podemos ter muitos desses multiplexadores para escolher entre muitos resultados – assim, nós conseguimos criar uma máquina realmente incrível.
Mas espere; temos outra ideia. Lembra-se daqueles flip-flops que criamos antes? Bem, e se conectarmos um multiplexador na saída de 1.024 flip-flops? Agora nós temos o que é chamado de memória de 1 kilobit. Nós podemos dar um “endereço” a ela, para que nos devolva um bit que foi armazenado naquele local numerado. Além do mais, esses bits agora pode ser “números” (dados) ou “comandos” (instruções).
A máquina de von Neumann
Agora temos tudo do que precisamos para construir um processador:
- temos a memória com todos os “comandos” (instruções) e “números” (dados);
- temos o “contador de programa”, que usamos para selecionar qual instrução será executada na memória;
- temos um bloco que realiza operações aritméticas (AND, OR, NOT etc.);
- a partir da memória, geramos as entradas para o nosso bloco aritmético;
- por fim, existem dois tipos de instruções: dados e controle. Cada instrução de dados contém quatro coisas: dois endereços especificando qual operação será realizada; mais dois endereços dizendo onde colocar o resultado de volta. As instruções de controle simplesmente colocam outro endereço de volta no “contador de programa”.
Esta coisa que você acabou de fazer se chama máquina de von Neumann, criada em 1945 pelo matemático John von Neumann. Hoje em dia, as pessoas estão começando a questionar se esta é a melhor maneira de criar chips, mas esta é a maneira padrão para criar qualquer processador de hoje em dia.
Cache e paralelismo
Quando eu digo que esta é a forma como todos os processadores são feitos, eu quis dizer teoricamente. É que a CPU do seu concorrente é bem mais rápida do que seu CPU baseado em von Neumann. Você só tem 1.000 kilobits de memória, enquanto seu concorrente pode lidar com bilhões (Gb) ou trilhões (Tb) de bits na memória. Mas eles não fornecem um bilhão de bits para um multiplexador e obtêm resultados dentro de um nanossegundo. O segredo deles é algo chamado localidade.
Isto significa que seu programa normalmente só usa algumas zonas de dados e instruções de memória por vez. Ou seja, você tem uma memória com gigabytes de dados, mas você leva uma pequena parte dela – que está sendo usada no momento – para uma matriz muito menor (talvez de 1 MB) chamada de cache. Agora você pode ter um cache ainda menor por baixo dele, e assim por diante, até que você possa chegar a algo que pode ser lido ou gravado na mesma quantidade de tempo em que você pode fazer um cálculo aritmético.
Outra ideia poderosa se chama execução fora de ordem. Este conceito pode ser ilustrado por um programa que calcula X = (A + B) * (C + D).
1. adicione A e B e armazene-o em U
2. adicione C e D e armazene-o em V
3. multiplique U e V e armazene-o em X
Normalmente, seu processador faria isso na sequência, realizando uma instrução após a outra e terminando a execução em 3 etapas. Mas, se você tiver dois somadores no sistema, pode executar as instruções 1 e 2 em paralelo, e terminar o cálculo em duas etapas. Dessa forma, você executa mais instruções em cada passo e termina tudo mais rápido.
A soma das partes
Agora volte no tempo em que você só conhecia uma simples porta lógica AND. O processador que você construiu parece tão distante disso… mas na verdade ele é um conjunto de camadas, que reutilizam um elemento simples para criar algo mais complexo. Essa é a ideia-chave aqui: a CPU é criada ao se reunir partes menores, que por sua vez são compostas de partes ainda menores. Mas se você o olhar na vida real, verá algo semelhante a isso:
Processador Intel Core i7 da geração Sandy Bridge
Claro, isso é apenas o básico. O que você viu acima é o equivalente a responder “Como funciona um carro de Fórmula 1?” com “Ele tem rodas, uma direção que orienta as rodas, e um motor para fazê-las rodar”.
Conceber e fazer uma CPU é um dos milagres da tecnologia moderna, e envolve um grande número de disciplinas de engenharia (incluindo, por exemplo, a física quântica, a metalurgia, a fotônica etc.). Agora, vamos entrar em um pouco mais de detalhe.
Fabricação
É uma proeza tecnológica criar e conectar bilhões de transistores minúsculos, cada um com largura inferior a 100 nm (ou cem bilionésimos de metro), em um padrão preciso definido por designers de circuitos e arquitetos de CPU – e tudo isso a um custo relativamente baixo. Claro que a criação e ligação desse enorme número de transistores é praticamente impossível de forma manual, ou até mesmo por qualquer forma mecânica.
Para superar isso, os chips são fabricados usando-se um método chamado fotolitografia, e por isso eles custam tão pouco em relação à sua complexidade. A ideia é semelhante à forma como uma foto analógica costumava ser revelada. Primeiro, aplica-se uma camada de óxido de silício por cima de silício. Em seguida, é aplicada uma camada de resina fotossensível por cima.
A ideia aqui é criar um padrão no silício que servirá como as portas lógicas dos transistores. Por isso, o inverso do padrão é feito na forma de uma “máscara”, através da qual a luz ultravioleta atinge a resina fotossensível. Mas como essa máscara é criada?
Aqui está a magia da fotolitografia: a máscara é muito maior do que o padrão microscópico a ser gravado. A luz que atravessa a máscara é simplesmente focada por uma lente para ter o tamanho certo quando atingir o silício. Quando a luz muda o material fotossensível, ele é removido por uma explosão de plasma, que deixa apenas o padrão desejado no óxido de silício.
Para criar uma camada de metal, segue-se um procedimento semelhante. No entanto, agora, o inverso do padrão é gravado em SiO2 (óxido de silício), e, em seguida, o metal é depositado sobre os “sulcos” criados pelo SiO2.
Isso é tão econômico porque, uma vez que se tem a “máscara”, você pode criar um número enorme de chips a partir dela. A máscara é muito cara, exigindo alguns milhões de dólares para ser feita, mas seu custo é diluído na quantidade de chips que você fabricar.
Tipos de memórias
Como eu disse anteriormente, você pode criar uma memória conectando flip-flops a multiplexadores. No entanto, esta não é uma forma especialmente eficiente de se fazer isto. Um flip-flop consome cerca de 15 a 20 transistores. Na prática, existem dois tipos de estruturas de memória: RAM estática (ou SRAM), que usa seis transistores por bit; e RAM dinâmica (ou DRAM), que usa apenas um transistor e um capacitor por bit. A RAM estática basicamente consiste em duas portas NOT conectadas em um circuito como este:
Nas portas NOT, se você insere 1, ela retorna 0 e vice-versa. Assim, existem dois estados possíveis para A e B: A = 1, B = 0; ou A = 0, B = 1. A ideia é aplicar alguma tensão externa para fazer o loop entrar em um ou outro estado – o bit “armazenado” – e depois simplesmente ler a tensão em A ou B para “ler” o bit.
Por outro lado, a RAM dinâmica ou DRAM é ainda mais simples, e se parece mais ou menos com isto:
Neste design, o transistor simplesmente age como um interruptor para armazenar carga no capacitor, caso em que ele é lido como 1; caso contrário, é 0. No entanto, a carga no capacitor acaba vazando, então é preciso ler e regravar os dados em intervalos fixos – por isso esta RAM é dinâmica.
Os caches em um chip são geralmente SRAM, porque esse tipo de memória é mais rápido. No entanto, as memórias principais de um computador são geralmente DRAM, por serem menores em tamanho; dessa forma, uma quantidade maior de memória pode caber num único chip.
Leitura adicional:
- fotolitografia
- memória estática de acesso aleatório
- memória de acesso aleatório dinâmico
- circuito aritmético
- arquitetura de von Neumann
- cache da CPU
- execução fora de ordem
Subhasis Das é formado em engenharia elétrica, e está obtendo seu PhD em arquitetura de computadores na Universidade Stanford.
Como funciona um chip de computador? apareceu originalmente no Quora. Você pode seguir o Quora no Twitter, Facebook e Google+.
Imagens por Shutterstock/Volodymyr Krasyuk e Wikipédia