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,8 +45,13 @@ import cde.{Parameters, Field}
|
||||
//
|
||||
// * The desired number of requests to be sent by each generator.
|
||||
//
|
||||
// * A list of physical addresses from which an address is drawn when
|
||||
// generating a fresh request.
|
||||
// * A bag of physical addresses, shared by all cores, from which an
|
||||
// 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]]
|
||||
|
||||
@ -55,15 +60,19 @@ trait HasTraceGenParams {
|
||||
val numGens = p(NGenerators)
|
||||
val numBitsInId = log2Up(numGens)
|
||||
val numReqsPerGen = p(MaxGenerateRequests)
|
||||
val memRespTimeout = 4096
|
||||
val memRespTimeout = 1024
|
||||
val numBitsInWord = p(WordBits)
|
||||
val numBytesInWord = numBitsInWord / 8
|
||||
val numBitsInWordOffset = log2Up(numBytesInWord)
|
||||
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(1 << logNumAddrsInTrace == addressBag.length)
|
||||
require((1 << logAddressBagLen) == addressBagLen)
|
||||
}
|
||||
|
||||
// ============
|
||||
@ -173,23 +182,50 @@ class TraceGenerator(id: Int)
|
||||
// Random addresses
|
||||
// ----------------
|
||||
|
||||
// Address list taken from module parameters.
|
||||
|
||||
val numAddrsInTrace = 1 << logNumAddrsInTrace
|
||||
// Address bag, shared by all cores, taken from module parameters.
|
||||
// In addition, there is a per-core random selection of extra addresses.
|
||||
|
||||
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.
|
||||
|
||||
val randAddrIndex = Module(new LCG(logNumAddrsInTrace)).io.out
|
||||
val randAddrBagIndex = Module(new LCG(logAddressBagLen)).io.out
|
||||
|
||||
// A random address from the address bag.
|
||||
|
||||
val addrIndices = (0 to numAddrsInTrace-1).
|
||||
map(i => UInt(i, logNumAddrsInTrace))
|
||||
val addrBagIndices = (0 to addressBagLen-1).
|
||||
map(i => UInt(i, logAddressBagLen))
|
||||
|
||||
val randAddr = MuxLookup(randAddrIndex, UInt(0),
|
||||
addrIndices.zip(bagOfAddrs))
|
||||
val randAddrFromBag = MuxLookup(randAddrBagIndex, UInt(0),
|
||||
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
|
||||
// --------------
|
||||
@ -205,19 +241,12 @@ class TraceGenerator(id: Int)
|
||||
// Distribution specified as a list of (frequency,value) pairs.
|
||||
// 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(
|
||||
(15, opLoad),
|
||||
(15, opStore),
|
||||
(10, opLoad),
|
||||
(10, opStore),
|
||||
(4, opFence),
|
||||
(3, opLRSC),
|
||||
(3, opSwap),
|
||||
(2, opDelay)))
|
||||
|
||||
// Request/response tags
|
||||
@ -319,7 +348,7 @@ class TraceGenerator(id: Int)
|
||||
opInProgress := UInt(1)
|
||||
}
|
||||
// Wait until all requests have had a response
|
||||
.elsewhen (io.mem.ordered && reqCount === respCount) {
|
||||
.elsewhen (reqCount === respCount) {
|
||||
// Emit fence response
|
||||
printf("%d: fence-resp @%d\n", tid, cycleCount)
|
||||
// Move on to a new operation
|
||||
@ -397,7 +426,8 @@ class TraceGenerator(id: Int)
|
||||
}
|
||||
}
|
||||
// Delay finished, send SC request
|
||||
when (opInProgress === UInt(3)) {
|
||||
//when (opInProgress === UInt(3)) {
|
||||
when (opInProgress === UInt(3) && !reqValid && reqCount === respCount) {
|
||||
when (canSendFreshReq) {
|
||||
// Set command, but leave address
|
||||
// i.e. use same address as LR did
|
||||
@ -487,18 +517,26 @@ class TraceGenerator(id: Int)
|
||||
}
|
||||
|
||||
// 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)
|
||||
assert(!timeout, s"Trace generator ${id} timed out waiting for response")
|
||||
// Raise an error if a response takes too long to come back
|
||||
val timeout = Timer(memRespTimeout, sendFreshReq, io.mem.resp.valid)
|
||||
assert(!timeout, s"Core ${id}: response timeout")
|
||||
|
||||
// Termination condition
|
||||
// ---------------------
|
||||
|
||||
io.finished := reqCount === UInt(numReqsPerGen) &&
|
||||
val done = reqCount === 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