clean up I$ parity code
This commit is contained in:
parent
55082e45c4
commit
b514c7b725
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user