From a3f49f60c74c33ede433a024ae85d1ca47ed3c78 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Tue, 4 Aug 2015 10:29:13 +0100 Subject: [PATCH] mem: Move trace functionality from the CommMonitor to a probe This changeset moves the access trace functionality from the CommMonitor into a separate probe. The probe can be hooked up to any component that exports probe points of the type ProbePoints::Packet. This patch moves the dependency on Google's Protocol Buffers library from the CommMonitor to the MemTraceProbe, which means that the CommMonitor (including stack distance profiling) no long depends on it. --- src/mem/CommMonitor.py | 10 --- src/mem/SConscript | 7 +- src/mem/comm_monitor.cc | 94 ------------------------- src/mem/comm_monitor.hh | 17 ----- src/mem/probes/MemTraceProbe.py | 51 ++++++++++++++ src/mem/probes/SConscript | 5 ++ src/mem/probes/mem_trace.cc | 114 +++++++++++++++++++++++++++++++ src/mem/probes/mem_trace.hh | 69 +++++++++++++++++++ tests/configs/tgen-simple-mem.py | 4 +- 9 files changed, 243 insertions(+), 128 deletions(-) create mode 100644 src/mem/probes/MemTraceProbe.py create mode 100644 src/mem/probes/mem_trace.cc create mode 100644 src/mem/probes/mem_trace.hh diff --git a/src/mem/CommMonitor.py b/src/mem/CommMonitor.py index ba871357d..aa8da62ed 100644 --- a/src/mem/CommMonitor.py +++ b/src/mem/CommMonitor.py @@ -53,16 +53,6 @@ class CommMonitor(MemObject): master = MasterPort("Master port") slave = SlavePort("Slave port") - # Boolean to enable or disable the trace. Writes to an a file named based on - # SimObject hierarchy. - trace_enable = Param.Bool(False, "Enable trace capture") - - # Boolean to compress the trace or not. - trace_compress = Param.Bool(True, "Enable trace compression") - - # 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 4f1216745..404f4a90f 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -30,11 +30,8 @@ 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('CommMonitor.py') +Source('comm_monitor.cc') SimObject('AbstractMemory.py') SimObject('AddrMapper.py') diff --git a/src/mem/comm_monitor.cc b/src/mem/comm_monitor.cc index 35f4738d6..beb7fe32c 100644 --- a/src/mem/comm_monitor.cc +++ b/src/mem/comm_monitor.cc @@ -38,12 +38,9 @@ * 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) @@ -55,67 +52,13 @@ CommMonitor::CommMonitor(Params* params) samplePeriod(params->sample_period / SimClock::Float::s), readAddrMask(params->read_addr_mask), writeAddrMask(params->write_addr_mask), - system(params->system), - traceStream(nullptr), 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(this); - registerExitCallback(cb); - } - DPRINTF(CommMonitor, "Created monitor %s with sample period %d ticks (%f ms)\n", name(), samplePeriodTicks, samplePeriod * 1E3); } -CommMonitor::~CommMonitor() -{ - // if not already done, close the stream - closeStreams(); -} - -void -CommMonitor::closeStreams() -{ - if (traceStream != NULL) - delete traceStream; -} - CommMonitor* CommMonitorParams::create() { @@ -128,14 +71,6 @@ CommMonitor::init() // 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 @@ -182,19 +117,6 @@ CommMonitor::recvAtomic(PacketPtr pkt) { ppPktReq->notify(pkt); - // if tracing enabled, store the packet information - // to the trace stream - if (traceStream != NULL) { - ProtoMessage::Packet pkt_msg; - pkt_msg.set_tick(curTick()); - pkt_msg.set_cmd(pkt->cmdToIndex()); - pkt_msg.set_flags(pkt->req->getFlags()); - pkt_msg.set_addr(pkt->getAddr()); - pkt_msg.set_size(pkt->getSize()); - - traceStream->write(pkt_msg); - } - const Tick delay(masterPort.sendAtomic(pkt)); assert(pkt->isResponse()); ppPktResp->notify(pkt); @@ -218,8 +140,6 @@ CommMonitor::recvTimingReq(PacketPtr pkt) const bool is_read = pkt->isRead(); const bool is_write = pkt->isWrite(); const MemCmd cmd = pkt->cmd; - const int cmd_idx = pkt->cmdToIndex(); - const Request::FlagsType req_flags = pkt->req->getFlags(); const unsigned size = pkt->getSize(); const Addr addr = pkt->getAddr(); const bool expects_response( @@ -253,20 +173,6 @@ CommMonitor::recvTimingReq(PacketPtr pkt) pkt->cmd = response_cmd; } - 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 && is_read) { DPRINTF(CommMonitor, "Forwarded read request\n"); diff --git a/src/mem/comm_monitor.hh b/src/mem/comm_monitor.hh index d2ce1d224..fb8f5eeb7 100644 --- a/src/mem/comm_monitor.hh +++ b/src/mem/comm_monitor.hh @@ -44,9 +44,7 @@ #include "base/statistics.hh" #include "mem/mem_object.hh" #include "params/CommMonitor.hh" -#include "proto/protoio.hh" #include "sim/probe/mem.hh" -#include "sim/system.hh" /** * The communication monitor is a MemObject which can monitor statistics of @@ -76,9 +74,6 @@ class CommMonitor : public MemObject */ CommMonitor(Params* params); - /** Destructor */ - ~CommMonitor(); - void init() M5_ATTR_OVERRIDE; void regStats() M5_ATTR_OVERRIDE; void startup() M5_ATTR_OVERRIDE; @@ -391,12 +386,6 @@ class CommMonitor : public MemObject /** This function is called periodically at the end of each time bin */ void samplePeriodic(); - /** - * Callback to flush and close all open output streams on exit. If - * we were calling the destructor it could be done there. - */ - void closeStreams(); - /** Periodic event called at the end of each simulation time bin */ EventWrapper samplePeriodicEvent; @@ -416,14 +405,8 @@ class CommMonitor : public MemObject /** Address mask for sources of write accesses to be captured */ const Addr writeAddrMask; - /** The system in which the monitor lives */ - System *const system; - /** @} */ - /** Output stream for a potential trace. */ - ProtoOutputStream *traceStream; - /** Instantiate stats */ MonitorStats stats; diff --git a/src/mem/probes/MemTraceProbe.py b/src/mem/probes/MemTraceProbe.py new file mode 100644 index 000000000..971765eb4 --- /dev/null +++ b/src/mem/probes/MemTraceProbe.py @@ -0,0 +1,51 @@ +# Copyright (c) 2014-2015 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 Sandberg + +from m5.params import * +from m5.proxy import * +from BaseMemProbe import BaseMemProbe + +class MemTraceProbe(BaseMemProbe): + type = 'MemTraceProbe' + cxx_header = "mem/probes/mem_trace.hh" + + # Boolean to compress the trace or not. + trace_compress = Param.Bool(True, "Enable trace compression") + + # packet trace output file, disabled by default + trace_file = Param.String("", "Packet trace output file") + diff --git a/src/mem/probes/SConscript b/src/mem/probes/SConscript index 7391545fb..78423c5d6 100644 --- a/src/mem/probes/SConscript +++ b/src/mem/probes/SConscript @@ -44,3 +44,8 @@ Source('base.cc') SimObject('StackDistProbe.py') Source('stack_dist.cc') + +# Packet tracing requires protobuf support +if env['HAVE_PROTOBUF']: + SimObject('MemTraceProbe.py') + Source('mem_trace.cc') diff --git a/src/mem/probes/mem_trace.cc b/src/mem/probes/mem_trace.cc new file mode 100644 index 000000000..6bf6f7f77 --- /dev/null +++ b/src/mem/probes/mem_trace.cc @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 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 + * Andreas Sandberg + */ + +#include "mem/probes/mem_trace.hh" + +#include "base/callback.hh" +#include "base/output.hh" +#include "params/MemTraceProbe.hh" +#include "proto/packet.pb.h" + +MemTraceProbe::MemTraceProbe(MemTraceProbeParams *p) + : BaseMemProbe(p), + traceStream(nullptr) +{ + std::string filename; + if (p->trace_file != "") { + // If the trace file is not specified as an absolute path, + // append the current simulation output directory + filename = simout.resolve(p->trace_file); + + const std::string suffix = ".gz"; + // If trace_compress has been set, check the suffix. Append + // accordingly. + if (p->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" + + (p->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. + registerExitCallback( + new MakeCallback(this)); +} + +void +MemTraceProbe::closeStreams() +{ + if (traceStream != NULL) + delete traceStream; +} + +void +MemTraceProbe::handleRequest(const PacketPtr &pkt) +{ + ProtoMessage::Packet pkt_msg; + + pkt_msg.set_tick(curTick()); + pkt_msg.set_cmd(pkt->cmdToIndex()); + pkt_msg.set_flags(pkt->req->getFlags()); + pkt_msg.set_addr(pkt->getAddr()); + pkt_msg.set_size(pkt->getSize()); + + traceStream->write(pkt_msg); +} + + +MemTraceProbe * +MemTraceProbeParams::create() +{ + return new MemTraceProbe(this); +} diff --git a/src/mem/probes/mem_trace.hh b/src/mem/probes/mem_trace.hh new file mode 100644 index 000000000..93c6067ae --- /dev/null +++ b/src/mem/probes/mem_trace.hh @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 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 Sandberg + */ + +#ifndef __MEM_PROBES_STACK_DIST_HH__ +#define __MEM_PROBES_STACK_DIST_HH__ + +#include "mem/packet.hh" +#include "mem/probes/base.hh" +#include "proto/protoio.hh" + +struct MemTraceProbeParams; + +class MemTraceProbe : public BaseMemProbe +{ + public: + MemTraceProbe(MemTraceProbeParams *params); + + protected: + void handleRequest(const PacketPtr &pkt) M5_ATTR_OVERRIDE; + + /** + * Callback to flush and close all open output streams on exit. If + * we were calling the destructor it could be done there. + */ + void closeStreams(); + + protected: + + /** Trace output stream */ + ProtoOutputStream *traceStream; +}; + +#endif //__MEM_PROBES_STACK_DIST_HH__ diff --git a/tests/configs/tgen-simple-mem.py b/tests/configs/tgen-simple-mem.py index 8c2aa80a9..d128eb37d 100644 --- a/tests/configs/tgen-simple-mem.py +++ b/tests/configs/tgen-simple-mem.py @@ -56,8 +56,8 @@ system = System(cpu = cpu, physmem = SimpleMemory(), # add a communication monitor, and also trace all the packets and # calculate and verify stack distance -system.monitor = CommMonitor(trace_file = "monitor.ptrc.gz", - trace_enable = True) +system.monitor = CommMonitor() +system.monitor.trace = MemTraceProbe(trace_file = "monitor.ptrc.gz") system.monitor.stackdist = StackDistProbe(verify = True) # connect the traffic generator to the bus via a communication monitor