\Section{Optimisation}\label{optimisation}

Dans cette dernière section nous allons voir des optimisations que nous pouvons apporter à la structure actuelle du cache non bloquant.

%\subSection{Pipeliner l'accès au cache}\label{pipeline}
%Nous avons vut que DCACHE.REQ\_ACK ne dépend pas que de l'état des FIFOs (donc disponible au début d'un cycle) mais également des requêtes entrantes (qui sont disponible en fin de cycle). Pour couper cette chaîne critique, nous pouvons pipeliner l'accès au port de requêtes ainsi que celui des réponses. 
%
%\subsubSection{DCACHE\_RSP}
%
%Sur cette interface, les réponses sont maintenues par le cache jusqu'à ce que le processeur accepte la réponse. Pour cela, nous pouvons implémenter une simple barrière de pipeline.
%
%\subsubSection{DCACHE\_REQ}
%
%Sur cette interface, les requêtes ne sont pas maintenues par le processeur quand le cache n'accepte pas une requête. Cette spécification permet au processeur de choisir une autre requête si elle n'a pas été acceptée. (Nous rappelons qu'une requête n'est pas acceptée si la file de destination est pleine ou si une requête précedente a verrouillée la ligne.)
%
%Dans ce cas ajouter une barrière de pipeline va consommer la requête mais le cache va être dans l'imposibilité de l'accepter et va empêcher d'en choisir une autre.

\subSection{RAM mono-port multi-banc}\label{mono-port}

La mémoire la plus dense est de la mémoire mono-port, c'est à dire qu'à chaque cycle, la mémoire mono-port accepte soit une lecture, soit une écriture et non les deux.

Jusqu'ici nous n'avons pas indiquer la façon d'implémenter les bancs mémoires des blocs RAM\_TAG, RAM\_DATA, RAM\_LOCK et RAM\_INFO. Pour les deux premiers blocs, il est important qu'ils soient le plus dense possible car il contiennent toute la logique et les informations du cache.

Comme chaque interface des blocs de RAM est une interface fifo, elle intègre implicitement un contrôle de flux. Ceci rends les interfaces indépendantent de l'implémentation des blocs proprement dit. (Par exemple, le bloc RAM\_DATA peut être implémenté avec de la mémoire dual-port, dans ce cas les sorties d'aquittement sont toujours égals à 1).

\printgraph{CACHE_implementation_monolithic}{0.7}{Implémentation monolitique d'un banc de registres}

De plus, les blocs internes peuvent être implémentés de manières multibancs. Comme le montre la figure \ref{CACHE_implementation_multi-banc}, un banc de registre monolitique (voir figure \ref{CACHE_implementation_monolithic} (contenant tous les registres) peut être décomposé en deux bancs de registre ayant chacun la moitié des registres. Le premier peut avoir les registres d'adresse paire, le second les registres d'adresse impaire.

\printgraph{CACHE_implementation_multi-banc}{0.7}{Implémentation multi-banc d'un banc de registres}

Avec la stratégie multi-banc, nous pouvons également implémenter une stratégie de partage des ports. Comme le montre la figure \ref{CACHE_implementation_multi-banc_x2_mono-port}, un module combinatoire vérifie si les adresses de chaque port n'entre pas en conflit, c'est à dire que chaque port cible deux bancs differents. En cas de conflits, une priorité doit être choisit. Nous faisons le choix de priorité fixe, en avantageant les ports utiliser par la section {\bf SECTION\_DCACHE\_RSP} puis {\bf SECTION\_VCI\_RSP}, puis {\bf SECTION\_VCI\_REQ} et enfin {\bf SECTION\_DCACHE\_REQ}.

Le tableau suivant montre les conflits d'accès au banc par rapport aux bits de poids fort de l'adresse :
\begin{center}
\begin{tabular}{cc|cc}
       &     & \multicolumn{2}{|c}{Port 1} \\
       & MSB &       0 & 1\\
\hline
Port 0 &   0 & conflit & ok\\
       &   1 & ok      & conflit\\
\end{tabular}
\end{center}

\printgraph{CACHE_implementation_multi-banc_x2_mono-port}{0.7}{Implémentation multi-banc mono-port (x2) d'un banc de registres}

Avec 2 ports et 2 bancs d'un port, la probabilité de conflit et de 50\%. Afin de réduire cette probabilité, il suffit d'augmenter le nombre de banc. Dans une configuration à 4 bancs, la probabilité est de 25\%. Ceci peut être vut dans le tableau suivant :
\begin{center}
\begin{tabular}{cc|cccc}
       &     & \multicolumn{4}{|c}{Port 1} \\
       & MSB &      00 &  01    &  10    &  11    \\
\hline					 							
Port 0 &  00 & conflit & ok     & ok     & ok     \\
       &  01 & ok      & conflit& ok     & ok     \\
       &  10 & ok      & ok     & conflit& ok     \\
       &  11 & ok      & ok     & ok     & conflit\\
\end{tabular}
\end{center}

\printgraph{CACHE_implementation_multi-banc_x4_mono-port}{0.7}{Implémentation multi-banc (x4) mono-port d'un banc de registres}

La seule condition pour implémenter des mémoires mono-port est de ne pas faire de conflits systhématique. C'est à dire que dans une même section, on ne doit pas utiliser deux ports avec la même adresse.

Les blocs posant problème sont sont RAM\_TAG et RAM\_LOCK. Le premier accède deux fois au cache de TAG mais avec deux adresses différentes : l'adresse de la requête et l'adresse de la victime. Par contre pour le bloc RAM\_LOCK, il accède 3 fois à ce bloc pendant la section {\bf SECTION\_DCACHE\_REQ}, une fois avec l'adress de la requête, et deux fois avec l'adresse de la victime.

Comme le bloc RAM\_LOCK est relativement petit (NB\_LINE x 3 bits), on peut ce permettre d'avoir plusieurs accès sur ces bancs. Sinon, nous pouvons toujours pipeliner l'accès et faire un bypass entre le contenu du banc de la barrière de pipeline et la nouvelle requête du processeur. %Nous pouvons voir cette technique implémenter dans le graphe \ref{CACHE_overview_mono-port}


%\printgraphonly{CACHE_overview_mono-port}{.8}


%\subSection{Signaux de contrôles}
%Dans cette section, nous allons voir les fonctions combinatoires permettant de gérer les différents signaux de contrôles 
