/*
- * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2012-2013, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* Andreas Hansson
*/
-#include "base/callback.hh"
-#include "base/output.hh"
#include "base/trace.hh"
#include "debug/CommMonitor.hh"
#include "mem/comm_monitor.hh"
-#include "proto/packet.pb.h"
#include "sim/stats.hh"
CommMonitor::CommMonitor(Params* params)
slavePort(name() + "-slave", *this),
samplePeriodicEvent(this),
samplePeriodTicks(params->sample_period),
+ samplePeriod(params->sample_period / SimClock::Float::s),
readAddrMask(params->read_addr_mask),
writeAddrMask(params->write_addr_mask),
- stats(params),
- stackDistCalc(params->stack_dist_calc),
- traceStream(NULL),
- system(params->system)
+ stats(params)
{
- // If we are using a trace file, then open the file
- if (params->trace_enable) {
- std::string filename;
- if (params->trace_file != "") {
- // If the trace file is not specified as an absolute path,
- // append the current simulation output directory
- filename = simout.resolve(params->trace_file);
-
- std::string suffix = ".gz";
- // If trace_compress has been set, check the suffix. Append
- // accordingly.
- if (params->trace_compress &&
- filename.compare(filename.size() - suffix.size(), suffix.size(),
- suffix) != 0)
- filename = filename + suffix;
- } else {
- // Generate a filename from the name of the SimObject. Append .trc
- // and .gz if we want compression enabled.
- filename = simout.resolve(name() + ".trc" +
- (params->trace_compress ? ".gz" : ""));
- }
-
- traceStream = new ProtoOutputStream(filename);
-
- // Create a protobuf message for the header and write it to
- // the stream
- ProtoMessage::PacketHeader header_msg;
- header_msg.set_obj_id(name());
- header_msg.set_tick_freq(SimClock::Frequency);
- traceStream->write(header_msg);
-
- // Register a callback to compensate for the destructor not
- // being called. The callback forces the stream to flush and
- // closes the output file.
- Callback* cb = new MakeCallback<CommMonitor,
- &CommMonitor::closeStreams>(this);
- registerExitCallback(cb);
- }
-
- // keep track of the sample period both in ticks and absolute time
- samplePeriod.setTick(params->sample_period);
-
DPRINTF(CommMonitor,
"Created monitor %s with sample period %d ticks (%f ms)\n",
- name(), samplePeriodTicks, samplePeriod.msec());
-}
-
-CommMonitor::~CommMonitor()
-{
- // if not already done, close the stream
- closeStreams();
-}
-
-void
-CommMonitor::closeStreams()
-{
- if (traceStream != NULL)
- delete traceStream;
+ name(), samplePeriodTicks, samplePeriod * 1E3);
}
CommMonitor*
// make sure both sides of the monitor are connected
if (!slavePort.isConnected() || !masterPort.isConnected())
fatal("Communication monitor is not connected on both sides.\n");
+}
- if (traceStream != NULL) {
- // Check the memory mode. We only record something when in
- // timing mode. Warn accordingly.
- if (!system->isTimingMode())
- warn("%s: Not in timing mode. No trace will be recorded.", name());
- }
-
+void
+CommMonitor::regProbePoints()
+{
+ ppPktReq.reset(new ProbePoints::Packet(getProbeManager(), "PktRequest"));
+ ppPktResp.reset(new ProbePoints::Packet(getProbeManager(), "PktResponse"));
}
BaseMasterPort&
Tick
CommMonitor::recvAtomic(PacketPtr pkt)
{
- // allow stack distance calculations for atomic if enabled
- if (stackDistCalc)
- stackDistCalc->update(pkt->cmd, pkt->getAddr());
+ ppPktReq->notify(pkt);
- return masterPort.sendAtomic(pkt);
+ const Tick delay(masterPort.sendAtomic(pkt));
+ assert(pkt->isResponse());
+ ppPktResp->notify(pkt);
+ return delay;
}
Tick
// Store relevant fields of packet, because packet may be modified
// or even deleted when sendTiming() is called.
- bool is_read = pkt->isRead();
- bool is_write = pkt->isWrite();
- MemCmd cmd = pkt->cmd;
- int cmd_idx = pkt->cmdToIndex();
- Request::FlagsType req_flags = pkt->req->getFlags();
- unsigned size = pkt->getSize();
- Addr addr = pkt->getAddr();
- bool expects_response = pkt->needsResponse() && !pkt->memInhibitAsserted();
+ const bool is_read = pkt->isRead();
+ const bool is_write = pkt->isWrite();
+ const MemCmd cmd = pkt->cmd;
+ const unsigned size = pkt->getSize();
+ const Addr addr = pkt->getAddr();
+ const bool expects_response(
+ pkt->needsResponse() && !pkt->memInhibitAsserted());
// If a cache miss is served by a cache, a monitor near the memory
// would see a request which needs a response, but this response
delete pkt->popSenderState();
}
- // If successful and we are calculating stack distances, update
- // the calculator
- if (successful && stackDistCalc)
- stackDistCalc->update(cmd, addr);
-
- if (successful && traceStream != NULL) {
- // Create a protobuf message representing the
- // packet. Currently we do not preserve the flags in the
- // trace.
- ProtoMessage::Packet pkt_msg;
- pkt_msg.set_tick(curTick());
- pkt_msg.set_cmd(cmd_idx);
- pkt_msg.set_flags(req_flags);
- pkt_msg.set_addr(addr);
- pkt_msg.set_size(size);
-
- traceStream->write(pkt_msg);
+ if (successful) {
+ // The receiver might already have modified the packet. We
+ // want to give the probe access to the original packet, which
+ // means we need to fake the original packet by temporarily
+ // restoring the command.
+ const MemCmd response_cmd(pkt->cmd);
+ pkt->cmd = cmd;
+ ppPktReq->notify(pkt);
+ pkt->cmd = response_cmd;
}
if (successful && is_read) {
}
}
+ if (successful) {
+ assert(pkt->isResponse());
+ ppPktResp->notify(pkt);
+ }
+
if (successful && is_read) {
// Decrement number of outstanding read requests
DPRINTF(CommMonitor, "Received read response\n");
}
void
-CommMonitor::recvRetryMaster()
+CommMonitor::recvReqRetry()
{
- slavePort.sendRetry();
+ slavePort.sendRetryReq();
}
void
-CommMonitor::recvRetrySlave()
+CommMonitor::recvRespRetry()
{
- masterPort.sendRetry();
+ masterPort.sendRetryResp();
}
void