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.
This commit is contained in:
Andreas Hansson 2013-01-07 13:05:37 -05:00
parent 11ab30fa5a
commit f456c7983d
9 changed files with 139 additions and 17 deletions

View file

@ -145,7 +145,7 @@ OutputDirectory::directory() const
return dir;
}
inline string
string
OutputDirectory::resolve(const string &name) const
{
return (name[0] != PATH_SEPARATOR) ? dir + name : name;

View file

@ -52,16 +52,6 @@ class OutputDirectory
/** System-specific path separator character */
static const char PATH_SEPARATOR = '/';
/**
* Returns relative file names prepended with name of this directory.
* Returns absolute file names unaltered.
*
* @param name file name to prepend with directory name
* @return file name prepended with base directory name or unaltered
* absolute file name
*/
std::string resolve(const std::string &name) const;
protected:
/**
* Determines whether given file name corresponds to standard output
@ -80,6 +70,16 @@ class OutputDirectory
/** Destructor. */
~OutputDirectory();
/**
* Returns relative file names prepended with name of this directory.
* Returns absolute file names unaltered.
*
* @param name file name to prepend with directory name
* @return file name prepended with base directory name or unaltered
* absolute file name
*/
std::string resolve(const std::string &name) const;
/** Opens a file (optionally compressed).
*
* Will open a file as a compressed stream if filename ends in .gz.

View file

@ -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")

View file

@ -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')

View file

@ -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<CommMonitor,
&CommMonitor::closeStreams>(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");

View file

@ -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
@ -77,6 +78,12 @@ class CommMonitor : public MemObject
/** Destructor */
~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__

View file

@ -41,4 +41,5 @@ Import('*')
# Only build if we have protobuf support
if env['HAVE_PROTOBUF']:
ProtoBuf('packet.proto')
Source('protoio.cc')

58
src/proto/packet.proto Normal file
View file

@ -0,0 +1,58 @@
// Copyright (c) 2012 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder. You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Andreas Hansson
// Put all the generated messages in a namespace
package Message;
// Packet header with the identifier describing what object captured
// the trace, the version of this file format, and the tick frequency
// for all the packet time stamps.
message PacketHeader {
required string obj_id = 1;
optional uint32 ver = 2 [default = 0];
required uint64 tick_freq = 3;
}
// Each packet in the trace contains a tick (which can be translated
// to absolute time using the frequency in the header), the command,
// the address, and the size in bytes
message Packet {
required uint64 tick = 1;
required uint32 cmd = 2;
required uint64 addr = 3;
required uint32 size = 4;
}

View file

@ -46,8 +46,8 @@ cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-mem.cfg")
system = System(cpu = cpu, physmem = SimpleMemory(),
membus = NoncoherentBus(clock="1GHz", width = 16))
# add a communication monitor
system.monitor = CommMonitor()
# add a communication monitor, and also trace all the packets
system.monitor = CommMonitor(trace_file = "monitor.ptrc.gz")
# connect the traffic generator to the bus via a communication monitor
system.cpu.port = system.monitor.slave