Haiku forth para o panel de LED

No tópico sobre o Painel de LED que o @douglas abriu, eu comentei sobre uma implementação de FORTH que eu comecei a fazer para fazer códigos do Forth Salon serem mostrados no painel:

Resolvi abrir esse tópico aqui para continuar a discussão separada e focar só na parte do interpretador aqui.

O código está aqui, e a ideia é fazer um site similar ao FORTH Salon mas, ao invés de mostrar localmente em JavaScript como o FS faz, isso mostraria no painel de LED. Como o painel é controlado por uma RPi, é possível implementar isso usando o Lwan (e por isso que está no repositório dele).

2 Likes

Consegui fazer o negócio gerar um GIF! :slight_smile:

Vou dar uma limpada no código mas logo mais faço o push pro GitHub. Não tá perfeito também, o resultado tá meio azulado e algumas cores estão erradas, mas o resultado tá claramente no caminho certo.

twist

1 Like

Gastei um tempinho hoje fazendo otimizações que são necessárias para que os demos funcionem com desempenho aceitável numa RPi:

  • Inlining é feito para todas as palavras de usuário
  • O código é verificado estaticamente se faz sentido com relação ao uso da pilha
  • Foram removidas as verificações de pertencimento à pilha e de execução de cada instrução, já que o código passa por um verificador
  • Redução de uso de memória, usando o próprio endereço das palavras para saber se é uma palavra fornecida pelo ambiente ou uma definida pelo usuário

Ainda preciso fazer algumas coisas:

  • Remover uso da pilha e usar posições fixas no contexto de execução. Isso remove as operações de push/pop que colocam dependência no índice da pilha, permitindo mais paralelismo a nível de instruções
  • Experimentar com um compilador JIT que faz chamadas diretas aos builtins. Fiz um blog post a esse respeito há uns anos atrás, que será útil agora. Várias melhorias podem ser feitas no JIT ao longo do tempo, incluindo:
    • “Inlining” de algumas palavras comuns, como operações aritméticas
    • Redução de peso para algumas operações (por exemplo, x 2 * virar x dup +)

Ontem eu implementei um esquema diferente de dispacho de instruções da VM, e consegui uma melhora no desempenho de 2x. A ideia é, ao invés de usar um switch-case como estava usando, é criar uma union com as coisas que uma instrução pode precisar, e cada instrução ser implementada por uma função, que pega o que que precisa da próxima união, faz o que precisa fazer, e executa a próxima (que sabemos que é relativa à instrução atual). É meio que um CPS.

Aqui tem um blog post explicando melhor como a técnica funciona: Faster virtual machines: Speeding up programming language execution - Mort's Ramblings

Infelizmente, não é eficiente suficiente pro propósito que eu quero, então estou pensando em como fazer um compilador. A ideia é gerar um arquivo C que eu possa compilar e linkar como uma biblioteca compartilhada e carregar com dlopen(), funcionando mais ou menos como um compilador JIT.

Por exemplo, para uma imagem de 64 * 64, e uma animação em 60fps, são 245760 execuções de um haiku por segundo. Nós temos 5 painéis de 64 * 64, o que dá 1228800 execuções por segundo para manter uma animação fluída em 60fps.

O compilador JIT do Forth Salon gera código para um fragment shader que é executado na GPU através das abstrações disponíveis pro JavaScript, e portanto é possível fazer isso no browser. É bem possível que eu tenha que fazer a mesma coisa também, e pra isso esse compilador que eu mencionei acima, que gera C, poderia gerar algum código útil para uma GPU. Eu nunca futuquei nessas coisas de shader, então vou precisar gastar um tempinho nisso fazendo uns experimentos.

Comecei a escrever o compilador JIT que gera um .so e carrega com dlopen(). Um teste preliminar parece promissor: mesmo se uma GPU não estiver disponível para compilar o Haiku para um fragment shader, deve ser possível fazer algo em código nativo para a CPU mesmo – e o código vai ficar parecido.