util: Enable using different call types in the gem5 ops java wrapper.
authorGabe Black <gabe.black@gmail.com>
Fri, 23 Oct 2020 03:01:05 +0000 (20:01 -0700)
committerGabe Black <gabe.black@gmail.com>
Mon, 21 Dec 2020 23:47:22 +0000 (23:47 +0000)
Convert the native implementation from C to C++. Also expand the test to
cycle through the different call mechanisms and call "sum" using each
one. This test should primarily be run on a gem5 native CPU which will
support all call types.

To access a particular call type, get an instance of the gem5.Ops class
from the callTypes static map, using the name of the call type you want
as the key. If you just want whatever the default is, use the additional
key "default".

Change-Id: If4ef812c9746fbf974e54cc9fe515e2b581e9939
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28182
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
util/m5/README.md
util/m5/SConstruct
util/m5/src/SConscript
util/m5/src/java/gem5/Ops.java
util/m5/src/java/gem5/OpsTest.java
util/m5/src/java/gem5/ops.c [deleted file]
util/m5/src/java/gem5/ops.cc [new file with mode: 0644]

index 7d2d66bfd5db8cd6c1281ec1ead864b15c9e729e..b9ccbff557d8f6bc888ad00b0f4bb2d0e322c06d 100644 (file)
@@ -345,15 +345,22 @@ library only if that trigger mechanism is supported for that ABI.
 
 # Java jar
 
-In your java source, import the gem5Op class which will have methods for
-calling each of the gem5 operations. The .so library will be loaded
-automatically.
+In your java source, import the gem5Op class.
 
-```shell
+```java
 import gem5.Ops
 ```
 
-These methods will all use the magic instruction based trigger mechanism.
+This class provides a static map named callTypes which map from each of the
+call type names ("addr", "inst", or "semi") to an Ops instance. That instance
+will provide a set of methods which trigger each of the gem5 operations using
+the requested trigger mechanism. The call type "default" maps to whatever the
+default call type is for the current ABI.
+
+```shell
+gem5.Ops gem5_ops = gem5.Ops.callTypes.get("default");
+long sum = gem5_ops.sum(1, 2, 3, 4, 5, 6);
+```
 
 
 
index 63143a806c170727f1b30514de6873cda17ec117..242bbe7c3f98cc1905cc53a704e454e32e9a36cd 100644 (file)
@@ -39,6 +39,8 @@ googletest_dir = ext_dir.Dir('googletest')
 src_dir = Dir('src')
 build_dir = Dir('build')
 
+main.SConsignFile(build_dir.File("sconsign").abspath)
+
 def abspath(d):
     return os.path.abspath(str(d))
 
index 5eabcc399f4cea587e052265dc50324c7e21329d..b3e057c7f8dc4bb9294066ebea06e9fbda5c970d 100644 (file)
@@ -37,7 +37,7 @@ m5 = 'm5.cc'
 m5_mmap = 'm5_mmap.c'
 usage = 'usage.cc'
 
-jni = 'java/gem5/ops.c'
+jni = 'java/gem5/ops.cc'
 lua = 'lua_gem5Op.cc'
 
 all_call_types = list(env['CALL_TYPE'].values())
@@ -117,6 +117,11 @@ if env['HAVE_JAVA']:
                      OUT=Dir('out').Dir('java'), JAVA_DIR=Dir('java'))
     # Set include paths to the C headers from the JDK which scons found for us.
     java_env.Append(CPPPATH='${JAVAINCLUDES}')
+    for ct in all_call_types:
+        if ct.default:
+            java_env.Append(CXXFLAGS=[ '-DCALL_TYPE_DEFAULT=%s' % ct.name ])
+        java_env.Append(CXXFLAGS=[ '-DCALL_TYPE_%s_ENABLED=%s' %
+                                   (ct.name, '1' if ct.enabled else '0') ])
     java_env.SharedLibrary('out/java/gem5Ops',
                            [ jni ] + m5op_shared + m5_mmap_shared)
 
index cc92505dda5754c775da1c4f73d41fd88524b376..44afad9765d96e0f634a1afd17b80e84dfd3b8ad 100644 (file)
 
 package gem5;
 
+import java.util.*;
+
 /**
  * Java class to implement JNI for m5Ops
  */
 
 public class Ops {
+    private Ops() {}
+
+    private static native void setupCallTypes();
+    private long dispatchTablePtr;
+
+    private static Map<String, Ops> _callTypes;
+    public static final Map<String, Ops> callTypes;
+
     static {
         System.loadLibrary("gem5Ops");
+        setupCallTypes();
+        callTypes = Collections.unmodifiableMap(_callTypes);
     }
 
     public native void arm(long address);
@@ -73,5 +85,4 @@ public class Ops {
     public native void panic();
     public native void work_begin(long workid, long threadid);
     public native void work_end(long workid, long threadid);
-
 }
index 6e855c9298696a602e2a580dfcbd4c2228cbebeb..5678ecdc8ac7c7bd9ac36d496d8c19b181696783 100644 (file)
@@ -34,15 +34,25 @@ import org.junit.runner.JUnitCore;
 import org.junit.runner.Result;
 import org.junit.runner.notification.Failure;
 
+import java.util.Random;
+import java.util.Map;
+
 import gem5.Ops;
 
 public class OpsTest {
 
     @Test
     public void m5SumShouldReturnSum() {
-        gem5.Ops gem5_ops = new gem5.Ops();
+        Random rand = new Random();
+
+        gem5.Ops gem5_ops = gem5.Ops.callTypes.get("default");
 
-        long a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;
+        long a = rand.nextInt(1000);
+        long b = rand.nextInt(1000);
+        long c = rand.nextInt(1000);
+        long d = rand.nextInt(1000);
+        long e = rand.nextInt(1000);
+        long f = rand.nextInt(1000);
 
         long sum = gem5_ops.sum(a, b, c, d, e, f);
         assertEquals(a + b + c + d + e + f, sum);
diff --git a/util/m5/src/java/gem5/ops.c b/util/m5/src/java/gem5/ops.c
deleted file mode 100644 (file)
index c3f9328..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2010 ARM Limited
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder.  You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdint.h>
-
-#include "gem5/m5ops.h"
-#include "java/gem5_Ops.h"
-
-/*
- * C library interface for gem5Op JNI
- */
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_arm(JNIEnv *env, jobject obj, jlong j_address)
-{
-    m5_arm(j_address);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_quiesce(JNIEnv *env, jobject obj)
-{
-    m5_quiesce();
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_quiesce_1ns(JNIEnv *env, jobject obj, jlong j_ns)
-{
-    m5_quiesce_ns(j_ns);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_quiesce_1cycle(JNIEnv *env, jobject obj, jlong j_cycles)
-{
-    m5_quiesce_cycle(j_cycles);
-}
-
-JNIEXPORT jlong JNICALL
-Java_gem5_Ops_quiesce_1time(JNIEnv *env, jobject obj)
-{
-    uint64_t time = m5_quiesce_time();
-    if (time & 0x8000000000000000ULL)
-        printf("Truncated return value from quiesceTime() to 63 bits\n");
-    return (time & 0x7FFFFFFFFFFFFFFFULL);
-}
-
-JNIEXPORT jlong JNICALL
-Java_gem5_Ops_rpns(JNIEnv *env, jobject obj)
-{
-    uint64_t time = m5_rpns();
-    if (time & 0x8000000000000000ULL)
-        printf("Truncated return value from rpns() to 63 bits\n");
-    return (time & 0x7FFFFFFFFFFFFFFFULL);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_wake_1cpu(JNIEnv *env, jobject obj, jlong j_cpuid)
-{
-    m5_wake_cpu(j_cpuid);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_exit(JNIEnv *env, jobject obj, jlong j_ns_delay)
-{
-    m5_exit(j_ns_delay);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_fail(JNIEnv *env, jobject obj, jlong j_ns_delay, jlong j_code)
-{
-    m5_fail(j_ns_delay, j_code);
-}
-
-JNIEXPORT jlong JNICALL
-Java_gem5_Ops_sum(JNIEnv *env, jobject obj, jlong a, jlong b, jlong c,
-                    jlong d, jlong e, jlong f)
-{
-    uint64_t result = m5_sum(a, b, c, d, e, f);
-    if (result & 0x8000000000000000ULL)
-        printf("Truncated return value from sum() to 63 bits\n");
-    return (result & 0x7FFFFFFFFFFFFFFFULL);
-}
-
-JNIEXPORT jlong JNICALL
-Java_gem5_Ops_init_1param(JNIEnv *env, jobject obj, jlong j_key_str1,
-                           jlong j_key_str2)
-{
-    uint64_t param = m5_init_param(j_key_str1, j_key_str2);
-    if (param & 0x8000000000000000ULL)
-        printf("Truncated return value from m_initparam() to 63 bits\n");
-    return (param & 0x7FFFFFFFFFFFFFFFULL);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_checkpoint(JNIEnv *env, jobject obj,
-                           jlong j_ns_delay, jlong j_ns_period)
-{
-    m5_checkpoint(j_ns_delay, j_ns_period);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_reset_1stats(JNIEnv *env, jobject obj,
-                             jlong j_ns_delay, jlong j_ns_period)
-{
-    m5_reset_stats(j_ns_delay, j_ns_period);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_dump_1stats(JNIEnv *env, jobject obj,
-                            jlong j_ns_delay, jlong j_ns_period)
-{
-    m5_dump_stats(j_ns_delay, j_ns_period);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_dump_1reset_1stats(JNIEnv *env, jobject obj,
-                                  jlong j_ns_delay, jlong j_ns_period)
-{
-    m5_dump_reset_stats(j_ns_delay, j_ns_period);
-}
-
-JNIEXPORT jlong JNICALL
-Java_gem5_Ops_read_1file(JNIEnv *env, jobject obj,
-                           jbyteArray j_buffer, jlong j_len, jlong j_offset)
-{
-    jbyte *buffer = (*env)->GetByteArrayElements(env, j_buffer, 0);
-
-    uint64_t result = m5_read_file(buffer, j_len, j_offset);
-
-    (*env)->ReleaseByteArrayElements(env, j_buffer, buffer, JNI_ABORT);
-    return (result & 0x7FFFFFFFFFFFFFFFULL);
-}
-
-JNIEXPORT jlong JNICALL
-Java_gem5_Ops_write_1file(JNIEnv *env, jobject obj,
-                            jbyteArray j_buffer, jlong j_len, jlong j_offset,
-                            jstring j_filename)
-{
-    jbyte *buffer = (*env)->GetByteArrayElements(env, j_buffer, 0);
-    const char *filename = (*env)->GetStringUTFChars(env, j_filename, NULL);
-
-    uint64_t result = m5_write_file(buffer, j_len, j_offset, filename);
-
-    (*env)->ReleaseStringUTFChars(env, j_filename, filename);
-    (*env)->ReleaseByteArrayElements(env, j_buffer, buffer, JNI_ABORT);
-    return (result & 0x7FFFFFFFFFFFFFFFULL);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_debug_1break(JNIEnv *env, jobject obj)
-{
-    m5_debug_break();
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_switch_1cpu (JNIEnv *env, jobject obj)
-{
-    m5_switch_cpu();
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_dist_1toggle_1sync(JNIEnv *env, jobject obj)
-{
-    m5_dist_toggle_sync();
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_add_symbol(JNIEnv *env, jobject obj,
-        jlong j_addr, jstring j_symbol)
-{
-    const char *symbol = (*env)->GetStringUTFChars(env, j_symbol, NULL);
-
-    m5_add_symbol(j_addr, symbol);
-
-    (*env)->ReleaseStringUTFChars(env, j_symbol, symbol);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_load_1symbol(JNIEnv *env, jobject obj)
-{
-    m5_load_symbol();
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_panic(JNIEnv *env, jobject obj)
-{
-    m5_panic();
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_work_1begin(JNIEnv *env, jobject obj,
-                            jlong j_workid, jlong j_threadid)
-{
-    m5_work_begin(j_workid, j_threadid);
-}
-
-JNIEXPORT void JNICALL
-Java_gem5_Ops_work_1end(JNIEnv *env, jobject obj,
-                          jlong j_workid, jlong j_threadid)
-{
-    m5_work_end(j_workid, j_threadid);
-}
-
diff --git a/util/m5/src/java/gem5/ops.cc b/util/m5/src/java/gem5/ops.cc
new file mode 100644 (file)
index 0000000..c1f36e4
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include <string>
+
+#include "call_type/addr_dt.hh"
+#include "call_type/inst_dt.hh"
+#include "call_type/semi_dt.hh"
+#include "gem5/m5ops.h"
+#include "java/gem5_Ops.h"
+
+#define _stringify(x) #x
+#define stringify(x) _stringify(x)
+
+struct JavaCallType
+{
+    const std::string name;
+    DispatchTable *dt;
+};
+
+JavaCallType java_call_types[] = {
+#if CALL_TYPE_addr_ENABLED
+    { "addr", &addr_dispatch },
+#endif
+#if CALL_TYPE_inst_ENABLED
+    { "inst", &inst_dispatch },
+#endif
+#if CALL_TYPE_semi_ENABLED
+    { "semi", &semi_dispatch },
+#endif
+};
+
+/*
+ * C library interface for gem5Op JNI
+ */
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_setupCallTypes(JNIEnv *env, jclass clazz)
+{
+    jclass map_class = env->FindClass("java/util/HashMap");
+    jmethodID map_constr_id = env->GetMethodID(map_class, "<init>", "()V");
+    jobject map = env->NewObject(map_class, map_constr_id);
+
+    jfieldID map_field_id = env->GetStaticFieldID(
+            clazz, "_callTypes", "Ljava/util/Map;");
+    env->SetStaticObjectField(clazz, map_field_id, map);
+
+    jmethodID map_put_id = env->GetMethodID(map_class, "put",
+            "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+    jmethodID ops_constr_id = env->GetMethodID(clazz, "<init>", "()V");
+    jfieldID ptr_field_id = env->GetFieldID(clazz, "dispatchTablePtr", "J");
+
+    for (const auto &ct: java_call_types) {
+        jobject ops = env->NewObject(clazz, ops_constr_id);
+        env->SetLongField(ops, ptr_field_id, (int64_t)(intptr_t)ct.dt);
+
+        jstring name = env->NewStringUTF(ct.name.c_str());
+
+        env->CallObjectMethod(map, map_put_id, name, ops);
+
+        if (ct.name == stringify(CALL_TYPE_DEFAULT)) {
+            jstring default_name = env->NewStringUTF("default");
+            env->CallObjectMethod(map, map_put_id, default_name, ops);
+            env->DeleteLocalRef(default_name);
+        }
+
+        env->DeleteLocalRef(name);
+        env->DeleteLocalRef(ops);
+    }
+
+    env->DeleteLocalRef(map);
+}
+
+static DispatchTable *
+getDispatchTable(JNIEnv *env, jobject obj)
+{
+    jclass clazz = env->GetObjectClass(obj);
+    jfieldID ptr_field_id = env->GetFieldID(clazz, "dispatchTablePtr", "J");
+    return (DispatchTable *)(intptr_t)(env->GetLongField(obj, ptr_field_id));
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_arm(JNIEnv *env, jobject obj, jlong j_address)
+{
+    getDispatchTable(env, obj)->m5_arm(j_address);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_quiesce(JNIEnv *env, jobject obj)
+{
+    getDispatchTable(env, obj)->m5_quiesce();
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_quiesce_1ns(JNIEnv *env, jobject obj, jlong j_ns)
+{
+    getDispatchTable(env, obj)->m5_quiesce_ns(j_ns);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_quiesce_1cycle(JNIEnv *env, jobject obj, jlong j_cycles)
+{
+    getDispatchTable(env, obj)->m5_quiesce_cycle(j_cycles);
+}
+
+JNIEXPORT jlong JNICALL
+Java_gem5_Ops_quiesce_1time(JNIEnv *env, jobject obj)
+{
+    uint64_t time = getDispatchTable(env, obj)->m5_quiesce_time();
+    if (time & 0x8000000000000000ULL)
+        printf("Truncated return value from quiesceTime() to 63 bits\n");
+    return (time & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+JNIEXPORT jlong JNICALL
+Java_gem5_Ops_rpns(JNIEnv *env, jobject obj)
+{
+    uint64_t time = getDispatchTable(env, obj)->m5_rpns();
+    if (time & 0x8000000000000000ULL)
+        printf("Truncated return value from rpns() to 63 bits\n");
+    return (time & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_wake_1cpu(JNIEnv *env, jobject obj, jlong j_cpuid)
+{
+    getDispatchTable(env, obj)->m5_wake_cpu(j_cpuid);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_exit(JNIEnv *env, jobject obj, jlong j_ns_delay)
+{
+    getDispatchTable(env, obj)->m5_exit(j_ns_delay);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_fail(JNIEnv *env, jobject obj, jlong j_ns_delay, jlong j_code)
+{
+    getDispatchTable(env, obj)->m5_fail(j_ns_delay, j_code);
+}
+
+JNIEXPORT jlong JNICALL
+Java_gem5_Ops_sum(JNIEnv *env, jobject obj, jlong a, jlong b, jlong c,
+                    jlong d, jlong e, jlong f)
+{
+    uint64_t result = getDispatchTable(env, obj)->m5_sum(a, b, c, d, e, f);
+    if (result & 0x8000000000000000ULL)
+        printf("Truncated return value from sum() to 63 bits\n");
+    return (result & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+JNIEXPORT jlong JNICALL
+Java_gem5_Ops_init_1param(JNIEnv *env, jobject obj, jlong j_key_str1,
+                           jlong j_key_str2)
+{
+    uint64_t param = getDispatchTable(env, obj)->m5_init_param(
+            j_key_str1, j_key_str2);
+    if (param & 0x8000000000000000ULL)
+        printf("Truncated return value from m_initparam() to 63 bits\n");
+    return (param & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_checkpoint(JNIEnv *env, jobject obj,
+                           jlong j_ns_delay, jlong j_ns_period)
+{
+    getDispatchTable(env, obj)->m5_checkpoint(j_ns_delay, j_ns_period);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_reset_1stats(JNIEnv *env, jobject obj,
+                             jlong j_ns_delay, jlong j_ns_period)
+{
+    getDispatchTable(env, obj)->m5_reset_stats(j_ns_delay, j_ns_period);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_dump_1stats(JNIEnv *env, jobject obj,
+                            jlong j_ns_delay, jlong j_ns_period)
+{
+    getDispatchTable(env, obj)->m5_dump_stats(j_ns_delay, j_ns_period);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_dump_1reset_1stats(JNIEnv *env, jobject obj,
+                                  jlong j_ns_delay, jlong j_ns_period)
+{
+    getDispatchTable(env, obj)->m5_dump_reset_stats(j_ns_delay, j_ns_period);
+}
+
+JNIEXPORT jlong JNICALL
+Java_gem5_Ops_read_1file(JNIEnv *env, jobject obj,
+                           jbyteArray j_buffer, jlong j_len, jlong j_offset)
+{
+    jbyte *buffer = env->GetByteArrayElements(j_buffer, 0);
+
+    uint64_t result = getDispatchTable(env, obj)->m5_read_file(
+            buffer, j_len, j_offset);
+
+    env->ReleaseByteArrayElements(j_buffer, buffer, JNI_ABORT);
+    return (result & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+JNIEXPORT jlong JNICALL
+Java_gem5_Ops_write_1file(JNIEnv *env, jobject obj,
+                            jbyteArray j_buffer, jlong j_len, jlong j_offset,
+                            jstring j_filename)
+{
+    jbyte *buffer = env->GetByteArrayElements(j_buffer, 0);
+    const char *filename = env->GetStringUTFChars(j_filename, NULL);
+
+    uint64_t result = getDispatchTable(env, obj)->m5_write_file(
+            buffer, j_len, j_offset, filename);
+
+    env->ReleaseStringUTFChars(j_filename, filename);
+    env->ReleaseByteArrayElements(j_buffer, buffer, JNI_ABORT);
+    return (result & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_debug_1break(JNIEnv *env, jobject obj)
+{
+    getDispatchTable(env, obj)->m5_debug_break();
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_switch_1cpu (JNIEnv *env, jobject obj)
+{
+    getDispatchTable(env, obj)->m5_switch_cpu();
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_dist_1toggle_1sync(JNIEnv *env, jobject obj)
+{
+    getDispatchTable(env, obj)->m5_dist_toggle_sync();
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_add_symbol(JNIEnv *env, jobject obj,
+        jlong j_addr, jstring j_symbol)
+{
+    const char *symbol = env->GetStringUTFChars(j_symbol, NULL);
+
+    getDispatchTable(env, obj)->m5_add_symbol(j_addr, symbol);
+
+    env->ReleaseStringUTFChars(j_symbol, symbol);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_load_1symbol(JNIEnv *env, jobject obj)
+{
+    getDispatchTable(env, obj)->m5_load_symbol();
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_panic(JNIEnv *env, jobject obj)
+{
+    getDispatchTable(env, obj)->m5_panic();
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_work_1begin(JNIEnv *env, jobject obj,
+                            jlong j_workid, jlong j_threadid)
+{
+    getDispatchTable(env, obj)->m5_work_begin(j_workid, j_threadid);
+}
+
+JNIEXPORT void JNICALL
+Java_gem5_Ops_work_1end(JNIEnv *env, jobject obj,
+                          jlong j_workid, jlong j_threadid)
+{
+    getDispatchTable(env, obj)->m5_work_end(j_workid, j_threadid);
+}
+