Estoy construyendo una CPU simple de 16 bits en Logisim y tengo la ALU lista y los códigos de operación que quiero tener. Ahora me resulta muy difícil encontrar la codificación correcta para los comandos, de modo que los diferentes subcircuitos (por ejemplo, lógica, aritmética) no necesiten todos los cables de control (que construyen la codificación) como entrada, sino la menor cantidad posible. ¿Existen estrategias o métodos que ayuden con un diseño eficiente de código de operación?
gracias por adelantado
cpu
computer-architecture
Benjoyo
fuente
fuente
Respuestas:
Creo que es un buen enfoque estudiar algunos otros conjuntos de instrucciones.
Uno pequeño sería el MSP430 de TI, es un procesador de 16 bits con aproximadamente 22 instrucciones.
http://www.physics.mcmaster.ca/phys3b06/MSP430/MSP430_Instruction_Set_Summary.pdf
También puede consultar los AVR de Atmel, que también tienen un conjunto de instrucciones bastante pequeño.
En un pequeño proyecto mío intenté desarrollar un procesador simple de 32 bits en VHDL con un pequeño conjunto de instrucciones (14 instrucciones):
http://www.blog-tm.de/?p=80
Debido a mi tiempo libre actual no está completamente terminado. Las instrucciones se implementan pero dos no se prueban y tal vez faltan algunos indicadores de estado.
fuente
Estudie (pero no reproduzca) el enfoque ARM para la codificación de instrucciones. Está muy orientado a prefijos (como el enfoque del árbol Huffman recomendado por Dzarda) y es muy uniforme en términos de dónde está la parte de selección de registro de la instrucción.
El enfoque poco imaginativo pero confiable es enumerar todas las señales de control que tiene, que probablemente serán más de 16 bits, y luego intentar hacer una minimización lógica de estilo de mapa de Karnaugh en ellas.
fuente
Una vez intenté hacer una CPU de 4 bits con núcleo de longitud de instrucción de 8 bits en Logisim. Terminé con una máquina de estado simple, más que una CPU, realmente.
Cosas al azar para buscar
Excelente video en Computerphile sobre los árboles Huffman:
fuente
El ISA que escribí para la clase tenía un código operativo de 4 bits como este:
1XXX ALU instructions 01XX jump, jump register, call etc 001X branch not equal, branch equal zero 000X 0 - load, 1 - store
En lugar de ser el más óptimo, este es uno de los estilos más fáciles de construir / diseñar puertas porque la señal de entrada de un solo bit puede controlar por completo qué camino lógico se toma. Alternativamente, puede codificar con Huffman sus símbolos más utilizados y ponerlos a cero para obtener un código operativo de longitud fija.
fuente
Una cosa que deberá considerar es si permite cualquier forma de instrucción de varias palabras, o cualquier cosa que pueda "actuar" como una instrucción de varias palabras; si lo hace, es posible que desee considerar si usar palabras de instrucción adicionales después de la instrucción principal o prefijar las palabras antes. Permitir prefijos y palabras de continuación puede aumentar la complejidad del manejo de interrupciones, pero puede evitar la necesidad de ajustar las instrucciones de uso poco frecuente en el mismo espacio de código de operación que las de uso común.
Si las instrucciones se obtienen en el ciclo antes de que se ejecuten, se podría tener una instrucción de "ramificación condicional" que haga que se omita la siguiente palabra de instrucción o que su contenido se transfiera directamente al contador del programa; dicho diseño podría agregar cierta complejidad adicional para interrumpir la secuenciación, pero podría aliviar la necesidad de utilizar una gran parte del espacio de código de operación para las instrucciones de "ramificación", "salto" y "llamada", al tiempo que permite un rango mucho más amplio de condiciones de ramificación de lo contrario sería posible. Dado que una rama que se toma generalmente requerirá un ciclo muerto después de la ejecución de la instrucción en sí misma, independientemente de dónde provenga la dirección, hacer que la dirección provenga de la siguiente palabra que se ha obtenido pero no se ejecutará no tiene ningún costo adicional hora.
Aunque mover la dirección de destino fuera de las instrucciones de bifurcación reducirá la cantidad de espacio de código de operación que engullen, un formato de código de operación de 16 bits sigue siendo bastante limitado. Usar instrucciones de prefijo puede ayudar con eso. Si, por ejemplo, uno quiere tener 32 registros, lo que permite que cualquier registro se especifique independientemente como fuente1, fuente2 y destino requeriría 15 bits en el código de operación, lo que permite un total enorme de dos instrucciones. No muy útil Por otro lado, sería bueno poder usar cualquiera de los 32 registros para cada uno de los tres operandos. Uno podría equilibrar los dos objetivos haciendo que cualquier operación ALU que no esté precedida por un prefijo use ocho bits para hacer dos selecciones de registro de uno de dieciséis, pero que una operación ALU que sigue inmediatamente a un prefijo use algunos bits en el prefijo a lo largo con ocho de las siguientes instrucciones, para permitir la selección independiente de ambas fuentes y el destino del conjunto completo de 32. Las instrucciones que usan los registros superiores tomarían dos palabras / ciclos en lugar de uno, pero en algunos casos tal compensación podría valer la pena. La mayor dificultad con el uso de prefijos es que uno debe evitar que ocurra una interrupción entre un prefijo y la siguiente instrucción o bien asegurarse de que si se produce una interrupción allí, la instrucción después del prefijo seguirá utilizando los registros correctos [por ejemplo, al tener el programa -lógica de guardar contador almacena la dirección de la última instrucción sin prefijo ejecutada]. pero en algunos casos, tal compensación podría valer la pena. La mayor dificultad con el uso de prefijos es que uno debe evitar que ocurra una interrupción entre un prefijo y la siguiente instrucción o bien asegurarse de que si se produce una interrupción allí, la instrucción después del prefijo seguirá utilizando los registros correctos [por ejemplo, al tener el programa -lógica de guardar contador almacena la dirección de la última instrucción sin prefijo ejecutada]. pero en algunos casos, tal compensación podría valer la pena. La mayor dificultad con el uso de prefijos es que uno debe evitar que ocurra una interrupción entre un prefijo y la siguiente instrucción o bien asegurarse de que si se produce una interrupción allí, la instrucción después del prefijo seguirá utilizando los registros correctos [por ejemplo, teniendo el programa -lógica de guardar contador almacena la dirección de la última instrucción sin prefijo ejecutada].
El uso de instrucciones de varias palabras hará que algunos aspectos del diseño sean más difíciles, pero puede reducir la necesidad de tomar otras decisiones difíciles.
fuente
Este tipo tiene los mejores detalles sobre la comprensión del cableado de la parte codificada de un decodificador, que explica las líneas de control para una CPU codificada: http://minnie.tuhs.org/CompArch/Tutes/week03.html Como puede ver, su elección en Opcodes realmente impacta cuán compleja es la lógica Decode.
fuente