summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMegan Wachs <megan@sifive.com>2017-03-01 12:12:05 -0800
committerMegan Wachs <megan@sifive.com>2017-03-01 12:12:05 -0800
commit7e9363b050a0eb593e83c16a288a4b08664b93ce (patch)
treedfaa6fccb78e7aefa914dc27ee6a671a26ceee79
parentb7c778c4e0b26e719226053a204142c0cb54dd4b (diff)
Add a 'performance counters' demo.
-rw-r--r--software/performance_counters/Makefile6
-rw-r--r--software/performance_counters/performance_counters.c111
2 files changed, 117 insertions, 0 deletions
diff --git a/software/performance_counters/Makefile b/software/performance_counters/Makefile
new file mode 100644
index 0000000..eb3e8f1
--- /dev/null
+++ b/software/performance_counters/Makefile
@@ -0,0 +1,6 @@
+TARGET = performance_counters
+C_SRCS += performance_counters.c
+CFLAGS += -O2 -fno-builtin-printf
+
+BSP_BASE = ../../bsp
+include $(BSP_BASE)/env/common.mk
diff --git a/software/performance_counters/performance_counters.c b/software/performance_counters/performance_counters.c
new file mode 100644
index 0000000..e7c12a3
--- /dev/null
+++ b/software/performance_counters/performance_counters.c
@@ -0,0 +1,111 @@
+// See LICENSE for license details.
+
+// This demo shows how to use basic
+// RISC-V profiling counters, mcycle
+// (counts the number of processor cycles)
+// and minstret (counts the number of retired instructions).
+// Note that both are writable as well.
+
+#include <stdio.h>
+
+// The CSR encodings are in this header.
+#include "encoding.h"
+
+// The mcycle counter is 64-bit counter, but since
+// Freedom E platforms use RV32, we must access it as
+// 2 32-bit registers. At 256MHz, the lower bits will
+// roll over approx. every 5 seconds, so we check for
+// rollover with this routine as suggested by the
+// RISC-V Priviledged Architecture Specification.
+
+#define rdmcycle(x) { \
+ uint32_t lo, hi, hi2; \
+ __asm__ __volatile__ ("1:\n\t" \
+ "csrr %0, mcycleh\n\t" \
+ "csrr %1, mcycle\n\t" \
+ "csrr %2, mcycleh\n\t" \
+ "bne %0, %2, 1b\n\t" \
+ : "=r" (hi), "=r" (lo), "=r" (hi2)) ; \
+ *(x) = lo | ((uint64_t) hi << 32); \
+ }
+
+
+// The minstret counter is 64-bit counter, but
+// Freedom E platforms use RV32, we must access it as
+// 2 32-bit registers, same as for mcycle.
+
+#define rdminstret(x) { \
+ uint32_t lo, hi, hi2; \
+ __asm__ __volatile__ ("1:\n\t" \
+ "csrr %0, minstreth\n\t" \
+ "csrr %1, minstret\n\t" \
+ "csrr %2, minstreth\n\t" \
+ "bne %0, %2, 1b\n\t" \
+ : "=r" (hi), "=r" (lo), "=r" (hi2)) ; \
+ *(x) = lo | ((uint64_t) hi << 32); \
+ }
+
+// Simple program to measure the performance of.
+
+int factorial(int i){
+
+ int result = 1;
+ for (int ii = 1; ii <= i; ii++) {
+ result = result * i;
+ }
+
+ return result;
+
+}
+
+
+int main()
+{
+
+ uint64_t before_cycle;
+ uint64_t before_instret;
+
+ uint64_t after_cycle;
+ uint64_t after_instret;
+
+ printf("\n\nDemo 1: Using Counter Differences.\n");
+
+ for (int ii = 0; ii < 3; ii++){
+ rdmcycle(&before_cycle);
+ rdminstret(&before_instret);
+
+ volatile int result = factorial (100);
+
+ rdmcycle(&after_cycle);
+ rdminstret(&after_instret);
+
+ printf("Loop %d: Retired %d instructions in %d cycles\n",
+ ii,
+ (uint32_t)(after_instret - before_instret),
+ (uint32_t)(after_cycle - before_cycle));
+ }
+
+ printf("\n\nDemo 2: Clearing Counters, Using Values Directly.\n");
+
+ for (int ii = 0; ii < 3; ii++){
+
+ write_csr(mcycle, 0);
+ write_csr(mcycleh, 0);
+ write_csr(minstret, 0);
+ write_csr(minstreth, 0);
+
+ volatile int result = factorial (100);
+
+ rdmcycle(&after_cycle);
+ rdminstret(&after_instret);
+
+ printf("Loop %d: Retired %d instructions in %d cycles\n",
+ ii,
+ (uint32_t)(after_instret),
+ (uint32_t)(after_cycle));
+
+ }
+
+ return 0;
+
+}