cpu: add support for outputing a protobuf formatted CPU trace

Doesn't support x86 due to static instruction representation.

--HG--
rename : src/cpu/CPUTracers.py => src/cpu/InstPBTrace.py
This commit is contained in:
Ali Saidi 2015-02-16 03:32:38 -05:00
parent 268d9e59c5
commit 4eff4fa12e
7 changed files with 614 additions and 0 deletions

37
src/cpu/InstPBTrace.py Normal file
View file

@ -0,0 +1,37 @@
# Copyright (c) 2007 The Regents of The University of Michigan
# All rights reserved.
#
# 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: Gabe Black
from m5.SimObject import SimObject
from m5.params import *
from InstTracer import InstTracer
class InstPBTrace(InstTracer):
type = 'InstPBTrace'
cxx_class = 'Trace::InstPBTrace'
cxx_header = 'cpu/inst_pb_trace.hh'
file_name = Param.String("Instruction trace output file")

View file

@ -35,6 +35,11 @@ if env['TARGET_ISA'] == 'null':
Source('intr_control_noisa.cc')
Return()
# Only build the protocol buffer instructions tracer if we have protobuf support
if env['HAVE_PROTOBUF'] and env['TARGET_ISA'] != 'x86':
SimObject('InstPBTrace.py')
Source('inst_pb_trace.cc')
SimObject('CheckerCPU.py')
SimObject('BaseCPU.py')

178
src/cpu/inst_pb_trace.cc Normal file
View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2014 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: Ali Saidi
*/
#include "cpu/inst_pb_trace.hh"
#include "base/callback.hh"
#include "base/output.hh"
#include "config/the_isa.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "debug/ExecEnable.hh"
#include "params/InstPBTrace.hh"
#include "proto/inst.pb.h"
#include "sim/core.hh"
namespace Trace {
ProtoOutputStream *InstPBTrace::traceStream;
void
InstPBTraceRecord::dump()
{
// We're trying to build an instruction trace so we just want macro-ops and
// instructions that aren't macro-oped
if ((macroStaticInst && staticInst->isFirstMicroop()) ||
!staticInst->isMicroop()) {
tracer.traceInst(thread, staticInst, pc);
}
// If this instruction accessed memory lets record it
if (getMemValid())
tracer.traceMem(staticInst, getAddr(), getSize(), getFlags());
}
InstPBTrace::InstPBTrace(const InstPBTraceParams *p)
: InstTracer(p), curMsg(nullptr)
{
// Create our output file
createTraceFile(p->file_name);
}
void
InstPBTrace::createTraceFile(std::string filename)
{
// Since there is only one output file for all tracers check if it exists
if (traceStream)
return;
traceStream = new ProtoOutputStream(simout.resolve(filename));
// Output the header
ProtoMessage::InstHeader header_msg;
header_msg.set_obj_id("gem5 generated instruction trace");
header_msg.set_ver(0);
header_msg.set_tick_freq(SimClock::Frequency);
header_msg.set_has_mem(true);
traceStream->write(header_msg);
// get a callback when we exit so we can close the file
Callback *cb = new MakeCallback<InstPBTrace,
&InstPBTrace::closeStreams>(this);
registerExitCallback(cb);
}
void
InstPBTrace::closeStreams()
{
if (curMsg) {
traceStream->write(*curMsg);
delete curMsg;
curMsg = NULL;
}
if (!traceStream)
return;
delete traceStream;
traceStream = NULL;
}
InstPBTrace::~InstPBTrace()
{
closeStreams();
}
InstPBTraceRecord*
InstPBTrace::getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr si,
TheISA::PCState pc, const StaticInstPtr mi)
{
// Only record the trace if Exec debugging in enabled
if (!Trace::enabled || !Debug::ExecEnable)
return NULL;
return new InstPBTraceRecord(*this, when, tc, si, pc, mi);
}
void
InstPBTrace::traceInst(ThreadContext *tc, StaticInstPtr si, TheISA::PCState pc)
{
if (curMsg) {
/// @todo if we are running multi-threaded I assume we'd need a lock here
traceStream->write(*curMsg);
delete curMsg;
curMsg = NULL;
}
// Create a new instruction message and fill out the fields
curMsg = new ProtoMessage::Inst;
curMsg->set_pc(pc.pc());
curMsg->set_inst(static_cast<uint32_t>(bits(si->machInst, 31, 0)));
curMsg->set_cpuid(tc->cpuId());
curMsg->set_tick(curTick());
curMsg->set_type(static_cast<ProtoMessage::Inst_InstType>(si->opClass()));
curMsg->set_inst_flags(bits(si->machInst, 7, 0));
}
void
InstPBTrace::traceMem(StaticInstPtr si, Addr a, Addr s, unsigned f)
{
panic_if(!curMsg, "Memory access w/o msg?!");
// We do a poor job identifying macro-ops that are load/stores
curMsg->set_type(static_cast<ProtoMessage::Inst_InstType>(si->opClass()));
ProtoMessage::Inst::MemAccess *mem_msg = curMsg->add_mem_access();
mem_msg->set_addr(a);
mem_msg->set_size(s);
mem_msg->set_mem_flags(f);
}
} // namespace Trace
Trace::InstPBTrace*
InstPBTraceParams::create()
{
return new Trace::InstPBTrace(this);
}

135
src/cpu/inst_pb_trace.hh Normal file
View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2014 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: Ali Saidi
*/
#ifndef __CPU_INST_PB_TRACE_HH__
#define __CPU_INST_PB_TRACE_HH__
#include "arch/types.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "cpu/static_inst_fwd.hh"
#include "params/InstPBTrace.hh"
#include "proto/protoio.hh"
#include "sim/insttracer.hh"
class ThreadContext;
namespace ProtoMessage {
class Inst;
}
namespace Trace {
/**
* This in an instruction tracer that records the flow of instructions through
* multiple cpus and systems to a protobuf file specified by proto/inst.proto
* for further analysis.
*/
class InstPBTraceRecord : public InstRecord
{
public:
InstPBTraceRecord(InstPBTrace& _tracer, Tick when, ThreadContext *tc,
const StaticInstPtr si, TheISA::PCState pc,
const StaticInstPtr mi = NULL)
: InstRecord(when, tc, si, pc, mi), tracer(_tracer)
{}
/** called by the cpu when the instruction commits.
* This implementation of dump calls InstPBTrace to output the contents to a
* protobuf file
*/
void dump() M5_ATTR_OVERRIDE;
protected:
InstPBTrace& tracer;
};
class InstPBTrace : InstTracer
{
public:
InstPBTrace(const InstPBTraceParams *p);
virtual ~InstPBTrace();
InstPBTraceRecord* getInstRecord(Tick when, ThreadContext *tc, const
StaticInstPtr si, TheISA::PCState pc, const
StaticInstPtr mi = NULL) M5_ATTR_OVERRIDE;
protected:
/** One output stream for the entire simulation.
* We encode the CPU & system ID so all we need is a single file
*/
static ProtoOutputStream *traceStream;
/** This is the message were working on writing. The majority of the message
* exists however the memory accesses will be delayed.
*/
ProtoMessage::Inst *curMsg;
/** Create the output file and write the header into it
* @param filename the file to create (if ends with .gz it will be
* compressed)
*/
void createTraceFile(std::string filename);
/** If there is a pending message still write it out and then close the file
*/
void closeStreams();
/** Write an instruction to the trace file
* @param tc thread context for the cpu ID
* @param si for the machInst and opClass
* @param pc for the PC Addr
*/
void traceInst(ThreadContext *tc, StaticInstPtr si, TheISA::PCState pc);
/** Write a memory request to the trace file as part of the cur instruction
* @param si for the machInst and opClass
* @param a address of the request
* @param s size of the request
* @param f flags for the request
*/
void traceMem(StaticInstPtr si, Addr a, Addr s, unsigned f);
friend class InstPBTraceRecord;
};
} // namespace Trace
#endif // __CPU_INST_PB_TRACE_HH__

View file

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

107
src/proto/inst.proto Normal file
View file

@ -0,0 +1,107 @@
// Copyright (c) 2014 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: Ali Saidi
// Put all the generated messages in a namespace
package ProtoMessage;
// 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 InstHeader {
required string obj_id = 1;
required uint32 ver = 2 [default = 0];
required uint64 tick_freq = 3;
required bool has_mem = 4;
}
message Inst {
required uint64 pc = 1;
required fixed32 inst = 2;
optional uint32 nodeid = 3;
optional uint32 cpuid = 4;
optional fixed64 tick = 5;
enum InstType {
None = 0;
IntAlu = 1;
IntMul = 2;
IntDiv = 3;
FloatAdd = 4;
FloatCmp = 5;
FloatCvt = 6;
FloatMult = 7;
FloatDiv = 8;
FloatSqrt = 9;
SIMDIntAdd = 10;
SIMDIntAddAcc = 11;
SIMDIntAlu = 12;
SIMDIntCmp = 13;
SIMDIntCvt = 14;
SIMDMisc = 15;
SIMDIntMult = 16;
SIMDIntMultAcc = 17;
SIMDIntShift = 18;
SIMDIntShiftAcc = 19;
SIMDSqrt = 20;
SIMDFloatAdd = 21;
SIMDFloatAlu = 22;
SIMDFloatCmp = 23;
SIMDFloatCvt = 24;
SIMDFloatDiv = 25;
SIMDFloatMisc = 26;
SIMDFloatMult = 27;
SIMDFloatMultAdd = 28;
SIMDFloatSqrt = 29;
MemRead = 30;
MemWrite = 31;
IprAccess = 32;
InstPrefetch = 33;
}
optional InstType type = 6; // add, mul, fp add, load, store, simd add,
optional uint32 inst_flags = 7; // execution mode information
// If the operation does one or more memory accesses
message MemAccess {
required uint64 addr = 1;
required uint32 size = 2;
optional uint32 mem_flags = 3;
}
repeated MemAccess mem_access = 8;
}

151
util/decode_inst_trace.py Executable file
View file

@ -0,0 +1,151 @@
#!/usr/bin/env python
# Copyright (c) 2013-2014 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: Ali Saidi
# Andreas Hansson
# This script is used to dump protobuf instruction traces to ASCII
# format. It assumes that protoc has been executed and already
# generated the Python package for the inst messages. This can
# be done manually using:
# protoc --python_out=. inst.proto
# The ASCII trace format uses one line per request.
import protolib
import sys
# Import the packet proto definitions
try:
import inst_pb2
except:
print "Did not find protobuf inst definitions, attempting to generate"
from subprocess import call
error = call(['protoc', '--python_out=util', '--proto_path=src/proto',
'src/proto/inst.proto'])
if not error:
print "Generated inst proto definitions"
try:
import google.protobuf
except:
print "Please install Python protobuf module"
exit(-1)
import inst_pb2
else:
print "Failed to import inst proto definitions"
exit(-1)
def main():
if len(sys.argv) != 3:
print "Usage: ", sys.argv[0], " <protobuf input> <ASCII output>"
exit(-1)
# Open the file in read mode
proto_in = protolib.openFileRd(sys.argv[1])
try:
ascii_out = open(sys.argv[2], 'w')
except IOError:
print "Failed to open ", sys.argv[2], " for writing"
exit(-1)
# Read the magic number in 4-byte Little Endian
magic_number = proto_in.read(4)
if magic_number != "gem5":
print "Unrecognized file", sys.argv[1]
exit(-1)
print "Parsing instruction header"
# Add the packet header
header = inst_pb2.InstHeader()
protolib.decodeMessage(proto_in, header)
print "Object id:", header.obj_id
print "Tick frequency:", header.tick_freq
print "Memory addresses included:", header.has_mem
if header.ver != 0:
print "Warning: file version newer than decoder:", header.ver
print "This decoder may not understand how to decode this file"
print "Parsing instructions"
num_insts = 0
inst = inst_pb2.Inst()
# Decode the inst messages until we hit the end of the file
optional_fields = ('tick', 'type', 'inst_flags', 'addr', 'size', 'mem_flags')
while protolib.decodeMessage(proto_in, inst):
# If we have a tick use it, otherwise count instructions
if inst.HasField('tick'):
tick = inst.tick
else:
tick = num_insts
if inst.HasField('nodeid'):
node_id = inst.nodeid
else:
node_id = 0;
if inst.HasField('cpuid'):
cpu_id = inst.cpuid
else:
cpu_id = 0;
ascii_out.write('%-20d: (%03d/%03d) %#010x @ %#016x ' % (tick, node_id, cpu_id,
inst.inst, inst.pc))
if inst.HasField('type'):
ascii_out.write(' : %10s' % inst_pb2._INST_INSTTYPE.values_by_number[inst.type].name)
for mem_acc in inst.mem_access:
ascii_out.write(" %#x-%#x;" % (mem_acc.addr, mem_acc.addr + mem_acc.size))
ascii_out.write('\n')
num_insts += 1
print "Parsed instructions:", num_insts
# We're done
ascii_out.close()
proto_in.close()
if __name__ == "__main__":
main()