From f6e9ffaa8fbe5a194f8d036652b820208e6e1925 Mon Sep 17 00:00:00 2001 From: Lux Date: Sun, 22 Sep 2024 16:29:24 -0700 Subject: [PATCH 01/19] ADD: working n-trace encoder --- riscv/execute.cc | 9 ++ riscv/processor.cc | 1 + riscv/processor.h | 5 ++ riscv/riscv.mk.in | 4 + riscv/trace_encoder_n.cc | 179 +++++++++++++++++++++++++++++++++++++++ riscv/trace_encoder_n.h | 98 +++++++++++++++++++++ riscv/trace_ingress.cc | 29 +++++++ riscv/trace_ingress.h | 82 ++++++++++++++++++ 8 files changed, 407 insertions(+) create mode 100644 riscv/trace_encoder_n.cc create mode 100644 riscv/trace_encoder_n.h create mode 100644 riscv/trace_ingress.cc create mode 100644 riscv/trace_ingress.h diff --git a/riscv/execute.cc b/riscv/execute.cc index f4c88cafa9..0083b1caf5 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -2,6 +2,8 @@ #include "config.h" #include "processor.h" +#include "trace_ingress.h" +#include "trace_encoder_n.h" #include "mmu.h" #include "disasm.h" #include "decode_macros.h" @@ -173,6 +175,13 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f try { npc = fetch.func(p, fetch.insn, pc); + + if (p->get_log_commits_enabled()) { + hart_to_encoder_ingress_t packet; + hart_to_encoder_ingress_init(p, &packet, &fetch.insn, npc); + p->get_trace_encoder()->trace_encoder_push_commit(&packet); + } + if (npc != PC_SERIALIZE_BEFORE) { if (p->get_log_commits_enabled()) { commit_log_print_insn(p, pc, fetch.insn); diff --git a/riscv/processor.cc b/riscv/processor.cc index 0b318f5e12..ddeb80f691 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -63,6 +63,7 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, register_base_instructions(); mmu = new mmu_t(sim, cfg->endianness, this); + trace_encoder = new trace_encoder_n(); disassembler = new disassembler_t(&isa); for (auto e : isa.get_extensions()) diff --git a/riscv/processor.h b/riscv/processor.h index 7744e861ab..d78a25a40a 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -17,6 +17,7 @@ #include "triggers.h" #include "../fesvr/memif.h" #include "vector_unit.h" +#include "trace_encoder_n.h" #define FIRST_HPMCOUNTER 3 #define N_HPMCOUNTERS 29 @@ -28,6 +29,7 @@ class simif_t; class trap_t; class extension_t; class disassembler_t; +class trace_encoder_n; reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc); @@ -367,6 +369,8 @@ class processor_t : public abstract_device_t void check_if_lpad_required(); + trace_encoder_n* get_trace_encoder() { return trace_encoder; } + private: const isa_parser_t isa; const cfg_t * const cfg; @@ -381,6 +385,7 @@ class processor_t : public abstract_device_t bool histogram_enabled; bool log_commits_enabled; FILE *log_file; + trace_encoder_n *trace_encoder; std::ostream sout_; // needed for socket command interface -s, also used for -d and -l, but not for --log bool halt_on_reset; bool in_wfi; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index bc512bfa41..ca69b093eb 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -41,6 +41,8 @@ riscv_install_hdrs = \ rocc.h \ sim.h \ simif.h \ + trace_encoder_n.h \ + trace_ingress.h \ trap.h \ triggers.h \ vector_unit.h \ @@ -49,6 +51,8 @@ riscv_precompiled_hdrs = \ insn_template.h \ riscv_srcs = \ + trace_encoder_n.cc \ + trace_ingress.cc \ processor.cc \ execute.cc \ dts.cc \ diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc new file mode 100644 index 0000000000..459fa39aa3 --- /dev/null +++ b/riscv/trace_encoder_n.cc @@ -0,0 +1,179 @@ +#include "trace_encoder_n.h" + +trace_encoder_n::trace_encoder_n() { + this->trace_sink= fopen("trace_n.bin", "wb"); + this->active = true; + this->enabled = false; + this->src = 0; + this->state = TRACE_ENCODER_N_IDLE; +} + +void trace_encoder_n::set_enable(bool enabled) { + bool was_enabled = this->enabled; + printf("[trace_encoder_n] setting enable to %d\n", enabled); + this->enabled = enabled; + if (!was_enabled && enabled) { + this->state = TRACE_ENCODER_N_IDLE; + } +} + +void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packet) { + printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet->i_addr); + this->packet = packet; + if (this->enabled) { + if (this->state == TRACE_ENCODER_N_IDLE) { + trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); + this->state = TRACE_ENCODER_N_DATA; + } else if (this->state == TRACE_ENCODER_N_DATA) { + this->icnt += this->packet->ilastsize; + if (this->packet->i_type == I_BRANCH_TAKEN) { + trace_encoder_generate_packet(TCODE_DBR); + this->icnt = 0; + } else if (this->packet->i_type == I_JUMP_INFERABLE || this->packet->i_type == I_JUMP_UNINFERABLE) { + trace_encoder_generate_packet(TCODE_IBR); + this->icnt = 0; + } + this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; + } else if (this->state == TRACE_ENCODER_N_FULL) { + trace_encoder_generate_packet(TCODE_FULL); + this->state = TRACE_ENCODER_N_DATA; + this->icnt = 0; + } + } +} + +void trace_encoder_n::trace_encoder_generate_packet(tcode_t tcode) { + trace_encoder_n_packet_t packet; + int num_bytes; + switch (tcode) { + case TCODE_PROG_TRACE_SYNC: + _set_program_trace_sync_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + break; + case TCODE_DBR: + _set_direct_branch_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + break; + case TCODE_IBR: + _set_indirect_branch_packet(&packet); + break; + default: + break; + } +} + +void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* packet){ + packet->tcode = TCODE_PROG_TRACE_SYNC; + packet->src = this->src; + packet->sync = SYNC_TRACE_EN; + packet->icnt = 0; + packet->f_addr = this->packet->i_addr >> 1; +} + +void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ + packet->tcode = TCODE_DBR; + packet->src = this->src; + packet->icnt = this->icnt; +} + +void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ + packet->tcode = TCODE_IBR; + packet->src = this->src; + packet->b_type = B_INDIRECT; + packet->icnt = this->icnt; + uint64_t e_addr = this->packet->i_addr >> 1; + packet->u_addr = e_addr ^ this->prev_addr; + this->prev_addr = e_addr; +} + +// returns the number of bytes written to the buffer +int trace_encoder_n::packet_to_buffer(trace_encoder_n_packet_t* packet){ + switch (packet->tcode) { + case TCODE_PROG_TRACE_SYNC: + return _packet_to_buffer_program_trace_sync(packet); + case TCODE_DBR: + return _packet_to_buffer_direct_branch_packet(packet); + case TCODE_IBR: + return _packet_to_buffer_indirect_branch_packet(packet); + default: + break; + } +} + +int trace_encoder_n::_packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet) { + int msb = find_msb(packet->f_addr); + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] = packet->sync << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] |= (packet->f_addr & 0b11) << 6; + int num_bytes = 0; + if (msb < 2) { + this->buffer[1] |= MSEO_LAST; + } else { + packet->f_addr >>= 2; + msb -= 2; + num_bytes = ceil_div(msb, 6); + for (int iter = 0; iter < num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->f_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->f_addr >>= 6; + } + this->buffer[2 + num_bytes - 1] |= MSEO_LAST; + } + return 2 + num_bytes; +} + +int trace_encoder_n::_packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet) { + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + int msb = find_msb(packet->icnt); + int num_bytes = ceil_div(msb, 6); + for (int iter = 0; iter < num_bytes; iter++) { + this->buffer[1 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; + } + this->buffer[1 + num_bytes - 1] |= MSEO_LAST; + return 1 + num_bytes; +} + +int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet) { + printf("[trace_encoder_n] _packet_to_buffer_indirect_branch_packet: packet->icnt: %lx\n", packet->icnt); + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] = packet->b_type << MDO_OFFSET | MSEO_IDLE; + // icnt + int icnt_msb = find_msb(packet->icnt); + int icnt_num_bytes = ceil_div(icnt_msb, 6); + this->buffer[1] |= (packet->u_addr & 0xF) << 4; + if (icnt_msb < 4) { + this->buffer[1] |= MSEO_EOF; + } else { + packet->icnt >>= 4; + icnt_msb -= 4; + icnt_num_bytes = ceil_div(icnt_msb, 6); + for (int iter = 0; iter < icnt_num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; + } + this->buffer[2 + icnt_num_bytes - 1] |= MSEO_EOF; + } + // u_addr + int u_addr_start = 2 + icnt_num_bytes; + int u_addr_msb = find_msb(packet->u_addr); + int u_addr_num_bytes = ceil_div(u_addr_msb, 6); + for (int iter = 0; iter < u_addr_num_bytes; iter++) { + this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->u_addr >>= 6; + } + this->buffer[u_addr_start + u_addr_num_bytes - 1] |= MSEO_LAST; + return u_addr_start + u_addr_num_bytes; +} + +// returns the 0-index of the most significant bit +int find_msb(uint64_t x) { + if (x == 0) return -1; + return 63 - __builtin_clzll(x); +} + +// returns the ceiling of the division of a 0-indexed a by b +int ceil_div(int a, int b) { + return a / b + 1; +} \ No newline at end of file diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h new file mode 100644 index 0000000000..dd0f69eb78 --- /dev/null +++ b/riscv/trace_encoder_n.h @@ -0,0 +1,98 @@ +#ifndef _RISCV_TRACE_ENCODER_N_H +#define _RISCV_TRACE_ENCODER_N_H + +#include "trace_ingress.h" +#include + +class hart_to_encoder_ingress_t; + +enum tcode_t { + TCODE_OWN = 2, // ownership + TCODE_DBR = 3, // direct branch + TCODE_IBR = 4, // indirect branch + TCODE_ERR = 8, // error + TCODE_PROG_TRACE_SYNC = 9, // program trace sync + TCODE_DBR_SYNC = 10, // direct branch sync + TCODE_IBR_SYNC = 11, // indirect branch sync + TCODE_FULL = 27, // resource full + TCODE_IBR_HIST = 28, // indirect branch history + TCODE_IBR_HIST_SYNC = 29, // indirect branch history sync + TCODE_RBR = 30, // repeated branches + TCODE_PROG_TRACE_CORR = 33 // program trace correlation +}; + +enum b_type_t { + B_INDIRECT = 0, // indirect branch + B_TRAP = 1, // trap + B_EXCEPTION = 2, // exception + B_INTERRUPT = 3 // interrupt +}; + +enum sync_t { + SYNC_TRACE_EN = 5, +}; + +struct trace_encoder_n_packet_t { + uint8_t size; // 8 bits + tcode_t tcode; // 6 bits + uint16_t src; // unused for now + uint8_t sync; // 4 bit + uint8_t b_type; // 2 bits + uint16_t icnt; // 16 bits + uint64_t f_addr; // 64 bits + uint64_t u_addr; // 64 bits + uint64_t tstamp; // unused for now +}; + +int find_msb(uint64_t x); +int ceil_div(int a, int b); + +enum trace_encoder_n_state_t { + TRACE_ENCODER_N_IDLE, + TRACE_ENCODER_N_DATA, + TRACE_ENCODER_N_FULL +}; + +#define MAX_TRACE_BUFFER_SIZE 38 + +#define MDO_OFFSET 2 + +#define MSEO_IDLE 0b00 +#define MSEO_EOF 0b01 +#define MSEO_RES 0b10 // reserved +#define MSEO_LAST 0b11 + +#define MAX_ICNT_BITS 15 +#define MAX_ICNT 1 << MAX_ICNT_BITS + +class trace_encoder_n { +public: + trace_encoder_n(); + void trace_encoder_push_commit(hart_to_encoder_ingress_t* packet); + void trace_encoder_generate_packet(tcode_t tcode); + + void set_enable(bool enabled); +private: + FILE* trace_sink; + + hart_to_encoder_ingress_t* packet; + bool active; + bool enabled; + uint16_t src; + trace_encoder_n_state_t state; + uint8_t buffer[MAX_TRACE_BUFFER_SIZE]; + uint16_t icnt; + uint64_t prev_addr; + + void _set_direct_branch_packet(trace_encoder_n_packet_t* packet); + void _set_indirect_branch_packet(trace_encoder_n_packet_t* packet); + void _set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); + + int packet_to_buffer(trace_encoder_n_packet_t* packet); + int _packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); + int _packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); + int _packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); +}; + + +#endif \ No newline at end of file diff --git a/riscv/trace_ingress.cc b/riscv/trace_ingress.cc new file mode 100644 index 0000000000..a3827ae990 --- /dev/null +++ b/riscv/trace_ingress.cc @@ -0,0 +1,29 @@ +#include "trace_ingress.h" + +insn_type _get_insn_type(insn_t* insn, bool taken) { + if (_is_branch(insn)) { + return taken ? I_BRANCH_TAKEN : I_BRANCH_NON_TAKEN; + } + else if (_is_jal(insn)) { + return I_JUMP_INFERABLE; + } + else if (_is_jalr(insn)) { + return I_JUMP_UNINFERABLE; + } + // TODO: further categorization is not implemented for now + else { + return I_NONE; + } +} + +void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* packet, insn_t* insn, reg_t npc) { + // print insn + bool taken = npc != p->get_state()->pc + insn_length(insn->bits()); + packet->i_type = _get_insn_type(insn, taken); + packet->exc_cause = 0; + packet->tval = 0; + packet->priv = P_M; // TODO: check for processor privilege level + packet->i_addr = p->get_state()->pc; + packet->iretire = 1; + packet->ilastsize = insn_length(insn->bits())/2; +} \ No newline at end of file diff --git a/riscv/trace_ingress.h b/riscv/trace_ingress.h new file mode 100644 index 0000000000..6648413e0b --- /dev/null +++ b/riscv/trace_ingress.h @@ -0,0 +1,82 @@ +#ifndef _RISCV_TRACE_INGRESS_H +#define _RISCV_TRACE_INGRESS_H + +#include "processor.h" +#include "encoding.h" + +enum trace_encoder_type { + N_TRACE_ENCODER, + E_TRACE_ENCODER +}; + +// Enumerates all possible instruction types +enum insn_type { + I_NONE = 0, + I_EXCEPTION = 1, + I_INTERRUPT = 2, + I_TRAP_RETURN = 3, + I_BRANCH_NON_TAKEN = 4, + I_BRANCH_TAKEN = 5, + // I_BRANCH_UNINFERABLE = 6, + I_RESERVED = 7, + I_CALL_UNINFERABLE = 8, + I_CALL_INFERABLE = 9, + I_JUMP_UNINFERABLE = 10, + I_JUMP_INFERABLE = 11, + I_COROUTINE_SWAP = 12, + I_RETURN = 13, + I_OTHER_UNINFERABLE = 14, + I_OTHER_INFERABLE = 15, +}; + +// Enumerates all possible privilege level encodings +enum priv_enc { + P_U = 0, + P_S = 1, + // 2 is reserved + P_M = 3, + // 4-7 is optional and unused for now + P_D = 4, + P_VU = 5, + P_VS = 6, + // 7 is reserved +}; + +// Core to encoder communication struct +// Assume a spike hart with max 1 instruction retired per cycle +// Regardless of RV64 or RV32, we fix the size of the instruction address to 64 bits +struct hart_to_encoder_ingress_t { + // instruction type + insn_type i_type; // 4 bits + // exception cause, mcause + uint8_t exc_cause; // 4 bits (only the lower 4 bits are used) + // trap value, mtval + uint64_t tval; // 64 bits + // core privilege level + priv_enc priv; // 3 bits + // retired instruction address + uint64_t i_addr; // 64 bits + //context, time, ctype, sijump are now unimplemented + // number of instructions retired - 0 or 1 for spike harts + bool iretire; // 1 bit + // ilastsize + int ilastsize; // 2 or 4, 2 bits +}; + +void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* packet, insn_t* insn, reg_t npc); + +#define CHECK_INSN(name) ((insn->bits() & MASK_##name) == MATCH_##name) + +static inline bool _is_branch(insn_t* insn) { + return CHECK_INSN(BEQ) || CHECK_INSN(BNE) || CHECK_INSN(BLT) || CHECK_INSN(BGE) || CHECK_INSN(BLTU) || CHECK_INSN(BGEU); +} + +static inline bool _is_jal(insn_t* insn) { + return CHECK_INSN(JAL); +} + +static inline bool _is_jalr(insn_t* insn) { + return CHECK_INSN(JALR); +} + +#endif // _RISCV_TRACE_INGRESS_H \ No newline at end of file From ffb81a9d6a6e534909dea79b725e85311f4f8de1 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 25 Sep 2024 17:41:38 -0700 Subject: [PATCH 02/19] ADD: formatting and debug utilities --- riscv/trace_encoder_n.cc | 14 ++++++++++++++ riscv/trace_encoder_n.h | 27 +++++++++++++++------------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 459fa39aa3..0343b041a5 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -42,14 +42,28 @@ void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packe } } +void print_packet(trace_encoder_n_packet_t* packet) { + printf("[trace_encoder_n] printing packet: tcode: %lx, src: %lx, icnt: %lx, f_addr: %lx, u_addr: %lx, b_type: %lx\n", packet->tcode, packet->src, packet->icnt, packet->f_addr, packet->u_addr, packet->b_type); +} + +void print_encoded_packet(uint8_t* buffer, int num_bytes) { + printf("[trace_encoder_n] encoded packet: "); + for (int i = 0; i < num_bytes; i++) { + printf("%lx ", buffer[i]); + } + printf("\n"); +} + void trace_encoder_n::trace_encoder_generate_packet(tcode_t tcode) { trace_encoder_n_packet_t packet; int num_bytes; switch (tcode) { case TCODE_PROG_TRACE_SYNC: _set_program_trace_sync_packet(&packet); + print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); break; case TCODE_DBR: _set_direct_branch_packet(&packet); diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index dd0f69eb78..2e05659352 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -22,10 +22,10 @@ enum tcode_t { }; enum b_type_t { - B_INDIRECT = 0, // indirect branch - B_TRAP = 1, // trap + B_INDIRECT = 0, // indirect branch + B_TRAP = 1, // trap B_EXCEPTION = 2, // exception - B_INTERRUPT = 3 // interrupt + B_INTERRUPT = 3 // interrupt }; enum sync_t { @@ -33,17 +33,20 @@ enum sync_t { }; struct trace_encoder_n_packet_t { - uint8_t size; // 8 bits - tcode_t tcode; // 6 bits - uint16_t src; // unused for now - uint8_t sync; // 4 bit - uint8_t b_type; // 2 bits - uint16_t icnt; // 16 bits - uint64_t f_addr; // 64 bits - uint64_t u_addr; // 64 bits - uint64_t tstamp; // unused for now + uint8_t size; // 8 bits + tcode_t tcode; // 6 bits + uint16_t src; // unused for now + uint8_t sync; // 4 bit + uint8_t b_type; // 2 bits + uint16_t icnt; // 16 bits + uint64_t f_addr; // 64 bits + uint64_t u_addr; // 64 bits + uint64_t tstamp; // unused for now }; +void print_packet(trace_encoder_n_packet_t* packet); +void print_encoded_packet(uint8_t* buffer, int num_bytes); + int find_msb(uint64_t x); int ceil_div(int a, int b); From 0ed1088060a08ca32bc1051f542ab02ea3e8e4ee Mon Sep 17 00:00:00 2001 From: Lux Date: Mon, 30 Sep 2024 11:01:35 -0700 Subject: [PATCH 03/19] FIX: correct icnt --- riscv/trace_encoder_n.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 0343b041a5..e0b5f5896a 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -6,6 +6,7 @@ trace_encoder_n::trace_encoder_n() { this->enabled = false; this->src = 0; this->state = TRACE_ENCODER_N_IDLE; + this->icnt = 0; } void trace_encoder_n::set_enable(bool enabled) { @@ -24,6 +25,7 @@ void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packe if (this->state == TRACE_ENCODER_N_IDLE) { trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); this->state = TRACE_ENCODER_N_DATA; + this->icnt += this->packet->ilastsize; } else if (this->state == TRACE_ENCODER_N_DATA) { this->icnt += this->packet->ilastsize; if (this->packet->i_type == I_BRANCH_TAKEN) { @@ -67,11 +69,17 @@ void trace_encoder_n::trace_encoder_generate_packet(tcode_t tcode) { break; case TCODE_DBR: _set_direct_branch_packet(&packet); + print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); break; case TCODE_IBR: _set_indirect_branch_packet(&packet); + print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); break; default: break; From b49d258e82f8ebb06e5f8fd0e92a4eeba0ae630a Mon Sep 17 00:00:00 2001 From: Lux Date: Mon, 30 Sep 2024 16:38:16 -0700 Subject: [PATCH 04/19] FIX: memory leak and incorrect encoding for indirect branches --- riscv/execute.cc | 6 +++--- riscv/trace_encoder_n.cc | 33 +++++++++++++++++++++------------ riscv/trace_encoder_n.h | 6 +++++- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index 0083b1caf5..b19e83217e 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -177,9 +177,9 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f npc = fetch.func(p, fetch.insn, pc); if (p->get_log_commits_enabled()) { - hart_to_encoder_ingress_t packet; - hart_to_encoder_ingress_init(p, &packet, &fetch.insn, npc); - p->get_trace_encoder()->trace_encoder_push_commit(&packet); + hart_to_encoder_ingress_t* packet = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); + hart_to_encoder_ingress_init(p, packet, &fetch.insn, npc); + p->get_trace_encoder()->trace_encoder_push_commit(packet); } if (npc != PC_SERIALIZE_BEFORE) { diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index e0b5f5896a..cce4803b54 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -7,6 +7,9 @@ trace_encoder_n::trace_encoder_n() { this->src = 0; this->state = TRACE_ENCODER_N_IDLE; this->icnt = 0; + this->updesc = false; + this->packet_0 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet + this->packet_1 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet } void trace_encoder_n::set_enable(bool enabled) { @@ -20,20 +23,25 @@ void trace_encoder_n::set_enable(bool enabled) { void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packet) { printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet->i_addr); - this->packet = packet; + free(this->packet_1); + this->packet_1 = this->packet_0; + this->packet_0 = packet; if (this->enabled) { if (this->state == TRACE_ENCODER_N_IDLE) { trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); this->state = TRACE_ENCODER_N_DATA; - this->icnt += this->packet->ilastsize; + this->icnt += this->packet_0->ilastsize; } else if (this->state == TRACE_ENCODER_N_DATA) { - this->icnt += this->packet->ilastsize; - if (this->packet->i_type == I_BRANCH_TAKEN) { + this->icnt += this->packet_0->ilastsize; + if (this->packet_0->i_type == I_BRANCH_TAKEN) { trace_encoder_generate_packet(TCODE_DBR); this->icnt = 0; - } else if (this->packet->i_type == I_JUMP_INFERABLE || this->packet->i_type == I_JUMP_UNINFERABLE) { + } else if (this->packet_0->i_type == I_JUMP_INFERABLE || this->packet_0->i_type == I_JUMP_UNINFERABLE) { + this->updesc = true; + } else if (this->updesc) { trace_encoder_generate_packet(TCODE_IBR); - this->icnt = 0; + this->icnt = this->packet_0->ilastsize; + this->updesc = false; } this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; } else if (this->state == TRACE_ENCODER_N_FULL) { @@ -91,7 +99,8 @@ void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* p packet->src = this->src; packet->sync = SYNC_TRACE_EN; packet->icnt = 0; - packet->f_addr = this->packet->i_addr >> 1; + packet->f_addr = this->packet_0->i_addr >> 1; + this->prev_addr = packet->f_addr; } void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ @@ -104,8 +113,8 @@ void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* pack packet->tcode = TCODE_IBR; packet->src = this->src; packet->b_type = B_INDIRECT; - packet->icnt = this->icnt; - uint64_t e_addr = this->packet->i_addr >> 1; + packet->icnt = this->icnt - this->packet_0->ilastsize; // + uint64_t e_addr = this->packet_0->i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; this->prev_addr = e_addr; } @@ -158,13 +167,12 @@ int trace_encoder_n::_packet_to_buffer_direct_branch_packet(trace_encoder_n_pack } int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet) { - printf("[trace_encoder_n] _packet_to_buffer_indirect_branch_packet: packet->icnt: %lx\n", packet->icnt); this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; this->buffer[1] = packet->b_type << MDO_OFFSET | MSEO_IDLE; // icnt int icnt_msb = find_msb(packet->icnt); - int icnt_num_bytes = ceil_div(icnt_msb, 6); - this->buffer[1] |= (packet->u_addr & 0xF) << 4; + int icnt_num_bytes = 0; + this->buffer[1] |= (packet->icnt & 0xF) << 4; if (icnt_msb < 4) { this->buffer[1] |= MSEO_EOF; } else { @@ -181,6 +189,7 @@ int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_pa int u_addr_start = 2 + icnt_num_bytes; int u_addr_msb = find_msb(packet->u_addr); int u_addr_num_bytes = ceil_div(u_addr_msb, 6); + printf("[trace_encoder_n] _packet_to_buffer_indirect_branch_packet: u_addr_start: %d, u_addr_msb: %d, u_addr_num_bytes: %d\n", u_addr_start, u_addr_msb, u_addr_num_bytes); for (int iter = 0; iter < u_addr_num_bytes; iter++) { this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; packet->u_addr >>= 6; diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 2e05659352..2c382e64e1 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -78,7 +78,11 @@ class trace_encoder_n { private: FILE* trace_sink; - hart_to_encoder_ingress_t* packet; + bool updesc; + + hart_to_encoder_ingress_t* packet_0; // the newer packet + hart_to_encoder_ingress_t* packet_1; // the older packet + bool active; bool enabled; uint16_t src; From 810d618eed7a077f4a66b9a7e62cc1264ac50bce Mon Sep 17 00:00:00 2001 From: Lux Date: Tue, 1 Oct 2024 17:21:48 -0700 Subject: [PATCH 05/19] FORMAT: indentation fix --- riscv/trace_encoder_n.cc | 325 ++++++++++++++++++++------------------- riscv/trace_encoder_n.h | 102 ++++++------ riscv/trace_ingress.cc | 45 +++--- riscv/trace_ingress.h | 90 +++++------ 4 files changed, 283 insertions(+), 279 deletions(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index cce4803b54..86cc60e89c 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -1,210 +1,213 @@ #include "trace_encoder_n.h" trace_encoder_n::trace_encoder_n() { - this->trace_sink= fopen("trace_n.bin", "wb"); - this->active = true; - this->enabled = false; - this->src = 0; - this->state = TRACE_ENCODER_N_IDLE; - this->icnt = 0; - this->updesc = false; - this->packet_0 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet - this->packet_1 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet + this->trace_sink= fopen("trace_n.bin", "wb"); + this->active = true; + this->enabled = false; + this->src = 0; + this->state = TRACE_ENCODER_N_IDLE; + this->icnt = 0; + this->updesc = false; + this->packet_0 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet + this->packet_1 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet } void trace_encoder_n::set_enable(bool enabled) { - bool was_enabled = this->enabled; - printf("[trace_encoder_n] setting enable to %d\n", enabled); - this->enabled = enabled; - if (!was_enabled && enabled) { - this->state = TRACE_ENCODER_N_IDLE; - } + bool was_enabled = this->enabled; + printf("[trace_encoder_n] setting enable to %d\n", enabled); + this->enabled = enabled; + if (!was_enabled && enabled) { + this->state = TRACE_ENCODER_N_IDLE; + } } void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packet) { - printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet->i_addr); - free(this->packet_1); - this->packet_1 = this->packet_0; - this->packet_0 = packet; - if (this->enabled) { - if (this->state == TRACE_ENCODER_N_IDLE) { - trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); - this->state = TRACE_ENCODER_N_DATA; - this->icnt += this->packet_0->ilastsize; - } else if (this->state == TRACE_ENCODER_N_DATA) { - this->icnt += this->packet_0->ilastsize; - if (this->packet_0->i_type == I_BRANCH_TAKEN) { - trace_encoder_generate_packet(TCODE_DBR); - this->icnt = 0; - } else if (this->packet_0->i_type == I_JUMP_INFERABLE || this->packet_0->i_type == I_JUMP_UNINFERABLE) { - this->updesc = true; - } else if (this->updesc) { - trace_encoder_generate_packet(TCODE_IBR); - this->icnt = this->packet_0->ilastsize; - this->updesc = false; - } - this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; - } else if (this->state == TRACE_ENCODER_N_FULL) { - trace_encoder_generate_packet(TCODE_FULL); - this->state = TRACE_ENCODER_N_DATA; - this->icnt = 0; - } - } + printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet->i_addr); + free(this->packet_1); + this->packet_1 = this->packet_0; + this->packet_0 = packet; + printf("[trace_encoder_n] new packet tcode: %lx\n", this->packet_0->i_type); + if (this->enabled) { + if (this->state == TRACE_ENCODER_N_IDLE) { + trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); + this->state = TRACE_ENCODER_N_DATA; + this->icnt += this->packet_0->ilastsize; + } else if (this->state == TRACE_ENCODER_N_DATA) { + this->icnt += this->packet_0->ilastsize; + printf("[trace_encoder_n] icnt: %lx\n", this->icnt); + if (this->packet_0->i_type == I_BRANCH_TAKEN) { + trace_encoder_generate_packet(TCODE_DBR); + this->icnt = 0; + } else if (this->packet_0->i_type == I_JUMP_INFERABLE || this->packet_0->i_type == I_JUMP_UNINFERABLE) { + this->updesc = true; + } else if (this->updesc) { + trace_encoder_generate_packet(TCODE_IBR); + this->icnt = this->packet_0->ilastsize; + printf("[trace_encoder_n] icnt: %lx\n", this->icnt); + this->updesc = false; + } + this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; + } else if (this->state == TRACE_ENCODER_N_FULL) { + trace_encoder_generate_packet(TCODE_FULL); + this->state = TRACE_ENCODER_N_DATA; + this->icnt = 0; + } + } } void print_packet(trace_encoder_n_packet_t* packet) { - printf("[trace_encoder_n] printing packet: tcode: %lx, src: %lx, icnt: %lx, f_addr: %lx, u_addr: %lx, b_type: %lx\n", packet->tcode, packet->src, packet->icnt, packet->f_addr, packet->u_addr, packet->b_type); + printf("[trace_encoder_n] printing packet: tcode: %lx, src: %lx, icnt: %lx, f_addr: %lx, u_addr: %lx, b_type: %lx\n", packet->tcode, packet->src, packet->icnt, packet->f_addr, packet->u_addr, packet->b_type); } void print_encoded_packet(uint8_t* buffer, int num_bytes) { - printf("[trace_encoder_n] encoded packet: "); - for (int i = 0; i < num_bytes; i++) { - printf("%lx ", buffer[i]); - } - printf("\n"); + printf("[trace_encoder_n] encoded packet: "); + for (int i = 0; i < num_bytes; i++) { + printf("%lx ", buffer[i]); + } + printf("\n"); } void trace_encoder_n::trace_encoder_generate_packet(tcode_t tcode) { - trace_encoder_n_packet_t packet; - int num_bytes; - switch (tcode) { - case TCODE_PROG_TRACE_SYNC: - _set_program_trace_sync_packet(&packet); - print_packet(&packet); - num_bytes = packet_to_buffer(&packet); - fwrite(this->buffer, 1, num_bytes, this->trace_sink); - print_encoded_packet(this->buffer, num_bytes); - break; - case TCODE_DBR: - _set_direct_branch_packet(&packet); - print_packet(&packet); - num_bytes = packet_to_buffer(&packet); - fwrite(this->buffer, 1, num_bytes, this->trace_sink); - print_encoded_packet(this->buffer, num_bytes); - break; - case TCODE_IBR: - _set_indirect_branch_packet(&packet); - print_packet(&packet); - num_bytes = packet_to_buffer(&packet); - fwrite(this->buffer, 1, num_bytes, this->trace_sink); - print_encoded_packet(this->buffer, num_bytes); - break; - default: - break; - } + trace_encoder_n_packet_t packet; + int num_bytes; + switch (tcode) { + case TCODE_PROG_TRACE_SYNC: + _set_program_trace_sync_packet(&packet); + print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); + break; + case TCODE_DBR: + _set_direct_branch_packet(&packet); + print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); + break; + case TCODE_IBR: + _set_indirect_branch_packet(&packet); + print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); + break; + default: + break; + } } void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* packet){ - packet->tcode = TCODE_PROG_TRACE_SYNC; - packet->src = this->src; - packet->sync = SYNC_TRACE_EN; - packet->icnt = 0; - packet->f_addr = this->packet_0->i_addr >> 1; - this->prev_addr = packet->f_addr; + packet->tcode = TCODE_PROG_TRACE_SYNC; + packet->src = this->src; + packet->sync = SYNC_TRACE_EN; + packet->icnt = 0; + packet->f_addr = this->packet_0->i_addr >> 1; + this->prev_addr = packet->f_addr; } void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ - packet->tcode = TCODE_DBR; - packet->src = this->src; - packet->icnt = this->icnt; + packet->tcode = TCODE_DBR; + packet->src = this->src; + packet->icnt = this->icnt; } void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ - packet->tcode = TCODE_IBR; - packet->src = this->src; - packet->b_type = B_INDIRECT; - packet->icnt = this->icnt - this->packet_0->ilastsize; // - uint64_t e_addr = this->packet_0->i_addr >> 1; - packet->u_addr = e_addr ^ this->prev_addr; - this->prev_addr = e_addr; + packet->tcode = TCODE_IBR; + packet->src = this->src; + packet->b_type = B_INDIRECT; + packet->icnt = this->icnt - this->packet_0->ilastsize; // + uint64_t e_addr = this->packet_0->i_addr >> 1; + packet->u_addr = e_addr ^ this->prev_addr; + this->prev_addr = e_addr; } // returns the number of bytes written to the buffer int trace_encoder_n::packet_to_buffer(trace_encoder_n_packet_t* packet){ - switch (packet->tcode) { - case TCODE_PROG_TRACE_SYNC: - return _packet_to_buffer_program_trace_sync(packet); - case TCODE_DBR: - return _packet_to_buffer_direct_branch_packet(packet); - case TCODE_IBR: - return _packet_to_buffer_indirect_branch_packet(packet); - default: - break; - } + switch (packet->tcode) { + case TCODE_PROG_TRACE_SYNC: + return _packet_to_buffer_program_trace_sync(packet); + case TCODE_DBR: + return _packet_to_buffer_direct_branch_packet(packet); + case TCODE_IBR: + return _packet_to_buffer_indirect_branch_packet(packet); + default: + break; + } } int trace_encoder_n::_packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet) { - int msb = find_msb(packet->f_addr); - this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; - this->buffer[1] = packet->sync << MDO_OFFSET | MSEO_IDLE; - this->buffer[1] |= (packet->f_addr & 0b11) << 6; - int num_bytes = 0; - if (msb < 2) { - this->buffer[1] |= MSEO_LAST; - } else { - packet->f_addr >>= 2; - msb -= 2; - num_bytes = ceil_div(msb, 6); - for (int iter = 0; iter < num_bytes; iter++) { - this->buffer[2 + iter] = ((packet->f_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->f_addr >>= 6; - } - this->buffer[2 + num_bytes - 1] |= MSEO_LAST; - } - return 2 + num_bytes; + int msb = find_msb(packet->f_addr); + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] = packet->sync << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] |= (packet->f_addr & 0b11) << 6; + int num_bytes = 0; + if (msb < 2) { + this->buffer[1] |= MSEO_LAST; + } else { + packet->f_addr >>= 2; + msb -= 2; + num_bytes = ceil_div(msb, 6); + for (int iter = 0; iter < num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->f_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->f_addr >>= 6; + } + this->buffer[2 + num_bytes - 1] |= MSEO_LAST; + } + return 2 + num_bytes; } int trace_encoder_n::_packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet) { - this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; - int msb = find_msb(packet->icnt); - int num_bytes = ceil_div(msb, 6); - for (int iter = 0; iter < num_bytes; iter++) { - this->buffer[1 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->icnt >>= 6; - } - this->buffer[1 + num_bytes - 1] |= MSEO_LAST; - return 1 + num_bytes; + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + int msb = find_msb(packet->icnt); + int num_bytes = ceil_div(msb, 6); + for (int iter = 0; iter < num_bytes; iter++) { + this->buffer[1 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; + } + this->buffer[1 + num_bytes - 1] |= MSEO_LAST; + return 1 + num_bytes; } int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet) { - this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; - this->buffer[1] = packet->b_type << MDO_OFFSET | MSEO_IDLE; - // icnt - int icnt_msb = find_msb(packet->icnt); - int icnt_num_bytes = 0; - this->buffer[1] |= (packet->icnt & 0xF) << 4; - if (icnt_msb < 4) { - this->buffer[1] |= MSEO_EOF; - } else { - packet->icnt >>= 4; - icnt_msb -= 4; - icnt_num_bytes = ceil_div(icnt_msb, 6); - for (int iter = 0; iter < icnt_num_bytes; iter++) { - this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->icnt >>= 6; - } - this->buffer[2 + icnt_num_bytes - 1] |= MSEO_EOF; - } - // u_addr - int u_addr_start = 2 + icnt_num_bytes; - int u_addr_msb = find_msb(packet->u_addr); - int u_addr_num_bytes = ceil_div(u_addr_msb, 6); - printf("[trace_encoder_n] _packet_to_buffer_indirect_branch_packet: u_addr_start: %d, u_addr_msb: %d, u_addr_num_bytes: %d\n", u_addr_start, u_addr_msb, u_addr_num_bytes); - for (int iter = 0; iter < u_addr_num_bytes; iter++) { - this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->u_addr >>= 6; - } - this->buffer[u_addr_start + u_addr_num_bytes - 1] |= MSEO_LAST; - return u_addr_start + u_addr_num_bytes; + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] = packet->b_type << MDO_OFFSET | MSEO_IDLE; + // icnt + int icnt_msb = find_msb(packet->icnt); + int icnt_num_bytes = 0; + this->buffer[1] |= (packet->icnt & 0xF) << 4; + if (icnt_msb < 4) { + this->buffer[1] |= MSEO_EOF; + } else { + packet->icnt >>= 4; + icnt_msb -= 4; + icnt_num_bytes = ceil_div(icnt_msb, 6); + for (int iter = 0; iter < icnt_num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; + } + this->buffer[2 + icnt_num_bytes - 1] |= MSEO_EOF; + } + // u_addr + int u_addr_start = 2 + icnt_num_bytes; + int u_addr_msb = find_msb(packet->u_addr); + int u_addr_num_bytes = ceil_div(u_addr_msb, 6); + printf("[trace_encoder_n] _packet_to_buffer_indirect_branch_packet: u_addr_start: %d, u_addr_msb: %d, u_addr_num_bytes: %d\n", u_addr_start, u_addr_msb, u_addr_num_bytes); + for (int iter = 0; iter < u_addr_num_bytes; iter++) { + this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->u_addr >>= 6; + } + this->buffer[u_addr_start + u_addr_num_bytes - 1] |= MSEO_LAST; + return u_addr_start + u_addr_num_bytes; } // returns the 0-index of the most significant bit int find_msb(uint64_t x) { - if (x == 0) return -1; - return 63 - __builtin_clzll(x); + if (x == 0) return -1; + return 63 - __builtin_clzll(x); } // returns the ceiling of the division of a 0-indexed a by b int ceil_div(int a, int b) { - return a / b + 1; + return a / b + 1; } \ No newline at end of file diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 2c382e64e1..1267f594e2 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -7,41 +7,41 @@ class hart_to_encoder_ingress_t; enum tcode_t { - TCODE_OWN = 2, // ownership - TCODE_DBR = 3, // direct branch - TCODE_IBR = 4, // indirect branch - TCODE_ERR = 8, // error - TCODE_PROG_TRACE_SYNC = 9, // program trace sync - TCODE_DBR_SYNC = 10, // direct branch sync - TCODE_IBR_SYNC = 11, // indirect branch sync - TCODE_FULL = 27, // resource full - TCODE_IBR_HIST = 28, // indirect branch history - TCODE_IBR_HIST_SYNC = 29, // indirect branch history sync - TCODE_RBR = 30, // repeated branches - TCODE_PROG_TRACE_CORR = 33 // program trace correlation + TCODE_OWN = 2, // ownership + TCODE_DBR = 3, // direct branch + TCODE_IBR = 4, // indirect branch + TCODE_ERR = 8, // error + TCODE_PROG_TRACE_SYNC = 9, // program trace sync + TCODE_DBR_SYNC = 10, // direct branch sync + TCODE_IBR_SYNC = 11, // indirect branch sync + TCODE_FULL = 27, // resource full + TCODE_IBR_HIST = 28, // indirect branch history + TCODE_IBR_HIST_SYNC = 29, // indirect branch history sync + TCODE_RBR = 30, // repeated branches + TCODE_PROG_TRACE_CORR = 33 // program trace correlation }; enum b_type_t { - B_INDIRECT = 0, // indirect branch - B_TRAP = 1, // trap - B_EXCEPTION = 2, // exception - B_INTERRUPT = 3 // interrupt + B_INDIRECT = 0, // indirect branch + B_TRAP = 1, // trap + B_EXCEPTION = 2, // exception + B_INTERRUPT = 3 // interrupt }; enum sync_t { - SYNC_TRACE_EN = 5, + SYNC_TRACE_EN = 5, }; struct trace_encoder_n_packet_t { - uint8_t size; // 8 bits - tcode_t tcode; // 6 bits - uint16_t src; // unused for now - uint8_t sync; // 4 bit - uint8_t b_type; // 2 bits - uint16_t icnt; // 16 bits - uint64_t f_addr; // 64 bits - uint64_t u_addr; // 64 bits - uint64_t tstamp; // unused for now + uint8_t size; // 8 bits + tcode_t tcode; // 6 bits + uint16_t src; // unused for now + uint8_t sync; // 4 bit + uint8_t b_type; // 2 bits + uint16_t icnt; // 16 bits + uint64_t f_addr; // 64 bits + uint64_t u_addr; // 64 bits + uint64_t tstamp; // unused for now }; void print_packet(trace_encoder_n_packet_t* packet); @@ -51,9 +51,9 @@ int find_msb(uint64_t x); int ceil_div(int a, int b); enum trace_encoder_n_state_t { - TRACE_ENCODER_N_IDLE, - TRACE_ENCODER_N_DATA, - TRACE_ENCODER_N_FULL + TRACE_ENCODER_N_IDLE, + TRACE_ENCODER_N_DATA, + TRACE_ENCODER_N_FULL }; #define MAX_TRACE_BUFFER_SIZE 38 @@ -70,35 +70,35 @@ enum trace_encoder_n_state_t { class trace_encoder_n { public: - trace_encoder_n(); - void trace_encoder_push_commit(hart_to_encoder_ingress_t* packet); - void trace_encoder_generate_packet(tcode_t tcode); + trace_encoder_n(); + void trace_encoder_push_commit(hart_to_encoder_ingress_t* packet); + void trace_encoder_generate_packet(tcode_t tcode); - void set_enable(bool enabled); + void set_enable(bool enabled); private: - FILE* trace_sink; + FILE* trace_sink; - bool updesc; + bool updesc; - hart_to_encoder_ingress_t* packet_0; // the newer packet - hart_to_encoder_ingress_t* packet_1; // the older packet + hart_to_encoder_ingress_t* packet_0; // the newer packet + hart_to_encoder_ingress_t* packet_1; // the older packet - bool active; - bool enabled; - uint16_t src; - trace_encoder_n_state_t state; - uint8_t buffer[MAX_TRACE_BUFFER_SIZE]; - uint16_t icnt; - uint64_t prev_addr; + bool active; + bool enabled; + uint16_t src; + trace_encoder_n_state_t state; + uint8_t buffer[MAX_TRACE_BUFFER_SIZE]; + uint16_t icnt; + uint64_t prev_addr; - void _set_direct_branch_packet(trace_encoder_n_packet_t* packet); - void _set_indirect_branch_packet(trace_encoder_n_packet_t* packet); - void _set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); + void _set_direct_branch_packet(trace_encoder_n_packet_t* packet); + void _set_indirect_branch_packet(trace_encoder_n_packet_t* packet); + void _set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); - int packet_to_buffer(trace_encoder_n_packet_t* packet); - int _packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); - int _packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); - int _packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); + int packet_to_buffer(trace_encoder_n_packet_t* packet); + int _packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); + int _packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); + int _packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); }; diff --git a/riscv/trace_ingress.cc b/riscv/trace_ingress.cc index a3827ae990..c4a7855fbd 100644 --- a/riscv/trace_ingress.cc +++ b/riscv/trace_ingress.cc @@ -1,29 +1,30 @@ #include "trace_ingress.h" insn_type _get_insn_type(insn_t* insn, bool taken) { - if (_is_branch(insn)) { - return taken ? I_BRANCH_TAKEN : I_BRANCH_NON_TAKEN; - } - else if (_is_jal(insn)) { - return I_JUMP_INFERABLE; - } - else if (_is_jalr(insn)) { - return I_JUMP_UNINFERABLE; - } - // TODO: further categorization is not implemented for now - else { - return I_NONE; - } + if (_is_branch(insn)) { + return taken ? I_BRANCH_TAKEN : I_BRANCH_NON_TAKEN; + } + else if (_is_jal(insn)) { + return I_JUMP_INFERABLE; + } + else if (_is_jalr(insn)) { + return I_JUMP_UNINFERABLE; + } + // TODO: further categorization is not implemented for now + else { + return I_NONE; + } } void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* packet, insn_t* insn, reg_t npc) { - // print insn - bool taken = npc != p->get_state()->pc + insn_length(insn->bits()); - packet->i_type = _get_insn_type(insn, taken); - packet->exc_cause = 0; - packet->tval = 0; - packet->priv = P_M; // TODO: check for processor privilege level - packet->i_addr = p->get_state()->pc; - packet->iretire = 1; - packet->ilastsize = insn_length(insn->bits())/2; + // print insn + bool taken = npc != p->get_state()->pc + insn_length(insn->bits()); + // printf("[trace_ingress] insn: %lx, taken: %d, npc: %lx, pc: %lx\n", insn->bits(), taken, npc, p->get_state()->pc); + packet->i_type = _get_insn_type(insn, taken); + packet->exc_cause = 0; + packet->tval = 0; + packet->priv = P_M; // TODO: check for processor privilege level + packet->i_addr = p->get_state()->pc; + packet->iretire = 1; + packet->ilastsize = insn_length(insn->bits())/2; } \ No newline at end of file diff --git a/riscv/trace_ingress.h b/riscv/trace_ingress.h index 6648413e0b..cbec95180a 100644 --- a/riscv/trace_ingress.h +++ b/riscv/trace_ingress.h @@ -5,62 +5,62 @@ #include "encoding.h" enum trace_encoder_type { - N_TRACE_ENCODER, - E_TRACE_ENCODER + N_TRACE_ENCODER, + E_TRACE_ENCODER }; // Enumerates all possible instruction types enum insn_type { - I_NONE = 0, - I_EXCEPTION = 1, - I_INTERRUPT = 2, - I_TRAP_RETURN = 3, - I_BRANCH_NON_TAKEN = 4, - I_BRANCH_TAKEN = 5, - // I_BRANCH_UNINFERABLE = 6, - I_RESERVED = 7, - I_CALL_UNINFERABLE = 8, - I_CALL_INFERABLE = 9, - I_JUMP_UNINFERABLE = 10, - I_JUMP_INFERABLE = 11, - I_COROUTINE_SWAP = 12, - I_RETURN = 13, - I_OTHER_UNINFERABLE = 14, - I_OTHER_INFERABLE = 15, + I_NONE = 0, + I_EXCEPTION = 1, + I_INTERRUPT = 2, + I_TRAP_RETURN = 3, + I_BRANCH_NON_TAKEN = 4, + I_BRANCH_TAKEN = 5, + // I_BRANCH_UNINFERABLE = 6, + I_RESERVED = 7, + I_CALL_UNINFERABLE = 8, + I_CALL_INFERABLE = 9, + I_JUMP_UNINFERABLE = 10, + I_JUMP_INFERABLE = 11, + I_COROUTINE_SWAP = 12, + I_RETURN = 13, + I_OTHER_UNINFERABLE = 14, + I_OTHER_INFERABLE = 15, }; // Enumerates all possible privilege level encodings enum priv_enc { - P_U = 0, - P_S = 1, - // 2 is reserved - P_M = 3, - // 4-7 is optional and unused for now - P_D = 4, - P_VU = 5, - P_VS = 6, - // 7 is reserved + P_U = 0, + P_S = 1, + // 2 is reserved + P_M = 3, + // 4-7 is optional and unused for now + P_D = 4, + P_VU = 5, + P_VS = 6, + // 7 is reserved }; // Core to encoder communication struct // Assume a spike hart with max 1 instruction retired per cycle // Regardless of RV64 or RV32, we fix the size of the instruction address to 64 bits struct hart_to_encoder_ingress_t { - // instruction type - insn_type i_type; // 4 bits - // exception cause, mcause - uint8_t exc_cause; // 4 bits (only the lower 4 bits are used) - // trap value, mtval - uint64_t tval; // 64 bits - // core privilege level - priv_enc priv; // 3 bits - // retired instruction address - uint64_t i_addr; // 64 bits - //context, time, ctype, sijump are now unimplemented - // number of instructions retired - 0 or 1 for spike harts - bool iretire; // 1 bit - // ilastsize - int ilastsize; // 2 or 4, 2 bits + // instruction type + insn_type i_type; // 4 bits + // exception cause, mcause + uint8_t exc_cause; // 4 bits (only the lower 4 bits are used) + // trap value, mtval + uint64_t tval; // 64 bits + // core privilege level + priv_enc priv; // 3 bits + // retired instruction address + uint64_t i_addr; // 64 bits + //context, time, ctype, sijump are now unimplemented + // number of instructions retired - 0 or 1 for spike harts + bool iretire; // 1 bit + // ilastsize + int ilastsize; // 2 or 4, 2 bits }; void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* packet, insn_t* insn, reg_t npc); @@ -68,15 +68,15 @@ void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* pac #define CHECK_INSN(name) ((insn->bits() & MASK_##name) == MATCH_##name) static inline bool _is_branch(insn_t* insn) { - return CHECK_INSN(BEQ) || CHECK_INSN(BNE) || CHECK_INSN(BLT) || CHECK_INSN(BGE) || CHECK_INSN(BLTU) || CHECK_INSN(BGEU); + return CHECK_INSN(BEQ) || CHECK_INSN(BNE) || CHECK_INSN(BLT) || CHECK_INSN(BGE) || CHECK_INSN(BLTU) || CHECK_INSN(BGEU); } static inline bool _is_jal(insn_t* insn) { - return CHECK_INSN(JAL); + return CHECK_INSN(JAL); } static inline bool _is_jalr(insn_t* insn) { - return CHECK_INSN(JALR); + return CHECK_INSN(JALR); } #endif // _RISCV_TRACE_INGRESS_H \ No newline at end of file From 200dee9021f1d4fcbf6828d0d95ee36ce327a0df Mon Sep 17 00:00:00 2001 From: Lux Date: Tue, 1 Oct 2024 21:34:55 -0700 Subject: [PATCH 06/19] FIX: adding compressed instruction check --- riscv/trace_ingress.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/trace_ingress.h b/riscv/trace_ingress.h index cbec95180a..26cbd2a626 100644 --- a/riscv/trace_ingress.h +++ b/riscv/trace_ingress.h @@ -68,15 +68,15 @@ void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* pac #define CHECK_INSN(name) ((insn->bits() & MASK_##name) == MATCH_##name) static inline bool _is_branch(insn_t* insn) { - return CHECK_INSN(BEQ) || CHECK_INSN(BNE) || CHECK_INSN(BLT) || CHECK_INSN(BGE) || CHECK_INSN(BLTU) || CHECK_INSN(BGEU); + return CHECK_INSN(BEQ) || CHECK_INSN(BNE) || CHECK_INSN(BLT) || CHECK_INSN(BGE) || CHECK_INSN(BLTU) || CHECK_INSN(BGEU) || CHECK_INSN(C_BEQZ) || CHECK_INSN(C_BNEZ); } static inline bool _is_jal(insn_t* insn) { - return CHECK_INSN(JAL); + return CHECK_INSN(JAL) || CHECK_INSN(C_JAL) || CHECK_INSN(C_J); } static inline bool _is_jalr(insn_t* insn) { - return CHECK_INSN(JALR); + return CHECK_INSN(JALR) || CHECK_INSN(C_JALR) || CHECK_INSN(C_JR); } #endif // _RISCV_TRACE_INGRESS_H \ No newline at end of file From 369dd65ea1eab3f3e4fafbed41058f1e21fd5181 Mon Sep 17 00:00:00 2001 From: Lux Date: Tue, 1 Oct 2024 21:35:18 -0700 Subject: [PATCH 07/19] ADD: golden reference trace for debugging --- riscv/trace_encoder_n.cc | 5 ++++- riscv/trace_encoder_n.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 86cc60e89c..a0913e18aa 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -2,6 +2,7 @@ trace_encoder_n::trace_encoder_n() { this->trace_sink= fopen("trace_n.bin", "wb"); + this->debug_reference = fopen("trace_n_ref_debug.log", "wb"); this->active = true; this->enabled = false; this->src = 0; @@ -28,6 +29,7 @@ void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packe this->packet_0 = packet; printf("[trace_encoder_n] new packet tcode: %lx\n", this->packet_0->i_type); if (this->enabled) { + fprintf(this->debug_reference, "%lx\n", packet->i_addr); if (this->state == TRACE_ENCODER_N_IDLE) { trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); this->state = TRACE_ENCODER_N_DATA; @@ -116,7 +118,8 @@ void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* pack packet->tcode = TCODE_IBR; packet->src = this->src; packet->b_type = B_INDIRECT; - packet->icnt = this->icnt - this->packet_0->ilastsize; // + printf("[trace_encoder_n] _set_indirect_branch_packet: this->icnt: %lx, this->packet_0->ilastsize: %lx\n", this->icnt, this->packet_0->ilastsize); + packet->icnt = this->icnt - this->packet_0->ilastsize; uint64_t e_addr = this->packet_0->i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; this->prev_addr = e_addr; diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 1267f594e2..f58788578c 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -77,6 +77,7 @@ class trace_encoder_n { void set_enable(bool enabled); private: FILE* trace_sink; + FILE* debug_reference; bool updesc; From 62fc95b7de25f43e04f19c46a075fd9b4cf25860 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 10:22:29 -0700 Subject: [PATCH 08/19] FIX: fully correctly decode --- riscv/trace_encoder_n.cc | 13 ++++--------- riscv/trace_encoder_n.h | 2 -- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index a0913e18aa..bda6a04e82 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -8,7 +8,6 @@ trace_encoder_n::trace_encoder_n() { this->src = 0; this->state = TRACE_ENCODER_N_IDLE; this->icnt = 0; - this->updesc = false; this->packet_0 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet this->packet_1 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet } @@ -37,16 +36,12 @@ void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packe } else if (this->state == TRACE_ENCODER_N_DATA) { this->icnt += this->packet_0->ilastsize; printf("[trace_encoder_n] icnt: %lx\n", this->icnt); - if (this->packet_0->i_type == I_BRANCH_TAKEN) { + if (this->packet_1->i_type == I_BRANCH_TAKEN) { trace_encoder_generate_packet(TCODE_DBR); - this->icnt = 0; - } else if (this->packet_0->i_type == I_JUMP_INFERABLE || this->packet_0->i_type == I_JUMP_UNINFERABLE) { - this->updesc = true; - } else if (this->updesc) { + this->icnt = this->packet_0->ilastsize; + } else if (this->packet_1->i_type == I_JUMP_INFERABLE || this->packet_1->i_type == I_JUMP_UNINFERABLE) { trace_encoder_generate_packet(TCODE_IBR); this->icnt = this->packet_0->ilastsize; - printf("[trace_encoder_n] icnt: %lx\n", this->icnt); - this->updesc = false; } this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; } else if (this->state == TRACE_ENCODER_N_FULL) { @@ -111,7 +106,7 @@ void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* p void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_DBR; packet->src = this->src; - packet->icnt = this->icnt; + packet->icnt = this->icnt - this->packet_0->ilastsize; } void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index f58788578c..60e7b1c970 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -79,8 +79,6 @@ class trace_encoder_n { FILE* trace_sink; FILE* debug_reference; - bool updesc; - hart_to_encoder_ingress_t* packet_0; // the newer packet hart_to_encoder_ingress_t* packet_1; // the older packet From 5818fd5e98ac80c27c0b4fa1a49138a3ce6e3d65 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 15:09:52 -0700 Subject: [PATCH 09/19] FIX: major flattening --- riscv/execute.cc | 15 ++++++++++--- riscv/processor.cc | 6 ++++-- riscv/processor.h | 5 ++--- riscv/riscv.mk.in | 7 +++--- riscv/trace_encoder_n.cc | 46 ++++++++++++++++++---------------------- riscv/trace_encoder_n.h | 26 ++++++++++++++++++----- riscv/trace_ingress.cc | 31 +-------------------------- riscv/trace_ingress.h | 21 +++++++++++++++--- 8 files changed, 82 insertions(+), 75 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index b19e83217e..bd99b2abce 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -7,6 +7,7 @@ #include "mmu.h" #include "disasm.h" #include "decode_macros.h" +#include "trace_ingress.h" #include static void commit_log_reset(processor_t* p) @@ -164,6 +165,7 @@ inline void processor_t::update_histogram(reg_t pc) static inline reg_t execute_insn_fast(processor_t* p, reg_t pc, insn_fetch_t fetch) { return fetch.func(p, fetch.insn, pc); } + static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t fetch) { if (p->get_log_commits_enabled()) { @@ -177,9 +179,16 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f npc = fetch.func(p, fetch.insn, pc); if (p->get_log_commits_enabled()) { - hart_to_encoder_ingress_t* packet = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); - hart_to_encoder_ingress_init(p, packet, &fetch.insn, npc); - p->get_trace_encoder()->trace_encoder_push_commit(packet); + hart_to_encoder_ingress_t packet { + .i_type = _get_insn_type(&fetch.insn, npc != p->get_state()->pc + insn_length(fetch.insn.bits())), + .exc_cause = 0, + .tval = 0, + .priv = P_M, // TODO: check for processor privilege level + .i_addr = pc, + .iretire = 1, + .ilastsize = insn_length(fetch.insn.bits())/2, + }; + p->trace_encoder.trace_encoder_push_commit(packet); } if (npc != PC_SERIALIZE_BEFORE) { diff --git a/riscv/processor.cc b/riscv/processor.cc index ddeb80f691..2649531d43 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -12,6 +12,7 @@ #include "platform.h" #include "vector_unit.h" #include "debug_defines.h" +#include "trace_encoder_n.h" #include #include #include @@ -39,7 +40,7 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset), in_wfi(false), check_triggers_icount(false), impl_table(256, false), extension_enable_table(isa.get_extension_table()), - last_pc(1), executions(1), TM(cfg->trigger_count) + last_pc(1), executions(1), TM(cfg->trigger_count), trace_encoder() { VU.p = this; TM.proc = this; @@ -63,7 +64,6 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, register_base_instructions(); mmu = new mmu_t(sim, cfg->endianness, this); - trace_encoder = new trace_encoder_n(); disassembler = new disassembler_t(&isa); for (auto e : isa.get_extensions()) @@ -205,6 +205,8 @@ void processor_t::reset() if (sim) sim->proc_reset(id); + + trace_encoder.reset(); } extension_t* processor_t::get_extension() diff --git a/riscv/processor.h b/riscv/processor.h index d78a25a40a..486c10bc0f 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -29,7 +29,6 @@ class simif_t; class trap_t; class extension_t; class disassembler_t; -class trace_encoder_n; reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc); @@ -369,7 +368,7 @@ class processor_t : public abstract_device_t void check_if_lpad_required(); - trace_encoder_n* get_trace_encoder() { return trace_encoder; } + trace_encoder_n* get_trace_encoder() { return &trace_encoder; } private: const isa_parser_t isa; @@ -385,7 +384,6 @@ class processor_t : public abstract_device_t bool histogram_enabled; bool log_commits_enabled; FILE *log_file; - trace_encoder_n *trace_encoder; std::ostream sout_; // needed for socket command interface -s, also used for -d and -l, but not for --log bool halt_on_reset; bool in_wfi; @@ -437,6 +435,7 @@ class processor_t : public abstract_device_t vectorUnit_t VU; triggers::module_t TM; + trace_encoder_n trace_encoder; }; #endif diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index ca69b093eb..0b63bb5169 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -41,18 +41,16 @@ riscv_install_hdrs = \ rocc.h \ sim.h \ simif.h \ - trace_encoder_n.h \ - trace_ingress.h \ trap.h \ triggers.h \ vector_unit.h \ + trace_ingress.h \ + trace_encoder_n.h \ riscv_precompiled_hdrs = \ insn_template.h \ riscv_srcs = \ - trace_encoder_n.cc \ - trace_ingress.cc \ processor.cc \ execute.cc \ dts.cc \ @@ -77,6 +75,7 @@ riscv_srcs = \ vector_unit.cc \ socketif.cc \ cfg.cc \ + trace_encoder_n.cc \ $(riscv_gen_srcs) \ riscv_test_srcs = \ diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index bda6a04e82..330d9a9d68 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -1,47 +1,43 @@ #include "trace_encoder_n.h" -trace_encoder_n::trace_encoder_n() { - this->trace_sink= fopen("trace_n.bin", "wb"); - this->debug_reference = fopen("trace_n_ref_debug.log", "wb"); - this->active = true; - this->enabled = false; - this->src = 0; +void trace_encoder_n::reset() { this->state = TRACE_ENCODER_N_IDLE; this->icnt = 0; - this->packet_0 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet - this->packet_1 = (hart_to_encoder_ingress_t*) malloc(sizeof(hart_to_encoder_ingress_t)); // create empty packet + this->packet_0 = hart_to_encoder_ingress_t(); // create empty packet + this->packet_1 = hart_to_encoder_ingress_t(); // create empty packet + this->enabled = false; + this->active = true; } void trace_encoder_n::set_enable(bool enabled) { bool was_enabled = this->enabled; - printf("[trace_encoder_n] setting enable to %d\n", enabled); + printf("[trace_encoder_n] QAQ setting enable to %d\n", enabled); this->enabled = enabled; if (!was_enabled && enabled) { this->state = TRACE_ENCODER_N_IDLE; } } -void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t* packet) { - printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet->i_addr); - free(this->packet_1); +void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t packet) { + printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet.i_addr); this->packet_1 = this->packet_0; this->packet_0 = packet; - printf("[trace_encoder_n] new packet tcode: %lx\n", this->packet_0->i_type); + printf("[trace_encoder_n] new packet tcode: %lx\n", _get_packet_0()->i_type); if (this->enabled) { - fprintf(this->debug_reference, "%lx\n", packet->i_addr); + fprintf(this->debug_reference, "%lx\n", packet.i_addr); if (this->state == TRACE_ENCODER_N_IDLE) { trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); this->state = TRACE_ENCODER_N_DATA; - this->icnt += this->packet_0->ilastsize; + this->icnt += _get_packet_0()->ilastsize; } else if (this->state == TRACE_ENCODER_N_DATA) { - this->icnt += this->packet_0->ilastsize; + this->icnt += _get_packet_0()->ilastsize; printf("[trace_encoder_n] icnt: %lx\n", this->icnt); - if (this->packet_1->i_type == I_BRANCH_TAKEN) { + if (_get_packet_1()->i_type == I_BRANCH_TAKEN) { trace_encoder_generate_packet(TCODE_DBR); - this->icnt = this->packet_0->ilastsize; - } else if (this->packet_1->i_type == I_JUMP_INFERABLE || this->packet_1->i_type == I_JUMP_UNINFERABLE) { + this->icnt = _get_packet_0()->ilastsize; + } else if (_get_packet_1()->i_type == I_JUMP_INFERABLE || _get_packet_1()->i_type == I_JUMP_UNINFERABLE) { trace_encoder_generate_packet(TCODE_IBR); - this->icnt = this->packet_0->ilastsize; + this->icnt = _get_packet_0()->ilastsize; } this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; } else if (this->state == TRACE_ENCODER_N_FULL) { @@ -99,23 +95,23 @@ void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* p packet->src = this->src; packet->sync = SYNC_TRACE_EN; packet->icnt = 0; - packet->f_addr = this->packet_0->i_addr >> 1; + packet->f_addr = _get_packet_0()->i_addr >> 1; this->prev_addr = packet->f_addr; } void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_DBR; packet->src = this->src; - packet->icnt = this->icnt - this->packet_0->ilastsize; + packet->icnt = this->icnt - _get_packet_0()->ilastsize; } void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_IBR; packet->src = this->src; packet->b_type = B_INDIRECT; - printf("[trace_encoder_n] _set_indirect_branch_packet: this->icnt: %lx, this->packet_0->ilastsize: %lx\n", this->icnt, this->packet_0->ilastsize); - packet->icnt = this->icnt - this->packet_0->ilastsize; - uint64_t e_addr = this->packet_0->i_addr >> 1; + printf("[trace_encoder_n] _set_indirect_branch_packet: this->icnt: %lx, _get_packet_0()->ilastsize: %lx\n", this->icnt, _get_packet_0()->ilastsize); + packet->icnt = this->icnt - _get_packet_0()->ilastsize; + uint64_t e_addr = _get_packet_0()->i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; this->prev_addr = e_addr; } diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 60e7b1c970..377babed0e 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -4,7 +4,7 @@ #include "trace_ingress.h" #include -class hart_to_encoder_ingress_t; +class processor_t; enum tcode_t { TCODE_OWN = 2, // ownership @@ -70,17 +70,30 @@ enum trace_encoder_n_state_t { class trace_encoder_n { public: - trace_encoder_n(); - void trace_encoder_push_commit(hart_to_encoder_ingress_t* packet); + + trace_encoder_n() { + printf("[trace_encoder_n] trace_encoder_n() constructor evaluated\n"); + this->trace_sink= fopen("trace_n.bin", "wb"); + this->debug_reference = fopen("trace_n_ref_debug.log", "wb"); + this->active = true; + this->enabled = false; + this->src = 0; + this->state = TRACE_ENCODER_N_IDLE; + this->icnt = 0; + this->packet_0 = hart_to_encoder_ingress_t(); // create empty packet + this->packet_1 = hart_to_encoder_ingress_t(); // create empty packet + } + void trace_encoder_push_commit(hart_to_encoder_ingress_t packet); void trace_encoder_generate_packet(tcode_t tcode); void set_enable(bool enabled); + void reset(); private: FILE* trace_sink; FILE* debug_reference; - hart_to_encoder_ingress_t* packet_0; // the newer packet - hart_to_encoder_ingress_t* packet_1; // the older packet + hart_to_encoder_ingress_t packet_0; // the newer packet + hart_to_encoder_ingress_t packet_1; // the older packet bool active; bool enabled; @@ -98,6 +111,9 @@ class trace_encoder_n { int _packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); int _packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); int _packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); + + inline hart_to_encoder_ingress_t* _get_packet_0() { return &packet_0; } + inline hart_to_encoder_ingress_t* _get_packet_1() { return &packet_1; } }; diff --git a/riscv/trace_ingress.cc b/riscv/trace_ingress.cc index c4a7855fbd..bc0cacd28b 100644 --- a/riscv/trace_ingress.cc +++ b/riscv/trace_ingress.cc @@ -1,30 +1 @@ -#include "trace_ingress.h" - -insn_type _get_insn_type(insn_t* insn, bool taken) { - if (_is_branch(insn)) { - return taken ? I_BRANCH_TAKEN : I_BRANCH_NON_TAKEN; - } - else if (_is_jal(insn)) { - return I_JUMP_INFERABLE; - } - else if (_is_jalr(insn)) { - return I_JUMP_UNINFERABLE; - } - // TODO: further categorization is not implemented for now - else { - return I_NONE; - } -} - -void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* packet, insn_t* insn, reg_t npc) { - // print insn - bool taken = npc != p->get_state()->pc + insn_length(insn->bits()); - // printf("[trace_ingress] insn: %lx, taken: %d, npc: %lx, pc: %lx\n", insn->bits(), taken, npc, p->get_state()->pc); - packet->i_type = _get_insn_type(insn, taken); - packet->exc_cause = 0; - packet->tval = 0; - packet->priv = P_M; // TODO: check for processor privilege level - packet->i_addr = p->get_state()->pc; - packet->iretire = 1; - packet->ilastsize = insn_length(insn->bits())/2; -} \ No newline at end of file +#include "trace_ingress.h" \ No newline at end of file diff --git a/riscv/trace_ingress.h b/riscv/trace_ingress.h index 26cbd2a626..420f4e5cc1 100644 --- a/riscv/trace_ingress.h +++ b/riscv/trace_ingress.h @@ -1,8 +1,9 @@ #ifndef _RISCV_TRACE_INGRESS_H #define _RISCV_TRACE_INGRESS_H -#include "processor.h" #include "encoding.h" +#include "decode.h" +#include enum trace_encoder_type { N_TRACE_ENCODER, @@ -63,8 +64,6 @@ struct hart_to_encoder_ingress_t { int ilastsize; // 2 or 4, 2 bits }; -void hart_to_encoder_ingress_init(processor_t* p, hart_to_encoder_ingress_t* packet, insn_t* insn, reg_t npc); - #define CHECK_INSN(name) ((insn->bits() & MASK_##name) == MATCH_##name) static inline bool _is_branch(insn_t* insn) { @@ -79,4 +78,20 @@ static inline bool _is_jalr(insn_t* insn) { return CHECK_INSN(JALR) || CHECK_INSN(C_JALR) || CHECK_INSN(C_JR); } +static inline insn_type _get_insn_type(insn_t* insn, bool taken) { + if (_is_branch(insn)) { + return taken ? I_BRANCH_TAKEN : I_BRANCH_NON_TAKEN; + } + else if (_is_jal(insn)) { + return I_JUMP_INFERABLE; + } + else if (_is_jalr(insn)) { + return I_JUMP_UNINFERABLE; + } + // TODO: further categorization is not implemented for now + else { + return I_NONE; + } +} + #endif // _RISCV_TRACE_INGRESS_H \ No newline at end of file From 6e2b5b4f0ca3649e9291abbe223b762795a308b2 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 15:10:21 -0700 Subject: [PATCH 10/19] FORMAT: imports --- riscv/trace_ingress.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/trace_ingress.h b/riscv/trace_ingress.h index 420f4e5cc1..f0a2081df0 100644 --- a/riscv/trace_ingress.h +++ b/riscv/trace_ingress.h @@ -1,9 +1,9 @@ #ifndef _RISCV_TRACE_INGRESS_H #define _RISCV_TRACE_INGRESS_H +#include #include "encoding.h" #include "decode.h" -#include enum trace_encoder_type { N_TRACE_ENCODER, From b3d8471ac90fd3db5e0d6f7aa1e88c7e2b874c98 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 15:38:36 -0700 Subject: [PATCH 11/19] ADD: --trace command line option --- riscv/execute.cc | 5 +++-- riscv/processor.cc | 5 +++++ riscv/processor.h | 3 +++ riscv/sim.cc | 15 ++++++++++----- riscv/sim.h | 2 +- spike_main/spike.cc | 6 +++++- 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index bd99b2abce..334a5e6b86 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -178,7 +178,8 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f try { npc = fetch.func(p, fetch.insn, pc); - if (p->get_log_commits_enabled()) { + if (p->get_trace_enabled()) { + printf("[execute.cc] trace enabled\n"); hart_to_encoder_ingress_t packet { .i_type = _get_insn_type(&fetch.insn, npc != p->get_state()->pc + insn_length(fetch.insn.bits())), .exc_cause = 0, @@ -223,7 +224,7 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f bool processor_t::slow_path() { return debug || state.single_step != state.STEP_NONE || state.debug_mode || - log_commits_enabled || histogram_enabled || in_wfi || check_triggers_icount; + log_commits_enabled || histogram_enabled || in_wfi || check_triggers_icount || trace_enabled; } // fetch/decode/execute loop diff --git a/riscv/processor.cc b/riscv/processor.cc index 2649531d43..1976953e5f 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -183,6 +183,11 @@ void processor_t::enable_log_commits() log_commits_enabled = true; } +void processor_t::enable_trace() +{ + trace_enabled = true; +} + void processor_t::reset() { xlen = isa.get_max_xlen(); diff --git a/riscv/processor.h b/riscv/processor.h index 486c10bc0f..08c6838756 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -254,7 +254,9 @@ class processor_t : public abstract_device_t void set_debug(bool value); void set_histogram(bool value); void enable_log_commits(); + void enable_trace(); bool get_log_commits_enabled() const { return log_commits_enabled; } + bool get_trace_enabled() const { return trace_enabled; } void reset(); void step(size_t n); // run for n cycles void put_csr(int which, reg_t val); @@ -383,6 +385,7 @@ class processor_t : public abstract_device_t unsigned xlen; bool histogram_enabled; bool log_commits_enabled; + bool trace_enabled; // whether core needs to trace instructions - does not mean the encoder itself is enabled! FILE *log_file; std::ostream sout_; // needed for socket command interface -s, also used for -d and -l, but not for --log bool halt_on_reset; diff --git a/riscv/sim.cc b/riscv/sim.cc index a44aea9413..51fd684d89 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -316,15 +316,20 @@ void sim_t::set_histogram(bool value) } } -void sim_t::configure_log(bool enable_log, bool enable_commitlog) +void sim_t::configure_log(bool enable_log, bool enable_commitlog, bool trace) { log = enable_log; - if (!enable_commitlog) - return; + if (enable_commitlog) { + for (processor_t *proc : procs) { + proc->enable_log_commits(); + } + } - for (processor_t *proc : procs) { - proc->enable_log_commits(); + if (trace) { + for (processor_t *proc : procs) { + proc->enable_trace(); + } } } diff --git a/riscv/sim.h b/riscv/sim.h index 93a2c21dde..efeab9a365 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -48,7 +48,7 @@ class sim_t : public htif_t, public simif_t // // If enable_log is true, an instruction trace will be generated. If // enable_commitlog is true, so will the commit results - void configure_log(bool enable_log, bool enable_commitlog); + void configure_log(bool enable_log, bool enable_commitlog, bool trace); void set_procs_debug(bool value); void set_remote_bitbang(remote_bitbang_t* remote_bitbang) { diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 1a298f2d5c..685950f345 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -56,6 +56,7 @@ static void help(int exit_code = 1) fprintf(stderr, " specify --device=, to pass down extra args.\n"); fprintf(stderr, " --log-cache-miss Generate a log of cache miss\n"); fprintf(stderr, " --log-commits Generate a log of commits info\n"); + fprintf(stderr, " --trace Generate a trace of instructions\n"); fprintf(stderr, " --extension= Specify RoCC Extension\n"); fprintf(stderr, " This flag can be used multiple times.\n"); fprintf(stderr, " --extlib= Shared library to load\n"); @@ -340,6 +341,7 @@ int main(int argc, char** argv) std::unique_ptr l2; bool log_cache = false; bool log_commits = false; + bool trace = false; const char *log_path = nullptr; std::vector> extensions; const char* initrd = NULL; @@ -442,6 +444,8 @@ int main(int argc, char** argv) [&](const char UNUSED *s){dm_config.support_haltgroups = false;}); parser.option(0, "log-commits", 0, [&](const char UNUSED *s){log_commits = true;}); + parser.option(0, "trace", 0, + [&](const char UNUSED *s){trace = true;}); parser.option(0, "log", 1, [&](const char* s){log_path = s;}); FILE *cmd_file = NULL; @@ -550,7 +554,7 @@ int main(int argc, char** argv) } s.set_debug(debug); - s.configure_log(log, log_commits); + s.configure_log(log, log_commits, trace); s.set_histogram(histogram); auto return_code = s.run(); From ca7b2b758215ee807bd089c5f3bddf4661b7282e Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 15:45:22 -0700 Subject: [PATCH 12/19] FIX: removing excess prints --- riscv/execute.cc | 1 - riscv/trace_encoder_n.cc | 18 ++++++------------ riscv/trace_encoder_n.h | 1 - 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index 334a5e6b86..7544360bf7 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -179,7 +179,6 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f npc = fetch.func(p, fetch.insn, pc); if (p->get_trace_enabled()) { - printf("[execute.cc] trace enabled\n"); hart_to_encoder_ingress_t packet { .i_type = _get_insn_type(&fetch.insn, npc != p->get_state()->pc + insn_length(fetch.insn.bits())), .exc_cause = 0, diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 330d9a9d68..794f92db8b 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -11,7 +11,6 @@ void trace_encoder_n::reset() { void trace_encoder_n::set_enable(bool enabled) { bool was_enabled = this->enabled; - printf("[trace_encoder_n] QAQ setting enable to %d\n", enabled); this->enabled = enabled; if (!was_enabled && enabled) { this->state = TRACE_ENCODER_N_IDLE; @@ -19,10 +18,8 @@ void trace_encoder_n::set_enable(bool enabled) { } void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t packet) { - printf("[trace_encoder_n] pushed commit packet at i_addr: %lx\n", packet.i_addr); this->packet_1 = this->packet_0; this->packet_0 = packet; - printf("[trace_encoder_n] new packet tcode: %lx\n", _get_packet_0()->i_type); if (this->enabled) { fprintf(this->debug_reference, "%lx\n", packet.i_addr); if (this->state == TRACE_ENCODER_N_IDLE) { @@ -31,7 +28,6 @@ void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t packet this->icnt += _get_packet_0()->ilastsize; } else if (this->state == TRACE_ENCODER_N_DATA) { this->icnt += _get_packet_0()->ilastsize; - printf("[trace_encoder_n] icnt: %lx\n", this->icnt); if (_get_packet_1()->i_type == I_BRANCH_TAKEN) { trace_encoder_generate_packet(TCODE_DBR); this->icnt = _get_packet_0()->ilastsize; @@ -66,24 +62,24 @@ void trace_encoder_n::trace_encoder_generate_packet(tcode_t tcode) { switch (tcode) { case TCODE_PROG_TRACE_SYNC: _set_program_trace_sync_packet(&packet); - print_packet(&packet); + // print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); - print_encoded_packet(this->buffer, num_bytes); + // print_encoded_packet(this->buffer, num_bytes); break; case TCODE_DBR: _set_direct_branch_packet(&packet); - print_packet(&packet); + // print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); - print_encoded_packet(this->buffer, num_bytes); + // print_encoded_packet(this->buffer, num_bytes); break; case TCODE_IBR: _set_indirect_branch_packet(&packet); - print_packet(&packet); + // print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); - print_encoded_packet(this->buffer, num_bytes); + // print_encoded_packet(this->buffer, num_bytes); break; default: break; @@ -109,7 +105,6 @@ void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* pack packet->tcode = TCODE_IBR; packet->src = this->src; packet->b_type = B_INDIRECT; - printf("[trace_encoder_n] _set_indirect_branch_packet: this->icnt: %lx, _get_packet_0()->ilastsize: %lx\n", this->icnt, _get_packet_0()->ilastsize); packet->icnt = this->icnt - _get_packet_0()->ilastsize; uint64_t e_addr = _get_packet_0()->i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; @@ -186,7 +181,6 @@ int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_pa int u_addr_start = 2 + icnt_num_bytes; int u_addr_msb = find_msb(packet->u_addr); int u_addr_num_bytes = ceil_div(u_addr_msb, 6); - printf("[trace_encoder_n] _packet_to_buffer_indirect_branch_packet: u_addr_start: %d, u_addr_msb: %d, u_addr_num_bytes: %d\n", u_addr_start, u_addr_msb, u_addr_num_bytes); for (int iter = 0; iter < u_addr_num_bytes; iter++) { this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; packet->u_addr >>= 6; diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 377babed0e..c2eea575c5 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -72,7 +72,6 @@ class trace_encoder_n { public: trace_encoder_n() { - printf("[trace_encoder_n] trace_encoder_n() constructor evaluated\n"); this->trace_sink= fopen("trace_n.bin", "wb"); this->debug_reference = fopen("trace_n_ref_debug.log", "wb"); this->active = true; From 1c8e63a760f742e2e944154fdb336e0d74d0faf9 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 15:49:25 -0700 Subject: [PATCH 13/19] FIX: remove unecessary constructor --- riscv/processor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 1976953e5f..0ec8fa773b 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -40,7 +40,7 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset), in_wfi(false), check_triggers_icount(false), impl_table(256, false), extension_enable_table(isa.get_extension_table()), - last_pc(1), executions(1), TM(cfg->trigger_count), trace_encoder() + last_pc(1), executions(1), TM(cfg->trigger_count) { VU.p = this; TM.proc = this; From 9a9b5727d2ac922afed559847f11c09fbacc9a3a Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 16:08:17 -0700 Subject: [PATCH 14/19] FORMAT: cosmetics --- riscv/execute.cc | 2 +- riscv/trace_encoder_n.cc | 32 ++++++++++++++++---------------- riscv/trace_encoder_n.h | 4 ++-- riscv/trace_ingress.cc | 1 - 4 files changed, 19 insertions(+), 20 deletions(-) delete mode 100644 riscv/trace_ingress.cc diff --git a/riscv/execute.cc b/riscv/execute.cc index 7544360bf7..7a6815782b 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -188,7 +188,7 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f .iretire = 1, .ilastsize = insn_length(fetch.insn.bits())/2, }; - p->trace_encoder.trace_encoder_push_commit(packet); + p->trace_encoder.push_commit(packet); } if (npc != PC_SERIALIZE_BEFORE) { diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 794f92db8b..d7353414a1 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -17,27 +17,27 @@ void trace_encoder_n::set_enable(bool enabled) { } } -void trace_encoder_n::trace_encoder_push_commit(hart_to_encoder_ingress_t packet) { +void trace_encoder_n::push_commit(hart_to_encoder_ingress_t packet) { this->packet_1 = this->packet_0; this->packet_0 = packet; if (this->enabled) { fprintf(this->debug_reference, "%lx\n", packet.i_addr); if (this->state == TRACE_ENCODER_N_IDLE) { - trace_encoder_generate_packet(TCODE_PROG_TRACE_SYNC); + generate_packet(TCODE_PROG_TRACE_SYNC); this->state = TRACE_ENCODER_N_DATA; - this->icnt += _get_packet_0()->ilastsize; + this->icnt += this->packet_0.ilastsize; } else if (this->state == TRACE_ENCODER_N_DATA) { - this->icnt += _get_packet_0()->ilastsize; - if (_get_packet_1()->i_type == I_BRANCH_TAKEN) { - trace_encoder_generate_packet(TCODE_DBR); - this->icnt = _get_packet_0()->ilastsize; - } else if (_get_packet_1()->i_type == I_JUMP_INFERABLE || _get_packet_1()->i_type == I_JUMP_UNINFERABLE) { - trace_encoder_generate_packet(TCODE_IBR); - this->icnt = _get_packet_0()->ilastsize; + this->icnt += this->packet_0.ilastsize; + if (this->packet_1.i_type == I_BRANCH_TAKEN) { + generate_packet(TCODE_DBR); + this->icnt = this->packet_0.ilastsize; + } else if (this->packet_1.i_type == I_JUMP_INFERABLE || this->packet_1.i_type == I_JUMP_UNINFERABLE) { + generate_packet(TCODE_IBR); + this->icnt = this->packet_0.ilastsize; } this->state = this->icnt >= MAX_ICNT ? TRACE_ENCODER_N_FULL : TRACE_ENCODER_N_DATA; } else if (this->state == TRACE_ENCODER_N_FULL) { - trace_encoder_generate_packet(TCODE_FULL); + generate_packet(TCODE_FULL); this->state = TRACE_ENCODER_N_DATA; this->icnt = 0; } @@ -56,7 +56,7 @@ void print_encoded_packet(uint8_t* buffer, int num_bytes) { printf("\n"); } -void trace_encoder_n::trace_encoder_generate_packet(tcode_t tcode) { +void trace_encoder_n::generate_packet(tcode_t tcode) { trace_encoder_n_packet_t packet; int num_bytes; switch (tcode) { @@ -91,22 +91,22 @@ void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* p packet->src = this->src; packet->sync = SYNC_TRACE_EN; packet->icnt = 0; - packet->f_addr = _get_packet_0()->i_addr >> 1; + packet->f_addr = this->packet_0.i_addr >> 1; this->prev_addr = packet->f_addr; } void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_DBR; packet->src = this->src; - packet->icnt = this->icnt - _get_packet_0()->ilastsize; + packet->icnt = this->icnt - this->packet_0.ilastsize; } void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_IBR; packet->src = this->src; packet->b_type = B_INDIRECT; - packet->icnt = this->icnt - _get_packet_0()->ilastsize; - uint64_t e_addr = _get_packet_0()->i_addr >> 1; + packet->icnt = this->icnt - this->packet_0.ilastsize; + uint64_t e_addr = this->packet_0.i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; this->prev_addr = e_addr; } diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index c2eea575c5..725cb95f03 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -82,8 +82,8 @@ class trace_encoder_n { this->packet_0 = hart_to_encoder_ingress_t(); // create empty packet this->packet_1 = hart_to_encoder_ingress_t(); // create empty packet } - void trace_encoder_push_commit(hart_to_encoder_ingress_t packet); - void trace_encoder_generate_packet(tcode_t tcode); + void push_commit(hart_to_encoder_ingress_t packet); + void generate_packet(tcode_t tcode); void set_enable(bool enabled); void reset(); diff --git a/riscv/trace_ingress.cc b/riscv/trace_ingress.cc deleted file mode 100644 index bc0cacd28b..0000000000 --- a/riscv/trace_ingress.cc +++ /dev/null @@ -1 +0,0 @@ -#include "trace_ingress.h" \ No newline at end of file From 4124ecc75d848561548821d7b78f1cc7830092a0 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 16:10:31 -0700 Subject: [PATCH 15/19] FORMAT: remove unused indirection --- riscv/trace_encoder_n.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 725cb95f03..714390af41 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -110,9 +110,6 @@ class trace_encoder_n { int _packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); int _packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); int _packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); - - inline hart_to_encoder_ingress_t* _get_packet_0() { return &packet_0; } - inline hart_to_encoder_ingress_t* _get_packet_1() { return &packet_1; } }; From 08e454204e19826e3167e89289f0178fee7b4d79 Mon Sep 17 00:00:00 2001 From: Lux Date: Wed, 2 Oct 2024 16:29:52 -0700 Subject: [PATCH 16/19] FORMAT: more cosmetics --- riscv/trace_encoder_n.cc | 120 +++++++++++++++++++-------------------- riscv/trace_encoder_n.h | 12 ++-- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index d7353414a1..3661d4f22b 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -51,7 +51,7 @@ void print_packet(trace_encoder_n_packet_t* packet) { void print_encoded_packet(uint8_t* buffer, int num_bytes) { printf("[trace_encoder_n] encoded packet: "); for (int i = 0; i < num_bytes; i++) { - printf("%lx ", buffer[i]); + printf("%lx ", buffer[i]); } printf("\n"); } @@ -60,33 +60,33 @@ void trace_encoder_n::generate_packet(tcode_t tcode) { trace_encoder_n_packet_t packet; int num_bytes; switch (tcode) { - case TCODE_PROG_TRACE_SYNC: - _set_program_trace_sync_packet(&packet); - // print_packet(&packet); - num_bytes = packet_to_buffer(&packet); - fwrite(this->buffer, 1, num_bytes, this->trace_sink); - // print_encoded_packet(this->buffer, num_bytes); - break; - case TCODE_DBR: - _set_direct_branch_packet(&packet); - // print_packet(&packet); - num_bytes = packet_to_buffer(&packet); - fwrite(this->buffer, 1, num_bytes, this->trace_sink); - // print_encoded_packet(this->buffer, num_bytes); - break; - case TCODE_IBR: - _set_indirect_branch_packet(&packet); - // print_packet(&packet); - num_bytes = packet_to_buffer(&packet); - fwrite(this->buffer, 1, num_bytes, this->trace_sink); - // print_encoded_packet(this->buffer, num_bytes); - break; - default: - break; + case TCODE_PROG_TRACE_SYNC: + set_program_trace_sync_packet(&packet); + // print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + // print_encoded_packet(this->buffer, num_bytes); + break; + case TCODE_DBR: + set_direct_branch_packet(&packet); + // print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + // print_encoded_packet(this->buffer, num_bytes); + break; + case TCODE_IBR: + set_indirect_branch_packet(&packet); + // print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + // print_encoded_packet(this->buffer, num_bytes); + break; + default: + break; } } -void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* packet){ +void trace_encoder_n::set_program_trace_sync_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_PROG_TRACE_SYNC; packet->src = this->src; packet->sync = SYNC_TRACE_EN; @@ -95,13 +95,13 @@ void trace_encoder_n::_set_program_trace_sync_packet(trace_encoder_n_packet_t* p this->prev_addr = packet->f_addr; } -void trace_encoder_n::_set_direct_branch_packet(trace_encoder_n_packet_t* packet){ +void trace_encoder_n::set_direct_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_DBR; packet->src = this->src; packet->icnt = this->icnt - this->packet_0.ilastsize; } -void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ +void trace_encoder_n::set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_IBR; packet->src = this->src; packet->b_type = B_INDIRECT; @@ -114,51 +114,51 @@ void trace_encoder_n::_set_indirect_branch_packet(trace_encoder_n_packet_t* pack // returns the number of bytes written to the buffer int trace_encoder_n::packet_to_buffer(trace_encoder_n_packet_t* packet){ switch (packet->tcode) { - case TCODE_PROG_TRACE_SYNC: - return _packet_to_buffer_program_trace_sync(packet); - case TCODE_DBR: - return _packet_to_buffer_direct_branch_packet(packet); - case TCODE_IBR: - return _packet_to_buffer_indirect_branch_packet(packet); - default: - break; + case TCODE_PROG_TRACE_SYNC: + return packet_to_buffer_program_trace_sync(packet); + case TCODE_DBR: + return packet_to_buffer_direct_branch_packet(packet); + case TCODE_IBR: + return packet_to_buffer_indirect_branch_packet(packet); + default: + break; } } -int trace_encoder_n::_packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet) { +int trace_encoder_n::packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet) { int msb = find_msb(packet->f_addr); this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; this->buffer[1] = packet->sync << MDO_OFFSET | MSEO_IDLE; this->buffer[1] |= (packet->f_addr & 0b11) << 6; int num_bytes = 0; if (msb < 2) { - this->buffer[1] |= MSEO_LAST; + this->buffer[1] |= MSEO_LAST; } else { - packet->f_addr >>= 2; - msb -= 2; - num_bytes = ceil_div(msb, 6); - for (int iter = 0; iter < num_bytes; iter++) { - this->buffer[2 + iter] = ((packet->f_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->f_addr >>= 6; - } - this->buffer[2 + num_bytes - 1] |= MSEO_LAST; + packet->f_addr >>= 2; + msb -= 2; + num_bytes = ceil_div(msb, 6); + for (int iter = 0; iter < num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->f_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->f_addr >>= 6; + } + this->buffer[2 + num_bytes - 1] |= MSEO_LAST; } return 2 + num_bytes; } -int trace_encoder_n::_packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet) { +int trace_encoder_n::packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet) { this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; int msb = find_msb(packet->icnt); int num_bytes = ceil_div(msb, 6); for (int iter = 0; iter < num_bytes; iter++) { - this->buffer[1 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->icnt >>= 6; + this->buffer[1 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; } this->buffer[1 + num_bytes - 1] |= MSEO_LAST; return 1 + num_bytes; } -int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet) { +int trace_encoder_n::packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet) { this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; this->buffer[1] = packet->b_type << MDO_OFFSET | MSEO_IDLE; // icnt @@ -166,24 +166,24 @@ int trace_encoder_n::_packet_to_buffer_indirect_branch_packet(trace_encoder_n_pa int icnt_num_bytes = 0; this->buffer[1] |= (packet->icnt & 0xF) << 4; if (icnt_msb < 4) { - this->buffer[1] |= MSEO_EOF; + this->buffer[1] |= MSEO_EOF; } else { - packet->icnt >>= 4; - icnt_msb -= 4; - icnt_num_bytes = ceil_div(icnt_msb, 6); - for (int iter = 0; iter < icnt_num_bytes; iter++) { - this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->icnt >>= 6; - } - this->buffer[2 + icnt_num_bytes - 1] |= MSEO_EOF; + packet->icnt >>= 4; + icnt_msb -= 4; + icnt_num_bytes = ceil_div(icnt_msb, 6); + for (int iter = 0; iter < icnt_num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; + } + this->buffer[2 + icnt_num_bytes - 1] |= MSEO_EOF; } // u_addr int u_addr_start = 2 + icnt_num_bytes; int u_addr_msb = find_msb(packet->u_addr); int u_addr_num_bytes = ceil_div(u_addr_msb, 6); for (int iter = 0; iter < u_addr_num_bytes; iter++) { - this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; - packet->u_addr >>= 6; + this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->u_addr >>= 6; } this->buffer[u_addr_start + u_addr_num_bytes - 1] |= MSEO_LAST; return u_addr_start + u_addr_num_bytes; diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 714390af41..0ff3e43175 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -102,14 +102,14 @@ class trace_encoder_n { uint16_t icnt; uint64_t prev_addr; - void _set_direct_branch_packet(trace_encoder_n_packet_t* packet); - void _set_indirect_branch_packet(trace_encoder_n_packet_t* packet); - void _set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); + void set_direct_branch_packet(trace_encoder_n_packet_t* packet); + void set_indirect_branch_packet(trace_encoder_n_packet_t* packet); + void set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); int packet_to_buffer(trace_encoder_n_packet_t* packet); - int _packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); - int _packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); - int _packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); + int packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); + int packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); + int packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); }; From b5bfcecf6e6e411a23e882703606c4b63f5ffb25 Mon Sep 17 00:00:00 2001 From: Lux Date: Mon, 7 Oct 2024 13:52:03 -0700 Subject: [PATCH 17/19] ADD: redo inferable jump for spec compliance --- riscv/trace_encoder_n.cc | 64 +++++++++++++++++++++++++++++++++------- riscv/trace_encoder_n.h | 11 ++++++- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 3661d4f22b..67fd90f5e6 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -31,7 +31,7 @@ void trace_encoder_n::push_commit(hart_to_encoder_ingress_t packet) { if (this->packet_1.i_type == I_BRANCH_TAKEN) { generate_packet(TCODE_DBR); this->icnt = this->packet_0.ilastsize; - } else if (this->packet_1.i_type == I_JUMP_INFERABLE || this->packet_1.i_type == I_JUMP_UNINFERABLE) { + } else if (this->packet_1.i_type == I_JUMP_UNINFERABLE) { generate_packet(TCODE_IBR); this->icnt = this->packet_0.ilastsize; } @@ -41,7 +41,13 @@ void trace_encoder_n::push_commit(hart_to_encoder_ingress_t packet) { this->state = TRACE_ENCODER_N_DATA; this->icnt = 0; } - } + } else if (!this->enabled) { + if (this->state == TRACE_ENCODER_N_DATA) { + generate_packet(TCODE_PROG_TRACE_CORR); + this->state = TRACE_ENCODER_N_IDLE; + this->icnt = 0; + } + } } void print_packet(trace_encoder_n_packet_t* packet) { @@ -59,27 +65,35 @@ void print_encoded_packet(uint8_t* buffer, int num_bytes) { void trace_encoder_n::generate_packet(tcode_t tcode) { trace_encoder_n_packet_t packet; int num_bytes; + this->packet_count++; switch (tcode) { case TCODE_PROG_TRACE_SYNC: set_program_trace_sync_packet(&packet); - // print_packet(&packet); + print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); - // print_encoded_packet(this->buffer, num_bytes); + print_encoded_packet(this->buffer, num_bytes); break; case TCODE_DBR: set_direct_branch_packet(&packet); - // print_packet(&packet); + print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); - // print_encoded_packet(this->buffer, num_bytes); + print_encoded_packet(this->buffer, num_bytes); break; case TCODE_IBR: set_indirect_branch_packet(&packet); - // print_packet(&packet); + print_packet(&packet); num_bytes = packet_to_buffer(&packet); fwrite(this->buffer, 1, num_bytes, this->trace_sink); - // print_encoded_packet(this->buffer, num_bytes); + print_encoded_packet(this->buffer, num_bytes); + break; + case TCODE_PROG_TRACE_CORR: + set_program_trace_corr_packet(&packet); + print_packet(&packet); + num_bytes = packet_to_buffer(&packet); + fwrite(this->buffer, 1, num_bytes, this->trace_sink); + print_encoded_packet(this->buffer, num_bytes); break; default: break; @@ -111,21 +125,30 @@ void trace_encoder_n::set_indirect_branch_packet(trace_encoder_n_packet_t* packe this->prev_addr = e_addr; } +void trace_encoder_n::set_program_trace_corr_packet(trace_encoder_n_packet_t* packet) { + packet->tcode = TCODE_PROG_TRACE_CORR; + packet->src = this->src; + packet->icnt = this->icnt; + packet->evcode = this->evcode; +} + // returns the number of bytes written to the buffer int trace_encoder_n::packet_to_buffer(trace_encoder_n_packet_t* packet){ switch (packet->tcode) { case TCODE_PROG_TRACE_SYNC: - return packet_to_buffer_program_trace_sync(packet); + return packet_to_buffer_program_trace_sync_packet(packet); case TCODE_DBR: return packet_to_buffer_direct_branch_packet(packet); case TCODE_IBR: return packet_to_buffer_indirect_branch_packet(packet); + case TCODE_PROG_TRACE_CORR: + return packet_to_buffer_program_trace_corr_packet(packet); default: break; } } -int trace_encoder_n::packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet) { +int trace_encoder_n::packet_to_buffer_program_trace_sync_packet(trace_encoder_n_packet_t* packet) { int msb = find_msb(packet->f_addr); this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; this->buffer[1] = packet->sync << MDO_OFFSET | MSEO_IDLE; @@ -189,6 +212,27 @@ int trace_encoder_n::packet_to_buffer_indirect_branch_packet(trace_encoder_n_pac return u_addr_start + u_addr_num_bytes; } +int trace_encoder_n::packet_to_buffer_program_trace_corr_packet(trace_encoder_n_packet_t* packet) { + int msb = find_msb(packet->icnt); + this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] = packet->evcode << MDO_OFFSET | MSEO_IDLE; + this->buffer[1] |= (packet->icnt & 0b11) << 6; + int num_bytes = 0; + if (msb < 2) { + this->buffer[1] |= MSEO_LAST; + } else { + packet->icnt >>= 2; + msb -= 2; + num_bytes = ceil_div(msb, 6); + for (int iter = 0; iter < num_bytes; iter++) { + this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->icnt >>= 6; + } + this->buffer[2 + num_bytes - 1] |= MSEO_LAST; + } + return 2 + num_bytes; +} + // returns the 0-index of the most significant bit int find_msb(uint64_t x) { if (x == 0) return -1; diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index 0ff3e43175..d205e531fd 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -32,12 +32,17 @@ enum sync_t { SYNC_TRACE_EN = 5, }; +enum evcode_t { + EVCODE_DISA = 4, +}; + struct trace_encoder_n_packet_t { uint8_t size; // 8 bits tcode_t tcode; // 6 bits uint16_t src; // unused for now uint8_t sync; // 4 bit uint8_t b_type; // 2 bits + uint8_t evcode; // 4 bits uint16_t icnt; // 16 bits uint64_t f_addr; // 64 bits uint64_t u_addr; // 64 bits @@ -81,6 +86,7 @@ class trace_encoder_n { this->icnt = 0; this->packet_0 = hart_to_encoder_ingress_t(); // create empty packet this->packet_1 = hart_to_encoder_ingress_t(); // create empty packet + this->packet_count = 0; } void push_commit(hart_to_encoder_ingress_t packet); void generate_packet(tcode_t tcode); @@ -93,6 +99,7 @@ class trace_encoder_n { hart_to_encoder_ingress_t packet_0; // the newer packet hart_to_encoder_ingress_t packet_1; // the older packet + uint64_t packet_count; bool active; bool enabled; @@ -105,11 +112,13 @@ class trace_encoder_n { void set_direct_branch_packet(trace_encoder_n_packet_t* packet); void set_indirect_branch_packet(trace_encoder_n_packet_t* packet); void set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); + void set_program_trace_corr_packet(trace_encoder_n_packet_t* packet); int packet_to_buffer(trace_encoder_n_packet_t* packet); - int packet_to_buffer_program_trace_sync(trace_encoder_n_packet_t* packet); + int packet_to_buffer_program_trace_sync_packet(trace_encoder_n_packet_t* packet); int packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet); int packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet); + int packet_to_buffer_program_trace_corr_packet(trace_encoder_n_packet_t* packet); }; From dac6f34b6ed5c0fe6ea8e24ff8cc55b560163076 Mon Sep 17 00:00:00 2001 From: Lux Date: Mon, 7 Oct 2024 14:20:24 -0700 Subject: [PATCH 18/19] ADD: add timestamps --- riscv/execute.cc | 1 + riscv/trace_encoder_n.cc | 65 +++++++++++++++++++++++++++++++++------- riscv/trace_encoder_n.h | 5 ++-- riscv/trace_ingress.h | 2 ++ 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index 7a6815782b..e972aa38a5 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -187,6 +187,7 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f .i_addr = pc, .iretire = 1, .ilastsize = insn_length(fetch.insn.bits())/2, + .i_timestamp = p->get_state()->mcycle->read(), }; p->trace_encoder.push_commit(packet); } diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index 67fd90f5e6..bade4e1bff 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -107,12 +107,16 @@ void trace_encoder_n::set_program_trace_sync_packet(trace_encoder_n_packet_t* pa packet->icnt = 0; packet->f_addr = this->packet_0.i_addr >> 1; this->prev_addr = packet->f_addr; + packet->tstamp = this->packet_0.i_timestamp; + this->prev_timestamp = this->packet_0.i_timestamp; } void trace_encoder_n::set_direct_branch_packet(trace_encoder_n_packet_t* packet){ packet->tcode = TCODE_DBR; packet->src = this->src; packet->icnt = this->icnt - this->packet_0.ilastsize; + packet->tstamp = this->packet_1.i_timestamp; + this->prev_timestamp = this->packet_1.i_timestamp; } void trace_encoder_n::set_indirect_branch_packet(trace_encoder_n_packet_t* packet){ @@ -123,13 +127,17 @@ void trace_encoder_n::set_indirect_branch_packet(trace_encoder_n_packet_t* packe uint64_t e_addr = this->packet_0.i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; this->prev_addr = e_addr; + packet->tstamp = this->packet_1.i_timestamp; + this->prev_timestamp = this->packet_1.i_timestamp; } void trace_encoder_n::set_program_trace_corr_packet(trace_encoder_n_packet_t* packet) { packet->tcode = TCODE_PROG_TRACE_CORR; packet->src = this->src; packet->icnt = this->icnt; - packet->evcode = this->evcode; + packet->evcode = EVCODE_DISA; + packet->tstamp = this->packet_1.i_timestamp; + this->prev_timestamp = this->packet_1.i_timestamp; } // returns the number of bytes written to the buffer @@ -151,11 +159,13 @@ int trace_encoder_n::packet_to_buffer(trace_encoder_n_packet_t* packet){ int trace_encoder_n::packet_to_buffer_program_trace_sync_packet(trace_encoder_n_packet_t* packet) { int msb = find_msb(packet->f_addr); this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; + // handling sync this->buffer[1] = packet->sync << MDO_OFFSET | MSEO_IDLE; + // handling f_addr this->buffer[1] |= (packet->f_addr & 0b11) << 6; int num_bytes = 0; if (msb < 2) { - this->buffer[1] |= MSEO_LAST; + this->buffer[1] |= MSEO_EOF; } else { packet->f_addr >>= 2; msb -= 2; @@ -164,21 +174,38 @@ int trace_encoder_n::packet_to_buffer_program_trace_sync_packet(trace_encoder_n_ this->buffer[2 + iter] = ((packet->f_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; packet->f_addr >>= 6; } - this->buffer[2 + num_bytes - 1] |= MSEO_LAST; + this->buffer[2 + num_bytes - 1] |= MSEO_EOF; + } + // handling tstamp + int tmsb = find_msb(packet->tstamp); + int tnum_bytes = ceil_div(tmsb, 6); + for (int iter = 0; iter < tnum_bytes; iter++) { + this->buffer[2 + num_bytes + iter] = ((packet->tstamp & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->tstamp >>= 6; } - return 2 + num_bytes; + this->buffer[2 + num_bytes + tnum_bytes - 1] |= MSEO_LAST; + return 2 + num_bytes + tnum_bytes; } int trace_encoder_n::packet_to_buffer_direct_branch_packet(trace_encoder_n_packet_t* packet) { this->buffer[0] = packet->tcode << MDO_OFFSET | MSEO_IDLE; int msb = find_msb(packet->icnt); int num_bytes = ceil_div(msb, 6); + // handling icnt for (int iter = 0; iter < num_bytes; iter++) { this->buffer[1 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; packet->icnt >>= 6; } - this->buffer[1 + num_bytes - 1] |= MSEO_LAST; - return 1 + num_bytes; + this->buffer[1 + num_bytes - 1] |= MSEO_EOF; + // handling tstamp + int tmsb = find_msb(packet->tstamp); + int tnum_bytes = ceil_div(tmsb, 6); + for (int iter = 0; iter < tnum_bytes; iter++) { + this->buffer[1 + num_bytes + iter] = ((packet->tstamp & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->tstamp >>= 6; + } + this->buffer[1 + num_bytes + tnum_bytes - 1] |= MSEO_LAST; + return 1 + num_bytes + tnum_bytes; } int trace_encoder_n::packet_to_buffer_indirect_branch_packet(trace_encoder_n_packet_t* packet) { @@ -208,8 +235,16 @@ int trace_encoder_n::packet_to_buffer_indirect_branch_packet(trace_encoder_n_pac this->buffer[u_addr_start + iter] = ((packet->u_addr & 0x3F) << MDO_OFFSET) | MSEO_IDLE; packet->u_addr >>= 6; } - this->buffer[u_addr_start + u_addr_num_bytes - 1] |= MSEO_LAST; - return u_addr_start + u_addr_num_bytes; + this->buffer[u_addr_start + u_addr_num_bytes - 1] |= MSEO_EOF; + // handling tstamp + int tmsb = find_msb(packet->tstamp); + int tnum_bytes = ceil_div(tmsb, 6); + for (int iter = 0; iter < tnum_bytes; iter++) { + this->buffer[u_addr_start + u_addr_num_bytes + iter] = ((packet->tstamp & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->tstamp >>= 6; + } + this->buffer[u_addr_start + u_addr_num_bytes + tnum_bytes - 1] |= MSEO_LAST; + return u_addr_start + u_addr_num_bytes + tnum_bytes; } int trace_encoder_n::packet_to_buffer_program_trace_corr_packet(trace_encoder_n_packet_t* packet) { @@ -219,7 +254,7 @@ int trace_encoder_n::packet_to_buffer_program_trace_corr_packet(trace_encoder_n_ this->buffer[1] |= (packet->icnt & 0b11) << 6; int num_bytes = 0; if (msb < 2) { - this->buffer[1] |= MSEO_LAST; + this->buffer[1] |= MSEO_EOF; } else { packet->icnt >>= 2; msb -= 2; @@ -228,9 +263,17 @@ int trace_encoder_n::packet_to_buffer_program_trace_corr_packet(trace_encoder_n_ this->buffer[2 + iter] = ((packet->icnt & 0x3F) << MDO_OFFSET) | MSEO_IDLE; packet->icnt >>= 6; } - this->buffer[2 + num_bytes - 1] |= MSEO_LAST; + this->buffer[2 + num_bytes - 1] |= MSEO_EOF; + } + // handling tstamp + int tmsb = find_msb(packet->tstamp); + int tnum_bytes = ceil_div(tmsb, 6); + for (int iter = 0; iter < tnum_bytes; iter++) { + this->buffer[2 + num_bytes + iter] = ((packet->tstamp & 0x3F) << MDO_OFFSET) | MSEO_IDLE; + packet->tstamp >>= 6; } - return 2 + num_bytes; + this->buffer[2 + num_bytes + tnum_bytes - 1] |= MSEO_LAST; + return 2 + num_bytes + tnum_bytes; } // returns the 0-index of the most significant bit diff --git a/riscv/trace_encoder_n.h b/riscv/trace_encoder_n.h index d205e531fd..25e49af536 100644 --- a/riscv/trace_encoder_n.h +++ b/riscv/trace_encoder_n.h @@ -46,7 +46,7 @@ struct trace_encoder_n_packet_t { uint16_t icnt; // 16 bits uint64_t f_addr; // 64 bits uint64_t u_addr; // 64 bits - uint64_t tstamp; // unused for now + uint64_t tstamp; }; void print_packet(trace_encoder_n_packet_t* packet); @@ -108,7 +108,8 @@ class trace_encoder_n { uint8_t buffer[MAX_TRACE_BUFFER_SIZE]; uint16_t icnt; uint64_t prev_addr; - + uint64_t prev_timestamp; + void set_direct_branch_packet(trace_encoder_n_packet_t* packet); void set_indirect_branch_packet(trace_encoder_n_packet_t* packet); void set_program_trace_sync_packet(trace_encoder_n_packet_t* packet); diff --git a/riscv/trace_ingress.h b/riscv/trace_ingress.h index f0a2081df0..fbd8790e2f 100644 --- a/riscv/trace_ingress.h +++ b/riscv/trace_ingress.h @@ -62,6 +62,8 @@ struct hart_to_encoder_ingress_t { bool iretire; // 1 bit // ilastsize int ilastsize; // 2 or 4, 2 bits + // timestamp + uint64_t i_timestamp; // 64 bits }; #define CHECK_INSN(name) ((insn->bits() & MASK_##name) == MATCH_##name) From 8a60abcd383ac9160408e60eee87c2b7a498462f Mon Sep 17 00:00:00 2001 From: Lux Date: Mon, 7 Oct 2024 14:27:34 -0700 Subject: [PATCH 19/19] FIX: use delta compressed timestamp --- riscv/trace_encoder_n.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/trace_encoder_n.cc b/riscv/trace_encoder_n.cc index bade4e1bff..24f919ff63 100644 --- a/riscv/trace_encoder_n.cc +++ b/riscv/trace_encoder_n.cc @@ -115,7 +115,7 @@ void trace_encoder_n::set_direct_branch_packet(trace_encoder_n_packet_t* packet) packet->tcode = TCODE_DBR; packet->src = this->src; packet->icnt = this->icnt - this->packet_0.ilastsize; - packet->tstamp = this->packet_1.i_timestamp; + packet->tstamp = this->packet_1.i_timestamp ^ this->prev_timestamp; this->prev_timestamp = this->packet_1.i_timestamp; } @@ -127,7 +127,7 @@ void trace_encoder_n::set_indirect_branch_packet(trace_encoder_n_packet_t* packe uint64_t e_addr = this->packet_0.i_addr >> 1; packet->u_addr = e_addr ^ this->prev_addr; this->prev_addr = e_addr; - packet->tstamp = this->packet_1.i_timestamp; + packet->tstamp = this->packet_1.i_timestamp ^ this->prev_timestamp; this->prev_timestamp = this->packet_1.i_timestamp; } @@ -136,7 +136,7 @@ void trace_encoder_n::set_program_trace_corr_packet(trace_encoder_n_packet_t* pa packet->src = this->src; packet->icnt = this->icnt; packet->evcode = EVCODE_DISA; - packet->tstamp = this->packet_1.i_timestamp; + packet->tstamp = this->packet_1.i_timestamp ^ this->prev_timestamp; this->prev_timestamp = this->packet_1.i_timestamp; }