moved ecc lib to uncore, l2 checks for partial write masks when ecc is enabled
This commit is contained in:
parent
9708d25dff
commit
3cf1778c92
@ -15,6 +15,7 @@ case object NPrimaryMisses extends Field[Int]
|
|||||||
case object NSecondaryMisses extends Field[Int]
|
case object NSecondaryMisses extends Field[Int]
|
||||||
case object CacheBlockBytes extends Field[Int]
|
case object CacheBlockBytes extends Field[Int]
|
||||||
case object CacheBlockOffsetBits extends Field[Int]
|
case object CacheBlockOffsetBits extends Field[Int]
|
||||||
|
case object ECCCode extends Field[Option[Code]]
|
||||||
|
|
||||||
abstract trait CacheParameters extends UsesParameters {
|
abstract trait CacheParameters extends UsesParameters {
|
||||||
val nSets = params(NSets)
|
val nSets = params(NSets)
|
||||||
@ -28,6 +29,7 @@ abstract trait CacheParameters extends UsesParameters {
|
|||||||
val rowBits = params(RowBits)
|
val rowBits = params(RowBits)
|
||||||
val rowBytes = rowBits/8
|
val rowBytes = rowBits/8
|
||||||
val rowOffBits = log2Up(rowBytes)
|
val rowOffBits = log2Up(rowBytes)
|
||||||
|
val code = params(ECCCode).getOrElse(new IdentityCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CacheBundle extends Bundle with CacheParameters
|
abstract class CacheBundle extends Bundle with CacheParameters
|
||||||
@ -176,6 +178,7 @@ abstract trait L2HellaCacheParameters extends CacheParameters with CoherenceAgen
|
|||||||
require(rowBits == innerDataBits) // TODO: relax this by improving s_data_* states
|
require(rowBits == innerDataBits) // TODO: relax this by improving s_data_* states
|
||||||
val nSecondaryMisses = params(NSecondaryMisses)
|
val nSecondaryMisses = params(NSecondaryMisses)
|
||||||
val isLastLevelCache = true
|
val isLastLevelCache = true
|
||||||
|
val ignoresWriteMask = !params(ECCCode).isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class L2HellaCacheBundle extends Bundle with L2HellaCacheParameters
|
abstract class L2HellaCacheBundle extends Bundle with L2HellaCacheParameters
|
||||||
@ -462,6 +465,12 @@ abstract class L2XactTracker extends XactTracker with L2HellaCacheParameters {
|
|||||||
|
|
||||||
def dropPendingBitInternal[T <: HasL2BeatAddr] (in: ValidIO[T]) =
|
def dropPendingBitInternal[T <: HasL2BeatAddr] (in: ValidIO[T]) =
|
||||||
~Fill(in.bits.refillCycles, in.valid) | ~UIntToOH(in.bits.addr_beat)
|
~Fill(in.bits.refillCycles, in.valid) | ~UIntToOH(in.bits.addr_beat)
|
||||||
|
|
||||||
|
def addPendingBitWhenBeatHasPartialWritemask(in: DecoupledIO[LogicalNetworkIO[Acquire]]): UInt = {
|
||||||
|
val a = in.bits.payload
|
||||||
|
val isPartial = a.wmask() != Acquire.fullWriteMask
|
||||||
|
addPendingBitWhenBeat(in.fire() && isPartial && Bool(ignoresWriteMask), in.bits.payload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
|
class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
|
||||||
@ -805,7 +814,8 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
|
|||||||
dropPendingBit(io.data.read) &
|
dropPendingBit(io.data.read) &
|
||||||
dropPendingBitWhenBeatHasData(io.inner.release) &
|
dropPendingBitWhenBeatHasData(io.inner.release) &
|
||||||
dropPendingBitWhenBeatHasData(io.outer.grant)) |
|
dropPendingBitWhenBeatHasData(io.outer.grant)) |
|
||||||
addPendingBitWhenBeatIsGetOrAtomic(io.inner.acquire)
|
addPendingBitWhenBeatIsGetOrAtomic(io.inner.acquire) |
|
||||||
|
addPendingBitWhenBeatHasPartialWritemask(io.inner.acquire)
|
||||||
val curr_read_beat = PriorityEncoder(pending_reads)
|
val curr_read_beat = PriorityEncoder(pending_reads)
|
||||||
io.data.read.valid := state === s_busy &&
|
io.data.read.valid := state === s_busy &&
|
||||||
pending_reads.orR &&
|
pending_reads.orR &&
|
||||||
@ -880,7 +890,8 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
|
|||||||
pending_reads := Mux(
|
pending_reads := Mux(
|
||||||
io.iacq().isBuiltInType(Acquire.getBlockType) || !io.iacq().isBuiltInType(),
|
io.iacq().isBuiltInType(Acquire.getBlockType) || !io.iacq().isBuiltInType(),
|
||||||
SInt(-1, width = innerDataBeats),
|
SInt(-1, width = innerDataBeats),
|
||||||
addPendingBitWhenBeatIsGetOrAtomic(io.inner.acquire)).toUInt
|
(addPendingBitWhenBeatIsGetOrAtomic(io.inner.acquire) |
|
||||||
|
addPendingBitWhenBeatHasPartialWritemask(io.inner.acquire)).toUInt)
|
||||||
pending_writes := addPendingBitWhenBeatHasData(io.inner.acquire)
|
pending_writes := addPendingBitWhenBeatHasData(io.inner.acquire)
|
||||||
pending_resps := UInt(0)
|
pending_resps := UInt(0)
|
||||||
pending_ignt_data := UInt(0)
|
pending_ignt_data := UInt(0)
|
||||||
|
146
uncore/src/main/scala/ecc.scala
Normal file
146
uncore/src/main/scala/ecc.scala
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
abstract class Decoding
|
||||||
|
{
|
||||||
|
def uncorrected: Bits
|
||||||
|
def corrected: Bits
|
||||||
|
def correctable: Bool
|
||||||
|
def uncorrectable: Bool
|
||||||
|
def error = correctable || uncorrectable
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Code
|
||||||
|
{
|
||||||
|
def width(w0: Int): Int
|
||||||
|
def encode(x: Bits): Bits
|
||||||
|
def decode(x: Bits): Decoding
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Bool(false)
|
||||||
|
def uncorrectable = y.xorR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SECCode extends Code
|
||||||
|
{
|
||||||
|
def width(k: Int) = {
|
||||||
|
val m = new Unsigned(k).log2 + 1
|
||||||
|
k + m + (if((1 << m) < m+k+1) 1 else 0)
|
||||||
|
}
|
||||||
|
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) != 0)
|
||||||
|
yield x(mapping(j))
|
||||||
|
r reduce (_^_)
|
||||||
|
} else
|
||||||
|
x(mapping(i))
|
||||||
|
}
|
||||||
|
Vec(y).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) != 0)
|
||||||
|
yield y(j-1)
|
||||||
|
r reduce (_^_)
|
||||||
|
}
|
||||||
|
val s = Vec(syndrome).toBits
|
||||||
|
|
||||||
|
private def swizzle(z: Bits) = Vec((1 to n).filter(i => !isPow2(i)).map(i => z(i-1))).toBits
|
||||||
|
def uncorrected = swizzle(y)
|
||||||
|
def corrected = swizzle(((y.toUInt << UInt(1)) ^ UIntToOH(s)) >> UInt(1))
|
||||||
|
def correctable = s.orR
|
||||||
|
def uncorrectable = Bool(false)
|
||||||
|
}
|
||||||
|
private def mapping(i: Int) = i-1-log2Up(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
class SECDEDCode extends Code
|
||||||
|
{
|
||||||
|
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 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)
|
||||||
|
UIntToOH(LFSR16()(log2Up(width)+f-1,0))(width-1,0)
|
||||||
|
}
|
||||||
|
def apply(x: Bits, f: Int): Bits = x ^ apply(x.getWidth, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
class SECDEDTest extends Module
|
||||||
|
{
|
||||||
|
val code = new SECDEDCode
|
||||||
|
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 = e ^ Mux(numErrors < UInt(1), UInt(0), ErrGen(n, 1)) ^ Mux(numErrors < UInt(2), UInt(0), ErrGen(n, 1))
|
||||||
|
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
|
||||||
|
}
|
@ -132,8 +132,10 @@ class HierarchicalXactTrackerIO extends HierarchicalTLIO with HasTrackerConflict
|
|||||||
|
|
||||||
abstract class XactTracker extends CoherenceAgentModule
|
abstract class XactTracker extends CoherenceAgentModule
|
||||||
with HasDataBeatCounters {
|
with HasDataBeatCounters {
|
||||||
def addPendingBitWhenBeat[T <: HasBeat](inc: Bool, in: T): UInt = Fill(in.tlDataBeats, inc) & UIntToOH(in.addr_beat)
|
def addPendingBitWhenBeat[T <: HasBeat](inc: Bool, in: T): UInt =
|
||||||
def dropPendingBitWhenBeat[T <: HasBeat](dec: Bool, in: T): UInt = ~Fill(in.tlDataBeats, dec) | ~UIntToOH(in.addr_beat)
|
Fill(in.tlDataBeats, inc) & UIntToOH(in.addr_beat)
|
||||||
|
def dropPendingBitWhenBeat[T <: HasBeat](dec: Bool, in: T): UInt =
|
||||||
|
~Fill(in.tlDataBeats, dec) | ~UIntToOH(in.addr_beat)
|
||||||
|
|
||||||
def addPendingBitWhenBeatHasData[T <: Data : TypeTag](in: DecoupledIO[T]): UInt = {
|
def addPendingBitWhenBeatHasData[T <: Data : TypeTag](in: DecoupledIO[T]): UInt = {
|
||||||
in.bits match {
|
in.bits match {
|
||||||
|
@ -5,6 +5,14 @@ package uncore
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.math._
|
import scala.math._
|
||||||
|
|
||||||
|
class Unsigned(x: Int) {
|
||||||
|
require(x >= 0)
|
||||||
|
def clog2: Int = { require(x > 0); ceil(log(x)/log(2)).toInt }
|
||||||
|
def log2: Int = { require(x > 0); floor(log(x)/log(2)).toInt }
|
||||||
|
def isPow2: Boolean = x > 0 && (x & (x-1)) == 0
|
||||||
|
def nextPow2: Int = if (x == 0) 1 else 1 << clog2
|
||||||
|
}
|
||||||
|
|
||||||
object MuxBundle {
|
object MuxBundle {
|
||||||
def apply[T <: Data] (default: T, mapping: Seq[(Bool, T)]): T = {
|
def apply[T <: Data] (default: T, mapping: Seq[(Bool, T)]): T = {
|
||||||
mapping.reverse.foldLeft(default)((b, a) => Mux(a._1, a._2, b))
|
mapping.reverse.foldLeft(default)((b, a) => Mux(a._1, a._2, b))
|
||||||
|
Loading…
Reference in New Issue
Block a user