Université de Bordeaux                     Collège Sciences et Technologies

ANNÉE UNIVERSITAIRE 2025 -- 2026
SESSION 1 DE PRINTEMPS

Parcours / Étape : LSTS / L2
Code UE : 4TIN408U
Épreuve : Architecture des ordinateurs


# EXERCICE 1 [30 points]

## Question 1.1 [10 points]

Le complément à deux est un mode de représentation des entiers relatifs sous forme binaire, de telle sorte que :

- on n'ait qu'un seul zéro ;

- on utilise le circuit d'addition classique pour les calculs.

L'opposé d'un nombre est calculé en :

- complémentant tous les bits du nombre ;

- ajoutant 1 au nombre résultant.

Le bit de poids fort indique le signe.

## Question 1.2 [20 points]

La table de vérité des deux sorties s0 et s1 en fonction de x2, x1 et x0 est la suivante :

    --------------------------
    | x2 | x1 | x0 | s0 | s1 |
    --------------------------
    |  0 |  0 |  0 |  0 |  0 |
    |  0 |  0 |  1 |  1 |  1 |
    |  0 |  1 |  0 |  1 |  0 |
    |  0 |  1 |  1 |  1 |  0 |
    |  1 |  0 |  0 |  0 |  1 |
    |  1 |  0 |  1 |  0 |  1 |
    |  1 |  1 |  0 |  0 |  1 |
    |  1 |  1 |  1 |  0 |  1 |
    --------------------------

On peut en déduire les équations logiques suivantes :

    s0 = AND (NOT (x2), OR (x1, x0))
    s1 = OR (x2, AND (NOT (x2), NOT (x1), x0))

# EXERCICE 2 [60 points]

## Question 2.1 [10 points]

Il faut brancher la sortie /Q de la bascule sur son entrée D. Ainsi, à
chaque top d'horloge, la nouvelle valeur mémorisée sera l'opposée de
la valeur actuelle exposée sur la sortie Q.

    D:D  = NOT (D:Q)
    D:Ck = f

## Question 2.2 [10 points]

On a le chronogramme suivant :
        
    H :      |----|    |----|    |----|    |----|    |----|
         ----|    |----|    |----|    |----|    |----|    |
        
    Q :      |---------|         |---------|         |-----
         ----|         |---------|         |---------|     

La fréquence du signal Q est la moitié de celle du signal H de
l'horloge.

## Question 2.3 [20 points]

Comme on ne veut pas de dérive de l'horloge, on ne peut rien brancher
d'autre sur chaque bascule D que le signal d'horloge H.

Pour la sortie Q0, on utilise le circuit de la question précédente,
qui fera changer d'état à la bascule D0 à chaque front montant.

Pour la sortie Q1, on doit faire changer d'état la bascule D1 à chaque
front montant lorsque la sortie Q0 est à 1. on va donc se servir du
signal Q0 comme d'un inverseur de la sortie Q1, au moyen d'une porte
XOR. On a donc le câblage suivant :

    D0:D  = NOT (D0:Q)
    D0:Ck = f
    D1:D  = XOR (D0:Q, D1:Q)
    D1:Ck = f

On a le chronogramme suivant :
        
    H :      |----|    |----|    |----|    |----|    |----|
         ----|    |----|    |----|    |----|    |----|    |
        
    Q0 :     |---------|         |---------|         |-----
         ----|         |---------|         |---------|     
        
    Q1 :               |-------------------|               
         --------------|                   |---------------
         00      01        10        11        00       01

## Question 2.4 [20 points]

Pour ce circuit, on utilise trois bascules D, que l'on connecte en
série. À la fin de la série, on place un inverseur, avant de reboucler
sur la première bascule. Cela donne le câblage suivant :

    D0:D  = NOT (D2:Q)
    D0:Ck = f
    D1:D  = D0:Q
    D1:Ck = f
    D2:D  = D1:Q
    D2:Ck = f

# EXERCICE 3 [70 points]

## Question 3.1 [30 points]

rrmovl rA,rB :

    Fetch :
    icode:ifun = M1[PC]
    rA:rB = M1[PC+1]
    valP = PC + 2

    Decode :
    valA = R[rA]

    Execute :
    ValE = 0 + valA

    Memory :

    Write back :
    R[rB] = valE

    PC update :
    PC = valP

pushl rA :

    Fetch :
    icode:ifun = M1[PC]
    rA:rB = M1[PC+1]
    valP = PC + 2

    Decode :
    valA = R[rA]
    valB = R[%esp]

    Execute :
    valE = valB + (-4)

    Memory :
    M4[valE] = valA

    Write back :
    R[%esp] = valE

    PC update :
    PC = valP

ret :

    Fetch :
    icode:ifun = M1[PC]
    valP = PC + 1

    Decode :
    valA = R[%esp]
    valB = R[%esp]

    Execute :
    valE = valB + 4

    Memory :
    ValM = M4[valA]

    Write back :
    R[%esp] = valE

    PC update :
    PC = valM

## Question 3.2 [20 points]

Chercher les mentions de RRMOVL, PUSHL, et RET.

    ################ Fetch Stage     ###################################
    
    # Does fetched instruction require a regid byte?
    bool need_regids =
    	icode in { OPL, IOPL, POPL, IRMOVL, RMMOVL, MRMOVL, RRMOVL, PUSHL };
    
    # Does fetched instruction require a constant word?
    bool need_valC =
    	icode in { IRMOVL, RMMOVL, MRMOVL, JXX, CALL, IOPL };
    
    ################ Decode Stage    ###################################
    
    ## What register should be used as the A source?
    int srcA = [
    	icode in { RMMOVL, OPL, RRMOVL, PUSHL } : rA;
    	icode in { POPL, RET } : RESP;
    	1 : RNONE; # Don't need register
    ];
    
    ## What register should be used as the B source?
    int srcB = [
    	icode in { OPL, IOPL, RMMOVL, MRMOVL } : rB;
    	icode in { POPL, CALL, PUSHL, RET } : RESP;
    	1 : RNONE;  # Don't need register
    ];
    
    ## What register should be used as the E destination?
    int dstE = [
    	icode in { IRMOVL, OPL, IOPL, RRMOVL } : rB;
    	icode in { POPL, CALL, PUSHL, RET } : RESP;
    	1 : RNONE;  # Don't need register
    ];
    
    ## What register should be used as the M destination?
    int dstM = [
    	icode in { MRMOVL, POPL } : rA;
    	1 : RNONE;  # Don't need register
    ];
    
    ################ Execute Stage   ###################################
    
    ## Select input A to ALU
    int aluA = [
    	icode in { OPL, RRMOVL } : valA;
    	icode in { IRMOVL, RMMOVL, MRMOVL, IOPL } : valC;
    	icode in { CALL, PUSHL } : -4;
    	icode in { POPL, RET } : 4;
    	# Other instructions don't need ALU
    ];
    
    ## Select input B to ALU
    int aluB = [
    	icode in { RMMOVL, MRMOVL, OPL, IOPL, CALL, POPL, PUSHL, RET } : valB;
    	icode in { IRMOVL, RRMOVL } : 0;
    	# Other instructions don't need ALU
    ];
    
    ## Set the ALU function
    int alufun = [
    	icode in { OPL, IOPL } : ifun;
    	1 : ALUADD;
    ];
    
    ## Should the condition codes be updated?
    bool set_cc = icode in { OPL, IOPL };
    
    ################ Memory Stage    ###################################
    
    ## Set read control signal
    bool mem_read = icode in { MRMOVL, POPL, RET };
    
    ## Set write control signal
    bool mem_write = icode in { RMMOVL, CALL, PUSHL };
    
    ## Select memory address
    int mem_addr = [
    	icode in { RMMOVL, CALL, MRMOVL, PUSHL } : valE;
    	icode in { POPL, RET } : valA;
    	# Other instructions don't need address
    ];
    
    ## Select memory input data
    int mem_data = [
    	icode in { RMMOVL, PUSHL } : valA;
    	icode == CALL : valP;
    	# Default: Don't write anything
    ];
    
    ################ Program Counter Update ############################
    
    ## What address should instruction be fetched at
    
    int new_pc = [
    	icode == CALL : valC;
    	icode == JXX && Bch : valC;
        icode == RET : valM;
    	1 : valP;
    ];

## Question 3.3 [10 points]

Il faut deux accès en lecture, pour lire les anciennes valeurs de rA
et rB, et deux accès en écriture, pour stocker les nouvelles valeurs
de rA et rB, résultant de l'échange de leurs valeurs.

## Question 3.4 [10 points]

Dans le schéma actuel, l'une des deux valeurs pouvant être stockées
dans la banque de registres est valM, valeur issue d'une lecture
mémoire. Or, XCHGL n'utilise pas la mémoire. Il faut donc un nouveau
bus, allant de l'une des deux valeurs (par exemple valB) à la banque
de registres, multiplexée avec valM.

# EXERCICE 4 [40 points]

## Question 4.1 [10 points]

On place le registre entre les blocs B et C. On a donc :

    t (A + B + R) = 130 ps
    t (C + D + E + R) = 170 ps
    Durée max = 170 ps
    Latence = 2 * Durée max = 340 ps
    Débit = 10^12 / 170 = 5,88 Gop/s

## Question 4.2 [10 points]

On place toujours le premier registre entre les blocs B et C. Pour le
second registre, on a le choix entre le placer entre C et D, ou
entre D et E. On a le même résultat dans les deux cas :

    t (A + B + R) = 130 ps
    t (C + R) = 70 ps
    t (D + E + R) = 120 ps

ou :

    t (A + B + R) = 130 ps
    t (C + D + R) = 110 ps
    t (E + R) = 80 ps

et donc :

    Durée max = 130 ps
    Latence = 3 * Durée max = 390 ps
    Débit = 10^12 / 130 = 7,69 Gop/s

## Question 4.3 [20 points]

La taille du plus grand bloc est de 90 ps. On n'a donc pas besoin de
placer des registres pour découper en dessous de cette limite. On
place donc des registres intermédiaires après les blocs A, B et D :

    t (A + R) = 40 ps
    t (B + R) = 110 ps
    t (C + D + R) = 110 ps
    t (E + R) = 80 ps
    Durée max = 110 ps
    Latence = 4 * Durée max = 440 ps
    Débit = 10^12 / 110 = 9,09 Gop/s
