clean up I$ parity code
This commit is contained in:
		| @@ -14,26 +14,38 @@ abstract class Decoding | ||||
|   def error = correctable || uncorrectable | ||||
| } | ||||
|  | ||||
| abstract class Encoding | ||||
| abstract class Code | ||||
| { | ||||
|   def width(w0: Int): Int | ||||
|   def encode(x: Bits): Bits | ||||
|   def decode(x: Bits): Decoding | ||||
| } | ||||
|  | ||||
| class Parity extends Encoding | ||||
| class IdentityCode extends Code | ||||
| { | ||||
|   def width(w0: Int) = w0 | ||||
|   def encode(x: Bits) = x | ||||
|   def decode(y: Bits) = new Decoding { | ||||
|     def uncorrected = y | ||||
|     def corrected = y | ||||
|     def correctable = Bool(false) | ||||
|     def uncorrectable = Bool(false) | ||||
|   } | ||||
| } | ||||
|  | ||||
| class ParityCode extends Code | ||||
| { | ||||
|   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) | ||||
|     def correctable = Bool(false) | ||||
|     def uncorrectable = y.xorR | ||||
|   } | ||||
| } | ||||
|  | ||||
| class SEC extends Encoding | ||||
| class SECCode extends Code | ||||
| { | ||||
|   def width(k: Int) = { | ||||
|     val m = log2Up(k) + 1 - !isPow2(k) | ||||
| @@ -75,30 +87,37 @@ class SEC extends Encoding | ||||
|   private def mapping(i: Int) = i-1-log2Up(i) | ||||
| } | ||||
|  | ||||
| class SECDED extends Encoding | ||||
| class SECDEDCode extends Code | ||||
| { | ||||
|   def width(k: Int) = new SEC().width(k)+1 | ||||
|   def encode(x: Bits) = new Parity().encode(new SEC().encode(x)) | ||||
|   private val sec = new SECCode | ||||
|   private val par = new ParityCode | ||||
|  | ||||
|   def width(k: Int) = sec.width(k)+1 | ||||
|   def encode(x: Bits) = par.encode(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 | ||||
|     val secdec = sec.decode(x(x.getWidth-2,0)) | ||||
|     val pardec = par.decode(x) | ||||
|  | ||||
|     def uncorrected = secdec.uncorrected | ||||
|     def corrected = secdec.corrected | ||||
|     def correctable = pardec.uncorrectable | ||||
|     def uncorrectable = !pardec.uncorrectable && secdec.correctable | ||||
|   } | ||||
| } | ||||
|  | ||||
| object ErrGen | ||||
| { | ||||
|   // generate a 1-bit error with approximate probability 2^-f | ||||
|   def apply(width: Int, f: Int): Bits = { | ||||
|     require(width > 0 && f >= 0 && log2Up(width) + f <= 16) | ||||
|     UFixToOH(LFSR16()(log2Up(width)+f-1,0))(width-1,0) | ||||
|   } | ||||
|   def apply(x: Bits, f: Int): Bits = x ^ apply(x.getWidth, f) | ||||
| } | ||||
|  | ||||
| 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 code = new SECDEDCode | ||||
|   val k = 4 | ||||
|   val n = code.width(k) | ||||
|  | ||||
| @@ -115,7 +134,7 @@ class SECDEDTest extends Component | ||||
|   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 i = e ^ Mux(numErrors < 1, 0, ErrGen(n, 1)) ^ Mux(numErrors < 2, 0, ErrGen(n, 1)) | ||||
|   val d = code.decode(i) | ||||
|  | ||||
|   io.original := c._1 | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import uncore._ | ||||
| import Util._ | ||||
|  | ||||
| case class ICacheConfig(sets: Int, assoc: Int, co: CoherencePolicyWithUncached, | ||||
|                         parity: Boolean = false) | ||||
|                         code: Code = new IdentityCode) | ||||
| { | ||||
|   val w = 1 | ||||
|   val ibytes = 4 | ||||
| @@ -15,12 +15,10 @@ case class ICacheConfig(sets: Int, assoc: Int, co: CoherencePolicyWithUncached, | ||||
|   val dm = assoc == 1 | ||||
|   val lines = sets * assoc | ||||
|   val databits = MEM_DATA_BITS | ||||
|   val datawidth = databits + (if (parity) 1 else 0) | ||||
|   val idxbits = log2Up(sets) | ||||
|   val offbits = OFFSET_BITS | ||||
|   val untagbits = idxbits + offbits | ||||
|   val tagbits = PADDR_BITS - untagbits | ||||
|   val tagwidth = tagbits + (if (parity) 1 else 0) | ||||
|  | ||||
|   require(isPow2(sets) && isPow2(assoc)) | ||||
|   require(isPow2(w) && isPow2(ibytes)) | ||||
| @@ -176,11 +174,12 @@ class ICache(implicit c: ICacheConfig) extends Component | ||||
|   val (rf_cnt, refill_done) = Counter(io.mem.xact_rep.valid, REFILL_CYCLES) | ||||
|   val repl_way = if (c.dm) UFix(0) else LFSR16(s2_miss)(log2Up(c.assoc)-1,0) | ||||
|  | ||||
|   val tag_array = Mem(c.sets, seqRead = true) { Bits(width = c.tagwidth*c.assoc) } | ||||
|   val enc_tagbits = c.code.width(c.tagbits) | ||||
|   val tag_array = Mem(c.sets, seqRead = true) { Bits(width = enc_tagbits*c.assoc) } | ||||
|   val tag_rdata = Reg() { Bits() } | ||||
|   when (refill_done) { | ||||
|     val wmask = FillInterleaved(c.tagwidth, if (c.dm) Bits(1) else UFixToOH(repl_way)) | ||||
|     val tag = Cat(if (c.parity) s2_tag.xorR else null, s2_tag) | ||||
|     val wmask = FillInterleaved(enc_tagbits, if (c.dm) Bits(1) else UFixToOH(repl_way)) | ||||
|     val tag = c.code.encode(s2_tag) | ||||
|     tag_array.write(s2_idx, Fill(c.assoc, tag), wmask) | ||||
|   } | ||||
|   /*.else*/when (s0_valid) { // uncomment ".else" to infer 6T SRAM | ||||
| @@ -201,39 +200,37 @@ class ICache(implicit c: ICacheConfig) extends Component | ||||
|  | ||||
|   val s1_tag_match = Vec(c.assoc) { Bool() } | ||||
|   val s2_tag_hit = Vec(c.assoc) { Bool() } | ||||
|   val s2_data_disparity = Vec(c.assoc) { Bool() } | ||||
|   val s2_dout = Vec(c.assoc){Reg{Bits()}} | ||||
|  | ||||
|   for (i <- 0 until c.assoc) { | ||||
|     val s1_vb = vb_array(Cat(UFix(i), s1_pgoff(c.untagbits-1,c.offbits))).toBool | ||||
|     val s2_vb = Reg() { Bool() } | ||||
|     val s2_tag_disparity = Reg() { Bool() } | ||||
|     val s2_tag_match = Reg() { Bool() } | ||||
|     val tag_out = tag_rdata(c.tagwidth*(i+1)-1, c.tagwidth*i) | ||||
|     val tag_out = tag_rdata(enc_tagbits*(i+1)-1, enc_tagbits*i) | ||||
|     when (s1_valid && rdy && !stall) { | ||||
|       s2_vb := s1_vb | ||||
|       s2_tag_disparity := tag_out.xorR | ||||
|       s2_tag_disparity := c.code.decode(tag_out).error | ||||
|       s2_tag_match := s1_tag_match(i) | ||||
|     } | ||||
|     s1_tag_match(i) := tag_out(c.tagbits-1,0) === s1_tag | ||||
|     s2_tag_hit(i) := s2_vb && s2_tag_match | ||||
|     s2_disparity(i) := Bool(c.parity) && s2_vb && (s2_tag_disparity || s2_data_disparity(i)) | ||||
|     s2_disparity(i) := s2_vb && (s2_tag_disparity || c.code.decode(s2_dout(i)).error) | ||||
|   } | ||||
|   s2_any_tag_hit := s2_tag_hit.reduceLeft(_||_) && !s2_disparity.reduceLeft(_||_) | ||||
|  | ||||
|   val s2_dout = Vec(c.assoc) { Reg() { Bits(width = c.databits) } } | ||||
|   for (i <- 0 until c.assoc) { | ||||
|     val data_array = Mem(c.sets*REFILL_CYCLES, seqRead = true){ Bits(width = c.datawidth) } | ||||
|     val data_array = Mem(c.sets*REFILL_CYCLES, seqRead = true){ Bits(width = c.code.width(c.databits)) } | ||||
|     val s1_dout = Reg(){ Bits() } | ||||
|     when (io.mem.xact_rep.valid && repl_way === UFix(i)) { | ||||
|       val d = io.mem.xact_rep.bits.data | ||||
|       val wdata = if (c.parity) Cat(d.xorR, d) else d | ||||
|       data_array(Cat(s2_idx,rf_cnt)) := wdata | ||||
|       data_array(Cat(s2_idx,rf_cnt)) := c.code.encode(d) | ||||
|     } | ||||
|     /*.else*/when (s0_valid) { // uncomment ".else" to infer 6T SRAM | ||||
|       s1_dout := data_array(s0_pgoff(c.untagbits-1,c.offbits-rf_cnt.getWidth)) | ||||
|     } | ||||
|     // if s1_tag_match is critical, replace with partial tag check | ||||
|     when (s1_valid && rdy && !stall && (Bool(c.dm) || s1_tag_match(i))) { s2_dout(i) := s1_dout } | ||||
|     s2_data_disparity(i) := s2_dout(i).xorR | ||||
|   } | ||||
|   val s2_dout_word = s2_dout.map(x => (x >> (s2_offset(log2Up(c.databits/8)-1,log2Up(c.ibytes)) << log2Up(c.ibytes*8)))(c.ibytes*8-1,0)) | ||||
|   io.resp.bits.data := Mux1H(s2_tag_hit, s2_dout_word) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user