129 lines
3.1 KiB
Scala
129 lines
3.1 KiB
Scala
|
package rocket
|
||
|
|
||
|
import Chisel._
|
||
|
import Constants._
|
||
|
import uncore._
|
||
|
import Util._
|
||
|
|
||
|
abstract class Decoding
|
||
|
{
|
||
|
def uncorrected: Bits
|
||
|
def corrected: Bits
|
||
|
def correctable: Bool
|
||
|
def uncorrectable: Bool
|
||
|
def error = correctable || uncorrectable
|
||
|
}
|
||
|
|
||
|
abstract class Encoding
|
||
|
{
|
||
|
def width(w0: Int): Int
|
||
|
def encode(x: Bits): Bits
|
||
|
def decode(x: Bits): Decoding
|
||
|
}
|
||
|
|
||
|
class Parity extends Encoding
|
||
|
{
|
||
|
def width(w0: Int) = w0+1
|
||
|
def encode(x: Bits) = Cat(x.xorR, x)
|
||
|
def decode(y: Bits) = new Decoding {
|
||
|
def uncorrected = y(y.getWidth-2,0)
|
||
|
def corrected = uncorrected
|
||
|
def correctable = y.xorR
|
||
|
def uncorrectable = Bool(false)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class SEC extends Encoding
|
||
|
{
|
||
|
def width(k: Int) = {
|
||
|
val m = log2Up(k) + 1 - !isPow2(k)
|
||
|
k + m + ((1 << m) < m+k+1)
|
||
|
}
|
||
|
def encode(x: Bits) = {
|
||
|
val k = x.getWidth
|
||
|
require(k > 0)
|
||
|
val n = width(k)
|
||
|
|
||
|
val y = for (i <- 1 to n) yield {
|
||
|
if (isPow2(i)) {
|
||
|
val r = for (j <- 1 to n; if j != i && (j & i))
|
||
|
yield x(mapping(j))
|
||
|
r reduce (_^_)
|
||
|
} else
|
||
|
x(mapping(i))
|
||
|
}
|
||
|
Vec(y){Bool()}.toBits
|
||
|
}
|
||
|
def decode(y: Bits) = new Decoding {
|
||
|
val n = y.getWidth
|
||
|
require(n > 0 && !isPow2(n))
|
||
|
|
||
|
val p2 = for (i <- 0 until log2Up(n)) yield 1 << i
|
||
|
val syndrome = p2 map { i =>
|
||
|
val r = for (j <- 1 to n; if j & i)
|
||
|
yield y(j-1)
|
||
|
r reduce (_^_)
|
||
|
}
|
||
|
val s = Vec(syndrome){Bool()}.toBits
|
||
|
|
||
|
private def swizzle(z: Bits) = Vec((1 to n).filter(i => !isPow2(i)).map(i => z(i-1))){Bool()}.toBits
|
||
|
def uncorrected = swizzle(y)
|
||
|
def corrected = swizzle(((y << 1) ^ UFixToOH(s)) >> 1)
|
||
|
def correctable = s.orR
|
||
|
def uncorrectable = Bool(false)
|
||
|
}
|
||
|
private def mapping(i: Int) = i-1-log2Up(i)
|
||
|
}
|
||
|
|
||
|
class SECDED extends Encoding
|
||
|
{
|
||
|
def width(k: Int) = new SEC().width(k)+1
|
||
|
def encode(x: Bits) = new Parity().encode(new SEC().encode(x))
|
||
|
def decode(x: Bits) = new Decoding {
|
||
|
val sec = new SEC().decode(x(x.getWidth-2,0))
|
||
|
val par = new Parity().decode(x)
|
||
|
def uncorrected = sec.uncorrected
|
||
|
def corrected = sec.corrected
|
||
|
def correctable = par.correctable
|
||
|
def uncorrectable = !par.correctable && sec.correctable
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class SECDEDTest extends Component
|
||
|
{
|
||
|
def inject(x: Bits, n: UFix) = {
|
||
|
val r = LFSR16()
|
||
|
val r1 = UFixToOH(r(log2Up(x.getWidth)-1,0))(x.getWidth-1,0)
|
||
|
val r2 = UFixToOH(r(log2Up(x.getWidth)*2-1,log2Up(x.getWidth)))(x.getWidth-1,0)
|
||
|
x ^ Mux(n < UFix(1), UFix(0), r1) ^ Mux(n < UFix(2), UFix(0), r2)
|
||
|
}
|
||
|
|
||
|
val code = new SECDED
|
||
|
val k = 4
|
||
|
val n = code.width(k)
|
||
|
|
||
|
val io = new Bundle {
|
||
|
val original = Bits(OUTPUT, k)
|
||
|
val encoded = Bits(OUTPUT, n)
|
||
|
val injected = Bits(OUTPUT, n)
|
||
|
val uncorrected = Bits(OUTPUT, k)
|
||
|
val corrected = Bits(OUTPUT, k)
|
||
|
val correctable = Bool(OUTPUT)
|
||
|
val uncorrectable = Bool(OUTPUT)
|
||
|
}
|
||
|
|
||
|
val c = Counter(Bool(true), 1 << k)
|
||
|
val numErrors = Counter(c._2, 3)._1
|
||
|
val e = code.encode(c._1)
|
||
|
val i = inject(e, numErrors)
|
||
|
val d = code.decode(i)
|
||
|
|
||
|
io.original := c._1
|
||
|
io.encoded := e
|
||
|
io.injected := i
|
||
|
io.uncorrected := d.uncorrected
|
||
|
io.corrected := d.corrected
|
||
|
io.correctable := d.correctable
|
||
|
io.uncorrectable := d.uncorrectable
|
||
|
}
|