Retomando a saga sessentaeoitomilheira de Mestre Jecel (Parte 1, Parte 2, Interlúdio) hoje mergulharemos de cabeça no minimalismo e conheceremos o Computador Mínimo. Também neste capítulo: um assembler 68000 feito em FORTRAN. Para mainframe. Ou melhor, para dois mainframes diferentes. Sim, WTF. Se não acredita, leia abaixo:
Resumo do projeto 3: desenvolver um projeto tão ambicioso quanto o “super micro” sem nenhuma experiência anterior com computadores 68000 não era uma boa ideia, de modo que seria importante comprar uma placa de desenvolvimento ou então construir um micro bem simples para testes iniciais. Acabamos adotando a segunda opção.
Com o projeto do “super micro” (que vai ser descrito na parte 4) em andamento, o fato de que os projetos anteriores nunca saíram do papel passou a ser um problema. Se fosse comprada uma placa da Motorola e ela não funcionasse, o defeito com certeza estaria no uso da mesma. Poderíamos supor que o projeto estava 100% certo e que a placa já havia sido testada depois de fabricada e por isso não teria componentes com defeito e nem problemas de montagem. Já numa placa nossa provavelmente teríamos alguns erros de projeto e também erros de montagem. Também enfrentaríamos problemas de software, já que iríamos desenvolver tudo o que usaríamos. Quando aparecessem defeitos, seria muito difícil localizar a causa.
O elemento mais básico de infraestrutura que precisávamos era um montador (“assembler”) para 68000. O Osvaldo se prontificou a desenvolver isso no Burroughs B6900 do CCE. O LSI-USP não tinha créditos para usar esta máquina, mas um professor amigo do Osvaldo dava aulas na ECA-USP (Escola de Comunicações e Artes) e tinha créditos sobrando. O CCE distribuía créditos uniformemente pelas unidades da USP, mas ninguém mais na ECA queria usar computadores ao contrário da Poli, IME ou Física. Como o pessoal do LSI não poderia usar a ferramenta no B6900, o Takeo exigiu que o assembler fosse escrito em Fortran para que pudesse depois ser portado para o mini da HP do laboratório. Isso complicou terrivelmente o projeto, já que manipulação de textos não é o forte do Fortran. Provavelmente deu o triplo do trabalho que se tivesse sido usado o Algol.
O Osvaldo tomou o cuidado de criar uma biblioteca para isolar as características da máquina. Por exemplo: uma variável inteira era de 48 bits no Burroughs e guardava 6 caracteres, mas era só 16 bits no HP e guardava 2 caracteres. O B6900 usava caracteres EBCDIC e o HP usava ASCII. Sem esta camada extra não seria viável portar o programa de uma máquina para a outra, mas foi um atraso no projeto. E no fim, o programa nunca rodou em nenhuma máquina além do Burroughs.
Por mais testes que o Osvaldo colocasse no programa, ele só poderia verificar conformidade com especificações escritas. Para testar no mundo real seria necessário rodar os binários gerados pelo assembler numa máquina com o 68000. As placas de desenvolvimento da Motorola não pareciam ser muito atraentes e o projeto anterior não tinha dado certo justamente pela falta de dinheiro para comprar placas prontas. Por isso resolvemos que a melhor maneira de testar o assembler (e futuro compilador C) seria construir uma máquina mínima com o 68000. Eu projetei em poucos minutos um computador com o processador, 128KB de memória dinâmica, duas EPROMs, uma porta serial, um circuito de reset e um oscilador de 8MHz. Este último circuito, apesar de trivial, acabou tomando a maior parte do tempo de projeto. Pelo que eu me lembro, não havia um controlador de unidades de disquetes. Mas o software foi escrito supondo que havia este periférico. Talvez o projeto desta parte tenha ficado para uma segunda etapa.
O Takeo gostou da ideia, mas rejeitou o controlador de memória dinâmica que eu projetei usando TTLs. Ele disse que isso tinha estragado projetos anteriores do laboratório e que havia sido adotada a política de ou usar memórias estáticas ou o controlador 8202 da Intel. Para este projeto ele me fez usar o 8203, capaz de operar com memórias de 64Kbits. Eu não gostei muito, já que a única parte que eu havia construído e testado do computador Z80 Einstein foi justamente um circuito de memória dinâmica e tinha funcionado direitinho. Mas, como veremos nos projetos 5 e 6, o Takeo tinha razão de se preocupar.
Enquanto um técnico construía a máquina, eu escrevi o software para ela no papel. Eu usava o C como pseudo-código e a ideia era depois reescrever tudo em linguagem de montagem. Era meu primeiro programa em C e eu não me preocupei de deixar 100% correto já que não seria compilado mesmo. O programa seria gravado nas EPROMs e deveria ser um sistema monitor da máquina. Ao invés de escrever um debugger tradicional, resolvi deixar o mais parecido possível com o shell do Unix. Assim, todos os comandos tinham redireção de entrada e saída (“<” e “>”) mas como não era multitarefa não tinham “pipes” (“|”).
O sistema de arquivo usava “inodes” como no Unix, mas era bem mais simples. Os quatro primeiros inodes eram especiais: arquivo de inodes, espaço livre, diretório raiz e blocos ruins. O setor 0 do disco era o início do arquivo de inodes, mas o resto dos inodes poderiam estar em qualquer lugar do disco e não numa área especial e fixa como na maioria dos sistemas de arquivos. O “espaço livre” era um arquivo que ocupava todo o disco que não estivesse sendo usado por outro arquivo. Ao criar um novo arquivo ou crescer um existente, blocos eram transferidos do espaço livre. Ao ser apagado um arquivo, os blocos eram devolvidos. Note que isso tende a deixar um disco bem fragmentado. O diretório raiz era um arquivo normal e podia ficar em qualquer lugar no disco. O arquivo de blocos ruins era como o de espaço livre mas era criado na hora da formatação e não era alterado depois. Simplesmente evitava que certos blocos fosse usados pelo sistema de arquivos. Para disquetes isso não era muito importante, mas na época os discos rígidos vinham com uma etiqueta colada listando os blocos ruins.
A parte mais inovadora do sistema é que regiões de memória poderiam ser acessadas como se fossem arquivos. Bastava usar algo como $2000:256 ou $2000-$20FF (onde “$” quer dizer hexadecimal e “base:comprimento” e “base-fim” representam uma faixa de memória) onde um nome de arquivo era esperado que todas as funções da biblioteca do Unix funcionariam como deveriam. Isso permitiria comandos como:
od $100-$1FF
para listar em octal uma região de memória, ou
cp $0E00000:30 /teste/x.bin
para salvar um trecho de memória no disco, ou
$100-$1C7 /imagem/v1
para iniciar a execução em $100 com breakpoint em $1C7 e um arquivo como parâmetro.
Na verdade a memória também era organizada como um sistema de arquivos, mas bem mais primitivo que o do disco. A primeira vez que um comando fosse chamado, ele seria copiado para o espaço livre mais alto na memória e executado lá. Se fosse chamado outra vez, ele seria encontrado neste “cache” e não precisaria ser trazido do disco outra vez. Se um programa fosse apagado da memória, todos os abaixo dele seriam movidos para cima para tapar o buraco. Os programas deveriam poder rodar em qualquer endereço.
A máquina ficou pronta, mas com um problema: não conseguiram comprar o 8203 e o laboratório só tinha o 8202 em estoque. Assim, aquele soquete estava vazio e a única memória usável do computador eram os registradores do 68000. Escrevi um programa de teste que só usava a EPROM e a porta serial (não dava para usar interrupções pois não havia memória para a pilha) e geramos um binário com o assembler do Osvaldo. Tudo funcionou perfeitamente já na primeira vez, mas ao olharmos os sinais do processador achamos que tinha alguma coisa errada. O sinal Address Strobe, que indica que a memória está sendo usada, parecia estar travado em zero. Depois de ajustarmos o osciloscópio por um tempo, vimos que na verdade tinha um monte de pulsos super estreitos. Sempre que um acesso terminava, outro começava imediatamente.
Pelos manuais do 68000 não era isso que deveria acontecer. Este processador não tinha um pipeline como o 8086 e se uma instrução levava 12 ciclos de relógio e fazia 2 acessos à memória (um para a própria instrução e outro para um dado) de 4 ciclos cada, o sinal AS deveria ficar alto por 4 ciclos. Mas não era o que acontecia. Apesar do manual não falar nada (nas versões de 1983 – mais tarde eles corrigiram isso) o processador fazia “pre fetch” de instruções como o 6502 (que muita gente, inclusive em documentação oficial, chama erroneamente de pipeline). Isso estragava nossos planos de colocar vários processadores numa única memória no projeto do super micro. Na próxima parte vou explicar como resolvemos isso.
Este primeiro teste foi a última vez em que vi este computador. Foi escrito o segundo programa que testaria a memória dinâmica e usaria direito a porta serial, mas este dependeria da compra do 8203 que acabou não acontecendo. É curioso que não me ocorreu usar o equivalente da Motorola (o SAM MC6883 ou SN74LS783) do TRS-80 Color Computer já que logo depois eu o usei no projeto do computador para crianças. De qualquer forma, eu e o Osvaldo raramente entrávamos nas salas do LSI, fazendo nosso trabalho na sala de usuários do CCE ou na biblioteca da elétrica. Por isso não vi a máquina ser construída e nem vi o que aconteceu com ela depois do primeiro teste, de modo que este projeto é menos real para mim do que outros que nem saíram do papel.
Um dos objetivos deste projeto era permitir que a futura equipe de software pudesse desenvolver os muitos utilitários do Unix em paralelo com o desenvolvimento do hardware do super micro e do núcleo do sistema operacional. Quando foram contratados estagiários para a equipe de software, foi comprado um Brascom BR1000 rodando Cromix para esta função.
Foi publicada a parte 4 prometida no terceiro parágrafo deste post? Se foi onde ela está?
Ainda não escrevi as partes seguintes desta história e vou demorar um pouco para fazê-lo (provavelmente só depois de março de 2015). Mas a idéia é continuar até descrever todos os meus projetos com 68000. Isso exclui varios outros projetos meus que não se encaixariam na lista de 68000 mas com certeza são retrocomputação. Depois vou ver qual é o melhor lugar para falar deles.