Add encoded message helpers to send branch information trace packets.

Signed-off-by: Daniel Henrique Barboza <[email protected]>
---
 hw/riscv/rv-trace-messages.c | 110 +++++++++++++++++++++++++++++++++++
 hw/riscv/rv-trace-messages.h |   7 +++
 2 files changed, 117 insertions(+)

diff --git a/hw/riscv/rv-trace-messages.c b/hw/riscv/rv-trace-messages.c
index 2f041aa639..7deaf25060 100644
--- a/hw/riscv/rv-trace-messages.c
+++ b/hw/riscv/rv-trace-messages.c
@@ -20,6 +20,8 @@ typedef enum {
     SYNC_PAYLOAD_SIZE_64BITS = 9,
     TRAP_PAYLOAD_SIZE_64BITS = 18,
     FORMAT2_PAYLOAD_SIZE_64BITS = 9,
+    FORMAT1_BASE_PAYLOAD_SIZE_64BITS = 5,
+    FORMAT1_PAYLOAD_MIN_SIZE_64BITS  = 10,
 } RVTraceMessagePayloadSize;
 
 typedef struct RVTraceMessageHeader {
@@ -67,6 +69,28 @@ typedef struct RVTraceFormat2Payload {
     uint8_t irdepth:3;
 } RVTraceFormat2Payload;
 
+typedef struct RVTraceFormat1BasePayload {
+    uint8_t format:2;
+    uint8_t branches:5;
+    uint32_t branch_map:31;
+} RVTraceFormat1BasePayload;
+
+/*
+ * FORMAT2_PAYLOAD_SIZE_64BITS = 9 plus 5 bits of 'branches',
+ * plus minimal 3 bits of 'branch_map' = 10 bytes.
+ */
+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;
+
 static uint8_t rv_etrace_write_bits(uint8_t *bytes, uint32_t bit_pos,
                                     uint32_t num_bits, uint32_t val)
 {
@@ -228,3 +252,89 @@ 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 = 0;
+
+    bit_pos += rv_etrace_write_header(buf, header);
+
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 2, payload.format);
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 5, payload.branches);
+    bit_pos += 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,
+                                     .addressLow = extract64(addr, 0, 32),
+                                     .addressHigh = extract64(addr, 32, 32)};
+    uint8_t payload_size = FORMAT1_PAYLOAD_MIN_SIZE_64BITS;
+    uint8_t branch_map_size = 0;
+    uint8_t bit_pos = 0;
+
+    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;
+
+    bit_pos += rv_etrace_write_header(buf, header);
+
+    payload.irreport = updiscon;
+    if (updiscon) {
+        payload.irdepth = 0b111;
+    } else {
+        payload.irdepth = 0;
+    }
+
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 2, payload.format);
+
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 5, payload.branches);
+
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, branch_map_size, 
payload.branch_map);
+
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 32, payload.addressLow);
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 32, payload.addressHigh);
+
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 1, payload.notify);
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 1, payload.updiscon);
+    bit_pos += rv_etrace_write_bits(buf, bit_pos, 1, payload.irreport);
+    bit_pos += 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 89f30e7d36..f8f1830852 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


Reply via email to