samedi 26 mai 2012

Code optimisation (III)

Voici une autre vieille routine que j'ai retrouvée suite au précédent article concernant le code 'déroulé', appelé aussi par les anglophones 'unrolled'.

Cette technique était utilisée sur des CPUs sans code cache L1 ou L2 (68000 et 68010), qui rappelons-le est une mémoire rapide au sein même du processeur qui conserve le code afin de minimiser les échanges beaucoup plus lents entre le 68k et la fastram.

La routine ici a été codé par les ingénieurs de Commodore dans les années 1983/84/85 (Kickstart 1.2), donc pour le 68000. Ce sont les vecteurs d'interruptions, les autovec de l'exec.library. Ils n'ont par la suite pas été retravaillé dans le Kickstart 3.1 et même dans le 3.9 :

Or, à partir du 68020, Motorola ajoute à ces nouveaux CPUs ce fameux code cache, mais hélas sans son compagnon le branch cache. Ce dernier n'arrive en effet que sur le 68060. Le branch cache est une nouvelle astuce qui permet d'éviter des cycles de branchements, indispensable pour maximiser encore l'efficience les boucles (loops) présentes dans le code cache. Peu importe de toutes façons, il n'y a aujourd'hui plus aucun intérêt à optimiser pour tout ce qui est en dessous du 68060.

Pour donc utiliser au mieux toutes les spécificités du 68060, il n'y a pas d'autres solutions que de tout reprogrammer, avec bien en tête l'architecture du 060.

Les six routines autovec font au total 544 octets. Il faut bien se souvenir que :
  1. Les accès fastram sont lents sur nos Amiga Classic, c'est à dire que le temps de transfère du code contenu de la mémoire pour traitement dans le CPU est élevé,
  2. Lorsque le CPU demande du contenu fastram, il attends de la recevoir de la mémoire.

Bref, pour ce genre de routine, plus le code est court et plus rapide c'est pour un CPU comme le 68060.

Avec donc une autre technique de programmation utilisant le moins possible le code avec des boucles, le résultat final ne nous donne plus que 134 octets !

Pour chaque autovec, un longword informatif est envoyé dans d1, contenant :
  1. Le nombre de décalage de bits (.b),
  2. Le décalage initial (.b),
  3. L'offset ($54 pour IntVec0) (.w).

Le registre d1 est ensuite utilisé par la boucle pour tester les bits relatifs aux six autovec :

Voilà donc 134 octets 68060 qui donnent un résultat identique aux 544 initiaux 68000 : c'est quatre fois moins. Notez qu'ici, ce nouveau code est totalement compatible avec le 68000, mais peut-être légèrement plus lent pour lui.

Une cerise est encore belle et bien présente ici : le gain de place dans le Kickstart, 410 octets de sauvés pour cet exemple. Commodore avait bourré au maximum toutes ses roms, et il n'y avait plus de disponibilité pour des commandes très utiles comme par exemple la 'dir'... En économisant donc le plus d'octets possibles, il sera tout à fait possible de rajouter ces routines quasi-indispensables pour les utilisateurs ! Qui n'a pas pesté ici au moins mille fois pour un 'dir' à charger d'abord par une disquette ou sur disque dur pour obtenir un directory ?

Pour finir, sachez que tous les CPUs ont des points forts et des points faibles. Ici pour ce qui concerne le 060, sa plus grande faiblesse est qu'il nécessite du code bien réfléchi et bien ordonné pour donner le meilleur de lui-même !

Monsieur le 68060 se régale avec du code bien optimisé pour sa personne !!
  

Code optimisation (II)

Voici un autre cas, différent. J'ai déjà entendu dire que les 68k étaient des CPUs lents. Croyance erronée.

C'est le code généré automatiquement (sans intervention humaine) par nos compilateurs C/C++ qui est lent. Nuance.

Voici un exemple édifiant dans miniGL. Là, le source en C/C++ :

Le compilateur utilisé est Gcc en mode -O3. Le résultat sera quasi le même quelque soit la version utilisée :

Cette fonction générée fait exactement 1196 octets.

En utilisant judicieusement les boucles (loops), il est possible d'obtenir le même résultat en seulement 94 octets !

Soit 1102 octets économisés ! Incroyable !! Cela représente tout ça :

Cosmos, grand défenseur des 68k, nan mais oh !
   

Code optimisation (I)

Voici un article qui concerne une optimisation toute simple qui consiste à regrouper plusieurs R_AllocMem consécutives (ou presque consécutives) en une seule.

Rappel pour les débutants en programmation : AmigaOS étant multitâche, la mémoire (fast ou chip) est donc gérée par le Kickstart de façon à ce que tous les programmes utilisent leur propre portion bien définie et non celle d'un autre. Chaque portion mémoire nécessaire au fonctionnement de tels ou tels jeux ou utilitaires doit donc être demandé poliment à une fonction de l'exec.library qui s'appelle R_AllocMem.

Ici, nous allons prendre comme exemple l'initialisation de la fblit.library. Son auteur, Stephen Brookes, est un très bon codeur et tout ce qui suit est une étourderie de sa part, il a codé cette init rapidos, très certainement. Notez qu'en désassemblant divers programmes, je rencontre ce genre de programmation assez souvent, d'où cet article qui sera utile à bon nombre de programmeurs puisqu'elle s'applique à tous les langages, du C/C++ à l'assembleur et sur tout type d'ordinateurs assez récents...

Tout d'abord, le code ici entouré qui dirige vers un guru rouge (_LVOAlert) est inutile puisque la layers.library est présente en Rom : ces sept instructions peuvent être tout simplement ôtées :

Pareil ici pour la graphics.library, elle est aussi en Rom et l'Amiga ne peut pas fonctionner sans, elle est donc forcement disponible et fonctionnelle :

Donc, hop, byebye aussi...

Voici donc arriver le vrai sujet de cet article, les R_AllocMem :

Quatre R_AllocMem presque consécutives avec le même type de mémoire (MEM_FAST|MEMF_CLEAR) demandé pour donc quatre zones de fastram :
  1. BEC_SIZEOF,
  2. LASTCHANCE_SIZEOF,
  3. SS_SIZE,
  4. SS_SIZE.

L'Amiga je le répète étant multitâche, les portions de mémoire seront peut-être consécutives comme sur le croquis du haut, mais peut-être pas... C'est R_AllocMem qui gère les allocations toute seule en fonction de la disponibilité, le coder n'a pas son mot à dire la dessus !
  
L'idée est donc de faire UNE SEULE R_AllocMem pour déjà avoir une mémoire moins fragmentée et de plus un très net gain de vitesse : en effet, R_AllocMem prends un très grand nombre de cycles à s'exécuter.

Il suffit tout simplement d'additionner les portions pour n'en former qu'une seule :

Faire ensuite l'unique R_AllocMem qui donnera un bloc des quatre zones pour ensuite redistribuer à la main avec une simple addition chacune des portions :
  
L'adresse mémoire rendue par R_AllocMem étant dans a2, voilà alors le résultat :
 
Nous obtenons donc l'adresse du second bloc (LASTCHANCE_SIZEOF) avec l'adresse de départ de la portion unique par une simple addition du premier (BEC_SIZEOF) et ainsi de suite pour tous les suivants...

Et avec cette astuce, cerise sur le gâteau, d'autres instructions deviennent inutiles (comme par exemple les 'beq' avant les _LVOInitSemaphore). Regardez tout ce que nous avons économisé :

86 octets sauvés et une seule allocation mémoire pour exactement le même résultat que le code original ! Whaou, super !!

Pour finir, il suffit d'un seul R_FreeMem pour libérer cette zone mémoire au lieu de quatre auparavant !
   

samedi 19 mai 2012

A1200 fix pour ACA

Certains Amigaïstes ont des soucis avec les dernières ACA1231 sur AI en ce moment.

En effet, il apparait des bugs graphiques, quand ce n'est pas une impossibilité de booter la machine !

Les soucis viennent de certaines cartes, peu importe leurs révisions, car des composants soudés ne sont pas les même que pour la grande majorité des 1200.

Ayant quatre A1200 ici, aucune n'a besoin d'un fix ! Peu importe, voici les modifs à faire.

Déjà la référence des composants qui sont deux condensateurs 22 pF au format 0805 :
  
Et deux ferrites 60R@100 toujours au format 0805 :

Voilà les précisions du designer des ACA :
 
I found a method to reliably reproduce the graphics corruption effect. It's an effect where the blitter gets the wrong data, thus copying the wrong data, or at least the wrong amount of data.

I had to place some insulating material on Alice to heat it up and keep it from radiating too much heat. With a cool Alice, or at least in free-floating air, it was hard to get the gfx corruption reliable, but with Alice in a cosy coat of styrofoam, I had reliable GFX corruption when moving windows around on the Workbench and when using the TGtest in AIBB.

At first I tried solving the problem on the digital side (within the CPLD of the accelerator), but failed due to it's high access speed to the chipset. As some of you like to call it, the ACA1230 is "maxing out" the AGA chipset, and to those of you who are a little more technical : my state machine relies on the chipset of catching the data on the falling edge of CPU_CLK right after DSACK has been detected active (low) on the previous rising edge. It's a matter of a few nanoseconds that Alice (and the blitter that's contained therein) is missing the data when hot.

I call the fix preliminary, because I have to wait until the whole system has cooled down and re-try. Note that Alice isn't the only one that's handling clocks - Budgie makes the largest part of that work, but Alice depends on those clocks, so I still need to verify that it works reliably on a cold start.

The board in question is a 1D4. I can't tell if it's a Commodore or an Escom board. However, I have measured severe clock jitter especially during blitter operation. This 1D4 board had no filters on the 14 MHz CPU clock lines installed at all, but all my other boards have a filter combination assembled that is NOT seen in the schematics. The two 14 MHz signals are ran through filter combos E121 and E122. Schematics say that it's 27R / 22 pF combinations, but the faulty board has no caps installed - only the 27R resistors. During heavy blitter operation, the 14 MHz clock (which is the basis for the whole accelerator  timing) is jittering as much as 8 ns, but it looks just fine with an idle workbench.

Remove resistors E121R and E122R and replace them with 0805 ferrite beads - something in the range of 60R@100MHz or more. The two parts are located on the top of the board, near the 28 MHz oscillator.

Next, assemble two 22 pF capacitors (size 0805) in places E121C and E122C. These places were empty on the board in question, but need to be assembled with the parts mentioned in the A1200 schematics, and that's a 22 pF capacitor. These two parts are located on the bottom of the mainboard, also near the 28 MHz oscillator.

This will clean up the 14 MHz clock "big time" and make it completely immune against blitter-induced noise. However, it's not fixing the whole problem. I found that when assembling E125C with a 22 pF capacitor, but leaving E123C open, the machine is rock-solid, even with a heated-up Alice. With E125C removed, it's still showing some gfx corruption, but with the one part in place, the data-takeover into the AGA chipset is truly happening at the right  moment, and the fast access of the ACA1230 doesn't cause trouble to the mainboard any more.

I found that some boards have a ferrite bead installed in E127R, and other boards have a 27R resistor installed there. This also makes a difference in chipset timing and may be another part that I have to look at if the board starts acting up again when cold. However, since I have boards working great with one or the other installed, it doesn't seem to make that much of a difference.

I'll let the board, accelerator and power supply cool down for a few hours now, and report back how it behaves when cold. If anyone of you with access  to the required parts, tools and "bad boards" wants to give this a try, I'd be happy to hear your report(s).


Il faut donc souder les deux 22 pF dans l'emplacement vide E121C et E122C de l'autre côté de la carte :

Ensuite, dessouder E121R et E122R en les remplacant par les deux ferrites ici :

Voilà, c'est tout. Les nouvelles ACA devraient marcher maintenant !
 

dimanche 13 mai 2012

A4000D IDE 3.5 fix

Le port IDE 3.5 du 4000 a un soucis avec certaines nappes IDE !

En effet, les constructeurs ont par la suite bouché une pinoche pour que les utilisateurs ne puissent pas inverser le connecteur lors du branchement :

C'est la 19, une GND :

Comme il y a d'autres GND sur le connecteur, pas de soucis donc pour la dessouder :

Voilà, ça aussi, c'est fait sur mes deux cartes !

Le connecteur accepte maintenant les deux types de nappe sans broncher.
 

vendredi 11 mai 2012

Indivision + BVision (III)

Bon, voici plutôt une amélioration : plus besoin de modifier le Mediator en quoique ce soit maintenant avec ce qui suit.

Il suffit de reprendre un autre connecteur à 90° :

De dessouder les cinq pinoches du haut de l'ancien connecteur :

Et de ressouder le nouveau comme ceci :

Voilà, c'est mieux comme ça : Indivision AGA compatible avec la BVision et le Mediator.
 

Indivision + BVision (II)

Mouarf, cette fois c'est le Mediator qui ne rentre plus avec cette nouvelle inclinaison de 90° !!

Il y a fallut remonter le coffrage en plastique pour servir de marquage...

... afin de découper bien droit :

Il a fallut aussi râper d'un bon millimètre le support et rajouter un scotch :

Ainsi que raccourcir les pinoches du support d'un composant du Mediator :

Voilà, c'est bon maintenant :

Tout est bien qui fini bien !
  

Indivision + BVision (I)

L'indivision AGA n'est pas compatible avec la BVision :

Ca rentre pas : il est quand même incroyable que le designer de l'Indivision n'est pas pensé à cette éventualité. Le propre des extensions est d'ajouter des fonctionnalités en plus à l'Amiga, et non pas à avoir à choisir entre telle ou telle... Et le nouvel Indivision AGA MK2 semble avoir le même soucis...

Enfin bref, tonton Cosmos est là pour solutionner...

Il existe des connecteurs à 90° :

Il faut ensuite ôter le capuchon :

Et dessouder les 10 pinoches qui dépassent :

Voilà, le nouveau est soudé :

Rajoutons alors le capuchon original :

Et ça rulez :

C'est ric-rac : les deux bouzins cohabitent bien maintenant !

dimanche 6 mai 2012

A1200 en tour

Pour les A1200 en tour sans Mediator ou GRex, avec une BVision par exemple, il est nécessaire d'alimenter la carte en électricité pour qu'elle fonctionne !

J'ai déjà vu des branchements comme ça, peu esthétiques :

En fait, Commodore a tout prévu, juste vers le connecteur alimentation :

Voilà, il suffit de souder les câbles qui vont bien...

... à un connecteur ATX femelle :

Plus élégant comme cela !
   

Pile BlizzardPPC

La BlizzardPPC a elle aussi une pile soudée sur sa carte :

Des VL2020 rechargeables :

Un simple support se ressoude, sans modif ici :

Voilà, ça c'est fait !