Add encoded message helpers to send branch information trace packets.
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
hw/riscv/rv-trace-messages.c | 126 +++++++++++++++++++++++++++++++++++
hw/riscv/rv-trace-messages.h | 7 ++
2 files changed, 133 insertions(+)
diff --git a/hw/riscv/rv-trace-messages.c b/hw/riscv/rv-trace-messages.c
index 3fa70ba81c..a93b0adfc6 100644
--- a/hw/riscv/rv-trace-messages.c
+++ b/hw/riscv/rv-trace-messages.c
@@ -64,6 +64,31 @@ typedef struct RVTraceFormat2Payload {
} RVTraceFormat2Payload;
#define FORMAT2_PAYLOAD_SIZE_64BITS 9
+typedef struct RVTraceFormat1BasePayload {
+ uint8_t format:2;
+ uint8_t branches:5;
+ uint32_t branch_map:31;
+} RVTraceFormat1BasePayload;
+#define FORMAT1_BASE_PAYLOAD_SIZE_64BITS 5
+
+typedef struct RVTraceFormat1Payload {
+ uint8_t format:2;
+ uint8_t branches:5;
+ uint32_t branch_map;
+ uint32_t addressLow;
+ uint32_t addressHigh;
+ uint8_t notify:1;
+ uint8_t updiscon:1;
+ uint8_t irreport:1;
+ uint8_t irdepth:3;
+} RVTraceFormat1Payload;
+
+/*
+ * FORMAT2_PAYLOAD_SIZE_64BITS = 9 plus 5 bits of 'branches',
+ * plus minimal 3 bits of 'branch_map' = 10 bytes.
+ */
+#define FORMAT1_PAYLOAD_MIN_SIZE_64BITS 10
+
static void rv_etrace_write_bits(uint8_t *bytes, uint32_t bit_pos,
uint32_t num_bits, uint32_t val)
{
@@ -245,3 +270,104 @@ size_t rv_etrace_gen_encoded_format2_msg(uint8_t *buf, uint64_t addr,
return HEADER_SIZE + header.length;
}
+
+size_t rv_etrace_gen_encoded_format1_noaddr(uint8_t *buf,
+ uint8_t branches,
+ uint32_t branch_map)
+{
+ RVTraceMessageHeader header = {.flow = 0, .extend = 0,
+ .length = FORMAT1_BASE_PAYLOAD_SIZE_64BITS};
+ RVTraceFormat1BasePayload payload = {.format = 0b01,
+ .branches = branches, .branch_map = branch_map};
+ uint8_t bit_pos;
+
+ rv_etrace_write_header(buf, header);
+ bit_pos = 8;
+
+ rv_etrace_write_bits(buf, bit_pos, 2, payload.format);
+ bit_pos += 2;
+
+ rv_etrace_write_bits(buf, bit_pos, 5, payload.branches);
+ bit_pos += 5;
+
+ rv_etrace_write_bits(buf, bit_pos, 31, payload.branch_map);
+
+ return HEADER_SIZE + header.length;
+}
+
+/*
+ * Same reservations made in the format 2 helper:
+ *
+ * - irreport and irdepth is always == updiscon;
+ *
+ * - return_stack_size_p + call_counter_size_p is hardcoded
+ * to 3 since we don't implement neither ATM.
+ */
+size_t rv_etrace_gen_encoded_format1(uint8_t *buf,
+ uint8_t branches, uint32_t branch_map,
+ uint64_t addr,
+ bool notify, bool updiscon)
+{
+ RVTraceMessageHeader header = {.flow = 0, .extend = 0};
+ RVTraceFormat1Payload payload = {.format = 0b01,
+ .branches = branches,
+ .notify = notify,
+ .updiscon = updiscon};
+ uint8_t payload_size = FORMAT1_PAYLOAD_MIN_SIZE_64BITS;
+ uint8_t branch_map_size = 0;
+ uint8_t bit_pos;
+
+ g_assert(branches < 32);
+
+ if (branches <= 3) {
+ branch_map_size = 3;
+ } else if (branches <= 7) {
+ branch_map_size = 7;
+ payload_size++;
+ } else if (branches <= 15) {
+ branch_map_size = 15;
+ payload_size += 2;
+ } else {
+ branch_map_size = 31;
+ payload_size += 4;
+ }
+
+ header.length = payload_size;
+
+ rv_etrace_write_header(buf, header);
+ bit_pos = 8;
+
+ payload.addressLow = extract64(addr, 0, 32);
+ payload.addressHigh = extract64(addr, 32, 32);
+
+ payload.irreport = updiscon;
+ if (updiscon) {
+ payload.irdepth = 0b111;
+ } else {
+ payload.irdepth = 0;
+ }
+
+ rv_etrace_write_bits(buf, bit_pos, 2, payload.format);
+ bit_pos += 2;
+
+ rv_etrace_write_bits(buf, bit_pos, 5, payload.branches);
+ bit_pos += 5;
+
+ rv_etrace_write_bits(buf, bit_pos, branch_map_size, payload.branch_map);
+ bit_pos += branch_map_size;
+
+ rv_etrace_write_bits(buf, bit_pos, 32, payload.addressLow);
+ bit_pos += 32;
+ rv_etrace_write_bits(buf, bit_pos, 32, payload.addressHigh);
+ bit_pos += 32;
+
+ rv_etrace_write_bits(buf, bit_pos, 1, payload.notify);
+ bit_pos += 1;
+ rv_etrace_write_bits(buf, bit_pos, 1, payload.updiscon);
+ bit_pos += 1;
+ rv_etrace_write_bits(buf, bit_pos, 1, payload.irreport);
+ bit_pos += 1;
+ rv_etrace_write_bits(buf, bit_pos, 3, payload.irdepth);
+
+ return HEADER_SIZE + header.length;
+}
diff --git a/hw/riscv/rv-trace-messages.h b/hw/riscv/rv-trace-messages.h
index 50a4a0ef19..2b371641a4 100644
--- a/hw/riscv/rv-trace-messages.h
+++ b/hw/riscv/rv-trace-messages.h
@@ -28,5 +28,12 @@ size_t rv_etrace_gen_encoded_trap_msg(uint8_t *buf, uint64_t trap_addr,
uint64_t tval);
size_t rv_etrace_gen_encoded_format2_msg(uint8_t *buf, uint64_t addr,
bool notify, bool updiscon);
+size_t rv_etrace_gen_encoded_format1_noaddr(uint8_t *buf,
+ uint8_t branches,
+ uint32_t branch_map);
+size_t rv_etrace_gen_encoded_format1(uint8_t *buf,
+ uint8_t branches, uint32_t branch_map,
+ uint64_t addr,
+ bool notify, bool updiscon);
#endif
--
2.51.1