Ordinateur portable maison ZedRipper sur seize Z80

Un article du site de l'ingénieur fou de la maison Chris Fenton



Découvrez le ZedRipper, une bête à 16 cœurs fonctionnant à 83 MHz et alimentée par des processeurs Z80, aussi portable qu'impossible. Il s'agit de ma dernière tentative d'assembler un ordinateur pour le plaisir et d'avoir satisfait plusieurs souhaits à la fois:
  • Enfin, utilisez le FPGA géant, qui traînait avec moi au ralenti.
  • Jouez une histoire alternative de la création d'ordinateurs, en abordant la question du multitâche du point de vue du fer.
  • Assemblez un ordinateur sur lequel je pourrais écrire des programmes courts amusants sur le chemin du travail dans le train.
  • Assembler une plateforme sur laquelle des expériences relativement simples d'architecture informatique pourraient être réalisées.


Photos glamour


Si vous n'avez pas le temps de lire une feuille de texte sur une architecture informatique peu pratique ...













Alors, quelle est cette bête?




ZedRipper est le résultat d'une tentative de construction de l'ordinateur le plus cool avec CP / M 2.2:

  • 16 processeurs Z80 fonctionnant à une fréquence de 83,33 MHz.
  • 64 Ko de mémoire dédiée pour chaque Z80.
  • Accélérateur de terminal compatible ANSI avec 16 sorties.
  • Tous les processeurs et périphériques sont connectés par un réseau en anneau unidirectionnel entièrement synchrone fonctionnant à 83 MHz.
  • Lecteur de 128 Mo sur une carte SD (16 disques de 8 Mo en CP / M).
  • Un noyau «serveur» qui démarre dans CP / M 2.2 et exécute le serveur de fichiers CP / NET (écrit en Turbo Pascal 3 sur l'ordinateur lui-même!), Qui fournit un accès partagé à la carte SD.
  • 15 noyaux «client» lançant CP / NOS à partir de la ROM. Chaque client a accès à un référentiel commun, et tout le monde peut exécuter n'importe quel programme CP / M 2.2 sans rivaliser pour les ressources avec d'autres noyaux.

Une autre route



Est-ce les échecs et Planetfall qui me distraient de mon éditeur Turbo Pascal?

Après mes aventures avec le portage de jeux sur Kaypro , j'ai eu une impression étonnamment chaleureuse de ce système d'exploitation primitif il y a 40 ans, et j'ai eu une idée que j'ai décidé de développer: et si l'histoire tournait dans la direction opposée, et que le PC continuerait des chemins de développement avec plusieurs processeurs tout de suite? Même dans les années 1980, les processeurs eux-mêmes (et bientôt la RAM) étaient relativement peu coûteux, mais le multitâche sur PC était basé uniquement sur des durées de coupe réduites lorsqu'une grande ressource (RAM ou CPU) était divisée entre des programmes concurrents. Iron ne pouvait pas faire face à cela (et il était très difficile d'obtenir des programmes qui se comportent bien sur des systèmes d'exploitation tels que DOS) jusqu'à ce que nous entrions dans l'ère des 386 et des ordinateurs avec plus de 4 Mo de mémoire.

Au cours de mes passe-temps historiques avec les ordinateurs, je suis tombé sur quelque chose de très intéressant pour moi: au début du développement, le système d'exploitation CP / M supportait une version «réseau» appelée CP / NET. La plupart des gens connaissent encore son idée aujourd'hui - mettre au bureau une ou deux «vraies» machines avec de gros disques et imprimantes, dont les ressources seraient partagées entre des clients légers, des terminaux avec CPU et RAM. Chaque utilisateur travaillerait comme s'il avait sa propre machine exécutant CP / M avec accès à de grands disques et imprimantes.

Comme je l'ai mentionné, le CPU et la RAM (généralement le Z80 avait 64 Ko de DRAM) n'étaient pas particulièrement chers, mais tous les pribluds externes nécessaires pour créer un ordinateur utile (lecteurs, imprimantes, moniteurs, ..) s'ajoutaient au coût total. À cette époque, l'ajout de plusieurs CPU / RAM à un ordinateur semblait une approche quelque peu décadente pour fournir à un utilisateur plusieurs CPU et RAM. Même CP / M est allé dans le sens de diviser les longueurs de temps pour MP / M OS.

J'ai trouvé qu'Exidy s'en rapprochait le plus - en 1981, ils ont sorti leur machine Multi-NET 80, qui permettait d'ajouter jusqu'à 16 cartes, chacune ayant un Z80 et une RAM. Cependant, il a été conçu pour fonctionner jusqu'à 16 utilisateurs individuels, et non pour le travail d'un seul utilisateur qui a lancé simultanément 16 programmes.


Si proche ...

Avance rapide de 40 ans - les transistors ont en fait chuté. Après la fermeture du laboratoire, j'ai hérité de plusieurs FPGA monstrueux (Stratix IV 530GX), et j'ai pensé qu'il serait si intéressant de le faire avec l'un d'eux. À un moment donné, je suis tombé sur un projet très intéressant de Grant Searle Multi-Comp , et il était assez facile d'assembler une machine fonctionnelle avec CP / M et un processeur. Mais j'avais besoin de plus. J'ai décidé de voir si je pouvais créer une machine multicœur sur CP / M avec de vrais multitâches - rien de délicat, juste de la force brute.

Nous configurons et lançons des logiciels


Dans ce projet, je me suis principalement concentré sur le matériel, et je n'ai pas écrit une seule ligne de code dans l'assembleur. Le CPU 0 se charge directement à partir de la ROM, que j'ai prise de Grant, et les nœuds restants sont chargés à partir de la ROM 4K / CP / NOS, que j'ai prise du simulateur Atari.

Les deux ROMs attendent une connexion à un terminal série via une interface standard, tandis que les clients CP / NOS attendent un autre port série connecté à un serveur. Il est facile de concevoir votre propre logique sur de si grands FPGA. J'ai développé ma logique de décodage d'adresses, grâce à laquelle le Z-Ring pour chaque CPU apparaît dans le schéma de mappage d'adresses si nécessaire.

À l'intérieur




Le cœur du ZedRipper est l'un de ces énormes FPGA Stratix IV 530GX. La carte HSMC est utilisée pour l'affichage, la réception des données du contrôleur de clavier et la connexion à la carte SD. Ethernet est utilisé pour télécharger le firmware, il y a donc un tel port sur le côté du boîtier, ainsi qu'un adaptateur pour carte SD et un emplacement pour un port série externe (pas encore utilisé).

Clavier et contrôleur



Clavier et trou au premier plan, où un dispositif de positionnement sera installé plus tard

J'avais un clavier PS / 2 compact qui traînait (de l'un de mes anciens projets avec un ordinateur portable), et je voulais le connecter aux E / S 2,5 V de mon FPGA. J'ai décidé de suivre la voie facile et d'ajouter un microcontrôleur Teensy 2.0 au bundle.


Contrôleur de colle chaude au bas du clavier

Cela a permis de traduire PS / 2 en ASCII, ainsi que de marquer facilement certaines des touches supplémentaires (F1-F12) en séquences «magiques» de commandes de terminal, pour plus de commodité. Le contrôleur fournit ensuite Z80 octets pour UART à 9600 bauds (en utilisant un simple diviseur de tension qui change de 5 V à 2,5 V pour FPGA). Étant donné que ce projet a été assemblé à partir de diverses ordures se trouvant dans mon atelier, c'était une solution pratique qui s'est bien révélée au travail.

Affichage



L'écran de chargement, le serveur s'exécute dans le coin supérieur gauche et trois programmes utilisateur différents fonctionnent sur des noyaux distincts

Caractéristiques d'affichage: 1280 × 800 10,1 ″, et il comprend VGA. FPGA utilise un simple réseau de résistances pour fournir jusqu'à 64 couleurs (R2G2B2). L'affichage nécessite une minuterie de 83,33 MHz (1280 × 800 à 60 Hz), donc pour plus de simplicité, tout le circuit fonctionne à cette fréquence.

Le projet de Grant, Multicomp, avait un code VHDL pour un simple terminal compatible ANSI. J'ai réécrit sa logique sur Verilog, puis développé un contrôleur vidéo prenant en charge 16 terminaux indépendants connectés via un nœud Z-Ring. L'affichage 1280 × 800 est considéré comme un affichage de 160x50 caractères (avec une police 8x16), et chaque terminal fonctionne comme un "sprite" 80x25 qui peut être déplacé n'importe où sur l'écran (avec une liste de priorités qui ajuste la séquence de rendu du terminal). Étant donné que chaque terminal fonctionne indépendamment des autres, il possède sa propre machine d'état, avec 2 Ko de RAM pour les caractères et 2 Ko «d'attributs» (pour stocker les informations de couleur). Chaque caractère prend en charge les couleurs d'arrière-plan et de caractère 4 bits. Étant donné que tous les terminaux doivent avoir les mêmes caractères d'indentation et qu'une cellule 8x16 ne peut contenir qu'un seul caractère, tous les terminaux peuvent utiliser la même ROM de 2 Ko contenant une police. En général, la logique d'affichage utilise environ 66 Ko de RAM de bloc.

En général, je reçois un gestionnaire de fenêtres très simple pour mes terminaux CP / M, qui fonctionne presque entièrement en raison du matériel. C'est l'un des domaines de recherche les plus riches - jusqu'à présent, seul le processeur du serveur est capable de réorganiser les terminaux, mais j'ai des plans ambitieux pour ajouter un dispositif de positionnement tel qu'une souris, qui permet d'utiliser le matériel Windows uniquement pour faire glisser les fenêtres et modifier la priorité des affichages.

Étant donné que le contrôleur de terminal n'est qu'un des nœuds Z-Ring (et rediriger cette interface vers l'un des Z80 est très simple), parmi les plans futurs, il sera possible d'ajouter un terminal «plein écran» 160x50 (éventuellement comme «arrière-plan»), et un véritable affichage 1280x800x64 couleurs avec SRAM externe rapide sur la carte.

Anneau en Z


Comment assembler un tas de Z80? Dans mon travail, j'ai fermement appris une chose: développer des réseaux est difficile. Les objectifs généraux de ce réseau étaient les suivants:

  • Implémentation simple.
  • Interface simple
  • Extensibilité arbitraire.
  • Performances adéquates.

Comme je l'ai déjà mentionné, mes Z80 s'attendent à se connecter à des ports série, donc l'interface était assez simple à faire - elle devait être déguisée en port série! Essentiellement, Z-Ring est un réseau en anneau synchrone unidirectionnel qui utilise des «crédits» pour contrôler le flux. Chaque nœud a un tampon entrant de 1 octet pour chacun des autres nœuds du réseau. Après une réinitialisation, chaque nœud a 1 «crédit» pour chacun des nœuds de réseau restants. Le schéma est paramétré, il est donc facilement extensible à des centaines de nœuds avec l'ajout d'une très petite quantité de logique, mais aujourd'hui Z-Ring prend en charge jusqu'à 32 nœuds (par conséquent, chaque nœud a besoin d'un tampon de 32 octets).

Le «bus» lui-même se compose d'un bit de validité, d'un ID «source», d'un ID «cible» et d'une charge utile de 1 octet (19 bits). Je pense que ce serait assez simple à implémenter en utilisant la logique TTL (si une personne avait échoué en 1981 et n’avait pas pu trouver de FPGA). Chaque "noeud" possède 2 pipelines pour les déclencheurs de bus - 0 et 1 étages - et lorsque vous entrez un message, il attend que le 0e étage soit vide, puis fusionne avec le 1er. Les messages sont entrés sur le nœud source et voyagent autour de l'anneau jusqu'à ce qu'ils atteignent la cible, après quoi ils se retrouvent dans le tampon approprié et mettent à jour l'indicateur de disponibilité des données. Lorsque le nœud de réception lit le tampon, il entre de nouveau dans le message d'origine, qui continue de voyager autour de l'anneau jusqu'à ce qu'il atteigne à nouveau la source, renvoyant le «crédit». Si vous envoyez le colis à une adresse inexistante, le prêt sera remboursé automatiquement après un cercle complet.

Étant donné que chaque arrêt sur l'anneau se compose de deux étages de convoyeur et qu'il n'y a pas de contre-pression, chaque message ne prend pas plus de 2 * (nombre de nœuds) cycles de livraison. L'implémentation actuelle a 17 nœuds (16 CPU + contrôleur d'affichage / clavier), et elle fonctionne sur un temporisateur de 12 ns, il faut donc environ 400 ns pour délivrer un message et retourner un prêt. Le contrôleur d'affichage peut envoyer du trafic avec un taux d'arrivée, de sorte que chaque CPU dispose d'une bande passante de 2 à 2,5 Mb / s vers son terminal (le bus passe suffisamment pour fournir les 16 CPU), ce qui est beaucoup pour les terminaux.

Dans la configuration actuelle, tout fonctionne bien, mais vous pouvez apporter des améliorations évidentes:

  • Pour approfondir les tampons de réception, ce qui augmentera le débit des nœuds - sur le FPGA, il existe de nombreux blocs libres de 1 Ko de RAM, qui prendront en charge 32 nœuds avec 32 crédits, de sorte que chaque processeur en théorie peut saturer le bus.
  • Ajoutez la prise en charge du mode d'adresse. L'ajout d'adresses 16 bits (ou plus) permettra un accès direct à la mémoire (DMA) (et l'ajout de DMA à chaque nœud sera simple). Le FPGA possède une énorme quantité de matériel supplémentaire (quelques mégaoctets de RAM statique et environ un gigaoctet de DDR3).
  • Ajoutez le contrôle de flux (et la mise en mémoire tampon) entre les nœuds.

Mais tout cela peut attendre des temps meilleurs.

Nutrition!


Une carte de débogage avec FPGA nécessite une alimentation d'entrée de 12 à 20 V, un écran a besoin de 12 V et un clavier et un contrôleur ont besoin de 5 V. Il est pratique que le FPGA ait des contrôleurs de 3,3, 5 et 12 V, qui sont assez faciles à connecter, donc Le FPGA est alimenté directement par une batterie lithium-polymère à 5000 mAh avec une tension de 14,4 V, puis distribue l'alimentation à tous les autres appareils. L'une des difficultés était que je ne voulais pas démonter l'ordinateur portable à chaque fois pour le charger, mais la batterie avait un connecteur d'alimentation + / - normal, ainsi qu'un connecteur «d'équilibrage» qui se connectait à chaque cellule individuelle. Ma solution imparfaite est que le bouton d'alimentation commute la connexion de la batterie entre l'alimentation FPGA et le connecteur de charge situé dans le logement fermé par un couvercle coulissant. Pas très pratique, mais vous pouvez simplement faire glisser le couvercle et retirer les connecteurs à partir de là pour les connecter à la charge sans utiliser les clés hexagonales.


La charge semble bizarre

Je n'ai pas testé la batterie à fond, mais elle dure au moins 3 heures (ce qui est plus que suffisant pour couvrir mes trajets en train). Très probablement, il durera environ 6 heures sans aucune optimisation de la consommation. Il ne prend pas en charge l'utilisation en même temps que la charge, cependant, l'ordinateur portable fonctionne sur batterie suffisamment longtemps pour que ce ne soit pas un problème.

Logement


Le cas de la conception «hacker» standard est une combinaison de contreplaqué de découpe laser de 3 mm et de plastique imprimé sur une imprimante 3D. J'ai chargé les charnières de l'écran à ressort, donc en fait il ressemble à un ordinateur portable ordinaire, quoique un peu lent. Je voulais lui donner le look des années 1980, donc les coins supérieurs de l'écran sont un peu comme Cray, et le faux support en cuir est fait sous les poignets. Le bord du contreplaqué découpé au laser est très désagréable pour les mains, donc ce support était étonnamment fonctionnel.

La vitesse


Je n'ai pas essayé un seul benchmark spécifiquement pour CP / M (je suppose que oui, mais je ne l'ai pas spécialement cherché). Comme cette machine a été conçue pour écrire des programmes en Turbo Pascal, j'ai essayé plusieurs micro-tests de vitesse. Il s'est avéré 15 à 35 K opérations en virgule flottante par seconde (en utilisant le type réel 48 bits dans TP), et environ 1 million d'opérations entières par seconde (avec le type entier 16 bits). Pas mal pour un processeur 8 bits et un environnement de programmation suffisamment pratique.

Un projet intéressant pour l'avenir pourrait être le développement d'un accélérateur pour les opérations en virgule flottante.

Élimination FPGA


Toute la logique, comme je l'ai déjà dit, est plutôt légère et ne consomme qu'environ 7% des ressources de la puce (bien que 40% de la RAM totale du bloc et 100% de la RAM M144k).

  • ALUT multinationaux 31808/424960 (7%)
  • ALUTES mémoire 0/212 480 (0%)
  • Registres logiques dédiés 10,231 / 424,960 (2%)
  • Utilisation logique 10%
  • Total registres 10231
  • Nombre total de bits de mémoire de bloc 9,005,056 / 21,233,664 (42%)
  • Éléments 18 bits du bloc DSP 0/1 024 (0%)

Plans futurs


Dans mes plans immédiats (c'est-à-dire que le fer est déjà dans l'atelier, il suffit de trouver le temps de souder):

  • Colorez tout. L'ordinateur portable est en contreplaqué, et je veux vraiment le recouvrir de quelque chose.
  • Dispositif de positionnement du joystick Connectez-le au contrôleur de clavier.
  • Suivi de la batterie. L'ADC sur le contrôleur de clavier facilite le suivi de la batterie, afin que je puisse comprendre à quel niveau la charge.
  • WiFi - J'ai ESP32 qui traîne pour lancer Zimodem! Avec le téléphone en mode point d'accès, cela devrait me permettre d'aller en ligne en déplacement. Il existe de bonnes applications de terminal pour CP / M, mais ce serait bien d'écrire quelque chose comme un client IRC ou un simple navigateur Web. Il sera également pratique d'utiliser le protocole de transfert de fichiers Kermit vers un ordinateur Linux moderne.
  • Le port série, accessible de l'extérieur, pour la connexion à une autre machine (un connecteur a déjà été imprimé pour cela, il suffit de le souder).
  • LED indiquant l'état actuel. Pour lui, il y a déjà un trou à l'avant - maintenant je prévois de le connecter au signal d'accès à la carte SD.

À plus long terme, j'attends avec impatience diverses idées de fer, qui seront amusantes à expérimenter avec:

  • Combien pouvez-vous overclocker le Z80? La première étape consiste à délier la vitesse du processeur du pixel timer, cependant, il sera également intéressant d'essayer d'appliquer des techniques informatiques modernes au Z80 (pipelines, changement de nom de registre, prédicteur de branche, etc.).
  • Il peut être intéressant d'ajouter des accélérateurs spéciaux pour des choses comme les opérations en virgule flottante. Il y a 1 024 blocs DSP inutilisés sur la puce, et je pense que personne n'a essayé de construire un accélérateur pour le format réel 48 bits dans TP.
  • Utilisez du fer existant! J'ai encore beaucoup de mémoire inutilisée, à savoir:

    • 512 Mo de mémoire SDRAM DDR3 avec un bus de données 64 bits
    • 128 Mo de mémoire SDRAM DDR3 avec un bus de données 16 bits
    • Deux mémoires SRAM QDR II + 4 Mo avec bus de données 18 bits
    • Mémoire flash de 64 Mo
    • 2 Mo de SSRAM

  • Améliorez la vidéo! La première étape consiste à ajouter la prise en charge du terminal «plein écran» 160x50, et la possibilité de passer à un terminal régulier 80x25 2 fois. L'utilisation d'une SSRAM externe ajoute simplement le mode 1280 × 800 @ 6 bits.
  • Développez les capacités du terminal actuel. Je pense que je peux ajouter la compatibilité avec un terminal comme ADM-3A (et ajouter le support graphique), qui est utilisé dans Kaypro / 84, alors j'aurai accès à une gamme plus large de logiciels (et je n'aurai pas à porter DD9).

Résumé


Jusqu'à présent, la voiture ne fonctionne que depuis quelques jours, mais je peux dire que j'aime vraiment tout. L'écran est agréable et clair, le clavier est grand et confortable, le corps est encombrant, mais il pèse peu (et tient dans un sac à dos). L'ordinateur portable était même étonnamment ergonomique pour travailler dans un train.

Je pense que je suis sur la bonne voie. La possibilité d'ouvrir un éditeur de texte dans une fenêtre pour prendre des notes tout en déboguant du code sur TP dans une autre est extrêmement pratique (ou la possibilité de prendre des notes tout en jouant à Zork!). On estime qu'une telle approche de la création d'ordinateurs multitâches à faible coût basés sur CP / M pourrait exister.

Vous voulez construire la même chose?


Jusqu'à présent, je n'ai pas de moyen facile d'obtenir des fichiers de la machine, donc la partie la plus utile du logiciel (serveur de fichiers CP / Net écrit en Turbo Pascal) est piégée. Restez avec nous et restez à l'écoute (ou écrivez-moi un e - mail si vous ne pouvez pas attendre du tout).À un moment donné, je rejoindrai probablement le 21e siècle et ouvrirai un compte sur github. Hélas, tout repose sur ce très «temps libre».

Source: https://habr.com/ru/post/fr480290/


All Articles