From fedee6c67d278da55c0be8837929f850f8b2283b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 30 Oct 2012 01:03:47 -0700 Subject: [PATCH] add generic error correcting codes --- rocket/src/main/scala/ecc.scala | 128 ++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 rocket/src/main/scala/ecc.scala diff --git a/rocket/src/main/scala/ecc.scala b/rocket/src/main/scala/ecc.scala new file mode 100644 index 00000000..cc1e00a6 --- /dev/null +++ b/rocket/src/main/scala/ecc.scala @@ -0,0 +1,128 @@ +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 +}