make unit tests local to the packages being tested
This commit is contained in:
@ -4,7 +4,6 @@ import Chisel._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import uncore.agents._
|
||||
import groundtest.common._
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
class CacheFillTest(implicit p: Parameters) extends GroundTest()(p)
|
||||
|
@ -5,7 +5,6 @@ import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import junctions._
|
||||
import rocket._
|
||||
import groundtest.common._
|
||||
import scala.util.Random
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import uncore.devices.NTiles
|
||||
import uncore.constants._
|
||||
import junctions._
|
||||
import rocket._
|
||||
import groundtest.common._
|
||||
import scala.util.Random
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import Chisel._
|
||||
import uncore.tilelink._
|
||||
import uncore.converters._
|
||||
import junctions._
|
||||
import groundtest.common._
|
||||
import cde.Parameters
|
||||
|
||||
class NastiGenerator(id: Int)(implicit val p: Parameters) extends Module
|
||||
|
@ -4,9 +4,8 @@ import Chisel._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import uncore.agents._
|
||||
import junctions.{ParameterizedBundle, HasAddrMapParameters}
|
||||
import junctions.{ParameterizedBundle, HasAddrMapParameters, Timer}
|
||||
import rocket.HellaCacheIO
|
||||
import groundtest.common._
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
class RegressionIO(implicit val p: Parameters) extends ParameterizedBundle()(p) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package groundtest.common
|
||||
package groundtest
|
||||
|
||||
import Chisel._
|
||||
import rocket._
|
@ -22,7 +22,6 @@ import uncore.constants._
|
||||
import uncore.devices.NTiles
|
||||
import junctions._
|
||||
import rocket._
|
||||
import groundtest.common._
|
||||
import scala.util.Random
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
|
@ -1,56 +1,7 @@
|
||||
package groundtest.common
|
||||
package groundtest
|
||||
|
||||
import Chisel._
|
||||
|
||||
// ============
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// =============
|
||||
// Dynamic timer
|
||||
// =============
|
@ -1,423 +0,0 @@
|
||||
package groundtest.unittests
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import cde.Parameters
|
||||
|
||||
abstract class Driver(implicit p: Parameters) extends TLModule()(p) {
|
||||
val io = new Bundle {
|
||||
val mem = new ClientUncachedTileLinkIO
|
||||
val start = Bool(INPUT)
|
||||
val finished = Bool(OUTPUT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that single-beat Gets of decreasing size return subsets of the
|
||||
* data returned by larger Gets
|
||||
*/
|
||||
class GetMultiWidthDriver(implicit p: Parameters) extends Driver()(p) {
|
||||
val s_start :: s_send :: s_recv :: s_done :: Nil = Enum(Bits(), 4)
|
||||
val state = Reg(init = s_start)
|
||||
|
||||
val size = Reg(UInt(width = MT_SZ))
|
||||
val ref = Reg(UInt(width = 64))
|
||||
val bytemask = MuxLookup(size, UInt(0), Seq(
|
||||
MT_D -> UInt("hff"),
|
||||
MT_W -> UInt("h0f"),
|
||||
MT_H -> UInt("h03"),
|
||||
MT_B -> UInt("h01")))
|
||||
val bitmask = FillInterleaved(8, bytemask)
|
||||
|
||||
io.mem.acquire.valid := (state === s_send)
|
||||
io.mem.acquire.bits := Get(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0),
|
||||
addr_beat = UInt(0),
|
||||
addr_byte = UInt(0),
|
||||
operand_size = size,
|
||||
alloc = Bool(false))
|
||||
io.mem.grant.ready := (state === s_recv)
|
||||
|
||||
when (state === s_start && io.start) {
|
||||
size := MT_D
|
||||
state := s_send
|
||||
}
|
||||
|
||||
when (io.mem.acquire.fire()) { state := s_recv }
|
||||
when (io.mem.grant.fire()) {
|
||||
when (size === MT_D) { ref := io.mem.grant.bits.data }
|
||||
size := size - UInt(1)
|
||||
state := Mux(size === MT_B, s_done, s_send)
|
||||
}
|
||||
|
||||
io.finished := state === s_done
|
||||
|
||||
assert(!io.mem.grant.valid || size === MT_D ||
|
||||
(io.mem.grant.bits.data & bitmask) === (ref & bitmask),
|
||||
"GetMultiWidth: smaller get does not match larger get")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that single-beat Gets across a range of memory return
|
||||
* the expected data.
|
||||
* @param expected The values of the data expected to be read.
|
||||
* Each element is the data for one beat.
|
||||
*/
|
||||
class GetSweepDriver(expected: Seq[BigInt])
|
||||
(implicit p: Parameters) extends Driver()(p) {
|
||||
|
||||
val s_start :: s_send :: s_recv :: s_done :: Nil = Enum(Bits(), 4)
|
||||
val state = Reg(init = s_start)
|
||||
|
||||
val nReqs = expected.size
|
||||
val (req_cnt, req_done) = Counter(io.mem.grant.fire(), nReqs)
|
||||
|
||||
when (state === s_start && io.start) { state := s_send }
|
||||
when (io.mem.acquire.fire()) { state := s_recv }
|
||||
when (io.mem.grant.fire()) { state := s_send }
|
||||
when (req_done) { state := s_done }
|
||||
|
||||
val (addr_block, addr_beat) = if (nReqs > tlDataBeats) {
|
||||
(req_cnt(log2Up(nReqs) - 1, tlBeatAddrBits),
|
||||
req_cnt(tlBeatAddrBits - 1, 0))
|
||||
} else {
|
||||
(UInt(0), req_cnt)
|
||||
}
|
||||
|
||||
val exp_data = Vec(expected.map(e => UInt(e, tlDataBits)))
|
||||
|
||||
io.mem.acquire.valid := (state === s_send)
|
||||
io.mem.acquire.bits := Get(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = addr_block,
|
||||
addr_beat = addr_beat)
|
||||
io.mem.grant.ready := (state === s_recv)
|
||||
io.finished := state === s_done
|
||||
|
||||
assert(!io.mem.grant.valid || io.mem.grant.bits.data === exp_data(req_cnt),
|
||||
"GetSweep: data does not match expected")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that multi-beat GetBlocks across a range of memory return
|
||||
* the expected data.
|
||||
* @param expected The values of the data expected to be read.
|
||||
* Each element is the data for one beat.
|
||||
*/
|
||||
class GetBlockSweepDriver(expected: Seq[BigInt])
|
||||
(implicit p: Parameters) extends Driver()(p) {
|
||||
val s_start :: s_send :: s_recv :: s_done :: Nil = Enum(Bits(), 4)
|
||||
val state = Reg(init = s_start)
|
||||
|
||||
val nReqs = ((expected.size - 1) / tlDataBeats + 1) * tlDataBeats
|
||||
val (req_cnt, req_done) = Counter(io.mem.grant.fire(), nReqs)
|
||||
val (addr_beat, beats_done) = Counter(io.mem.grant.fire(), tlDataBeats)
|
||||
|
||||
val tlBlockOffset = tlByteAddrBits + tlBeatAddrBits
|
||||
val addr_block =
|
||||
if (nReqs > tlDataBeats) req_cnt(log2Up(nReqs) - 1, tlBlockOffset)
|
||||
else UInt(0)
|
||||
|
||||
io.mem.acquire.valid := (state === s_send)
|
||||
io.mem.acquire.bits := GetBlock(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = addr_block)
|
||||
io.mem.grant.ready := (state === s_recv)
|
||||
io.finished := state === s_done
|
||||
|
||||
when (state === s_start && io.start) { state := s_send }
|
||||
when (io.mem.acquire.fire()) { state := s_recv }
|
||||
when (beats_done) { state := s_send }
|
||||
when (req_done) { state := s_done }
|
||||
|
||||
val exp_data = Vec(expected.map(e => UInt(e, tlDataBits)))
|
||||
|
||||
assert(!io.mem.grant.valid || req_cnt >= UInt(expected.size) ||
|
||||
io.mem.grant.bits.data === exp_data(req_cnt),
|
||||
"GetBlockSweep: data does not match expected")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that single-beat Puts across a range of memory persists correctly.
|
||||
* @param n the number of beats to put
|
||||
*/
|
||||
class PutSweepDriver(val n: Int)(implicit p: Parameters) extends Driver()(p) {
|
||||
val (s_idle :: s_put_req :: s_put_resp ::
|
||||
s_get_req :: s_get_resp :: s_done :: Nil) = Enum(Bits(), 6)
|
||||
val state = Reg(init = s_idle)
|
||||
|
||||
val (put_cnt, put_done) = Counter(state === s_put_resp && io.mem.grant.valid, n)
|
||||
val (get_cnt, get_done) = Counter(state === s_get_resp && io.mem.grant.valid, n)
|
||||
|
||||
val (put_block, put_beat) = if (n > tlDataBeats) {
|
||||
(put_cnt(log2Up(n) - 1, tlBeatAddrBits),
|
||||
put_cnt(tlBeatAddrBits - 1, 0))
|
||||
} else {
|
||||
(UInt(0), put_cnt)
|
||||
}
|
||||
val (get_block, get_beat) = if (n > tlDataBeats) {
|
||||
(get_cnt(log2Up(n) - 1, tlBeatAddrBits),
|
||||
get_cnt(tlBeatAddrBits - 1, 0))
|
||||
} else {
|
||||
(UInt(0), get_cnt)
|
||||
}
|
||||
|
||||
val dataRep = (tlDataBits - 1) / log2Up(n) + 1
|
||||
val put_data = Fill(dataRep, put_cnt)(tlDataBits - 1, 0)
|
||||
val get_data = Fill(dataRep, get_cnt)(tlDataBits - 1, 0)
|
||||
|
||||
io.mem.acquire.valid := (state === s_put_req) || (state === s_get_req)
|
||||
io.mem.acquire.bits := Mux(state === s_put_req,
|
||||
Put(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = put_block,
|
||||
addr_beat = put_beat,
|
||||
data = put_data),
|
||||
Get(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = get_block,
|
||||
addr_beat = get_beat))
|
||||
io.mem.grant.ready := (state === s_put_resp) || (state === s_get_resp)
|
||||
|
||||
when (state === s_idle && io.start) { state := s_put_req }
|
||||
when (state === s_put_req && io.mem.acquire.ready) { state := s_put_resp }
|
||||
when (state === s_put_resp && io.mem.grant.valid) {
|
||||
state := Mux(put_done, s_get_req, s_put_req)
|
||||
}
|
||||
when (state === s_get_req && io.mem.acquire.ready) { state := s_get_resp }
|
||||
when (state === s_get_resp && io.mem.grant.valid) {
|
||||
state := Mux(get_done, s_done, s_get_req)
|
||||
}
|
||||
|
||||
io.finished := (state === s_done)
|
||||
|
||||
assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() ||
|
||||
io.mem.grant.bits.data === get_data,
|
||||
"PutSweepDriver: data does not match")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that write-masked single-beat puts work correctly by putting
|
||||
* data with steadily smaller write-masks to the same beat.
|
||||
* @param minBytes the smallest number of bytes that can be in the writemask
|
||||
*/
|
||||
class PutMaskDriver(minBytes: Int = 1)(implicit p: Parameters) extends Driver()(p) {
|
||||
val (s_idle :: s_put_req :: s_put_resp ::
|
||||
s_get_req :: s_get_resp :: s_done :: Nil) = Enum(Bits(), 6)
|
||||
val state = Reg(init = s_idle)
|
||||
val nbytes = Reg(UInt(width = log2Up(tlWriteMaskBits) + 1))
|
||||
val wmask = (UInt(1) << nbytes) - UInt(1)
|
||||
val wdata = Fill(tlDataBits / 8, Wire(UInt(width = 8), init = nbytes))
|
||||
// TL data bytes down to minBytes logarithmically by 2
|
||||
val expected = (log2Ceil(tlDataBits / 8) to log2Ceil(minBytes) by -1)
|
||||
.map(1 << _).foldLeft(UInt(0, tlDataBits)) {
|
||||
// Change the lower nbytes of the value
|
||||
(value, nbytes) => {
|
||||
val mask = UInt((BigInt(1) << (nbytes * 8)) - BigInt(1), tlDataBits)
|
||||
val wval = Fill(tlDataBits / 8, UInt(nbytes, 8))
|
||||
(value & ~mask) | (wval & mask)
|
||||
}
|
||||
}
|
||||
|
||||
when (state === s_idle && io.start) {
|
||||
state := s_put_req
|
||||
nbytes := UInt(8)
|
||||
}
|
||||
when (state === s_put_req && io.mem.acquire.ready) {
|
||||
state := s_put_resp
|
||||
}
|
||||
when (state === s_put_resp && io.mem.grant.valid) {
|
||||
nbytes := nbytes >> UInt(1)
|
||||
state := Mux(nbytes === UInt(minBytes), s_get_req, s_put_req)
|
||||
}
|
||||
when (state === s_get_req && io.mem.acquire.ready) {
|
||||
state := s_get_resp
|
||||
}
|
||||
when (state === s_get_resp && io.mem.grant.valid) {
|
||||
state := s_done
|
||||
}
|
||||
|
||||
io.finished := (state === s_done)
|
||||
io.mem.acquire.valid := (state === s_put_req) || (state === s_get_req)
|
||||
io.mem.acquire.bits := Mux(state === s_put_req,
|
||||
Put(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0),
|
||||
addr_beat = UInt(0),
|
||||
data = wdata,
|
||||
wmask = Some(wmask)),
|
||||
Get(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0),
|
||||
addr_beat = UInt(0)))
|
||||
io.mem.grant.ready := (state === s_put_resp) || (state === s_get_resp)
|
||||
|
||||
assert(!io.mem.grant.valid || state =/= s_get_resp ||
|
||||
io.mem.grant.bits.data === expected,
|
||||
"PutMask: data does not match expected")
|
||||
}
|
||||
|
||||
class PutBlockSweepDriver(val n: Int)(implicit p: Parameters)
|
||||
extends Driver()(p) {
|
||||
val (s_idle :: s_put_req :: s_put_resp ::
|
||||
s_get_req :: s_get_resp :: s_done :: Nil) = Enum(Bits(), 6)
|
||||
val state = Reg(init = s_idle)
|
||||
|
||||
val (put_beat, put_beat_done) = Counter(
|
||||
state === s_put_req && io.mem.acquire.ready, tlDataBeats)
|
||||
val (put_cnt, put_done) = Counter(
|
||||
state === s_put_resp && io.mem.grant.valid, n)
|
||||
val (get_beat, get_beat_done) = Counter(
|
||||
state === s_get_resp && io.mem.grant.valid, tlDataBeats)
|
||||
val (get_cnt, get_done) = Counter(get_beat_done, n)
|
||||
|
||||
val dataRep = (tlDataBits - 1) / (log2Up(n) + tlBeatAddrBits) + 1
|
||||
val put_data = Fill(dataRep, Cat(put_cnt, put_beat))(tlDataBits - 1, 0)
|
||||
val get_data = Fill(dataRep, Cat(get_cnt, get_beat))(tlDataBits - 1, 0)
|
||||
|
||||
when (state === s_idle && io.start) { state := s_put_req }
|
||||
when (put_beat_done) { state := s_put_resp }
|
||||
when (state === s_put_resp && io.mem.grant.valid) {
|
||||
state := Mux(put_done, s_get_req, s_put_req)
|
||||
}
|
||||
when (state === s_get_req && io.mem.acquire.ready) { state := s_get_resp }
|
||||
when (get_beat_done) { state := Mux(get_done, s_done, s_get_req) }
|
||||
|
||||
val put_acquire = PutBlock(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = put_cnt,
|
||||
addr_beat = put_beat,
|
||||
data = put_data)
|
||||
|
||||
val get_acquire = GetBlock(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = get_cnt)
|
||||
|
||||
io.finished := (state === s_done)
|
||||
io.mem.acquire.valid := (state === s_put_req) || (state === s_get_req)
|
||||
io.mem.acquire.bits := Mux(state === s_put_req, put_acquire, get_acquire)
|
||||
io.mem.grant.ready := (state === s_put_resp) || (state === s_get_resp)
|
||||
|
||||
assert(!io.mem.grant.valid || state =/= s_get_resp ||
|
||||
io.mem.grant.bits.data === get_data,
|
||||
"PutBlockSweep: data does not match expected")
|
||||
}
|
||||
|
||||
class PutAtomicDriver(implicit p: Parameters) extends Driver()(p) {
|
||||
val s_idle :: s_put :: s_atomic :: s_get :: s_done :: Nil = Enum(Bits(), 5)
|
||||
val state = Reg(init = s_idle)
|
||||
val sending = Reg(init = Bool(false))
|
||||
|
||||
val put_acquire = Put(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0),
|
||||
addr_beat = UInt(0),
|
||||
// Put 15 in bytes 3:2
|
||||
data = UInt(15 << 16),
|
||||
wmask = Some(UInt(0x0c)))
|
||||
|
||||
val amo_acquire = PutAtomic(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0),
|
||||
addr_beat = UInt(0),
|
||||
addr_byte = UInt(2),
|
||||
atomic_opcode = M_XA_ADD,
|
||||
operand_size = MT_H,
|
||||
data = UInt(3 << 16))
|
||||
|
||||
val get_acquire = Get(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0),
|
||||
addr_beat = UInt(0))
|
||||
|
||||
io.finished := (state === s_done)
|
||||
io.mem.acquire.valid := sending
|
||||
io.mem.acquire.bits := MuxLookup(state, get_acquire, Seq(
|
||||
s_put -> put_acquire,
|
||||
s_atomic -> amo_acquire,
|
||||
s_get -> get_acquire))
|
||||
io.mem.grant.ready := !sending
|
||||
|
||||
when (io.mem.acquire.fire()) { sending := Bool(false) }
|
||||
|
||||
when (state === s_idle && io.start) {
|
||||
state := s_put
|
||||
sending := Bool(true)
|
||||
}
|
||||
when (io.mem.grant.fire()) {
|
||||
when (state === s_put) { sending := Bool(true); state := s_atomic }
|
||||
when (state === s_atomic) { sending := Bool(true); state := s_get }
|
||||
when (state === s_get) { state := s_done }
|
||||
}
|
||||
|
||||
assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() ||
|
||||
io.mem.grant.bits.data(31, 16) === UInt(18))
|
||||
}
|
||||
|
||||
class PrefetchDriver(implicit p: Parameters) extends Driver()(p) {
|
||||
val s_idle :: s_put_pf :: s_get_pf :: s_done :: Nil = Enum(Bits(), 4)
|
||||
val state = Reg(init = s_idle)
|
||||
val sending = Reg(init = Bool(false))
|
||||
|
||||
when (state === s_idle) {
|
||||
sending := Bool(true)
|
||||
state := s_put_pf
|
||||
}
|
||||
|
||||
when (io.mem.acquire.fire()) { sending := Bool(false) }
|
||||
when (io.mem.grant.fire()) {
|
||||
when (state === s_put_pf) { sending := Bool(true); state := s_get_pf }
|
||||
when (state === s_get_pf) { state := s_done }
|
||||
}
|
||||
|
||||
io.finished := (state === s_done)
|
||||
io.mem.acquire.valid := sending
|
||||
io.mem.acquire.bits := Mux(state === s_put_pf,
|
||||
PutPrefetch(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0)),
|
||||
GetPrefetch(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(0)))
|
||||
io.mem.grant.ready := !sending
|
||||
}
|
||||
|
||||
class DriverSet(driverGen: Parameters => Seq[Driver])(implicit p: Parameters)
|
||||
extends Driver()(p) {
|
||||
val s_start :: s_run :: s_done :: Nil = Enum(Bits(), 3)
|
||||
val state = Reg(init = s_start)
|
||||
|
||||
val drivers = driverGen(p)
|
||||
val idx = Reg(init = UInt(0, log2Up(drivers.size)))
|
||||
val finished = Wire(init = Bool(false))
|
||||
|
||||
when (state === s_start && io.start) { state := s_run }
|
||||
when (state === s_run && finished) {
|
||||
when (idx === UInt(drivers.size - 1)) { state := s_done }
|
||||
idx := idx + UInt(1)
|
||||
}
|
||||
|
||||
io.finished := state === s_done
|
||||
|
||||
io.mem.acquire.valid := Bool(false)
|
||||
io.mem.grant.ready := Bool(false)
|
||||
|
||||
drivers.zipWithIndex.foreach { case (driv, i) =>
|
||||
val me = idx === UInt(i)
|
||||
|
||||
driv.io.start := me && state === s_run
|
||||
driv.io.mem.acquire.ready := io.mem.acquire.ready && me
|
||||
driv.io.mem.grant.valid := io.mem.grant.valid && me
|
||||
driv.io.mem.grant.bits := io.mem.grant.bits
|
||||
|
||||
when (me) {
|
||||
io.mem.acquire.valid := driv.io.mem.acquire.valid
|
||||
io.mem.acquire.bits := driv.io.mem.acquire.bits
|
||||
io.mem.grant.ready := driv.io.mem.grant.ready
|
||||
finished := driv.io.finished
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package groundtest.unittests
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import junctions.NastiConstants._
|
||||
import uncore.tilelink._
|
||||
import uncore.converters._
|
||||
import uncore.constants._
|
||||
import uncore.devices._
|
||||
import groundtest.common._
|
||||
import cde.{Field, Parameters}
|
||||
|
||||
abstract class UnitTest extends Module {
|
||||
val io = new Bundle {
|
||||
val finished = Bool(OUTPUT)
|
||||
val start = Bool(INPUT)
|
||||
}
|
||||
|
||||
when (io.start) {
|
||||
printf(s"Started UnitTest ${this.getClass.getSimpleName}\n")
|
||||
}
|
||||
}
|
||||
|
||||
case object UnitTests extends Field[Parameters => Seq[UnitTest]]
|
||||
|
||||
class UnitTestSuite(implicit p: Parameters) extends GroundTest()(p) {
|
||||
val tests = p(UnitTests)(p)
|
||||
|
||||
val s_idle :: s_start :: s_wait :: s_done :: Nil = Enum(Bits(), 4)
|
||||
val state = Reg(init = s_idle)
|
||||
val test_idx = Reg(init = UInt(0, log2Up(tests.size)))
|
||||
val test_finished = Vec(tests.map(_.io.finished))
|
||||
|
||||
when (state === s_idle) { state := s_start }
|
||||
when (state === s_start) { state := s_wait }
|
||||
when (state === s_wait && test_finished(test_idx)) {
|
||||
state := s_start
|
||||
test_idx := test_idx + UInt(1)
|
||||
state := Mux(test_idx === UInt(tests.size - 1), s_done, s_start)
|
||||
}
|
||||
|
||||
io.status.timeout.valid := Bool(false)
|
||||
tests.zipWithIndex.foreach { case (mod, i) =>
|
||||
mod.io.start := (state === s_start) && test_idx === UInt(i)
|
||||
val timeout = Timer(1000, mod.io.start, mod.io.finished)
|
||||
assert(!timeout, s"UnitTest ${mod.getClass.getSimpleName} timed out")
|
||||
when (timeout) {
|
||||
io.status.timeout.valid := Bool(true)
|
||||
io.status.timeout.bits := UInt(i)
|
||||
}
|
||||
}
|
||||
io.status.finished := (state === s_done)
|
||||
io.status.error.valid := Bool(false)
|
||||
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package groundtest.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")
|
||||
}
|
||||
|
||||
|
@ -1,170 +0,0 @@
|
||||
package groundtest.unittests
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import junctions.NastiConstants._
|
||||
import groundtest.common._
|
||||
import cde.Parameters
|
||||
|
||||
class NastiDriver(dataWidth: Int, burstLen: Int, nBursts: Int)
|
||||
(implicit p: Parameters) extends NastiModule {
|
||||
val io = new Bundle {
|
||||
val nasti = new NastiIO
|
||||
val finished = Bool(OUTPUT)
|
||||
val start = Bool(INPUT)
|
||||
}
|
||||
|
||||
val dataBytes = dataWidth / 8
|
||||
val nastiDataBytes = nastiXDataBits / 8
|
||||
|
||||
val (write_cnt, write_done) = Counter(io.nasti.w.fire(), burstLen)
|
||||
val (read_cnt, read_done) = Counter(io.nasti.r.fire(), burstLen)
|
||||
val (req_cnt, reqs_done) = Counter(read_done, nBursts)
|
||||
|
||||
val req_addr = Cat(req_cnt, UInt(0, log2Up(burstLen * dataBytes)))
|
||||
|
||||
val write_data = UInt(0x10000000L, dataWidth) | Cat(req_cnt, write_cnt)
|
||||
val expected_data = UInt(0x10000000L, dataWidth) | Cat(req_cnt, read_cnt)
|
||||
|
||||
val (s_idle :: s_write_addr :: s_write_data :: s_write_stall :: s_write_resp ::
|
||||
s_read_addr :: s_read_data :: s_read_stall :: s_done :: Nil) = Enum(Bits(), 9)
|
||||
val state = Reg(init = s_idle)
|
||||
|
||||
val (stall_cnt, stall_done) = Counter(state === s_read_stall, 2)
|
||||
|
||||
io.nasti.aw.valid := (state === s_write_addr)
|
||||
io.nasti.aw.bits := NastiWriteAddressChannel(
|
||||
id = UInt(0),
|
||||
addr = req_addr,
|
||||
size = UInt(log2Up(dataBytes)),
|
||||
len = UInt(burstLen - 1))
|
||||
|
||||
io.nasti.w.valid := (state === s_write_data)
|
||||
io.nasti.w.bits := NastiWriteDataChannel(
|
||||
data = Cat(write_data, write_data),
|
||||
last = (write_cnt === UInt(burstLen - 1)))
|
||||
|
||||
io.nasti.b.ready := (state === s_write_resp)
|
||||
|
||||
io.nasti.ar.valid := (state === s_read_addr)
|
||||
io.nasti.ar.bits := NastiReadAddressChannel(
|
||||
id = UInt(0),
|
||||
addr = req_addr,
|
||||
size = UInt(log2Up(dataBytes)),
|
||||
len = UInt(burstLen - 1))
|
||||
|
||||
io.nasti.r.ready := (state === s_read_data)
|
||||
|
||||
io.finished := (state === s_done)
|
||||
|
||||
when (state === s_idle && io.start) { state := s_write_addr }
|
||||
when (io.nasti.aw.fire()) { state := s_write_data }
|
||||
when (io.nasti.w.fire()) { state := s_write_stall }
|
||||
when (state === s_write_stall) { state := s_write_data }
|
||||
when (write_done) { state := s_write_resp }
|
||||
when (io.nasti.b.fire()) { state := s_read_addr }
|
||||
when (io.nasti.ar.fire()) { state := s_read_data }
|
||||
when (io.nasti.r.fire()) { state := s_read_stall }
|
||||
when (stall_done) { state := s_read_data }
|
||||
when (read_done) { state := s_write_addr }
|
||||
when (reqs_done) { state := s_done }
|
||||
|
||||
val full_addr = req_addr + (read_cnt << UInt(log2Up(dataBytes)))
|
||||
val byteshift = full_addr(log2Up(nastiDataBytes) - 1, 0)
|
||||
val bitshift = Cat(byteshift, UInt(0, 3))
|
||||
val read_data = (io.nasti.r.bits.data >> bitshift) & Fill(dataWidth, UInt(1, 1))
|
||||
|
||||
assert(!io.nasti.r.valid || read_data === expected_data,
|
||||
s"NastiDriver got wrong data")
|
||||
|
||||
val ar_timeout = Timer(1024, io.nasti.ar.fire(), io.nasti.r.fire())
|
||||
val aw_timeout = Timer(1024, io.nasti.aw.fire(), io.nasti.b.fire())
|
||||
|
||||
assert(!ar_timeout && !aw_timeout,
|
||||
s"NastiDriver for $name timed out")
|
||||
}
|
||||
|
||||
|
||||
class AtosConverterTestBackend(implicit p: Parameters) extends NastiModule()(p) {
|
||||
val io = new Bundle {
|
||||
val nasti = (new NastiIO).flip
|
||||
val finished = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
val (s_waddr :: s_wdata :: s_wresp ::
|
||||
s_raddr :: s_rresp :: s_done :: Nil) = Enum(Bits(), 6)
|
||||
val state = Reg(init = s_waddr)
|
||||
|
||||
val n_words = 4
|
||||
val test_data = Reg(Vec(n_words, UInt(width = nastiXDataBits)))
|
||||
val req_id = Reg(UInt(width = nastiXIdBits))
|
||||
|
||||
val (w_count, w_last) = Counter(io.nasti.w.fire(), n_words)
|
||||
val (r_count, r_last) = Counter(io.nasti.r.fire(), n_words)
|
||||
|
||||
when (io.nasti.aw.fire()) {
|
||||
req_id := io.nasti.aw.bits.id
|
||||
state := s_wdata
|
||||
}
|
||||
when (io.nasti.w.fire()) {
|
||||
test_data(w_count) := io.nasti.w.bits.data
|
||||
when (io.nasti.w.bits.last) { state := s_wresp }
|
||||
}
|
||||
when (io.nasti.b.fire()) { state := s_raddr }
|
||||
when (io.nasti.ar.fire()) {
|
||||
req_id := io.nasti.ar.bits.id
|
||||
state := s_rresp
|
||||
}
|
||||
when (io.nasti.r.fire() && io.nasti.r.bits.last) { state := s_done }
|
||||
|
||||
io.nasti.aw.ready := (state === s_waddr)
|
||||
io.nasti.w.ready := (state === s_wdata)
|
||||
io.nasti.ar.ready := (state === s_raddr)
|
||||
|
||||
io.nasti.b.valid := (state === s_wresp)
|
||||
io.nasti.b.bits := NastiWriteResponseChannel(id = req_id)
|
||||
|
||||
io.nasti.r.valid := (state === s_rresp)
|
||||
io.nasti.r.bits := NastiReadDataChannel(
|
||||
id = req_id,
|
||||
data = test_data(r_count),
|
||||
last = r_last)
|
||||
|
||||
io.finished := (state === s_done)
|
||||
}
|
||||
|
||||
class AtosConverterTest(implicit val p: Parameters) extends UnitTest
|
||||
with HasNastiParameters {
|
||||
val frontend = Module(new NastiDriver(nastiXDataBits, 4, 1))
|
||||
val backend = Module(new AtosConverterTestBackend)
|
||||
|
||||
val serdes = Module(new AtosSerdes(8))
|
||||
val desser = Module(new AtosDesser(8))
|
||||
|
||||
val client_conv = Module(new AtosClientConverter)
|
||||
val manager_conv = Module(new AtosManagerConverter)
|
||||
|
||||
client_conv.io.nasti <> frontend.io.nasti
|
||||
serdes.io.wide <> client_conv.io.atos
|
||||
desser.io.narrow <> serdes.io.narrow
|
||||
manager_conv.io.atos <> desser.io.wide
|
||||
backend.io.nasti <> manager_conv.io.nasti
|
||||
frontend.io.start := io.start
|
||||
|
||||
io.finished := frontend.io.finished && backend.io.finished
|
||||
}
|
||||
|
||||
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,111 +0,0 @@
|
||||
package groundtest.unittests
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import junctions.NastiConstants._
|
||||
import cde.Parameters
|
||||
|
||||
class NastiDemuxDriver(n: Int)(implicit p: Parameters) extends Module {
|
||||
val io = new Bundle {
|
||||
val start = Bool(INPUT)
|
||||
val finished = Bool(OUTPUT)
|
||||
val nasti = new NastiIO
|
||||
val select = UInt(OUTPUT, log2Up(n))
|
||||
}
|
||||
|
||||
val (s_idle :: s_write_addr :: s_write_data :: s_write_resp ::
|
||||
s_read_addr :: s_read_resp :: s_done :: Nil) = Enum(Bits(), 7)
|
||||
val state = Reg(init = s_idle)
|
||||
|
||||
val select = Reg(init = UInt(0, log2Up(n)))
|
||||
|
||||
when (state === s_idle && io.start) { state := s_write_addr }
|
||||
when (io.nasti.aw.fire()) { state := s_write_data }
|
||||
when (io.nasti.w.fire()) { state := s_write_resp }
|
||||
when (io.nasti.b.fire()) { state := s_read_addr }
|
||||
when (io.nasti.ar.fire()) { state := s_read_resp }
|
||||
when (io.nasti.r.fire()) {
|
||||
when (select === UInt(n - 1)) {
|
||||
state := s_done
|
||||
} .otherwise {
|
||||
select := select + UInt(1)
|
||||
state := s_write_addr
|
||||
}
|
||||
}
|
||||
|
||||
io.nasti.aw.valid := (state === s_write_addr)
|
||||
io.nasti.aw.bits := NastiWriteAddressChannel(
|
||||
id = UInt(0),
|
||||
addr = UInt(0),
|
||||
size = UInt("b011"))
|
||||
io.nasti.w.valid := (state === s_write_data)
|
||||
io.nasti.w.bits := NastiWriteDataChannel(data = select)
|
||||
io.nasti.b.ready := (state === s_write_resp)
|
||||
io.nasti.ar.valid := (state === s_read_addr)
|
||||
io.nasti.ar.bits := NastiReadAddressChannel(
|
||||
id = UInt(0),
|
||||
addr = UInt(0),
|
||||
size = UInt("b011"))
|
||||
io.nasti.r.ready := (state === s_read_resp)
|
||||
|
||||
io.finished := (state === s_done)
|
||||
io.select := select
|
||||
|
||||
assert(!io.nasti.r.valid || io.nasti.r.bits.data === select,
|
||||
"NASTI DeMux test: Read data did not match")
|
||||
}
|
||||
|
||||
class NastiDemuxSlave(implicit p: Parameters) extends NastiModule()(p) {
|
||||
val io = (new NastiIO).flip
|
||||
|
||||
val (s_write_wait :: s_write_data :: s_write_resp ::
|
||||
s_read_wait :: s_read_resp :: s_done :: Nil) = Enum(Bits(), 6)
|
||||
val state = Reg(init = s_write_wait)
|
||||
|
||||
val value = Reg(UInt(width = 64))
|
||||
val id = Reg(UInt(width = nastiXIdBits))
|
||||
|
||||
when (io.aw.fire()) {
|
||||
id := io.aw.bits.id
|
||||
state := s_write_data
|
||||
}
|
||||
|
||||
when (io.w.fire()) {
|
||||
value := io.w.bits.data
|
||||
state := s_write_resp
|
||||
}
|
||||
|
||||
when (io.b.fire()) { state := s_read_wait }
|
||||
|
||||
when (io.ar.fire()) {
|
||||
id := io.ar.bits.id
|
||||
state := s_read_resp
|
||||
}
|
||||
|
||||
when (io.r.fire()) { state := s_done }
|
||||
|
||||
io.aw.ready := (state === s_write_wait)
|
||||
io.w.ready := (state === s_write_data)
|
||||
io.b.valid := (state === s_write_resp)
|
||||
io.b.bits := NastiWriteResponseChannel(id = id)
|
||||
io.ar.ready := (state === s_read_wait)
|
||||
io.r.valid := (state === s_read_resp)
|
||||
io.r.bits := NastiReadDataChannel(id = id, data = value)
|
||||
}
|
||||
|
||||
class NastiMemoryDemuxTest(implicit p: Parameters) extends UnitTest {
|
||||
val nSlaves = 4
|
||||
|
||||
val driver = Module(new NastiDemuxDriver(nSlaves))
|
||||
driver.io.start := io.start
|
||||
io.finished := driver.io.finished
|
||||
|
||||
val demux = Module(new NastiMemoryDemux(nSlaves))
|
||||
demux.io.master <> driver.io.nasti
|
||||
demux.io.select := driver.io.select
|
||||
|
||||
for (i <- 0 until nSlaves) {
|
||||
val slave = Module(new NastiDemuxSlave)
|
||||
slave.io <> demux.io.slaves(i)
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package groundtest.unittests
|
||||
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import uncore.devices._
|
||||
import uncore.tilelink._
|
||||
import uncore.converters._
|
||||
import groundtest.common._
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user