Séance 6

Transcription

Séance 6
DSP
Plan








Présentation générale du domaine DSP
Le choix du DSP
L’architecture interne du 21061
Jeu d’instruction
Registres d’état du DSP
Accès mémoire et pipeline
Les interruptions
Assembleur Sharc
I - Présentation générale
Flexibilité Vs performances
Flexibilité
Proc.
généraliste
Coût de conception
µ. Contrôleur
DSP
ASIP
Performances-1
Idem avec l’efficacité énergétique
Générations de DSP
La R&D autour des DSP en France
II – Le choix des DSP
Comparaison DSP / Proc généraliste
Sharc
Pentium
critère
60-66 MHz
2-3 GHz
Fréquence
1 cycle/inst
2-3 cycles/inst
Add
1cycle/inst
1-10 cycles/inst
Mul
1 cycle/inst
20* plus vite =
20*60 = 1,2GHz
~20 cycles/inst
(MMX)
MAC :
Lecture
échantillon
Lecture coef filtre
Mul
ACC
Calcul prochaine @
Comparaison DSP / Proc généraliste
Sharc
Pentium
critère
Mem on Chip
Bus système
100-166MHz
(Pentium = 100MHz)
Cache :
PCI = 66 MHz
ISA = 8 MHz
…
Bus + Mem
Unités de calcul //
3 cycles/inst
FIR
Questions…


Pourquoi le DSP n’a-t-il pas alors remplacé les
CISC ?
 Compatibilité
 Performance limité sur applis générales
 Espace adressable réduit sur DSP
Futur du DSP :
 TMS 320C54 ou BlackFin
 = DSP + RISC
Harvard / Von Neuman



Les accès mémoire sont découplés
 Accès instructions
 Accès données
Harvard :
 2 accès // par instruction
 2 fois + rapide
 Au prix d’une architecture beaucoup plus complexe :
tout est doublé
Von Neumann
 Accès mémoire séquentiels
 Plus flexible
 Archi plus simple
III – Architecture Sharc
Les concurrents



Texas Instruments
 TMS320C54x, TMS320C6x…
 De 20 à 400 MIPS en mono core
 Plus de 2000 MIPS en multi core
 Plus souvent en virgule fixe 16 bits
Motorola
 DSP 56x00
Analog Device
 1er DSP, 1980, ADSP-2100
 3 unités de calculs // : instructions multi-fonctions
 1990, famille Sharc (Super Harvard Architecture)
 2106x, 66MFLOPS
La carte utilisée en TP – EZ-KIT Lite
UART
CODEC
Caractéristiques de l’architecture Sharc








Architecture de type Harvard (bus Data 40 bits + Bus Program 48
bits)
Cache 32 instructions
16 registres de données (40 bits)
Structure pipeline à 3 étages (F + D + E)
Parallélisme d’instructions (sous certaines conditions)
Unité de calcul avec multiplieur, additionneur en virgule fixe ou
flottante et registre à décalage
2 unités de génération d’adresses (DAG) avec buffers circulaires
(convolutions) et adressage « bit-reversed » (FFT)
Gestion câblée des boucles
Le pipeline
instruction i
instruction i+1
lecture
décodage exécution
lecture
décodage exécution
lecture
instruction i+2
en permanence !
décodage exécution
temps
Architecture interne du 21061
CACHE
MEMORY
32 x 48
DAG 1
8 x 4 x 32
DAG 2
8 x 4 x 24
JTAG TEST &
EMULATION
PROGRAM
SEQUENCER
PMA BUS
24
DMA BUS
32
PMD BUS
48
DMD BUS
40
FLAGS
TIMER
PMA
DMA
PMD
BUS CONNECT
FLOATING & FIXED-POINT
MULTIPLIER,
FIXED-POINT
ACCUMULATOR
DMD
REGISTER
FILE
16 x 40
32-BIT
BARREL
SHIFTER
FLOATING-POINT
& FIXED-POINT
ALU
Vue système
Benchmarks
Principe d’utilisation en TP
Host PC
Binaire
LDF
Étapes de traitement






Acquisition du signal audio analogique
Conversion analogique-numérique
Réception des échantillons (DMA, liaison série)
Lecture échantillons en mémoire
Traitement des échantillons
Envoie des résultats (DMA, liaison série)
Mémoire
Organisation mémoire




Architecture de Harvard modifiée
 La mémoire peut contenir soit des instructions soit
des données
Memoire interne
 (0x0000 0000 -> 0x0007 FFFF)
 Registres du proc
 + IO registers
 + 2 blocs 0 et 1 de 0,5 Mbits = 16K*32 bits
Mémoire partagée
 (0x0008 0000 => 0x003F FFFF)
 Bus externe = 6 Sharc
Mémoire externe
 (0x0040 0000 => 0xFFFF FFFF)
Memory Map
Organisation mémoire interne
0x 0000 0000
256 registres interne
0x 0000 0100
Réservé
Accès 32 ou 48 bits
Bloc0
Adressage normal
Bloc 1
Adressage normal
0x 0002 0000
0x 0002 4000
0x 0002 8000
Alias Bloc 1
Accès 16 bits
Bloc 0
Adressage court
Bloc 1
Adressage court
Alias Bloc 1
Adressage court
0x 0004 0000
0x 0004 8000
0x 0005 0000
0x 0008 0000
Bus d’adresse

Accès // en 1 cycle sauf si
même bloc
3 bus :
 PM (programmes)


24 bits d’@
48 bits de données (inst)
 DM


Fetch
16Mmots
(data)
32 bits d’@
32/40 bits de données
Read/Wr
4Gmots
 IO


17 bits d’@
48 bits de données
 PX

Pont entre le bus PM et DM
6 contrôleurs DMA
128 Kmots
Blocs - accès par taille de mots variables

Harvard modifiée : chaque bloc peut contenir code et
données
Blocs à double accès : accès DMA par bus IO sur un
port + accès PM/DM sur 2e port
Bloc =
 8 colonnes de 4K mots de 16 bits
 Un accès mot de 16, 32, 40 ou 48 bits
8 colonnes
 1 instruction = 48 bits
Accès 40/48 bits

Accès 32 bits

Accès 16 bits



4Kmots
Accès 40 ou 48 bits


Les données de 40 bits sont stockées dans de
mots de 48 cadrées sur les MSB
Un mot est donc stocké sur 3 colonnes dont
seules les 6 première sont utilisables => 8K
mots de 40 ou 48 bits
c0
c1
c2
H
M
L
0x2 0000
B0
0x2 1000
0x2 0FFF
0x2 1FFF
0x2 4000
0x2 5000
B1
0x2 4FFF
H
M
L
c3
c4
c5
L
H
M
c6
c7
-
-
-
-
0x2 3FFF
L
0x2 5FFF
0x2 3000
H
M
Accès 32 bits

Un mot de 32 est donc stocké sur 2 colonnes
=> 16K mots de 32 par bloc
c0
c1
H
L
0x2 0000
B0
0x2 1000
c2
c3
H
L
0x2 2000
c4
c5
H
L
0x2 3000
0x2 0FFF
0x2 1FFF
0x2 2FFF
0x2 3FFF
0x2 4000
0x2 5000
0x2 6000
0x2 7000
B1
0x2 4FFF
H
L
H
0x2 5FFF
L
H
0x2 6FFF
L
0x2 7FFF
c6
c7
H
L
H
L
Accès 16 bits (adressage court)

Les adresses des accès 16 bits sont celles des
accès 32 bits multipliées par 2 (cf. organisation
mémoire)
 Avec le bit LSB à 0 pour lire les 16 bits LSB
(colonnes 1, 3, 5, 7)
 et à 1 pour lire les MSB des mots de 32 bits
(colonnes 0, 2, 4, 6)
Exemple – contenu du bloc1
@
0
1
2
3
4
5
6
7
0x000
140A
0004
0000
7FA1
1301
0002
A52D
05DF
0x001
142A
0000
0020
014B
063E
0002
BC45
69C3
0x002
0FDE
0131
2D91
AC05
A632
4593
F8EC
8726
…
Accès 48 bits
Adresse
Mot lu - H
M
L
0x2 4000
140A
0004
0000
0x2 4001
142A
0000
0020
1301
0002
7FA1
…
0x2 5000
Accès 32 bits
Adresse
Mot lu - H
L
0x2 4000
140A
0004
0x2 4001
142A
0000
0000
7FA1
…
0x2 5000
Accès 16 bits
Adresse
Mot
Adresse
mot
0x4 8000
0004
0x4 A000
7FA1
0x4 8001
140A
0x4 A001
0000
0FDE
0x4 E000
05DF
…
0x4 8005
Accès à un bloc avec des formats différents

Il est possible de mélanger dans un même bloc
des instructions de 48 bits et des données de 32
bits
 Toujours placer les données après les
instructions !
 Toujours placer les données à partir d’une
colonne paire (adresses multiples de 4K)!
‘Mapping’ de l’exécutable dans l’espace
mémoire - segments




MEMORY
{
isr_table { TYPE(PM RAM) START(0x00020000) END(0x000200FF) WIDTH(48) }
seg_init { TYPE(PM RAM) START(0x00020100) END(0x0002010F) WIDTH(48) }
b0_code { TYPE(PM RAM) START(0x000200e0) END(0x00020fff) WIDTH(48) }
b0_data { TYPE(PM RAM) START(0x00022800) END(0x00022cff) WIDTH(32) }
b0_idat { TYPE(DM RAM) START(0x00022d00) END(0x00022fff) WIDTH(32) }




b1_code { TYPE(PM RAM) START(0x00024000) END(0x00024Bff) WIDTH(48) }
b1_data { TYPE(DM RAM) START(0x00024C00) END(0x00024Eff) WIDTH(32) }


seg_heap
seg_stak



{ TYPE(DM RAM) START(0x00026000) END(0x000266ff) WIDTH(32) }
{ TYPE(DM RAM) START(0x00026700) END(0x00026Aff) WIDTH(32)}
}
Configuration du type d’accès
Résultat de l’édition de lien
0xCF28
0x0000
File2.o
Image exécutable
‘loader’ section
‘loader’ section
Code/data (file1.o)
Code/data
.text section
.text section
code
.text (file1.o)
.text (file2.o)
.bss section
data
code
0x0000
File1.o
.text section
code
.data section
Init data
Bibliothèque.lib
.data section
.data (file1.o)
.data (file2.o)
.bss section
.bss (file1.o)
.bss (file2.o)
.data section
Init data
.bss section
data







































}}
Sections de code
ROCESSOR p0{
LINK_AGAINST( $COMMAND_LINE_LINK_AGAINST) // Other object files to link against.
OUTPUT( $COMMAND_LINE_OUTPUT_FILE )
// Resulting executable file name.
SECTIONS{
interupt_vector_table
{
INPUT_SECTIONS( $OBJECTS(seg_rth) $LIBRARIES(seg_rth))
} >isr_table
seg_init
{
INPUT_SECTIONS( $OBJECTS(seg_init) $LIBRARIES(seg_init))
} >seg_init
block0_program_code
{
INPUT_SECTIONS( $OBJECTS(seg_pmco) $LIBRARIES(seg_pmco))
} >b0_code
block1_program_code
{
INPUT_SECTIONS( $OBJECTS(seg_pmco) )
} >b1_code
block0_data
{
INPUT_SECTIONS( $OBJECTS(seg_pmda) $LIBRARIES(seg_pmda))
} >b0_data
block1_data
{
INPUT_SECTIONS( $OBJECTS(seg_dmda) $LIBRARIES(seg_dmda))
} >b1_data
stackseg
{
ldf_stack_space = .;
ldf_stack_length = MEMORY_SIZEOF(seg_stak);
} > seg_stak
heap
{
ldf_heap_space = .;
ldf_heap_end = ldf_heap_space + MEMORY_SIZEOF(seg_heap) - 1;
ldf_heap_length = ldf_heap_end - ldf_heap_space;
} > seg_heap
Modes d’adressage
Modes d’adressage


L’accès à la mémoire est utilisé avec :
 DM(adr) ou PM(adr) désigne l’accès mémoire par
les bus DM/PM à l’adresse adr
Adressage direct
 DM (0x24000) = R0;
// accès par bus DM
 PM (0x24001) = R1;
//accès par bus PM
Adressage indirect





Le Sharc dirpose de 2 jeux de registres DAG1 et DAG 2
(Data Adress Generator) permettant l’adressage indirect
Cf. schéma suivant
Chaque jeu de registre est doublé (shadows registres)
DAG1 est relié au bus DM, 32 bits
 Les registres 0 à 7 sont donc de 32 bits
DAG2 est relié au bus PM, 24 bits
 Les registres 8 à 15 sont donc de 24 bits
Les DAGs
DAG1
(32 bits)
I0
I1
I2
I3
I4
I5
I6
I7
M0
M1
M2
M3
M4
M5
M6
M7
L0
L1
L2
L3
L4
L5
L6
L7
B0
B1
B2
B3
B4
B5
B6
B7
registres d’index
registres modifieurs
registres longueur et base
(buffers circulaires)
registres principaux
registres shadow
Les DAGs
DAG1
(32 bits)
I0
I1
I2
I3
I4
I5
I6
I7
DAG2
(24 bits)
I8
I9
I10
I11
I12
I13
I14
I15
M0
M1
M2
M3
M4
M5
M6
M7
M8
M9
M10
M11
M12
M13
M14
M15
L0
L1
L2
L3
L4
L5
L6
L7
L8
L9
L10
L11
L12
L13
L14
L15
B0
B1
B2
B3
B4
B5
B6
B7
B8
B9
B10
B11
B12
B13
B14
B15
registres principaux
registres shadow
registres principaux
registres shadow
DAGs



Ix registres d’index
Chaque registre Ix peut être associé à un offset
sous forme
 D’un immédiat
 Ou d’un registre My (modificateur)
2 modes :
 Pré incrémenté sans modification de l’index
 Post incrémenté avec modification
Exemple
Post
 R0 = 0xA0A0A0A0;
 M6 = 2;
 I0 = 0x0002 4000;
 DM(I0, M6) = R0; // I0 est modifié après accès mémoire et
devient 0x0002 4002
Pré
 R0 = 0xA0A0A0A0;
 I0 = 0x0002 4000;
 DM(0xFFFF FFFF, I0) = R0; // accès mémoire à l’@
0x23FFF (+ (-1)) et I0 reste à la valeur 0x0002 4000
Adressage circulaire






Utilisation des registres Bx et Lx associés à un reg. Ix
Bx = Base de buffer
Lx = Longueur à initialiser à une valeur non nulle
Lorsque Bx est initialisé, le Ix correspondant est
automatiquement initialisé à la même valeur
Ix est utilisé en indirect normal avec 2 restrictions :
 L’offset (My ou Imd) doit être inférieur à Lx
 Le mode pré incrémenté ne peut être utilisé
Une interruptions indicative est généré au dépassement
lorsque Ix est ramené circulairement
Exemple





Adressage de buffers circulaires :
B0 = 0x00024000,
//init. de B0 et I0
L0 = 8;
//init. longueur du buffer
M1 = 1;
//init. modifieur
R0 = DM(I0,M1);
//si IO>B0+L0 alors
// I0=B0
L’utilisation des buffers circulaires
B0
L0
longueur et
base du tableau
I0
pointeur sur
le tableau
Les mécanismes de déplacement du
pointeur, de test de la fin du tableau
et de ré-initialisation sont câblés
dans les DAG...
Modes d’adressage
Codes Conditions
Pipeline
Pipeline


Le sharc dispose d’un pipeline à 3 étages
 3 instructions sont en cours de traitement
 1 instruction se termine à chaque cycle
Le fonctionnement idéal est perturbé lorsque :
 Une instruction N utilise le bus PM pour accéder
à la mémoire. Il y a alors conflit avec la phase de
fetch de l’instruction N+2.

Le compilateur ajoute un cycle d’attente (NOP)
 L’instruction
N provoque une rupture de
séquence (JUMP, CALL).
 L’instruction N+1 adresse la mémoire avec un
registre de DAG modifié par l’instruction N
exemple d’utilisation du cache
0x20000:
...
0x20001:
R0 = PM(0x23013);
// lecture sur bus PM
0x20002:
R2 = R0 + R1;
// opération arithmétique
0x20003:
DM(0x24000) = R0;
// écriture sur le bus DM
0x20004:
...
0x20005:
...
exemple d’utilisation du cache
(1ère occurrence)
Execute
Execute
Decode
Decode
Execute
Fetch
Fetch
Execute
Decode
Lecture data sur leDecode
bus
Fetch
PM
Fetch
Decode
Recherche sur le bus PM
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Les deux opérations nécessitent deux
accès simultanés sur le même bus !
exemple d’utilisation du cache
(1ère occurrence)
....
....
Fetch + Mise en cache
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(1ère occurrence)
Execute
Decode
....
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(1ère occurrence)
Execute
Decode
Fetch
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(1ère occurrence)
Execute
Decode
Fetch
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(2ème occurrence)
Execute
Execute
Decode
Decode
Execute
Fetch
Fetch
Execute
Decode
Decode
Fetch
Fetch
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(2ème occurrence)
Execute
Decode
Fetch
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(2ème occurrence)
Execute
Decode
Fetch
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
exemple d’utilisation du cache
(2ème occurrence)
Execute
Decode
Fetch
0x20000:
...
0x20001:
R0 = PM(0x23013);
0x20002:
R2 = R0 + R1;
0x20003:
DM(0x24000) = R0;
0x20004:
...
0x20005:
...
Cache instructions :
00 0
01 0
03 1 DM(0x24000) = R0
Conclusion sur l’utilisation du cache
Le pipeline entraîne l’ajout d’un cycle
supplémentaire à chaque fois qu’un conflit
d’accès au bus est détecté.
La présence du cache d’instruction ne permet
de résoudre le conflit
qu’à la deuxième occurrence seulement.
⇒ Un code optimisé (en vitesse) ne contient de
conflits de bus qu’à l’intérieur des boucles...
problème 2 : Le cas des dépendances de données


Lors de la phase de décodage de l’instruction, le processeur prépare
l’accès aux données et calcule l’adresse des accès en mémoire.
Il y a conflit de dépendance de données lorsqu’une instruction effectue
un accès en mémoire avec un registre d’index (Ix) modifié lors de
l’instruction précédente.
Execute
0x20002:
Decode
0x20003:
0x20004:
I0 = 0x23013;
// Init index I0
R2 = DM(I0,M0)
// accès avec IO
...
La modification de l’index I0 et le calcul
de l’adresse avec I0 nécessiteront deux cycles
au lieu d’un !
problème 3 : Le cas des ruptures de séquence
Execute
R0 = R1 + R2;
Execute
Decode
R2 = lshift R2 by 12;
Decode
Execute
Fetch
CALL
Fetch
!!
!!
routine;
routine:
R5 = 1;
R5 = 0;
R9 = min(R5, R2);
I8 = tableau;
...
...
problème 3 : Le cas des ruptures de séquence
R0 = R1 + R2;
R2 = lshift R2 by 12;
CALL
NOP
!!
routine;
routine:
Fetch
R5 = 1;
R5 = 0;
R9 = min(R5, R2);
I8 = tableau;
...
...
problème 3 : Le cas des ruptures de séquence
R0 = R1 + R2;
R2 = lshift R2 by 12;
CALL
routine;
R5 = 0;
NOP
I8 = tableau;
...
routine:
Decode
Fetch
R5 = 1;
R9 = min(R5, R2);
...
problème 3 : Le cas des ruptures de séquence
R0 = R1 + R2;
R2 = lshift R2 by 12;
CALL
routine;
R5 = 0;
I8 = tableau;
...
routine:
Execute
R5 = 1;
Decode
R9 = min(R5, R2);
Fetch
...
⇒ Deux cycles sont perdus (idem lors du retour de la routine) !!
solution : Utilisation des branchements retardés
Execute
Decode
Execute
CALL
Execute
Fetch
Decode
R0 = R1 + R2;
Execute
Decode
Fetch
Fetch
Decode
R2 = lshift R2 by 12; Execute
Fetch
Decode
R5 = 0;
routine (DB);
I8 = tableau;
routine:
Fetch
R5 = 1;
R9 = min(R5, R2);
...
...
⇒ Pas de perte de cycles au moment du branchement
(idem lors du retour du sous-programme) !
INCONVENIENT : si la rupture de séquence se trouve à
l ’intérieur d’une boucle de moins de trois instructions,
le branchement retardé est impossible !
2.4.3) Les boucles câblées


Dans les applications de traitement du signal, la plupart des
traitements font intervenir des calculs sur des structures de
données de taille connue à l’avance (convolutions, matrices, FFT,
etc).
Pour optimiser ces calculs, le processeur DSP possède un
mécanisme de boucles câblées (hardware loops) qui accélère les
tests de fin de boucle.
R4 = 8;
MRF = 0;
test de fin
LCNTR = 8, DO _loop UNTIL LCE;
R0 = DM(I0,M0);
longueur de la boucle
R5 = lshift R0 by R4;
_loop: MRF= MRF + R5*R5;
...
corps de la boucle
R4 = 8;
MRF = 0;
LCNTR = 8, DO _loop UNTIL LCE;
R0 = DM(I0,M0);
A l’exécution : le compteur
est initialisé, les adresses de fin
et de début sont empilées dans
des piles hardware
R5 = lshift R0 by R4;
_loop: MRF= MRF + R5*R5;
...

Au cycle Fetch : le compteur est décrémenté,
la condition de fin est testée et la prochaine
adresse est calculée (adresse de début ou
prochaine adresse)
Pour la réalisation de boucles imbriquées, le processeur dispose de
piles matérielles (hardware) de profondeur 6 (6 boucles imbriquées
maximum) :
Pile des compteurs de programme,
Pile des compteurs de boucle,
Pile des adresses de fin de boucle.
problème 1 : Le pipeline et les boucles câblées
R4 = 32;
La condition est un résultat nul
DO _loop UNTIL EQ;
R0 = DM(I0,M0);
_loop: R5 = R0 - R4;
...

Au cycle Fetch : l’indicateur est celui résultant
de l’exécution de R4=32 (pour le premier
passage)...
Pour des boucles de longueur faible, le processeur « duplique » les
instructions dans son pipeline et ajoute, lorsque c’est nécessaire,
des « NOP » en fin de boucle pour la terminaison :
longueur
1
1
2
2
répétition
1 ou 2
>= 3
1
>= 2
dummy cycles
2
0
2
0
problème 2 : Le pipeline, les branchements et
les boucles câblées
R4 = 32;
LCNTR = 8, DO _loop UNTIL LCE;
...
CALL
routine;
R0 = DM(I0,M0);
_loop: R5 = R0 - R4;
...


Cette instruction sera lue (cycle Fetch) deux fois à
cause de l’instruction de branchement : 1ère fois
sans être exécutée (CALL), 2ème fois au retour de
la routine.
⇒ Le compteur de boucle est décrémenté deux fois !
PAS de ruptures de séquence non retardées dans les trois
dernières instructions d’une boucle câblée !
Plus généralement : pas de branchements dans les boucles (code
peu efficace) !
Conclusion sur l’utilisation des boucles
Les boucles câblées sont un moyen efficace d’optimiser les performances
d’un code (traitement du signal = nombreuses boucles) mais le pipeline
impose une attention particulière pour le codage des boucle !
⇒ Un code optimisé (en vitesse) ne contient de
conflits de bus qu’à l’intérieur des boucles...
⇒ Les boucles doivent être de longeurs significatives
(déroulage des boucles courtes)
⇒ Les boucles ne doivent pas contenir de branchements !
Les registres du Sharc
Registres du processeur SHARC 21061
Universal Registers
 Program Sequencer
 Data Address Generators
 Bus Exchange
 Timer
 System Registers
Registres du
processeur
Registres de contrôle
Registres d’état
Register
Function
Initialization After Reset
 MODE1
Mode Control 1 0x0000 (cleared)
 MODE2
Mode Control 2 0xn000 0000 *
 ASTAT
Arithmetic Status
0x00nn 0000 **
 STKY
Sticky Status 0x0540 0000
 IRPTL
Interrupt Latch 0x0000 (cleared)
 IMASK
Interrupt Mask 0x0003
 IMASKP
Interrupt Mask Pointer 0x0000 (cleared)
 USTAT1
User Status 1 0x0000 (cleared)
 USTAT2
User Status 2 0x0000 (cleared)
Registres d’IO
 Register Function Initialization After Reset
 SYSCON System Configuration 0x0000 0010
 SYSTAT System Status 0x0000 0nn0 *
Interruptions
Interruptions




Les Sharc dispose de 3 entrées d’IR externes : IRQ0,
IRQ1, IRQ2
 Actives sur front (descendant)
 Ou sur niveau (bas)
Il y a également des sources d’IR internes
Lorsque qu’une IR est détectée, elle est mémorisée
dans le registre IRPTL. Son numéro dans le registre
correspond à sa priorité
La table des vecteurs d’IR comporte 32 entrées de 4
instructions chacune à l’adresse 0x0002 0000 en
mémoire interne bloc 0.
Vecteur d’interruption
Masquage des IR



Globalement par le bit IRPTEN du registre MODE1
(0=masquée)
Individuellement avec les bits du registre IMASK (sauf le
RESET)
Lorsqu’une IR est acceptée
 Le PC est poussé dans la pile PC
 Les registres ASTAT sont poussés dans la pile de
statut
 La demande est effacée de IRPTL
 La prochaine instruction est celle du vecteur d’IR
associé
Programmation du DSP
Modes de programmation

3 choix de programmation
 Langage C
 Langage Assembleur
 Mixte
Programmation en C






Le mode de programmation C est le mode par défaut si
aucun fichier .LDF n’a été associé.
Dans ce cas le fichier 21061.LDF est utilisé par défaut.
Le fichier 060_hdr.doj qui initialise les tables
d’interruptions et appelle la fonction main() est ajouté.
Le point d’entrée du programme est à l’adresse 0x20005
(2e mot du vecteur RESET)
La fin du programme est un boucle infinie contenant
IDLE associée au label __lib_prog_term.
Le paramètre n de return (n) est écrit dans R0 ou il peut
être lu après l’exécution.
Extension du C ANSI
Mots clés :
 Inline <function> : indique que le code de function doit
être intégré dans le code l’appelant
 asm(‘’texte’’)
: insère le code ASM dans le
prog C
 dm/pm
: forcer l’allocation es variables
globales ou statique en DM ou en PM
 Segment(‘nom’)
: spécifier explicitement le nom
du segment des instr/données qui suivent
 Bool
: type booléen
Programmation assembleur
Registres et paramètres de fonctions
Paramètres
 Les 3 premiers paramètres passés à une fonction asm sont passés
dans les registres R4,R8 et R12 dans cet ordre. Ensuite les autres
sont passés dans la pile.
Gestion de la pile
 I6 est le frame pointer
 I7 est le stack pointer
Valeur de retour
 La valeur retournée par une fonction est passée dans R0.
Nommage
 Une variable nommée X et C doit être nommée _X en assembleur
Exemple Y(n) = a.X(n) + b.X(n-1)
// Acquisition
 R0 = dm (Entree_Droite);
 R0 = ashift r0 by -1;
 R1 = dm (Entree_Droite);
 R1 = ashift r1 by -1;
 R15 = r0 + r1;
// Traitement
 R2 = 0x7FFF FFFF;
// 1 en Q1.31
 R3 = dm (Coeff_RC); // r3 = Coef a
 R2 = r2-r3;
// r2 = coef b = 1-a
 R0 = r15*r3 (SSF);
// r0 = x(n)*a
 R1 = dm (Accu_Sortie);// - R1 = r1 * r2 (SSF);
//r1 = y(n-1) * b
 R4 = r1 + r0
// r4 = a.x(n) + b.y(n-1)
 Dm (Accu_sortie) = r4;
// Sortie
Dm(Sortie_Droite) = r4;
Dm (Sortie_Gauche) = r4;
2.4.4) Les instructions parallèles

Certaines instructions peuvent provoquer des opérations en parallèle :
 Double additions-soustractions :
R0 = R8+R12, R1 = R8-R12;
 Multiplication/Accumulation et addition/soustraction en virgule fixe
R0 = R1*R4 (SSFR), R2 = R8-R12;
 Multiplication et opération arithmétique en virgule flottante
F2 = F0*F4, F5 = (F8+F12)/2;
 Multiplication et double addition-soustraction en virgule fixe ou
flottante
R5=R0*R4(SSFR),R6=R9+R13,R7=R9-R13;
F0=F1*F5, F1=F8+F12, F2=F8-F12;

Ces instructions peuvent s’effectuer également en parallèle avec des
transferts sur les bus DM et PM simultanés...
F0=F1*F5, F1=F8+F12, F5=F8-F12,
F8=DM(I0,M0),F12=PM(I8,M8);
Exemple
Code C :
Int additionne(int a, int b, int c, int d, int e){
Int J;
J = additionne (1,2,3,4,5);
J++;
}
 Code asm compilé
R2 = 5;
// dernier paramètre
DM (I7, -1) = R2; // mise au sommet de pile
R1 = 4;
// avant dernier
DM(I7, -1) = R1;
R12 = 3;
R8 = 2;
R4 = 1;
CJUMP _additionne(DB); // DB = retardé CJUMP fait aussi R2 = I6 et I6 = I7
DM (I7, -1) = R2; // empile R2 = ancien frame pointer
DM(I7, -1) = PC; // empile l’@ courante

MODIFY (I7, 2); // Au retour de l’appel dépile les 2 dernier paramètres
R3 = R0;
R3 = R3 +1;
// J++
Code du fichier asm
.SECTION/PM seg_pmco;
.GLOBAL _Additionne;
_Additionne :
MODIFY(I7, -1);
DM (-2, I6) = R1;
R0 = R0 +R8;
R0 = R0 + R12, R1 = DM(1, I6); // avant dernier paramètre
R0 = R0 + R1, R1 = DM(1,I6); // dernier paramètre
R0 = R0 + R1, R1 = DM(-2;I6);// Restitue R1
I12 = DM(-1, I6);
// Adresse de retour -1
JUMP (M14, I12) (DB);
I7 = I6;
I6 = DM(0, I6);
// saut de retour, M14 = 1 !!
// restitue la pile
// restitue ‘ancien frame pointer
Illustration
I7
Sauvegarde de R1
Adresse de retour -1
(@ de DM(I7, -1) = PC
Ancienne valeur de I6
(dans le prog principal)
4
(avant dernier param)
5
(dernier param)
I7 au début de
la fonction
I6 (I7 à la fin
de la fonction)