Como projetar eficientemente o opcode para uma CPU?

12

Estou construindo uma CPU simples de 16 bits no Logisim e tenho a ALU pronta e os códigos de operação que eu quero ter. Agora, acho realmente difícil encontrar a codificação correta para os comandos, para que os diferentes subcircuitos (por exemplo, lógica, aritmética) não precisem de todos os fios de controle (que constroem a codificação) como entrada, mas o mínimo possível. Existem estratégias ou métodos que ajudam com um design eficiente de código de operação?

thx antecipadamente

Benjoyo
fonte
1
Crie sua ALU primeiro e veja quais cabos de controle ele precisa. Em seguida, conecte-os diretamente ao registro "instrução atual". O mesmo para a lógica de controle de acesso à memória e quaisquer outras principais classes de códigos de operação. Em seguida, use os bits restantes para selecionar qual subcircuito será ativado.
precisa saber é o seguinte
1
Há também o artigo original de Ken Chapman de sua máquina de estado programável de 8 bits KCPSM, também conhecida como PicoBlaze. Descreve como ele escolheu as instruções e projetou o ISA. dc.uba.ar/materias/disfpga/2010/c2/descargas/…
Paebbels

Respostas:

9

Eu acho que é uma boa abordagem estudar alguns outros conjuntos de instruções.

Um pequeno seria o MSP430 da TI, é um processador de 16 bits com cerca de 22 instruções.

http://www.physics.mcmaster.ca/phys3b06/MSP430/MSP430_Instruction_Set_Summary.pdf

Você também pode procurar nos AVRs da Atmel, eles também possuem um conjunto de instruções bastante pequeno.

Em um pequeno projeto meu, tentei desenvolver um simples processador de 32 bits em VHDL com um pequeno conjunto de instruções (14 instruções):

http://www.blog-tm.de/?p=80

Devido ao meu tempo livre atual, ele não está totalmente concluído. As instruções são implementadas, mas duas não são testadas e talvez alguns sinalizadores de status estejam ausentes.

TM90
fonte
Mas não encontrei algo em que pudesse ver qual é a codificação real e por que foi escolhida para ser assim.
Benjoyo 27/01
Você pode encontrar a codificação reall no repositório : github.com/TM90/MISC_Processor/raw/master/Documentation/… . A razão pela qual escolhi essas codificações de uma maneira que a lógica no decodificador de instruções ficou mínima.
TM90 27/01
7

Estude (mas não replique) a abordagem ARM para codificação de instruções. É fortemente orientado a prefixos (como a abordagem de árvore de Huffman recomendada por Dzarda) e altamente uniforme em termos de onde o registrador seleciona parte da instrução.

A abordagem sem imaginação, porém confiável, é enumerar todos os sinais de controle você possui, que provavelmente terão mais de 16 bits, e tentar executar a minimização lógica do estilo do mapa de Karnaugh neles.

pjc50
fonte
Eu realmente não entendo o que você quer dizer com sinais de controle.
Benjoyo 27/01
O que descobri e gostei no ARM é o campo de condição, incluirei isso.
Benjoyo 27/01
Os sinais de controle são as entradas para os vários multiplexadores e permitem que os dados diretos entre as partes da CPU.
Pjc50
Para uma arquitetura de 16 bits, não acho que a codificação de instruções do ARM seja apropriada. Mayby thumb2 é melhor. Mas eu gosto da maneira como MIPS de codificação, simples e fácil de entender, embora um pouco desperdício
phuclv
4

Uma vez eu tentei fazer uma CPU de 4 bits com núcleo de comprimento de instrução de 8 bits no Logisim. Acabou com uma máquina de estado simples, mais do que uma CPU, realmente.

Coisas aleatórias para procurar

  • Árvores Huffman
  • Codificação de comprimento fixo ou variável?
  • É um design de von Neumann com espaço de endereço único ou no estilo Harvard com dados / programa separados?

Excelente vídeo no Computerphile sobre árvores Huffman:

https://www.youtube.com/watch?v=umTbivyJoiI

Dzarda
fonte
A codificação Huffman não funciona para uma codificação de comprimento fixo, certo?
Benjoyo 27/01
@ Benjoyo Posso imaginar um cenário com os bits sobressalentes sendo usados ​​para variações das instruções mais usadas, fornecendo mais funcionalidade.
Dzarda
Mas não entendo que tipo de otimização isso traz. Isso não me ajuda com o design do circuito. Qual é o objetivo ao usar a codificação Huffman para opcode?
Benjoyo 27/01
4

O ISA que escrevi para a classe já teve um código operacional de 4 bits, assim: 1XXX ALU instructions 01XX jump, jump register, call etc 001X branch not equal, branch equal zero 000X 0 - load, 1 - store

Em vez de ser o mais ideal, esse é um dos estilos mais fáceis de construir / projetar portões, porque o sinal de entrada de um único bit pode controlar inteiramente qual caminho lógico é seguido. Como alternativa, você pode codificar com Huffman seus símbolos mais usados ​​e zerá-los para obter um código operacional de comprimento fixo.


fonte
Esse tipo de otimização é o que estou procurando no momento. Mas eu tenho um código de operação de 5 bits e luto para agrupar os comandos para que faça sentido no circuito.
Benjoyo 27/01
@ Benjoyo, você pode ter várias instruções de ALU com o conjunto de bits superior. Também a cobertura da minha condição de salto era muito fraca e a maioria dos galhos normais exigiria duas instruções. Geralmente, eu pensava nas categorias como: Matemática / Controle / Memória
3

Uma coisa que você precisa considerar é se deve permitir qualquer forma de instrução com várias palavras ou qualquer coisa que possa "agir" como uma instrução com várias palavras; se o fizer, convém considerar se deve usar palavras de instruções adicionais após a instrução principal ou prefixar as palavras antes dela. Permitir prefixos e palavras subsequentes pode aumentar a complexidade do tratamento de interrupções, mas pode evitar a necessidade de ajustar instruções raramente usadas no mesmo espaço de código de operação que as usadas com freqüência.

Se as instruções são buscadas no ciclo antes de serem executadas, pode-se ter uma instrução de "ramificação condicional" que faz com que a próxima palavra de instrução seja ignorada ou então seu conteúdo é transferido diretamente para o contador do programa; esse design pode adicionar uma complexidade extra à interrupção do seqüenciamento, mas pode facilitar a necessidade de usar grande parte do espaço do código de operação para instruções de "ramificação", "salto" e "chamada", permitindo uma variedade muito maior de condições de ramificação do que seria possível. Como uma ramificação obtida geralmente requer um ciclo morto após a execução da instrução, independentemente da origem do endereço, ter o endereço da palavra seguinte que foi buscada, mas não será executada, não custa mais Tempo.

Embora a remoção do endereço de destino das instruções de ramificação reduza a quantidade de espaço do código de operação que eles consomem, um formato de código de operação de 16 bits ainda é bastante restrito. O uso de instruções de prefixo pode ajudar com isso. Se, por exemplo, alguém quiser ter 32 registros, permitir que qualquer registro seja especificado independentemente como origem1, origem2 e destino exigiria 15 bits no código de operação, permitindo um total impressionante de duas instruções. Não é muito útil. Por outro lado, seria capaz de usar qualquer um dos 32 registros para cada um dos três operandos. Pode-se equilibrar os dois objetivos fazendo com que qualquer operação da ALU que não seja precedida por um prefixo use oito bits para fazer duas de dezesseis seleções de registro, mas uma operação da ALU que segue imediatamente um prefixo use alguns bits no prefixo junto com oito da instrução a seguir, para permitir a seleção independente de ambas as fontes e o destino do conjunto completo de 32. As instruções que usam os registros superiores precisariam de duas palavras / ciclos em vez de um, mas em alguns casos essa troca poderia valer a pena. A maior dificuldade com o uso de prefixos é que é preciso impedir que uma interrupção ocorra entre um prefixo e a próxima instrução ou garantir que, se ocorrer uma interrupção, a instrução após o prefixo ainda use os registros corretos [por exemplo, tendo o programa -counter save logic armazena o endereço da última instrução sem prefixo executada]. mas, em alguns casos, essa troca poderia valer a pena. A maior dificuldade com o uso de prefixos é que é preciso impedir que uma interrupção ocorra entre um prefixo e a próxima instrução ou garantir que, se ocorrer uma interrupção, a instrução após o prefixo ainda use os registros corretos [por exemplo, tendo o programa -counter save logic armazena o endereço da última instrução sem prefixo executada]. mas, em alguns casos, essa troca poderia valer a pena. A maior dificuldade com o uso de prefixos é que é preciso impedir que uma interrupção ocorra entre um prefixo e a próxima instrução ou garantir que, se ocorrer uma interrupção, a instrução após o prefixo ainda use os registros corretos [por exemplo, tendo o programa -counter save logic armazena o endereço da última instrução sem prefixo executada].

O uso de instruções com várias palavras dificultará alguns aspectos do design, mas poderá reduzir a necessidade de tomar outras decisões difíceis.

supercat
fonte
0

Esse cara tem os melhores detalhes para entender a fiação rígida da parte codificada de um decodificador, o que explica as linhas de controle de uma CPU codificada: http://minnie.tuhs.org/CompArch/Tutes/week03.html Como você pode ver, sua A opção em Opcodes realmente afeta o quão complexa é a lógica de decodificação.

cmacdona101
fonte