From f456c7983ded455b006d25a9c5e17401f6c22dca Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Mon, 7 Jan 2013 13:05:37 -0500 Subject: mem: Add tracing support in the communication monitor This patch adds packet tracing to the communication monitor using a protobuf as the mechanism for creating the trace. If no file is specified, then the tracing is disabled. If a file is specified, then for every packet that is successfully sent, a protobuf message is serialized to the file. --- src/mem/CommMonitor.py | 3 +++ src/mem/SConscript | 8 ++++++-- src/mem/comm_monitor.cc | 48 +++++++++++++++++++++++++++++++++++++++++++++++- src/mem/comm_monitor.hh | 12 +++++++++++- 4 files changed, 67 insertions(+), 4 deletions(-) (limited to 'src/mem') diff --git a/src/mem/CommMonitor.py b/src/mem/CommMonitor.py index a34a57db4..3f9106cc4 100644 --- a/src/mem/CommMonitor.py +++ b/src/mem/CommMonitor.py @@ -49,6 +49,9 @@ class CommMonitor(MemObject): master = MasterPort("Master port") slave = SlavePort("Slave port") + # packet trace output file, disabled by default + trace_file = Param.String("", "Packet trace output file") + # control the sample period window length of this monitor sample_period = Param.Clock("1ms", "Sample period for histograms") diff --git a/src/mem/SConscript b/src/mem/SConscript index 374f904a8..ca89418b5 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -30,17 +30,21 @@ Import('*') +# Only build the communication if we have support for protobuf as the +# tracing relies on it +if env['HAVE_PROTOBUF']: + SimObject('CommMonitor.py') + Source('comm_monitor.cc') + SimObject('AddrMapper.py') SimObject('Bridge.py') SimObject('Bus.py') -SimObject('CommMonitor.py') SimObject('MemObject.py') Source('addr_mapper.cc') Source('bridge.cc') Source('bus.cc') Source('coherent_bus.cc') -Source('comm_monitor.cc') Source('mem_object.cc') Source('mport.cc') Source('noncoherent_bus.cc') diff --git a/src/mem/comm_monitor.cc b/src/mem/comm_monitor.cc index 7e98f64f6..88e549cbb 100644 --- a/src/mem/comm_monitor.cc +++ b/src/mem/comm_monitor.cc @@ -38,9 +38,12 @@ * 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) @@ -51,8 +54,31 @@ CommMonitor::CommMonitor(Params* params) samplePeriodTicks(params->sample_period), readAddrMask(params->read_addr_mask), writeAddrMask(params->write_addr_mask), - stats(params) + stats(params), + traceStream(NULL) { + // If we are using a trace file, then open the file, + if (params->trace_file != "") { + // If the trace file is not specified as an absolute path, + // append the current simulation output directory + std::string filename = simout.resolve(params->trace_file); + traceStream = new ProtoOutputStream(filename); + + // Create a protobuf message for the header and write it to + // the stream + Message::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(this); + registerExitCallback(cb); + } + // keep track of the sample period both in ticks and absolute time samplePeriod.setTick(params->sample_period); @@ -61,6 +87,13 @@ CommMonitor::CommMonitor(Params* params) name(), samplePeriodTicks, samplePeriod); } +void +CommMonitor::closeStreams() +{ + if (traceStream != NULL) + delete traceStream; +} + CommMonitor* CommMonitorParams::create() { @@ -154,6 +187,19 @@ CommMonitor::recvTimingReq(PacketPtr pkt) pkt->senderState = senderState; } + if (successful && traceStream != NULL) { + // Create a protobuf message representing the + // packet. Currently we do not preserve the flags in the + // trace. + Message::Packet pkt_msg; + pkt_msg.set_tick(curTick()); + pkt_msg.set_cmd(pkt->cmdToIndex()); + pkt_msg.set_addr(pkt->getAddr()); + pkt_msg.set_size(pkt->getSize()); + + traceStream->write(pkt_msg); + } + if (successful && isRead) { DPRINTF(CommMonitor, "Forwarded read request\n"); diff --git a/src/mem/comm_monitor.hh b/src/mem/comm_monitor.hh index e59b8c467..271ae5fff 100644 --- a/src/mem/comm_monitor.hh +++ b/src/mem/comm_monitor.hh @@ -45,6 +45,7 @@ #include "base/time.hh" #include "mem/mem_object.hh" #include "params/CommMonitor.hh" +#include "proto/protoio.hh" /** * The communication monitor is a MemObject which can monitor statistics of @@ -75,7 +76,13 @@ class CommMonitor : public MemObject CommMonitor(Params* params); /** Destructor */ - ~CommMonitor() { } + ~CommMonitor() {} + + /** + * Callback to flush and close all open output streams on exit. If + * we were calling the destructor it could be done there. + */ + void closeStreams(); virtual BaseMasterPort& getMasterPort(const std::string& if_name, PortID idx = InvalidPortID); @@ -427,6 +434,9 @@ class CommMonitor : public MemObject /** Instantiate stats */ MonitorStats stats; + + /** Output stream for a potential trace. */ + ProtoOutputStream* traceStream; }; #endif //__MEM_COMM_MONITOR_HH__ -- cgit v1.2.3