No sabía cómo funcionan los procesadores, así que escribí un simulador de software


Hace unos meses, de repente me sorprendió la idea de que no tenía idea de los principios del hardware de la computadora. Todavía no sé cómo funcionan las computadoras modernas .

Leí el libro "¿Pero cómo lo sabe?" Clark Scott con una descripción detallada de una computadora simple de 8 bits: comenzando con puertas lógicas, RAM, transistores de procesador, terminando con un dispositivo de lógica aritmética y operaciones de entrada-salida. Y quería implementar todo esto en código.

Aunque no estoy tan interesado en la física de los microcircuitos, el libro simplemente se desliza a lo largo de las ondas y explica maravillosamente los circuitos eléctricos y cómo se mueven los bits alrededor del sistema: no es necesario que el lector conozca la ingeniería eléctrica. Pero las descripciones textuales no son suficientes para mí. Tengo que ver las cosas en acción y aprender de mis errores inevitables. Entonces comencé a implementar circuitos en el código. El camino era espinoso, pero instructivo.

El resultado de mi trabajo se puede encontrar en el repositorio de computadora simple: una calculadora simple. Es simple y calcula.






Programas de muestra

El código del procesador se implementa como un terrible grupo de puertas lógicas que se encienden y apagan , pero funciona. Ejecuté las pruebas unitarias , y todos sabemos que las pruebas unitarias son una prueba irrefutable de que el programa funciona.

El código procesa la entrada del teclado y muestra el texto en la pantalla usando un conjunto de glifos minuciosamente diseñado para una fuente profesional, que llamé Daniel Code Pro . El único truco: para tomar la entrada del teclado y emitir el resultado, tuve que conectar los canales a través de GLFW , pero de lo contrario es una simulación completa del software del circuito eléctrico.

Incluso escribí un ensamblador grosero que me abrió los ojos a muchas cosas, por decir lo menos. El no es perfecto. De hecho, incluso un poco horrible, pero me mostró problemas que otras personas ya habían resuelto muchos, muchos años atrás.

¿Pero por qué haces esto?


“Los niños de trece años están construyendo procesadores en Minecraft. Llámame cuando puedas hacer una CPU real con relés telegráficos.

Mi modelo mental del dispositivo de la CPU está atascado en el nivel de los libros de texto de informática para principiantes. El procesador para el emulador Gameboy, que escribí en 2013, en realidad no se parece a las CPU modernas. Incluso si el emulador es solo una máquina de estado (máquina de estado), no describe el estado a nivel de puertas lógicas. Casi todo se puede implementar utilizando solo la switch y manteniendo el estado de los registros.

Quiero entender mejor cómo funciona todo, porque no sé, por ejemplo, qué son la caché y la canalización L1 / L2, y no estoy muy seguro de entender los artículos sobre las vulnerabilidades Meltdown y Spectre. Alguien dijo que optimizaban el código de tal manera que usaran el caché del procesador, pero no sé cómo verificarlo, excepto para tomar una palabra. No estoy muy seguro de lo que significan todas las instrucciones x86. No entiendo cómo las personas envían tareas a GPU o TPU. Y en general, ¿qué es TPU? No sé cómo usar las instrucciones SIMD.

Todo esto se basa en una base que debe aprenderse primero. Significa volver a lo básico y hacer algo simple. El libro mencionado de Clark Scott describe una computadora simple. Por eso empecé con eso.

¡Gloria a Scott! El trabaja!


La computadora de Scott es un procesador de 8 bits conectado a 256 bytes de RAM, todos conectados a través de un bus de sistema de 8 bits. Tiene 4 registros de propósito general y 17 instrucciones de máquina . Alguien hizo un simulador visual para la web : es realmente genial. ¡Da miedo pensar cuánto tiempo llevó rastrear todos los estados del circuito!


Circuito con todos los componentes del procesador Scott. Copyright 2009-2016. Siegbert Filbinger y John Clark Scott

El libro lo acompaña a lo largo de la ruta desde puertas lógicas modestas hasta bits en la memoria y registros, y luego continúa estratificando componentes hasta que obtenga algo similar al diagrama anterior. Le recomiendo leer el libro, incluso si ya está familiarizado con los conceptos. Simplemente no es la versión de Kindle, porque los gráficos a veces son difíciles de ampliar y desmontar el "lector" en la pantalla. En mi opinión, este es un problema de Kindle de larga data.

Mi computadora es diferente de la versión de Scott, excepto que la actualicé a 16 bits para aumentar la cantidad de memoria disponible, porque almacenar solo glifos para la tabla ASCII ocupa la mayor parte de la máquina de 8 bits de Scott, dejando muy poco espacio para código útil.

Mi proceso de desarrollo


En general, el desarrollo se realizó de acuerdo con este esquema: leer texto, estudiar diagramas y luego tratar de implementarlos en un lenguaje de programación de propósito general y definitivamente no usar ninguna herramienta especializada para diseñar circuitos integrados. Escribí el simulador en Go simplemente porque estoy un poco familiarizado con este lenguaje. Los escépticos pueden decir: "¡tonto! ¿No podría aprender VHDL o Verilog , o LogSim , o alguna otra cosa? Pero para entonces ya había escrito mis bits, bytes y puertas lógicas y me había hundido demasiado. Quizás la próxima vez aprenda estos idiomas y entienda cuánto tiempo perdí, pero estos son mis problemas.

En un circuito grande, un montón de valores booleanos simplemente se transmiten en la computadora, por lo que cualquier lenguaje que sea compatible con el álgebra booleana es adecuado.

La aplicación de un esquema a estos valores booleanos nos ayuda a nosotros (los programadores) a derivar el significado y, lo que es más importante, a decidir qué orden de bytes usará el sistema y asegurarnos de que todos los componentes transmitan datos en el bus en el orden correcto.

Fue muy difícil de implementar. En aras de la parcialidad, elegí una representación con orden de bytes inverso, pero al probar ALU no pude entender por qué salieron los números incorrectos. Mi gato escuchó muchas expresiones no imprimibles.

El desarrollo no fue rápido: quizás me llevó alrededor de un mes o dos de mi tiempo libre. Pero cuando solo el procesador completó con éxito la operación 2+2=5Estaba en el séptimo cielo con felicidad.

Todo salió como de costumbre hasta que llegó a E / S. El libro propuso un diseño de sistema con un teclado simple y una interfaz de pantalla para ingresar datos en la máquina y generar el resultado. Bueno, ya hemos ido tan lejos , no tiene sentido detenerse a la mitad. Me propuse un objetivo para implementar la escritura en el teclado y mostrar letras en la pantalla.

Periféricos


Los dispositivos periféricos usan una plantilla de adaptador como interfaz de hardware entre la CPU y el mundo exterior. Probablemente sea fácil adivinar que esta plantilla está tomada del diseño de software.


Cómo se conectan los adaptadores de E / S a la ventana GLFW

Con esta separación, resultó ser bastante simple conectar el teclado y la pantalla a una ventana que ejecuta GLFW. De hecho, acabo de extraer la mayor parte del código de mi emulador y lo modifiqué un poco para que los canales Go funcionen como señales de E / S.

Empezamos la computadora




Esta es probablemente la parte más difícil, al menos la más engorrosa. Es difícil escribir en ensamblador con un conjunto tan limitado de instrucciones, y en mi ensamblador aproximado es aún peor, porque no puedes engañar a nadie más que a ti mismo.

El mayor problema era hacer malabarismos con cuatro registros, rastrearlos extrayendo datos de los registros y almacenándolos temporalmente en la memoria. En el proceso, recordé que el procesador Gameboy tiene un registro de puntero de pila para la conveniencia de cargar y cargar registros. Desafortunadamente, esta computadora no tiene ese lujo, por lo que tuvo que transferir constantemente datos manualmente desde y hacia la memoria.

Decidí dedicar tiempo a una sola seudoinstrucción CALL para llamar a una función y luego volver al punto. Sin esto, las llamadas solo están disponibles en un nivel de profundidad.

Además, dado que la máquina no admite interrupciones, tuve que implementar un terrible código de sondeo del estado del teclado. El libro discute los pasos necesarios para implementar interrupciones, pero esto complica seriamente el circuito.

Pero deja de quejarte, todavía escribí cuatro programas , y la mayoría de ellos usan algún tipo de código común para representar fuentes, entrada de teclado, etc. Este no es un sistema operativo, pero da una idea de lo que hace un sistema operativo simple.

No fue facil. La parte más difícil del programa de escritura de texto es determinar cuándo saltar a una nueva línea o qué sucede cuando presiona Enter.

 main-getInput: CALL ROUTINE-io-pollKeyboard CALL ROUTINE-io-drawFontCharacter JMP main-getInput 
El ciclo principal del programa de redacción de textos.

No me molesté en implementar la tecla Retroceso y las teclas modificadoras. Pero me di cuenta de cuánto trabajo requiere el desarrollo de editores de texto y lo tedioso que es.

Conclusiones


Fue un proyecto divertido y muy útil para mí. En medio de la programación en lenguaje ensamblador, casi me olvido de las puertas lógicas a continuación. Subí a los niveles superiores de abstracción.

Aunque este procesador es muy simple y está lejos de la CPU de mi computadora portátil, me parece que el proyecto me enseñó mucho, en particular:

  • Cómo se mueven los bits a través del bus entre todos los componentes.
  • ¿Cómo funciona ALU simple ?
  • Cómo se ve un simple bucle Fetch-Decode-Execute.
  • Que una máquina sin un registro de puntero de pila y un concepto de pila es una mierda.
  • Ese auto sin interrupciones también apesta.
  • Qué es ensamblador y qué hace.
  • Cómo interactúan los periféricos con un procesador simple.
  • Cómo funcionan las fuentes simples y cómo mostrarlas en la pantalla.
  • Cómo se vería un sistema operativo simple .

Entonces, ¿qué sigue? El libro dice que nadie ha producido tales computadoras desde 1952. Esto significa que tengo que estudiar el material en los últimos 67 años. Me llevará un tiempo Puedo ver que el manual x86 tiene 4.800 páginas lo suficiente para una lectura agradable y fácil antes de acostarse.

Tal vez me mimen un poco con el sistema operativo, el lenguaje C, mataré la noche con el kit de construcción PiDP-11 y un soldador, y luego abandonaré esto. No sé, ya veremos.

En serio, estoy pensando en explorar la arquitectura RISC, posiblemente RISC-V. Probablemente sea mejor comenzar con los primeros procesadores RISC para comprender su origen. Los procesadores modernos tienen muchas más funciones: cachés y más, quiero entenderlos. Hay mucho que aprender

¿Será útil este conocimiento en mi trabajo principal? Quizás útil, aunque poco probable. En cualquier caso, me gusta, así que no importa. Gracias por leer!

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


All Articles