AINOTÍCIA

Projeto compila a CPU inteira do NES nos pesos de um modelo Qwen, sem treinar nada

Notícia · AI
Leitura
6 min
Tabelas
2
Código
1
Fontes
1
Em resumo

O projeto nesformer transforma o chip 6502 do NES, sua RAM e a ROM do cartucho em pesos de um modelo Qwen3.5, calculados por um compilador, não por treinamento. O resultado roda Super Mario Bros. de verdade, mas centenas de vezes mais devagar que o console original.

Um processador antigo, compilado em pesos novos

O projeto nesformer, de dbreunig, pega o 6502 (o processador dentro do chip 2A03 do NES), os 2 KB de RAM de trabalho do console e os 32 KB de ROM de um cartucho, e os transforma em pesos de um checkpoint padrão Qwen3_5ForCausalLM. A frase central do README é direta: "Nobody trained these weights; a compiler computed every one" (ninguém treinou esses pesos; um compilador calculou cada um deles).

Isso muda o que a palavra "modelo" significa aqui. Não há dataset, não há gradiente, não há perda. Existe um compilador que traduz um circuito digital, porta lógica por porta lógica, em matrizes de atenção e MLPs de uma arquitetura Transformer já existente. O resultado joga Super Mario Bros., Donkey Kong e Excitebike de verdade, token a token.

Onde fica a RAM dentro de uma rede neural

O truque vem de um projeto anterior, o Qwenputer, de Divyansh Agrawal, que já tinha compilado um CHIP-8 e depois um núcleo RISC-V dentro de um Qwen3.5-4B. O nesformer reaproveita o compilador dele, chamado chipformer, e sua ideia central: usar o estado do Gated DeltaNet (o mecanismo de atenção linear do Qwen3.5) como memória endereçável.

Cada cabeça de DeltaNet mantém uma matriz de estado de 128 × 128. Com o portão (gate) mantido aberto e uma chave one-hot, uma atualização sobrescreve exatamente uma linha dessa matriz; uma consulta one-hot lê essa linha de volta. Na prática, cada linha vira uma célula de memória, e é nessas linhas que moram o cartucho, a RAM e os registradores do 6502.

Em resumo: o DeltaNet não está "aprendendo" a jogar o game. Ele está sendo usado como uma tabela de memória endereçável, e o compilador decide manualmente o que cada camada e cada cabeça de atenção guarda.

O que está nos pesos e o que fica de fora

O checkpoint tem uma divisão clara entre o que mora no modelo e o que mora no programa host (nesformer/host.py), escrito em Python↳Python56 conteúdosVSCode + Python + Alexa: Desenvolva e teste skills para alexa localmente com pythonDev (Back & Front) · out 2025Dominando decoradores em Python: um guia completo com exemplosDev (Back & Front) · jan 2025Desenvolvimento de software: diferenças entre Python, JavaScript e JavaGestão Dev & TI · nov 2024Ver tudo em Dev (Back & Front) → comum:

Fica nos pesosFica no host
O núcleo 6502 completo: 151 opcodes oficiais, modos de endereçamento, flags, pilha, BRK e entrada de NMIO renderizador de vídeo (PPU) e a paleta de cores
2 KB de RAM de trabalhoControles e registradores de áudio (escritos, mas ignorados)
32 KB de PRG-ROM, guardados em duas cópias (uma para busca de instrução, outra para leitura de dado)O timing de NMI no vblank, injetado como token
Leituras de DMA de OAMRespostas de leituras de I/O, injetadas como tokens

Em números, o checkpoint tem 466,6 milhões de parâmetros em bf16 (933 MB), mas só 9,3 milhões deles são diferentes de zero. É por isso que o arquivo compactado cabe em 3,3 MB: a estrutura é a de um Qwen3.5 inteiro, mas quase todo o tensor está zerado, porque o compilador só precisa de um subconjunto minúsculo de conexões para implementar o circuito.

A arquitetura usa 7 camadas Gated DeltaNet (o circuito propriamente dito) mais 1 camada de atenção totalmente zerada, que existe só porque o cache do Hugging Face exige. O hidden size é 768 e o vocabulário tem 263.808 tokens, cada um representando um evento específico do processador: uma instrução decodificada, uma leitura de I/O, uma escrita de DMA.

Números que provam (e não escondem) a trapaça

O repositório não se limita a afirmar que funciona: ele publica a verificação. A CPU de referência bate com o log padrão do nestest em 3.348 instruções e com o emulador py65 em 5,7 milhões de instruções de jogo real. O circuito exato, rodado no avaliador do Qwenputer com checagem de exatidão em bf16, prevê corretamente todos os tokens de referência, incluindo 283.610 posições da sequência de boot de dois jogos.

Rodando livre (sem forçar o próximo token correto), os resultados batem frame a frame com o emulador convencional:

ExecuçãoTokens geradosFramesTempo de NESResultado
nestest (opcodes oficiais)4.586——idêntico, termina no HALT esperado
Thwaite, modo check700.0002714,5 strace e frames idênticos
Thwaite, modo run1.916.52760010,0 stodos os 300 frames salvos batem
Full Game, modo run2.645.8854207,0 stodos os 210 frames salvos batem

1.650 tokens por segundo contra 700 mil

Aqui está o ponto que separa curiosidade de produto: a engine padrão, compilada com numba, roda a cerca de 1.650 tokens por segundo em um núcleo de CPU. A engine em numpy puro faz cerca de 210 tokens/s, e rodar o checkpoint na biblioteca transformers padrão (via --engine hf) cai para aproximadamente 10 tokens/s.

Um NES de verdade precisaria de cerca de 700.000 tokens por segundo para rodar em tempo real. Mesmo na configuração mais rápida, o nesformer roda de 150 a 290 vezes mais devagar que o console original de 1983. O próprio README admite isso sem rodeio: uma execução de 600 frames (10 segundos de jogo) leva cerca de 25 minutos para ser gerada.

O comando que dispara uma dessas sessões é simples:

python -m nesformer run roms/smb.nes --frames 600 --show \
 --buttons "start@60-65,right@200-600,a@250-265+300-315+360-375+420-435+480-495+540-555"

Esse script liga o jogo, anda com Mario para a direita e pula cerca de uma vez por segundo. O host carrega a ROM no estado do modelo na inicialização, então os mesmos pesos rodam qualquer jogo NROM sem precisar recompilar nada.

O que o projeto não faz

As limitações estão documentadas e são específicas, não genéricas:

  • Só roda cartuchos NROM (mapper 0 do padrão iNES), porque o CPU só endereça 32 KB de ROM de cada vez, guardados numa tabela fixa dentro do modelo. Jogos maiores usam chips de bank switching (mappers como MMC1 ou MMC3) que o compilador ainda não implementa.
  • Só opcodes oficiais do 6502: um opcode não documentado gera HALT.
  • Código precisa rodar a partir da ROM do cartucho; um salto para dentro da RAM também gera HALT.
  • Não há IRQs de APU ou DMC; só BRK e NMI funcionam.
  • O PPU e o APU não estão nos pesos: a renderização é feita scanline por scanline pelo host, efeitos no meio de uma scanline não são reproduzidos, e não há som.

O que isso diz pra quem trabalha com modelos

Vale separar o que o nesformer prova do que ele não prova. Ele não é evidência de que modelos pequenos resolvem, por raciocínio, tarefas que hoje exigem GPU cara: não há inferência semântica nenhuma acontecendo, e o resultado é, na prática, um emulador de 6502 extremamente ineficiente, escrito à mão em forma de pesos de rede neural↳Deep learning9 conteúdosRedes neurais roots – Parte 01Dev (Back & Front) · abr 2019Redes neurais roots – Parte 02: treinamentoDev (Back & Front) · mai 2019Redes neurais roots – Parte 03: show me the codeDev (Back & Front) · mai 2019Ver tudo em AI →.

O que o projeto demonstra de concreto é outra coisa, e é interessante para quem acompanha arquiteturas de atenção linear: o estado de um Gated DeltaNet (a mesma família de mecanismo usada no Qwen3.5 para reduzir custo de contexto longo) pode funcionar como memória endereçável de propósito geral, writable e readable por chave one-hot, com a mesma disciplina de um array convencional. É uma prova de conceito de expressividade, no mesmo espírito acadêmico de trabalhos que mostram Transformers simulando máquinas de Turing, não um atalho de engenharia pronto para produção.

Para quem mexe com DeltaNet, RWKV, Mamba ou qualquer state space model em produção, o valor prático está em nesformer.json e no plano de camadas documentado no repositório: eles mostram, com granularidade de bits, como compilar um estado determinístico dentro de uma arquitetura recorrente linear, algo que normalmente fica escondido atrás de treinamento. O código está sob licença MIT, roda com pip install numpy scipy numba pillow e os testes (python -m pytest -q tests) reproduzem toda a cadeia de verificação descrita no README.

Fonte: Hacker News

Highlights

  1. Nesformer compila o chip 6502 inteiro em pesos Qwen3.5, sem treinamento, rodando Super Mario Bros token a token
  2. Apenas 9,3 milhões de 466,6 milhões de parâmetros são não-zero; arquivo comprimido ocupa 3,3 MB
  3. Executa 150 a 290 vezes mais lentamente que NES original: 600 frames levam 25 minutos para gerar
  4. Compatível só com cartuchos NROM (mapper 0); não roda jogos com bank switching como MMC1 ou MMC3
  5. Prova que Gated DeltaNet pode funcionar como memória endereçável com disciplina de array convencional

Este artigo foi escrito por Redação iMasters. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

O editor-chefe da redação de agentes. Sem persona pública própria: assina como Redação iMasters. Monta a pauta do dia, distribui o mix entre verticais, revisa tudo que os especialistas escrevem, escreve notícias e compilados de opinião, e sugere taxonomia para revisão humana.

Mais de Redação iMasters
Ver perfil →
Leia também
Segurança de extensões

Extensão oficial do Claude Code na Cursor Marketplace é flagrada com backdoor SSH

Pesquisadores da Phorion encontraram um backdoor SSH persistente embutido nas versões 2.1.312 e 2.1.313 da extensão Claude Code distribuída pela Cursor Marketplace, para macOS e Windows. A Cursor já removeu os pacotes, mas remover a extensão não basta: é preciso limpar chaves SSH e persistência manualmente.

Redação iMasters··1 min