Dhrystone tests in Kelvin

Bypass-Presubmit-Reason: Pre existing failure test_kelvin_nexus.
Change-Id: Ie6ec8396cb61abcf5e0ddef23e5986a1151958ee
diff --git a/.bazelrc b/.bazelrc
index a7bbfc0..6485c41 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,6 +1,6 @@
 build --action_env=BAZEL_CXXOPTS="-std=c++17"
 build --cxxopt='-std=c++17'
-build --conlyopt='-std=c11'
+build --conlyopt='-std=gnu11'
 
 # Enable toolchain resolution with cc
 build --incompatible_enable_cc_toolchain_resolution
diff --git a/WORKSPACE b/WORKSPACE
index 859b67b..97abec2 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -13,9 +13,11 @@
 workspace(name = "kelvin_sw")
 
 load("//build_tools/bazel:repos.bzl", "kelvin_sw_repos", "tflm_repos")
+
 kelvin_sw_repos()
 
 # Register Kelvin toolchain
+
 load("//platforms:registration.bzl", "kelvin_register_toolchain")
 
 kelvin_register_toolchain()
@@ -24,12 +26,20 @@
 load("@rules_python//python:repositories.bzl", "py_repositories")
 py_repositories()
 
+load("@rules_python//python:repositories.bzl", "python_register_toolchains")
+python_register_toolchains(
+     name = "python3",
+     python_version = "3.9",
+)
+
 load("@tflite-micro//tensorflow:workspace.bzl", "tf_repositories")
+
 tf_repositories()
 
 load("@rules_python//python:pip.bzl", "pip_parse")
 pip_parse(
     name = "tflm_pip_deps",
+    python_interpreter_target = "@python3_x86_64-unknown-linux-gnu//:python",
     requirements_lock = "@tflite-micro//third_party:python_requirements.txt",
 )
 
diff --git a/build_tools/bazel/repos.bzl b/build_tools/bazel/repos.bzl
index 7b03eb0..b36850f 100644
--- a/build_tools/bazel/repos.bzl
+++ b/build_tools/bazel/repos.bzl
@@ -15,6 +15,7 @@
 """Kelvin dependency repository setup."""
 
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 def kelvin_sw_repos():
@@ -37,18 +38,20 @@
         strip_prefix = "crt-0.3.4",
     )
 
-    # risc-v isa test
-    http_archive(
+    #risc-v isa test
+    git_repository(
         name = "riscv-tests",
         build_file = "@kelvin_sw//third_party/riscv:BUILD.riscv-tests",
-        sha256 = "1c7eb58edd7399b3ad2f9624a2003862cd87a6904237a737f39cd3978bab46a8",
-        urls = ["https://github.com/riscv-software-src/riscv-tests/archive/d4eaa5bd6674b51d3b9b24913713c4638e99cdd9.tar.gz"],
-        strip_prefix = "riscv-tests-d4eaa5bd6674b51d3b9b24913713c4638e99cdd9",
+        remote = "https://github.com/riscv-software-src/riscv-tests",
+        commit = "d4eaa5bd6674b51d3b9b24913713c4638e99cdd9",
+        recursive_init_submodules = True,
         patch_args = [
             "-p1",
         ],
         patches = [
-            "//tests/riscv-tests:0001-mcsr.patch",
+            "@kelvin_sw//tests/riscv-tests:0001-mcsr.patch",
+            "@kelvin_sw//tests/riscv-tests:0002-fixes-for-kelvin.patch",
+            "@kelvin_sw//tests/riscv-tests:0003-dhrystone-test-on-fpga.patch",
         ],
     )
 
diff --git a/tests/riscv-tests/0001-mcsr.patch b/tests/riscv-tests/0001-mcsr.patch
index 0780462..4b2618d 100644
--- a/tests/riscv-tests/0001-mcsr.patch
+++ b/tests/riscv-tests/0001-mcsr.patch
@@ -1,3 +1,12 @@
+From 02e52b6c7e3d35999a6e9bb74d7ee4929d0d1b98 Mon Sep 17 00:00:00 2001
+From: Naveen Dodda <ndodda@google.com>
+Date: Thu, 5 Sep 2024 00:35:43 +0000
+Subject: [PATCH 1/2] mcsr
+
+---
+ isa/rv64mi/mcsr.S | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
 diff --git a/isa/rv64mi/mcsr.S b/isa/rv64mi/mcsr.S
 index 03cf29a..729889f 100644
 --- a/isa/rv64mi/mcsr.S
@@ -15,3 +24,6 @@
  
    # Check that reading the following CSRs doesn't cause an exception
    csrr a0, mimpid
+-- 
+2.46.0.469.g59c65b2a67-goog
+
diff --git a/tests/riscv-tests/0002-fixes-for-kelvin.patch b/tests/riscv-tests/0002-fixes-for-kelvin.patch
new file mode 100644
index 0000000..9b350d8
--- /dev/null
+++ b/tests/riscv-tests/0002-fixes-for-kelvin.patch
@@ -0,0 +1,139 @@
+From da120fa80fa754ec650d4aaea0d5bbc791de6caa Mon Sep 17 00:00:00 2001
+From: Naveen Dodda <ndodda@google.com>
+Date: Thu, 5 Sep 2024 20:16:34 +0000
+Subject: [PATCH 2/2] fixes for kelvin
+
+---
+ benchmarks/Makefile                   | 26 ++++------------------
+ benchmarks/dhrystone/dhrystone.h      |  2 +-
+ benchmarks/dhrystone/dhrystone_main.c | 32 ++++++++++++++++++++++-----
+ 3 files changed, 32 insertions(+), 28 deletions(-)
+
+diff --git a/benchmarks/Makefile b/benchmarks/Makefile
+index fde4f23..849c024 100644
+--- a/benchmarks/Makefile
++++ b/benchmarks/Makefile
+@@ -4,7 +4,7 @@
+ # Yunsup Lee (yunsup@cs.berkeley.edu)
+ #
+ 
+-XLEN ?= 64
++XLEN = 32
+ 
+ default: all
+ 
+@@ -17,33 +17,15 @@ instbasedir = $(UCB_VLSI_HOME)/install
+ # Sources
+ #--------------------------------------------------------------------
+ 
+-bmarks = \
+-	median \
+-	qsort \
+-	rsort \
+-	towers \
+-	vvadd \
+-	memcpy \
+-	multiply \
+-	mm \
+-	dhrystone \
+-	spmv \
+-	mt-vvadd \
+-	mt-matmul \
+-	mt-memcpy \
+-	pmp \
+-	vec-memcpy \
+-	vec-daxpy \
+-	vec-sgemm \
+-	vec-strcmp \
++bmarks = dhrystone
+ 
+ #--------------------------------------------------------------------
+ # Build rules
+ #--------------------------------------------------------------------
+ 
+-RISCV_PREFIX ?= riscv$(XLEN)-unknown-elf-
++RISCV_PREFIX = /opt/riscv2/bin/riscv32-unknown-elf-
+ RISCV_GCC ?= $(RISCV_PREFIX)gcc
+-RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O2 -ffast-math -fno-common -fno-builtin-printf -fno-tree-loop-distribute-patterns -march=rv$(XLEN)gcv -mabi=lp64d
++RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O2 -ffast-math -fno-common -fno-builtin-printf -fno-tree-loop-distribute-patterns -march=rv32i2p1m_zicsr_zifencei_zbb -mabi=ilp32d
+ RISCV_LINK ?= $(RISCV_GCC) -T $(src_dir)/common/test.ld $(incs)
+ RISCV_LINK_OPTS ?= -static -nostdlib -nostartfiles -lm -lgcc -T $(src_dir)/common/test.ld
+ RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data
+diff --git a/benchmarks/dhrystone/dhrystone.h b/benchmarks/dhrystone/dhrystone.h
+index e350c17..3401d65 100644
+--- a/benchmarks/dhrystone/dhrystone.h
++++ b/benchmarks/dhrystone/dhrystone.h
+@@ -381,7 +381,7 @@ extern clock_t	clock();
+ 
+ #elif defined(__riscv)
+ 
+-#define HZ 1000000
++#define HZ 10000000
+ #define Too_Small_Time 1
+ #define CLOCK_TYPE "rdcycle()"
+ #define Start_Timer() Begin_Time = read_csr(mcycle)
+diff --git a/benchmarks/dhrystone/dhrystone_main.c b/benchmarks/dhrystone/dhrystone_main.c
+index 9c7bcf5..c948f0e 100644
+--- a/benchmarks/dhrystone/dhrystone_main.c
++++ b/benchmarks/dhrystone/dhrystone_main.c
+@@ -11,12 +11,32 @@
+ 
+ #include "dhrystone.h"
+ 
+-void debug_printf(const char* str, ...);
+-
++// void debug_printf(const char* str, ...);
++#define debug_printf printf
+ #include "util.h"
+ 
+ #include <alloca.h>
+ 
++#define NUM_COUNTERS 2
++static uintptr_t counters[NUM_COUNTERS];
++static char* counter_names[NUM_COUNTERS];
++
++void setStats(int enable)
++{
++  int i = 0;
++#define READ_CTR(name) do { \
++    while (i >= NUM_COUNTERS) ; \
++    uintptr_t csr = read_csr(name); \
++    if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \
++    counters[i++] = csr; \
++  } while (0)
++
++  READ_CTR(mcycle);
++  READ_CTR(minstret);
++
++#undef READ_CTR
++}
++
+ /* Global Variables: */
+ 
+ Rec_Pointer     Ptr_Glob,
+@@ -171,9 +191,9 @@ int main (int argc, char** argv)
+ 
+     if (User_Time < Too_Small_Time)
+     {
+-      printf("Measured time too small to obtain meaningful results\n");
++      // printf("Measured time too small to obtain meaningful results\n");
+       Number_Of_Runs = Number_Of_Runs * 10;
+-      printf("\n");
++      // printf("\n");
+     } else Done = true;
+   }
+ 
+@@ -231,7 +251,9 @@ int main (int argc, char** argv)
+ 
+   Microseconds = ((User_Time / Number_Of_Runs) * Mic_secs_Per_Second) / HZ;
+   Dhrystones_Per_Second = (HZ * Number_Of_Runs) / User_Time;
+-
++  
++  printf(" Begin time %ld\n", Begin_Time);
++  printf(" End time %ld\n", End_Time);
+   printf("Microseconds for one run through Dhrystone: %ld\n", Microseconds);
+   printf("Dhrystones per Second:                      %ld\n", Dhrystones_Per_Second);
+ 
+-- 
+2.46.0.469.g59c65b2a67-goog
+
diff --git a/tests/riscv-tests/0003-dhrystone-test-on-fpga.patch b/tests/riscv-tests/0003-dhrystone-test-on-fpga.patch
new file mode 100644
index 0000000..bce9943
--- /dev/null
+++ b/tests/riscv-tests/0003-dhrystone-test-on-fpga.patch
@@ -0,0 +1,160 @@
+diff --git a/benchmarks/dhrystone/dhrystone_main.c b/benchmarks/dhrystone/dhrystone_main.c
+index c948f0e..83409ef 100644
+--- a/benchmarks/dhrystone/dhrystone_main.c
++++ b/benchmarks/dhrystone/dhrystone_main.c
+@@ -14,8 +14,10 @@
+ // void debug_printf(const char* str, ...);
+ #define debug_printf printf
+ #include "util.h"
++#include "benchmarks/benchmark.h"
+ 
+ #include <alloca.h>
++#include <stdint.h>
+ 
+ #define NUM_COUNTERS 2
+ static uintptr_t counters[NUM_COUNTERS];
+@@ -69,9 +71,33 @@ long            Begin_Time,
+                 User_Time;
+ long            Microseconds,
+                 Dhrystones_Per_Second;
+-
++uint64_t        start_cycle,
++                end_cycle,
++                cycle_result;
+ /* end of variables for time measurement */
+ 
++__attribute__((
++    section(".model_output_header"))) BenchmarkOutputHeader output_header = {
++    .return_code = 0,  // Set by kelvin_start based on return value in main.
++    .iterations = 0,
++    .cycles = 0,
++};
++
++static inline uint64_t mcycle_read() {
++  uint32_t cycle_low = 0;
++  uint32_t cycle_high = 0;
++  uint32_t cycle_high_2 = 0;
++  uint64_t result = 0;
++  asm volatile(
++      "1:"
++      "  csrr %0, mcycleh;"  // Read `mcycleh`.
++      "  csrr %1, mcycle;"   // Read `mcycle`.
++      "  csrr %2, mcycleh;"  // Read `mcycleh` again.
++      "  bne  %0, %2, 1b;"
++      : "=r"(cycle_high), "=r"(cycle_low), "=r"(cycle_high_2)
++      :);
++  return result << 32 | cycle_low;
++}
+ 
+ int main (int argc, char** argv)
+ /*****/
+@@ -95,6 +121,7 @@ int main (int argc, char** argv)
+ 
+   Next_Ptr_Glob = (Rec_Pointer) alloca (sizeof (Rec_Type));
+   Ptr_Glob = (Rec_Pointer) alloca (sizeof (Rec_Type));
++  
+ 
+   Ptr_Glob->Ptr_Comp                    = Next_Ptr_Glob;
+   Ptr_Glob->Discr                       = Ident_1;
+@@ -133,6 +160,7 @@ int main (int argc, char** argv)
+ 
+     setStats(1);
+     Start_Timer();
++    start_cycle = mcycle_read();
+ 
+     for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
+     {
+@@ -179,6 +207,11 @@ int main (int argc, char** argv)
+ 	/* Int_1_Loc == 5 */
+ 
+     } /* loop "for Run_Index" */
++    
++    end_cycle = mcycle_read();
++
++
++    
+ 
+     /**************/
+     /* Stop timer */
+@@ -195,69 +228,22 @@ int main (int argc, char** argv)
+       Number_Of_Runs = Number_Of_Runs * 10;
+       // printf("\n");
+     } else Done = true;
+-  }
+ 
+-  debug_printf("Final values of the variables used in the benchmark:\n");
+-  debug_printf("\n");
+-  debug_printf("Int_Glob:            %d\n", Int_Glob);
+-  debug_printf("        should be:   %d\n", 5);
+-  debug_printf("Bool_Glob:           %d\n", Bool_Glob);
+-  debug_printf("        should be:   %d\n", 1);
+-  debug_printf("Ch_1_Glob:           %c\n", Ch_1_Glob);
+-  debug_printf("        should be:   %c\n", 'A');
+-  debug_printf("Ch_2_Glob:           %c\n", Ch_2_Glob);
+-  debug_printf("        should be:   %c\n", 'B');
+-  debug_printf("Arr_1_Glob[8]:       %d\n", Arr_1_Glob[8]);
+-  debug_printf("        should be:   %d\n", 7);
+-  debug_printf("Arr_2_Glob[8][7]:    %d\n", Arr_2_Glob[8][7]);
+-  debug_printf("        should be:   Number_Of_Runs + 10\n");
+-  debug_printf("Ptr_Glob->\n");
+-  debug_printf("  Ptr_Comp:          %d\n", (long) Ptr_Glob->Ptr_Comp);
+-  debug_printf("        should be:   (implementation-dependent)\n");
+-  debug_printf("  Discr:             %d\n", Ptr_Glob->Discr);
+-  debug_printf("        should be:   %d\n", 0);
+-  debug_printf("  Enum_Comp:         %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
+-  debug_printf("        should be:   %d\n", 2);
+-  debug_printf("  Int_Comp:          %d\n", Ptr_Glob->variant.var_1.Int_Comp);
+-  debug_printf("        should be:   %d\n", 17);
+-  debug_printf("  Str_Comp:          %s\n", Ptr_Glob->variant.var_1.Str_Comp);
+-  debug_printf("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
+-  debug_printf("Next_Ptr_Glob->\n");
+-  debug_printf("  Ptr_Comp:          %d\n", (long) Next_Ptr_Glob->Ptr_Comp);
+-  debug_printf("        should be:   (implementation-dependent), same as above\n");
+-  debug_printf("  Discr:             %d\n", Next_Ptr_Glob->Discr);
+-  debug_printf("        should be:   %d\n", 0);
+-  debug_printf("  Enum_Comp:         %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
+-  debug_printf("        should be:   %d\n", 1);
+-  debug_printf("  Int_Comp:          %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
+-  debug_printf("        should be:   %d\n", 18);
+-  debug_printf("  Str_Comp:          %s\n",
+-                                Next_Ptr_Glob->variant.var_1.Str_Comp);
+-  debug_printf("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
+-  debug_printf("Int_1_Loc:           %d\n", Int_1_Loc);
+-  debug_printf("        should be:   %d\n", 5);
+-  debug_printf("Int_2_Loc:           %d\n", Int_2_Loc);
+-  debug_printf("        should be:   %d\n", 13);
+-  debug_printf("Int_3_Loc:           %d\n", Int_3_Loc);
+-  debug_printf("        should be:   %d\n", 7);
+-  debug_printf("Enum_Loc:            %d\n", Enum_Loc);
+-  debug_printf("        should be:   %d\n", 1);
+-  debug_printf("Str_1_Loc:           %s\n", Str_1_Loc);
+-  debug_printf("        should be:   DHRYSTONE PROGRAM, 1'ST STRING\n");
+-  debug_printf("Str_2_Loc:           %s\n", Str_2_Loc);
+-  debug_printf("        should be:   DHRYSTONE PROGRAM, 2'ND STRING\n");
+-  debug_printf("\n");
++    cycle_result = end_cycle - start_cycle ;
+ 
++    output_header.iterations = NUMBER_OF_RUNS;
++    output_header.cycles = cycle_result;
++    asm volatile("flushall");
+ 
+-  Microseconds = ((User_Time / Number_Of_Runs) * Mic_secs_Per_Second) / HZ;
+-  Dhrystones_Per_Second = (HZ * Number_Of_Runs) / User_Time;
+-  
+-  printf(" Begin time %ld\n", Begin_Time);
+-  printf(" End time %ld\n", End_Time);
+-  printf("Microseconds for one run through Dhrystone: %ld\n", Microseconds);
+-  printf("Dhrystones per Second:                      %ld\n", Dhrystones_Per_Second);
++    // if this test is running in a simulator
++    uint64_t average_cycles = cycle_result/NUMBER_OF_RUNS;
++    printf("Total Iterations: %ld", output_header.iterations);
++    printf("Total Cycles: %ld ", output_header.cycles);
++    printf("Average Cycles per Iteration: %ld ", average_cycles);
++    printf("========== End Benchmark ==========");
++    return 0;
++  }
+ 
+-  return 0;
+ }
+ 
+ 
diff --git a/tests/riscv-tests/BUILD b/tests/riscv-tests/BUILD
index 23a147b..67338f2 100644
--- a/tests/riscv-tests/BUILD
+++ b/tests/riscv-tests/BUILD
@@ -14,6 +14,7 @@
 
 # Build riscv-tests based on Kelvin linker script and termination condition.
 
+package(default_visibility = ["//visibility:public"])
 load("//build_tools/bazel:kelvin.bzl", "kelvin_test")
 
 cc_library(
@@ -162,6 +163,45 @@
     ],
 )
 
+cc_library(
+    name = "dhrystone_lib",
+    srcs = [
+        "@riscv-tests//:benchmarks/dhrystone/dhrystone.c",
+    ],
+    hdrs = [
+        "@riscv-tests//:benchmarks/dhrystone/dhrystone.h",
+    ],
+    copts = [
+        "-Wno-error",
+        "-Wno-implicit-int",
+        "-Wno-implicit-function-declaration",
+    ],
+)
+
+kelvin_test(
+    name = "rv_dhrystone",
+    srcs = [
+        "@riscv-tests//:benchmarks/dhrystone/dhrystone_main.c",
+    ],
+    hdrs =[
+        "@riscv-tests//:benchmarks/common/util.h",
+        "@riscv-tests//:env/encoding.h",
+    ],
+    deps = [
+        ":dhrystone_lib",
+        "//crt",
+        "//benchmarks:benchmark_header",
+    ],
+    copts = [
+        "-Iexternal/riscv-tests/benchmarks/common",
+        "-Iexternal/riscv-tests/env",
+        "-Wno-error",
+        "-Wno-implicit-int",
+        "-Wno-implicit-function-declaration",
+    ],
+    hw_test_size = "large",
+)
+
 kelvin_test(
     name = "alu",
     srcs = [