Como eu não sabia como os processadores funcionam, escrevi um simulador de software.


Alguns meses atrás, fiquei subitamente impressionado com o pensamento de que não fazia ideia dos princípios do hardware do computador. Ainda não sei como os computadores modernos funcionam.

Eu li o livro "Mas como ele sabe?" Clark Scott com uma descrição detalhada de um computador simples de 8 bits: começando com portas lógicas, RAM, transistores de processador, terminando com um dispositivo de lógica aritmética e operações de entrada e saída. E eu queria implementar tudo isso no código.

Embora eu não esteja tão interessado na física dos microcircuitos, o livro simplesmente desliza ao longo das ondas e explica lindamente os circuitos elétricos e como os bits se movem pelo sistema - o leitor não precisa conhecer a engenharia elétrica. Mas descrições textuais não são suficientes para mim. Eu tenho que ver as coisas em ação e aprender com meus erros inevitáveis. Então comecei a implementar circuitos no código. O caminho era espinhoso, mas instrutivo.

O resultado do meu trabalho pode ser encontrado no repositório de computadores simples: uma calculadora simples. Ele é simples e calcula.






Programas de exemplo

O código do processador é implementado como um monte terrível de portas lógicas que são ligadas e desligadas , mas funciona. Fiz os testes de unidade e todos sabemos que os testes de unidade são uma evidência irrefutável de que o programa funciona.

O código processa a entrada do teclado e exibe o texto na tela usando o conjunto de glifos meticulosamente criado para a fonte profissional, que chamei de Daniel Code Pro . O único truque: para pegar a entrada do teclado e gerar o resultado, tive que conectar os canais via GLFW , mas, caso contrário, é uma simulação totalmente em software do circuito elétrico.

Até escrevi um montador rude que abriu meus olhos para muitas coisas, para dizer o mínimo. Ele não é perfeito. Na verdade, até um pouco ruim, mas ele me mostrou problemas que outras pessoas já haviam resolvido muitos, muitos anos atrás.

Mas por que você está fazendo isso?


“Treze anos estão construindo processadores no Minecraft. Ligue-me quando puder fazer uma CPU real com relés de telégrafo. ”

Meu modelo mental do dispositivo da CPU está preso no nível dos livros didáticos de ciência da computação para iniciantes. O processador para o emulador Gameboy, que escrevi em 2013, na verdade não se parece com CPUs modernas. Mesmo que o emulador seja apenas uma máquina de estado (máquina de estado), ele não descreve o estado no nível das portas lógicas. Quase tudo pode ser implementado usando apenas a switch e mantendo o estado dos registros.

Quero entender melhor como tudo funciona, porque não sei, por exemplo, qual é o cache e o pipelining L1 / L2 e não tenho muita certeza de entender os artigos sobre as vulnerabilidades Meltdown e Spectre. Alguém disse que otimiza o código de forma a usar o cache do processador, mas eu não sei como verificá-lo, exceto por uma palavra. Não sei bem o que significam todas as instruções x86. Não entendo como as pessoas enviam tarefas para GPUs ou TPUs. E, em geral, o que é TPU? Não sei como usar as instruções do SIMD.

Tudo isso é construído sobre uma base que precisa ser aprendida primeiro. Significa voltar ao básico e fazer algo simples. O livro acima mencionado de Clark Scott descreve um computador simples. Por isso comecei com isso.

Glória a Scott! Ele trabalha!


O computador de Scott é um processador de 8 bits conectado a 256 bytes de RAM, todos conectados através de um barramento de sistema de 8 bits. Possui 4 registros de uso geral e 17 instruções de máquina . Alguém criou um simulador visual para a web : é realmente ótimo. É assustador pensar em quanto tempo levou para rastrear todos os estados do circuito!


Circuito com todos os componentes do processador Scott. Direitos autorais 2009-2016. Siegbert Filbinger e John Clark Scott

O livro acompanha você ao longo do caminho, desde portas lógicas modestas até bits na memória e registros, e continua a camadas de componentes até que você obtenha algo semelhante ao diagrama acima. Eu recomendo a leitura do livro, mesmo se você já estiver familiarizado com os conceitos. Apenas não a versão do Kindle, porque às vezes é difícil ampliar e desmontar o "leitor" na tela. Na minha opinião, esse é um problema antigo do Kindle.

Meu computador difere da versão de Scott, exceto que a atualizei para 16 bits para aumentar a quantidade de memória disponível, porque armazenar apenas glifos para a tabela ASCII ocupa a maior parte da máquina de 8 bits de Scott, deixando muito pouco espaço para código útil.

Meu processo de desenvolvimento


Em geral, o desenvolvimento ocorreu de acordo com este esquema: ler texto, estudar diagramas e tentar implementá-los em uma linguagem de programação de uso geral e, definitivamente, não usar ferramentas especializadas para projetar circuitos integrados. Eu escrevi o simulador no Go simplesmente porque estou um pouco familiarizado com esse idioma. Os céticos podem dizer: "Burro! Você não aprendeu VHDL ou Verilog , LogSim ou qualquer outra coisa. Mas naquela época eu já havia escrito meus bits, bytes e portas lógicas e mergulhado fundo demais. Talvez da próxima vez eu aprenda essas línguas e entenda quanto tempo perdi, mas esses são meus problemas.

Em um circuito grande, vários valores booleanos são simplesmente transmitidos no computador; portanto, qualquer linguagem que seja amigável com a álgebra booleana é adequada.

A aplicação de um esquema a esses valores booleanos ajuda a nós (programadores) a obter significado e, o mais importante, a decidir em que ordem de bytes o sistema usará e a garantir que todos os componentes transmitam dados no barramento na ordem correta.

Foi muito difícil de implementar. Por uma questão de viés, escolhi uma representação com ordem inversa de bytes, mas ao testar a ALU, não conseguia entender por que os números errados foram exibidos. Meu gato ouviu muitas expressões imprimíveis.

O desenvolvimento não foi rápido: talvez demorasse cerca de um mês ou dois do meu tempo livre. Mas quando apenas o processador concluiu com êxito a operação 2+2=5, Eu estava no sétimo céu com felicidade.

Tudo correu como de costume até chegar à E / S. O livro propôs um projeto de sistema com uma interface simples de teclado e display para inserir dados na máquina e gerar o resultado. Bem, nós já fomos tão longe , não faz sentido parar no meio do caminho. Estabeleci uma meta para implementar a digitação no teclado e a exibição de letras no visor.

Periféricos


Os dispositivos periféricos usam um modelo de adaptador como uma interface de hardware entre a CPU e o mundo externo. Provavelmente, é fácil adivinhar que esse modelo foi emprestado do design de software.


Como os adaptadores de E / S se conectam à janela GLFW

Com essa separação, tornou-se bastante simples conectar o teclado e o monitor a uma janela executando o GLFW. Na verdade, eu apenas peguei a maior parte do código do meu emulador e o modifiquei um pouco para fazer os canais Go funcionarem como sinais de E / S.

Iniciamos o computador




Esta é provavelmente a parte mais difícil, pelo menos a mais complicada. É difícil escrever no assembler com um conjunto tão limitado de instruções, e no meu assembler bruto é ainda pior, porque você não pode enganar ninguém além de si mesmo.

O maior problema foi manipular quatro registros, rastreando-os puxando dados dos registros e armazenando-os temporariamente na memória. No processo, lembrei que o processador Gameboy possui um registro de ponteiro de pilha para a conveniência de carregar e carregar registros. Infelizmente, este computador não tem esse luxo, portanto você precisava transferir dados manualmente manualmente para e da memória.

Decidi dedicar tempo a apenas uma pseudo- CALL para chamar uma função e depois retornar ao ponto. Sem isso, as chamadas estão disponíveis apenas um nível em profundidade.

Além disso, como a máquina não suporta interrupções, eu tive que implementar um terrível código de pesquisa de estado do teclado. O livro discute as etapas necessárias para implementar interrupções, mas isso complica seriamente o circuito.

Mas pare de reclamar, eu ainda escrevi quatro programas , e a maioria deles usa algum tipo de código comum para renderizar fontes, entrada de teclado etc. Isso não é um sistema operacional, mas fornece uma compreensão do que um sistema operacional simples faz.

Não foi fácil. A parte mais difícil do programa de redação de texto é descobrir quando saltar para uma nova linha ou o que acontece quando você pressiona Enter.

 main-getInput: CALL ROUTINE-io-pollKeyboard CALL ROUTINE-io-drawFontCharacter JMP main-getInput 
O ciclo principal do programa de redação de textos

Não me preocupei em implementar a tecla Backspace e as teclas modificadoras. Mas percebi quanto trabalho o desenvolvimento de editores de texto exige e o quão tedioso é.

Conclusões


Foi um projeto divertido e muito útil para mim. No meio da programação em linguagem assembly, quase me esqueci dos portões lógicos abaixo. Subi aos níveis superiores de abstração.

Embora esse processador seja muito simples e esteja longe da CPU do meu laptop, parece-me que o projeto me ensinou muito, em particular:

  • Como os bits se movem pelo barramento entre todos os componentes.
  • Como a ALU simples funciona?
  • Como é um loop Fetch-Decode-Execute simples .
  • Que uma máquina sem um ponteiro de registro e um conceito de pilha - é uma merda.
  • Aquele carro sem interrupções também é uma merda.
  • O que é assembler e o que ele faz.
  • Como os periféricos interagem com um processador simples.
  • Como as fontes simples funcionam e como exibi-las no visor.
  • Como pode ser um sistema operacional simples .

Então, o que vem a seguir? O livro diz que ninguém produziu esses computadores desde 1952. Isso significa que eu tenho que estudar o material nos últimos 67 anos. Vai demorar um pouco. Percebo que o manual x86 tem 4.800 páginas o suficiente para uma leitura agradável e fácil antes de dormir.

Talvez eu seja um pouco mimado com o sistema operacional, a linguagem C, matarei a noite com o kit de construção PiDP-11 e um ferro de solda e, em seguida, abandonarei essa coisa. Eu não sei, vamos ver.

Sério, estou pensando em explorar a arquitetura RISC, possivelmente RISC-V. Provavelmente, é melhor começar com os primeiros processadores RISC para entender sua origem. Processadores modernos têm muito mais recursos: caches e mais, quero entendê-los. Há muito o que aprender.

Esse conhecimento será útil no meu trabalho principal? Talvez útil, embora improvável. De qualquer forma, eu gosto, então não importa. Obrigado pela leitura!

Source: https://habr.com/ru/post/pt453158/


All Articles