Add generation, encoding and sending logic for N-Trace
ProgTraceCorrelation message.

Signed-off-by: Konstantin Semichastnov <[email protected]>
---
 hw/riscv/rv-trace-messages.c | 40 ++++++++++++++++++++++++++++++++++++++++
 hw/riscv/rv-trace-messages.h |  4 ++++
 hw/riscv/trace-encoder.c     | 28 ++++++++++++++++++++++++++++
 hw/riscv/trace-encoder.h     |  8 ++++++++
 4 files changed, 80 insertions(+)

diff --git a/hw/riscv/rv-trace-messages.c b/hw/riscv/rv-trace-messages.c
index 8a9a3c6955..708e48bbed 100644
--- a/hw/riscv/rv-trace-messages.c
+++ b/hw/riscv/rv-trace-messages.c
@@ -359,11 +359,14 @@ typedef enum {
     WIDTH_FADDR  = 63,
     WIDTH_UADDR  = 63,
     WIDTH_HIST   = 32,
+    WIDTH_EVCODE = 4,
+    WIDTH_CDF    = 2,
     WIDTH_RCODE  = 4,
 } NTraceFieldWidth;
 
 typedef enum {
     TCODE_PROG_TRACE_SYNC        = 0x9,
+    TCODE_PROG_TRACE_CORRELATION = 0x21,
     TCODE_RESOURCE_FULL          = 0x1b,
     TCODE_INDIRECT_BRANCH_HIST   = 0x1c,
 } NTraceTcodeFieldValues;
@@ -373,6 +376,10 @@ typedef enum {
     SYNC_TRACE_ENABLED = 5,
 } NTraceSyncFieldValues;
 
+typedef enum {
+    CDF_ICNT_AND_HIST_PRESENT = 1,
+} NTraceCdfFieldValues;
+
 typedef enum {
     RCODE_HIST_PRESENT = 1,
 } NTraceRcodeFieldValues;
@@ -432,6 +439,20 @@ typedef struct NTraceFieldPayload {
         .value = (val),      \
     }
 
+#define PAYLOAD_EVCODE(val)    \
+    {                          \
+        .type = FIELD_FIXED,   \
+        .width = WIDTH_EVCODE, \
+        .value = (val),        \
+    }
+
+#define PAYLOAD_CDF(val)     \
+    {                        \
+        .type = FIELD_FIXED, \
+        .width = WIDTH_CDF,  \
+        .value = (val),      \
+    }
+
 #define PAYLOAD_RCODE(val)    \
     {                         \
         .type = FIELD_FIXED,  \
@@ -531,6 +552,25 @@ size_t rv_ntrace_gen_encoded_prog_trace_sync_msg(uint8_t 
*buf, uint64_t faddr)
     return rv_ntrace_gen_encoded_msg(buf, msg_fields);
 }
 
+size_t rv_ntrace_gen_encoded_prog_trace_correlation_msg(uint8_t *buf,
+                                                        uint32_t evcode,
+                                                        uint32_t icnt,
+                                                        uint32_t hist)
+{
+    const NTraceFieldPayload msg_fields[] = {
+        PAYLOAD_TCODE(TCODE_PROG_TRACE_CORRELATION),
+        /* SRC field is not supported for now */
+        PAYLOAD_EVCODE(evcode),
+        PAYLOAD_CDF(CDF_ICNT_AND_HIST_PRESENT),
+        PAYLOAD_ICNT(icnt),
+        PAYLOAD_HIST(hist),
+        /* TSTAMP field is not supported for now */
+        PAYLOAD_END(),
+    };
+
+    return rv_ntrace_gen_encoded_msg(buf, msg_fields);
+}
+
 size_t rv_ntrace_gen_encoded_resource_full_msg(uint8_t *buf, uint32_t hist)
 {
     const NTraceFieldPayload msg_fields[] = {
diff --git a/hw/riscv/rv-trace-messages.h b/hw/riscv/rv-trace-messages.h
index 7ed8737d14..a4d14de59a 100644
--- a/hw/riscv/rv-trace-messages.h
+++ b/hw/riscv/rv-trace-messages.h
@@ -38,6 +38,10 @@ size_t rv_etrace_gen_encoded_format1(uint8_t *buf,
                                      bool notify, bool updiscon);
 
 size_t rv_ntrace_gen_encoded_prog_trace_sync_msg(uint8_t *buf, uint64_t faddr);
+size_t rv_ntrace_gen_encoded_prog_trace_correlation_msg(uint8_t *buf,
+                                                        uint32_t evcode,
+                                                        uint32_t icnt,
+                                                        uint32_t hist);
 size_t rv_ntrace_gen_encoded_resource_full_msg(uint8_t *buf, uint32_t hist);
 size_t rv_ntrace_gen_indirect_branch_hist_msg(uint8_t *buf, uint8_t btype,
                                               uint32_t icnt, uint64_t uaddr,
diff --git a/hw/riscv/trace-encoder.c b/hw/riscv/trace-encoder.c
index 302458bfba..c36d205f50 100644
--- a/hw/riscv/trace-encoder.c
+++ b/hw/riscv/trace-encoder.c
@@ -259,6 +259,16 @@ static void trencoder_te_ctrl_postw(RegisterInfo *reg, 
uint64_t val)
     RISCVCPU *cpu = te->cpu;
     CPURISCVState *env = &cpu->env;
 
+
+    if (te->ntrace && te->enabled) {
+        if (!trTeActive || !trTeEnable || !trTeInstTracing) {
+            uint32_t inst_len = get_inst_len_at(env->pc);
+
+            trencoder_send_prog_trace_correlation(OBJECT(te), env->pc, 
inst_len,
+                                                  CORRELATION_TRACE_DISABLED);
+        }
+    }
+
     if (!trTeActive) {
         te->enabled = false;
         te->trace_running = false;
@@ -658,6 +668,24 @@ static uint32_t rv_ntrace_get_and_reset_icnt(TraceEncoder 
*trencoder,
     return icnt;
 }
 
+void trencoder_send_prog_trace_correlation(Object *trencoder_obj, uint64_t pc,
+                                           uint32_t inst_len,
+                                           TraceStopReason evcode)
+{
+    TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj);
+    g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE);
+    uint32_t icnt = rv_ntrace_get_and_reset_icnt(trencoder, pc, inst_len);
+    uint32_t hist = rv_ntrace_encode_and_reset_branch_map(trencoder);
+    uint8_t msg_size;
+
+    g_assert(trencoder->ntrace);
+
+    msg_size = rv_ntrace_gen_encoded_prog_trace_correlation_msg(msg, evcode,
+                                                                icnt, hist);
+
+    trencoder_send_message_smem(trencoder, msg, msg_size);
+}
+
 void trencoder_trace_trap_insn(Object *trencoder_obj, uint64_t curr_pc,
                                uint64_t target_pc, uint32_t ecause,
                                bool is_interrupt, uint64_t tval)
diff --git a/hw/riscv/trace-encoder.h b/hw/riscv/trace-encoder.h
index d1ff813035..55d53c2582 100644
--- a/hw/riscv/trace-encoder.h
+++ b/hw/riscv/trace-encoder.h
@@ -63,12 +63,20 @@ typedef enum {
     BTYPE_INTERRUPT    = 3,
 } TraceBranchType;
 
+typedef enum {
+    CORRELATION_TRACE_DISABLED = 4,
+} TraceStopReason;
+
 #define TYPE_TRACE_ENCODER "trace-encoder"
 
 OBJECT_DECLARE_SIMPLE_TYPE(TraceEncoder, TRACE_ENCODER)
 
 void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc);
 void trencoder_send_prog_trace_sync(Object *trencoder_obj, uint64_t pc);
+void trencoder_send_prog_trace_correlation(Object *trencoder_obj,
+                                           uint64_t pc,
+                                           uint32_t inst_len,
+                                           TraceStopReason evcode);
 void trencoder_send_indirect_branch_hist(TraceEncoder *trencoder,
                                          uint64_t curr_pc,
                                          uint32_t curr_inst_len,

-- 
2.43.0


Reply via email to