tests,mem-ruby: Enhance ruby false sharing test with Atomics
New ruby mem test includes a percentages of AMOs that will be executed randomly in ruby mem test Change-Id: Ie95ed78e59ea773ce6b59060eaece3701fe4478c
This commit is contained in:
@@ -62,6 +62,12 @@ parser.add_argument(
|
||||
default=0,
|
||||
help="percentage of accesses that should be functional",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--atomic",
|
||||
type=int,
|
||||
default=30,
|
||||
help="percentage of accesses that should be atomic",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--suppress-func-errors",
|
||||
action="store_true",
|
||||
@@ -105,6 +111,7 @@ cpus = [
|
||||
max_loads=args.maxloads,
|
||||
percent_functional=args.functional,
|
||||
percent_uncacheable=0,
|
||||
percent_atomic=args.atomic,
|
||||
progress_interval=args.progress,
|
||||
suppress_func_errors=args.suppress_func_errors,
|
||||
)
|
||||
@@ -133,7 +140,7 @@ else:
|
||||
dmas = []
|
||||
|
||||
dma_ports = []
|
||||
for (i, dma) in enumerate(dmas):
|
||||
for i, dma in enumerate(dmas):
|
||||
dma_ports.append(dma.test)
|
||||
Ruby.create_system(args, False, system, dma_ports=dma_ports)
|
||||
|
||||
@@ -155,7 +162,7 @@ system.ruby.randomization = True
|
||||
|
||||
assert len(cpus) == len(system.ruby._cpu_ports)
|
||||
|
||||
for (i, cpu) in enumerate(cpus):
|
||||
for i, cpu in enumerate(cpus):
|
||||
#
|
||||
# Tie the cpu memtester ports to the correct system ports
|
||||
#
|
||||
|
||||
@@ -63,6 +63,7 @@ class MemTest(ClockedObject):
|
||||
percent_reads = Param.Percent(65, "Percentage reads")
|
||||
percent_functional = Param.Percent(50, "Percentage functional accesses")
|
||||
percent_uncacheable = Param.Percent(10, "Percentage uncacheable")
|
||||
percent_atomic = Param.Percent(50, "Percentage atomics")
|
||||
|
||||
# Determine how often to print progress messages and what timeout
|
||||
# to use for checking progress of both requests and responses
|
||||
|
||||
@@ -94,6 +94,7 @@ MemTest::MemTest(const Params &p)
|
||||
percentReads(p.percent_reads),
|
||||
percentFunctional(p.percent_functional),
|
||||
percentUncacheable(p.percent_uncacheable),
|
||||
percentAtomic(p.percent_atomic),
|
||||
requestorId(p.system->getRequestorId(this)),
|
||||
blockSize(p.system->cacheLineSize()),
|
||||
blockAddrMask(blockSize - 1),
|
||||
@@ -115,6 +116,7 @@ MemTest::MemTest(const Params &p)
|
||||
// set up counters
|
||||
numReads = 0;
|
||||
numWrites = 0;
|
||||
numAtomics = 0;
|
||||
|
||||
// kick things into action
|
||||
schedule(tickEvent, curTick());
|
||||
@@ -142,7 +144,7 @@ MemTest::completeRequest(PacketPtr pkt, bool functional)
|
||||
outstandingAddrs.erase(remove_addr);
|
||||
|
||||
DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
|
||||
pkt->isWrite() ? "write" : "read",
|
||||
pkt->isWrite() ? pkt->isAtomicOp() ? "atomic" : "write" : "read",
|
||||
req->getPaddr(), blockAlign(req->getPaddr()),
|
||||
pkt->isError() ? "error" : "success");
|
||||
|
||||
@@ -153,7 +155,25 @@ MemTest::completeRequest(PacketPtr pkt, bool functional)
|
||||
panic( "%s access failed at %#x\n",
|
||||
pkt->isWrite() ? "Write" : "Read", req->getPaddr());
|
||||
} else {
|
||||
if (pkt->isRead()) {
|
||||
if (pkt->isAtomicOp()) {
|
||||
uint8_t ref_data = referenceData[req->getPaddr()];
|
||||
if (pkt_data[0] != ref_data) {
|
||||
panic("%s: read of %x (blk %x) @ cycle %d "
|
||||
"returns %x, expected %x\n", name(),
|
||||
req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
|
||||
pkt_data[0], ref_data);
|
||||
}
|
||||
DPRINTF(MemTest,
|
||||
"Completing atomic at address %x (blk %x) value %x\n",
|
||||
req->getPaddr(), blockAlign(req->getPaddr()),
|
||||
pkt_data[0]);
|
||||
|
||||
referenceData[req->getPaddr()] =
|
||||
atomicPendingData[req->getPaddr()];
|
||||
|
||||
numAtomics++;
|
||||
stats.numAtomics++;
|
||||
} else if (pkt->isRead()) {
|
||||
uint8_t ref_data = referenceData[req->getPaddr()];
|
||||
if (pkt_data[0] != ref_data) {
|
||||
panic("%s: read of %x (blk %x) @ cycle %d "
|
||||
@@ -167,9 +187,10 @@ MemTest::completeRequest(PacketPtr pkt, bool functional)
|
||||
|
||||
if (numReads == (uint64_t)nextProgressMessage) {
|
||||
ccprintf(std::cerr,
|
||||
"%s: completed %d read, %d write accesses @%d\n",
|
||||
name(), numReads, numWrites, curTick());
|
||||
nextProgressMessage += progressInterval;
|
||||
"%s: completed %d read, %d write, "
|
||||
"%d atomic accesses @%d\n",
|
||||
name(), numReads, numWrites, numAtomics, curTick());
|
||||
nextProgressMessage += progressInterval;
|
||||
}
|
||||
|
||||
if (maxLoads != 0 && numReads >= maxLoads)
|
||||
@@ -205,7 +226,9 @@ MemTest::MemTestStats::MemTestStats(statistics::Group *parent)
|
||||
ADD_STAT(numReads, statistics::units::Count::get(),
|
||||
"number of read accesses completed"),
|
||||
ADD_STAT(numWrites, statistics::units::Count::get(),
|
||||
"number of write accesses completed")
|
||||
"number of write accesses completed"),
|
||||
ADD_STAT(numAtomics, statistics::units::Count::get(),
|
||||
"number of atomic accesses completed")
|
||||
{
|
||||
|
||||
}
|
||||
@@ -221,6 +244,8 @@ MemTest::tick()
|
||||
unsigned cmd = random_mt.random(0, 100);
|
||||
uint8_t data = random_mt.random<uint8_t>();
|
||||
bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
|
||||
bool do_atomic = (random_mt.random(0, 100) < percentAtomic) &&
|
||||
!uncacheable;
|
||||
unsigned base = random_mt.random(0, 1);
|
||||
Request::Flags flags;
|
||||
Addr paddr;
|
||||
@@ -281,13 +306,36 @@ MemTest::tick()
|
||||
pkt = new Packet(req, MemCmd::ReadReq);
|
||||
pkt->dataDynamic(pkt_data);
|
||||
} else {
|
||||
DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n",
|
||||
do_functional ? "functional " : "", req->getPaddr(),
|
||||
blockAlign(req->getPaddr()), data);
|
||||
if (do_atomic) {
|
||||
DPRINTF(MemTest,
|
||||
"Initiating atomic at addr %x (blk %x) value %x\n",
|
||||
req->getPaddr(), blockAlign(req->getPaddr()), data);
|
||||
|
||||
pkt = new Packet(req, MemCmd::WriteReq);
|
||||
pkt->dataDynamic(pkt_data);
|
||||
pkt_data[0] = data;
|
||||
TypedAtomicOpFunctor<uint8_t> *_amo_op =
|
||||
new AtomicGeneric3Op<uint8_t>(
|
||||
data, data,
|
||||
[](uint8_t* b, uint8_t a, uint8_t c){
|
||||
*b = c;
|
||||
});
|
||||
assert(_amo_op);
|
||||
AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(_amo_op);
|
||||
req->setAtomicOpFunctor(std::move(amo_op));
|
||||
req->setFlags(Request::ATOMIC_RETURN_OP);
|
||||
|
||||
pkt = new Packet(req, MemCmd::WriteReq);
|
||||
pkt->dataDynamic(pkt_data);
|
||||
pkt_data[0] = data;
|
||||
atomicPendingData[req->getPaddr()] = data;
|
||||
} else {
|
||||
DPRINTF(MemTest,
|
||||
"Initiating %swrite at addr %x (blk %x) value %x\n",
|
||||
do_functional ? "functional " : "", req->getPaddr(),
|
||||
blockAlign(req->getPaddr()), data);
|
||||
|
||||
pkt = new Packet(req, MemCmd::WriteReq);
|
||||
pkt->dataDynamic(pkt_data);
|
||||
pkt_data[0] = data;
|
||||
}
|
||||
}
|
||||
|
||||
// there is no point in ticking if we are waiting for a retry
|
||||
|
||||
@@ -131,6 +131,7 @@ class MemTest : public ClockedObject
|
||||
const unsigned percentReads;
|
||||
const unsigned percentFunctional;
|
||||
const unsigned percentUncacheable;
|
||||
const unsigned percentAtomic;
|
||||
|
||||
/** Request id for all generated traffic */
|
||||
RequestorID requestorId;
|
||||
@@ -138,6 +139,7 @@ class MemTest : public ClockedObject
|
||||
unsigned int id;
|
||||
|
||||
std::unordered_set<Addr> outstandingAddrs;
|
||||
std::unordered_map<Addr, uint8_t> atomicPendingData;
|
||||
|
||||
// store the expected value for the addresses we have touched
|
||||
std::unordered_map<Addr, uint8_t> referenceData;
|
||||
@@ -169,6 +171,7 @@ class MemTest : public ClockedObject
|
||||
|
||||
uint64_t numReads;
|
||||
uint64_t numWrites;
|
||||
uint64_t numAtomics;
|
||||
const uint64_t maxLoads;
|
||||
|
||||
const bool atomic;
|
||||
@@ -180,6 +183,7 @@ class MemTest : public ClockedObject
|
||||
MemTestStats(statistics::Group *parent);
|
||||
statistics::Scalar numReads;
|
||||
statistics::Scalar numWrites;
|
||||
statistics::Scalar numAtomics;
|
||||
} stats;
|
||||
|
||||
/**
|
||||
|
||||
@@ -757,6 +757,13 @@ class Request : public Extensible<Request>
|
||||
return atomicOpFunctor.get();
|
||||
}
|
||||
|
||||
void
|
||||
setAtomicOpFunctor(AtomicOpFunctorPtr amo_op)
|
||||
{
|
||||
atomicOpFunctor = std::move(amo_op);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accessor for hardware transactional memory abort cause.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user