cpu: Add support for protobuf input for the trace generator
This patch adds support for reading input traces encoded using protobuf according to what is done in the CommMonitor. A follow-up patch adds a Python script that can be used to convert the previously used ASCII traces to protobuf equivalents. The appropriate regression input is updated as part of this patch.
This commit is contained in:
parent
9c5ef235cc
commit
1da209140c
6 changed files with 38 additions and 62 deletions
|
@ -39,6 +39,9 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
|
# Only build the traffic generator if we have support for protobuf as the
|
||||||
|
# tracing relies on it
|
||||||
|
if env['HAVE_PROTOBUF']:
|
||||||
SimObject('TrafficGen.py')
|
SimObject('TrafficGen.py')
|
||||||
|
|
||||||
Source('traffic_gen.cc')
|
Source('traffic_gen.cc')
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "cpu/testers/traffic_gen/traffic_gen.hh"
|
#include "cpu/testers/traffic_gen/traffic_gen.hh"
|
||||||
#include "debug/Checkpoint.hh"
|
#include "debug/Checkpoint.hh"
|
||||||
#include "debug/TrafficGen.hh"
|
#include "debug/TrafficGen.hh"
|
||||||
|
#include "proto/packet.pb.h"
|
||||||
#include "sim/stats.hh"
|
#include "sim/stats.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
@ -497,65 +498,35 @@ TrafficGen::StateGraph::RandomGen::nextExecuteTick()
|
||||||
|
|
||||||
TrafficGen::StateGraph::TraceGen::InputStream::InputStream(const string&
|
TrafficGen::StateGraph::TraceGen::InputStream::InputStream(const string&
|
||||||
filename)
|
filename)
|
||||||
|
: trace(filename)
|
||||||
{
|
{
|
||||||
trace.rdbuf()->pubsetbuf(readBuffer, 4 * 1024 * 1024);
|
// Create a protobuf message for the header and read it from the stream
|
||||||
trace.open(filename.c_str(), ifstream::in);
|
Message::PacketHeader header_msg;
|
||||||
|
if (!trace.read(header_msg)) {
|
||||||
|
panic("Failed to read packet header from %s\n", filename);
|
||||||
|
|
||||||
if (!trace.is_open()) {
|
if (header_msg.tick_freq() != SimClock::Frequency) {
|
||||||
fatal("Traffic generator trace file could not be"
|
panic("Trace %s was recorded with a different tick frequency %d\n",
|
||||||
" opened: %s\n", filename);
|
header_msg.tick_freq());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TrafficGen::StateGraph::TraceGen::InputStream::reset()
|
TrafficGen::StateGraph::TraceGen::InputStream::reset()
|
||||||
{
|
{
|
||||||
// seek to the start of the input trace file
|
trace.reset();
|
||||||
trace.seekg(0, ifstream::beg);
|
|
||||||
trace.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TrafficGen::StateGraph::TraceGen::InputStream::read(TraceElement& element)
|
TrafficGen::StateGraph::TraceGen::InputStream::read(TraceElement& element)
|
||||||
{
|
{
|
||||||
string buffer;
|
Message::Packet pkt_msg;
|
||||||
bool format_error = false;
|
if (trace.read(pkt_msg)) {
|
||||||
assert(trace.good());
|
element.cmd = pkt_msg.cmd();
|
||||||
getline(trace, buffer);
|
element.addr = pkt_msg.addr();
|
||||||
|
element.blocksize = pkt_msg.size();
|
||||||
// Check that we have something to process. This assumes no EOF at
|
element.tick = pkt_msg.tick();
|
||||||
// the end of the line.
|
|
||||||
if (buffer.size() > 0 && !trace.eof()) {
|
|
||||||
std::istringstream iss(buffer);
|
|
||||||
|
|
||||||
char rOrW, ch;
|
|
||||||
iss >> rOrW;
|
|
||||||
if (rOrW == 'r') {
|
|
||||||
element.cmd = MemCmd::ReadReq;
|
|
||||||
} else if (rOrW == 'w') {
|
|
||||||
element.cmd = MemCmd::WriteReq;
|
|
||||||
} else {
|
|
||||||
format_error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eat a comma, then get the address
|
|
||||||
iss >> ch;
|
|
||||||
format_error |= ch != ',';
|
|
||||||
iss >> element.addr;
|
|
||||||
|
|
||||||
// eat a comma, then get the blocksize
|
|
||||||
iss >> ch;
|
|
||||||
format_error |= ch != ',';
|
|
||||||
iss >> element.blocksize;
|
|
||||||
|
|
||||||
// eat a comma, then get the tick
|
|
||||||
iss >> ch;
|
|
||||||
format_error |= ch != ',';
|
|
||||||
iss >> element.tick;
|
|
||||||
|
|
||||||
if (format_error)
|
|
||||||
fatal("Trace format error in %s\n", buffer);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,12 +41,11 @@
|
||||||
#ifndef __MEM_TRAFFIC_GEN_HH__
|
#ifndef __MEM_TRAFFIC_GEN_HH__
|
||||||
#define __MEM_TRAFFIC_GEN_HH__
|
#define __MEM_TRAFFIC_GEN_HH__
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "base/hashmap.hh"
|
#include "base/hashmap.hh"
|
||||||
#include "mem/mem_object.hh"
|
#include "mem/mem_object.hh"
|
||||||
#include "mem/qport.hh"
|
#include "mem/qport.hh"
|
||||||
#include "params/TrafficGen.hh"
|
#include "params/TrafficGen.hh"
|
||||||
|
#include "proto/protoio.hh"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The traffic generator is a master module that generates stimuli for
|
* The traffic generator is a master module that generates stimuli for
|
||||||
|
@ -449,15 +448,8 @@ class TrafficGen : public MemObject
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// Input file stream for the ASCII trace
|
/// Input file stream for the protobuf trace
|
||||||
std::ifstream trace;
|
ProtoInputStream trace;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a 4MB read buffer for the input trace
|
|
||||||
* file. This is to reduce the number of disk accesses
|
|
||||||
* and thereby speed up the execution.
|
|
||||||
*/
|
|
||||||
char readBuffer[4 * 1024 * 1024];
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
|
|
||||||
|
# both traffic generator and communication monitor are only available
|
||||||
|
# if we have protobuf support, so potentially skip this test
|
||||||
|
require_sim_object("TrafficGen")
|
||||||
|
require_sim_object("CommMonitor")
|
||||||
|
|
||||||
# even if this is only a traffic generator, call it cpu to make sure
|
# even if this is only a traffic generator, call it cpu to make sure
|
||||||
# the scripts are happy
|
# the scripts are happy
|
||||||
cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-dram.cfg")
|
cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-dram.cfg")
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
|
|
||||||
|
# both traffic generator and communication monitor are only available
|
||||||
|
# if we have protobuf support, so potentially skip this test
|
||||||
|
require_sim_object("TrafficGen")
|
||||||
|
require_sim_object("CommMonitor")
|
||||||
|
|
||||||
# even if this is only a traffic generator, call it cpu to make sure
|
# even if this is only a traffic generator, call it cpu to make sure
|
||||||
# the scripts are happy
|
# the scripts are happy
|
||||||
cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-mem.cfg")
|
cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-mem.cfg")
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
r,19088743,64,1000
|
gem51
|
||||||
w,48879,64,4000
|
)Converted ASCII trace tgen-simple-mem.trc€”ëÜèçŠ<C3A7> @ ïý @
|
Loading…
Reference in a new issue