Commit d51103a2 authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

tracing: checkpoint

parent 1bef652d
CXXFLAGS := -O3 -Wall -Wextra -g -Wno-unused-parameter -fpermissive
LDLIBS := -lboost_iostreams
process: process.o sym_map.o
process: CC=$(CXX)
clean:
rm *.o process
#pragma once
class Event {
public:
uint64_t ts;
Event(uint64_t ts_)
: ts(ts_)
{
}
virtual void dump(std::ostream &out) = 0;
};
class EHostCall : public Event {
public:
const std::string &fun;
EHostCall(uint64_t ts_, const std::string &fun_)
: Event(ts_), fun(fun_)
{
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.CALL " << fun << std::endl;
}
};
class EHostMsiX : public Event {
public:
uint16_t vec;
EHostMsiX(uint64_t ts_, uint16_t vec_)
: Event(ts_), vec(vec_)
{
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.MSIX " << vec << std::endl;
}
};
class EHostDmaR : public Event {
public:
uint64_t id;
uint64_t addr;
uint64_t size;
EHostDmaR(uint64_t ts_, uint64_t id_, uint64_t addr_, uint64_t size_)
: Event(ts_), id(id_), addr(addr_), size(size_)
{
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.DMAR id=" << id << " addr=" << addr << " size=" <<
size << std::endl;
}
};
class EHostDmaW : public Event {
public:
uint64_t id;
uint64_t addr;
uint64_t size;
EHostDmaW(uint64_t ts_, uint64_t id_, uint64_t addr_, uint64_t size_)
: Event(ts_), id(id_), addr(addr_), size(size_)
{
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.DMAW id=" << id << " addr=" << addr << " size=" <<
size << std::endl;
}
};
class EHostDmaC : public Event {
public:
uint64_t id;
EHostDmaC(uint64_t ts_, uint64_t id_)
: Event(ts_), id(id_) {
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.DMAC id=" << id << std::endl;
}
};
class EHostMmioR : public Event {
public:
uint64_t id;
uint64_t addr;
uint64_t size;
EHostMmioR(uint64_t ts_, uint64_t id_, uint64_t addr_, uint64_t size_)
: Event(ts_), id(id_), addr(addr_), size(size_)
{
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.MMIOR id=" << id << " addr=" << addr << " size=" <<
size << std::endl;
}
};
class EHostMmioW : public Event {
public:
uint64_t id;
uint64_t addr;
uint64_t size;
EHostMmioW(uint64_t ts_, uint64_t id_, uint64_t addr_, uint64_t size_)
: Event(ts_), id(id_), addr(addr_), size(size_)
{
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.MMIOW id=" << id << " addr=" << addr << " size=" <<
size << std::endl;
}
};
class EHostMmioC : public Event {
public:
uint64_t id;
EHostMmioC(uint64_t ts_, uint64_t id_)
: Event(ts_), id(id_) {
}
virtual void dump(std::ostream &out)
{
out << ts << ": H.MMIOC id=" << id << std::endl;
}
};
#pragma once
#include <cstddef>
#include <cstring>
class parser {
protected:
const char *buf;
size_t buf_len;
size_t pos;
public:
parser(const char *buf_, size_t buf_len_, size_t start_pos = 0)
: buf(buf_), buf_len(buf_len_), pos(start_pos)
{
}
inline size_t trim_spaces()
{
size_t cnt = 0;
for (; pos < buf_len && buf[pos] == ' '; pos++, cnt++);
return cnt;
}
inline bool consume_char(char c)
{
if (pos == buf_len || buf[pos] != c) {
return false;
}
pos++;
return true;
}
inline bool consume_hex(uint64_t &val)
{
size_t val_len = 0;
val = 0;
for (; pos < buf_len; pos++) {
char d = buf[pos];
bool is_d = d >= '0' && d <= '9';
bool is_x = d >= 'a' && d <= 'f';
if (!is_d && !is_x)
break;
val <<= 4;
if (is_d)
val |= d - '0';
else
val |= d - 'a' + 10;
val_len++;
}
return val_len > 0;
}
inline bool consume_dec(uint64_t &val)
{
size_t val_len = 0;
val = 0;
for (; pos < buf_len; pos++) {
char d = buf[pos];
if (d < '0' || d > '9')
break;
val = val * 10 + (d - '0');
val_len++;
}
return val_len > 0;
}
inline bool consume_str(const char *str)
{
size_t str_len = strlen(str);
if (pos + str_len > buf_len || memcmp(buf + pos, str, str_len)) {
return false;
}
pos += str_len;
return true;
}
inline bool extract_until(char end_c, std::string &str)
{
size_t end = pos;
for (; end < buf_len && buf[end] != end_c; end++);
if (end >= buf_len)
return false;
str.assign(buf + pos, end - pos);
pos = end + 1;
return true;
}
};
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include "events.h"
#include "parser.h"
#include "process.h"
namespace bio = boost::iostreams;
sym_map sym_map;
size_t cpu_lines = 0;
size_t eth_lines = 0;
uint64_t ts_first = 2686011870000ULL;//2655884308815ULL;
void process_msg(uint64_t ts, char *comp_name, size_t comp_name_len, char *msg,
size_t msg_len)
{
Event *e = nullptr;
parser p(msg, msg_len, 0);
/*if (ts < ts_first)
return;*/
if (comp_name_len == 18 && !memcmp(comp_name, "system.switch_cpus", 18)) {
cpu_lines++;
if (!p.consume_str("T0 : 0x"))
return;
uint64_t addr;
if (!p.consume_hex(addr) || p.consume_char('.'))
return;
if (const std::string *s = sym_map.lookup(addr)) {
e = new EHostCall(ts, *s);
}
} else if (comp_name_len == 18 && !memcmp(comp_name, "system.pc.ethernet", 18)) {
eth_lines++;
/*std::cout.write(msg, msg_len);
std::cout << std::endl;*/
if (!p.consume_str("cosim: "))
return;
uint64_t id = 0;
uint64_t addr = 0;
uint64_t size = 0;
if (p.consume_str("received ")) {
if (p.consume_str("MSI-X intr vec ") && p.consume_dec(id)) {
e = new EHostMsiX(ts, id);
} else if (p.consume_str("DMA read id ") && p.consume_dec(id) &&
p.consume_str(" addr ") && p.consume_hex(addr) &&
p.consume_str(" size ") && p.consume_dec(size))
{
// cosim: received DMA read id 94113551511792 addr 23697ad60 size 20
e = new EHostDmaR(ts, id, addr, size);
} else if (p.consume_str("DMA write id ") && p.consume_dec(id) &&
p.consume_str(" addr ") && p.consume_hex(addr) &&
p.consume_str(" size ") && p.consume_dec(size))
{
// cosim: received DMA write id 94113551528032 addr 236972000 size 4
e = new EHostDmaW(ts, id, addr, size);
} else if (p.consume_str("read completion id ") &&
p.consume_dec(id))
{
// cosim: received read completion id 94583743418112
e = new EHostMmioC(ts, id);
} else if (p.consume_str("write completion id ") &&
p.consume_dec(id))
{
// cosim: received write completion id 94583743418736
e = new EHostMmioC(ts, id);
}
} else if (p.consume_str("sending ")) {
if (p.consume_str("read addr ") && p.consume_hex(addr) &&
p.consume_str(" size ") && p.consume_dec(size) &&
p.consume_str(" id ") && p.consume_dec(id))
{
// cosim: sending read addr c012a500 size 4 id 94583743418112
e = new EHostMmioR(ts, id, addr, size);
} else if (p.consume_str("write addr ") && p.consume_hex(addr) &&
p.consume_str(" size ") && p.consume_dec(size) &&
p.consume_str(" id ") && p.consume_dec(id))
{
// cosim: sending write addr c0108000 size 4 id 94584005188256
e = new EHostMmioW(ts, id, addr, size);
}
} else if (p.consume_str("completed DMA id ") && p.consume_dec(id)) {
e = new EHostDmaC(ts, id);
}
}
if (e) {
e->dump(std::cout);
} /*else {
std::cout.write(msg, msg_len);
std::cout << std::endl;
}*/
}
size_t process_line(char *buf, size_t pos, size_t buf_len)
{
size_t line_start = pos;
size_t comp_name_start = 0;
size_t comp_name_len = 0;
bool valid = true;
// eat spaces
for (; pos < buf_len && buf[pos] == ' '; pos++);
// parse ts
uint64_t ts = 0;
size_t ts_len = 0;
for (; pos < buf_len && buf[pos] >= '0' && buf[pos] <= '9'; pos++) {
ts = ts * 10 + buf[pos] - '0';
ts_len++;
}
if (ts_len == 0) {
valid = false;
goto out;
}
// skip colon
if (buf[pos] != ':') {
valid = false;
goto out;
}
pos++;
// skip space
if (buf[pos] != ' ') {
valid = false;
goto out;
}
pos++;
comp_name_start = pos;
for (; pos < buf_len && buf[pos] != ' ' && buf[pos] != '\n'; pos++, comp_name_len++);
// skip space
if (buf[pos] != ' ') {
valid = false;
goto out;
}
if (buf[pos - 1] != ':') {
valid = false;
goto out;
}
comp_name_len--;
pos++;
out:
// eat line
size_t msg_start = pos;
size_t msg_len = 0;
for (; pos < buf_len && buf[pos] != '\n'; pos++, msg_len++);
if (pos >= buf_len) {
// line is incomplete
return 0;
}
buf[pos] = 0;
if (valid) {
process_msg(ts, buf + comp_name_start, comp_name_len, buf + msg_start,
msg_len);
} else {
std::cout << buf + line_start << std::endl;
std::cout << pos << std::endl;
}
return pos + 1;
}
void gem5_parse(const std::string &path)
{
bool use_gz = false;
std::istream *inf = nullptr;
if (use_gz) {
std::ifstream *file = new std::ifstream(path, std::ios_base::in |
std::ios_base::binary);
bio::filtering_streambuf<bio::input> *in = new
bio::filtering_streambuf<bio::input>();
in->push(bio::gzip_decompressor());
in->push(*file);
inf = new std::istream(in);
} else {
inf = new std::ifstream(path, std::ios_base::in);
}
const size_t buf_size = 16 * 1024 * 1024;
char *buf = new char[buf_size];
size_t len, off = 0, pos = 0;
do {
inf->read(buf + pos, buf_size - pos);
len = pos + inf->gcount();
off += len;
pos = 0;
size_t newpos;
while (pos != len && (newpos = process_line(buf, pos, len)) != 0) {
pos = newpos;
}
if (pos == len) {
pos = 0;
} else {
memmove(buf, buf + pos, len - pos);
pos = len - pos;
}
} while (len > 0);
delete[] buf;
}
int main(int argc, char *argv[])
{
sym_map.add_filter("entry_SYSCALL_64");
sym_map.add_filter("__do_sys_gettimeofday");
sym_map.add_filter("__sys_sendto");
sym_map.add_filter("i40e_lan_xmit_frame");
sym_map.add_filter("syscall_return_via_sysret");
sym_map.add_filter("__sys_recvfrom");
sym_map.add_filter("deactivate_task");
sym_map.add_filter("interrupt_entry");
sym_map.add_filter("i40e_msix_clean_rings");
sym_map.add_filter("napi_schedule_prep");
sym_map.add_filter("__do_softirq");
sym_map.add_filter("trace_napi_poll");
sym_map.add_filter("net_rx_action");
sym_map.add_filter("i40e_napi_poll");
sym_map.add_filter("activate_task");
sym_map.add_filter("copyout");
sym_map.load_file("linux.dump", 0);
sym_map.load_file("i40e.dump", 0xffffffffa0000000ULL);
std::cerr << "map loaded" << std::endl;
gem5_parse(argv[1]);
}
#pragma once
#include <map>
#include <set>
#include <string>
class sym_map {
protected:
bool filter_en;
bool insmap_en;
std::set<std::string> filter;
public:
std::map<uint64_t, std::string> map;
std::map<uint64_t, std::string> map_ins;
void add_filter(const std::string &sym);
void load_file(const char *path, uint64_t offset = 0);
inline const std::string *lookup(uint64_t addr)
{
auto it = map.find(addr);
if (it == map.end())
return nullptr;
return &it->second;
}
};
#include <fstream>
#include "parser.h"
#include "process.h"
void sym_map::add_filter(const std::string &sym)
{
filter_en = true;
filter.insert(sym);
}
void sym_map::load_file(const char *path, uint64_t offset)
{
std::ifstream file(path, std::ios_base::in | std::ios_base::binary);
std::string line;
std::string label = "";
while (std::getline(file, line)) {
parser p(line.c_str(), line.size());
uint64_t addr;
p.trim_spaces();
p.consume_hex(addr);
if (p.consume_char(':')) {
if (insmap_en && !label.empty()) {
map_ins[addr + offset] = label;
}
} else if (p.consume_str(" <")) {
p.extract_until('>', label);
if (!filter_en || filter.find(label) != filter.end())
map[addr + offset] = label;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment