2017-01-22 01:52:40 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
2017-07-07 19:48:16 +02:00
|
|
|
package freechips.rocketchip.tilelink
|
2017-01-22 01:52:40 +01:00
|
|
|
|
|
|
|
import Chisel._
|
2017-07-07 19:48:16 +02:00
|
|
|
import freechips.rocketchip.config.Parameters
|
|
|
|
import freechips.rocketchip.diplomacy._
|
2017-01-22 01:52:40 +01:00
|
|
|
|
|
|
|
// q is the probability to delay a request
|
|
|
|
class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule
|
|
|
|
{
|
2017-09-14 03:06:03 +02:00
|
|
|
val node = TLAdapterNode()
|
2017-01-22 01:52:40 +01:00
|
|
|
require (0.0 <= q && q < 1)
|
|
|
|
|
|
|
|
lazy val module = new LazyModuleImp(this) {
|
2017-03-11 01:48:57 +01:00
|
|
|
def feed[T <: Data](sink: DecoupledIO[T], source: DecoupledIO[T], noise: T) {
|
2017-10-30 23:01:17 +01:00
|
|
|
val allow = UInt((q * 65535.0).toInt) <= LFSRNoiseMaker(16, source.valid)
|
2017-01-22 01:52:40 +01:00
|
|
|
sink.valid := source.valid && allow
|
|
|
|
source.ready := sink.ready && allow
|
|
|
|
sink.bits := source.bits
|
2017-03-11 01:48:57 +01:00
|
|
|
when (!sink.valid) { sink.bits := noise }
|
2017-01-22 01:52:40 +01:00
|
|
|
}
|
|
|
|
|
2017-09-14 03:06:03 +02:00
|
|
|
(node.in zip node.out) foreach { case ((in, _), (out, _)) =>
|
2017-03-11 01:48:57 +01:00
|
|
|
val anoise = Wire(in.a.bits)
|
|
|
|
anoise.opcode := LFSRNoiseMaker(3)
|
|
|
|
anoise.param := LFSRNoiseMaker(3)
|
|
|
|
anoise.size := LFSRNoiseMaker(anoise.params.sizeBits)
|
|
|
|
anoise.source := LFSRNoiseMaker(anoise.params.sourceBits)
|
|
|
|
anoise.address := LFSRNoiseMaker(anoise.params.addressBits)
|
|
|
|
anoise.mask := LFSRNoiseMaker(anoise.params.dataBits/8)
|
|
|
|
anoise.data := LFSRNoiseMaker(anoise.params.dataBits)
|
|
|
|
|
|
|
|
val bnoise = Wire(out.b.bits)
|
|
|
|
bnoise.opcode := LFSRNoiseMaker(3)
|
|
|
|
bnoise.param := LFSRNoiseMaker(3)
|
|
|
|
bnoise.size := LFSRNoiseMaker(bnoise.params.sizeBits)
|
|
|
|
bnoise.source := LFSRNoiseMaker(bnoise.params.sourceBits)
|
|
|
|
bnoise.address := LFSRNoiseMaker(bnoise.params.addressBits)
|
|
|
|
bnoise.mask := LFSRNoiseMaker(bnoise.params.dataBits/8)
|
|
|
|
bnoise.data := LFSRNoiseMaker(bnoise.params.dataBits)
|
|
|
|
|
|
|
|
val cnoise = Wire(in.c.bits)
|
|
|
|
cnoise.opcode := LFSRNoiseMaker(3)
|
|
|
|
cnoise.param := LFSRNoiseMaker(3)
|
|
|
|
cnoise.size := LFSRNoiseMaker(cnoise.params.sizeBits)
|
|
|
|
cnoise.source := LFSRNoiseMaker(cnoise.params.sourceBits)
|
|
|
|
cnoise.address := LFSRNoiseMaker(cnoise.params.addressBits)
|
|
|
|
cnoise.data := LFSRNoiseMaker(cnoise.params.dataBits)
|
|
|
|
cnoise.error := LFSRNoiseMaker(1)(0)
|
|
|
|
|
|
|
|
val dnoise = Wire(out.d.bits)
|
|
|
|
dnoise.opcode := LFSRNoiseMaker(3)
|
|
|
|
dnoise.param := LFSRNoiseMaker(3)
|
|
|
|
dnoise.size := LFSRNoiseMaker(dnoise.params.sizeBits)
|
|
|
|
dnoise.source := LFSRNoiseMaker(dnoise.params.sourceBits)
|
|
|
|
dnoise.sink := LFSRNoiseMaker(dnoise.params.sinkBits)
|
|
|
|
dnoise.data := LFSRNoiseMaker(dnoise.params.dataBits)
|
|
|
|
dnoise.error := LFSRNoiseMaker(1)(0)
|
|
|
|
|
|
|
|
val enoise = Wire(in.e.bits)
|
|
|
|
enoise.sink := LFSRNoiseMaker(enoise.params.sinkBits)
|
|
|
|
|
|
|
|
feed(out.a, in.a, anoise)
|
|
|
|
feed(out.c, in.c, cnoise)
|
|
|
|
feed(out.e, in.e, enoise)
|
|
|
|
feed(in.b, out.b, bnoise)
|
|
|
|
feed(in.d, out.d, dnoise)
|
2017-01-22 01:52:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object TLDelayer
|
|
|
|
{
|
2017-12-01 20:27:54 +01:00
|
|
|
def apply(q: Double)(implicit p: Parameters): TLNode =
|
|
|
|
{
|
|
|
|
val delayer = LazyModule(new TLDelayer(q))
|
|
|
|
delayer.node
|
|
|
|
}
|
2017-01-22 01:52:40 +01:00
|
|
|
}
|