\chapter{Algoritmy pro test pamětí}

Pro plné otestování paměti by bylo potřeba přečíst každý bit v obou stavech pro všechny kombinace všech ostatních buněk. Náročnost takového testování by byla $\mathcal{O}(n\cdot{}2^{n})$. Tato složitost v praxi znemožňuje kompletní test paměti a každý testovací algoritmus představuje podstatné zkrácení doby. Testy se snažíme zjednodušit tak, aby zanedbaly pouze nepravděpodobné chyby v paměti.

Pro představu časové náročnosti nám pomůže tabulka \ref{tab:algo-op-times}. Zde je jasně vidět důvod snahy použít algoritmy se složitostí $\mathcal{O}(c\cdot{}n)$.

\tabulkaex{tab:algo-op-times}{
\begin{tabular}{lllll}
  \hline
  & \multicolumn{4}{c}{t} \\
  Velikost paměti [B] & $\mathcal{O}(n)$ & $\mathcal{O}(n\cdot{}log(n))$ & $\mathcal{O}(n^{2})$ & $\mathcal{O}(2^{n})$   \\\hline
  16 k                & 1.6 ms   & 6.9 ms               & 26.8 s      & $10^{11340}$ s\\
  512 k               & 52.4 ms  & 300.0 ms             & 7.6 h       &              \\
  2 M                 & 210.0 ms & 1.3 s                & 5 dní       &              \\
  100 M               & 10.5 s   & 84.1 s               & 35 let      &              \\
  2 G                 & 3.6 min  & 33.4 min             & 146 století &              \\\hline
\end{tabular}
}{Závislost požadovaného testovacího času pro různou složitost algoritmu.}{Závislost požadovaného testovacího času pro různou složitost algoritmu. Předpokládáme testovací kontrolér s jedním cyklem na operaci pracujícím na frekvenci $10MHz$.} 

Je také důležité zmínit, že se v textu budeme zabývat výlučně výskytem jediné chyby v paměti. V případě vícenásobné chyby může z pohledu testovacího algoritmu docházet k maskování chyb, kdy dvě různé chyby ovlivňující jedinou buňku vedou ke zdánlivě správným výsledkům.

\section{Klasické testovací algoritmy}

\subsection{Algoritmus 0--1}
Jde o nejzákladnější testovací algoritmus pro polovodičové paměti. Podstatou algoritmu je přečíst všechny paměťové buňky v hodnotě 0 a 1. Jde o test popsaný algoritmem:
\begin{enumerate}
  \item Zapiš na všechny paměťové pozice hodnotu 0.
  \item Přečti všechny paměťové pozice a testuj na hodnotu 0.
  \item Opakuj body 1 a 2 pro hodnotu 1.
\end{enumerate}

Tento algoritmus plně pokryje defekty SA1 a SA0, pokud je adresní dekodér bez defektu. Úpravou tohoto algoritmu vznikne algoritmus MATS+, který je nejjednodušším algoritmem ze skupiny march algoritmů.

\subsection{GALPAT, Walking 1/0}
Jde o algoritmy se složitostí $\mathcal{O}(n^{2})$, které jsou zaměřeny na pokrytí CF. Algoritmus testuje, zda zápis na libovolnou adresu paměti nezmění současně data i na jiné adrese.

GALPAT algoritmus je popsán následujícími kroky:

\begin{enumerate}
  \item Na všechny adresy je zapsána hodnota $x$.
  \item Na aktuální pozici se zapíše $\overline{x}$.
  \item Provede se čtení všech paměťových pozic a porovná se s očekávanou hodnotou. Po každé hodnotě se navíc čte i aktuální pozice.
  \item Na aktuální pozici se zapíše $x$  a pokračuje se bodem 2 pro další adresu.
  \item Po projití celé paměti se test zopakuje s $x=\overline{x}$.
\end{enumerate}


Algoritmus Walking 1/0\footnote{Označován také jako WALPAT (WALking PATtern).} ve 3. bodě opakovaně nečte aktuální pozici a její čtení provede až na konci smyčky.

Tyto algoritmy plně pokryjí všechny SA0, SA1, TF, CF a chyby adresního dekodéru.

\subsection{Sliding diagonal}
Princip algoritmu je stejný jako v případě GALPAT. Aktuální pozice však není jediná adresa, ale množina adres tvořících diagonálu přes geometrické rozložení paměťového pole. Tím dojde ke snížení složitosti na $\mathcal{O}(n^{2/3})$ za cenu toho, že některé CF nejsou detekovány.

\section{March algoritmy}
March algoritmy jsou množinou algoritmů pro testování pamětí s náročností $\mathcal{O}(c\cdot{}n)$. March algoritmus sestává ze sekvence čtení a zápisů do paměti, které jsou seskupené do march elementů, které aplikujeme na každou paměťovou pozici paměťového pole ve vzestupném nebo sestupném pořadí adres. March algoritmy předpokládají paměť s bitovým přístupem.

Pro zápis march algoritmů využijeme gramatiku podle tabulky \ref{tab:march-gram}.

\tabulka{tab:march-gram}{
\begin{tabular}{lp{12cm}}
  \hline
  Zápis & Význam \\\hline
  $w0$/$w1$ & Zápis symbolu 0/1 na aktuální paměťovou pozici \\
  $r0$/$r1$ & Čtení aktuální paměťové pozice a porovnání s očekávaným symbolem \\
  $\Uparrow(...)$   & Skupina čtení/zápisů prováděná na celé paměti adresované postupně ve vzestupném pořadí \\
  $\Downarrow(...)$ & Skupina čtení/zápisů prováděná na celé paměti adresované postupně v sestupném pořadí \\
  $\Updownarrow(...)$ & Skupina čtení/zápisů prováděná na celé paměti adresované postupně v libovolném pořadí \\
  $Del$               & Pauza v testovacím algoritmu pro stimulaci DRF\footnotemark \\\hline
\end{tabular}
}{Gramatika march testů}

March algoritmy se označují jménem, případně délkou algoritmu. Seznam základních march algoritmů je v tabulce \ref{tab:march-tests}. Pokrytí jednobitových chyb uvedenými algoritmy je vidět v tabulce \ref{tab:march-coverage}. Pokrytí WDF, DRF a dDR chyb lze jednoduše doplnit i do ostatních testů zdvojením některých čtecích a zápisových operací a doplněním zpoždění do testu.

%Make \+ word-wrap command without hyphen
\newcommand\+{\discretionary{}{}{}}

\tabulka{tab:march-tests}{
  \begin{tabular}{l>{\raggedright}p{9cm}l}
    \hline
    Název testu & Kód testu & Zdroj\\\hline
    MATS ($4\cdot{}n$)     & $\Updownarrow~(w0)\+\Updownarrow~(r0,w1)\+\Updownarrow~(r1)$ & \cite{memory-testing}\\
    MATS+ ($5\cdot{}n$)    & $\Updownarrow~(w0)\+\Uparrow~(r0,w1)\+\Downarrow~(r1,w0)$    & \cite{IEEE-march-tests}\cite{memory-testing}\cite{march-ss}\\
    MATS++ ($6\cdot{}n$)   & $\Updownarrow~(w0)\+\Uparrow~(r0,w1)\+\Downarrow~(r1,w0,r0)$ & \cite{memory-testing}\\
    March X ($6\cdot{}n$)  & $\Updownarrow~(w0)\+\Uparrow~(r0,w1)\+\Downarrow~(r1,w0)\+\Updownarrow~(r0)$ & \cite{memory-testing}\\
    March C ($11\cdot{}n$) & $\Updownarrow~(w0)\+\Uparrow~(r0,w1)\+\Uparrow~(r1,w0)\+\Uparrow~(r0)\+\Downarrow~(r0,w1)\+\Downarrow~(r1,w0)\+\Updownarrow~(r0)$ & \cite{memory-testing}\\
    March C- ($10\cdot{}n$)& $\Updownarrow~(w0)\+\Uparrow~(r0,w1)\+\Uparrow~(r1,w0)\+\Downarrow~(r0,w1)\+\Downarrow~(r1,w0)\+\Updownarrow~(r0)$ & \cite{IEEE-march-tests}\cite{memory-testing}\cite{march-ss}\\
    March A ($15\cdot{}n$) & $\Updownarrow~(w0)\+\Uparrow~(r0,w1,w0,w1)\+\Uparrow~(r1,w0,w1)\+\Downarrow~(r1,w0,w1,w0)\+\Downarrow~(r0,w1,w0)$ & \cite{memory-testing}\\
    March Y ($8\cdot{}n$)  & $\Updownarrow~(w0)\+\Uparrow~(r0,w1,r1)\+\Downarrow~(r1,w0,r0)\+\Updownarrow~(r0)$ & \cite{memory-testing}\\
    March B ($16\cdot{}n$) & $\Updownarrow~(w0)\+\Uparrow~(r0,w1,r1,w0,w1)\+\Uparrow~(r1,w0,w1)\+\Downarrow~(r1,w0,w1,w0)\+\Downarrow~(r0,w1,w0)$ & \cite{IEEE-march-tests}\cite{memory-testing}\cite{march-ss}\\
    March G ($23\cdot{}n$) & $\Updownarrow~(w0)\+\Uparrow~(r0,w1,r1,w0,r0,w1)\+\Uparrow~(r1,w0,w1)\+\Downarrow~(r1,w0,w1,w0)\+\Downarrow~(r0,w1,w0)\+Del\+\Updownarrow~(r0,w1,r1)\+Del\+\Updownarrow~(r1,w0,r0)$ & \cite{IEEE-march-tests}\\
    March SS ($22\cdot{}n$)& $\Updownarrow~(w0)\+\Uparrow~(r0,r0,w0,r0,w1)\+\Uparrow~(r1,r1,w1,r1,w0)\+\Downarrow~(r0,r0,w0,r0,w1)\+\Downarrow~(r1,r1,w1,r1,w0)\+\Updownarrow~(r0)$ & \cite{march-ss}\\
    March U ($13\cdot{}n$) & $\Updownarrow~(w0)\+\Uparrow~(r0,w1,r1,w0)\+\Uparrow~(r0,w1)\+\Downarrow~(r1,w0,r0,w1)\+\Downarrow~(r1,w0)$ & \cite{march-ss}\\
    March LR ($14\cdot{}n$)& $\Updownarrow~(w0)\+\Downarrow~(r0,w1)\+\Uparrow~(r1,w0,r0,w1)\+\Uparrow~(r1,w0)\+\Uparrow~(r0,w1,r1,w0)\+\Uparrow~(r0)$ & \cite{march-ss}\\
    March SR ($14\cdot{}n$)& $\Updownarrow~(w0)\+\Uparrow~(r0,w1,r1,w0)\+\Uparrow~(r0,r0)\+\Uparrow~(w1)\+\Downarrow~(r1,w0,r0,w1)\+\Downarrow~(r1,r1)$ & \cite{march-ss}\\
    PMOVI ($13\cdot{}n$)   & $\Updownarrow~(w0)\+\Uparrow~(r0,w1,r1)\+\Uparrow~(r1,w0,r0)\+\Downarrow~(r0,w1,r1)\+\Downarrow~(r1,w0,r0)$ & \cite{march-ss}\\
    \hline
  \end{tabular}
}{March testy}
\tabulka{tab:march-coverage}{
  \begin{tabular}{l|lllllll}
    \hline 
    March test             & SaF & SoF & TF  & DR  & dDR & DRF & WDF \\\hline
    MATS ($4\cdot{}n$)     & 2/2 & 0/1 & 0/2 & 2/2 & 0/2 & 0/2 & 0/2 \\  
    MATS+ ($5\cdot{}n$)    & 2/2 & 0/1 & 1/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    MATS++ ($6\cdot{}n$)   & 2/2 & 0/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\ 
    March X ($6\cdot{}n$)  & 2/2 & 0/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March C ($11\cdot{}n$) & 2/2 & 0/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March C- ($10\cdot{}n$)& 2/2 & 0/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March A ($15\cdot{}n$) & 2/2 & 0/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March Y ($8\cdot{}n$)  & 2/2 & 1/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March B ($16\cdot{}n$) & 2/2 & 0/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March G ($23\cdot{}n$) & 2/2 & 1/1 & 2/2 & 2/2 & 0/2 & 2/2 & 0/2 \\
    March SS ($22\cdot{}n$)& 2/2 & 0/1 & 2/2 & 2/2 & 2/2 & 0/2 & 2/2 \\
    March U ($13\cdot{}n$) & 2/2 & 1/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March LR ($14\cdot{}n$)& 2/2 & 1/1 & 2/2 & 2/2 & 0/2 & 0/2 & 0/2 \\
    March SR ($14\cdot{}n$)& 2/2 & 1/1 & 2/2 & 2/2 & 2/2 & 0/2 & 0/2 \\
    PMOVI ($13\cdot{}n$)   & 2/2 & 1/1 & 2/2 & 2/2 & 2/2 & 0/2 & 0/2 \\
    \hline
    
  \end{tabular}
}{Pokrytí jednobitových chyb march algoritmy}

\tabulka{tab:march-coverage-cf}{
  \begin{tabular}{l|lllllll}
    \hline 
    March test             & CFst & CFid & CFin \\\hline
%    MATS ($4\cdot{}n$)     & 0/8  & 0/8  & 0/4  \\  
    MATS+ ($5\cdot{}n$)    & 4/8  & 3/8  & 0/4  \\
    MATS++ ($6\cdot{}n$)   & 4/8  & 3/8  & 0/4  \\ 
    March X ($6\cdot{}n$)  & 5/8  & 4/8  & 0/4  \\
    March C ($11\cdot{}n$) & 8/8  & 8/8  & 4/4  \\
    March C- ($10\cdot{}n$)& 8/8  & 8/8  & 4/4  \\
    March A ($15\cdot{}n$) & 6/8  & 8/8  & 4/4  \\
    March Y ($8\cdot{}n$)  & 5/8  & 4/8  & 0/4  \\
    March B ($16\cdot{}n$) & 6/8  & 8/8  & 4/4  \\
    March G ($23\cdot{}n$) & 6/8  & 8/8  & 4/4  \\
    March SS ($22\cdot{}n$)& 8/8  & 8/8  & 4/4  \\
    March U ($13\cdot{}n$) & 8/8  & 8/8  & 4/4  \\
    March LR ($14\cdot{}n$)& 8/8  & 8/8  & 4/4  \\
    March SR ($14\cdot{}n$)& 8/8  & 8/8  & 4/4  \\
    PMOVI ($13\cdot{}n$)   & 8/8  & 7/8  & 3/4  \\
    \hline
    
  \end{tabular}
}{Pokrytí vícebitových chyb march algoritmy}
\subsection{Volnosti march algoritmů}

Při implementaci march algoritmů můžeme provést jistá zjednodušení nebo optimalizace při zachování vlastností implementovaného algoritmu. Tyto oblasti označíme jako volnosti march algoritmů \cite{ieee-march-dof}. V této práci užijeme následující dva z šesti pozorovaných: 

Jako první stupeň volnosti představuje možnost použít jiný než prostý binární čítač pro adresaci paměťových buněk. Podmínkou pro implemetovaný čítač je projití všech $2^n$ stavů. V sekvenci se také musí vyskytnout každý stav právě jednou. U vybraného čítače musí existovat možnost čítat v opačném pořadí pro implementaci \uv{čítání směrem dolů}.

Druhý stupeň volnosti je v testovacích datech. Pro test je třeba využít dvojici navzájem inverzních dat, tj. $0$ a $1$. Tato testovací slova nemusí být stejná pro všechny paměťové pozice a lze je generovat například z adresy. Nutnou podmínkou je, aby datová slova odpovídající $0$ a $1$ byla pro danou adresu konstantní během celého march algoritmu.
%Addtocounter to fix multiple footnotes in floats
%\addtocounter{footnote}{-1}
\footnotetext{Patří k operacím, o které se standardní march testy rozšiřují.}
%\addtocounter{footnote}{1}
\FloatBarrier
\subsection{Paměti s přístupem po slovech}

Při testu pamětí, které mají datové slovo širší než jeden bit, dochází k problému, protože nelze k paměti přistupovat po jednotlivých bitech. Z toho důvodu by nešlo stimulovat CF mezi jednotlivými bity paměťového slova a tím by došlo ke snížení pokrytí chyb v testu.
Pro stimulaci CF mezi jednotlivými datovými linkami použijeme různá datová slova, která budeme během testu měnit.
Pro generaci testu se dá použít pevná množina datových slov, která testují různé kombinace a jejich inverze (např.: 000, 111, 101, 010). Tento postup používá například BIST kontrolér firmy Virage Logic.

Pokud se zaměříme pouze na pokrytí datových linek a čtecích zesilovačů, bude možno využít pseudonáhodné generování testovacích dat. Toto si můžeme dovolit díky volnosti v march algoritmech. Testovací data generujeme logickou funkcí, která má za vstup aktuální adresu. Tato změna je velice nenáročná na velikost BIST kontroléru.

Poslední způsob pro testování pamětí s přístupem po slovech je použít smarch algoritmy, které budou předmětem další kapitoly.
%Move text here due to float figure position
%\footnotetext{Zde se moje tvrzení rozcházi s \cite{march-ss}, kde tvrdí plné pokrytí dDR chyb (v jejich práci označené jako DRDF). Algorimtus PMOVI neobsahuje elementy $rx,rx$ tudíž nemůže dDR pokrýt.}

\section{Smarch algoritmy}

Smarch neboli \uv{serial march} algoritmy jsou odvozeny z původních march algoritmů pro testování paměti, která přistupuje k datům na úrovni slov. Smarch algoritmy využívají sériový přístup k paměti, kdy jsou jednotlivé bity při každé operaci na paměti rotovány přes paměťové slovo \cite{ieee-smarch}. Princip takového přístupu je znázorněn na obrázku \ref{fig:smarch-access}.

\image{fig:smarch-access}{
  \input{obrazky/smarch-access.tex}}{Přístup k datovým bitům v smarch algoritmu}{}

Tato změna také znamená, že operace zápis a čtení je potřeba provádět vždy současně. V popisu smarch algoritmu se budou vyskytovat pouze přístupy $wxry$, kde $x$ jsou data určená k zápisu do paměti a $y$ data právě čtená z paměti. Výstup $y$ je nutné v prvních march elementech ignorovat. O tuto možnost je třeba rozšířit gramatiku march testů -- tuto operaci formálně zapíšeme jako $(wxry)^n$.

Příkladem smarch algoritmů může být algoritmus SMarchCHKBci od firmy Mentor Graphics Corporation \cite{tessent-memoryBIST}. Tento algoritmus je popsán výrazem \ref{eq:smarchchkbci}\footnote{Algoritmus není přepsán úplně správně. V originálním algoritmu jsou bloky bez udání směru čítání provedeny pouze pro jedinou adresu.}. Tento algoritmus plně pokryje chyby SaF, SoF, TF, DR, dDR, DRF, WDF, CFst, CFid, CFin a defekty adresního dekodéru.

\vzorec{eq:smarchchkbci}{
\begin{split}
  &\Updownarrow((w1rx)^n, r1, w1) \Updownarrow((w0r1)^n, r0, r0) \Uparrow((w0rx)^n, r0) \\
  &\Uparrow((w0r0)^n) \Uparrow((w1r0)^n) \Uparrow((w1r1)^n) \Uparrow((w0r1)^n)          \\
  &\Updownarrow((w0rx)^n, r0, r0) \Uparrow(w0,r0) \Uparrow((w1r0)^n, r1, w1)            \\
  &\Uparrow((w0r1)^n, r0, w0) \Downarrow((w1r0)^n, r1, r1)                              \\
  &\Downarrow((w0r1)^n, r0, r0) \Downarrow((w0r0)^n) \Updownarrow((w1rx)^n, r1, r1)     \\
  &\Uparrow(w1, r1) \Uparrow((w1r1)^n) \Updownarrow((w0r1)^n, w0, r0) \Uparrow(w0, r0)
\end{split}
}{}{}

