First cut at refactoring unittests into a top-level utility. Individual tests co-located with their DUT. No functional changes.
This commit is contained in:
parent
dfd6bfb454
commit
7dd4492abb
@ -8,9 +8,8 @@ import uncore.tilelink._
|
|||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import uncore.unittests._
|
import unittest._
|
||||||
import junctions._
|
import junctions._
|
||||||
import junctions.unittests._
|
|
||||||
import scala.collection.mutable.LinkedHashSet
|
import scala.collection.mutable.LinkedHashSet
|
||||||
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
||||||
import scala.math.max
|
import scala.math.max
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package coreplex
|
package coreplex
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import junctions.unittests.UnitTestSuite
|
import unittest.UnitTestSuite
|
||||||
import rocket.Tile
|
import rocket.Tile
|
||||||
import uncore.tilelink.TLId
|
import uncore.tilelink.TLId
|
||||||
import cde.Parameters
|
import cde.Parameters
|
||||||
|
@ -5,6 +5,7 @@ import uncore.tilelink._
|
|||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import junctions._
|
import junctions._
|
||||||
import rocket._
|
import rocket._
|
||||||
|
import util.Timer
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import uncore.devices.NTiles
|
|||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import junctions._
|
import junctions._
|
||||||
import rocket._
|
import rocket._
|
||||||
|
import util.Timer
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import Chisel._
|
|||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
import junctions._
|
import junctions._
|
||||||
|
import util.Timer
|
||||||
import rocket.TileId
|
import rocket.TileId
|
||||||
import cde.Parameters
|
import cde.Parameters
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ import uncore.tilelink._
|
|||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import junctions.{ParameterizedBundle, HasAddrMapParameters, Timer}
|
import junctions.{ParameterizedBundle, HasAddrMapParameters}
|
||||||
|
import util.Timer
|
||||||
import rocket.HellaCacheIO
|
import rocket.HellaCacheIO
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import uncore.constants._
|
|||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import junctions._
|
import junctions._
|
||||||
import rocket._
|
import rocket._
|
||||||
|
import util.{Timer, DynamicTimer}
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
|
@ -2,35 +2,6 @@ package groundtest
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
// =============
|
|
||||||
// Dynamic timer
|
|
||||||
// =============
|
|
||||||
|
|
||||||
// Timer with a dynamically-settable period.
|
|
||||||
|
|
||||||
class DynamicTimer(w: Int) extends Module {
|
|
||||||
val io = new Bundle {
|
|
||||||
val start = Bool(INPUT)
|
|
||||||
val period = UInt(INPUT, w)
|
|
||||||
val stop = Bool(INPUT)
|
|
||||||
val timeout = Bool(OUTPUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
val countdown = Reg(init = UInt(0, w))
|
|
||||||
val active = Reg(init = Bool(false))
|
|
||||||
|
|
||||||
when (io.start) {
|
|
||||||
countdown := io.period
|
|
||||||
active := Bool(true)
|
|
||||||
} .elsewhen (io.stop || countdown === UInt(0)) {
|
|
||||||
active := Bool(false)
|
|
||||||
} .elsewhen (active) {
|
|
||||||
countdown := countdown - UInt(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.timeout := countdown === UInt(0) && active
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// LCG16 module
|
// LCG16 module
|
||||||
// ============
|
// ============
|
||||||
|
158
src/main/scala/junctions/MultiWidthFifo.scala
Normal file
158
src/main/scala/junctions/MultiWidthFifo.scala
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package junctions
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import unittest.UnitTest
|
||||||
|
|
||||||
|
class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module {
|
||||||
|
val io = new Bundle {
|
||||||
|
val in = Decoupled(Bits(width = inW)).flip
|
||||||
|
val out = Decoupled(Bits(width = outW))
|
||||||
|
val count = UInt(OUTPUT, log2Up(n + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inW == outW) {
|
||||||
|
val q = Module(new Queue(Bits(width = inW), n))
|
||||||
|
q.io.enq <> io.in
|
||||||
|
io.out <> q.io.deq
|
||||||
|
io.count := q.io.count
|
||||||
|
} else if (inW > outW) {
|
||||||
|
val nBeats = inW / outW
|
||||||
|
|
||||||
|
require(inW % outW == 0, s"MultiWidthFifo: in: $inW not divisible by out: $outW")
|
||||||
|
require(n % nBeats == 0, s"Cannot store $n output words when output beats is $nBeats")
|
||||||
|
|
||||||
|
val wdata = Reg(Vec(n / nBeats, Bits(width = inW)))
|
||||||
|
val rdata = Vec(wdata.flatMap { indat =>
|
||||||
|
(0 until nBeats).map(i => indat(outW * (i + 1) - 1, outW * i)) })
|
||||||
|
|
||||||
|
val head = Reg(init = UInt(0, log2Up(n / nBeats)))
|
||||||
|
val tail = Reg(init = UInt(0, log2Up(n)))
|
||||||
|
val size = Reg(init = UInt(0, log2Up(n + 1)))
|
||||||
|
|
||||||
|
when (io.in.fire()) {
|
||||||
|
wdata(head) := io.in.bits
|
||||||
|
head := head + UInt(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (io.out.fire()) { tail := tail + UInt(1) }
|
||||||
|
|
||||||
|
size := MuxCase(size, Seq(
|
||||||
|
(io.in.fire() && io.out.fire()) -> (size + UInt(nBeats - 1)),
|
||||||
|
io.in.fire() -> (size + UInt(nBeats)),
|
||||||
|
io.out.fire() -> (size - UInt(1))))
|
||||||
|
|
||||||
|
io.out.valid := size > UInt(0)
|
||||||
|
io.out.bits := rdata(tail)
|
||||||
|
io.in.ready := size < UInt(n)
|
||||||
|
io.count := size
|
||||||
|
} else {
|
||||||
|
val nBeats = outW / inW
|
||||||
|
|
||||||
|
require(outW % inW == 0, s"MultiWidthFifo: out: $outW not divisible by in: $inW")
|
||||||
|
|
||||||
|
val wdata = Reg(Vec(n * nBeats, Bits(width = inW)))
|
||||||
|
val rdata = Vec.tabulate(n) { i =>
|
||||||
|
Cat(wdata.slice(i * nBeats, (i + 1) * nBeats).reverse)}
|
||||||
|
|
||||||
|
val head = Reg(init = UInt(0, log2Up(n * nBeats)))
|
||||||
|
val tail = Reg(init = UInt(0, log2Up(n)))
|
||||||
|
val size = Reg(init = UInt(0, log2Up(n * nBeats + 1)))
|
||||||
|
|
||||||
|
when (io.in.fire()) {
|
||||||
|
wdata(head) := io.in.bits
|
||||||
|
head := head + UInt(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (io.out.fire()) { tail := tail + UInt(1) }
|
||||||
|
|
||||||
|
size := MuxCase(size, Seq(
|
||||||
|
(io.in.fire() && io.out.fire()) -> (size - UInt(nBeats - 1)),
|
||||||
|
io.in.fire() -> (size + UInt(1)),
|
||||||
|
io.out.fire() -> (size - UInt(nBeats))))
|
||||||
|
|
||||||
|
io.count := size >> UInt(log2Up(nBeats))
|
||||||
|
io.out.valid := io.count > UInt(0)
|
||||||
|
io.out.bits := rdata(tail)
|
||||||
|
io.in.ready := size < UInt(n * nBeats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiWidthFifoTest extends UnitTest {
|
||||||
|
val big2little = Module(new MultiWidthFifo(16, 8, 8))
|
||||||
|
val little2big = Module(new MultiWidthFifo(8, 16, 4))
|
||||||
|
|
||||||
|
val bl_send = Reg(init = Bool(false))
|
||||||
|
val lb_send = Reg(init = Bool(false))
|
||||||
|
val bl_recv = Reg(init = Bool(false))
|
||||||
|
val lb_recv = Reg(init = Bool(false))
|
||||||
|
val bl_finished = Reg(init = Bool(false))
|
||||||
|
val lb_finished = Reg(init = Bool(false))
|
||||||
|
|
||||||
|
val bl_data = Vec.tabulate(4){i => UInt((2 * i + 1) * 256 + 2 * i, 16)}
|
||||||
|
val lb_data = Vec.tabulate(8){i => UInt(i, 8)}
|
||||||
|
|
||||||
|
val (bl_send_cnt, bl_send_done) = Counter(big2little.io.in.fire(), 4)
|
||||||
|
val (lb_send_cnt, lb_send_done) = Counter(little2big.io.in.fire(), 8)
|
||||||
|
|
||||||
|
val (bl_recv_cnt, bl_recv_done) = Counter(big2little.io.out.fire(), 8)
|
||||||
|
val (lb_recv_cnt, lb_recv_done) = Counter(little2big.io.out.fire(), 4)
|
||||||
|
|
||||||
|
big2little.io.in.valid := bl_send
|
||||||
|
big2little.io.in.bits := bl_data(bl_send_cnt)
|
||||||
|
big2little.io.out.ready := bl_recv
|
||||||
|
|
||||||
|
little2big.io.in.valid := lb_send
|
||||||
|
little2big.io.in.bits := lb_data(lb_send_cnt)
|
||||||
|
little2big.io.out.ready := lb_recv
|
||||||
|
|
||||||
|
val bl_recv_data_idx = bl_recv_cnt >> UInt(1)
|
||||||
|
val bl_recv_data = Mux(bl_recv_cnt(0),
|
||||||
|
bl_data(bl_recv_data_idx)(15, 8),
|
||||||
|
bl_data(bl_recv_data_idx)(7, 0))
|
||||||
|
|
||||||
|
val lb_recv_data = Cat(
|
||||||
|
lb_data(Cat(lb_recv_cnt, UInt(1, 1))),
|
||||||
|
lb_data(Cat(lb_recv_cnt, UInt(0, 1))))
|
||||||
|
|
||||||
|
when (io.start) {
|
||||||
|
bl_send := Bool(true)
|
||||||
|
lb_send := Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (bl_send_done) {
|
||||||
|
bl_send := Bool(false)
|
||||||
|
bl_recv := Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (lb_send_done) {
|
||||||
|
lb_send := Bool(false)
|
||||||
|
lb_recv := Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (bl_recv_done) {
|
||||||
|
bl_recv := Bool(false)
|
||||||
|
bl_finished := Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (lb_recv_done) {
|
||||||
|
lb_recv := Bool(false)
|
||||||
|
lb_finished := Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.finished := bl_finished && lb_finished
|
||||||
|
|
||||||
|
val bl_start_recv = Reg(next = bl_send_done)
|
||||||
|
val lb_start_recv = Reg(next = lb_send_done)
|
||||||
|
|
||||||
|
assert(!little2big.io.out.valid || little2big.io.out.bits === lb_recv_data,
|
||||||
|
"Little to Big data mismatch")
|
||||||
|
assert(!big2little.io.out.valid || big2little.io.out.bits === bl_recv_data,
|
||||||
|
"Bit to Little data mismatch")
|
||||||
|
|
||||||
|
assert(!lb_start_recv || little2big.io.count === UInt(4),
|
||||||
|
"Little to Big count incorrect")
|
||||||
|
assert(!bl_start_recv || big2little.io.count === UInt(8),
|
||||||
|
"Big to Little count incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
|||||||
package junctions.unittests
|
package junctions
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import junctions._
|
|
||||||
import junctions.NastiConstants._
|
|
||||||
import cde.Parameters
|
import cde.Parameters
|
||||||
|
|
||||||
class NastiDemuxDriver(n: Int)(implicit p: Parameters) extends Module {
|
class NastiDemuxDriver(n: Int)(implicit p: Parameters) extends Module {
|
||||||
@ -93,7 +91,7 @@ class NastiDemuxSlave(implicit p: Parameters) extends NastiModule()(p) {
|
|||||||
io.r.bits := NastiReadDataChannel(id = id, data = value)
|
io.r.bits := NastiReadDataChannel(id = id, data = value)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NastiMemoryDemuxTest(implicit p: Parameters) extends UnitTest {
|
class NastiMemoryDemuxTest(implicit p: Parameters) extends unittest.UnitTest {
|
||||||
val nSlaves = 4
|
val nSlaves = 4
|
||||||
|
|
||||||
val driver = Module(new NastiDemuxDriver(nSlaves))
|
val driver = Module(new NastiDemuxDriver(nSlaves))
|
@ -1,8 +1,6 @@
|
|||||||
package junctions.unittests
|
package junctions
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import junctions._
|
|
||||||
import junctions.NastiConstants._
|
|
||||||
import cde.Parameters
|
import cde.Parameters
|
||||||
|
|
||||||
class NastiDriver(dataWidth: Int, burstLen: Int, nBursts: Int)
|
class NastiDriver(dataWidth: Int, burstLen: Int, nBursts: Int)
|
||||||
@ -76,16 +74,3 @@ class NastiDriver(dataWidth: Int, burstLen: Int, nBursts: Int)
|
|||||||
assert(!io.nasti.r.valid || read_data === expected_data,
|
assert(!io.nasti.r.valid || read_data === expected_data,
|
||||||
s"NastiDriver got wrong data")
|
s"NastiDriver got wrong data")
|
||||||
}
|
}
|
||||||
|
|
||||||
class HastiTest(implicit p: Parameters) extends UnitTest {
|
|
||||||
val sram = Module(new HastiTestSRAM(8))
|
|
||||||
val bus = Module(new HastiBus(Seq(a => Bool(true))))
|
|
||||||
val conv = Module(new HastiMasterIONastiIOConverter)
|
|
||||||
val driver = Module(new NastiDriver(32, 8, 2))
|
|
||||||
|
|
||||||
bus.io.slaves(0) <> sram.io
|
|
||||||
bus.io.master <> conv.io.hasti
|
|
||||||
conv.io.nasti <> driver.io.nasti
|
|
||||||
io.finished := driver.io.finished
|
|
||||||
driver.io.start := io.start
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package junctions
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
import unittest.UnitTest
|
||||||
|
|
||||||
object HastiConstants
|
object HastiConstants
|
||||||
{
|
{
|
||||||
@ -547,3 +548,16 @@ class HastiTestSRAM(depth: Int)(implicit p: Parameters) extends HastiModule()(p)
|
|||||||
io.hready := ready
|
io.hready := ready
|
||||||
io.hresp := HRESP_OKAY
|
io.hresp := HRESP_OKAY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HastiTest(implicit p: Parameters) extends UnitTest {
|
||||||
|
val sram = Module(new HastiTestSRAM(8))
|
||||||
|
val bus = Module(new HastiBus(Seq(a => Bool(true))))
|
||||||
|
val conv = Module(new HastiMasterIONastiIOConverter)
|
||||||
|
val driver = Module(new NastiDriver(32, 8, 2))
|
||||||
|
|
||||||
|
bus.io.slaves(0) <> sram.io
|
||||||
|
bus.io.master <> conv.io.hasti
|
||||||
|
conv.io.nasti <> driver.io.nasti
|
||||||
|
io.finished := driver.io.finished
|
||||||
|
driver.io.start := io.start
|
||||||
|
}
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
package junctions.unittests
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
import junctions._
|
|
||||||
import junctions.NastiConstants._
|
|
||||||
|
|
||||||
class MultiWidthFifoTest extends UnitTest {
|
|
||||||
val big2little = Module(new MultiWidthFifo(16, 8, 8))
|
|
||||||
val little2big = Module(new MultiWidthFifo(8, 16, 4))
|
|
||||||
|
|
||||||
val bl_send = Reg(init = Bool(false))
|
|
||||||
val lb_send = Reg(init = Bool(false))
|
|
||||||
val bl_recv = Reg(init = Bool(false))
|
|
||||||
val lb_recv = Reg(init = Bool(false))
|
|
||||||
val bl_finished = Reg(init = Bool(false))
|
|
||||||
val lb_finished = Reg(init = Bool(false))
|
|
||||||
|
|
||||||
val bl_data = Vec.tabulate(4){i => UInt((2 * i + 1) * 256 + 2 * i, 16)}
|
|
||||||
val lb_data = Vec.tabulate(8){i => UInt(i, 8)}
|
|
||||||
|
|
||||||
val (bl_send_cnt, bl_send_done) = Counter(big2little.io.in.fire(), 4)
|
|
||||||
val (lb_send_cnt, lb_send_done) = Counter(little2big.io.in.fire(), 8)
|
|
||||||
|
|
||||||
val (bl_recv_cnt, bl_recv_done) = Counter(big2little.io.out.fire(), 8)
|
|
||||||
val (lb_recv_cnt, lb_recv_done) = Counter(little2big.io.out.fire(), 4)
|
|
||||||
|
|
||||||
big2little.io.in.valid := bl_send
|
|
||||||
big2little.io.in.bits := bl_data(bl_send_cnt)
|
|
||||||
big2little.io.out.ready := bl_recv
|
|
||||||
|
|
||||||
little2big.io.in.valid := lb_send
|
|
||||||
little2big.io.in.bits := lb_data(lb_send_cnt)
|
|
||||||
little2big.io.out.ready := lb_recv
|
|
||||||
|
|
||||||
val bl_recv_data_idx = bl_recv_cnt >> UInt(1)
|
|
||||||
val bl_recv_data = Mux(bl_recv_cnt(0),
|
|
||||||
bl_data(bl_recv_data_idx)(15, 8),
|
|
||||||
bl_data(bl_recv_data_idx)(7, 0))
|
|
||||||
|
|
||||||
val lb_recv_data = Cat(
|
|
||||||
lb_data(Cat(lb_recv_cnt, UInt(1, 1))),
|
|
||||||
lb_data(Cat(lb_recv_cnt, UInt(0, 1))))
|
|
||||||
|
|
||||||
when (io.start) {
|
|
||||||
bl_send := Bool(true)
|
|
||||||
lb_send := Bool(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (bl_send_done) {
|
|
||||||
bl_send := Bool(false)
|
|
||||||
bl_recv := Bool(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (lb_send_done) {
|
|
||||||
lb_send := Bool(false)
|
|
||||||
lb_recv := Bool(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (bl_recv_done) {
|
|
||||||
bl_recv := Bool(false)
|
|
||||||
bl_finished := Bool(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (lb_recv_done) {
|
|
||||||
lb_recv := Bool(false)
|
|
||||||
lb_finished := Bool(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.finished := bl_finished && lb_finished
|
|
||||||
|
|
||||||
val bl_start_recv = Reg(next = bl_send_done)
|
|
||||||
val lb_start_recv = Reg(next = lb_send_done)
|
|
||||||
|
|
||||||
assert(!little2big.io.out.valid || little2big.io.out.bits === lb_recv_data,
|
|
||||||
"Little to Big data mismatch")
|
|
||||||
assert(!big2little.io.out.valid || big2little.io.out.bits === bl_recv_data,
|
|
||||||
"Bit to Little data mismatch")
|
|
||||||
|
|
||||||
assert(!lb_start_recv || little2big.io.count === UInt(4),
|
|
||||||
"Little to Big count incorrect")
|
|
||||||
assert(!bl_start_recv || big2little.io.count === UInt(8),
|
|
||||||
"Big to Little count incorrect")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -244,128 +244,3 @@ class DecoupledHelper(val rvs: Seq[Bool]) {
|
|||||||
(rvs.filter(_ ne exclude) ++ includes).reduce(_ && _)
|
(rvs.filter(_ ne exclude) ++ includes).reduce(_ && _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module {
|
|
||||||
val io = new Bundle {
|
|
||||||
val in = Decoupled(Bits(width = inW)).flip
|
|
||||||
val out = Decoupled(Bits(width = outW))
|
|
||||||
val count = UInt(OUTPUT, log2Up(n + 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inW == outW) {
|
|
||||||
val q = Module(new Queue(Bits(width = inW), n))
|
|
||||||
q.io.enq <> io.in
|
|
||||||
io.out <> q.io.deq
|
|
||||||
io.count := q.io.count
|
|
||||||
} else if (inW > outW) {
|
|
||||||
val nBeats = inW / outW
|
|
||||||
|
|
||||||
require(inW % outW == 0, s"MultiWidthFifo: in: $inW not divisible by out: $outW")
|
|
||||||
require(n % nBeats == 0, s"Cannot store $n output words when output beats is $nBeats")
|
|
||||||
|
|
||||||
val wdata = Reg(Vec(n / nBeats, Bits(width = inW)))
|
|
||||||
val rdata = Vec(wdata.flatMap { indat =>
|
|
||||||
(0 until nBeats).map(i => indat(outW * (i + 1) - 1, outW * i)) })
|
|
||||||
|
|
||||||
val head = Reg(init = UInt(0, log2Up(n / nBeats)))
|
|
||||||
val tail = Reg(init = UInt(0, log2Up(n)))
|
|
||||||
val size = Reg(init = UInt(0, log2Up(n + 1)))
|
|
||||||
|
|
||||||
when (io.in.fire()) {
|
|
||||||
wdata(head) := io.in.bits
|
|
||||||
head := head + UInt(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (io.out.fire()) { tail := tail + UInt(1) }
|
|
||||||
|
|
||||||
size := MuxCase(size, Seq(
|
|
||||||
(io.in.fire() && io.out.fire()) -> (size + UInt(nBeats - 1)),
|
|
||||||
io.in.fire() -> (size + UInt(nBeats)),
|
|
||||||
io.out.fire() -> (size - UInt(1))))
|
|
||||||
|
|
||||||
io.out.valid := size > UInt(0)
|
|
||||||
io.out.bits := rdata(tail)
|
|
||||||
io.in.ready := size < UInt(n)
|
|
||||||
io.count := size
|
|
||||||
} else {
|
|
||||||
val nBeats = outW / inW
|
|
||||||
|
|
||||||
require(outW % inW == 0, s"MultiWidthFifo: out: $outW not divisible by in: $inW")
|
|
||||||
|
|
||||||
val wdata = Reg(Vec(n * nBeats, Bits(width = inW)))
|
|
||||||
val rdata = Vec.tabulate(n) { i =>
|
|
||||||
Cat(wdata.slice(i * nBeats, (i + 1) * nBeats).reverse)}
|
|
||||||
|
|
||||||
val head = Reg(init = UInt(0, log2Up(n * nBeats)))
|
|
||||||
val tail = Reg(init = UInt(0, log2Up(n)))
|
|
||||||
val size = Reg(init = UInt(0, log2Up(n * nBeats + 1)))
|
|
||||||
|
|
||||||
when (io.in.fire()) {
|
|
||||||
wdata(head) := io.in.bits
|
|
||||||
head := head + UInt(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (io.out.fire()) { tail := tail + UInt(1) }
|
|
||||||
|
|
||||||
size := MuxCase(size, Seq(
|
|
||||||
(io.in.fire() && io.out.fire()) -> (size - UInt(nBeats - 1)),
|
|
||||||
io.in.fire() -> (size + UInt(1)),
|
|
||||||
io.out.fire() -> (size - UInt(nBeats))))
|
|
||||||
|
|
||||||
io.count := size >> UInt(log2Up(nBeats))
|
|
||||||
io.out.valid := io.count > UInt(0)
|
|
||||||
io.out.bits := rdata(tail)
|
|
||||||
io.in.ready := size < UInt(n * nBeats)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============
|
|
||||||
// Static timer
|
|
||||||
// ============
|
|
||||||
|
|
||||||
// Timer with a statically-specified period.
|
|
||||||
// Can take multiple inflight start-stop events with ID
|
|
||||||
// Will continue to count down as long as at least one event is inflight
|
|
||||||
|
|
||||||
class Timer(initCount: Int, maxInflight: Int) extends Module {
|
|
||||||
val io = new Bundle {
|
|
||||||
val start = Valid(UInt(width = log2Up(maxInflight))).flip
|
|
||||||
val stop = Valid(UInt(width = log2Up(maxInflight))).flip
|
|
||||||
val timeout = Valid(UInt(width = log2Up(maxInflight)))
|
|
||||||
}
|
|
||||||
|
|
||||||
val inflight = Reg(init = Vec.fill(maxInflight) { Bool(false) })
|
|
||||||
val countdown = Reg(UInt(width = log2Up(initCount)))
|
|
||||||
val active = inflight.reduce(_ || _)
|
|
||||||
|
|
||||||
when (active) {
|
|
||||||
countdown := countdown - UInt(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (io.start.valid) {
|
|
||||||
inflight(io.start.bits) := Bool(true)
|
|
||||||
countdown := UInt(initCount - 1)
|
|
||||||
}
|
|
||||||
when (io.stop.valid) {
|
|
||||||
inflight(io.stop.bits) := Bool(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.timeout.valid := countdown === UInt(0) && active
|
|
||||||
io.timeout.bits := PriorityEncoder(inflight)
|
|
||||||
|
|
||||||
assert(!io.stop.valid || inflight(io.stop.bits),
|
|
||||||
"Timer stop for transaction that's not inflight")
|
|
||||||
}
|
|
||||||
|
|
||||||
object Timer {
|
|
||||||
def apply(initCount: Int, start: Bool, stop: Bool): Bool = {
|
|
||||||
val timer = Module(new Timer(initCount, 1))
|
|
||||||
timer.io.start.valid := start
|
|
||||||
timer.io.start.bits := UInt(0)
|
|
||||||
timer.io.stop.valid := stop
|
|
||||||
timer.io.stop.bits := UInt(0)
|
|
||||||
timer.io.timeout.valid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,9 +7,8 @@ import uncore.tilelink._
|
|||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import uncore.unittests._
|
import unittest._
|
||||||
import junctions._
|
import junctions._
|
||||||
import junctions.unittests._
|
|
||||||
import scala.collection.mutable.LinkedHashSet
|
import scala.collection.mutable.LinkedHashSet
|
||||||
import scala.collection.immutable.HashMap
|
import scala.collection.immutable.HashMap
|
||||||
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
||||||
|
@ -30,3 +30,30 @@ class SmiIOTileLinkIOConverter(val dataWidth: Int, val addrWidth: Int)
|
|||||||
decoupledNastiConnect(nasti2smi.io.nasti, tl2nasti.io.nasti)
|
decoupledNastiConnect(nasti2smi.io.nasti, tl2nasti.io.nasti)
|
||||||
io.smi <> nasti2smi.io.smi
|
io.smi <> nasti2smi.io.smi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SmiConverterTest(implicit val p: Parameters) extends unittest.UnitTest
|
||||||
|
with HasTileLinkParameters {
|
||||||
|
val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
||||||
|
|
||||||
|
val smiWidth = 32
|
||||||
|
val smiDepth = 64
|
||||||
|
val tlDepth = (smiWidth * smiDepth) / tlDataBits
|
||||||
|
|
||||||
|
val smimem = Module(new SmiMem(smiWidth, smiDepth))
|
||||||
|
val conv = Module(new SmiIOTileLinkIOConverter(
|
||||||
|
smiWidth, log2Up(smiDepth))(outermostParams))
|
||||||
|
val driver = Module(new DriverSet(
|
||||||
|
(driverParams: Parameters) => {
|
||||||
|
implicit val p = driverParams
|
||||||
|
Seq(
|
||||||
|
Module(new PutSweepDriver(tlDepth)),
|
||||||
|
Module(new PutMaskDriver(smiWidth / 8)),
|
||||||
|
Module(new PutBlockSweepDriver(tlDepth / tlDataBeats)),
|
||||||
|
Module(new GetMultiWidthDriver))
|
||||||
|
})(outermostParams))
|
||||||
|
|
||||||
|
conv.io.tl <> driver.io.mem
|
||||||
|
smimem.io <> conv.io.smi
|
||||||
|
driver.io.start := io.start
|
||||||
|
io.finished := driver.io.finished
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package uncore.devices
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
import unittest.UnitTest
|
||||||
import junctions._
|
import junctions._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
@ -159,3 +160,24 @@ class TileLinkTestRAM(depth: Int)(implicit val p: Parameters) extends Module
|
|||||||
ram(acq_addr) := (old_data & ~wmask) | (result & wmask)
|
ram(acq_addr) := (old_data & ~wmask) | (result & wmask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TileLinkRAMTest(implicit val p: Parameters)
|
||||||
|
extends UnitTest with HasTileLinkParameters {
|
||||||
|
|
||||||
|
val depth = 2 * tlDataBeats
|
||||||
|
val ram = Module(new TileLinkTestRAM(depth))
|
||||||
|
val driver = Module(new DriverSet(
|
||||||
|
(driverParams: Parameters) => {
|
||||||
|
implicit val p = driverParams
|
||||||
|
Seq(
|
||||||
|
Module(new PutSweepDriver(depth)),
|
||||||
|
Module(new PutMaskDriver),
|
||||||
|
Module(new PutAtomicDriver),
|
||||||
|
Module(new PutBlockSweepDriver(depth / tlDataBeats)),
|
||||||
|
Module(new PrefetchDriver),
|
||||||
|
Module(new GetMultiWidthDriver))
|
||||||
|
}))
|
||||||
|
ram.io <> driver.io.mem
|
||||||
|
driver.io.start := io.start
|
||||||
|
io.finished := driver.io.finished
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package uncore.devices
|
package uncore.devices
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import unittest.UnitTest
|
||||||
import junctions._
|
import junctions._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
@ -41,6 +42,26 @@ class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module
|
|||||||
data = rdata)
|
data = rdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ROMSlaveTest(implicit p: Parameters) extends UnitTest {
|
||||||
|
implicit val testName = "ROMSlaveTest"
|
||||||
|
val romdata = Seq(
|
||||||
|
BigInt("01234567deadbeef", 16),
|
||||||
|
BigInt("ab32fee8d00dfeed", 16))
|
||||||
|
val rombytes = romdata.map(_.toByteArray.reverse).flatten
|
||||||
|
val rom = Module(new ROMSlave(rombytes))
|
||||||
|
val driver = Module(new DriverSet(
|
||||||
|
(driverParams: Parameters) => {
|
||||||
|
implicit val p = driverParams
|
||||||
|
Seq(
|
||||||
|
Module(new GetMultiWidthDriver),
|
||||||
|
Module(new GetSweepDriver(romdata)),
|
||||||
|
Module(new GetBlockSweepDriver(romdata)))
|
||||||
|
}))
|
||||||
|
rom.io <> driver.io.mem
|
||||||
|
driver.io.start := io.start
|
||||||
|
io.finished := driver.io.finished
|
||||||
|
}
|
||||||
|
|
||||||
class NastiROM(contents: Seq[Byte])(implicit p: Parameters) extends Module {
|
class NastiROM(contents: Seq[Byte])(implicit p: Parameters) extends Module {
|
||||||
val io = new NastiIO().flip
|
val io = new NastiIO().flip
|
||||||
val ar = Queue(io.ar, 1)
|
val ar = Queue(io.ar, 1)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package uncore.unittests
|
package uncore.tilelink
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import junctions._
|
import junctions._
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import cde.Parameters
|
import cde.Parameters
|
@ -3,7 +3,7 @@ package uncore.tilelink2
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import chisel3.util.LFSR16
|
import chisel3.util.LFSR16
|
||||||
import junctions.unittests._
|
import unittest._
|
||||||
|
|
||||||
class IDMapGenerator(numIds: Int) extends Module {
|
class IDMapGenerator(numIds: Int) extends Module {
|
||||||
val w = log2Up(numIds)
|
val w = log2Up(numIds)
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
package uncore.unittests
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
import junctions._
|
|
||||||
import junctions.unittests._
|
|
||||||
import uncore.devices._
|
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.converters._
|
|
||||||
import cde.Parameters
|
|
||||||
|
|
||||||
class SmiConverterTest(implicit val p: Parameters) extends UnitTest
|
|
||||||
with HasTileLinkParameters {
|
|
||||||
val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
|
||||||
|
|
||||||
val smiWidth = 32
|
|
||||||
val smiDepth = 64
|
|
||||||
val tlDepth = (smiWidth * smiDepth) / tlDataBits
|
|
||||||
|
|
||||||
val smimem = Module(new SmiMem(smiWidth, smiDepth))
|
|
||||||
val conv = Module(new SmiIOTileLinkIOConverter(
|
|
||||||
smiWidth, log2Up(smiDepth))(outermostParams))
|
|
||||||
val driver = Module(new DriverSet(
|
|
||||||
(driverParams: Parameters) => {
|
|
||||||
implicit val p = driverParams
|
|
||||||
Seq(
|
|
||||||
Module(new PutSweepDriver(tlDepth)),
|
|
||||||
Module(new PutMaskDriver(smiWidth / 8)),
|
|
||||||
Module(new PutBlockSweepDriver(tlDepth / tlDataBeats)),
|
|
||||||
Module(new GetMultiWidthDriver))
|
|
||||||
})(outermostParams))
|
|
||||||
|
|
||||||
conv.io.tl <> driver.io.mem
|
|
||||||
smimem.io <> conv.io.smi
|
|
||||||
driver.io.start := io.start
|
|
||||||
io.finished := driver.io.finished
|
|
||||||
}
|
|
||||||
|
|
||||||
class ROMSlaveTest(implicit p: Parameters) extends UnitTest {
|
|
||||||
implicit val testName = "ROMSlaveTest"
|
|
||||||
val romdata = Seq(
|
|
||||||
BigInt("01234567deadbeef", 16),
|
|
||||||
BigInt("ab32fee8d00dfeed", 16))
|
|
||||||
val rombytes = romdata.map(_.toByteArray.reverse).flatten
|
|
||||||
val rom = Module(new ROMSlave(rombytes))
|
|
||||||
val driver = Module(new DriverSet(
|
|
||||||
(driverParams: Parameters) => {
|
|
||||||
implicit val p = driverParams
|
|
||||||
Seq(
|
|
||||||
Module(new GetMultiWidthDriver),
|
|
||||||
Module(new GetSweepDriver(romdata)),
|
|
||||||
Module(new GetBlockSweepDriver(romdata)))
|
|
||||||
}))
|
|
||||||
rom.io <> driver.io.mem
|
|
||||||
driver.io.start := io.start
|
|
||||||
io.finished := driver.io.finished
|
|
||||||
}
|
|
||||||
|
|
||||||
class TileLinkRAMTest(implicit val p: Parameters)
|
|
||||||
extends UnitTest with HasTileLinkParameters {
|
|
||||||
|
|
||||||
val depth = 2 * tlDataBeats
|
|
||||||
val ram = Module(new TileLinkTestRAM(depth))
|
|
||||||
val driver = Module(new DriverSet(
|
|
||||||
(driverParams: Parameters) => {
|
|
||||||
implicit val p = driverParams
|
|
||||||
Seq(
|
|
||||||
Module(new PutSweepDriver(depth)),
|
|
||||||
Module(new PutMaskDriver),
|
|
||||||
Module(new PutAtomicDriver),
|
|
||||||
Module(new PutBlockSweepDriver(depth / tlDataBeats)),
|
|
||||||
Module(new PrefetchDriver),
|
|
||||||
Module(new GetMultiWidthDriver))
|
|
||||||
}))
|
|
||||||
ram.io <> driver.io.mem
|
|
||||||
driver.io.start := io.start
|
|
||||||
io.finished := driver.io.finished
|
|
||||||
}
|
|
||||||
|
|
||||||
object UncoreUnitTests {
|
|
||||||
def apply(implicit p: Parameters): Seq[UnitTest] =
|
|
||||||
Seq(
|
|
||||||
Module(new SmiConverterTest),
|
|
||||||
Module(new ROMSlaveTest),
|
|
||||||
Module(new TileLinkRAMTest),
|
|
||||||
Module(new uncore.tilelink2.TLFuzzRAMTest))
|
|
||||||
}
|
|
21
src/main/scala/unittest/TempListOfTests.scala
Normal file
21
src/main/scala/unittest/TempListOfTests.scala
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package unittest
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import cde.Parameters
|
||||||
|
|
||||||
|
object JunctionsUnitTests {
|
||||||
|
def apply(implicit p: Parameters): Seq[UnitTest] =
|
||||||
|
Seq(
|
||||||
|
Module(new junctions.MultiWidthFifoTest),
|
||||||
|
Module(new junctions.NastiMemoryDemuxTest),
|
||||||
|
Module(new junctions.HastiTest))
|
||||||
|
}
|
||||||
|
|
||||||
|
object UncoreUnitTests {
|
||||||
|
def apply(implicit p: Parameters): Seq[UnitTest] =
|
||||||
|
Seq(
|
||||||
|
Module(new uncore.converters.SmiConverterTest),
|
||||||
|
Module(new uncore.devices.ROMSlaveTest),
|
||||||
|
Module(new uncore.devices.TileLinkRAMTest),
|
||||||
|
Module(new uncore.tilelink2.TLFuzzRAMTest))
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package junctions.unittests
|
package unittest
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import junctions._
|
|
||||||
import cde.{Field, Parameters}
|
import cde.{Field, Parameters}
|
||||||
|
import util.Timer
|
||||||
|
|
||||||
trait HasUnitTestIO {
|
trait HasUnitTestIO {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
@ -56,11 +56,3 @@ class UnitTestSuite(implicit p: Parameters) extends Module {
|
|||||||
|
|
||||||
assert(!timer.io.timeout.valid, "UnitTest timed out")
|
assert(!timer.io.timeout.valid, "UnitTest timed out")
|
||||||
}
|
}
|
||||||
|
|
||||||
object JunctionsUnitTests {
|
|
||||||
def apply(implicit p: Parameters): Seq[UnitTest] =
|
|
||||||
Seq(
|
|
||||||
Module(new MultiWidthFifoTest),
|
|
||||||
Module(new NastiMemoryDemuxTest),
|
|
||||||
Module(new HastiTest))
|
|
||||||
}
|
|
74
src/main/scala/util/Timer.scala
Normal file
74
src/main/scala/util/Timer.scala
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/// See LICENSE for license details.
|
||||||
|
package util
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
/** Timer with a statically-specified period.
|
||||||
|
* Can take multiple inflight start-stop events with ID
|
||||||
|
* Will continue to count down as long as at least one event is inflight
|
||||||
|
*/
|
||||||
|
class Timer(initCount: Int, maxInflight: Int) extends Module {
|
||||||
|
val io = new Bundle {
|
||||||
|
val start = Valid(UInt(width = log2Up(maxInflight))).flip
|
||||||
|
val stop = Valid(UInt(width = log2Up(maxInflight))).flip
|
||||||
|
val timeout = Valid(UInt(width = log2Up(maxInflight)))
|
||||||
|
}
|
||||||
|
|
||||||
|
val inflight = Reg(init = Vec.fill(maxInflight) { Bool(false) })
|
||||||
|
val countdown = Reg(UInt(width = log2Up(initCount)))
|
||||||
|
val active = inflight.reduce(_ || _)
|
||||||
|
|
||||||
|
when (active) {
|
||||||
|
countdown := countdown - UInt(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (io.start.valid) {
|
||||||
|
inflight(io.start.bits) := Bool(true)
|
||||||
|
countdown := UInt(initCount - 1)
|
||||||
|
}
|
||||||
|
when (io.stop.valid) {
|
||||||
|
inflight(io.stop.bits) := Bool(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.timeout.valid := countdown === UInt(0) && active
|
||||||
|
io.timeout.bits := PriorityEncoder(inflight)
|
||||||
|
|
||||||
|
assert(!io.stop.valid || inflight(io.stop.bits),
|
||||||
|
"Timer stop for transaction that's not inflight")
|
||||||
|
}
|
||||||
|
|
||||||
|
object Timer {
|
||||||
|
def apply(initCount: Int, start: Bool, stop: Bool): Bool = {
|
||||||
|
val timer = Module(new Timer(initCount, 1))
|
||||||
|
timer.io.start.valid := start
|
||||||
|
timer.io.start.bits := UInt(0)
|
||||||
|
timer.io.stop.valid := stop
|
||||||
|
timer.io.stop.bits := UInt(0)
|
||||||
|
timer.io.timeout.valid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Timer with a statically-specified period. */
|
||||||
|
class DynamicTimer(w: Int) extends Module {
|
||||||
|
val io = new Bundle {
|
||||||
|
val start = Bool(INPUT)
|
||||||
|
val period = UInt(INPUT, w)
|
||||||
|
val stop = Bool(INPUT)
|
||||||
|
val timeout = Bool(OUTPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
val countdown = Reg(init = UInt(0, w))
|
||||||
|
val active = Reg(init = Bool(false))
|
||||||
|
|
||||||
|
when (io.start) {
|
||||||
|
countdown := io.period
|
||||||
|
active := Bool(true)
|
||||||
|
} .elsewhen (io.stop || countdown === UInt(0)) {
|
||||||
|
active := Bool(false)
|
||||||
|
} .elsewhen (active) {
|
||||||
|
countdown := countdown - UInt(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.timeout := countdown === UInt(0) && active
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user