1
0

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:
Matthew Naylor 2016-03-18 12:11:11 +00:00
parent 04be438847
commit bda5772e98

View File

@ -45,8 +45,13 @@ 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]]
@ -55,15 +60,19 @@ trait HasTraceGenParams {
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)
} }
// ======================= // =======================