Je suis un ingénieur informatique professionel, et j'ai connu le microprocesseur depuis ses débuts. J'ai eu la curiosité de jeter un regard sur l'ordinateur de guidage Apollo qui a été rendu public. J'ai lu la documentation du manuel opérateur, et c'est vraiment la plus bizarre qu'il m'ait été donné de lire, si bizarre qu'elle m'a fait me dresser les cheveux sur la tête quand je l'ai lue (et j'ai lu de nombreuses documentations techniques). Le programme du module de commande lunaire est aussi três bizarre; je doute fortement qu'il ait piloté quoique ce soit; il ne pourrait même être compilé, c'est à dire transformé en code machine pour être exécuté. Si je résume quelques uns des principaux problèmes de l'ordinateur Apollo, avant de rentrer plus dans les détails, je peux citer les points suivants: - L'ordinateur Apollo utilise une technique de commutation de mémoire qui est absurde car elle n'utilise pas la pleine capacité du système d'adressage, et mène à gaspiller du temps et de la mémoire qui sont très limités sur l'ordinateur Apollo; et commuter de la mémoire exécutable n'a pas de sens, car cela signifie que le code qui suit l'instruction de commutation ne sera jamais exécuté. - L'ordinateur Apollo n'a pas le jeu minimal basique d'instructions que tout processeur a d'habitude, mais a à la place des instructions alambiquées qui sont très peu pratiques à utiliser. - L'ordinateur Apollo fait des choses inutiles qui gaspillent du temps de calcul (comme sauver le contenu de l'instruction suivant l'appel à une interruption en plus de sauver son adresse qui est la seule chose qu'il devrait sauver). - L'ordinateur Apollo fournit des instructions qui calculent quelque chose de si bizarre dans l'accumulateur (principal registre du processeur) que cela est équivalent à détruire son contenu, et ainsi rend ces instructions pratiquement inutilisables. - L'ordinateur Apollo a des instructions qui ne requièrent pas un paramètre qui serait pourtant nécessaire pour leur fonctionnement, ou inversement requièrent un paramètre qui est inutile pour leur fonctionnement. - L'ordinateur Apollo a des instructions qui ne sont pas claires; elles ne spécifient pas vraiment ce qu'elles font. - L'ordinateur Apollo est dit capable de faire du temps réel (le temps réel permet à plusieurs tâches de s'exécuter en parallèle), et pourtant il n'a même pas l'environnement minimal qui serait nécessaire pour permettre au temps réel de fonctionner (pas de pile, et pas de fonction pour gérer le temps réel). - L'ordinateur Apollo a des instructions qui gaspillent inutilement du temps processeur (comme les instructions "non programmées" qui comptent des impulsions matérielles; de telles instructions n'ont jamais existé dans aucun processeur pour la bonne raison qu'elles n'ont pas de raison d'y exister). - Tout ce qui tourne sur un processeur vient d'instructions programmées; donc, le fait que quelque chose "volerait" du temps à l'ordinateur, comme ils disent, est hilarant...à moins qu'un ingénieur ait programmé quelque chose et ne l'ait pas dit aux autres, Hum! - L'ordinateur Apollo utilise le système complément à 1 (qui fait une distinction entre +0 et -0 et est moins performant que le système complément à 2), quoique ce système de représentation était déjà caduque au temps d'Apollo. Le chapitre IV traite spécifiquement ce sujet. |
1) Même si dans ce qui suit vous avez quelque difficulté à suivre mes explications techniques, il y a quelque chose que tout le monde devrait pouvoir comprendre: Dans la documentation il y a des lignes qui ont été barrées; Cela a t'il du sens? Sur une documentation tapée, vous ne barrez jamais du texte, vous l'enlevez simplement. 2) Page 3: les mots mémoire de l'AGC sont de 15 bits plus un bit de parité. Mais les registres internes sont de 16 bits; leur seizième bit était utilisé comme "overflow". Le bit de parité est maintenu electroniquement et invisible à l'utilisateur. Pourquoi restreindre les mots à 15 bits au lieu de 16 bits, ce qui aurait été plus logique (surtout si les registres internes sont de 16 bits). Les mots mémoire auraient du être de 16 bits, et le bit de parité aurait été un 17ème bit invisible à l'utilisateur. Et le bit d'overflow n'a rien à faire dans l'accumulateur et autres registres; il aurait du se trouver dans un registre spécial, appelé registre d'état, en même temps que d'autres bits d'état, comme le bit de carry qui est manquant. 3) Page 3: Le système de représentation complément à 1 était déjà caduc au temps d'Apollo (voir chapitre III). 4) Page 5: Ils disent les choses suivantes: a) Les registres compteurs/timers sont incrémentés par des impulsions matérielles. b) L'incrémentation d'un compteur/timer prend du temps CPU. Ceci est contradictoire: Si l'incrémentation d'un compteur prend du temps CPU, celc signifie que l'incrémentation est logicielle, et elle n'est donc pas faite par impulsions matérielles. Si elle faite par impulsions matérielles, l'incrémentation n'a pas de raison de prendre des cycles CPU. Il n'y a rien de tel que des "séquences non programmées", même si ces séquences non programmées portent des noms bizarres tels que "PINC" ou "MINC". L'idée qu'une impulsion matérielle répétitive puisse générer du temps CPU est hérétique. Seul du code exécuté peut générer du temps CPU; un signal externe ne peut pas générer du temps CPU, à l'exception des interruptions qui provoquent l'exécution de séquences programmées. Si un signal hardware générait du temps CPU pour incrémenter un compteur, cela serait parfaitement stupide (et un grand gaspillage de temps CPU) car un compteur électronique peut aussi bien le faire et la CPU a des choses plus intelligentes à faire que compter un signal matériel. Lorsqu'un signal matériel répétiif doit être compté, un compteur électronique est utilisé; non seulement c'est couramment le cas, mais cela a toujours été le cas depuis le début (les compteurs électroniques sont des circuits basiques et ont existé avant même les processeurs). Le processeur peut lire le compteur à travers un canal I/O; bien sûr, quand il le fait, cela prend des cycles CPU, mais il n'a pas à le faire à chaque impulsion matérielle, seulement quand il a besoin de l'information. Un rebouclage du compteur peut aussi générer une interruption sur le processeur, permettant au processeur de faire un traitement quand un compte programmé d'impulsions a été atteint. 5) Page 6: Ils disent que le 16ème bit de l'accumulateur (registre spécial de la CPU) est utilisé en association avec le 15éme bit pour indiquer le dépassement (overflow). Il ya d'autre bits d'état qui existent (le carry par exemple) et ces bits d'état sont placés dans un registre spécial appelé "status register". L'accumulateur n'est jamais utilisé pour indiquer un dépassement; un dépassement de l'accumulateur positionne le bit de dépassement du registre d'état comme pour toute autre donnée mémoire. Cela a toujours été le cas depuis les premiers processeurs. Il n'y a pas de raison de gaspiller un bit de l'accumulateur pour y mettre l'indicateur de dépassement. 6) Page 8: LRUPT est un registre qui sert à mémoriser la valeur du registre L (compteur programme) lors d'une interruption. Mais ce qui est comique est qu'ils disent que le fait de se dérouter vers la routine d'interruption ne met pas à jour automatiquement le registre LRUPT avec le compteur programme (L); et la restauration de L depuis LRUPT n'est pas automatique non plus. C'est tout à fait ridicule car L pourrait être plus commodément poussé sur une pile pour le sauver, et retiré de celle-ci au retour de l'interruption. Si la sauvegarde et la restauration de LRUPT ne sont pas automatiques, alors ce registre n'est pas três utile. 7) Page 9: TIME1 est un compteur sur 14 bits (pourquoi pas sur 16 bits) qui reboucle toutes les 163,84 secondse; sur rebouclage de TIME1, le compteur de 14 bits TIME2 est automatiquement incrémenté. Ceci est ridicule: Pouquoi est-ce que TIME1 et TIME2 ne sont pas sur 16 bits? Ils pourraient compter une valeur 16 fois plus grande. Avec une horloge d'une milliseconde, ils pourraient compter plus que 31 jours, et avec une plus grande précision. 8) Page 9/10: TIME3 est un compteur incrémenté toutes les 10 millisecondes qui génére une interruption sur rebouclage. TIME4 est également un compteur incrémenté toutes les 10 millisecondes qui génére une interruption sur rebouclage. Ils disent que l'incrémentation de TIME3 est déphasée de 5 millisecondes relativement à celle de TIME4 de telle sorte que leurs interruptions ne puissent pas se produire simultanément. Ensuite ils disent que TIME5 est aussi un compteur incrémenté toutes les 10 millisecondes qui génére une interruption sur rebouclage; mais rien n'est prévu pour synchroniser TIME5 ni avec TIME3, ni avec TIME4. Cela signifie que la routine d'interruption associée à TIME5 peut interrompre celle associée à TIME3 ou celle associée à TIME4. De plus les adresses des routines d'interruption associées à ces compteurs ne sont séparées que par 10 octal, et 10 octal cela laisse seulement 8 octets pour programmer la routine d'interruption; et cette routine d'interruption doit obligatoirement se terminer avec une instruction permettant le retour vers le programme interrompu (ce qui rend la routine d'nterruption encore plus courte). Que voulez-vous programmer en moins de 8 octets (cela fait seulement 4 instructions, puisque chaque instruction occupe deux octets)? C'est ridicule! Bien sûr, il peut y avoir un saut vers une routine située ailleurs en mémoire, à un endroit où il y a plus d'espace pour programmer la routine; mais, pour programmer le saut, deux octets suffisent, et il y a alors 8 octets non utilisés; cela veut dire que l'intervalle entre les adresses des routines d'interruption aurait pu être réduit à deux octets. Donc, pour résumer, l'intervalle entre les routines d'interruption est soit trop court, soit trop long. 9) Page 10: TIME6 esr un compteur incrémenté tous les 1/1600 de seconde par une séquence non programmée. Cela ne veut absolument rien dire, une séquence est toujours programmée, sinon ce n'est pas une séquence. Après avoir chargé TIME6 avec le compte correspondant au délai désiré, l'utilisateur autorise le compteur en positionnant un but dans un registre I/O. Sur rebouclage de TIME6, une routine d'interruption est appelée, et ils disent que le bit d'autorisation de registre I/O est automatiquament remis à zéro, mais en fait il ne pourrait être automatiquement remis à zéro, ce serait à l'utilisateur de le faire. 10) Page 11: PIPAX est un registre qui veut dire "accélarateur pendulaire d'intégration d'impulsions". C'est absolument ridicule: Les registres de la CPU ne portent pas de tels noms, ils portent des noms qui représentent leur fonction qui est une fonction purement numérique. 11) Page 13: La manière dont la mémoire est mappée n'a pas de sens. Les banques de mémoire peuvent être adressées sans avoir besoin de faire du mapping mémoire. La commutation de mémoire consomme à la fois de la place et du temps de manière complétement inutile. La mémoire RAM et ROM peut être n'importe où. Les registres CPU qui permettent la commutation de mémoire sont une une pure hérésie; de tels registres n'ont jamais existé dans aucune CPU. 12) Page 15: Ils disent que le traitement d'une routine d'interruption peut être reporté si une interruption est déjà en cours de traitement et pas encore terminée (par une instruction RESUME). Dans ce cas, pourquoi avoir déphasé l'incrémentation du compteur TIME3 relativement à celle du compteur TIME4 de manière à éviter la simultaneité de leurs interruptions, puisque celle qui arriverait en deuxième attendrait que la première soit terminée avant d'être traitée? 13) Page 15: Ils disent que la deuxième étape du traitement d'une routine d'interruption est de sauver l'instruction courante dans le registre BRUPT. Cela n'a absolument pas de sens. C'est l'adresse de l'instruction qui doit être sauvée, mais l'instruction elle-même ne serait jamais sauvée; aucune CPU ne l'a jamais fait. Ils ne terminent pas la description du traitement de l'interruption, c'est à dire expliquer que l'instruction RESUME recharge le compteur de programme depuis le registre ZRUPT. 14) Page 16: Ils disent qu'une instruction est représentée de la manière suivante: CCC AAA AAA AAA AAA C'est à dire un code instruction sur 3 bits seulement, une adresse mémoire de 12 bits. Normalement le code instruction ne se mélange pas avec l'adresse, mais en est séparé. Le code instruction est typiquement spécifié sur un octet, ce qui autorise un jeu de jusqu'à 256 instructions. L'adresse ne serait pas systématiquement spécifiée derrière le code de l'instruction, mais seulement si l'instruction requiert une adresse. L'adresse serait fournie sur 16 bits dans le mot qui suit; elle n'aurait pas de raison d'être fournie sur 12 bits seulement; cela étendrait la capcité d'adressage par un facteur 16, et eviterait d'avoir à faire de la commutation d'adressage qui est extrêmement pénalisante, à la fois en place mémoire et en temps d'exécution. Maintenant, dans l'AGC d'apollo, le code instruction est en fait mélangé avec l'adresse, parce que toutes les adresses ne sont pas permises pour l'adressage de mémoire. Les adresses débutant à zéro ne sont pas utilisées (elles sont utilisées comme registres de la CPU) et sont utilisées comme complément du code instruction. Par exemple, si l'instruction est "01000" octal, l'adresse est "1000" et est une adresse valide, dans ce cas, le code instruction "0" indique qu'il s'agit d'une instruction "TC" appelant le sous-programme à l'adresse 1000 octal. Mais si l'instruction est "00001", le code instruction est aussi "0", mais l'adresse "0001" indique que l'instruction est en fait "XLQ" au lieu de "TC". Cela veut dire que la connaissance du code de l'instruction n'est pas suffisante pour savoir quelle instruction exécuter, le processeur doit aussi analyser l'adresse avant de savoir quelle adresse exécuter; ceci est moins efficace que si le processeur pouvait directement savoir à partir du code instruction quelle instruction il doit exécuter. 15) Dans toutes les CPUs, y compris les três anciennes, il y avait un jeu d'instructions spéciallement dédié à faire des sauts conditionnels. Ces instructions testent les bits de status positionnés par des opérations précédentes: cela peut être une addition, une soustraction, mais cela peut aussi être une simple comparaison. Ces instructions incluent des sauts conditionnels tels que: Sauter si égal, sauter si plus grand, sauter si plus grand ou égal, sauter si plus petit, sauter si plus petit ou égal, sauter si retenue, sauter si pas de retenue .. Sur cette CPU, il y a seulement deux instructions conditionnelles: BZF et CCS. BZF teste seulement si l'accumulateur est nul, et c'est totalement insuffisant, il devrait aussi y avoir une instruction testant le signe. Il y a bien l'instruction CCS qui peut tester le signe d'une donnée mémoire.. le problème est que cette instruction détruit le contenu de l'accumulateur en calculant quelque chose dedans depuis la donnée mémoire de manière déterminée que l'utilisateur ne peut pas choisir; et elle réalise des sauts d'instruction suivant le résultat du test, ce qui veut dire que l'utilisateur doit rajouter des sauts derrière CCS pour exécuter la séquence désirée en fonction du résultat du test. C'est fait pour être aussi peu pratique que possible, de manière totalement irrationnelle; aucun concepteur sérieux de CPU ne ferait des instructions aussi peu pratiques à utiliser. Ce n'est pas que cette CPU fonctionne différemment des autres CPUs, c'est qu"elle fonctionne de manière irrationnelle. 16) Page 24: l'instruction "DTCB" (Double transfer control switching both banks) est dite réaliser un saut et commuter simultanément les mémoires fixe et effaçable. Ceci est hilarant: cette instruction est si peu commode à utiliser qu'il est difficile d'imaginer dans quel contexte elle pourrait être utilisée. Commuter juste une banque mémoire est déjà peu pratique à utiliser, mais commuter les deux banques en même temps a encore moins de sens! 17) L'instruction "DV" divise la pair de registres CPU A et L par une donnée mémoire dont l'adresse est donnée sur 12 bits. Ils disent que cette instruction peut fonctionner suivant deux modes différents (diviser la paire A&L par une valeur simple précision ou par une valeur double longueur complémentée à 1 pointée par l'adresse). Le problème est qu'il n'y a absolument rien qui dit à la CPU quel mode utiliser, puisqu'il y a juste l'instruction et l'adresse mémoire et pas d'information additionnelle. la CPU doit être extralucide pour déterminer quel mode utiliser! Ils donnent quelques exemples dont la division fonctionne dans une table. Parmi ces exemples, ils disent que, lorsque +0,0 est dans la paire A,L, et +0,0 dans le registre K, alors l'instruction DV calcule un quotient de "0,999389648" dans le registre A. Alors la division de 0 par 0 donne quelque chose différent de 0? Comme c'est original! 18) Page 28: La manière dont l'instruction "INDEX" fonctionne est hilarante. Elle est dite changer le comportement de l'instruction qui suit; ils donnent l'exemple qui suit: INDEX A TC JMPTAB ... TCF LOC-2 TCF LOC-1 JMPTAB TCF LOC0 TCF LOC1 TCF LOC2 TCF LOC3 L'instruction TC appelle normalement un sous-programme, mais le fait qu'elle soit précédée par l'instruction INDEX fait qu'elle devient un saut conditionel suivant le contenu de l'accumulateur. Ils disent que, si l'accumulateur contient 0, elle saute à l'étiquette JMPTAB qui fait un saut à LOC0, si l'accumulateur contient 1, elle saute à l'instruction après JMPTAB qui saute à LOC1, si l'accumulateur contient 2, elle saute à la deuxième instruction après JUMPTAB sui saute à LOC2... Mais là où cela devient hilarant, c'est que si l'accumulateur contient -1, elle saute à l'instruction avant JMPTAB, et si l'accumulateur contient -2, elle saute à l'instruction encore avant. L'instruction avant JMPTAB saute à l'instruction un octet avant l'étiquette LOC, et l'instruction avant cette dernière saute à l'instruction deux octets avant l'étiquette LOC. Mais s'il y a un saut à l'instruction deux mots avant l'étiquette LOC, l'instruction un mot avant l'étiquette LOC sera aussi exécutée...à moins qu'il n'y ait un saut à une autre étiquette dans l'instruction deux mots avant l'étiquette LOC, mais dans ce cas pourquoi ne pas directement utiliser cette étiquette dans l'instruction "TCF LOC-2". 19) Page 32: L'instruction NOOP est également hilarante; non parce que cela n'a pas de sens d'avoir une instruction qui ne fait rien, car cette instruction existe effectivement dans des CPUs normales, et est utilisée pour fournir des délais courts. Ce qui est hilarant est que cette instruction est dite prendre deux cycles si exécutée en mémoire écrasable et un cycle en mémoire fixe. Dans des CPUs normale, cette instruction prend toujours un cycle, où qu'elle soit exécutée. 20) Page 33: L'instruction "RAND" est dite faire des ET des bits de l'accumulateur à partir d'un registre I/O. Oh vraiment: Aucune CPU qui existe et a existé n'a jamais offert cette possibilité. Il y a seulement une instruction pour lire une adresse I/O (quand elle peut être lue), et une pour l'écrire (quand elle peut être écrite). Ceci est une instruction purement imaginaire. 21) Page 34: L'instruction "RESUME" permet de terminer une interruption et de retourner vers l'instruction qui était sur le point d'être traitée lorsque l'interruption s'est produite. Ils disent que lorsque l'interruption se produit, l'instruction pointée par le compteur de programme est automatiquement sauvée dans le registre BRUPT de la CPU. Au retour, l'instruction sauvée dans BRUPT est automatiquement exécutée; mais pourquoi la sauver dans BRUPT, puisqu'elle sera exécutée de toute manière au retour de l'interruption si le registre BRUPT n'est pas modifié. Et si la routine d'interruption modifie le registre BRUPT pour qu'une autre instruction soit exécutée au retour, pourquoi ne pas directement l'exécuter, ce qui serait plus rapide, puisque, si la routine d'interruption copie l'instruction dans BRUPT, le temps de la copie s'ajoute à celui de l'exécution de l'instruction, alors qu'il ny a que le temps d'exécution si l'instruction est directement exécutée. Ceci est totalement illogique et n'a absolument pas de sens! 22) Page 35: L'instruction "RETURN" permet de retourner d'un sous-proramme en chargeant le compteur de programme (le registre Z) depuis le registre Q qui contient normalement l'adresse de retour; l'instruction TC qui permet d'appeler un sous-programme sauve automatiquement l'adresse de retour dans le registre Q. Puisqu'il n'y a qu'un registre unique pour sauver l'adresse de retour, un sous-programme ne peut pas en appeler un autre. Dans une CPU normale, les adresses de retour sont sauvées sur une pile (une partie de mémoire qui est spécialement dédiée à sauver/rappeler des données mémoire, des adresses de retour..) qui permet d'appeler un sous-programme depuis un autre sous-programme. Dans cette CPU, l'appel d'un sous-programme (par l'instruction TC) depuis un autre sous-programme n'est pas possible, car l'adresse de retour est sauvée dans un registre unique; l'appel d'un sous-programme à l'intérieur d'un sous-programme résulterait en ce que l'adresse de retour du premier sous-programme soit écrasée par l'adresse de retour du deuxième sous-programme; ce qui rendrait le retour depuis le premier sous-programme impossible. 23) Page 39: L'instruction "TS" (transfer to storage) est hilarante. Elle transfére d'abord le contenu de l'accumulateur vers une donnée mémoire dont l'adresse est indiquée en opérande. Jusque là, rien d'anormal. Mais ce qui est vraiment bizarre est ce qui est fait avec l'accumulateur. Si l'accumulateur contient un dépassement, et seulement dans ce cas, ses bits sont mis à +1 oo -1 (qu'est ce que cela veut dire?), et la prochaine instruction est sautée. Cette instruction est três peu pratique à utiliser. Il devrait y avoir une instruction juste pour faire le transfert, et une autre pour réaliser cette fonction três spéciale sur l'accumulateur, mais avoir une instruction qui fait les deux en même temps n'a pas de sens, c'est pratiquement impossible à utiliser. 24) Page 43: Depuis la page 43, ils décrivent ce qu'ils appellent des "Pseudo-operations". Si une instruction n'est pas une instruction existante dans le jeu d'instruction de la CPU, alors elle peut seulement être une "macro-instruction", c'est à dire un jeu programmé d'instructions qui est associé à cette macro-instruction. Ils décrivent la pseudo-operation 1DNADR comme transmettant les deux mots pointés par l'adresse mémoire spécifiée...mais transmettant à quoi? Il y a toujours une destination dans une transmission, dire que c'est juste transmis de signifie rien, si la destination de la transmission et la manière dont la transmission se fait ne sont pas spécifiés! 25) Page 45: La pseudo-opération "BANK" est dite repositionner l'adresse interne du yaYUL à la première adresse inutilisée la la banque de mémoire spécifiée. La conséquence du changement de banque de programme est que le compteur de programme est placé sur une autre banque de mémoire, à une adresse dite "la première inutilisée", et que l 'instruction qui suit le changement de banque ne sera pas exécutée séquentiellement. Cela signifie que, si, dans une autre banque de mémoire, il y a une instruction de changement de banque qui spécifie le numéro de banque courante, l"instruction suivante à être executée devrait être l'instruction suivant la dernière instruction de changement de banque. Je montre ici une animation qui décrit comment deux banques pourraient alternativement aller de l'une à l'autre; mais cela pourrait impliquer plusieurs tâches: Une banque 1 pourrait changer vers une banque 2, laquelle changerait vers une banque 3, laquelle changerait vers un banque 4...et, à un moment, une banque rechangerait vers la banque 1. Mais, lorsqu'une banque changerait vers une autre banque, le processeur devrait connaître l'adresse de la "première instruction inutilisée" de cette banque, qui aurait été sauvée lorsque cette banque elle-même a changé vers une autre banque, et mise à l'adresse de l'instruction suivant le changement de banque. Cela signifie, que dans la zone des registres généraux, il devrait y avoir une zone pour sauver les adresses des "premières instructions inutilisées" des banques, pour chaque banque. Mais il n'y a pas de telle zone décrite dans la documentation. 26) Ils décrivent la "pseudo-operation" STCALL de la manière suivante: STCALL X Y et disent que X est dans une banque écrasable non commutable. Mais ils ne décrivent pas ce que cette opération fait! 27) Page 48: Ils disent que la pseudo opération "SETLOC" place la prochaine instruction ou pseudo opération à l'adresse spécifiée. Mais qu'est ce que cela veut dire? Si seulement une instruction est placée à cette adresse, exécuter depuis cette adresse exécutera seulement cette instruction. 28) Page 50. L'instruction "STORE" sauve une donnée à une adresse spécifiée. Elle sauve la donnée de deux manières différentes: 1) soit dans la banque de mémoire non interchangeable. 2) Soit dans la banque de mémoire interchangeable courante. Et elle ne peut être sauvée dans une autre banque de mémoire. Au cas où elle doit être sauvée dans la banque de mémoire interchangeable courante, l'instruction doit être écrite sour la forme suivante: STORE 0400* Numéro de banque + (X-1400) X étant l'adresse dans laquelle la donnée doit être sauvée dans la banque. Mais c'est là où cela devient absurde: Le numéro de banque interchangeable ne peut être que celui de la banque courante, car la donnée ne peut être sauvée dans une autre banque de mémoire interchangeable. Alors, quelle est l'utilité de spécifier le numéro de banque, si cela ne peut être que celui de la banque courante? Supposons maintenant que la banque de mémoire courante soit la banque 2, et que l'utilisateur spécifie le numéro de banque 3 dans la deuxième forme. Est-ce que l'instruction ne fera rien, ou ignorera t-elle le numéro de banque et sauvera la donnée dans la banque 2? Probablement le second cas. Mais, dans ce cas, pourquoi ne pas changer la seconde forme de l'instruction pour ne pas avoir à spécifier le numéro de banque mémoire, et ne pas simplement l'écrire: STORE X-1400 Mais faire simple était hors de question pour les ingénieurs qui avait décidé de pousser l'absurdité aussi loin que possible. 29) Pourquoi la commutation de banque de mémoire n'a pas de sens. L'AGC a réduit l'adressage mémoire à 12 bits, alors que 16 bits devraient normalement être utilisés pour cet adressage mémoire, il n'y a pas de raison d'être limité à 12 bits. Cela permettrait d'adresser 16 fois plus de mémoire, et éviterait d'utiliser la commutation mémoire qui est três pénalisante. La commutation de mémoire sur les données n'a déjà pas de sens. Imaginez que vous ayez une donnée dans la banque 1, que vous vouliez l'ajouter à une donnée en banque 2, et mettre le résultat en banque 3. Vous devez commuter sur la banque 1, prendre la première donnée, puis commuter en banque 2, ajouter la seconde donnée, et finalement commuter en banque 3, pour écrire le résultat. Cela veut dire que vous devez programmer des instructions de commutation de banque, qu'elles prennent de la place en mémoire programme, ainsi que du temps d'éxécution Ce gaspillage pourrait être évité s'il n'y avait pas de commutation mémoire. La commutation de banque en mémoire programme a encore moins de sens. Lorsque vous faites de la commutation en mémoire programme, aucune valeur n'est initialement prévue pour le compteur de programme. Cela veut dire que l'exécution part normalement depuis le début de la nouvelle banque. Bien sûr, il serait possible de placer une valeur dans une donnée que la nouvelle banque pourrait tester pour savoir où sauter, mais c'est plutôt compliqué à utiliser. Lorque vous appelez un sous-programme ou vous sautez à une autre séquence, elle doit être dans la même banque de mémoire, elle ne peut pas être dans une autre banque; ce n'est pas pratique du tout; il n'y aurait pas de tel problème s'il n'y avait pas de commutation de banque; un programme unique pourrait être utilisé pour toute la mémoire. Et si vous mettez une instruction de commutation de banque programme dans votre code, cela veut dire que le code qui suit cette instruction ne sera pas exécuté puisque le processeur aura commuté vers une autre banque de mémoire programme; si l'instruction qui suit n'a pas d'étiquette, elle ne sera pas atteignable. |
Link to the CM program Considérations generales sur le programme du module de commande. a) Même si vous avez des difficultés à comprendre mes explications techniques, pensez vous vraiment que les commentaires(le texte après le caractère '#') va avec les instructions? b) Les étiquettes sont les chaînes de caractères qui commencent sur le premier caractère d'une ligne; elles sont utilisées pour identifier une adresse mémoire dans le programme, et permettent de faire un branchement direct à cette adresse. Les étiquettes doivent seulement contenir des lettres et des caractères numériques, ainsi que quelques autres caractères (comme underscore, par exemple). Elles ne peuvent pas contenir des espaces, des caractères de ponctuation (.,;), des caractères numériques (+-*/). Les étiquettes doivent également être uniques; il ne peut pas y avoir deux étiquettes de même nom dans le programme (autrement, lorsqu'un branchement est fait à cette étiquette, la CPU ne saurait pas à laquelle de ces étiquettes se brancher). Un programme contenant une étiquette dupliquée ne peut pas être compilé, c'est à dire transformé en code machine, et donc ne peut pas être exécuté. c) Dans les instructions requérant une adresse mémoire, cette adresse mémoire peut seulement être spécifiée comme un symbole (eventuellement avec une valeur ajoutée ou soustraite) ou éventuellement comme une adresse octale (généralement c'est une adresse c'est une adresse hexadécimale, mais dans cette CPU l'adressage octal semble être privilégié). En aucun cas cette adresse mémoire ne peut contenir une multiplication ou une division (telle que "A/B") ou être une valeur numérique flottante (telle que "0.1234"). d) Plusieurs instructions ne sont pas référencées dans la manuel opérateur, ni comme instruction CPU, ni comme pseudo opération; et il est donc difficile de savoir ce qu'elles font! e) Il y a plusieurs exemples d'instructions inutiles, comme sauver plusieurs fois de suite une même donnée qui n'est jamais modifiée (pas même initialisée) et jamais utilisée; ou une donnée mémoire qui est écrite avec une valeur, et réécrite avec une autre valeur sans que la valeur précédente ait été utilisée. f) L'instruction TC permet d'appeler un sous-programme; dans la documentation il est dit qu'un sous-programme appelé par TC ne peut pas appeler un autre sous-programme à l'intérieur de son traitement pour la bonne raison que l'adresse de retour est sauvée dans un registre unique et non sur une pile. . Je donne ci-après quelques exemples d'incongruités dans le programme du module de commande. 1) L'instruction "BANK 35" commute sur la banque de mémoire 35; cette banque contient un autre programme, ce qui veut dire que les instructions qui suivent ne vont pas être exécutées puisqu'elles ne sont pas dans la même banque! Et l'instruction qui suit l'instruction BANK n'a pas d'étiquette, ce qui signifie qu'il n'est pas possible de s'y brancher; elle n'a donc aucune chance d'être jamais exécutée! 2) L' instruction "SETLOC BODYATT" est utilisée pour placer la prochaine instruction à l'adresse "BODYATT". Mais "BODYATT" n'est défini nulle part, seulement utilisé dans cette instruction. 3) L'instruction "BANK" permet de charger le compteur de programme avec la première adresse "inutilisée" de la banque fixe courante. Cela veut dire que nous allons exécuter des instructions non programmées...três intéressant! 4) CM/POSE n'est pas une étiquette valide. . 5) Dans le programme, il y a la séquence: SETPD VLOAD 0 VN L'intruction "VLOAD" est une instruction de l'interpéteur, mais elle doit être suivie de l'adresse d'un vecteur, et elle est suivie dune valeur numérique "0" à la place. 6) L'instruction "STORE -VREL" une instruction de l'interprêteur permettant de mémoriser un vecteur à l'adresse mémoire spécifiée. Mais "-VREL" n'est pas une adresse valide. 7) L'instruction "STORE UXA/2" mémorise quelque chose (non spécifié) à l'adresse mémoire spécifiée. Le second membre peut seulement être un nom symbolique (avec éventuellement une valeur ajoutée ou soustraite) ou une adresse octale, mais ne peut pas contenir une division. 8) A different points du programme nous trouvons la séquence "PUSH CDULOGIC". Apparemment elle pousse une variable CDULOGIC sur une pile; c'est bizarre pour les raisons suivantes: - CDULOGIC n'est pas initialisé. - CDULOGIC nest jamais modifié. - CDULOGIC est répétitivement poussé sans avoir été modifié, et n'est jamais retiré de la pile, ce qui veut dire que son contenu n'est jamais utilisé. - Et d'ailleurs, d'après la documentation, la CPU n'utilise pas de pile! 9) L'instruction "BZF DOGAMDOT" saute à l'étiquette DOGAMDOT" si l'accumulateur contient zéro; et sinon continue en séquence; l'instruction "TC NOGAMDOT" appelle le sous-programme "NOGAMDOT". L'instruction "TC NOGAMDOT" sauve l'adresse de l'instruction suivant l'appel à NOGAMDOT dans le registre Q, et se branche sur la procédure NOGAMDOT, de sorte que le programme continue depuis cette procédure. Normalement, comme l'instruction TC est supposée appeler un sous-programme, la procédure NOGAMDOT devrait se terminer avec une instruction "TC Q" qui place dans le compteur de programme l'adresse de retour qui a été sauvée dans le registre Q, et qui est l'adresse de l'instruction suivant l'appel à NOGAMDOT; le traitement reprend alors depuis l'instruction suivant l'appel à NOGAMDOT. Mais la procédure NOGAMDOT fait elle-même un appel à un sous-programme "CORANGOV"; l'appel à CORANGOV est fait de manière similaire à l'appel à NOGAMDOT. L'adresse de l'instruction suivant l'appel à CORANGOV est sauvée dans le registre Q, et le compteur de programme se branche sur le sous-programme CORANGOV qui est alors exécuté. Lorsque le sous-programme CORANGOV se termine, il exécute l'instruction "TC Q" qui place dans le compteur de programme l'adresse de retour qui a été sauvée dans le registre Q, qui est l'adresse de l'instruction suivant l'appel à CORANGOV, et l'exécution reprend depuis cette instruction. Maintenant, si la procédure NOGAMDOT essaie de retourner à son appelant avec une instruction "TC Q" après avoir appelé le sous-programme CORANGOV, elle ne retournera pas à l'instruction suivant l'appel à NOGAMDOT, mais à l'instruction qui suit l'appel à CORANGOV à la place, car l'adresse de l'instruction suivant l'appel à NOGAMDOT a été remplacée par l'adresse de l'instruction suivant l'appel à CORANGOV quand CORANGOV a été appelé par NOGAMDOT; en effet le registre Q ne peut mémoriser qu'une unique adresse de retour, ce qui signifie que les appels imbriqués ne sont pas permis. Cela signifie que NOGAMDOT ne peut pas retourner à son appelant s'il appelle lui-même un sous-programme (ou plusieurs). De toute façon, ce n'est pas un problème, car la procédure NOGAMDOT ne retourne pas à son appelant; elle ne se termine pas par une instruction "TC Q", mais par une instruction "GOTO POSEXIT" à la place. S'il était retourné avec une instruction" TC Q", cela aurait été une erreur. Mais, puisque la procédure NOGAMDOT ne retourne pas à son appelant, il n'était pas nécessaire de l'appeler avec une instruction TC, elle aurait pu être appelée avec une instruction "TCF" qui fonctionne comme une instruction "TC" (i.e. elle permet de se brancher sur NOGAMDOT), avec la différence qu'elle ne sauve pas l'adresse de retour dans le registre Q. Alors, allez-vous dire: Si cela marche avec les deux solutions, où est le problème? Le problème est que l'instruction "TC" fait un travail supplémentaire relativement à l'instruction "TCF" qui est inutile, puisque l'adresse de retour qu'elle sauve dans le registre Q ne peut être utilisée, étant ultérieurement remplacée par une autre adresse de retour. Si le branchement à NOGAMDOT est fait avec l'instruction "TCF", le programme s'exécutera légèrement plus vite que si le branchement est fait avec l'instruction "TC", car elle ne fait pas une opération inutile. Un programme ne doit pas seulement marcher, il doit aussi marcher le plus vite possible, surtout lorsque ce programme marche dans un contexte de temps-réel, et sur un ordinateur aussi lent que l'était l'ordinateur d'Apollo! Bien sûr, je ne pense pas que l'ingénieur qui a écrit ce programme était incompétent, mais je pense qu'il l'a fait exprès pour donner un indice, car il savait que ce programme ne serait jamais utilisé dans une mission lunaire. 10) Le sous-programme CORANGOV est étrange: CORANGOV TS L TC Q INDEX A CA LIMITS ADS L TC Q Dans ce sous-programme; la première instruction "TS L", selon la documentation, charge l'accumulateur soit avec +1, soit avec -1 si l'overflow est positionné (respectivement positivement ou négativement), et saute l'instruction suivante, sinon l'instruction suivante est éxécutée. L'instruction suivante, "TC Q", est donc exécutée dans tous les cas, sauf si l'accumulateur contenait un overflow lorsque la première instruction a été exécutée: cette instruction "TC Q" fait que le sous-programme revient immédiatement, et que donc les instructions suivantes du sous-programme ne sont pas éxécutées. Cela signifie que la troisième instruction n'est exécutée que si l'accumulateur contenait un overflow lors de l'exécution de la première instruction, et dans ce cas il contient soit +1, soit -1, puisque la première instruction met une de ces valeurs dedans si l'overflow est couramment positionné. Il y a ensuite deux instructions consécutives "INDEX A" et "CA LIMITS"; l'instruction "CA LIMITS" signifierait normalement que le contenu de la variable LIMITS est chargé dans l'accumulateur; mais l'instruction précédente, "INDEX A", modifie son comportement, et fait que l'adresse de la variable MIMITS" est additionnée au contenu de l'accumulateur pour former l'adresse d'une variable dont le contenu doit être placé dans l'accumulateur. Cela signifie que LIMITS est en fait à considérer comme une table indexée par le contenu courant de l'accumulateur; mais, lorsque vous indexez une table, la valeur que vous donnez pour indexer cette table doit être positive et ne pas excéder le nombre d'éléments de la table. Ici, l'accumulateur ne peut avoir que deux valeurs, +1, ou -1; cela signifie que ce couple d'instructions prendrait exclusivement soit le second élément de la table, soit la valeur qui précède cette table, et n'est pas incluse dans la table!. Donc soit un unique élément de la table LIMITS est utilisé, soit un élément en dehors de cette table. Est-ce que cela a le moindre sens? De plus, avant de retourner du sous-programme, une instruction "ADS L" est exécutée; cette instruction ajoute l'accumulateur au registre L, et place le résultat à la fois dans l'accumulateur et le registre L, selon la documentation. Mais la documentation dit ceci à propos de cette instruction: "L'overflow de l'accumulateur n'est corrigé ni avant ni après l'addition". Donc, ce sous-programme était supposé corriger l'overflow de l'accumulateur, mais sa dernière instruction détruit l'effet de la correction. J'ai trouvé un sous-programme similaire dans le programme "CM_ENTRY_DIGITAL_AUTOPILOT" de Comanche055. La seule différence est que l'instruction "CA" est remplacée par l'instruction "CAF". En fait CAF fonctionne de la même manière que CA, avec la différence qu'elle affiche un message d'erreur si la table LIMITS n'est ni dans la mémoire fixe, ni dans la mémoire dynamique. Mais pourquoi est-ce que le programme "CM_ENTRY_DIGITAL_AUTOPILOT" aurait besoin de tester l'accessibilité de la table LIMITS et pas le programme"CM_BODY_ATTITUDE"? Et dans aucun de ces deux programmes la table LIMITS n'est définie. 11) Le sous-programme "NOGAMDOT" appelé par "TC NOGAMDOT" tranfére le contenu de l'accumulateur vers la donnée mémoire "GAMDOT" par l'instruction "TS GAMDOT". Au retour de ce sous-programme (s'il y a retour), l'exécution continue en séquence et rencontre l'instruction "TS GAMDOT" à nouveau. Entre ces deux instructions, GAMDOT n'a pas été utilisé (et n'est jamais utilisé); alors quel est l'intérêt de copier l'accumulateur dans GAMDOT, si c'est pour le copier à nouveau sans avoir utilisé la copie précédente? 12) Pour en terminer avec ce programme, la conclusion est que le programme contient 302 lignes generant 7027 octets. Cela fait une moyenne de 23 octets par ligne. Pour un programme assembleur, cela semble absolument délirant. |
J'ai jeté un oeil sur les équations de guidage dans la documentation de la NASA. Si vous les regardez de loin, avec un oeil non informé, elles peuvent sembler impressionnantes et très sérieuses. Mais, lorsque vous les regardez plus attentivement, vous commencez à voir plein d'incohérences et absurdités. Je ne vais pas montrer toutes les absurdités que j'ai vues dans la documentation, je vais juste donner quelques exemples. Cette fonction "maximum of", d'un extrait d'organigramme de la documentation de la NASA, est censée donner le maximum de deux valeurs; ces valeurs doivent bien sûr être uniques et précises; mais l'une de ces valeurs données en paramètre ne représente pas qu'une seule valeur, mais une variation entre deux valeurs, nous pouvons donc nous demander comment le maximum va être obtenu! Cette formule est manifestement incohérente. Dans cet extrait d'organigramme de la documentation de la NASA, un sous-programme pour transformer les coordonnées relatives du module lunaire en coordonnées relatives à la lune est appelée, mais elle est seulement appelée si le module lunaire est sur le site d'alunissage; ceci est complétement absurde, car le module lunaire a besoin des coordonnées relatives à la lune de manière permanente, pas seulement lorsqu'il est au dessus du site d'alunissage...autrement il aura quelque difficulté à alunir! Dans cet extrait d'organigramme, un test est réalisé pour voir si une "solution Lambert" est couramment disponible; si non, un traitement est fait qui ne l'utilise pas; mais, si une solution existe, un test est fait pour voir si une variable "SF" est couramment égale à 1, auquel cas la solution Lambert n'est pas utilisée, alors pourquoi ne pas permettre de passer le test précédent si cette variable est égale à 1 puisque la solution Lambert n'est pas utilisée dans ce cas? Il est évident que, si le guidage avait voulu être sérieux, chaque organigramme aurait été écrit de manière à faire sa tâche dans le temps le plus court possible. Ceci est particulièrement important, car l'ordinateur n'est pas puissant, et avait de gros problèmes pour finir sa tâche à temps (au point de se bloquer parfois pour cette raison et de devoir redémarrer!). Nous aurions donc pu nous attendre à ce que les organigrammes soient aussi optimisés que possible. Dans cet exemple, un jeu de valeurs doit être calculé pour des valeurs de la variable P allant de 20 à 0; le calcul de ces valeurs utilise deux variables auxiliaires i et j associées avec la valeur P. La variable j commence par la valeur 29 et décrémente depuis cette valeur, mais elle saute les valeurs 26 à 3,ce qui signifie qu'elle va directement de la valeur 27 à la valeur 2; la variable i part de la valeur courante de j, et saute également les valeurs 26 à 3. Ceci est l'organigramme qu'ils donnent pour le calcul de la table de valeurs. Est ce que je veux dire que cet organigramme ne fonctionne pas? Oh non, il marche parfaitement. Alors, où est le problème? Le problème est comme suit: Lorsque la variable i a la valeur 27, les opérations suivantes sont réalisées dessus: - La valeur 27 de i est comparée avec 0; est-elle nulle? Non, elle ne l'est pas, et elle va donc sur la branche "Non" du test. - Puis la valeur 27 de i est décrémentée ce qui donne 26 comme résultat. - La nouvelle valeur de i est alors comparée avec 26; est-elle égale à 26? Oui, elle est couramment égale à 26. - Le test sort donc sur la branche "Oui", et la valeur 2 est mise dans la variable i. Donc, lorsque la variable i sort du calcul avec la valeur 27, quatre opérations sont réalisées dessus. Et, pour la variable j, c'est exactement la même chose: Quatre opérations sont réalisées sur la variable j lorsqu'elle a couramment la valeur 27. Maintenant voyons cet organigramme que j'ai corrigé. Il fonctionne également, et les variables i et j seront traitées exactement dans le même ordre que dans l'organigramme précédent. Lorsque i et j sont différents de 27, le même nombre d'opérations sont réalisées sur ces variables. C'est lorsque i ou j a la valeur 27 que la différence apparaît: Lorsque la variable i sort avec la valeur 27, la valeur 27 est directement comparée avec la valeur 27, et, si elle a cette valeur, la valeur 2 est directement mise dedans, le calcul est appelé à nouveau pour le jeu suivant de valeurs; cela fait donc seulement deux opérations pour la valeur 27 au lieu de quatre dans l'organigramme précédent, que ce soit pour la variable i ou j. Ceci signifie que ce nouvel organigramme fonctionne plus efficacement, et prend moins d'opérations que l'organigramme précédent, et sera donc plus rapide que ce dernier. Vous allez maintenant dire: Les deux solutions fonctionnent, et la différence de traitement n'est pas très importante. Elle peut ne pas être très importante, mais le point est QU'ELLE EXISTE! Si le guidage utilise de manière permanente des processus non optimisés, il est manifeste que la tâche de guidage va perdre du temps sur son traitement. Si l'AGC avait été un ordinateur puissant, et que plein de temps soit resté après qu'il ait fini sa tâche, cela n'aurait pas été un problème...Mais nous savons que l'AGC avait de gros problèmes de performance, et la fameuse alarme 1202 réultait du fait qu'il n'arrivait pas à terminer la tâche de guidage à temps parfois. Un programmeur compétent écrit toujours ses programmes de manière à ce qu'ils soient aussi performants et optimisés que possible, même s'ils tournent sur un ordinateur puissant qui n'a pas de problème de temps de traitement comme l'AGC. Il n'y a donc que deux solutions possibles: - Ou bien ils avaient donné la tâche d'écrire les programmes de guidage à des ingénieurs incompétents, ce qui serait surprenant pour un projet aussi gros que celui d'Apollo. - Ou bien les ingénieurs étaient compétents, mais ils n'avaient pas l'intention d'écrire un programme sérieux dont ils savaient parfaitement qu'il ne ferait jamis alunir un vaisseau spatial. Pour moi, il ne fait pas de doute que c'est la seconde hypothèse qui est la bonne. Un document de la librairie de la NASA, "Critique of IBM Apollo study report" fait une comparaison entre les performances de l'ordinateur IBM de la fusée Saturn, et l'AGC. L'ordinateur IBM qui était embarqué dans la fusée Saturne semble être un ordinateur sérieux, différemment de l'AGC. Et, contrairement à l'AGC, il utilisait rationellement le système de complément à 2, au lieu du système périmé et moins performant du complément à 1 de l'AGC, ce qui montre que l'AGC aurait parfaitement pu l'utiliser. Je n'ai trouvé rien à lui critiquer, il est était adapté au besoin. La raison pour laquelle il n'a pas été utilisé dans le module lunaire est qu'il n'était pas assez compact pour le module; pour la fusée Saturn, il convenait, car la fusée est grosse et peut se permettre le volume et le poids de l'ordinateur IBM, mais le module lunaire avait besoin de quelque chose de plus petit. L'ordinateur IBM avait trois modules de données, avec chacun 4906 mots de 28 bits, dont deux bits de parité et un bit de signe. L'AGC avait 2048 mots de mémoire effaçable, et 36864 mots de mémoire morte. Les mots de l'AGC avaient 16 bits, mais un de ces bits était le bit de parité, et donc 15 bits seulement étaient utilisables. Dans le document, ils font des comparaisons variées entre l'AGC et l'ordinateur IBM, et soulignent les déficiences de l'ordinateur IBM. Je vais montrer quelques unes de ces comparaisons absurdes. Sur cette comparaison, ils montrent sur la gauche l'addition de deux vecteurs de trois doubles mots de 28 bits sur l'AGC, qui ne requiert que 60 bits de mémoire qui qui utilise l'interprêteur, et ils montrent sur la droite l'addition similaire de trois mots simples de 25 bits sur l'ordinateur IBM qui requiert 117 bits de memoire, donc presque le double de mémoire; la conclusion est que l'AGC est plus performant pour faire cette addition que l'IBM. Mais la séquence de l'AGC nest pas correcte, l'interprêteur est utilisé de manière incorrecte. Les instructions de l'interprêteur étaient seulement décrites de manière sommaire dans la documentation générale de l'AGC et ne m'ont pas permis de vérifier si la séquence était correcte, mais j'ai trouvé un document dans la librairie de la NASA, écrit par Charles Muntz, et qui décrivait précisément comment l'interprêteur fonctionnait. L'instruction de l'interprêteur VAD permet d'utiliser deux vecteurs double précision, mais elle ajoute un vecteur B qui est spécifié derrière cette instruction à un vecteur qui est déjà dans une zone de mémoire spéciale, appelée MPAC, et qui est précédemment chargée par une autre instruction de l'interprêteur, appelée "VLOAD"; ce qui est incorrect dans la séquence est que le premier vecteur à ajouter est spécifié après l'instruction VAD, alors qu'il devrait être spécifié auparavant comme paramètre d'une autre instruction de l'interprêteur (VLOAD). Je montre sur la droite la séquence correcte qui réaliserait les additions des deux vecteurs double précision A et B, et placerait le résultat dans le vecteur double précision C. Nous avons donc maintenant sur la gauche la séquence correcte qui fonctionnerait pour ajouter les vecteurs double précision A et B, et place le résultat dans le vecteur double précision C. Avec cette séquence, contrairement à celle qu'ils ont montrée, la comparaison aurait un sens. Je ne me suis pas soucié de déterminer la memoire nécessaire pour memoriser cette nouvelle correcte séquence, mais elle est probablement proche de celle nécessaire pour la séquence incorrecte. De toute façon, même avec la séquence correcte, la comparaison n'a quand même pas de sens. Les instructions interprêtées ne sont pas directement exécutables par le processeur, elles doivent être traduites en instructions assembleur que le processeur peut exécuter. Et le processeur de l'AGC n'avait pas d'instructions qui permettant de faire des additions double précision comme l'ordinateur IBM; en fait il avait des instructions portant sur des double mots, mais ne permettant pas de faire ces additions aussi directement que pour l'ordinateur IBM; ceci sera clarifié sur le dernier exemple que je montrerai. Donc, la comparaison n'a pas beaucoup de sens, car elle compare des instructions interprêtées de l'AGC qui ne peuvent pas être directement exécutées par le processeur et necessitent l'interprêteur pour être traduites, avec les instructions de l'ordinateur IBM qui sont directement exécutables par le processeur. Deuxième exemple; Ils montrent ensuite une séquence d'instructions représentées sur la gauche de cette double vue; les programmeurs de l'AGC se plaignent que les programmeurs de l'IBM n'ont pas fait d'effort pour optimiser la séquence, et leur demandent de l'optimiser; après optimisation, cette séquence devient celle représentée sur la droite de la double vue. Les remarques suivantes peuvent être faites concernant cette optimisation: 1) La séquence non optimisée contient trois fois l'instruction "CLA *+2" que nous ne trouvons pas dans la séquence optimisée. l'instruction "CLA" existe dans le jeu d'instructions de l'ordinateur IBM, et permet de charger une donnée dans l'accumuilateur (registre principal de l'ordinateur). Cela pourrait sembler une instruction raisonnable, n'était le membre droit de l'instruction; le membre droit désigne l'adresse d'une donnée qui doit être chargée dans l'accumulateur; le problème est que cette adresse est spécifiée comme "*+2"; le symbole '*' est utilisé dans l'ordinateur pour représenter la valeur courante du compteur de programme (certains ordinateurs utilisent aussi '$'), c'est à dire l'adresse de l'instruction couramment exécutée; "*+2" représente la valeur courante du compteur de programme plus deux mots; comme l'instruction CLA occupe deux mots en mémoire, cette adresse représente en fait l'adresse de l'instruction suivant l'instruction "CLA"; cela signifie que cette instruction chargerait dans l'accumulateur le contenu de l'instruction qui la suit...Mais une instruction est faite pour être exécutée, et non pour être traitée comme une donnée, elle ne représente rien en tant que donnée. Ceci explique pourquoi l'instruction "CLA *+2" est complétement absurde, et bien sûr le programmeur qui l'a utilisée le savait, et donc pas étonnant qu'elle ait été éliminée dans la séquence optimisée. 2) La séquence non optimisée contient trois fois l'instruction "HOPCON *+1" que nous ne trouvons pas dans la séquence optimisée. Cette instruction ressemble à l'instruction "HOP" qui est aussi utilisée dans la séquence; l'instruction "HOP" existe dans le jeu d'instructions de l'ordinateur et est principalement utilisée pour faire des appels à des sous-programmes; selon la documentation IBM, un sous-programme appelée avec une instruction "HOP" retourne à l'appelant avec une instruction HOP constante, qui est symbolisée par l'instruction "HOPCON" utilisée sans paramètre (puisque c'est le compteur de programme mémorisé qui est utilisé). Donc, d'abord cette instruction est utilisée avec un membre droit qu'elle ne devrait pas avoir, mais de plus l'adresse spécifiée dans le membre droit correspond avec l'adresse de la prochaine instruction, ce qui rend cette instruction encore plus absurde. L'instruction "HOPCON *+1" est donc également absurde, et voulue comme telle; il n'est pas surprenant qu'elle ait été éliminée dans la séquence optimisée. 3) Finalement, nous avons encore trois instructions qui ne sont pas non plus dans la séquence optimisée. En fait ces instructions sauvent dans ces variables des valeurs qui sont déjà dans d'autres variables, car le programme ne les modifie pas après les avoir chargées dans l'accumulateur avant de les sauver dans les nouvelles variables. Une valeur donnée n'a besoin d'être sauvée que dans une seule variable; elle n'a pas besoin d'être sauvée dans deux variables différentes qui contiendraient la même chose. Donc, finalement, le programmeur IBM a mis dans cette séquence des instructions dont il savait parfaitement qu'elles étaient insensées et il savait à l'avance qu'il aurait à les éliminer pour obtenir quelque chose de cohérent. Il n'a pas du faire beaucoup d'effort pour "optimiser" sa séquence. Troisième exemple: Sur cette double vue, je montre sur la gauche une séquence dans laquelle ils ajoutent successivement deux mots en simple précision dans l'AGC, ce qui donne 28 bits de précision; ils disent que cette séquence de 7 instructions tourne en 168 microsecondes. Sur la droite, je montre la séquence de 3 instructions qui ajoute deux mots sur l'ordinateur IBM, ce qui donne 25 bits de précision seulement, et qui tournent plus lentement que la séquence AGC, c'est à dire en 246 microsecondes. Ils disent que la séquence de 7 instructions de l'AGC tourne en moins de temps que la séquence de 3 instructions seulement de l'IBM!! Donc une séquence de 3 instructions prend plus de temps pour tourner qu'une séquence de 7 instructions, c'est à dire plus que le double d'instructions? Cette différence vient d'une estimation plus qu'optimiste des timings sur l'AGC. En fait, le plus souvent la documentation de l'AGC ne dit pas explicitement ce que le hardware de l'ordinateur fait....comme ce cycle mémoire de 12 cycles d'horloge pour lire un mot de 15 bits qui n'est décrit nulle part et demeure un mystère! Alors que la documentation de l'IBM décrit exactement ce que l'ordinateur fait. Et il y a d'autres problèmes avec la séquence de l'AGC. D'abord il y a une complication inutile avec les instructions que j'ai entourées, "CAF ZERO" et "AD A"; la première charge dans l'accumulateur une variale qui contient manifestement zéro dans le même temps qu'elle met à zéro l'overflow, tandis que la deuxième ajoute la variable A à l'accumulateur; ceci est équivalent à charger directement dans l'accumulateur la variable A, ce qui peut être fait avec l'instruction que je montre sur la droite "CAF A". Donc, à présent, nous avons pour l'AGC une séquence de seulement six instructions au lieu de sept initialement, et qui fait la même chose que la séquence initiale, et qui s'exécutera un peu plus rapidement. Mais, est-ce que cette séquence fait réellement le travail prévu, et de manière optimale? En fait, elle ne fait pas vraiment le travail, car l'overflow éventuel généré par la première addition (A+1 et B+1) devrait être reporté dans la deuxième addition (A et B), et ce n'est pas le cas puisque l'overflow est mis à zéro par l'instruction CAF. Nous aurions besoin d'une instruction qui charge une variable dans l'accumulateur sans mise à zéro de l'overflow, mais je ne l'ai pas trouvée dans le jeu d'instructions de l'AGC. Puis, plus important, cette séquence n'est même pas optimale, car il existe des instructions qui peuvent gérer des doubles mots qui auraient pu être utilisées pour faire ce travail. - L'instruction "DCA A" charge dans la paire de registres A et L le double mot pointé par A, c'est à dire A et A+1. - L'instruction "DXCH C" échange le contenu de la paire de registres A et L avec le double mot pointé par C; ceci signifie qu'elle met le double mot A,A+1 (couramment dans les registres A,L) dans le double mot C,C+1; notez que nous aurions pu utiliser une instruction qui se contente de placer le contenu des registres A,L dans le double mot C,C+1 sans faire l'échange avec la paire de registres A et L, mais cette instruction n'existe pas dans le jeu d'instructions de l'AGC. - L' instruction "DCA B" charge dans la paire de registres A et L le double mot pointé par B, c'st à dire B et B+1. - Finalement l'instruction "DAS C" ajoute au double mot pointé par C la paire de registres A,L; comme le double mot C,C+1 contient couramment le double mot A,A+1, et que la paire de registres A,L contient couramment le double mot B,B+1, ceci est équivalent à mettre dans le double mot C,C+1 la somme des double mots A,A+1 et B,B+1 ce qui est précisément le travail à faire. Nous avons maintenant pour l'AGC une séquence qui n'est pas seulement correcte, car elle gére correctement l'overflow dans l'addition des doubles mots, mais est aussi réduite à 4 instructions. Elle s'exécute certainement plus rapidement que la séquence initiale de l'AGC (et correctement), mais je n'ai pas essayé de connaître son temps d'exécution, car je considére les timings des instructions de l'AGC comme pure fantaisie (contrairement à ceux de l'IBM qui sont réels et fiables). |
Ce chapitre traite du système de représentation binaire qui a été adopté pour l'ordinateur d'APollo (AGC). Au début des années 60, les ordinateurs étaient encore des grosses machines pas encore arrivées à maturité; elles n'existaient que comme grosses machines coûteuses, et seules les grosses sociétés pouvaient se l'offrir. Ils ne fonctionnaient pas encore de manière optimale, et c'était le temps où les ingénieurs cherchaient des solutions qui étaient encore loin d'être aussi performantes qu'aujourd'hui. Les ordinateurs ont d'abord utilisé le système de représentation binaire appelé "complément à 1", car c'était celui qui semblait le plus simple, le plus évident. Dans cette représentation, les nombre négatifs sont juste représentés en inversant les bits des nombres positifs (i.e. un bit à 1 devient uun 0, et vice versa). Ce qui est bizarre dans cette représentation est que 0 a deux valeurs différentes, une appelée "+0" et codée avec tous les bits à zéro, et l'autre appelée "-0" et codée avec tous les bits à un; pourtant, on nous a appris dans nos cours de maths que +0 et -0 représentent la même valeur! Le fait que 0 pouvait être représenté avec deux valeurs différentes dans ce système de représentation n'a pas semblé troubler ceux qui furent les premiers à l'utiliser. L'IBM 7090, un odinateur du début des années 60 (1962) a utilisé ce système de représentation. L'UNIVAC 1100 de la même période a également utilisé ce système de représentation. Toutefois, dès 1963, les ordinateurs ont commencé à utiliser un système de représentation appelé "complément à deux". Dans ce système de représentation, les nombre négatifs sont les nombre négatifs du système de complément à 1 (avec tous les bits complémentés) avec ajout d'une unité. Donc la représentation (sur un octet) de -1 n'est plus 11111110 mais 11111110+1=11111111, c'est à dire la représentation de -0 dans le système de complément à 1 (-1 prend la place de -0 dans le système de complément à 2). Donc, dans ce système de représentation, 0 a une valeur unique, et non plus deux valeurs différentes comme dans le système de complément à 1. La conséquence de ceci est que les nombre négatifs peuvent encoder un nombre de plus que les nombres positifs. Dans le système de complément à 1, un mot de 16 bits peut représenter des nombres de -32767 à +32767, alors que, dans le système de complément à 2, le même mot de 16 bits peut représenter des nombre de -32768 à 32767. Vous aller penser que, si c'est la seule différence, cela semble plutôt pauvre pour expliquer le succès du complément à deux, et l'abandon du système de complément à un, mais en fait la différence est bien plus importante que cela, comme je vais vous l'expliquer. Le premier ordinateur (où l'un des premiers) à utiliser le système de complément à deux est le PDP-5 de DEC. Il a été développé en 1963, et offert au public en 1964. DEC a fait un successeur au PDP-5, le PDP-8, utilisant également le système de complément à deux, et qui a été développé en 1964, et offert au public en 1965. En Avril 1964, IBM a annoncé l'IBM 360, son premier ordinateur à utiliser le système de complément à deux. Cet ordinateur a été utilisé par la NASA. Et, en ce qui concerne les microprocesseurs, qui ont commencé à apparaître dans les années 70 (ici le premier d'entre eux, l'intel 8080), ils ont utilisé le système de complément à deux depuis le début, et jamais le système de complément à un. Alors, pourquoi les constructeurs d'ordinateur ont-ils délaissé le système de complément à un pour le système de complément à deux? Je vais d'abord avoir un mot à propos de l'addition de bits, les bits sont additionnés en prenant en compte une retenue (carry) qui est produite par l'addition précédente de bits, comme dans les additions décimales que vous avez l'habitude de faire. La partie supérieure de la figure montre l'addition de bits lorsqu'il n'y a pas de retenue, et la partie inférieure l'addition de bits lorsqu'il y a une retenue. J'indique en bas à droite de chaque addition la retenue qui est générée par l'addition de bits, et qui est prise en compte dans l'addition suivante de bits. Cette animation montre le mécanisme de l'addition de -0 avec +1 dans le système de complément à un. Bizarrement, le résultat obtenu est ...+0! Pourtant on nous appris dans nos cours de maths que 1+0=1 et non 0. Toutefois, cela ne veut pas dire qu'un ordinateur utilisant le complément à un ne peut pas faire correctement des additions, car le dépassement est ensuite testé pour mettre à jour l'addition dans une seconde passe. Cette seconde animation montre le mécanisme de l'addition de -1 avec -2 dans le système de complément à un. Bizarrement, le résultat obtenu est...-4! Pourtant on nous a appris dans cours de maths que -1 ajouté à -2 fait -3 et non -4. Une fois de plus le test de dépassement permet de corriger le résultat de l'addition et d'obtenir le résultat correct. Mais cela montre que le résultat des additions n'est pas immédiat et requiert des tests complémentaires. Maintenant voyons comment une addition de nombre négatifs marche dans le système de complément à deux: Si nous ajoutons -1 à -2, nous obtenons...-3, c'est à dire directement le bon résultat, pas besoin de le mettre à jour comme dans le système de complément à un. Ceci signifie que le système de complément à deux donne des résultats plus directs que le système de complément à un, et évite de faire des tests. Comme il vaut mieux faire matériellement les tests qui doivent être faits par le système de complément à un plutôt que de les faire logiciellement, ce qui diminuerait de manière importante les performances du système, cela signifie que le système matériel est plus compliqué pour implémenter un système de complément à un que pour implémenter un système de complément à deux. Et, même avec le matériel rajouté, les système de complément à un reste moins performant que le système de complément à deux. Vous commencez donc à comprendre pourquoi le système de complément à deux est largement préférable au système de complément à un. En 1964, la NASA a organisé des réunions pour parler du matériel d'Apollo, et les choix qui devaient être faits, en partculier pour le matériel électronique de l'ordinateur. En particulier, ils ont discuté à propos de l'utilisation des circuits intégrés pour résuire le volume de l'ordinateur. C'était le moment de faire des choix judicieux pour le matériel et obtenir la meilleure efficacité pour l'ordinateur (i.e. minimisation du matériel, et optimisation des performances). A cette époque, les avantages du système de complement à deux sur le système de complément à un étaient connus, et les constructeurs d'ordinateur commençaient à utiliser le complément à deux au lieu du complément à un pour un meilleur rendement de leurs ordinateurs, et réduire les coûts. Les ingénieurs du MIT ne pouvaient l'ignorer (l'ingénieur qui a developpé le PDP-5 était même diplômé du MIT). ! Ils savaient qu'il existait deux systèmes de représentation, avec l'un d'eux plus performant que l'autre. Ils avaient le choix entre le système de complément à deux, requérant moins de matériel pour réaliser les mêmes fonctions, et plus performant... ...Et le système de complément à un, moins aisé à implémenter matériellement, et moins performant. Alors, qui a été couronné? Le système le plus performant ou le moins performant? Très étonnamment, c'est le second qui été choisi, contre toute logique! Alors, pourquoi les ingénieurs du MIT, qui n'étaient certainement pas stupides, ont choisi ce qu'ils savaient être le système le moins performant, celui qui nécessitait le plus de circuiterie électronique pour obtenir un résultat moins performant que celui qui aurait été obtenu avec le système qu'ils ont rejeté? Je doute que ce soit parce qu'ils avaient la "nostalgie" du système de complément à un! je pense plutôt que la raison était qu'ils n'avaient pas l'intention de faire un ordinateur sérieux qu'il savaient parfaitement qu'il ne ferait jamais alunir un module lunaire. |
J'ai jeté un regard sur le livre de Frank O'Brien "Apollo Guidance Computer, Architecture and operation". Frank O'Brien commence par décrire la philosophie des systèmes temp-réel avec des tâches tournant concuramment. Ce qu'il dit dans sa préface tient debout. Puis il commence à décrire la gestion des tâches dans l'ordinateur d'Apollo. Mais O'Brien n'est pas un spécialiste des systèmes temps-réel; il est plus un écrivain qu'un ingénieur informaticien. Il n'est donc pas conscient de certains aspects absurdes sur la manière dont l'ordinateur d'Apollo était géré. De mon côté, je suis un ingénieur informaticien spécialisé dans les applications temps-réel, et j'ai travaillé sur des processus high-tech. Alors, ce à quoi O'Brien passe à coté, je peux le voir, et je vais le décrire dans ce chapitre. Les ordinateurs modernes ont une pile. Un pile permet de mémoriser des variables temporaires locales, et également de faire des appels imbriqués. Dans un système multi-tâches, la pile rend plus commode l'échange des tâches. Chaque tâche a sa propre pile, et, lorsqu'une tâche doit tourner, le pointeur de pile du processeur a simplement à pointer vers la pile du processus courant. Une pile fonctionne suivant le principe "Dernier rentré - premier sorti"; lorsqu'une donnée doit être sauvée dans la pile, elle est poussée sur le sommet de la pile, et, quand elle doit être restaurée, elle est extraite du sommet de la pile; si elle est la dernière à avoir été poussée, elle sera la première à être extraite. Une pile permet de gérer inteligemment des données locales, et de faire des appels successifs à des sous-programmes: A chaque fois qu'un sous-programme est appelé, son adresse de retour et ses paramètres sont poussés sur la pile; ce sous-programme peut aussi avoir des données temporaires qu'il pousse aussi sur la pile: ce sous-programme peut à son tour appeler un autre sous-programme, et l'adresse de ce nouveau sous-programme et ses paramètres seront à leur tour poussés sur la pile; lorsque le sous-programme se termine, ses données locales et paramètres sont extraits de la pile, ainsi que son adresse de retour qui lui permet de savoir où il doit retourner, c'est à dire l'adresse qui suit immédiatement l'appel au sous-programme; la seule limitation d'une pile est sa taille. Maintenant, l'ordinateur d'Apollo n'avait pas de pile. Il avait un registre unique pour sauver l'adresse de retour, appelé Q. Lorsque le processeur exécutait une instruction du programme principal appelant un sous-programme, avant d'aller au début du sous-programme, il sauvait l'adresse de l'instruction suivant l'appel dans le registre Q. Puis il commençait à exécuter le sous-programme. Quand la fin du sous-programme était atteinte, le processeur rechargeait le compteur de programme avec le contenu de Q, c'est à dire l'adresse de l'instruction suivant l'appel, et le processeur pouvait alors reprendre le traitement du programme principal depuis cette instruction. LE registre Q fonctionne donc parfaitement pour appeler un sous-programme depuis le programme principal. Une pile n'est pas nécessaire pour un simple appel de sous-programme. Maintenant supposons que le sous-programme appelé par le programme principal veuille appeler un second sous-programme à son tour. Il doit également sauver l'adresse de l'instruction suivant l'appel dans le registre Q, mais il y a un problème, car Q contient couramment l'adresse de l'instruction suivant l'appel dans le programme principal. Alors, que va faire le sous-programme? Supposons que le sous-programme passe outre et ré-écrive Q avec l'adresse de l'instruction suivant l'appel au deuxième sous-programme, de sorte que le deuxième sous-programme puisse revenir au premier sous-programme après qu'il se termine. Le deuxième sous-programme commence à s'exécuter. Le second sous-programme se termine, et le compteur de programme est rechargé à partir du contenu de Q qui contient l'adresse de l'instruction suivant l'appel au deuxième sous-programme. Le premier sous-programme peut continuer son traitement. Alors j'ai été trop pessimiste, cela peut fonctionner? Non en fait, parce que, lorsque le premier sous-programme se termine, le compteur de programme est rechargé avec le contenu de Q; mais Q contient couramment l'adresse de l'instruction suivant l'appel au second sous-programme dans le premier sous-programme, et non l'adresse de l'instruction suivant l'appel au premier sous-programme dans le programme principal. Donc, les instructions entre l'appel au second sous-programme et la fin du premier sous-programme vont être exécutées à nouveau, et ce indéfiniment... Vous voyez donc l'effet d'avoir un seul registre pour sauver l'adresse de retour: Cela interdit de faire des appels imbriqués multiples. Le programme principal peut appeler un sous-programme, mais un sous-programme ne peut appeler lui-même un autre sous-programme, sinon cela crée une boucle sans fin fatale dont l'ordinateur ne peut sortir. Maintenant vous allez dire qu'il n'est pas forcément nécessaire qu'un sous-programme appelle un autre sous-programme, que cela ne vaut pas la peine d'implémenter un gestion de pile dans le processeur. Peut-être, mais le programmeur doit en être consient, et être sûr de ne jamais appeler un sous-programme depuis un autre sous-programme. Certes, nous pouvons accepter la simplification d'utiliser un registre unique pour gérer l'appel aux sous-programmes, ce qui peut se justifier par le fait de ne pas avoir à gérer de pile. Mais il y a cependant quelque chose qui est moins justifiable: Lorsqu'une interruption se produit, non seulement l'adresse de l'instruction interrompue est sauvée dans le registre ZRUPT, ce qui est parfaitement normal, mais de plus le contenu de cette instruction est sauvée dans le registre BRUPT, et ceci est beaucoup moins normal. En effet, lorsque l'intettuption se termine, le compteur de programme est rechargé à partir du registre ZRUPT pour continuer le traitement à partir de l'instruction interrompue, ce qui est un processus parfaitement normal, mais de plus l'instruction interrompue serait mise à jour avec le contenu du registre BRUPT dans laquelle elle aurait été sauvée avant le traitement de l'interruption? Pour quoi faire??? Ceci est totalement inutile, car l'instruction interrompue a gardé son contenu pendant l'exécution de l'interruption, et il n'y a donc pas lieu de la recharger à partir du registre BRUPT! Le processeur réalise donc des opérations qui sont totalement inutiles; cela complique inutilement le traitement de l'appel, et de plus cela gaspille des temps de cycle, car le fait de sauver dans et restaurer depuis le registre BRUPT prend des temps de cycles au processeur. La gestion du registre BRUPT n'est donc absolument pas justifiée par la simplification, bien au contraire, car elle crée une complication complètement inutile, et gaspille de la puissance de l'ordinateur (qui n'en a déjà pas beaucoup). Nous allons maintenant voir comment la gestion des tâches était faite sur l'ordinateur d'Apollo. Le principe était que chaque tâche allouait un jeu de ressources; ces ressources consistaient en un "core set" dans lequel la tâche mémorisait ses principaux attributs (son addresse courante, sa priorité...), et une zone plus importante appelée zone VAC, dans laquelle la tâche pouvait mémoriser les variables que lesquelles elle travaillait spécifiquement. La tâche pouvait aussi utiliser des données globales qui pouvaient être partagées par d'autres tâches. La première opération qu'une tâche lancée faisait était d'allouer ces ressources depuis des blocs de mémoires réservés pour ces ressources. Cela signifie qu'il devait rester au moins un core set dans le bloc des core sets, et une zone VAC dans le bloc des zones VAC; lorsque la tâche avait trouvé un core set et une zone VAC, elle marquait le premier mot de ceux-ci comme étant reservés, de sorte que les autres tâches ne puissent les prendre. Inversement, lorsqu'une tâche se terminait, elle libérait ses ressources en démarquant les premiers mots des ressources comme étant libres. Mais ce n'était pas parce qu'une tâche avait alloué des ressources qu'elle pouvait immédiatement tourner. Les tâches de priorité supérieure avaient précédence sur les tâches de priorité inférieure. Supposez quer deux tâches soient couramment définies; un tâche P3 de priorité 3, et une tâche P1 de priorité 1; comme P3 a une priorité supérieure à P1, il est couramment en train de tourner, et P1 attend que P3 se termine pour pouvoir tourner à son tour. Un registre NEWJOB indique si la tâche couramment en train de tourner est la plus prioritaire ou non; si c'est le cas, NEWJOB contient 0, et sinon NEWJOB contient l'adresse du core set d'une tâche plus prioritaire en attente de pouvoir tourner. Généralement NEWJOB contient 0. A présent arrive une tâche P2 de priorité 2 intermédiaire entre les priorités de P1 et P3. La première chose que P2 fait est d'allouer ses ressources, soit un core set and une zone VAC, et d'initialiser le core set (le marquant comme réservé, mettant dedans l'adresse de départ du programme, sa priorité...). Mais P2 voit qu'il est moins prioritaire que la tâche courante P3, et il ne change donc pas le contenu de NEWJOB qui reste à 0. P3 continue donc son traitement sans être dérangé par P2. P3 atteint sa fin et libère les ressources qu'il avait réservées (le core set et la zone VAC). Le processeur recherche à présent la tâche la plus prioritaire parmi les tâches en attente en examinant les priorités mémorisées dans les core sets, et trouve que c'est P2. Le core set et la zone VAC de P2 sont copiés dans les premiers core set and zone VAC qui sont toujours ceux de la tâche en cours d'exécution. Le compteur de programme est chargé avec l'adresse de la première instruction de P2 qui commence à se dérouler. P2 se termine finalement, et libère ses ressources (le core set et la zone VAC). A présent P1 est la seule tâche restante; et donc son core set et zone VAC sont copiés dans les premiers core set et zone VAC qui sont ceux de la tâche en cours d'exécution, et elle commence à se dérouler. P1 se termine finalement, et libère ses ressources. Il n'y a plus de tâche restante, et il disent que dans ce cas ils font tourner une pseudo tâche appelée "DUMMY JOB". Mais ce cas a peu de chance de se produire, car ils disent que les tâches SERVICER s'accumulaient comme elles étaient retardées par les autres tâches, et il y avait donc toujours plusieurs tâches restantes (jusqu'au point d'épuiser les ressources!). Supposons à présent que la tâche de plus haute priorité courante P2 ait une priorité 2. Arrive à présent une tâche P3 de priorité 3 plus haute que les priorités des deux autres tâches. La première chose que P3 fait est d'allouer ses ressources, soit un core set et une zone VAC, et d'initialiser le core set (le marquant comme réservé, mettant dedans l'adresse de départ du programme, sa priorité...). Mais, contrairement à l'exemple précédent, P3 voit qu'il a une priorité plus haute que la tâche courante P2. Il ne laisse donc par le registre NEWJOB inchangé, mais au contraire y écrit l'adresse de son core set, afin que la tâche P2 soit informée qu'une tâche plus prioritaire est en attente d'exécution. P2 continue de s'exécuter jusqu'à ce qu'il rencontre un point de test du changement de tâche. Un point de test est décrit comme étant un jeu des deux instructions suivantes: CCS NEWJOB TC CHANG1 Si NEWJOB contient couramment 0, la tâche courante est couramment la plus prioritaire, et le test de NEWJOB par CCS fait que le processeur saute l'instruction suivante; la tâche continue de d'exécuter; mais, si NEWJOB ne contient pas zéro, le test de NEWJOB par CCS fait que l'instruction suivante est exécutée, laquelle appelle un programme qui faisait l'échange des tâches pour remplacer la tâche courante avec la tâche plus prioritaire. C'est ici le cas, NEWJOB est non nul, et contient l'adresse du core set de P3. Conséquemment, l'échange des tâches doit être fait. Le core set et la zone VAC de P2 sont d'abord mis à jour avec les premiers core set et zone VAC de la tâche en cours (précédemment P2), de sorte que P2 puisse recouvrer son contexte d'exécution lorsqu'il reprendra la main. Puis le core set et la zone VAC de P3 sont copiés dans les premiers core set et zone VAC de la tâche en cours, et P3 commence de s'exécuter depuis son début. P3 se termine finalement et libère ses ressources (core set et zone VAC). Après la fin de P3, P2 est à présent la tâche la plus prioritaire. les premiers core set et zone VAC de la tâche en cours sont mis à jour avec le core set et zone VAC de P2; comme le compteur de programme de P2 a été mémorisé dans son core set, P2 peut repartir depuis le point où il a été interrompu par P3, et non depuis son début. P2 se termine et libère ses ressources (core set et zone VAC). P1 est à présent la seule tâche restante, et son core set et VAC area sont donc copiés dans les premiers core set et VAC area de la tâche courante, et P1 commence à s'exécuter. P1 se termine finalement, et libère ses ressources. Ce processus est inutilement compliqué. le regisre NEWJOB n'est même pas nécessaire. Dès que P3 arrive, au lieu d'attendre que P2 atteigne un point de test, il serait plus pratique si le core set et la zone VAC de P2 etaient immédiatement mis à jour avec les premiers core set et zone VAC de la tâche en cours (P2). Et le core set et la zone VAC de P3 seraient copiés dans les premiers core set et zone VAC de la tâche en cours, de manière à ce que P3 puisse commencer à s'exécuter. Avec cette gestion, P3 n'aurait pas à attendre que P2 s'aperçoive qu'il y a une tâche plus prioritaire en attente; il commencerait immédiatement à s'exécuter dès que lancé, sans délai. Dans la gestion qu'ils ont imaginée, comparée avec la gestion que j'ai décrite, il y a des opérations que la gestion que j'ai d'écrite n'a pas à faire, et qui surchargent le changement de tâche. D'abord la tâche entrante doit mettre à jour le registre NEWJOB; mais ce n'est pas l'opération qui prend le plus de temps au processeur. L'opération qui prend le plus de temps est que la tâche en cours doit régulièrement tester si une tâche plus prioritaire n'est pas arrivée, en insérant régulièrement ces deux instructions dans son programme: CCS NEWJOB TC CHANG1 Si elle ne fait pas ce test assez souvent, alors la nouvelle tâche entrante aura à attendre plus de temps avant d'être servie. D'un autre côté, si la tâche courante fait ce test assez souvent, alors, peut-être que la nouvelle tâche entrante peut être servie assez rapidement après être arrivée, mais la tâche courante gâchera beaucoup de temps à faire ces tests. Avec le processus que j'ai décrit, il n'y a pas de temps gaspillé à faire des tests, et la nouvelle tâche entrante est servie immédiatement. Ils disent que le programmeur devrait s'assurer qu'il n'y ait pas plus de vingt millisecondes séparant deux tests successifs, mais comment voulez-vous que le programmeur estime ceci? C'est délirant! Maintenant, vous pouvez dire: Dans le système que j'ai décrit, une tâche plus prioritaire peut interrompre la tâche courante à n'importe quel endroit qu'elle soit La tâche courante ne peut pas choisir l'endroit où elle est interrompue. La plupart du temps, cela n'a pas d'importance, car, lorsque la tâche courante travaille sur son propre VAC, comme elle est la seule qui y accède et le modifie, elle peut être interrompue à tout moment. Mais, dans certains cas, la tâche courante peut désirer ne pas être interrompue durant une séquence limitée (lorsqu'elle lit ou modifie des variables globales aussi utilisées par d'autres tâches, par exemple). Dans ce cas, il existe une solution possible. Nous utilisons encore le registre NEWJOB dans cette solution, mais nous ajoutons un autre registre spécial que j'appellerai "PROTECT". Généralement, les registres NEWJOB et PROTECT contiennent 0. Lorsqu'une tâche plus prioritaire P3 est lancée, elle teste le registre PROTECT. Si le registre PROTECT contient 0, cela signifie que la tâche courante n'est pas en train d'exécuter une zone protégée de code, et la nouvelle tâche P3, au lieu de mettre à jour P3, réalise l'échange de tâches, mettant à jour le core set et la zone VAC de P2 avec ceux de la tâche en cours, et copiant ses propres core set et zone VAC dans ceux de la tâche en cours. Elle commence ensuite à s'éxécuter depuis son début. Supposons à présent que la tâche courante veuille exécuter une séquence de code dans laquelle elle ne soit pas interrompue par une tâche plus prioritaire. Elle met d'abord 1 dans le registre PROTECT, pour notifier le fait qu'elle exécute couramment une zone de code protégé. Puis, alors que la tâche courante exécute son code protégé, une nouvelle tâche P3 plus prioritaire arrive. P3 teste le contenu de PROTECT et voit qu'il est à 1. P3 sait alors que la tâche courante exécute une zone de code protégé, et, au lieu de réaliser immédiatement l'échange des tâches, écrit simplement l'adresse de son core set dans le registre NEWJOB, de la même manière que dans la solution qui a été retenue dans Apollo. Puis, elle ne s'exécute pas, mais attend que P2 la démarre. P2 termine sa zone de code protégé, et écrit un 0 dans le registre PROTECT de manière à terminer la protection d'interruption par une autre tâche. Immédiatement après avoir déverrouillé PROTECT, P2 doit tester NEWJOB pour voir si une tâche plus prioritaire a été lancée pendant l'exécution de la zone de code protégé. Si c'est le cas (i.e. NEWJOB ne contient pas 0), P2 réalise lui-même l'échange des tâches et démarre P3, tandis qu'il se met en attente que P3 se termine avant de reprendre son propre traitement. Je montre ici l'organigramme pour une nouvelle tâche entrante. Et je montre ici l'organigramme pour la tâche courante lorsqu'elle veut exécuter une zone de code protégé dans laquelle elle ne veut pas être interrompue. Dans cette solution, il y a encore des tests du registre NEWJOB, alors pourquoi ai-je protesté contre son emploi tel qu'ils l'ont prévu? Pace que, dans cette dernière solution, l'usage de NEWJOB n'est qu'occasionel, exceptionel... ...alors que dans la solution Apollo, ce test est systématique et fait répétitivement à intervalles rapprochés. Il va donc sucer une bonne part de la puissance de l'ordinateur. Maintenant, quel était le principal problème de la gestion des tâches de l'ordinateur d'Apollo? Le principal problème est qu'ils avaient donné la plus basse priorité à la tâche la plus importante, c'est à dire la tâche "SERVICER", qui était chargée du guidage (ce qui incluait l'acquisition des données, le calcul d'équations à partir de ces données et les données attendues qui résultaient en des corrections à appliquer au réacteur principal et les réacteur latéraux, et l'envoi des commandes correspondantes aux réacteurs). Le résultat était que la tâche SERVICER était souvent interrompue par des tâches plus prioritaires qui retardaient son exécution. La conséquence était que le temps d'exécution de SERVICER était souvent plus long que prévu, et dépassait sa période d'exécution (après chaque période une nouvelle tâche SERVICER était automatiquement lancée, car elle devait tourner périodiquement); cette période était de deux secondes, ce qui aurait normalement dû suffire pour que la tâche SERVICER termine son traitement avant l'arrivée de la tâche SERVICER suivante: mais ce n'était souvent pas le cas, à cause de la perturbation créée par les autres tâches (y compris la tâche de gestion du clavier et de l'affichage). Donc, à force d'être constamment retardée, et de ne pouvoir terminer son traitement à temps avant la tâche SERVICER suivante, les tâches SERVICER en attente s'accumulaient progressivement. Et, à chaque fois qu'une nouvelle tâche SERVICER était lancée, elle réservait des resources des blocs de ressources disponibles (un core set and une zone VAC). A un moment donné, il y avait tant de tâches SERVICER en attente, qu'elles avaient épuisé les ressources disponibles, et qu'il ne restait plus de core set ou zone VAC libre dans les blocs de ressources. Si, à ce moment là, une nouvelle tâche plus prioritaire se présentait, elle essayait d'allouer ses propres ressources, mais elle n'y parvenait pas, car les ressources avaient toutes été prises par les tâches SERVICER en attente. L'ordinateur était alors dans une situation qu'il ne pouvait gérer, car la nouvelle tâche entrante ne pouvait allouer les ressources dont elle avait absolument besoin pour tourner. Dans cette situation, ils disent que la seule solution était un redémarrage de l'ordinateur. Ils disent qu'ils avaient des solutions pratiques pour faire le redémarrage, pour minimiser le travail que l'ordinateur avait à faire pour revenir dans la situation dans laquelle il était avant le blocage, mais c'est du pipeau, un redémarrage n'est jamais anodin. La réalité est que cette situation n'aurait jamais du se produire. Et il existe des solutions pour ne pas la laisser arriver. Une première solution serait que, même s'il y a plusieurs tâches SERVICER en attente, une seule devrait couramment réserver des ressources. Supposez qu'une nouvelle tâche SERVICER soit lancée, et que la précedente soit encore en train de tourner (pour avoir été trop interrompue par des tâches plus prioritaires). Puisqu'il y a déjà une tâche SERVICER en cours, cette nouvelle tâche ne réserverait pas de ressources (i.e. elle ne reserverait pas un core set et une zone VAC). Au lieu de cela, elle incrémenterait simplement un compteur de tâche dans le core set de la tâche SERVICER courante, afin de l'informer qu'une nouvelle tâche SERVICER a été lancée pendant qu'elle s'exécutait. Puis elle disparaîtrait simplement, et la tâche SERVICER courante continuerait à s'exécuter normalement (à moins d'être interrompue par une tâche plus prioritaire). Lorsqu'elle se termine, la tâche SERVICER courante testerait son compteur de tâche dans son core set de manière à déterminer sa prochaine action. Si le compteur de tâche est différent de 0, cela signifie qu'au moins une nouvelle tâche SERVICER a été lancée pendant qu'elle s'exécutait; dans ce cas, elle garderait ses ressources au lieu de les libérer, décrémenterait le compteur de tâche, et recommencerait depuis son début. Et, si le compteur de tâche est nul, cela signifie qu'aucune tâche SERVICER est en attente, et la tâche SERVICER courante libérerait simplement ses ressources. Avec ce processus, même s'il y a plusieurs tâches SERVICER en attente, et quel que soit ce nombre, seul un core set et une zone VAC seraient réservés pour toutes les tâches SERVICER en attente; il n'y a pas de danger que les tâches SERVICER épuisent les ressources disponibles, et l'ordinateur ne se bloquerait pas, et n'aurait jamais à redémarrer. Même si cette solution n'est pas retenue, et qu'une nouvelle tâche SERVICER entrante réserve des ressources même si une autre tâcher SERVICER tourne déjà, il y a encore une autre solution pour empècher les tâches SERVICER d'épuiser les ressources disponibles. Supposez qu'une tâche SERVICER soit couramment en train de tourner, et qu'une autre tâche SERVICER soit en attente. Alors arrive une troisième tâche SERVICER. Que devrait faire cette troisième tâcher SERVICER? Allouer des ressources et attendre comme la seconde tâche SERVICER? Pas du tout, il est tout à fait inutile que cette nouvelle tâche SERVICER attende...Parce que d'ici qu'elle puisse tourner, une nouvelle tâche SERVICER aura déjà été lancée; Il est donc préférable de juste la jeter; il n'est pas sain de laisser les tâches SERVICER s'accumuler, car il n'y a pas moyen que trop de tâches SERVICER accumulées puissent être servies à intervalles réguliers, et il est impportant qu'elles soient servies à un intervalle aussi régulier que possible, et pas un intervalle flottant. Donc, le fait que les tâches SERVICER épuisent les ressources disponibles est loin d'être une fatalité et peut être aisément évité. Maintenant, comment est-ce que l'AGC gérait le redémarrage? A des points réguliers, appelées "way points" (points de passage), une tâche sauvait ses données dans une zone de sauvegarde avant de traiter l'instruction suivante. Alors, l'AGC est bloqué, après avoit inconsidérément gaspillé du temps de traitement. Chaque tâche existante revient à son dernier point de passage (sauf si elle y est déjà). Les données de la tâche sont restaurées à partir de la zone de sauvegarde. Et puis la tâche exécute à nouveau toutes les instructions entre le point de passage et le point où elle s'est retrouvée bloquée. La tâche gaspille donc du temps à restaurer des données, et exécuter à nouveau des instructions qu'elle avait déjà exécutées avant de se retrouver bloquée. Pouquoi dis-je qu'elle gaspille ce temps? Est-ce que je veux dire que la tâche aurait pu redémarrer sans revenir au point de passage? Cette gestion des points de passage est rendue encore plus absurde par le fait que sauver les données de la tâche est loin d'être immédiat. Certains imaginent que cela pourrait être fait par une manipulation magique, mais il n'y a pas de miracle; Les données de la tâche sont dans la mémoire magnétique, et également celles de la zone de sauvegarde; donc sauver tous les mots de la zone de données vers la zone de sauvegarde signifierait une séquence d'accès de lecture et écriture dans la mémoire magnétique, et c'est loin d'être instantané; de nos jours, les accès mémoire sont extrêmement rapides, mais les accès dans la mémoire magnétique de tores étaient plutôt lents en comparaison. Une routine de guidage est en train de tourner. Une tâche plus prioritaire l'interrompt. Cette tâche essaie d'allouer une aire VAC afin qu'elle lui permette de tourner. Mais elle ne le peut pas, car les tâches de guidage retardées dans la liste d'attente ont épuisé toutes les ressources de mémoire disponibles. Alors l'alarme 1202 est affichée sur le DSKY, avertissant les astronautes du problème. La procédure BAILOUT est alors appelée, de manière à finaliser le traitement. Alors, que devrait faire cette procédure? BAILOUT devrait d'abord retirer toutes les tâches de guidage retardées de la liste d'attente. En effet, elles sont trop tardives et ne seront jamais exécutées, car, lorsque la tâche de guidage courante est terminée, elle sera automatiquement remplacée par la prochaine routine de guidage, les tâches de guidage dans la liste d'attente ne seront pas utilisées. Les tâches de guidage retirées de la liste d'attente n'ont donc plus besoin des ressources mémoire qu'elles ont allouées, et celles-ci peuvent être retournées dans la réserve de ressources mémoire. A présent que la réserve d'aires VAC a de nouveau été remplie, la tâche interrompante peut allouer l'aire VAC dont elle a besoin pour tourner. La tâche interrompante peut alors tourner, et, lorsqu'elle se termine, elle exécute l'instruction "RESUME" qui permet de retourner au point où la routine de guidage avait été interrompue. Et la routine de guidage peut alors reprendre son traitement depuis le point où elle avait été interrompue, avec ses données courantes. Lorsque la routine de guidage se termine, la tâche de guidage suivante est automatiquement lancée, car les tâches de guidage sont automatiquement lancées toutes les deux secondes. Nous avons ici un redémarrage propre, une situation saine où les ressources mémoire sont à nouveau disponibles, et qui permet à l'ordinateur de fonctionner normalement. Alors pourquoi, lorsque la tâche interrompante est revenue au point où la tâche de guidage avait été interrompue, le programme retournerait au point de passage précédent... ...transférerait vers les données courantes les données sauvées à ce point de passage, ce qui est un processus assez long... ...et exécuterait à nouveau les instructions entre ce point de passage et le point où la routine de guidage avait été interrompue... ...Alors que, tout ce qu'elle avait à faire, après le retour de la tâche interrompante, était de simplement exécuter la partie de programme qui suit le point d'interruption! Tout d'abord, et rien que cela aurait pu suffire à ce que les tâches SERVICER ne s'accumulent pas et n'épuisent pas les ressources, la tâche SERVICER, qui est la tâche la plus importante, car elle assure le guidage du vaisseau spatial, aurait du se voir attribuer la plus haute priorité et non la plus basse. Quelles sont les conséquences d'attribuer la plus basse priorité à cette tâche? Dans son "Tales about the Apollo guidance computer", Don Eyles dit que le délai de réaction du réacteur était de 0,3 seconde, mais ils avaient initialement prévu qu'il serait de 0,2 seconde; le réacteur était donc en retard de 0,1 seconde sur la prévision; la conséquence, d'après Don Eyles, était qu'ils observaient de sérieuse perturbations dans le comportement du réacteur, qu'ils appelaient "throttle excursions" et dont je représente le graphe sur la figure, et ces perturbations pouvaient être potentiellement dangereuses, d'après Don Eyles, et mettre en danger le guidage du vaisseau spatial. Alors ils prévoyaient de compenser le délai de réaction du réacteur en envoyant la commande 0,1 seconde plus tôt, de manière à faire comme si le délai de réaction du réacteur était seulement de 0,2 seconde. Mais un ingénieur décida de ne pas compenser, et il eut raison, car la NASA parvint à réduire le temps de réaction du réacteur de 0,3 seconde à 0,2 seconde, ce qui fit que la compensation n'était plus nécessaire, et ce qui fit disparaître les perturbations observées. Maintenant imaginez, si la tâche SERVICER ne peut pas être servie régulièrement, et son exécution est constamment retardée de manière aléatoire, cela signifie que le moment auquel la commande est envoyée va varier de manière consistante, davantage que 0,1 seconde. Donc, si le fait que la commande soit retardée de 0,1 seconde peut avoir de sérieuses conséquences, imaginez ce que cela peut donner si la commande est retardée davantage de manière aléatoire? Ne serait-ce pas une bonne raison pour donner la priorité la plus haute à la tâche SERVICER, de manière à ce qu'elle puisse tourner régulièrement et envoyer les commandes à temps? Et, si la tâche SERVICER n'avait pas à faire des tests répétitifs pour voir si une tâche plus prioritaire n'est pas en attente, elle aurait économisé pas mal de temps pour son exécution, et elle aurait eu plus de chance de finir à temps! Et aussi, s'il n'y avait pas eu des instructions de l'ordinateur (PINC and MINC) pour compter des impulsions matérielles (et peu importe que ces instructions soient appelées 'non programmées", car elles prennent quand même des temps de cycle à l'ordinateur)... ...Et que la tâche de compter les impulsions matérielles avait été dévolue à un simple compteur électronique que le processeur peut lire à tout moment avec un opération I/O (et l'opération I/O existe, elle est décrite dans la documentation!)... ...cela aurait permis de sauver une importante quantité de temps de cycle qui auraient été plus intelligemment utilisés pour le traitement de la tâche SERVICER qui aurait eu alors plus de chance de terminer à temps et d'être servie à intervalles réguliers au lieu d'intervalles irréguliers (jusqu'au point de provoquer l'épuisement des ressources à cause de la gestion absurde, et conséquemment le redémarrage de l'ordinateur!). IL N'Y AURAIT JAMAIS DU AVOIR UN REDEMARRAGE DE L'ORDINATEUR, JAMAIS! Et c'était parfaitement possible, même avec les ressources limitées de l'ordinateur, sans ajouter de complication au matériel (et même en le simplifiant). Cela va même encore plus loin dans l'absurdité, car ils disent qu'un programme inconnu volait des temps de cycle à l'ordinateur, dégradant ses performances. LOL, les pirates informatiques existaient même en ce temps! Donc, définitivement, l'ordinateur d'Apollo n'était pas un ordinateur sérieux, mais un clown, juste bon pour le cirque! |
Ce chapitre traite de la mémoire à cordes de tores d'Apollo qui est supposée avoit contenu le programme d'Apollo. De nos jours, la mémoire d'un ordinateur est contenue dans ces circuits intégrés. Celui-ci est assez ancien, les circuits actuels sont plus petits et contiennent davantage de mémoire, mais relativement à la mémoire qui existait au temps d'Apollo, il est révolutionnaire et super concentré. Ce type ce mémoire est appelé mémoire "RAM" (pour "Random access memory"), ce qui signifie wqu'il est posible à la fois d'ecrire dans et lire depuis ce circuit. Mais ce type de mémoire perd son contenu lorsqu'il n'est plus alimenté. Ce type de mémoire est appelé "ROM" ("Read only memory") ou "PROM" (pour "Programmable read only memory"), et différemment du précédent, il ne peut être que lu et non écrit. Mais il a l'avantage sur le précédent de ne pas perdre son contenu lorsqu'il n'est plus alimenté. Ce type de mémoire est utilisé quand il doit contenir un programme résident qui doit toujours rester dedans, et permet à l'ordinateur de démarrer quand il est mis sous tension. Il est aussi possible d'utiliser de tels circuits si l'ordinateur doit faire une tâche donnée lorsque mis sous tension. Les PROM sont programmées à l'aide d'un dispositif spécial; un programme qui commande le programmeur de PROM est lancé, et l'utilisateur rentre son programme; le programme de commande envoie ensuite le programme de l'utilisateur au programmeur de PROM qui brûle les instructions dans la PROM, de sorte que celle-ci contienne définitivement ces instructions. La PROM programmée contiendra toujours ces instructions, que l'ordinateur soit sous tension ou non (mais elle ne peut être dynamiquement écrite, différemment d'une RAM). Il y a également des PROM spéciales appelées EPROM (pour PROM effaçables) qui peuvent être réécrites plusieurs fois, quoique non dynamiquement. De manière à réécrire une EPROM, son contenu doit d'abord être effacé: pour ce faire, l'EPROM a une sorte de petite "fenêtre" qui peut être traversée par des rayons UV et qui permet aux rayons UV d'effacer le contenu de l'EPROM. Lorsqu'une EPROM doit être reprogrammée, elle est mise dans un appareil spécial qui envoie des rayons UV à travers la fenêtre de l'EPROM; après quelque temps d'exposition, le contenu de l'EPROM est effacé, et elle peut être programmée à nouveau de la même manière qu'une PROM ordinaire avec le programmeur de PROM. Bien sûr, ce n'est pas aussi rapide que l'écriture dans une RAM, qui est immédiate, mais cela permet de réutiliser plusieurs fois l'EPROM différemment d'une PROM ordinaire, tandis que l'EPROM peut conserver son programme lorsqu'elle n'est pas alimentée, ce qui n'est pas le cas d'une RAM. Une EPROM est donc plus économique d'une PROM ordinaire lorsqu'elle doit être modifiée plusieurs fois. Dans les années 50, 60, et 70 (au moins au début des années 70), les circuits intégrés n'existaient pas encore. Les ordinateurs étaient de grosses machines qui n'étaient pas accessibles aux gens ordinaires, et que seulement les grosses industries pouvaient s'offrir. La mémoire de ces ordinateurs consistaient en matrices de tores de ferrites; chaque tore représentait un bit de mémoire; cela vous donne une idée du nombre de tels tores qu'il fallait pour avoir une quantité confortable de mémoire (quoique ces ordinateurs n'avaient pas autant de mémoire que les ordinateurs actuels). En ce temps il n'y avait pas de mémoire morte qui gardait l'information lorsqu'elle n'était pas alimentée, car le besoin n'existait pas. Lorsqu'un ordinateur était démarré, le système de fonctionnement était d'abord lu depuis des bandes magnétiques, et mémorisé dans la mémoire à tores qui lui était réservée. Puis les utilisateurs donnaient leurs programmes sur des cartes perforées (une instruction par carte, ce qui signifie que les programmes avaient autant de cartes que d'instructions); et l'opérateur introduisait les paquets de cartes perforées dans un lecteur spécial qui les décodait et les envoyait au processeur qui les enregistrait dans la mémoire à tores. Ces programmes utilisaient des données qui étaient également mémorisées et modifiées dans la mémoire à tores. Les avions auraient pu avoir besoin de mémoire morte pour l'ordinateur si les ordinateurs embarqués existaient en ce temps, mais les ordinateurs n'étaient pas encore assez compacts pour être embarqués à bord d'avions; alors les avions utilisaient des calculateurs analogiques qui étaient adéquats pour guider les avions de ce temps, même s'ils n'auraient pas pu être utilisés pour gérer votre budget ou jouer à des jeux vidéos. Alors, comment est-ce que la mémoire à tores fonctionnait? Les tores étaient placés à l'intersection de lignes et de colonnes d'une matrice de fils; il y avait deux fils perpendiculaires traversant chaque tore. Le champ magnétique du tore pouvait être modifié si chacun des fils le traversant était parcouru par un demi-courant, car la somme des deux demi-courants faisait un courant complet qui permettait la modification du champ magnétique du tore. D'un autre côté, si seulement un fil est alimenté avec un demi-courant et pas l'autre, ce demi-courant tout seul n'est pas assez pour changer le champ magnétique du tore. Sur le schéma qui est montré, seul le tore au centre est traversé par deux fils parcourus par un demi-courant, et c'est le seul qui aura son champ magnétique modifié. Les autres tores n'ont qu'un seul fil parcouru par un demi-courant et l'autre fil n'est pas parcouru par un courant, de sorte que leur champ magnétique ne sera pas modifié. Ce processus permet de cibler spécifiquement le tore qui doit être modifié (ou lu). Lorsque les deux fils se croisant sont parcourus par un courant négatif, le tore de ferrite est polarisé négativement, et inversement, lorsque les deux fils se croisant sont parcourus par un courant positif, le tore de ferrite est polarisé positivement. Le fait que le tore de ferrite soit polarisé négativement correspond à un bit mis à zéro, et le fait qu'il soit polarité positivement correspond à un bit mis à un. Lorsque le tore est déjà polarisé négativement, et des courants négatifs parcourent les fils qui se croisent, le champ magnétique du tore demeure inchangé; un fil de détection traversant le tore ne détecte alors rien; l'ordinateur sait alors qu'un zéro était mémorisé sur ce tore. D'un autre côté, lorsque le tore est couramment polarisé positivement, et que des courants négatifs sont envoyés dans les fils qui se croisent, le champ magnétique du tore change, et ce changement crée une courte impulsion dans le fil de détection; quoique cette impulsion soit courte, l'électronique est assez rapide pour la détecter; c'est la détection de cette impulsion qui dit que le tore de ferrite était polarisé positivement avant que les courants ne soient envoyés dans les fils; l'ordinateur sait alors qu'un bit à un était mémorisé dans ce tore. Le problème de la lecture est qu'elle est toujours faite par envoi de courants négatifs dans les fils, et le tore sera donc toujours polarisé négativement après la lecture, même s'il était polarisé positivement avant celle-ci; cela signifie que, si une impulsion a été détectée dans le fil de détection, des courants positifs doivent à nouveau être envoyés dans les fils pour faire retourner le tore à son état précédent (sinon, la fois suivante, un 0 serait lu sur le tore à la place d'un 1). Cela peut sembler un peu compliqué expliqué de cette manière, mais en fait ce processus est très rapide, et permet de lire la mémoire à une vitesse assez rapide. Les tores sont donc insérés dans une matrice de fils, et ces fils sont commandés avec des circuits dont le schéma est représenté sur la droite; ce circuit peut envoyer soit un courant négatif (pour lire les tores) ou un courant positif (pour reprogrammer les 1 des tores qui ont été détectés avec un champ positif); le courant négatif ou positif sera seulement envoyé si un signal de validation l'autorise; ce signal de validation dépend de l'adresse mémoire courante qui doit être lue ou réécrite. Vous voyez donc que le principe de la mémoire à tores repose sur un changement dynamique du champ magnétique. Lorsque la mémoire à tores n'est pas alimentée, elle est toujours déprogrammée et ne peut pas retenir d'information; lorsqu'elle est alimentée, les tores doivent d'avord être initialement polarisés positivement ou négativement en envoyant soit un courant positif ou un courant négatif dans les fils qui se croisent, suivant que les tores doivent mémoriser un 1 ou un 0. Et lorsqu'une donnée mémoire doit être modifiée, les fils traversant les tores correspondants aux 1 de cette donnée doivent être parcourus par un courant positif (à moins d'être déja polarisés positivement), tandis que les fils traversant les tores correspondants aux 0 de cette donnée doivent être parcourus par un courant négatif (à moins d'être déjà polarisés négativement). Dans la mémoire à tores normale, vous voyez que les fils d'activations qui passent à traverts les tores ont un diamètre assez important relativement au tore. Ils doivent en effet pouvoir transporter un courant suffisant pour changer the champ magnétique du tore, et, s'ils étaient trop fins, il ne pourraient supporter ce courant. Dans l'article de Wikipedia, ils disent que chaque demi-courant était compris entre 0,4 et 0,8 ampères (deux demi-courants sont nécessaires pour changer le champ magnétique du tore, un ne suffit pas); si un fil unique doit changer le champ magnétique du tore, ce courant doit être doublé; il serait alors compris entre 0,8 et 1,6 ampère. En ce qui converne les fils de détection, ils peuvent être plus fins, car l'impulsion qu'ils reçoivent est relativement faible. Alors, comment la mémoire à cordes de tores d'Apollo fonctionnait elle? Ils faisaient passer les fils de détection à travers les tores ou les faisait contourner les tores; quand un fil de détection passait à travers un tore, il était supposé représenter un 1, et quand il le contournait, il était sensé représenter un 0. Jusqu'à 64 fils de détection pouvaient passer à travers un tore! J'ai trouvé une documentation sur le site de la NASA expliquant comment la mémoire à cordes de tores (core rope memory) et la mémoire effaçable aussi fonctionnaient. D'abord je dois donner quelque explications à propos de la diode et du transistor, car je me reférerai à ces explications dans ce qui suit. Une diode est un composant electronique qui laisse passer le courant dans un sens et le bloque dans l'autre sens; et, dans le sens dans lequel elle laisse passer le courant, la diode se comporte comme une résistance pratiquement nulle. Un transistor est un composant plus sophistiqué qui a trois électrodes appelées la base (l'électrode de gauche), l'émetteur (l'électrode avec une flèche), et le collecteur (l'électrode du haut). La particularité du transistor est qu'une faible variation de courant entre la base et l'émetteur génére une plus grande variation de courant entre le collecteur et l'émetteur; cette particularité permet d'utiliser le transistor comme un amplificateur de signal. Un transistor peut également être utilisé pour bloquer ou autoriser un courant entre le collecteur et l'émetteur à partir d'une commande rentrée sur la base du transistor. Il y a deux types de transistors: - Dans les transistors appelés "NPN", le courant va du collecteur vers l'émetteur; ces transistors sont représentés avec la flèche de l'émetteur orientée vers l'extérieur du transistor. - Dans les transistors appelés "PNP", le courant va de l'émetteur vers le collecteur; ces transistors sont représentés avec la flèche de l'émetteur orientée vers l'intérieur du transistor. Lorsque le transistor est connecté de manière à ce que le courant aille de la base vers l'émetteur, le courant va du collecteur vers l'émetteur (ou de l'émetteur vesr le collecteur dans le case d'un PNP): le transistor est alors non bloqué. Mais, lorsque le transistor est connecté de manière à ce que le courant ne puisse aller de la base vesr l'émetteur, le courant ne peut aller du collecteur vers l'émetteur (ou vice versa dans le cas d'un PNP); le transistor est alors bloqué. Ceci est le schéma simplifié qu'ils donnent pour expliquer comment la mémoire à cordes de tores d'Apollo fonctionne. Pour tester à travers quels tores un fil de détection passe, et quels tores il contourne, il n'est pas possible d'activer plusieurs tores en même temps. En effet, si deux tores qui sont traversés par un fil de détection sont activés simultanément, la ligne de détection recevra une impulsion, mais il ne sera pas possible de dire si la ligne de détection passe à travers le premier de ces deux tores, ou bien le deuxième, ou encore tous les deux, car, que le premier tore génére une impulsion, ou que ce soit le second, ou les deux, dans tous les cas le fil de détection recevra la même impulsion (représentant un 1). D'un autre côté, si le fil de détection ne reçoit pas d'impulsion, là il peut être sûr qu'il ne passe à travers aucun de ces deux tores. La seule solution pour tester les bits sur une ligne de détection est d'activer les tores un par un (mais, lorsqu'un tore est activé, il est possible de tester toutes les lignes de détections en même temps pour ce tore). Si seul le second tore est activé, si une ligne de détection voit une impulsion, elle sait alors pour sûr qu'elle passe à travers ce tore; et si elle ne reçoit pas d'impulsion, elle sait aussi pour sûr qu'elle contourne ce tore. De même, si seul le troisième tore est activé, si une ligne de détection voit une impulsion, elle sait alors pour sûr qu'elle passe à travers ce tore; et, si elle ne voit pas d'impulsion, elle sait pour sûr qu'elle contourne ce tore. Quand les second et troisième tores sont successivement activés, la deuxième reçoit une impulsion dans les deux cas, et elle sait donc qu'elle passe à travers ces deux tores, et donc qu'elle a un 1 programmé sur ces deux tores. Alors, comment activer les tores indépendamment, de manière à ce qu'un seul soit activé à un moment donné? Le moyen le plus logique est de faire passer chaque ligne d'activation à travers un seul tore, une par tore. Il y a deux manières possibles: 1) La manière décrite sur la partie haute de la figure. Un courant d'activation (à gauche sur la figure) est d'abord envoyé dans un sens dans la ligne d'activation, changeant le champ magnétique du tore. Puis un courant de désactivation (à droite sur la figure) est envoyé en sens inverse pour remettre le champ magnétique du tore dans son état initial. Ce changement double du champ magnétique du tore génére une impulsion dans une ligne de détection passant à travers le tore (et, si la ligne de détection contourne le tore, elle ne verra pas d'impulsion). 2) La manière décrite sur la partie basse de la figure. Un courant d'activation (à gauche sur la figure) est envoyé dans un sens dans la ligne d'activation, changeant le champ magnétique du tore. Puis un courant de désactivation (à droite sur la figure) est envoyé en sens inverse, non dans la ligne d'activation, mais dans une ligne commune de désactivation qui passe à travers tous les tores, lequel remet le tore dans son état initial. Ce changement double du champ magnétique du tore génére également une impulsion dans une ligne de détection passant à travers le tore (et, si la ligne de détection contourne le tore, elle ne verra pas d'impulsion). Dans ce mode, seuls des courants d'activation sont envoyés dans les lignes d'activation, et seule la ligne commune de désactivation replace les tores dans leur état initial. Mais, curieusement, ils n'ont pas choisi ce mode naturel pour activer les tores. Les lignes qui permettent de sélectionner quel tore doit être activé ne sont pas des "lignes d'activation", mais des "lignes d'inhibition", et elles fonctionnent en sens inverse; elles ne permettent pas d'activer un tore, mais bien au contraire d'empêcher qu'il ne soit activé. Sur mes exemples, le fil du bas traversant un tore est une ligne d'inhibition, le fil central est la ligne commune d'activation/désactivation qui traverse tous les tores, et le fil du haut plus mince est un fil de détection. 1) Le processus d'activation d'un tore est décrit sur la partie supérieure de la figure. Un courant d'activation (à gauche sur la figure) est d'abord envoyé dans un sens à travers la ligne commune d'activation/Désactivation, changeant le champ magnétique du tore. Puis un courant de désactivation (à droite sur la figure) est envoyé en sens opposé à travers la même ligne commune d'activation/désactivation, remettant le tore dans son état initial. Ce double changement du champ magnétique du tore génére une impulsion dans une ligne de détection qui traverse le tore (et si elle contourne le tore, elle ne voit pas d'impulsion). 2) Dans le cas où un tore ne doit pas être activé parce qu'il n'est le tore couramment testé, le processus d'inhibition de l'activation du tore est décrit sur la partie inférieure de la figure. Le courant d'activation (à gauche sur la figure) est envoyé dans la ligne commune d'activation/désactivation, mais un courant de désactivation est envoyé en sens inverse dans la ligne d'inhibition simultanément de sorte que le courant d'activation de la ligne commune ne peut changer le champ magnétique du tore, et conséquemment il n'y a pas d'impulsion générée dans un fil de détection passant à travers ce tore (venant de ce tore). Le courant de désactivation (à droite sur la figure) est ensuite envoyé dans la ligne commune d'activation/désactivation, mais, comme le champ magnétique du tore n'a pas été changé, ce courant de désactivation n'a pas d'effet sur le tore. Donc, de manière à n'activer qu'un seul tore, aucun courant de doit être envoyé dans la ou les ligne(s) d'inhibition traversant ce tore, et, dans tous les autres tores, il doit y avoir (au moins) une ligne d'inhibition dans laquelle un courant de désactivation est envoyé en même temps que le courant d'activation dans la ligne commune. (Remarquez aussi que les courants envoyés dans les fils ne doivent pas être comparés avec les courants envoyés dans deux fils dans la mémoire à tores normale; dans la mémoire à tores, ce sont deux demi-courants qui se complémentent, et ici ce sont deux courants pleins qui se neutralisent). Donc, le concept de lignes d'inhibition semble moins évident que celui des lignes d'activation, mais il semble néanmoins fonctionner. Pourtant ce dernier concept crée de gros problèmes que nous allons voir. J'ai coloré avec différentes couleurs les quatre lignes d'inhibition qui permettent de sélectionner ou inhiber les tores. Vous pouvez voir que chacune de ces lignes d'inhibition traverse deux tores. La troisième ligne d'activation traverse les deuxième et quatrième tores. Si un courant de désactivation est envoyé dans cette ligne seulement, le courant d'activation envoyé dans la ligne commune d'activation/désactivation activera les premier et troisième tores, car seuls les deuxième et quatrième tores sont empêchés de changer leur champ magnétique. Si nous voulons que le premier tore soit le seul à être activé, alors des courants de désactivation doivent être envoyés dans les troisième et quatrième lignes d'inhibition. Remarquez que ces lignes traversent toutes deux le quatrième tore; cela signifie que deux courants de désactivation au lieu d'un seul sont envoyés à travers ce tore. Le processus de lecture des bits programmés sur les tores pour les 16 lignes de détection est décrit dans cette démonstration. Des courants de désactivation sont d'abord envoyés dans les troisième et quatrième lignes d'inhibition lorsque le courant est envoyé dans la ligne commune d'activation/désactivation de manière à ce que le premier tore soit le seul à être activé. Comme seule la première ligne de détection traverse le premier tore, mais ni la deuxième ligne de détection et ni la seizième (les autres lignes de détection ne sont pas spécifiées), seule la première ligne de détection a un 1 programmé sur ce tore alors que les autres lignes de détection ont un 0 programmé sur ce tore. Donc, pour le premier tore, nous avons la combinaison "10...0" (en commençant par la première ligne de détection). Puis un courant de désactivation est envoyé dans les seconde et quatrième lignes d'inhibition, causant l'inhibition de tous les tores sauf le deuxième, qui est le tore couramment testé. Comme seule la deuxième ligne de détection traverse le deuxième tore, elle est la seule à recevoir une impulsion. Donc, pour le deuxième tore, nous avons la combinaison "01...0". Puis un courant de désactivation est envoyé à travers la première et troisième ligne d'inhibition, causant l'inhibition de tous les tores sauf le troisième, qui le tore couramment testé. Comme les deuxième et seizième lignes de détection traversent le troisième tore, ce sont ces deux-là qui reçoivent une impulsion. Donc, pour le troisième tore, nous avons la combinaison "01...1". Puis un courant de désactivation est envoyé à travers les première et deuxième lignes d'activation, causant l'inhibition de tous les tores sauf le quatrième, qui est le tore couramment testé. Comme seule la première ligne de détection traverse le quatrième tore, c'est la seule à recevoir une impulsion. Donc, pour le quatrième tore, nous avons la combinaison "10...0". Donc, en activant successivement un tore à la fois, il est possible de lire les bits qui ont été programmés sur les fils d'activation en les faisant soit traverser les tores (pour un 1) ou les contourner (pour un 0). Avec ces 4 tores et 16 lignes d'activation, il est possible de mémoriser 4*16=64 bits. Remarquez toutefois que nous devons envoyer deux courants de désactivation à chaque étape du procesus (et qu'il y a à chaque fois un tore qui reçoit deux courants de désactivation au lieu d'un seul). Une autre solution serait de faire passer chaque ligne d'inhibition à travers tous les tores sauf un, donc à travers 3 tores sur cet exemple simplifié. . La première ligne d'inhibition traverse les deuxième, troisième et quatrième tores, mais pas le premier; donc, envoyant un courant de désactivation dans cette ligne, cela inhibe tous les tores sauf le premier. . La deuxième ligne d'inhibition traverse les premier, troisième et quatrième tores, mais pas le deuxième; donc, envoyant un courant de désactivation dans cette ligne, cela inhibe tous les tores sauf le deuxième. . La troisième ligne d'inhibition traverse les premier, deuxième et quatrième tores, mais pas le troisième; donc, envoyant un courant de désactivation dans cette ligne, cela inhibe tous les tores sauf le troisième. . La quatrième ligne d'inhibition traverse les premier, deuxième, et troisième tores, mais pas le quatrième; donc, envoyant un courant de désactivation dans cette ligne, cela inhibe tous les tores sauf le quatrième. Donc nous avons maintenant à n'envoyer qu'un seul courant de désactivation pour tester chaque tore...mais nous avons à faire passer à travers chaque tore un nombre de fils d'inhibition égal au nombre de tores moins un (3 dans notre exemple de 4 tores). En réalité, il y a 256 tores sur la carte mémoire, ce qui signifie que nous devrions faire passer 255 fils d'inhibition à travers chaque tore; ceci est strictement impossible, vu le diamètre minimal des fils d'inhibition. Nous devons donc chercher une autre solution. Une autre solution est de faire passer une seule ligne d'inhibition à travers chaque tore: . la première ligne d'inhibition traverse seulement le premier tore. . La deuxième ligne d'inhibition traverse seulement le deuxième tore. ... Donc, dans cette solution, une seule ligne d'inhibition traverse un tore, et cela résoud le nombre de lignes d'inhibition traversant un tore. Mais, lorsqu'un tore doit être activé, tous les autres tores doivent être inhibés, ce qui signifie que des courants de désactivation doivent être envoyés dans toutes les lignes d'inhibition sauf celle traversant le tore couramment testé. Même si la gestion de la mémoire est faite avec des unités séparées dont ils montrent le schéma, cela fait encore trois courants qui doivent être envoyés pour lire un tore, alors qu'un seul aurait suffi si des lignes d'activations avaient été utilisées au lieu de lignes d'inhibition. Alors, pourquoi ne pas utiliser le concept plus normal de "lignes d'activation" au lieu de "lignes d'inhibition"? Dans le concept de "lignes d'activation", seul un courant d'activation est envoyé dans une ligne d'activation, et seulement une ligne d'activation passe à travers un tore. Pas de problème de lignes multiples traversant un tore et pas de gaspillage d'énergie. Ceci montre que l'utilisation du concept de "lignes d'inhibition" pour alternativement activer les tores qui sont testés n'a pas de sens, et que le concept de "lignes d'activation" est le seul concept raisonable qui peut fonctionner. En fait, ils auraient pu activer le tore à tester de la même manière que dans une mémoire à tores conventionelle: En envoyant des demi-courants dans les lignes et colonnes d'une matrice de fils, de sorte que le tore à tester soit à l'intersection de la ligne et de la colonne dans lesquelles des demi-courants sont couramment envoyés. Mais le fait qu'ils aient illogiquement utilisé des "lignes d'inhibition" au lieu de "lignes d'activation" n'est pas le seul problème de la carte ROM. Ce schéma montre comment l'impulsion générée par les tores était lue. Il y avait des commandes pour activer la lecture des impultions générées par les tores individuellement. De manière à sélectionner la ligne de détection qui doit générer une impulsion dans la bobine de sortie (cerclée de bleu), ils utilisaient des commandes de sélection de ligne et de sélection de module; par exemple, sur ce schéma, la seule ligne de détection des quatre qui peut générer son impulsion dans la bobine est celle encadrée de vert clair, car c'est la seule connectée à la fois à une ligne sélectionnée (représentée en vert foncé) et un module sélectionné (aussi représenté en vert foncé); les trois autres, encadrées de rouge clair, ne peuvent générer leur impulsion dans la bobine, car elles sont connectées soit à une ligne non sélectionnée (représentée en rouge foncé), ot un module non sélectionné (aussi représenté en rouge foncé), ou même aux deux. Je donne quelques explications sur la manière dont l'impulsion détectée était transmise à la bobine. - J'appelle VR la tension de référence de 14 Volts. - J'appelle R la valeur des résistances - J'appelle I1 le courant qui vient de la sélection de ligne. - J'appelle I2 le courant qui passe à travers la diode d4 (qui vient de droite). - J'appelle V la tension du point commun que j'ai cerclé en rouge. Le courant qui va au point de sélection de module est égal à la somme de I1 et I2. Donc V: - Est égal à R*(I1+I2) - Est aussi égal à VR-0,7-R*I1 - Et est aussi égal à VR-0,7-R*I2 (0,7 étant la tension entre les extremités des diodes) Nous avons donc les équations: R*(I1+I2)=VR-0,7-R*I1 R*(I1+I2)=VR-0,7-R*I2 La résolution des equations donne: I2=(VR-0,7)/(3*R) Lorsque la ligne de détection génére un courant que j'appelerai i, ce courant passe aussi à travers la résistance qui est connectée au point de sélection de module. Nous avons donc maintenant: V=R*(I1+i+I2) Et les équations deviennent: R*(I1+I2+i)=VR-0,7-R*I1 R*(I1+I2+i)=VR-0,7-R*I2 La résolution de cette équation donne ce résultat: I2=(VR-0.7)/(3*R)-i/3 Donc une variation de i/3 relativement à la valeur précédente. Cela signifie que seulement un tiers de la très faible impulsion de la ligne de détection parvient à la bobine. Certains fans d'Apollo affirment qu'un courant ne peut traverser les fils de détections qui ne sont pas sélectionnés, mais, même si ce qu'ils affirment est vrai, cela fait encore 48 fils de détection qui peuvent potentiellement être traversés par un courant, et, comme le courant de détection sélectionné est divisé par 3 avant de parvenir au primaire de l'amplificateur, cela reste un courant trop faible pour pouvoir être amplifié. L'impulsion détectée dans la ligne de détection est amplifiée pour être utilisée par un circuit dont le schéma est montré ici. Nous avons vu que cette impulsion était divisée par trois par rapport à l'impulsion originelle. Nous allons maintenant voir que cette faible impulsion était même incorrectement amplifiée. Cet amplificateur utilise deux paires de transistors; cet assemblage spécial est appelé un "push-pull"; cela signifie que la première paire de transistors couplés (cerclé de vert) amplifie la partie positive de l'impulsion (colorée de vert), et la deuxième paire de transistors couplés (cerclée de bleu) amplifie l'autre partie de l'impulsion (colorée de bleu). Je montre ici un amplificateur simple fait avec un transistor. Le signal à amplifier est envoyé sur la base du transistor (la connection qui au centre du transistor), et le signal amplifié est obtenu sur le collecteur du transistor. Sur la première paire du push-pull (transistors cerclés de vert), le collecteur du premier transistor de la paire est connecté sur la base du second transistor; c'est la connection que j'ai tracée en rouge. Mais, sur la seconde paire du push-pull (transistors cerclés de bleu), le collecteur du premier transistor devrait également être connectée à la base du second transistor...mais ce n'est pas le cas, la connection entre le collecteur du premier transistor bleuté et la base de second transistor bleuté est manquante; j'ai cerclé l'endroit où la connexion manquante devrait être visible. Comme il n'y a pas de connexion entre les deux transistors de la seconde paire du push-pull, cela signifie que le deuxième partie de l'impulsion ne peut être amplifiée. Cette omission est clairement prévue comme un indice de la fraude. La connexion manquante entre la base et le collecteur n'est certainement pas accidentelle, car cette erreur existe sur deux schémas différents, un sur un document daté de 1966, et l'autre sur un document daté de 1972. Dans un article publié en 1967, Hopkins montre le schéma d'un amplificateur, et, sur ce schéma, l'erreur de la connexion manquante a été corrigée; comme l'article d'Hopkins a été publié entre les dates dex deux documents erronnés, cela montre que la décision d'ajouter ou retirer la connexion sur le schéma, qui a été evoquée par certains fans d'Apollo, ne tient pas. Hopkins a corrigé cette erreur pour attirer l'attention, pour montrer que quelque chose était anormal. Toutefois, Hopkins a laissé l'erreur de transistor de sortie incorrectement monté. A propos du transistor incorrectement monté, j'ai d'abord pensé que le strobe contrôlant la sortie était prévu comme une anomalie. Cela aurait été vrai sur la carte prototype, qui avait jusqu'à 64 fils de détection passant à travers les tores. En effet, comme il y a 16 bits simultanément lus, cela ferait 64/16=4 fils de détection par bit. Comme la sélection de ligne de détection permettait de sélectionner une parmi quatre lignes de détection, cela signifie que la ligne de détection sélectionnée représentait un bit du mot de 16 bits à lire. Et le diagramme pour lire un bit du mot de 16 bits à lire aurait ressemblé à ceci. La sélection de ligne de détection aurait sélectionné une des quatre lignes de détection du bit, l'amplificateur l'aurait amplifié, et la sortie de l'amplificateur aurait directement été un bit du mot. Donc, pour la carte prototype, le strobe aurait effectivement été inutile, et sa présence une anomalie. Mais, dans les modules de mémoire finaux, ce n'était pas 64, mais 192 fils qui pouvaient passer à travers un tore, trois fois plus que pour la carte prototype. Cela ferait 192/16=12 lignes de détection pour un bit. Cela signifie que ce que la sélection de ligne de détection sélectionnait ne représentait pas un bit, mais une possibilité sur trois pour le bit. Pour que la sélection de ligne de détection sélectionne directement une ligne de détection correspondant à un bit, elle aurait du sélectionner une parmi 12 lignes de détection. De plus, comme je l'ai précédemment demontré, la sélection de ligne de détection réduisait le courant de ligne de détection sélectionnée à un tiers avant qu'elle ne parvienne à l'amplificateur. Pour le module de mémoire final, le diagramme de l'acquisition d'un bit du mot de 16 bits aurait ressemblé à ceci. Il y aurait eu trois modules de sélection de ligne de détection; chacun de ces modules de sélection de ligne de détection aurait sélectionné l'une des 4 lignes de détection; chaque sortie de module de sélection serait rentrée dans un amplificateur qui l'aurait amplifiée, mais seule une sortie d'amplificateur aurait été prise en compte pour représenter le bit final, et les sorties des deux autres amplifcateurs ignorées, quoiqu'elles amplifiaient aussi une ligne de détection sélectionnée. Donc, pour le module de mémoire final, le strobe avait finalement un sens; il permettait de spécifier si cette sortie d'amplificateur devait être prise en compte pour représenter le bit lu, ou ignorée. Mais, si le strobe n'est finalement pas une anomalie, le transistor de sortie reste incorrectement connecté. Il est en fait monté à l'envers. Lorsqu'un transistor NPN (flèche de l'émetteur orientée vers l'extérieur) est utilisé pour valider ou invalider un signal en contrôlant sa base, son émetteur est connecté à une référence stable, généralement la masse; ici, ce n'est pas le cas, car l'émetteur est connecté à la sortie de l'étage amplificateur dont le niveau change lorsqu'il amplifie une impulsion. Et, lorsque la base du transistor est mise à la masse, et que l'étage amplificateur n'amplifie pas une impulsion, elle aurait une tension négative relativement à l'émetteur connecté au 14V, et ce n'est pas bon pour le transistor. Ceci est la manière dont le transistor de sortie devrait avoir été connecté, avec son émetteur connecté à la masse. Lorsque la base du transistor est activée, le transistor de sortie conduit, forçant le collecteur à la masse, et la sortie finale de l'amplificateur ne suivrait alors pas la sortie de l'étage amplificateur, ce qui signifie qu'il ne serait pas sélectionné pour fournir le bit. Et, lorsque la base serait mise à la masse, le collecteur de transistor suivrait alors la sortie de l'étage amplificateur, ce qui signifie que l'amplificateur serait sélectionné pour fournir le bit. Ce schéma simplifié montre comment les trois amplificateurs seraient connectés, de sorte que seule la sortie de l'un d'eux serait sélectionnée pour fournir le bit. Les sorties des amplificateurs seraient dirigées vers une porte NOR; une porte NOR sort un 1 lorsque toutes ses entrées sont à 0, et un 0 sinon. Pour deux des amplificateurs, ceux qui ne sont pas sélectionnés, les strobes seraient activés, ce qui forcerait leurs sorties à 0, et, pour le troisième, celui qui est sélectionné, le strobe serait mis à la masse, permettant sa sortie de suivre la sortie de l'étage amplificateur; lorsqu'il n'y a pas d'impulsion, cette sortie serait à 1, forçant la sortie du bit à 0. Et, lorsqu'une impulsion arriverait, la sortie de l'étage amplificateur serait tirée vers le bas, et la sortie de l'amplificateur deviendrait 0, ce qui forcerait le bit de sortie à 1. Donc, si la connexion manquante entre la base et le connecteur dans l'étage amplificateur est restaurée, et si le transistor de sortie est connecté correctement, est-ce que cela signifie que cet amplificateur marcherait correctement? En fait il y a encore un autre problème, quoiqu'il soit moins visible. Ceci est le schéma de la sélection d'une ligne de détection, et son amplification, dans le brevet d'une mémoire d'imprimante, qui mémorise la matrice de points pour un caractère à imprimer. Les tores, qui représentent les lignes de la matrice, sont activés successivement, et les lignes de détection, représentant les colonnes de la matrice de points, sont successivement sélectionnés, et amplifiés pour imprimer un point du caractère. A propos de cet amplificateur, le brevet dit qu'il ne fait pas qu'amplifier l'impulsion, mais qu'il l'étire également. Un élongateur d'impulsion est un dispositif qui permet de rendre une impulsion plus longue, de manière à l'exploiter plus aisément, et laisser le temps de la lire. Maintenant regardez bien: La partie que j'ai encadrée de rouge sur l'amplificateur de bit de l'imprimante est appelée un circuit RC (avec une résistance et un condensateur) et elle permet de convertir l'impulsion arrivant sur le secondaire du transformateur en un courant permanent temporaire, qui peut alors être lu par la logique de lecture. Après la lecture du bit, l'état de l'entrée que j'ai cerclée en bleu était changé, de manière à décharger le condensateur, et permettre la lecture du bit suivant. Dans l'amplificateur de bit de l'AGC, ce circuit est absent, ce qui signifie que l'impulsion n'est pas mémorisée sur le secondaire du transformateur, et tout ce que le transformateur fait est de transmettre l'impumsion à l'amplificateur sans la mémoriser, et, comme tel, il est inutile. Maintenant, pouquoi l'impulsion aurait-elle besoin d'être allongée? Pour que l'interface de bit acquière correctement le bit à partir de l'impulsion de détection, il y a deux conditions: 1) Que l'impulsion soit déjà activée au moment de la lecture. 2) Que l'impulsion soit encore activée au moment de la lecture. Si le bit était acquis exactement au même moment où le tore est activé, il ne serait pas acquis correctement, car l'impulsion ne serait pas encore présente. C'est pourquoi le processus de la lecture du bit se fait en trois étapes séquencées temporellement: 1) Activation du tore. 2) Lecture de l'impulsion 3) Reset. Toutefois, il n'y a pas de garantie que l'impulsion soit encore active lorsque le bit est acquis à la seconde étape, auquel cas il serait lu comme un 0 alors que l'impulsion s'est bien produite. C'est pourquoi l'impulsion est allongée par l'amplificateur, de sorte que l'impulsion amplifiée soit sûre d'être présente lorsqu'elle est acquise à la seconde étape. Le reset, à la troisième étape, coupe l'impulsion allongée en plus de réinitialiser le tore. Donc, comment est-ce que l'interface aurait fonctionné, en supposant que tous les défauts que j'ai cités lui aient permis de fonctionner? Il y a 12 lignes possibles de détection pour le bit, mais, pour une adresse donnée, seule une de ces lignes de détection doit être prise en compte. Supposons que la première doive être prise en compte pour sortir le bit correspondant. Le premier module de sélection de ligne de détection doit sélectionner la première ligne de détection; comme les lignes de sélection sont rentrées dans les trois modules de sélection, les deux autres modules de sélection sélectionnent également leur première ligne de détection, mais cela n'a pas d'importance en fait, car leurs sorties amplifiées ne seront pas prises en compte. Les strobes sont programmés de sorte que seule la sortie du premier amplificateur est prise en compte; finalement, le bit de sortie correspond à la première des 12 lignes de détection associées au bit. Supposons à présent que c'est la deuxième des 12 lignes de détection associées au bit qui doive représenter le bit. Le premier module de sélection de ligne de détection doit maintenant sélectionner sa deuxième entrée, et les strobes sont encore programmés pour que la sortie du premier amplifcateur soit prise en compte pour sortir le bit; finalement, le bit de sortie correspond à la deuxième des 12 lignes de détection associées au bit. Supposons à présent que c'est la cinquième des 12 lignes de détection associées au bit qui doive représenter le bit. Le deuxième module de sélection de ligne de détection doit sélectionner sa première entrée, et les strobes doivent être programmés pour que la sortie du deuxième amplificateur soit prise en compte pour sortir le bit; finalement, le bit de sortie correspond à la cinquième des 12 lignes de détection associées au bit. Supposons à présent que c'est la sixième des 12 lignes de détection associées au bit qui doive représenter le bit. Le deuxième module de sélection de ligne de détection doit sélectionner sa deuxième entrée, et les strobes doivent être programmés pour que la sortie du deuxième amplificateur soit prise en compte pour sortir le bit; finalement, le bit de sortie correspond à la sixième des 12 lignes de détection associées au bit. Je ne pense pas avoir à donner plus d'exemples: La sélection dune ligne de détection est faite en faisant une double sélection; En sélectionnant une ligne de détection, et en sélectionnant une sortie d'amplificateur. Mais, est-ce la meilleure manière pour que l'interface de bit fonctionne (en ignorant les défauts de l'amplificateur). J'ai seulement représenté deux commandes pour contrôler le bloc de détection de ligne de détection, car il y a quatre combinaisons possibles pour sélectionner une ligne de détection sur quatre. Cela signifie que chaque entrée est rentrée deux fois pour contrôler l'interface de sélection; un fois non inversée, et une fois inversée. Maintenant, il serait possible de contrôler l'interface de sélection de ligne de détection avec quatre commandes indépendantes. Cela permettrait de sélectionner plusieurs lignes de détection en même temps, ce qui ne présente pas le moindre intérêt, mais cela permettrait également de n'en sélectionner aucune, ce qui veut dire qu'aucun courant n'irait de l'interface de sélection de ligne de détection à l'amplificateur correspondant, et c'est plus intéressant d'un autre côté. Cela pourrait être intéressant, car il n'y a pas de raison qu'un courant circule d'une ligne de détection, et soit amplifié, si la sortie de l'amplificateur n'est pas prise en compte pour la génération du bit. Mais, dans ce cas, cela signifierait que les strobes de commande ne sont pas nécessaires. En effet, puisque les amplificateurs correspondants ne reçoivent pas d'impulsion, leurs sorties resteront à 1, ce qui signifie que les sorties des amplificateurs peuvent être directement connectés à une porte NAND, sans être contrôlées par un strobe. L'amplificateur qui reçoit une impulsion, l'amplifiera, et sortira un 0, ce qui forcera la sortie de la porte NAND à 1. Et, si la ligne de détection ne reçoit pas d'impulsion (i.e. ne passe pas à travers le tore activé), l'amplificateur correspondant sortira un 1, ce qui générera un 0 sur la sortie de la porte NAND, puisque les sorties des autres amplificateurs restent à 1, comme ils ne reçoivent pas d'impulsion, la sortie de leur interface de sélection de ligne de détection étant désactivée. Pour résumer, cela signifie que, si les interfaces de sélection de ligne de détection pouvaient être contrôlés pour ne sélectionner aucune ligne de détection, le strobe qui contrôle la sortie des amplificateur deviendrait inutile, et l'amplificateur pourrait être simplifié comme je le montre. Mais le strobe qui contrôle la sortie de l'amplifcateur est bien là, et sa présence prouve que les ingénieurs avaient exclu la possibilité que les interfaces de sélection de ligne de sélection puissent être contrôlés pour ne pas sélectionner de ligne de détection du tout. Considérons à présent la sélection et amplification des lignes de détection de l'interface de la mémoire d'imprimante (et nous pouvons supposer qu'il a fonctionné, il n'est pas allé sur la lune, il n'avait pas de raison de tricher). Regardez comment la sélection était faite: les lignes de commande de sélection (C1à C5) rentraient au milieu de ponts de résistances, et les lignes de détection arrivaient sur les extrêmités de des ponts; elles étaient connectées au primaire d'un transformateur à travers des diodes; une ligne de détection était sélectionnée en activant sa ligne de commande, tandis que toutes les autres lignes de commande étaient mises à la masse; seule la ligne de détection dont la ligne de commande était activée avait un courant la parcourant, pourvu qu'elle passe à travers le tore couramment activé, et c'est son courant qui passait à travers le primaire du transformateur, sans subir de réduction, et amplifié et allongé par l'amplificateur qui suit. Cet interface d'imprimante montre comment la sélection des lignes de détection aurait dû être faite: Il aurait dû y avoir un transformateur unique, et autant de ponts de résistances que de lignes de détection associés au bit (12), autant de lignes de commande que de lignes de détection à sélectionner; seule une ligne de commande aurait été activée à la fois, permettant à un courant de traverser sa ligne de détection lorsqu'elle passait à travers le tore activé, et le courant de la ligne de détection sélectionnée aurait parcouru le primaire du transformateur sans réduction; les 11 autres lignes de détection n'auraient pas eu un courant les traversant, car leurs lignes de commande seraient mises à la masse; remarquez le condensateur qui est connecté sur le secondaire du transformateur, qui permet de maintenir l'impulsion après qu'elle ait disparu sur le primaire, et qui laisse le temps de la lire; ce condensateur manque sur la mémoire d'Apollo. Par exemple, si c'est la première ligne de détection qui doit être lue pour le bit, seule la première ligne de commande serait activée, et toutes les autres mises à la masse; le courant de la première ligne de détection irait dans le transformateur, entiérement, sans réduction, et serait correctement amplifié et allongé par l'amplificateur unique du bit, et l'unique amplificateur pour le bit aurait sorti un bit mémorisé, sans qu'un strobe soit nécessaire. Et, de même, si c'est la seconde ligne de détection qui doit être lue pour le bit, seule la seconde ligne de commande serait activée, et toutes les autres mises à la masse; le courant de la deuxième ligne de détection circulerait entièrement à travers le transformateur, et serait correctement amplifié et allongé par l'amplificateur unique du bit. Donc, ceci est définitivement la manière dont l'interface du bit aurait du fonctionner, sous réserve que nous gardions la logique d'utiliser des fils de détection pour programmer les bits. D'un côté, nous avons trois modules de sélection de ligne de détection, réduisant à un tiers le courant de la ligne sélectionnée, et permettant à trois courants de circuler à travers trois lignes de détection sélectionnées, trois amplificateurs, consommant du courant, amplifiant incorrectement l'impulsion, ne l'allongeant pas, et incorrectement contrôlés, et, d'un autre côté, nous avons une ligne de détection unique sélectionnée, qui est la seule dans laquelle un courant circule, qui n'est pas réduite avant d'arriver à l'amplificateur, qui est correctement amplifiée et allongée par un amplificateur unique, et qui ne nécessite pas de contrôle sur l'amplificateur pour générer le bit. Il n'est pas utile de vous dire quel est le meilleur des deux systèmes; si vous n'êtes pas complètement stupide, vous devez être capable de le deviner tout seul! Et la sélection d'une ligne de détection pour le bit ne requiert pas plus de bits du bus d'adresse pour l'interface amélioré que pour l'interface de l'AGC. En effet, la sélection d'une ligne de détection parmi 12 possibles pour l'interface amélioré serait faite avec un interface appelé "Décodeur 1 parmi N"; c'est un circuit qui accepte une combinaison de n entrées binaires et sort 2^n sorties (deux n fois multiplié par lui-même), dont seulement une est activée à la fois, laquelle correspond à la combinaison binaire des entrées; l'exemple affiché montre comment valider une parmi les 4 sorties suivant la combinaison binaire des deux entrées. Plutôt que de montrer un schéma complet pour un décodeur ayant 4 entrées et 16 sorties, qui serait un peu trop surchargé pour être lisible, je montre ici une animation qui montre comment chaque porte du décodeur serait connectée aux quatre entrées. Ce décodeur permettrait de sélectionner une des 12 commandes de l'interface amélioré pour le bit à partir d'une adresse de 4 bits. Il n'est pas nécessaire de répéter ce décodeur pour les 16 bits, le même décodeur pourrait être utilisé pour tous les interfaces de bit. Et, concernant l'interface de bit de l'AGC, une adresse de 2 bits serait nécessaire pour sélectionner une ligne de détection parmi 4, et une autre adr'esse de 2 bits pour sélectionner une parmi les trois sorties des amplificateurs, ce qui ferait aussi une adresse de 4 bits en tout. Cela signifie que l'interface amélioré de bit n'a pas besoin de plus de bits pour être contrôlé à partir du bus d'adresse que l'interface de bit de l'AGC. De plus, les lignes d'inhibition ne sont même pas utilisées correctement; à la manière dont elles étaient utilisées, il y avait deux courants d'inhibition passant à travers un tore. Si elles avaient été utilisées correctement, alors seule une ligne d'inhibition serait passée à travers chaque tore, et aurait été activée pour inhiber ce tore, comme c'est fait dans l'interface de mémoire d'imprimante qui marche réellement. En plus du fait que le processus d'inhibition est incorrect (à cause de deux lignes d'inhibition activées passant dans un tore), le fait d'utiliser les lignes d'inhibition comme c'était fait dans la mémoire d'Apollo implique également que les fils d'inhibition devaient également être "tissés" pour alternativement passer à travers les tores ou les contourner. Et nous allons voir que cela complique le test du tissage des fils. Considérons le fil de détection 2, que j'indique avec une flèche bleue. Ce fil contourne le premier tore (quand il est correctement tissé), parce qu'un 0 est programmé pour ce fil de détection sur le premier tore Donc, lorsqu'un courant est envoyé dans la ligne d'activation commune (fil coloré en vert), et des contre-courants dans les troisième et quatrième lignes d'inhibition, comme ces lignes d'inhibition passent à travers tous les tores à part le premier, elles empècheront tous les tores d'être activés, sauf le premier tore qui sera donc le seul à être activé. Si le fil de détection 2 contourne le premier tore, comme il le devrait, il ne montrera alors pas de courant, montrant qu'un 0 est programmé pour cette ligne de détection sur le premier tore; la non détection de courant dans le fil de détection 2 montrera qu'il a été correctement tissé. A présent, considérons cette situation. Le fil de détection 2 (indiqué avec une flèche bleue), au lieu de contourner le premier tore, passe à travers celui-ci, parce qu'une gentille main tisseuse a fait une erreur. Le résultat est que, lorsque le premier tore est activé (en envoyant un courant dans la ligne commune et des contre-courants dans les troisième et quatrième lignes d'inhibition), il montrera un courant, alors qu'il ne le devrait pas. Les ingénieurs en déduiront alors qu'une gentille main tisseuse a fait passer ce fil de détection à travers le premier tore, alors qu'il aurait du le contourner, et referont tisser le fil de détection défectueux. Maintenant, considérons cette situation à la place. Le fil de détection 2 (indiquée avec une flèche bleue) a été correctement tissé, et contourne le premier tore, comme il le devrait. Mais la troisième ligne d'inhibition (pointée par une flèche rose), au lieu de passer à travers le second tore, le contourne. Le résultat est que, lorsqu'un courant est envoyé dans la ligne commune, et des contre-courants dans les troisième et quatrième lignes d'inhibition, il n'y aura pas de ligne d'inhibition activée passant à travers le second tore, et donc le second tore sera activé en même temps que le premier tore, alors qu'il ne le devrait pas. Comme le fil de détection 2 passe à travers le second tore, et que le second tore est indûment activé, le fil de détection 2 sera activé, non parce que le premier tore est activé, mais parce que le second l'est. Si les ingénieurs pensent que les lignes d'inhibition sont correctement tissées, ils en déduiront que le fil de détection 2 a été incorrectement tissé, qu'il passe à travers le premier tore quand il devrait le contourner, et le feront retisser, alors qu'il était correctement tissé, car il contourne effectivement le premier tore, comme il le doit. Le retissage de ce fil de détection ne résoudra donc pas le problème. Donc, est-ce que cela signifie que, si l'interface du bit avait ressemblé à ceci, il aurait pu fonctionner normalement, et que c'est la manière dont il aurait du être conçu? Il y a toutefois une grosse différence avec la mémoire d'imprimante que nous avons vue: Dans cette mémoire d'imprimante, la sélection est faite entre toutes les lignes de détection passant à travers les tores; cela signifie qu'il n'y aura jamais plus d'une ligne de détection à travers laquelle un courant circule. Dans cet interface de bit, il y a seulement un courant circulant dans la ligne de détection sélectionnée, mais il y a 16 bits à lire pour le mot à lire, ce qui signifie qu'il y a 15 autres lignes de détection dans lesquelles un courant peut circuler, qui correspondent aux 15 autres bits. Donc, si cet interface est utilisé, cela signifie qu'il peut y avoir 16 courants circulant dans des lignes de détection sélectionnées (dans l'interface original de l'AGC, c'est 48), et 16, c'est trop, cela implique une réduction significative du courant circulant dans chacune de ces lignes de détection (sous la condition qu'elles passent toutes à travers du tore activé, ce qui peut arriver). Cela signifie que, quoique cet interface soit bien plus performant que celui de l'AGC, il présente encore un sérieux inconvénient à fonctionner correctement. C'est pourquoi les mémoires à cordes de tores des autres ordinateurs, comme celle de 'UNIVAC (à droite sur la vue stéréoscopique), quoiqu'elles montrent une similitude avec la mémoire de l'AGC, fonctionnent de manière complétement différente. En effet, dans ces mémoires, les lignes, qui passent à travers ou contournent les tores, ne sont pas des lignes de détection, mais des lignes de commande à la place, et cela change tout. Dans ces mémoires, les tores ont un fil de détection unique. En effet, le texte associé avec cette figure, dans le brevet d'une memoire à cordes de tores, est comme suit: "the magnetic thin-film wires 1 are used as information lines (which function doubly as digit lines and sense lines), and the conductor wires 2 are used as word drive lines." Soit: "Les pistes magnétiques 1 sont utilisées commes lignes d'informations (qui fonctionnent à la fois comme lignes de détection et de digits), et les fils conducteurs 2 sont utilisées comme lignes de commande". Dans la mémoire de l'AGC, seul un tore est activé à la fois, et des courants peuvent passer dans plusieurs lignes de détection, et, dans les mémoires à cordes de tore qui marchent vraiment, seule une ligne de commande est activée à la fois, et plusieurs tores peuvent être activés à la fois par cette ligne de commande, générant un courant dans chacune de leur unique ligne de détection. Au lieu d'être tous lus sur le même tore, les bits sont lus sur plusieurs tores. Avec le même nombre de lignes de commande que de lignes de détection, et le même nombre de tores, ces mémoires peuvent mémoriser la même quantité d'information, car, de même qu'une ligne de détection programme un bit en passant ou contournant un tore, une ligne de commande programme également un bit en passant à travers ou contournant un tore. Donc, si la mémoire de l'AGC fonctionnait suivant le même principe que les mémoires à cordes de tores des autres ordinateurs, qui sont prouvées fonctionner, le schema serait changé comme je le montre ici; Les lignes passant à travers ou contournant les tores serait appelées drive lines (lignes de commande), et non sense lines (lignes de détection), et il n'y aurait pas de lignes d'inhibition, ce qui signifie que ces dernières n'auraient pas à être tissées dans les tores, contrairement à la mémoire originale de l'AGC. J'explique ici comment cela fonctionnerait: La première ligne de commande passe à travers les premier et quatrième tores, ce qui signifie que, lorsqu'elle est activée, les premier et quatrième tores seraient activés, et leurs lignes de détection détecteraient un courant, ce qui correspondrait au mot de 4 bits 1001. La seconde ligne de commande passe à travers les deuxième et troisième tores, ce qui signifie que, lorqu'elle est activée, les deuxième et troisième tores seraient activés, et leurs lignes de détection détecteraient un courant, ce qui correspondrait au mot de 4 bits 0110. Enfin, la troisième ligne de commande passe à travers le troisième tore, ce qui signifie que, lorsqu'elle est activée, le troisième tore serait activé, et leurs lignes de détection détecteraient un courant, ce qui correspondrait au mot de 4 bits 0010. Cette démonstration a été faite avec quatre tores, mais le nombre de tores pourrait être étendu à 16 pour lire un mot de 16 bits. Vous voyez donc que cette manière de fonctionner est bien meilleure: 1) pas besoin de lignes d'inhibition. 2) seulement un courant passant dans une ligne de détection, ce qui signifie que le courant qui la parcourt serait suffisant pour être amplifié. Donc, cet interface est bien meilleur que... ...celui-ci, qui lui-même est bien meilleur que... ..celui qui a été conçu pour l'AGC. Cet interface est si mauvais, il cumule de si nombreux handicaps, qu'il n'avait pas la moindre chance de marcher, et les ingénieurs le savaient, car ils l'ont voulu très mauvais, et qu'il ne fonctionne pas. Pour en revenir à la carte prototype, Il y a également le problème du transport des fils. Nous avons 256 lignes d'inhibition plus les 64 lignes de détection, ce qui fait un total de 320 fils pour controntrôler cette carte mémoire. Les trois connecteurs que j'ai cerclés devraient pour tranporter 320 connections, ce qui fait 106.66 connections par connecteur; et, comme une connection ne peut être fractionelle, cela fait que chaque connecteur devrait avoir au poins 107 points. Le capot des connecteurs permet de voir partiellement les broches du connecteur; nous en voyons trois pour chaque connecteur; nous pouvons mesurer l'intervalle qui les sépare, et nous pouvons en déduire le nombre de points de ces connecteurs. J'ai reconstitué ici les broches d'un connecteur en dupliquant les trois broches visibles sur la longueur totale du connecteur; dans ma reconstitution, le connecteur a 19 broches; bien sûr il peut y avoir une marge d'erreur, mais nous somme très loin des 107 broches que le connecteur devrait avoir; et même s'il y a deux rangées de ces broches, voire trois, nous sommes encore loin du compte. De plus, il est difficile de croire qu'il y a 107 fils dans le groupe de fils venant à chaque connecteur! La documentation de la NASA dit qu'il était possible d'insérer 6 modules de mémoire ROM dans l'habitacle de l'ordinateur d'Apollo. Et également que chacun de ces modules avait 512 tores avec 192 lignes de détection passant ou contournant ces tores, ce qui fait une capacité de 98304 bits, et 98304/16=6,144 mots de 16 bits, ou 6K mots en court. Donc, avec 6 modules de 6K mots, nous avons une capacité totale de 6x6K=36K mots, la mémoire dont la NASA affirme que l'ordinateur d'Apollo disposait. Ceci est la vue explosée de l'ordinateur d'Apollo. Sur cette vue explosée, nous voyons le plateau du fond, appelé plateau A, dans lequel pouvaient seulement être enfichés des modules courts, ce qui exclut les modules de mémoire qui sont des modules relativement longs, et, par dessus, le plateau B sur lequel il y avait une fenêtre pour enficher les modules de mémoire, qui devaient pouvoir être facilement retirés, car il pouvait s'avérer nécessaire de les modifier (contrairement aux modules courts qui sont cablés une fois pour toutes). Ici nous voyons l'intérieur du plateau A avec les connecteurs pour les modules courts. Sur cette vue, nous voyons le plateau B au dessus du plateau A. Des modules de mémoire peuvent être insérés sur chaque côté du plateau B, mais les modules de mémoires ne peuvent être insérés sur le bas de l'ordinateur, car le bas de l'ordinateur est le plateau A, et est réservé pour les modules courts; il n'y a pas de place pour les modules de mémoire dans le plateau A. A première vue, le plateau B semble capable de contenir six modules de mémoire (trois de chaque côté). Maintenant voyons: Pour les deux modules supérieurs; nous voyons des rainures pour les insérer..., mais, pour celui du bas, nous ne voyons pas de rainure; sans rainure, le module du bas ne sera pas maintenu, et branlera. Sur cette photocomposition, j'ai ajouté la rainure manquante sur le côté droit pour le module du bas, que j'indique avec une flèche. Sur cette illustration du plateau B seul; nous voyons quatre connecteurs au fond du plateau. Quelqu'un a dit qu'il y avait déjà deux modules insérés de chaque côté du plateau... ...Mais, sur ce gros-plan, nous voyons que: 1) Ces modules ont seulement la moitié de la largeur qu'ils devraient avoir. 2) Ces modules ne touchent pas les plaques frontales. 3) Et, sur les plaques frontales, nous pouvons lire l'inscription "RETREAD" à l'envers. Sur ce gros-plan de l'illustration précédente, nous voyons deux modules de mémoire; un est déjà à moitié inséré, et l'autre n'est pas inséré. Sur celui qui n'est pas inséré; nous voyons l'inscription "RETREAD", mais normalement, pas à l'envers. Et ce n'est pas parce que ce module est lui-même placé à l'envers, car nous pouvons voir que, par plusieurs détails que j'ai cerclés, ce module n'est pas à l'envers. Ceci veut dire que, lorsqu'un module est inséré, l'inscription "RETREAD" ne devrait pas être à l'envers. Certains m'ont dit que ce que je montrais comme des manques était des ombres... Alors la zone noire que j'ai cerclée de rouge serait une ombre, et non un manque? L'ombre ne peut provenir de la barre qui est au-dessus, car nous voyons son ombre que j'ai cerclée de jaune, qui n'est même pas noire, mais grise! Cette ombre ne pourrait provenir que de la plaque frontale; mais, pour que la plaque frontale crée cette ombre, la source de lumière devrait venir de l'avant du plateau, suivant la flèche que j'ai dessinée en rouge. Mais, si la lumière avait vraiment cette direction, alors les parties que j'ai cerclées d'orange ne seraient pas ombrées, et elles le sont! Même si la lumière provenait du côté droit, ces parties ne seraient pas ombrées; pourqu'elles le soient, la lumière doit venir de l'arrière du plateau... ...Et, dans ce cas, la plaque frontale ne pourrait créer l'ombre que nous voyons! Les adeptes d'Apollo m'ont aussi dit que nous ne pouvions voir l'arête du module; ceci est seulement vrai au début du module; mais, plus loin, à l'endroit que j'indique avec une flèche jaune, cette arête est visible. Je montre ici un gros-plan de la partie que j'ai indiquée avec une flèche gauche sur la figure précédente. Nous pouvons clairement voir l'arête du module de mémoire que j'indique avec une flèche jaune. Donc, les modules qui sont déjà insérés auraient été insérés à l'envers, et n'auraient pas la largeur normale, seulement la moitié de celle-ci? Sur une vidéo, nous semblons voir six connecteurs blancs sur le fond du plateau B, ce qui montrerait que six modules de mémoire peuvent être insérés, mais ces connecteurs sont mal placés... ...Et deuxièmement, sur le côté gauche du plateau B, nous voyons seulement deux rainures pour insérer les modules de mémoire... ...Et troisièmement, nous voyons un module de mémoire devant le plateau B, et il est évident qu'il n'est pas physiquement possible d'insérer trois de ces modules sur chaque côté du plateau B; le plateau B n'est pas assez haut. Remarquez aussi qu'il n'y a pas de rainures sur la plaque centrale! Maintenant, le point principal est que les modules de mémoire de l'ordinateur avaient 512 tores et 192 lignes de détection, donnant théoriquement une capacité de mémoire de 6K mots. Voyons maintenant si ce module de mémoire avait vraiment 192 lignes de détection et 512 tores! Nous ne voyons pas bien les tores de ce module mémoire partout, mais nous les voyons assez bien sur le coin bas droit du module mémoire. Il est possible de compter les tores du modules de mémoire; il y a 8 rangées de 32 tores, ce qui fait un total de 256 tores, et non 512. Où sont les 256 autres tores? Et, si les lignes de détection sont trop fines pour être comptées directement, nous avons un moyen indirect de les compter. Chaque ligne de détection était en effet individuellement connectée a un douple diode&résistance qui permet de la sélectionner pour la lecture (ou ne pas la sélectionner); ces couples diode&résistance sont indiqués avec une flèche sur le haut du module et ils sont assez visibles pour être comptés; il y en a 96. Il devrait y en avoir 192, donc les autres couples diode&résistance doivent être sur le bas du module! Nous pouvons voir les diodes des couples; j'en ai cerclé une. Maintenant, si nous comparons quelque couples diode&résistance sur le haut du module et sur le bas du module, nous voyons qu'ils sont différents, alors qu'ils devraient être identiques! Ils sont plus longs sur le haut que sur le bas du module; pourtant ils devraient normalement avoir la même longueur! En fait, s'ils sont différents, c'est parce que les résistances que j'ai encadrées de rouge sur le haut du module manquent sur le bas du module, et, sans ces résistances, les lignes de détection connectées aux couples diode&résistance du bas du module ne peuvent être sélectionnées, et donc utilisées. Seules les 96 lignes de détection connectées aux couples diode&résistance sur le haut du module peuvent être utilisées. Quelqu'un a suggéré que les 256 autres tores et 96 autres couples diode&résistance seraient sur l'autre face du module. Concentrons-nous sur le connecteur du module. Nous voyons le connecteur entièrement, ce qui montre que le module est placé sous le connecteur; cela signifie que le module est placé sur le fond de son boîtier; il n'y a pas de place pour mettre des tores sur l'autre face du module, car une seconde couche de tores ne devrait pas être trop proche de la première couche, il devrait y avoir une séparation minimale entre les deux, et cela exclut de placer le module trop près du fond du boîtier. Et, sur les couples diode&résistance de la partie inférieure du module, nous voyons les diodes des couples; ce sont les résistances qui manquent, rendant les couples de la partie inférieure inopérants. Seules les lignes de détection sont connectées à des diodes, et non les lignes de commande. Ils n'auraient pas mis des diodes sur le compte des 96 autres lignes de détection qui n'auraient pas d'usage, ils n'auraient rien mis; placer ces diodes signifie que la partie inférieure du module était censée contenir les 96 autres couples diode&résistance, mais ces derniers ont été rendus inopérants en omettant les résistances. Il n'y a pas de couples diode&résistance sur l'autre face du module. Donc, maintenant, ce module de mémoire n'a que la motié du nombre normal de tores, et la moitié des lignes de détection qui sont utilisables...et conséquement, sa capacité mémoire tombe au quart de sa mémoire normale, donc 1,5K au lieu de 6K mots. Nous avons donc maintenant quatre modules de mémoire avec une capacité de mémoire de 1,5K mots seulement, ce qui fait une capacité totale de 6K mots; nous sommes loin de la capacité annoncée de 36K mots! Et même si l'on peut insérer six modules de mémoires, avec des modules de 1,5 k mots, cela ne fait toujours que 9K au lieu de 36K. Et la manière manuelle dont la mémoire était "tissée" n'a pas de sens non plus: Espérer que des travailleurs ne fassent pas d'erreur. Les tisseuses devaient faire passer les fils à travers les tores ou les contourner 16384 fois (pour une carte mémoire). Cela fait 16384 occasions de faire une erreur! Et s'ils avaient vraiment fait toutes les cartes mémoire pour mémoriser les 36384 mots annoncés de mémoire, cela aurait fait 589824 occasions de faire une erreur! Bien sûr, après que les tisseuses aient enfilé les bons fils dans les tores, il y avait certainement une procédure pour vérifier qu'il n'y avait pas d'erreur, mais, s'il y en avait une ou plusieurs, la carte devait être retournée à l'usine pour être corrigée; et les corrections étaient très difficiles (un fil défectueux devait être complètement enlevé pour être "tissé" à nouveau - à condition qu'il localisent le fil défectueux correctement, et ne le confondent pas avec un fil correctement tissé!). Faire des corrections dans la carte mémoire étaint donc un vrai cauchemar! Il n'y a donc absolument aucun doute que la mémoire à cordes de tores d'Apollo était une plaisanterie et non destinée à fonctionner réellement. Quand ils ont baptisé cette mémoire "LOL, cela ne voulait donc pas dire "Little Old Lady"... ..mais ce que cela veut généralement dire, soit "Laughing Out Loud". Cela signifiait clairement que cette mémoire était un gag, et qu'elle ne pouvait pas marcher. Maintenant certains affirment que l'expression "Laughing Out Lout", abrégée "LOL", a été spécialement créée pour Internet et qu'elle n'existait pas auparavant de sorte que les ingénieurs de la NASA n'auraient pu l'utiliser pour baptiser la mémoire à cordes de tores. Rien n'est plus faux: L'expression "Laugh Out Loud" est loin d'être récente. Une vielle bande dessinée "Laugh Out Loud cats" peut en témoigner; cette bande dessinée a été créée vers 1912, ce qui prouve que l'expression "Laugh Out Loud" est loin d'être récente. Et il est très probable que cette expression est encore plus ancienne. Les créateurs d'Internet n'ont pas créé l'expression "laughing out Loud", ils ont juste réactualisé une expression qui existait déjà. Ceci est le schèma simplifié de la mémoire volatile (RAM). Le pavé qui est à l'intérieur des boucles de courant représente le tableau de tores. Si aucune mémoire à cordes de tores n'a été utilisée en dehors d'Apollo (au moins de la manière dont elle existe pour Apollo), tel n'est pas le cas de la mémoire normale volatile à tores qui peut parfaitement fonctionner. Donc, si la mémoire ROM ne pouvait fonctionner, nous aurions au moins pu nous attendre à ce que la mémoire RAM fonctionne? Mais ils ont même réussi à ne pas la faire fonctionner! J'ai représenté en rouge le chemin du courant d'écriture; le courant tourne dans le sens des aiguilles d'une montre; cela le fait monter dans le pavé du tableau de tores. Et j'ai représenté en bleu le chemin du courant de lecture (la ligne de détection); le courant tourne également dans le sens des auguilles d'une montre, mais, comme la boucle de lecture est à gauche de la boucle d'écriture, cela le fait descendre dans le pavé du tableau de tores. Maintenant, ce qui est anormal est que la boucle d'écriture et la boucle de lecture ont une partie commune; c'est le même fil qui permet à la fois de changer le champ magnétique d'un fil et de détecter l'impulsion qui est générée par le changement du champ magnétique du tore. Ceci est absolument impossible; le fil qui permet de générer le changement du champ magnétique du tore, en envoyant un courant à travers celui-ci, ne peut être en même temps le fil qui détecte cette impulsion, TOTALEMENT IMPOSSIBLE! Et, encore plus absurde, le courant qui circule dans la boucle d'écriture et celui circulant dans la boucle de lecture vont en sens opposé dans leur partie commune! Vous auriez pu penser que cela était déjà assez incohérent pour satisfaire les saboteurs? On non, ils ont rajouté un grain de sel! Ceci est le schéma du circuit qui permet de lire d'impulsion de détection. Cet interface contient deux transistors (T2,T3) montés en régulateur de courant. La régulation de courant est basée sur le fait que, lorsqu'un courant parcourt une diode, cela génére une différence de tension de 0,7 volts sur ses extrêmités. Lorsqu'une impulsion arrive sur la base de T1, T1 devient activé et le courant peut passer de son collecteur à son émetteur. A cause de la double diode connectée à la base de T2, la tension sur la base de T2 est alors égale à 14-1,4 volts (2x0,7=1,4); la tension sur l'émetteur du transistor PNP T2 est égale à la tension sur sa base plus 0.7 volts, soit 14-0,7 volts; cela générerait un courant régulé de 0,7/R à travers la résistance R. Si T2 est activé, le courant peut passer de son émetteur à son collecteur, et passe aussi à travers la double diode connectée à la base de T3; la tension sur la base de T3 est alors égale à 1,4 volts (2x0,7 volts). Si le transistor T2 est activé, les tensions sur son émetteur et son collecteur devraient être égales, mais la double diode D1&D2 force la tension de l'émetteur à 13,3 volts, et la double diode D3&D4 force la tension du collecteur à 1,4 volts! Cela ne peut marcher, cet interface est aberrant. Donc, aussi incroyable que cela paraisse, ni la mémoire ROM ni la mémoire RAM d'Apollo ne pouvaient fonctionner. Elles apparaissent toutes deux comme une plaisanterie! Mais n'ayez pas d'inquiètude pour Apollo, Otto est alà pour contrôler la situation! |
Et, entre l'homme et l'ordinateur, il y avait l'unité DSKY, c'est à dire un affichage couplé avec un clavier. Vous auriez pu penser que cette unité fonctionnait correctement? FAUX ESPOIR! Ce schéma montre comment l'affichage était commandé. Il y a deux commandes pour sélectionner un relais (représenté comme une spirale): - Une commande de mot qui sélectionne le chiffre qui doit être affiché. - Et une commande de ligne qui sélectionne un relais à activer dans ce chiffre. De manière à activer un relais, les commandes de mot et de ligne doivent être activées. Lorsque la commande de ligne est activée, les transistors que j'ai cerclés en rouge sont activés par la commande de ligne. Un courant circule alors depuis les collecteurs vers les relais, que j'ai cerclés de vert; mais, de manière à ce que ce courant puisse circuler à travers les relais, il doit également circuler à travers le transistor que j'ai cerclé d'orange, lequel est activé par la commande de sélection de mot. Mais, pourquoi y a t-il deux transistors et deux relais, quand un seul suffirait? L'argument est que cela crée une redondance: Si un transistor tombe en panne et ne peut activer le relais à travers sa propre connexion, l'autre le peut encore à travers la sienne propre. Il y a donc deux transistors pour envoyer une commande d’activation de segments, de manière à ce que cela puisse encore fonctionner si un transistor tombe en panne. Mais, si le premier transistor de la paire, celui que j'ai cerclé de rouge, est coupé, il n'activera pas le relais (lorsque les commandes de mot et de ligne sont activées), mais cela ne permettra pas au transistor suivant d'activer le relais, car le transistor en panne permet également d'activer le transistor suivant. Donc, en dépit de la présence du second transistor, le relais ne sera pas activé. La redondance ne joue pas son rôle. Maintenant, si le transistor tombe en panne de court-circuit, il activera le relais de manière permanente, même si la commande de ligne n'est pas activée (mais celle de mot l'est), et cela même si le transistor suivant fonctionne correctement. Une fois de plus, la redondance ne joue pas son rôle. Et, si le second transistor de la paire, celui que j'ai cerclé de rouge, tombe en panne de court-circuit, il activera également de manière permanente le relais, même si la commande de ligne n'est pas activée, et cela même si le premier transistor fonctionne correctement. Non seulement la redondance ne joue pas son rôle, mais elle aggrave même les choses, car il y a plus de chance qu'un transistor sur deux tombe en panne de court-circuit qu'un seul. S'ils avaient voulu faire une vraie redondance, ils l'auraient faite comme je la montre ici: - Si un transistor est coupé, l'autre paire de transistors peut encore activer correctement le relais, lorsque la commande ligne est activée. - Et, si un transistor tombe en panne de court-circuit, l'autre transistor de la paire, qui fonctionne encore correctement, l'empêchera d'activer le relais de manière permanente. Nous avons maintenant une vraie redondance qui fait que, si un transistor tombe en panne (mais un seul), le relais peut encore être commandé correctement, i.e. activé seulement si la commande de ligne est activée, et non dans le cas contraire. Ici, sur le schéma, ils utilisent 5 sélections de lignes qui rentrent dans la matrice des relais pour allumer les segments du digit correspondant à la valeur à afficher. En réalité, seulement 4 sélections de ligne seraient nécessaires pour afficher toutes les valeurs possibles (10 valeurs pour un digit numérique, et 16 valeurs pour un digit hexadécimal). Donc, seulement 4 bits sont vraiment nécessaires pour l'affichage d'un digit, et aussi pour tous les digits, car c'est la sélection de mot qui détermine pour quel digit les sélections courantes de ligne s'appliquent. Et, comme il y a 24 sélections de mot à commander (pour les 21 digits et les 3 signes +/-), cela peut être fait avec une commande de 5 bits (les 5 bits sont rentrés dans une matrice de diodes qui permet de produire les 24 sélections de mot). Ce schéma montre comment l'unité DSKY était connectée. Les sélections de mot sont commandées avec 4 bits seulement, alors que 5 seraient nécessaires, et la matrice de diodes sort seulement 14 sélections de mot, alors que 24 seraient nécessaires (pour les 21 digits et les 3 signes +/-). Et il y a 11 sélections de lignes, alors que 5 seulement seraient nécessaires (En réalité, seulement 4 seraient vraiment nécessaires). Nous avons ici une incohérence complète. Et il y a d'autres problèmes dans ce qui est montré. D'abord le collecteur du transistor que j'ai cerclé de rouge n'est pas connecté à une référence positive. Donc, la matrice de relais qui suit ne pourra fonctionner correctement. Et, deuxièmement, sur l'entrée de l'inverseur de code clavier, il y a un condensateur de traversée dont nous pouvons nous étonner ce qu'il fait ici. Si l'utilisateur appuie trop rapidement sur la touche, ce condensateur pourrait faire que la touche ne serait pas vue appuyée. J'ai ajouté une connection à une référence positive sur le transistor connecté à l'entrée de la matrice de diodes de sélection de mot pour que la sélection fonctionne normalement. Mais les problèmes de connexion de l'unité DSKY ne sont pas les seuls problèmes. L'AGC utilisait un affichage electroluminescent sur un fond sombre. vos ordinateurs modernes utilisent des affichages modernes comme celui que je montre; en fait les affichages que vous utilisez couramment sont plus évolués que celui que je montre, car ils sont extra-plats, mais j'utiliserai celui-ci qui est plus démonstratif. Sur ce type d'affichage, un faisceau balaie un écran; la largeur et hauteur du balayage peuvent être ajustés, et également son intensité; conséquemment la taille et luminosité des caractères sur l'écran peuvent varier. Mais l'ordinateur d'Apollo n'utilisait pas du tout cette technologie pour son affichage. Au lieu de cela il utilisait une technologie beaucoup plus simple, qui avait l'avantage d'être plus simple à commander et plus rapide, ce qui était important vu sa faible puissance. L'affichage était consitué d'une série de "7-Segment" qui pouvaient représenter le chiffre à afficher. Cette animation montre comment un 7-Segment fonctionne: Un 7-Segment est constitué de sept segments lumineux (d'où son nom); lorsqu'un chiffre doit apparaître, les segments qui le représentent au mieux sont allumés. Il y a un circuit spécial qui réalise la conversion entre un chiffre binaire et les commandes correspondantes qui doivent être envoyées au 7-Segment pour allumer les segments qui le représentent; cette animation montre comment ce convertisseur fonctionne. Un chiffre représenté par un 7-Segment peut être allumé... ...Ou éteint... ...Mais il ne peut pas être à moitié allumé. Un segment est allumé ou éteint, mais pas à moitié allumé. Donc un 7-Segment a deux particularités qu'il est important de noter: - Sa taille est déterminée physiquement, et ne peut pas varier. - Sa luminosité est aussi unique, et ne peut pas changer (i.e. il ne peut devenir plus terne). Un affichage electroluminescent utilise toujours un fond sombre, sinon les symboles ne seuraient pas bien visibles lorsqu'ils sont allumés; les 7-segments sont faiblement visibles même lorsqu'ils ne sont pas allumés. Ceci est le programme de l'AGC qui affiche sur le DSKY. De manière à afficher sur le DSKY, il devrait écrire dans le canal 10. Et, pour écrire dans un un canal I/O, l'instruction "WRITE" doit être utilisée. Mais, dans le programme d'affichage, il n'y a d'accès à aucun canal, et en particulier au canal 10. Cela signifie que le programme n'essaie même pas d'afficher sur le DSKY. Donc, autant dans le matériel que dans le logiciel, il y a de sérieux problèmes qui font que l'AGC ne peut rien afficher sur le DSKY. |
Dans la mission Apollo 11, "Buzz Aldrin" (ou plutôt l'acteur qui se fait passer pour lui) fait une démonstration de l'AGC dans le module de commande. Tout le monde a admiré cette séquence, supposée montrer que l'AGC marchait parfaitement. Pourtant elle contient plein d'indices qu'elle est fausse. Dans cette séquence, nous voyons tous les segments électroluminescents, ou presque, devenir soudainement allumés. Le verbe 35 permet de faire le test des lampes, qui permet d'allumer temporairement tous les indicateurs lumineux, et les segments électroluminescents. Dans l'AGC virtuel, avant que le test des lampes ne débute, l'affichage ressemble à ceci; ceci est ce que nous voyons dans la séquence du module de commande avant que l'astronaute ne tape la touche "ENTR". Et, dans l'AGC virtuel, après le début du test des lampes, l'affichage ressemble à ceci; ceci pourrait être ce que nous voyons dans la séquence du module de commande après que l'astronaute ait pressé la touche "ENTR", quoique nous puissions pas voir clairement, parce que l'affichage est trop flou. Avant que l'astronaute ne presse la touche "ENTR", au début de la vidéo, le verbe semble afficher la valeur "35" qui doit avoir été tapée par l'astronaute avant que la vidéo ne débute. Il est donc logique que, lorsqu'il presse la touche "ENTR", le test des lampes commence, et affiche quelque chose qui ressemble à ce que nous voyons. Il y a pourtant quelques problèmes. D'abord, lorsque les segments apparaissent allumés, au lieu de s'éclairer tous en même temps comme ils le devraient, il apparaissent de manière progressive au lieu de cela comme cette animation ralentie le montre; la séquence complète s'étend sur une demie seconde; cela peut ne pas sembler beaucoup, mais, pour un ordinateur, même pour un ordinateur lent tel que l'AGC, c'est énorme. Si l'AGC a besoin d'une demie seconde pour allumer quelques digits, nous pouvons alors nous interroger sur sa capacité à guider le vaisseau spatial! De plus, alors que tous les indicateurs apparaissent allumés sur la gauche, durant cette séquence la moitié d'entre eux s'éteignent pour se rallumer ensuite; où est la cohérence dans ceci? De même, lorsque le test des lempe est arrêté, les segments électroluminescents devraient s'éteindre tous en même temps; mais il s'éteignent aussi progressivement au lieu de cela, sur un intervalle d'une demie seconde comme c'est visible sur cette animation ralentie. Et il y a un autre problème. Sur le clavier de l'unité, il y avait une touche appelée "STBY" (pour "Standby", cerclée de rouge). Hors du mode de standby, cette touche permet de continuer lorsqu'une routine interne demande des données, et de lui dire que continuer son traitement, soit avec des données tapées, ou éventuellement sans spécifier de donnée. Pendant le test des lampes, il n'y avait couramment pas de commande en cours, puisque l'indicateur "PROG" n'est pas allumé, et il s'allume lorsqu'une routine interne veut prendre contrôle de l'unité. L'astronaute n'a donc pas de raison de taper la touche "STBY" à ce stade. Pourtant, juste avant de taper la prochaine séquence de commande, j'ai pris l'astronaute en train de taper sans nécessité la touche "STBY". Voici l'image que j'ai capturée sur laquele il tape cette touche. Nous allons nous intéresser à la séquence finale de la démonstration. Voici un extrait de la séquence. Nous voyons l'astronaute taper une commande, et puis des données pour cette commande. Quelle est cette commande exactement? L'astronaute tape d'abord la touche du verbe. Puis l'astronaute tape la touche "3". Puis l'astronaute tape la touche "7". Finalement l'astronaute tape la touche "Entr", pour terminer la commande, et la faire prendre en compte. Quelle est cette séquence exactement? Selon la documentation du DSKY, la séquence Verbe, 3, 7, et Entr correspond à une séquence de changement de mode majeur; son effet est de razer le registre d'affichage du groupe, et de faire clignoter le registre d'affichage du verbe; un mode majeur de deux caractères doit alors être tapé, suivi de la touche Entr. Alors que les deux chiffres du nouveau mode majeur sont tapés, ils apparaissent successivement dans le registre d'affichage du groupe. J'ai cerclé de rouge le registre d'affichage du verbe, et de vert le registre d'affichage du groupe. L'astronaute tape ensuite la touche "0", qui correspond au premier chiffre du nouveau mode majeur; après avoir été tapé, il apparaît dans le digit de gauche du registre d'affichage du groupe. Puis l'astronaute tape la touche "1", qui correspond au second chiffre du nouveau mode majeur; après avoir été tapé, il apparaît dans le digit de droite du registre d'affichage du groupe. Finalement l'astronaute tape la touche Entr pour faire prendre en compte le nouveau code de mode majeur; vous voyez que les deux digits du nouveau mode majeur apparaissent dans le registre d'affichage du groupe, ce qui montre qu'il a été correctement tapé. Lorsque l'indicateur d'activité de l'ordinateur (cerclé de rouge) s'éteint, cela signifie que l'ordinateur a fini de traiter la commande; à ce moment, la documentation dit que le nouveau code de mode majeur devrait être affiché dans le registre d'affichage du mode majeur, c'est à dire le premier registre de donnée (cerclé de vert); mais vous pouvez constater qu'il n'y a rien dans ce registre de donnée, il est vide! Et il y a un dernier indice que la séquence est fausse. Au début du test des lampes, une lampe, sur la gauche de l'AGC (cerclée de rouge), s'allume. A la fin de la séquence, l'astronaute lève la main pour presser un bouton qui éteint cette lampe. Pourtant, avant même que l'astronaute ne lève la main, comme cette animation ralentie le montre, la lampe s'éteint automatiquement, ce qui signifie que l'astronaute n'a plus besoin de l'éteindre. Pourtant, il n'arrête pas de lever la main, et presse inutilement le bouton d'extinction de la lampe. Toutefois, contrairement aux indices précédents, celui-ci ne montre pas un fonctionnement incorrect de l'AGC, mais juste une maneuvre illogique de l'astronaute. Cette démonstration contient donc une succession d'indices qui la prouvent comme fausse. Vous remarquerez que, dans cette démonstration, le find de l'affichage de l'ordinateur apparaît noir. Pourtant, sur cette photo d'Eldon Hall pianotant sur le clavier de l'AGC, nous voyons que le fond de l'affichage de l'AGC est clair de manière inattendue, plus clair que le reste de l'unité; et nous voyons des symboles noirs dessus. Alors quelqu'un m'a montré cette photo de l'AGC que l'on peut voir dans le musée de l'histoire de l'ordinateur, et qui ressemble à celui que l'on voit sur la photo précédente. Mais le fond de l'affichage est clair au lieu d'être sombre. Et nous ne pouvons pas deviner les symboles des 7-segments dessus, même faiblement. Si c'était un affichage electroluminescent, le fond de l'affichage serait plus sombre, et nous pourrions faiblement distinguer les symboles dessus. Ce ne peut être qu'un affichage à cristal liquide. Les affichages à cristal liquide ont commencé d'apparaître en 1971. Au début des missions Apollo, ils n'existaient pas encore, mais, à la fin des missions, ils commençaient d'apparaître, quoique leur technologie ne soit pas encore mûre. La première version d'affichage à cristal liquide affichait des digits blancs sur un fond noir. Les versions ultérieures d'affichage LCD affichérent des digits noirs sur un fond clair. Les premiers fonds clairs étaient jaunes, car le jaune était en fait un filtre placé devant l'affichage de manière à absorber les rayons ultra-violets dommageables et prolonger la vie du liquide du cristal. Toutefois la technologie de l'écran LCD n'était pas encore bien maîtrisée au début des années 70. La lenteur de réponse des cristaux liquides du début, et l'inquiétude à propos de la longévité et la stabilité en température du liquide du cristal on retardé son acceptation généralisée jusqu'a la moitié des années 70. Cela signifie que, s'ils avaient utilisé un affichage LCD dans les dernières missions, il y avait un risque élevé que les symboles de l'affichage disparaissent ou deviennent illisibles; ceci n'était pas acceptable dans les missions Apollo, dans laquelle le bon fonctionnement de l'affichage était si vital. En fait, le seul avantage de l'affichage LCD sur l'affichage electroluminescent était la moindre consommation de courant, mais c'était au prix de la sécurité! La documentation de l'AGC écrite par Eldon Hall, et datée de 1972, dit clairement que l'AGC utilisait un affichage electroluminescent; il n'est fait nulle part mention d'un affichage LCD. Quand j'ai dit aux fans d'Apollo que je doutais que les affichages montrés sur ces photos aient jamais affichés quelque chose, ils m'ont montré une photo et une démonstration animée avec ce type d'affichage affichant effectivement quelque chose, et c'est alors que j'ai compris le trucage. On m'a d'abord montré cette photo avec un affichage qui ressemble à celui qui est montré au musée. Il m'a d'abord intrigué, et puis j'ai trouvé des choses intéressantes dessus, que je vais expliquer. D'abord, si nous comparons l'unité DSKY avec celle de la vidéo du module de commande, il est manifeste que les affichages sont très différents. Sur la vidéo du module de commande, le fond est indéniablement bien plus sombre que le reste de l'AGC, et sur la photo présentée par les fans d'Apollo, c'est l'inverse. Alors quoi? Auraient-ils changé la technologie de l'AGC entre temps? Maintenant, les segments pourraient être faux, ils pourraient être ajoutés à l'affichage. Bien sûr, vous allez me dire: Prouvez-le! Il y a plusieurs indices qui montrent que cette photo est une mise en scène, et je vais les donner. Premier indice: Concentrons nous sur la partie de l'affichage que j'ai cerclée. Voyez la barre horizontale du signe '+': Elle touche le chiffre '0' sur sa droite; sur un affichage electroluminescent, les symboles sont bien séparés et ne se touchent pas. Deuxième indice: Sur la gauche de l'unité; nous voyons le cable qui le connecte à l'ordinateur. Concentrons nous sur la partie que j'ai cerclée. Le cable devrait aller au connecteur de l'unité sur son dos; au lieu de cela, il va sur le devant de celle-ci, et devient plus mince; la manière dont il est connecté est complètement anormale. Troisième indice, et le plus intéressant: Voyez l'indicateur que j'ai cerclé. Cet indicateur est l'indicateur "TEMP", et cet indicateur indique que la température du memble stable de l'IMU (les gyros) est hors limites. L'IMU est essentiel au vaisseau spatial, car il permet son guidage; s'il s'arrêtait de fonctionner, le vaisseau spatial resterait sans guidage. Et n'allez pas penser que la base sur terre pourrait guider la vaisseau spatial à la place, car la terre a aussi besoin des informations de l'IMU pour calculer les position et orientation du vaisseau spatial, lesquelles informations sont transmises via le réseau MSFN. Vous pourriez dire: Cela ne prouve pas que cela pourrait aussi arriver durant une mission lunaire, car l'AGC peut avoir travailler pendant longtemps lorsque cette photo a été prise; je ne peux savoir combien de temps il a fonctionné lorsque cette photo a été prise. Oh si, je le sais, et je vais expliquer comment je le sais. L'AGC avaient deux timers comptant le temps, appelés TIME1 et TIME2; les deux étaient des compteurs de 14 bits. Le premier, TIME1, était incrémenté par un signal d'holroge de 10 ms, et comptait donc les centièmes de seconde. Comme il avait 14 bits, il pouvait compter jusqu'à 2^14-1=16383; à l'impulsion d'horloge suivante après qu'il ait atteint son compte maximum, il était remis à zéro en même temps qu'il envoyait une impulsion au compteur suivant TIME2, le timer TIME2 était donc incrémenté tous les 16384 centièmes de seconde, ou encore 163,84 secondes; il comptait aussi jusqu'à 16383. Les deux timers étaient équivalents à un timer de 28 bits qui compterait jusqu'à 16384*16384-1=268435455 centièmes de seconde, ou encore 2684354,55 secondes. Exprimé en heures, cela faisait : 2684354,55/3600=745,65 heures; en en jours, cela faisait : 745,65/24=31,07 jours, donc juste un peu plus qu'un mois. Cela va bien au delà de la mission lunaire la plus longue. Il y avait deux manières d'afficher les timers. Le verbe 16 permet d'afficher des données sélectionnées par le groupe. Les groupes 36 et 65 correspondent à l'affichage des timers. L'AGC virtuel montre comment le groupe 36 affichait les timers sur trois lignes: - La première ligne affiche les heures. - La deuxième ligne affiche les minutes. - La trosième ligne affiche les centièmes de seconde. L'AGC virtuel est pas clair à propos de la manière dont le groupe 65 affiche les timers; en le lisant, on pourrait penser que le groupe 65 affiche les timers de la même manière que le groupe 36. Mais dans ce cas, ce que nous voyons sur la photo serait faux, car nous ne voyons que deux lignes de données affichées. Mais ce que nous voyons sur l'affichage n'est pas incorrect, car le groupe 65 affiche les timers différemment du groupe 36, selon ce que j'ai vérifié dans la documentation de l'AGC. - La première ligne affiche les heures sous la forme XXX.XX; en fait, le point décimal n'est pas affiché; le double timer est simplement affiché en centièmes d'heures, en divisant celui-ci par 3600 et en gardant la partie entière de cette division.; cette ligne peut aller jusqu'à 74565. - La deuxième ligne affiche les secondes sous la forme XXX.XX; en fait, le point décimal n'est pas non àplus affiché; le double timer est affiché en centièmes de seconde; mais comme cinq chiffres ne sont pas assez pour afficher le timer, seuls les 5 derniers chiffres de droite sont affichés; cette ligne peut aller jusqu'à 99999. Ce que nous voyons sur l'affichage est donc compatible avec ce que j'ai dit. Il y a une corrélation entre les deux lignes affichées que je vais expliquer, et que nous pouvons vérifier. La valeur 133 affichée sur la première ligne correspond à un nombre de centièmes d'heures; pour obtenir la valeur correspondante en centièmes de secondes, nous le multiplions par 3600, ce qui donne: 133*3600=478800 centièmes de seconde; mais, comme il change tous les 3600 centièmes de seconde, la valeur courante du double timer est comprise entre cette valeur et cette valeur plus 3599, donc entre 478800 and 478800+3599= 482399; exprimé en modulo 100000, cela ferait pour la deuxième ligne une valeur comprise entre 78800 and 82399; la deuxième ligne affiche 78812, et est donc dans la plage attendue; les deux lignes sont donc compatibles; je me serait attendu à ce qu'elles ne le soient pas, mais je dois admettre la compatibilité des deux lignes affichées. Mais cela prouve au moins quelque chose: l'AGC a fonctionné durant 1,33 heures; la partie fractionelle 33 ne représente pas des minutes mais 0,33 heure; de manière à savoir combien cela fait en minutes, nous devons multiplier la partie fractionelle par le nombre de minutes dans une heure, soit: 60x0,33=19.8 minutes, nous pouvons l'arrondir à 20 minutes. Nous avons à présent la preuve que l'AGC a fonctionné pendant une heure et 20 minutes lorsque cette photo a été prise, et, dans un temps si court, l'IMU a déjà des problèmes de température. Maintenant réflechissez: si l'IMU surchauffe après avoir seulement fonctionné pendant un peu plus d'une heure dans un environnement qui est plus ouvert que celui du vaisseau spatial, qu'est ce que cela donnera lorsqu'il a à fonctionner pendant plusieurs jours de manière continue dans l'environnement plus confiné du vaisseau spatial? Nous avons toute raison de penser qu'il a une bonne chance de tomber en panne et de laisser le vaisseau spatial sans guidage! Les fans d'Apollo m'ont aussi montré une animation de cette unité DSKY. Dessus nous voyons les chiffres changer, et ce ne peut pas être, comme je l'avais suggéré, quelque chose (comme de l'adhésif fluorescent) juste collé dessus. Toutefois, si nous comparons l'affichage sur cette animation avec l'affichage de la vidéo du module de commande, nous voyons que la lisibilité des chiffres est bien meilleure dans la vidéo du module de commande, en raison d'un contraste meilleur procuré par un fond plus sombre. En fait, si nous regardons de près, l'affichage sur cette unité DSKY re ressemble pas du tout à des segments electroluminescents; le contraste est exécrable (il est toujours bon pour un affichage electroluminescent), les segments ne sont pas nets, et, comme sur la photo, les barres horizontales des signes '+' touchent les chiffres voisins. Cela ne ressemble absolument pas à un affichage electroluminescent. Mais, d'un autre côté, cela ressemble à une image projetée depuis un projecteur. L'animation était projetée depuis un projecteur visant l'affichage du DSKY. Bien sûr, ce n'était pas ce projecteur. Et, si l'affichage n'avait pas la bonne qualité pour un affichage electroluminescent (pas assez sombre)... ...Il avait de bonne propiétés reflectives comme un écran de projecteur. Ces propriétés réflectives permettaient de réfléchir l'image projetée depuis un projecteur, ce qu'un écran noir n'aurait pu faire (vous n'avez jamais vu un écran de projecteur noir, n'est-ce pas?). Maintenant quels sont les éléments dont je dispose pour étayer ma théorie? A un moment donné durant la séquence, nous les voyons reculer un peu l'unité DSKY. Cette vue stéréosocpique montre sur la gauche l'unité avant qu'ils ne la reculent, et sur la droite l'unité après qu'ils l'aient reculée (vous pouvez aussi voir que l'unité a été reculée si vous considérez les trous sur le haut de l'appareil qui est sur la droite de l'unité). Mais pourquoi l'ont-ils reculée? Ce n'était pas pour la mettre davantage en évidence, car, auparavant, elle est était plus proche et entiérement visible, et donc mieux placée au début de la séquence qu'à la fin. Il doit donc y avoir une autre raison, et je l'ai cherchée. Finalement j'ai trouvé cette raison lorsque j'ai remarqué un reflet qui apparaît sur le bas de l'image au début de la démonstration. Ce reflet est manifestement créé par le faisceau du projecteur, ce qui nous permet de savoir qu'il était placé sous l'image. Et, de sorte qu'il n'y ait pas d'ambiguïté, que ce reflet n'est pas juste une tâche blanche, nous voyons ce reflet bouger au cours de la démonstration. Ils ont donc reculé un peu l'unité pour obtenir une meilleure orientation du faisceau du projecteur qui éviterait ce reflet sur l'image, et effectivement nous ne voyons plus ce reflet dans la deuxième partie de la séquence après le recul de l'unité. Le fait de reculer l'unité permet également d'éviter le reflet du faisceau du projecteur sur la main de l'opérateur: La photo de gauche montre une image de la démonstration avant le recul de l'unité, et la photo de droite après le recul de l'unité. La main a approximativement la même orientation sur les deux images. Sur ces gros plans, nous voyons que la bague que l'opérateur porte est plus brillante sur la première image (i.e. avant le recul de l'unité) que sur la seconde (i.e. après le recul de l'unité), en dépit du fait qu'il y a un doigt au dessus de la bague qui devrait l'ombrer. Sur la première image, nous ne voyons pas son relief, alors que nous le voyons sur la seconde. Il y a d'autres éléments d'évidence que l'affichage que nous voyons est projeté depuis un projecteur. En examinant les images échantillonées de la séquence une par une, j'ai noticé une variation de l'affichage entre deux images consécutives. Ce n'est pas très évident sur cette animation globale... ...Mais c'est bien plus visible sur cette animation faite avec deux fenêtres de l'affichage de la même taille et la même position exactement prises sur deux images consécutives de la séquence. Vous voyez clairement que le "35" flotte (pas seulement en position, mais aussi en taille) sur l'affichage (remarquez la variation du sommet des chiffres relativement à la fenêtre au dessus); ceci ne pourrait pas arriver avec un affichage electroluminescent sur lequel les segments gardent toujours la même taille physique qui ne peut varier, et cela prouve indéniablement que l'affichage est projeté. Au milieu du test lumineux, les chiffres du verbe et du groupe (les deux paires de chiffres au dessus des lignes de données) deviennent subitement moins lumineux pour retrouver ensuite leur luminosité normale (alors que la luminosité des autres chiffres reste stable); ceci aussi ne peut arriver avec un affichage electroluminescent sur lequel les segments des chiffres peuvent être allumés ou éteints, mais pas à moitié allumés. Ceci prouve également que l'affichage est projeté. Vous direz! Très bien, mais l'opérateur devait presser les touches au bon moment, car, s'il n'était pas synchronisé avec l'affichage, cela se verrait! Oui, mais l'opérateur savait à l'avance ce qu'il devait taper, le scénario était préparé à l'avance. Il pourrait y avoir un léger décalage entre ce que l'opérateur tape et l'affichage, mais ce problème était résolu comme je l'explique ici sur cette animation ralentie: L'opérateur doit taper un '6' dans la séquence; il est un peu en avance sur l'affichage projeté; il place donc son doigt devant le '6' et attend qu'il apparaisse sur l'affichage; aussitôt que le '6' projeté apparaît, il termine l'appui sur la touche; cela ne prend que quelques fractions de seconde, et donc le spectateur ne remarque rien, et pense que c'est le fait que l'opérateur a pressé le '6' qui l'a fait apparaître à l'affichage, alors qu'il était simplement dans la séquence projetée. De manière à bien saisir ce que l'opérateur fait au moment où le '6' apparaît sur l'affichage, j'ai echantillonné la vidéo plus rapidement que je ne le fais d'habitude, c'est à dire 20 images par secondes au lieu des 10 images habituelles. Je montre ici sur cette vue stéréoscopique deux images consécutives de la séquence echantillonnée; sur la première (à gauche), le '6' est déjà apparu sur l'affichage; l'opérateur réagit immédiatement en pressant la touche '6'; mais, même s'il est très rapide, il y a quand même un petit retard dans sa réaction, et c'est pourquoi nous le voyons presser le '6' dans l'image suivante (à droite). Ce n'est pas très visible dans la vue stéréoscopique que j'ai montrée, mais c'est beaucoup plus visible sur cette animation alternant l'image sur laquelle le '6' apparaît sur l'affichage (titrée "BEFORE" en vert) avec l'image sur laquelle l'opérateur presse la touche (titrée "AFTER" en rouge). Si c'était vraiment l'AGC qui affiche le '6', il ne pourrait apparaître avant que l'opérateur n'ait pressé la touche. Sur cette image extraite de la séquence, l'opérateur utilise une technique spéciale pour améliorer la synchronisation entre ce qu'il tape et ce qui apparaît à l'affichage. Au lieu d'uiliser seulement un doigt comme il le devrait normalement, il utilise deux doigts croisés; il commence à utiliser le doigt qui est dessous; si l'affichage change, il retire alors sa main, comme ce que nous voyons sur l'image, de sorte que nous voyions le doigt qu'il a utilisé pour taper la touche; mais, s'il est un peu en avance sur l'affichage, il utilise alors le deuxième doigt, celui du dessus, et fait croire qu'il a utilisé celui-ci pour presser la touche. En fait, cela explique pourquoi le DSKY avait ce type d'affichage. Ce n'était effectivement pas un affichage à cristaux liquides, c'était un affichage qui avait de bonnes propriétés réflectives pour afficher une image depuis un projecteur, de manière a ce que l'unité DSKY n'avait pas besoin d'être une unité vivante, et que ce qui était affiché dessus pouvait être simulé par projection. Maintenant les truqueurs ont donné plusieurs indices que cette séquence est un montage. 1) Il y a l'indcateur "TEMP" qui s'allume, comme sur la photo, après que l'AGC a tourné pendant à peine plus d'une heure et demie (puisque la première ligne du timer affiche 152, ce qui représente 1,52 heure, donc en fait une heure et 31 minutes), laissant de sérieux doutes à propos de la viabilité de l'IMU. 2) Il y a aussi l'indicateur "KEY REL" qui s'allume briévement lorsque l'opérateur presse la touche '3' au lieu de la touche "KEY REL" (qui est juste à droite du '3') qui est associée à cet indicateur. Remarquez que cet indicateur ressemble à une main avec l'index levé. 3) Et il y a même un nouvel indice qui n'était pas sur la photo! A un moment ils font afficher le timer avec le verbe 15 et le groupe 65 comme je l'ai expliqué auparavant. La ligne du dessus (les centièmes d'heure) affiche "00152" et la ligne du bas (5 derniers chiffres des centièmes de seconde) affiche "45723". 152 centièmes d'heure correspond à 152x3600=547200 centièmes de seconde. Cela signifie que la ligne du bas devrait afficher au moins 47200 (entre 47200 et 47200+3599=50799)...Et elle affiche seulement 45723, donc moins que la valeur minimale qu'elle devrait afficher! Et n'invoquez pas un problème de rafraîchissement, car la différence correspond à presque 15 secondes! Donc, cette fois, contrairement à la photo, il n'y a pas de correspondance entre les deux lignes du timer, et nous avons un indice de trucage que nous n'avions pas avec la photo! Et, puisque je fais une comparaison entre les deux affichages, voyez la différence impressionante de contraste entre les deux affichages! Le contraste est bien pire sur la séquence animée que sur la photo. Il est absolument manifeste qu'il n'est pas produit de la même manière sur la photo et sur la séquence animée. Sur la photo, l'affichage n'est pas projeté, il est três probablement rajouté en dur sur l'écran (peut-être avec du ruban adhésif fluorescent, ou un feutre spécial). |
lien vers la vidéo "computer for Apollo Une présentation de l'ordinateur d'Apollo a été faite en 1965 par la NASA: "A computer for Apollo". Cela semble une démonstration sérieuse, mais en surface seulement. Si nous grattons la surface, plein d'anomalies apparaissent. Cette présentation fait successivement défiler Eldon Hall, Ramon Alonso, Albert Hopkins, et un ingénieur principal de Raytheon. Eldon hall fait d'abord une présentation de la manière dont le vaisseau spatial est guidé. Il explique comment l'alignement avec une étoile permet de guider le vaisseau spatial. En bougeant les mains, il illustre comment l'angle entre l'étoile et la terre décroît alors que le vaisseau spatial s'éloigne de la terre. Mais il omet de dire que cet angle change également si le vaisseau spatial bouge latéralement sans s'éloigner de la terre. En fait, il n'est pas possible de faire le guidage en utilisant seulement une étoile; nous sommes dans un système tridimensionel, et, dans un tel système, trois références sont nécessaires; une d'elles est la terre, et les deux autres doivent être deux étoiles, et suffisamment éloignées l'une de l'autre. Donc, en montrant un schéma avec seulement une étoile utilisée pour le guidage au lieu de deux, Eldon Hall trompe intentionnellement les spectateurs de la démonstration, qui ne sont pas, pour la vaste majorité, assez avertis de la manière dont le guidage d'un vaisseau spatial doit être fait pour remarquer le problème. C'est ensuite au tour de Ramon Alonso de faire sa présentation. Ramon Alonso explique comment l'ordinateur fonctionne. Alonso est le co-auteur, avec Albert Hopkins, d'un document de 1963 qui contient déjà une information délirante, avec la description d'une mémoire qui ne pouvait pas marcher. J'ai présenté ce document comme la preuve que le truquage d'Apollo a commencé au temps de Kennedy, et non après qu'il ait disparu. Alonso fait d'abord une démonstration de l'affichage du temps sur l'écran. Mais il y a déjà un petit problème. Lequel? La première ligne de donnée affiche les centièmes d'heure, et la seconde les cinq premiers chiffres des centièmes de seconde. Plus tard, l'affichage a été changé pour afficher les heures, minutes, et centièmes de seconde sur trois lignes, mais, au temps de la présentation, l'affichage se faisait encore sur deux lignes seulement.En fait ces deux lignes ont une relation entre elles: En multipliant les centièmes d'heure par 3600, nous obtenons un compte de centièmes de seconde modulo 3600; ceci signifie que le compte réel de centièmes de seconde est compris entre le produit du compte de centièmes de seconde par 3600, et ce produit plus 3599; ceci permet de faire la relation entre les deux lignes. La première ligne de donnée affiche 9856, et la seconde 80275. Si je multiplie 9856 par 3600, j'obtiens 35481600, et, si j'en garde les 5 premiers chiffres, cela donne 81600; ceci signifie que la seconde ligne de donnée devrait afficher un compte compris entre 81600 et 81600+3599=85199; pourtant elle affiche seulement 80275 et est en dehors de cette plage. Pour conclure, Alonso montre un affichage qui est illogique, impossible, et il le fait intentionnellement. Remarquez aussi que le fond de l'écran de l'ordinateur est complétement noir. Pourtant, sur cette photo de 1962, Eldon Hall tape sur un ordinateur dont l'affichage a un fond clair. Ceci est contradictoire et prévu comme une incohérence. Le fond d'un affichage électroluminescent doit toujours être noir pour une question de contraste. Le fond d'un affichage à cristaux liquide peut être clair, parce que les chiffres peuvent être noirs, mais cette technologie n'existait pas du temps d'Apollo. Puis Alonso utilise le mot 57 pour rentrer les angles désirés pour l'alignement du télescope. Il rentre les angles en X et Y (ils sont en centièmes de degré). Il rentre 180 pour l'angle X, et 325 pour l'angle Y. Y a t'il un problème? Oui, il y a un problème, car, dans la documentation, ils disent que l'angle maximal pour Y est 179,99°, et ici Alonso a rentré 325° pour cet angle! Puis Alonso change la direction du télescope, depuis l'orientation initiale qu'il a définie, en le maneuvrant. A la fin, nous voyons qu'il tourne le réticule autour de l'axe Z. En fait, il n'y a pas que deux angles pour orienter le télescope, mais trois angles. Il y a les angles de translation (X et Y), mais aussi l'angle de rotation du réticule (Z), et celui-ci devrait aussi être renseigné. Puis Alonso dit, qu'en pressant un bouton, il peut dire à l'ordinateur de prendre en compte l'ajustement manuel qu'il vient de faire. Puis, Alonso fait afficher les angles courants optiques avec le mot 56 et dit que les angles observés sont très proches des angles qu'il avait précédemment rentrés. Mais, précisément, ils ne devraient pas être proches! Alonso a maneuvré le télescope, et, ce faisant, il a changé les angles optiques de manière conséquente! Ils devraient donc montrer une différence importante avec ceux qu'Alonso avait rentrés, en non en être proches! De plus, la troisième ligne affiche le temps du réglage, et non un angle; elle devrait plutôt avoir été réservée pour afficher le troisième angle manquant, celui en Z, l'angle de roulis. En bref, Alonso vient de faire une démonstration dans laquelle il a volontairement accumulé des absurdités! Puis c'est le tour d'Albert Hopkins de faire sa démonstration. Hopkins fait une bréve présentation de l'ordinateur. Il fait une présentation de l'unité arithmétrique qu'il présente comme une unité qui prend des opérandes depuis la mémoire dynamique, réalise une opération sur ceux-ci, et place le résultat calculé dans la mémoire dynamique. Mais, si les opérateurs que j'ai cerclés de vert produisent effectivement un résultat qui peut être placé dans la memoire dynamique, les opérateurs >' et '#' ("Plus grand que" et "différent de") sont des opérateurs de comparaison et ne produisent pas des résultats mots comme les opérateurs arithmétiques, mais seulement mettent à jour des bits de status qui sont utilisés pour faire des branchements conditionnels. Il s n'ont rien à faire dans l'unité arithmétique. Et, en ce qui concerne l'opérateur que j'ai cerclé de jaune, c'est un opérateur fantaisiste qui n'a pas d'existence. Hopkins explique également que les entrées depuis d'autres organes sont directement stockées dans la mémoire dynamique par une connection directe, et que les mots depuis la mémoire dynamique sont directement envoyés vers d'autres organes. Mais, en réalité, il n'y a pas de connection directe entre les entrées&sorties et la mémoire dynamique. Les entrées et sorties devraient aller vers et depuis l'unité centrale qui les prend en charge. L'unité centrale lit une entrée dans un registre interne, mais n'est pas tenue de la mettre dans la mémoire dynamique; elle peut directement réaliser une opération dessus sans stocker l'entrée originale et seulement stocker le résultat de l'opération dans la mémoire dynamique. Elle peut aussi directement rediriger une entrée lue vers un autre organe, sans passer par la mémoire dynamique. L'unité centrale peut aussi sortir une donnée qu'elle a calculée dans un registre interne. Pour conclure, la présentation qu'Hopkins fait de l'ordinateur est incorrecte, mais il le fait intentionnellement. Il pourrait faire une présentation correcte, mais il ne le veut pas. Le but est de montrer aux futures générations qu'ils ont été pris en otages du truquage, et ne l'ont pas approuvé. Puis un ingénieur principal de Raytheon fait une présentation de la manière dont les unités AGC sont produites. Il montre un tore de la mémoire à cordes de tores. A travers ce tore, jusqu'à 192 fils de détection pouvaient passer. Il est absolument impossible que tous ces fils de détection puissent déceler un courant détectable, même s'ils pouvaient passer à travers le tore. De plus, la manière dont les tores sont activés, selon la documentation, n'a pas le moindre sens, car, au lieu d'activer directement un tore avec une ligne de commande (ou éventuellement deux lignes portant un demi-courant chacune), ils activent tous les tores avec une ligne d'activation commune, et désactivent tous les tores avec des lignes d'inhibition, sauf celui qui est couramment testé. Le résultat est non seulement un gaspillage insensé d'énergie, mais aussi que plein de fils d'inhibition doivent passer à travers les tores; et ces fils d'inhibition ont une section plus importante que les fils de détection, car ils reçoivent un courant plus important. Il est tout simplement impossible que tous ces fils puissent passer à travers un tore, sans compter le fait que cela ne marche pas non plus électriquement. Ajoutez à ceci que les fils ne doivent pas être dénudés, mais gainés. Puis l'ingénieur de Raytheon montre l'arrière de l'ordinateur, et nous voyons un fouillis anarchique de fils. De plus, nous n'avons même pas le compte normal de fils, car chaque carte mémoire avait 512 fils de commande et 192 fils de détection! Puis l'ingénieur de Raytheon montre les travailleuses faisant passer les fils de détection à travers ou en dehors des tores, suivant les instructions qu'elles avaient reçu. Penser qu'une mémoire puisse être conçue de cette manière est pure fantaisie. 512*192=98304 occasions de faire une erreur pour chaque carte mémoire. Et faire une erreur impliquait de retirer complétement un fil de détection pour l'enfiler à nouveau! Si au moins cela avait pu marcher! Mais même pas! Cette mémoire a été surnommée LOL par les ingénieurs du MIT. Et, is officiellement, cela voulait dire "Little Old Lady" (petite vieille dame), en privé cela signifiait ce que cela signifie d'ordinaire. Puis les connexions sur le dos de l'ordinateur étaient faites avec une machine rudimentaire. Lorsque nous la voyons fonctionner, nous pouvons avoir de sérieux doutes sur ces capacités à remplir une tâche aussi compliquée que celle de faire toutes les nombreuses et précises connexions qui devaient être faites (sur chaque carte mémoire, il y a normalement quelques sept-cent connexions - Si nous ajoutons les fils de détection aux fils de commande!) Les informations pour faire une connexion étaient stockées sur une carte perforée, une par connexion. Etant donné le grand nombre de connexions qui devaient être faites, cela représentait un nombre très important de cartes perforées. Quand nous voyons la lenteur avec laquelle les cartes perforées défilent, cela devait représenter un sacré temps pour faire toutes les connexions. Nous pouvons nous demander pourquoi les instructions de connexion n'étaient pas plutôt mémorisées sur une bande magnétique. Puis l'ingénieur de Raytheon fait une démonstration de la manière dont l'AGC pouvait être testé. Pour débuter le test, il tape le verbe 50. Mais, dans la documentation, ils disent ceci à propos du verbe 50; "Ce verbe n'est utilisé que par des routines internes qui désirent que l'opérateur réalise une certaine tâche. Il ne devrait jamais être tapé par l'opérateur" Alors, comment est-ce que l'ingénieur pouvait démarrer le test avec ce verbe alors que la documentation de la NASA dit qu'il ne devrait pas l'utiliser? |