


Crie um emulador que reproduza o barramento e a temporização do hardware real
Use ao criar ou corrigir um emulador. Divide o código por partes do hardware, copia o barramento, a temporização e o DMA do hardware real, testa com programas que passam no aparelho real e mantém estáveis os estados salvos e a API pública.
Para usar estas regras de IA
## Explique o código incomum e rode as checagens de tipos e os testes
Escreva o código do emulador para profissionais que talvez não conheçam o hardware original. Explique por que uma regra de temporização, um efeito colateral ou uma solução alternativa existe, em vez de presumir que uma implementação incomum seja autoexplicativa. Inclua links para referências de hardware reconhecidas quando elas ajudarem a esclarecer o comportamento.
Localize e use os comandos documentados do repositório para formatação, análise estática, verificação de tipos, testes, compilações, modo de monitoramento e avaliações de desempenho. Trate as verificações obrigatórias como parte da alteração:
- Execute a formatação e os testes específicos durante as iterações.
- Execute a verificação de tipos quando declarações públicas ou limites tipados forem alterados.
- Execute a suíte completa considerada oficial antes de registrar a alteração ou fazer a entrega.
- Execute a avaliação de desempenho em mudanças importantes ou quando houver suspeita de regressão de desempenho.
- Mantenha refatorações não relacionadas separadas de uma correção específica.
Atualize os exemplos públicos e as referências da API quando métodos, opções, retornos de chamada, exportações ou formatos de entrada aceitos forem alterados. Coloque detalhes locais da implementação em comentários próximos; reserve as orientações do projeto para a arquitetura e as regras aplicáveis a vários componentes.
## Divida o emulador em componentes que sigam as partes do hardware
Organize o emulador em torno dos subsistemas de hardware que ele modela. Use um pequeno coordenador para sincronizar os componentes e disponibilizar retornos de chamada para renderização, áudio, estado e atualizações de memória persistente.
Separe as responsabilidades de processadores, vídeo, áudio, mapeamento de cartucho ou memória, carregamento de programas, auxiliares de renderização, controladores e serialização. Dê uma interface clara a cada componente e permita que ele gerencie seu próprio estado interno.
Use herança somente quando as variantes de hardware compartilharem um comportamento-base real e substituírem regras específicas de mapeamento ou alternância de bancos. Prefira composição para subsistemas independentes e evite acessos ocultos entre os limites dos componentes.
Defina uma base de tempo comum. A execução por quadros ainda exige contagem precisa de ciclos dentro de cada quadro, enquanto os aplicativos hospedeiros continuam responsáveis pela temporização da apresentação e pelo agendamento.
Centralize a conversão de estados salvos por meio de contratos simétricos de serialização e restauração usados por todos os componentes com estado.
## Reproduza cada leitura e escrita do barramento, incluindo os acessos fictícios
Modele o barramento como um comportamento com estado, não como uma simples consulta de endereço para valor. O hardware real pode reter o valor mais recente, devolver dados armazenados em registradores de retenção de endereços não mapeados ou somente de escrita, ou controlar apenas determinados bits.
Acompanhe registradores de retenção separados quando barramentos de hardware diferentes mantiverem estados independentes. Atualize o registrador apropriado a cada carregamento, escrita, operação de pilha, busca de código de operação e busca de vetor de interrupção observável. Quando um dispositivo controlar apenas parte de um valor, combine esses bits com o estado retido do barramento exatamente como o hardware faz.
Implemente leituras e escritas fictícias como operações reais do barramento. Elas podem atualizar valores retidos e acionar efeitos colaterais de E/S mesmo quando o programa nunca usa o valor devolvido.
Codifique explicitamente a sequência do barramento para cada modo de endereçamento:
- O endereçamento indexado pode ler um endereço intermediário antes de uma correção de página.
- A indexação de página zero pode ler o endereço não indexado antes de aplicar o índice.
- A indexação indireta pode ler um ponteiro ou endereço intermediário antes de alcançar o endereço efetivo.
- Instruções de armazenamento e de leitura-modificação-escrita podem realizar acessos fictícios obrigatórios mesmo sem cruzamento de página.
- Uma instrução de leitura-modificação-escrita pode gravar o valor original antes de gravar o valor modificado.
Preserve a ordem específica da instrução quando uma busca ocorrer antes ou depois de uma operação de pilha. Reordenar operações que produzem os mesmos valores finais nos registradores ainda pode ser observavelmente incorreto no barramento.
## Sincronize os dispositivos no meio da instrução e trate o DMA como ciclos reais do barramento
Quando o emulador executa um componente de forma atômica, mas o hardware real avança os componentes em sincronia, um estado desatualizado pode aparecer em acessos a registradores no meio de uma instrução. Corrija isso no limite em que o acesso se torna observável.
Registre quantas operações de barramento a instrução atual concluiu. Antes de ler ou gravar um registrador de dispositivo sincronizado, avance esse dispositivo pela proporção exata de ciclos de relógio correspondente às operações decorridas. Subtraia o trabalho já aplicado do avanço posterior no nível do quadro para que o tempo nunca seja contado duas vezes.
Modele a criação do sinalizador de interrupção separadamente da entrega da interrupção. Um controle de inibição pode impedir a criação de um sinalizador de estado, em vez de apenas suprimir o sinal externo de interrupção. Os testes devem distinguir esses comportamentos.
Represente DMA como o controle de ciclos reais do barramento. Uma transferência pode alterar o valor atual do barramento, atrasar o avanço do processador ou mudar o resultado de instruções cuja saída dependa do estado do barramento. Preserve a ordem entre DMA, acessos de instruções e efeitos colaterais dos dispositivos.
Implemente instruções não oficiais ou de casos extremos documentadas somente com base em referências e testes confiáveis. Não simplifique seu comportamento de ciclos apenas porque programas comuns não as utilizam.
## Teste com programas que comprovadamente passam no hardware real
Use várias camadas de testes, cada uma com uma finalidade distinta:
- Testes unitários verificam inicialização, semântica de instruções, regras de mapeamento, espelhamento de memória, transições de estado e tratamento de erros.
- Testes de regressão específicos fixam buffers de quadro, amostras de áudio, rastros do barramento ou outras saídas determinísticas.
- Estruturas de integração executam programas de diagnóstico confiáveis e comparam o estado detalhado da máquina ou códigos de erro.
- Suítes de precisão de hardware abrangem interações que testes isolados de instruções não conseguem revelar.
Considere corretos os programas de referência consolidados quando se souber que passam em hardware real. Investigue o emulador, a estrutura de testes, a configuração de teste e o ambiente antes de culpar o programa de referência.
Registre explicitamente as falhas aceitas com uma justificativa específica e limitada. Uma lista de falhas conhecidas não autoriza ocultar novas regressões nem ampliar uma exceção existente.
Teste os valores finais e a ordem das operações quando o hardware puder observar acessos intermediários. Adicione um caso de regressão sempre que uma correção da especificação ou um comportamento antes classificado incorretamente alterar a implementação.
## Faça os estados salvos se restaurarem por completo e pare a execução após uma falha
Os estados salvos devem incluir todos os componentes que afetem a execução futura, inclusive os estados do processador, vídeo, áudio, mapeador, registrador de retenção, interrupção e temporização. Verifique se a serialização seguida da restauração reproduz a execução, e não apenas se os dados podem ser analisados.
Disponibilize a memória persistente por meio de um retorno de chamada claro ou de um limite de armazenamento, em vez de acoplar o núcleo a um único ambiente hospedeiro.
Mantenha os controladores comuns como máquinas de estado simples, com transições explícitas de botões e protocolos seriais. Modele periféricos especializados por meio de APIs dedicadas que preservem seus comportamentos distintos de espaço, temporização ou detecção de luz.
Após uma exceção de execução irrecuperável, defina um estado explícito de falha e impeça a continuação da execução de quadros. Exija uma reinicialização ou uma nova carga do programa documentada para recuperar, em vez de continuar a partir de um estado parcialmente alterado.
Mantenha estáveis as entradas de programa aceitas e os tipos públicos de retorno de chamada. Mantenha as declarações públicas de tipos junto com a implementação para que os consumidores no navegador e no servidor observem o mesmo contrato de API.
## Gere os arquivos só pela build e informe o que ficou sem teste
Gere pacotes de distribuição, arquivos minificados, mapas de código-fonte e declarações por meio da compilação aprovada. Não edite diretamente as saídas geradas.
Verifique todos os alvos de execução e formatos de módulo que o projeto afirma aceitar. A integração contínua deve executar as mesmas verificações de formatação, análise estática, compilação, tipos e testes exigidas localmente.
Antes de alterar o comportamento do hardware, consulte especificações reconhecidas e notas de implementação confiáveis. Documente o motivo de um código não óbvio junto à operação afetada, incluindo a consequência observável de mudar sua ordem.
Revise a comparação final das alterações em busca de edições acidentais em arquivos gerados, documentação pública desatualizada, caminhos de temporização não testados e limpezas não relacionadas. Relate as verificações específicas executadas, os resultados das avaliações de desempenho quando pertinentes, as falhas conhecidas e qualquer caminho de hardware que permaneça sem verificação.
