[ASM 68000] Mesurer les cycles d’un code

Forum Amiga Coding [ASM 68000] Mesurer les cycles d’un code

  • Ce sujet contient 10 réponses, 4 participants et a été mis à jour pour la dernière fois par donamiga, le il y a 4 années et 8 mois.
  • Créateur
    Sujet
  • #102244
    Arnaud.68K
      • Level 3
      • Messages : 69

      Bonjour,

      L’un de vous sait il comment mesurer le nombre de cycles d’un programme en assembleur (68000) sur Amiga.

      Après quelques recherches, j’ai pas trouvé de registre qui va bien, la mesure de la position du balayage écran étant une solution mais si on pouvait compter les cycles ce serait top.

      Mon but est d’optimiser du code et d’avoir une mesure factuelle.

      Merci pour votre aide

       

      A500 + 512k, adepte du SM attention avec un A devant !

    Affichage de 10 réponses de 1 à 10 (sur un total de 10)

    Partager sur vos réseaux sociaux préférés :
    Facebooktwitterredditpinterestlinkedintumblrmail

    • Auteur
      Réponses
    • #102245
      slack
        • Level 7
        • Messages : 465

        Bonjour Arnaud.68000,

        Que veux-tu dire par mesurer le nombre de cycles d’un programme ?

        Dans la documentation motorola, il y a le nombre de cycles d’horloge que prend chaque instruction.

         



        #102246
        Arnaud.68K
          • Level 3
          • Messages : 69

          Merci Slack,

          Ce que j’entends par mesurer le nombre de cycles (horloge) c’est si j’exécute un code du type :

          moveq #0,d1

          move.w #25,d0

          _Boucle:

          Add.l #1,d1

          dbf d0,_Boucle

          Il va consommer un certains nombre de cycles horloges.

          Si je remplaçant add.l par addq, il va peut être consommer moins de cycles.

           

          Me référer à une table de correspondance des cycles utilisés par instruction peut être fastidieux surtout si le code à des boucle et des tests.

          Ce qui serait top, ce serait d’avoir un truc du type :

          t1=timer

          exécution du code

          t2=timer-t1

          Pour cela je sais pas si il existe un registre sur l’A500 qui s’incrémente en fonction des cycles d’horloge ( ou une technique similaire)

           

           

           

          A500 + 512k, adepte du SM attention avec un A devant !

          #102254
          donamiga
            • Level 5
            • Messages : 249

            timer CIA (B ou TOD)
            voir code de ross :

            http://eab.abime.net/showpost.php?p=1199574

            https://eab.abime.net/showthread.php?t=99238

            sujet:

            http://eab.abime.net/showthread.php?t=88383

            peut etre que ça peut aider

            j’allais oublier le tuto de Jel sur les CIA :

             

            #102264
            lexomil
              • Level 3
              • Messages : 80

              Salut !

              si ton code tient dans une VBL le plus simple reste quand même de changer la couleur du fond au début et à la fin de ta fonction. ça te donnera pas le nombre de cycles écoulés (pour ça rien de mieux que de le faire à la main), mais tu verra rapidement si un changement te fais gagner ou perdre du temps.

              #102277
              slack
                • Level 7
                • Messages : 465

                @ Arnaud.68000,

                Voici quelques informations et demandes de renseignements pour mieux t’aider.

                 

                Les tables fournies par Motorola pour le processeur 68000 permettent de compter facilement les cycles utilisés par du code aussi simple que :

                moveq #0,d1

                move.w #25,d0

                _Boucle:

                Add.l #1,d1

                dbf d0,_Boucle

                Les boucles ne compliquent pas le calcul.

                Par contre, je ne connais pas de tables pour les processeurs à partir du 68020.

                 

                 

                Que veux-tu faire ? Coder une boucle d’attente ? Optimiser du code ?

                 

                 

                As-tu besoin d’une mesure précise du temps écoulé entre les deux lectures du timer ?

                Pour une mesure grossière, tu peux laisser le multitâche et les interruptions. Sur un système non chargé, tu répète les mesures et tu prends la plus courte.

                Pour une mesure précise, ton code ne doit pas être interrompu entre les deux lectures du timer. Je pense qu’il faut interdire les interruptions avant de la première lecture et les autoriser après la seconde. Attention, tu risques de perturber le fonctionnement du système d’exploitation si tu coupes les interruptions pendant une durée trop longue.

                 

                Tu peux regarder les 2 articles suivants :

                http://obligement.free.fr/articles/assembleur_ressources.php

                http://obligement.free.fr/articles/c_cia.php

                #102345
                Arnaud.68K
                  • Level 3
                  • Messages : 69

                  Bonjour,

                  Merci pour vos réponses

                  @DonAmiga & Slack : pas mal les liens je vais prendre le temps de regarder tout ça

                  @Lexomil : oui j’ai déjà une routine pour visualiser le cycle VBL (quand ça rentre dedans), mais des fois des changements minimes ne se voient pas facilement avec le VBL

                  @Slack : oui je souhaite chercher une mesure précise de mon code pour voir les effets de mes optimisations (l’idée est aussi la démarche intellectuelle) et parfois on parle de quelques cycles localement ici et là ou parfois de code assez long.

                  Je me souviens d’avoir fait (il y a 25 ans)  un code pour pivoter  3 fois de 90° des lettres 32×32 ayant différents angles 0°, 10 ,20,30,40,50,60,70,80°, en vu de faire un scroll rotatif 360°. Mon code prenait 3 à 4 secondes en pre-traitement. Je pense que ce code (si je le retrouve) est largement optimisable.  C’est pour cela qu’une mesure serait la bienvenue.

                  Sinon il y a bien easy68k, un assembleur 68000 sur PC, qui donne le nombre de cycles utilisés après execution mais il ne tient pas compte de l’env Amiga.

                   

                  Je vais regarder vos suggestions, merci encore

                  A500 + 512k, adepte du SM attention avec un A devant !

                  #102351
                  lexomil
                    • Level 3
                    • Messages : 80

                    Ha ok, c’est vraiment pour mesurer des routines assez « lourdes », dans ce cas je penses que le plus adapté c’est en utilisant les timers du système.

                    Jette un oeil du coté de la lowlevel.library (ROM 3.1) et de la méthode ElapsedTime ça pourrait te suffire, la granularité est de l’ordre de la microseconde donc à même d’évaluer une différence entre deux implémentations de ta routine.

                    #102354
                    donamiga
                      • Level 5
                      • Messages : 249

                      bin oui, c’est pour ça que j’ai mis le lien de la routine de ross: http://eab.abime.net/showpost.php?p=1199574

                       

                      #102430
                      Arnaud.68K
                        • Level 3
                        • Messages : 69

                        Voici en synthèse les 2 codes issus de vos suggestions, ajustés et complémentaire (pour A500)

                        L’un mesure le nombre de cycles pour des routines courtes inférieures au temps du faisceau horizontal.

                        L’autre mesure des routines plus conséquentes en ms (convient moins à un nombre d’instructions faibles)

                        Code pour mesurer des cycles :

                        **********************************************************
                        ;Code pour mesurer les cycles d’un code inferieur au temps de trace d’une ligne
                        ;Calibre pour A500
                        ;
                        ;Resultat dans D0 = nombre de cycles, D1=Start, D2=Stop
                        ;
                        ;Sources :
                        ;http://eab.abime.net/showpost.php?p=1199574
                        ;http://eab.abime.net/showthread.php?t=88383

                        section code,code

                        DMACONR=$002
                        VHPOSR=$006
                        INTENA=$09A
                        INTENAR=$01C
                        INTREQ=$09C
                        INTREQR=$01E
                        DMACON=$096

                        ;———- Macros ———-

                        ;Attendre le Blitter
                        ;Quand la seconde opérande est une adresse, BTST ne permet de tester que les bits 7-0 de l’octet pointé,
                        ;mais traitant la première opérande comme le numéro du bit modulo 8,
                        ;BTST #14,DMACONR(a5) revient à tester le bit 14%8=6 de l’octet de poids fort de DMACONR,
                        ;ce qui correspond bien à BBUSY…

                         

                        WAITBLIT: MACRO
                        _waitBlitter0\@
                        btst #14,DMACONR(a5)
                        bne _waitBlitter0\@
                        _waitBlitter1\@
                        btst #14,DMACONR(a5)
                        bne _waitBlitter1\@
                        ENDM

                        start:
                        clr.l d0
                        lea $DFF000,a5

                        move.w #$4000,INTENA(a5) ;INTENA INTEN off
                        move.w #$0200,DMACON(A5) ;DMACON DMAEN off

                        WAITBLIT

                        move.l #$DFF006,a0 ;VHPOSR
                        WaitRaster:
                        cmp.b #$00,(a0) ;test if Hpos=0
                        bne WaitRaster

                        move.w (a0),d1 ;start_value

                        ;— Code à tester —
                        ;nop ;unknown_cycles to count
                        move.l #15,D5
                        ;— FIN CODE —

                        move.w (a0),d2 ;end_value (we know this takes $00000004)
                        move.w d2,d0 ;end_value to d2
                        sub.w d1,d0 ;end_value – start value
                        sub.w #$4,d0 ;d2 – $00000004
                        add d0,d0 ;d2 x 2 = unknown_cycles

                        Fin:
                        move.w #$8200,DMACON(A5) ;DMACON DMAEN ON
                        move.w #$C000,INTENA(a5) ;INTENA INTEN ON
                        rts

                        **********************************************************

                         

                        Code pour mesurer un temps en ms

                        **********************************************************
                        ;Code pour mesurer des codes d’execution assez longs en ms
                        ;car le temps de la sub de VPOS Stop est inclus
                        ;Calibre pour A500
                        ;
                        ;resultat dans D0 = ms
                        ;
                        ;Sources modifie :
                        ;code speed tester by ross for EAB members
                        ;http://eab.abime.net/showpost.php?p=1199574
                        ;
                        PAL = 15625
                        NTSC = 15734
                        ConfigEcran=PAL

                        CIAA =$BFE001
                        CIAB =$BFD000
                        PRA =$000 ;/DTR /RTS /CD /CTS /DSR SEL POUT BUSY
                        prb =$100 ; /MTR /SEL3 /SEL2 /SEL1 /SEL0 /SIDE DIR /STEP
                        DDRA =$200 ;Direction for Port A (BFD000);1 = output (set to 0xFF)
                        DDRB =$300 ;Direction for Port B (BFD100);1 = output (set to 0xFF)
                        TALO =$400 ;CIAB timer A low byte (.715909 Mhz NTSC; .709379 Mhz PAL)
                        TAHI =$500 ;CIAB timer A high byte
                        TBLO =$600 ;CIAB timer B low byte (.715909 Mhz NTSC; .709379 Mhz PAL)
                        TBHI =$700 ;CIAB timer B high byte
                        TODLO =$800 ;Horizontal sync event counter bits 7-0
                        TODMID =$900 ;Horizontal sync event counter bits 15-8
                        TODHI =$A00 ;Horizontal sync event counter bits 23-16
                        SDR =$C00 ;CIAB serial data register (unused)
                        ICR =$D00 ;CIAB interrupt control register
                        CRA =$E00 ;CIAB Control register A
                        CRB =$F00 ;CIAB Control register B

                        section code,code

                        start:
                        lea $DFF000,a5
                        lea CIAB,a4

                        move.w #$4000,$9A(a5) ;INTENA INTEN off
                        move.w #$0200,$96(A5) ;DMACON DMAEN off
                        BltWait:
                        move.w 2-$9a(a5),d0 ; blitter wait
                        add.w d0,d0
                        bmi.b BltWait

                        ;if you need to init/move/setup packed data
                        jsr init

                        bsr.b CIAtoD ; start time
                        move.l d0,d2

                        jsr Code ; GO!

                        bsr.b CIAtoD ; end time

                        sub.l d2,d0 ; elapsed

                        ;15625=PAL 15734=NTSC
                        divu.w #ConfigEcran*256/1000,d0 ; d0=ms (pal_hfreq*scale_down/granularity)
                        bvs.b OverFlow ; overflow?, something over specs..
                        and.l #$FFFF,d0
                        bra fin

                        OverFlow:
                        move.l #$EEEEEEEE,D0 ;erreur
                        Fin:
                        move.w #$8200,$96(A5) ;DMACON DMAEN ON
                        move.w #$C000,$9A(a5) ;INTENA INTEN ON

                        rts

                        CIAtoD:
                        move.b TODHI(a4),d0 ;$200(a4),d0
                        swap d0
                        move.b TODMID(a4),d0 ;$100(a4),d0
                        lsl.w #8,d0
                        move.b TODLO(a4),d0
                        lsl.l #8,d0 ; scale up (counter wrap proof)
                        rts

                        Init: ; insert your init code here (not timed)
                        rts

                        Code: ; insert your code here (a500 is the target)
                        move.l #200000,d1
                        .loop
                        move.w d1,$dff180
                        subq.l #1,d1
                        bne.b .loop
                        rts
                        **********************************************************

                        Pour aller plus loin

                        A l’occasion je vais voir si on peut faire des 2 codes un code générique qui mesure à la fois les cycles et le temps d’exécution quelque soit la taille de la routine à évaluer.

                        Mais si quelqu’un veut se pencher avec moi sur le sujet j’ai rien contre ;-)

                        Encore merci pour votre aide.

                         

                        A500 + 512k, adepte du SM attention avec un A devant !

                        #102436
                        donamiga
                          • Level 5
                          • Messages : 249

                          ;BTST #14,DMACONR(a5) revient à tester le bit 14%8=6 de l’octet de poids fort de DMACONR,
                          ;ce qui correspond bien à BBUSY…

                          d’ailleurs on ecrit : btst #6,DMACONR(a5)

                          déjà pas besoins de 2 sources differents pour les 2 methodes, mettre les 2 routs dans 1 source avec le code à tester

                          utiliser des reg differents pour calcul et sauvegarde des resultats de chaque test

                          ajouter pour sauver ces regs avant l’execution du code:
                          Code:
                          movem.l d0-d7/a0-a6,-(sp) ; tous ou registres à sauver seulement

                          movem.l (sp)+,d0-d7/a0-a6
                          rts

                           

                        Partager sur vos réseaux sociaux préférés :
                        Facebooktwitterredditpinterestlinkedintumblrmail
                        Affichage de 10 réponses de 1 à 10 (sur un total de 10)
                        • Vous devez être connecté pour répondre à ce sujet.