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:
parent
11ab30fa5a
commit
f456c7983d
9 changed files with 139 additions and 17 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
58
src/proto/packet.proto
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue