エラーを検出するコード

エラーを検出するためには、エラーが起こると正常なデータとは異なるデータになってしまうように正常なデータを作っておく。例えば、元のデータに1ビットを追加して、追加のビットの値を、全体の"1"のビットの数が偶数になるように選ぶという規則とする。

このデータをメモリに書き込んで、それを読み出した時に、全体の"1"の数が奇数になっていたら、どこかのビットが反転したということが分かる。このやり方をパリティチェックと言う。2ビットが反転してしまうと、全体の"1"の数は偶数に戻ってしまうので、エラーを検出しそこなってしまうが、1ビットのエラーであれば、必ず検出できる。

より強力な検出方法としてCRC(Cyclic Redundancy Check)という方法がある。元のデータが72ビットある場合、最初のビットをx71の係数、次のビットをx70の係数、…x1の係数、x0の係数と考える。そして、図3.11に示すように、GDDR5で使われているCRC-8-ATMの場合は、データビットを係数とする多項式をx8+x2+x+1で割った余りをチェックビットとして付ける。ただし、係数は0か1の2進数であるので0-1は1になるとして計算する。

図3.11 CRCの計算。入力データの左端がx71の係数、その次がx70の係数。ここでは一部の係数しか書かれていない。引き算は、各桁の値のXORで行える。次回は剰余の最上位の"1"のところに除数の最上位の"1"を合わせて引き算を行う

GDDR5 DRAMは8ビットのデータにデータバスの値を反転するDBI信号を加えた9ビットデータをBurst Length=8のグループでまとめた72ビットのデータに対して、CRC-8-ATMでチェックビットを計算する。そしてデータを送った後で、EDC信号線を使って8ビットのチェックビットをシリアルに送る。このCRCでは、2ビットのエラーを検出することができる。

受け側では同様にチェックビットを計算し、EDC信号で送られたチェックビットと一致すればエラーなし、一致しなければエラーと判断する。そしてエラーの場合は、送り側に再送を依頼することで誤りを訂正する。

ただし、このCRCによるエラーの検出、訂正はGPUとGDDR5 DRAMの間の信号伝送のエラーに対するもので、メモリの中でのデータ化けを検出する機能はない。なお、JEDECの規格では、読み出し、書き込みともにCRCチェックをサポートすることが可能であるが、すべての機能をサポートすることは必須ではなく、例えばMicronのGDDR5 DRAMのドキュメントでは読み出し側しかCRCをサポートしていないと書かれている。

原理的には、チェックビットを格納するメモリがあれば、読み出し時にCRCを計算してメモリの中でのデータ化けを検出することは可能であるが、読み出し時にエラーを検出してもGPUに正しいデータを再送してもらう訳にはいかない(どのアドレスの読み出しに対しても再送ができるためにはメモリに記憶されているすべてのデータをGPUが持っている必要があり、その場合は、そもそも外部のメモリチップは不要である)ので、訂正はできない。

エラーを訂正するコード

最大1ビットのエラーしか発生しないと考えると、64ビットのデータを受け取ったとき、そのデータは、エラーなし、ビット0がエラー、ビット1がエラー、…ビット63がエラーと65通りの結果が考えられる。受け取ったデータから、この65通りのどのケースであるかが区別できないと、訂正はできない。この区別が分かるようにするためにはチェックビットを付ける必要がある。

チェックビットにもエラーは発生し得るので、元のデータビット数をD、チェックビット数をCとすると2C>D+Cが成り立っていることが必要条件である。そして、この条件が成り立っていれば、エラーが起こったビットを特定する符号化ができることが示されている。

データビット数Dが64の場合は7ビットのチェックビットを付ければこの条件を満足する。ただし、この符号は、2ビットのエラーが起こると、別のビットがエラーしたと判定してしまい、誤訂正を行ってしまう。このため、もう1ビット チェックビットを追加し、2ビットエラーは訂正はできないが、検出はできるという符号を使うのが一般的である。この符号はSingle bit Error Correction Double bit Error Detection(SECDED)コードと呼ばれる。