VI. L'unité MAC▲
L'un des champs d'application privilégiés des ColdFire est le traitement
de signaux. Qu'il s'agisse de réseau, d'audio, de vidéo, d'images ou toute
autre chose, on a très souvent besoin de traiter des signaux analogiques
pour en faire des données numériques. Un certain nombre d'opérations
mathématiques dites transformées sont alors nécessaires.
On aura tous entendu parler de la Transformée de Fourier ou de la Transformée
Cosinus Discrète. Ces traitements nécessitent toujours des opérations
de la forme :
Somme des f(x) pour x = 0 à x = n
Tous les ColdFire sont doté d'une unité Multiply-Accumulate (dite unité MAC ou eMAC suivant les modèles), dédiée à ces traitements. Incluses sous forme de coprocesseur, leur jeu d'instruction s'utilise comme celui du processeur central.
Nous ne parlerons ici que de l'unité MAC du MCF5307 mais les autres ne présentent pas de grandes différences.
Cette unité présente l'intérêt d'être très rapide. Par exemple, le temps
d'exécution de MAC.W est d'un seul cycle, MAC.L prend trois cycles
(hors temps d'accès mémoire). Cette unité permet donc le traitement
de flux dans de très bonnes conditions.
L'unité MAC réalise les opérations suivantes :
- MAC : a = a + b*c
- MSAC : a = a - b*c
La multiplication peut être agrémentée d'un décalage d'un bit à droite ou à gauche.
L'unité MAC met en œuvre trois registres :
- L'accumulateur (RACC) : un registre de 32 bits contenant le résultat.
- Le Mask Register (RMASK) : un registre de 16 bits.
- Le Registre d'état (MACSR) : un registre de 32 bits dont seul les 8 bits de poids faible sont accessibles
Les déplacements suivants sont possibles :
Instruction | Effet |
---|---|
MOVE.L Dx,RACC | Place le contenu dun registre de donnée dans laccumulateur |
MOVE.L #cte,RACC | Place une constante dans laccumulateur |
MOVE.L RACC,Dx | Place le contenu de laccumulateur dans un registre de donnée |
MOVE.L Dx,MACSR | Place le contenu dun registre de donnée dans le registre détat |
MOVE.L #cte,MACSR | Place une constante dans le registre détat |
MOVE.L MACSR,CCR | Place le registre détat MAC dans le registre détat principal |
MOVE.L MACSR,Dx | Place le registre détat dans un registre |
MOVE.L Dx,RMASK | Copie le registre de donnée dans le masque |
MOVE.L #cte,RMASK | Copie une constante dans le masque |
MOVE.L RMASK, Dx | Copie le masque dans un registre de donnée |
Passons aux instructions MAC et MSAC. Leur utilisation est symétrique.
Elles existent sous plusieurs formes ( pour Rx tous les registres de donnée
et d'adresse sont possibles):
Instruction | Effet | Exemple | Temps d'exécution (Cycles) |
---|---|---|---|
MAC|MSAC.L|W Rx,Rx{<<|>>} | Multiplie source par destination. Le résultat est éventuellement décalé. Et ajouté à l'accumulateur | MAC.L D0,D1<< MAC.L A0,D2 |
1 pour W , 3 pour L |
MAC|MSAC.W Rx.U,Rx.L{<<|>>} | Multiplie les 16 bits de poids fort de la source par les 16 bits de poids faible de la destination. Le résultat est décalé et ajouté à l'accumulateur | MAC.W D0.U,D0.L>> MAC.W D0.U,D1.L | 1 |
MAC|MSAC.W Rx.U,Rx.L {<<|>>},(Ax)+,Rx | Multiplie les 16 bits de poids fort par les 16 bits de poids faible du registre. Le résultat est décalé et ajouté à l'accumulateur. En même temps, la valeur pointée par (Ax)+ est placée dans Rx | MSAC.W D0.U,D0.L,(A1)+,D0 | 2 |
Dans la dernière forme l'usage du masque
est nécessaire. Celui-ci détermine la façon dont doit boucler le programme.
- RMASK : 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
- Instruction : MAC.W D0.U,D0.L,(A1)+,D0
Lorsque A1 aura été incrémenté 2 puissance 5 fois (32), il reprendra sa valeur initiale.
Pour utiliser les instructions de branchement de type Bcc,
il faudra recopier le registre d'état MAC dans le registre d'état principal :
MOVE.L MACSR,CCR
La correspondance est la suivante :
- CCR : - - - X N Z V C
- MACSR : OMC S/U 0 0 N Z V C
Tous les tests portant sur N Z V C à savoir : MI, PL, EQ, NE, VC, VS peuvent donc être utilisé.
Le bit OMC (Overflow/Saturation Mode Control) influera sur le comportement
en fonction du bit S /U. Il évite de faire le tour.
S/U (Signed/Unsigned) permettra le comportement suivant :
- 0 = arithmétique signée. Si OMC est à 1 en cas de débordement positif RACC restera à 0x7FFFFFFF et à 0x80000000 pour un débordement négatif
- 1 = arithmétique non signée. Si OMC est à 1 en cas de débordement RACC saturera à 0x00000000 ou à 0xFFFFFFFF
L'exemple typique de mise en œuvre de l'unité MAC est la création
d'un filtre à réponse impulsionnelle finie très répandu dans le
domaine du traitement du son. Il s'agit d'un moyen de " lisser "
un signal. On multiplie une suite de valeurs issue d'une acquisition
analogique par des cœfficients particuliers. On additionne ensuite les valeurs
traitées qu'on restitue le plus souvent sous la forme d'un nouveau signal
(par exemple dans un équaliseur).
Ici les valeurs seront stockées dans un tableau pointé par A1. Le coefficient sera dans les 16 bits
de poids fort (.U), la donnée dans les 16 bits de
poids faible. On utilisera D0 comme tampon et D2
pour retourner le résultat .
org $20000
init: nop
clr.l D0
clr.l D1; D1 sera notrre compteur de boucle
move.l #$FFEF,rmask ; notre tableau fait 32 mots longs
move.l #$FFFFFFC0,macsr ; on travaille en non signé avec
; gestion du débordement.
; les F ne servent à rien (zone protégée).
debut: clr.l D2
move.l #32,D1
move.l #0,racc ; mise à zero de l'accumulateur
move.l (A2)+,D1 ; mise en place de la premiere valeur
boucle: mac.w D0.U,D0.L(A0)+,D0
subi.l #1,D1
bne boucle
result: move.l racc,D2
*ici on va chercher d'autres valeurs ...*
bra debut
fin: nop
Il ne faut pas pour autant négliger l'utilisation de cette unité dans des situations moins évidentes. Le gain de performance est parfois non négligeable. Pour des choses telles que le schéma de Horner ou les calculs de puissance, il est bon de se poser la question.