Updates to the trace-generator: (1) Don't terminate via HTIF exit, which can cause other, unfinished, cores to be cut short. Instead emit FINISHED messsages allowing an external process to send a SIGTERM to the emulator once all cores have finished. (2) Add some support for greater address variation without having to recompile, disabled by default. (3) Generate atomic, LR/SC, and fence operations by default in addition to plain loads and stores. These changes require newer versions of files in the rocket-chip/scripts directory. I will submit a pull request for those too.
This commit is contained in:
parent
04be438847
commit
bda5772e98
@ -45,25 +45,34 @@ import cde.{Parameters, Field}
|
|||||||
//
|
//
|
||||||
// * The desired number of requests to be sent by each generator.
|
// * The desired number of requests to be sent by each generator.
|
||||||
//
|
//
|
||||||
// * A list of physical addresses from which an address is drawn when
|
// * A bag of physical addresses, shared by all cores, from which an
|
||||||
// generating a fresh request.
|
// address can be drawn when generating a fresh request.
|
||||||
|
//
|
||||||
|
// * A number of random 'extra addresses', local to each core, from
|
||||||
|
// which an address can be drawn when generating a fresh request.
|
||||||
|
// (This is a way to generate a wider range of addresses without having
|
||||||
|
// to repeatedly recompile with a different address bag.)
|
||||||
|
|
||||||
case object AddressBag extends Field[List[Int]]
|
case object AddressBag extends Field[List[Int]]
|
||||||
|
|
||||||
trait HasTraceGenParams {
|
trait HasTraceGenParams {
|
||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
val numGens = p(NGenerators)
|
val numGens = p(NGenerators)
|
||||||
val numBitsInId = log2Up(numGens)
|
val numBitsInId = log2Up(numGens)
|
||||||
val numReqsPerGen = p(MaxGenerateRequests)
|
val numReqsPerGen = p(MaxGenerateRequests)
|
||||||
val memRespTimeout = 4096
|
val memRespTimeout = 1024
|
||||||
val numBitsInWord = p(WordBits)
|
val numBitsInWord = p(WordBits)
|
||||||
val numBytesInWord = numBitsInWord / 8
|
val numBytesInWord = numBitsInWord / 8
|
||||||
val numBitsInWordOffset = log2Up(numBytesInWord)
|
val numBitsInWordOffset = log2Up(numBytesInWord)
|
||||||
val addressBag = p(AddressBag)
|
val addressBag = p(AddressBag)
|
||||||
val logNumAddrsInTrace = log2Up(addressBag.length)
|
val addressBagLen = addressBag.length
|
||||||
|
val logAddressBagLen = log2Up(addressBagLen)
|
||||||
|
val genExtraAddrs = false
|
||||||
|
val logNumExtraAddrs = 1
|
||||||
|
val numExtraAddrs = 1 << logNumExtraAddrs
|
||||||
|
|
||||||
require(numBytesInWord * 8 == numBitsInWord)
|
require(numBytesInWord * 8 == numBitsInWord)
|
||||||
require(1 << logNumAddrsInTrace == addressBag.length)
|
require((1 << logAddressBagLen) == addressBagLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
@ -173,23 +182,50 @@ class TraceGenerator(id: Int)
|
|||||||
// Random addresses
|
// Random addresses
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
// Address list taken from module parameters.
|
// Address bag, shared by all cores, taken from module parameters.
|
||||||
|
// In addition, there is a per-core random selection of extra addresses.
|
||||||
val numAddrsInTrace = 1 << logNumAddrsInTrace
|
|
||||||
|
|
||||||
val bagOfAddrs = addressBag.map(x => UInt(x, numBitsInWord))
|
val bagOfAddrs = addressBag.map(x => UInt(x, numBitsInWord))
|
||||||
|
|
||||||
|
val extraAddrs = (0 to numExtraAddrs-1).
|
||||||
|
map(i => Reg(UInt(width = 16)))
|
||||||
|
|
||||||
// A random index into the address bag.
|
// A random index into the address bag.
|
||||||
|
|
||||||
val randAddrIndex = Module(new LCG(logNumAddrsInTrace)).io.out
|
val randAddrBagIndex = Module(new LCG(logAddressBagLen)).io.out
|
||||||
|
|
||||||
// A random address from the address bag.
|
// A random address from the address bag.
|
||||||
|
|
||||||
val addrIndices = (0 to numAddrsInTrace-1).
|
val addrBagIndices = (0 to addressBagLen-1).
|
||||||
map(i => UInt(i, logNumAddrsInTrace))
|
map(i => UInt(i, logAddressBagLen))
|
||||||
|
|
||||||
val randAddr = MuxLookup(randAddrIndex, UInt(0),
|
val randAddrFromBag = MuxLookup(randAddrBagIndex, UInt(0),
|
||||||
addrIndices.zip(bagOfAddrs))
|
addrBagIndices.zip(bagOfAddrs))
|
||||||
|
|
||||||
|
// Random address from the address bag or the extra addresses.
|
||||||
|
|
||||||
|
val randAddr =
|
||||||
|
if (! genExtraAddrs) {
|
||||||
|
randAddrFromBag
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// A random index into the extra addresses.
|
||||||
|
|
||||||
|
val randExtraAddrIndex = Module(new LCG(logNumExtraAddrs)).io.out
|
||||||
|
|
||||||
|
// A random address from the extra addresses.
|
||||||
|
|
||||||
|
val extraAddrIndices = (0 to numExtraAddrs-1).
|
||||||
|
map(i => UInt(i, logNumExtraAddrs))
|
||||||
|
|
||||||
|
val randAddrFromExtra = Cat(UInt(0),
|
||||||
|
MuxLookup(randExtraAddrIndex, UInt(0),
|
||||||
|
extraAddrIndices.zip(extraAddrs)), UInt(0, 3))
|
||||||
|
|
||||||
|
Frequency(List(
|
||||||
|
(1, randAddrFromBag),
|
||||||
|
(1, randAddrFromExtra)))
|
||||||
|
}
|
||||||
|
|
||||||
// Random opcodes
|
// Random opcodes
|
||||||
// --------------
|
// --------------
|
||||||
@ -205,19 +241,12 @@ class TraceGenerator(id: Int)
|
|||||||
// Distribution specified as a list of (frequency,value) pairs.
|
// Distribution specified as a list of (frequency,value) pairs.
|
||||||
// NOTE: frequencies must sum to a power of two.
|
// NOTE: frequencies must sum to a power of two.
|
||||||
|
|
||||||
//val randOp = Frequency(List(
|
|
||||||
// (10, opLoad),
|
|
||||||
// (10, opStore),
|
|
||||||
// (4, opFence),
|
|
||||||
// (3, opLRSC),
|
|
||||||
// (3, opSwap),
|
|
||||||
// (2, opDelay)))
|
|
||||||
|
|
||||||
// For now, just generate loads and stores as this is enough to
|
|
||||||
// expose strange behaviour.
|
|
||||||
val randOp = Frequency(List(
|
val randOp = Frequency(List(
|
||||||
(15, opLoad),
|
(10, opLoad),
|
||||||
(15, opStore),
|
(10, opStore),
|
||||||
|
(4, opFence),
|
||||||
|
(3, opLRSC),
|
||||||
|
(3, opSwap),
|
||||||
(2, opDelay)))
|
(2, opDelay)))
|
||||||
|
|
||||||
// Request/response tags
|
// Request/response tags
|
||||||
@ -319,7 +348,7 @@ class TraceGenerator(id: Int)
|
|||||||
opInProgress := UInt(1)
|
opInProgress := UInt(1)
|
||||||
}
|
}
|
||||||
// Wait until all requests have had a response
|
// Wait until all requests have had a response
|
||||||
.elsewhen (io.mem.ordered && reqCount === respCount) {
|
.elsewhen (reqCount === respCount) {
|
||||||
// Emit fence response
|
// Emit fence response
|
||||||
printf("%d: fence-resp @%d\n", tid, cycleCount)
|
printf("%d: fence-resp @%d\n", tid, cycleCount)
|
||||||
// Move on to a new operation
|
// Move on to a new operation
|
||||||
@ -397,7 +426,8 @@ class TraceGenerator(id: Int)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delay finished, send SC request
|
// Delay finished, send SC request
|
||||||
when (opInProgress === UInt(3)) {
|
//when (opInProgress === UInt(3)) {
|
||||||
|
when (opInProgress === UInt(3) && !reqValid && reqCount === respCount) {
|
||||||
when (canSendFreshReq) {
|
when (canSendFreshReq) {
|
||||||
// Set command, but leave address
|
// Set command, but leave address
|
||||||
// i.e. use same address as LR did
|
// i.e. use same address as LR did
|
||||||
@ -487,18 +517,26 @@ class TraceGenerator(id: Int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Response timeouts
|
// Response timeouts
|
||||||
// -----------------
|
// ---------------------------
|
||||||
//
|
|
||||||
// Raise an error if a response takes too long to come back.
|
|
||||||
|
|
||||||
val timeout = Timer(memRespTimeout, io.mem.req.fire(), io.mem.resp.valid)
|
// Raise an error if a response takes too long to come back
|
||||||
assert(!timeout, s"Trace generator ${id} timed out waiting for response")
|
val timeout = Timer(memRespTimeout, sendFreshReq, io.mem.resp.valid)
|
||||||
|
assert(!timeout, s"Core ${id}: response timeout")
|
||||||
|
|
||||||
// Termination condition
|
// Termination condition
|
||||||
// ---------------------
|
// ---------------------
|
||||||
|
|
||||||
io.finished := reqCount === UInt(numReqsPerGen) &&
|
val done = reqCount === UInt(numReqsPerGen) &&
|
||||||
respCount === UInt(numReqsPerGen)
|
respCount === UInt(numReqsPerGen)
|
||||||
|
|
||||||
|
val donePulse = done && !Reg(init = Bool(false), next = done)
|
||||||
|
|
||||||
|
// Emit that this thread has completed
|
||||||
|
when (donePulse) {
|
||||||
|
printf(s"FINISHED ${numGens}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
io.finished := Bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// =======================
|
// =======================
|
||||||
|
Loading…
Reference in New Issue
Block a user