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