From 48f7ee9244bbf317c3240de840a48bf3959b5353 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 22 Oct 2020 20:01:05 -0700 Subject: [PATCH] util: Enable using different call types in the gem5 ops java wrapper. 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 Reviewed-by: Bobby R. Bruce Maintainer: Gabe Black Tested-by: kokoro --- util/m5/README.md | 17 ++- util/m5/SConstruct | 2 + util/m5/src/SConscript | 7 +- util/m5/src/java/gem5/Ops.java | 13 ++- util/m5/src/java/gem5/OpsTest.java | 14 ++- util/m5/src/java/gem5/{ops.c => ops.cc} | 141 ++++++++++++++++++------ 6 files changed, 152 insertions(+), 42 deletions(-) rename util/m5/src/java/gem5/{ops.c => ops.cc} (57%) diff --git a/util/m5/README.md b/util/m5/README.md index 7d2d66bfd..b9ccbff55 100644 --- a/util/m5/README.md +++ b/util/m5/README.md @@ -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); +``` diff --git a/util/m5/SConstruct b/util/m5/SConstruct index 63143a806..242bbe7c3 100644 --- a/util/m5/SConstruct +++ b/util/m5/SConstruct @@ -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)) diff --git a/util/m5/src/SConscript b/util/m5/src/SConscript index 5eabcc399..b3e057c7f 100644 --- a/util/m5/src/SConscript +++ b/util/m5/src/SConscript @@ -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) diff --git a/util/m5/src/java/gem5/Ops.java b/util/m5/src/java/gem5/Ops.java index cc92505dd..44afad976 100644 --- a/util/m5/src/java/gem5/Ops.java +++ b/util/m5/src/java/gem5/Ops.java @@ -37,13 +37,25 @@ 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 _callTypes; + public static final Map 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); - } diff --git a/util/m5/src/java/gem5/OpsTest.java b/util/m5/src/java/gem5/OpsTest.java index 6e855c929..5678ecdc8 100644 --- a/util/m5/src/java/gem5/OpsTest.java +++ b/util/m5/src/java/gem5/OpsTest.java @@ -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.cc similarity index 57% rename from util/m5/src/java/gem5/ops.c rename to util/m5/src/java/gem5/ops.cc index c3f93289f..c1f36e483 100644 --- a/util/m5/src/java/gem5/ops.c +++ b/util/m5/src/java/gem5/ops.cc @@ -36,42 +36,114 @@ */ #include +#include +#include +#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, "", "()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, "", "()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) { - m5_arm(j_address); + getDispatchTable(env, obj)->m5_arm(j_address); } JNIEXPORT void JNICALL Java_gem5_Ops_quiesce(JNIEnv *env, jobject obj) { - m5_quiesce(); + getDispatchTable(env, obj)->m5_quiesce(); } JNIEXPORT void JNICALL Java_gem5_Ops_quiesce_1ns(JNIEnv *env, jobject obj, jlong j_ns) { - m5_quiesce_ns(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) { - m5_quiesce_cycle(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 = m5_quiesce_time(); + 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); @@ -80,7 +152,7 @@ Java_gem5_Ops_quiesce_1time(JNIEnv *env, jobject obj) JNIEXPORT jlong JNICALL Java_gem5_Ops_rpns(JNIEnv *env, jobject obj) { - uint64_t time = m5_rpns(); + uint64_t time = getDispatchTable(env, obj)->m5_rpns(); if (time & 0x8000000000000000ULL) printf("Truncated return value from rpns() to 63 bits\n"); return (time & 0x7FFFFFFFFFFFFFFFULL); @@ -89,26 +161,26 @@ Java_gem5_Ops_rpns(JNIEnv *env, jobject obj) JNIEXPORT void JNICALL Java_gem5_Ops_wake_1cpu(JNIEnv *env, jobject obj, jlong j_cpuid) { - m5_wake_cpu(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) { - m5_exit(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) { - m5_fail(j_ns_delay, 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 = m5_sum(a, b, c, d, e, 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); @@ -118,7 +190,8 @@ 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); + 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); @@ -128,39 +201,40 @@ 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); + 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) { - m5_reset_stats(j_ns_delay, 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) { - m5_dump_stats(j_ns_delay, 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) { - m5_dump_reset_stats(j_ns_delay, 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(env, j_buffer, 0); + jbyte *buffer = env->GetByteArrayElements(j_buffer, 0); - uint64_t result = m5_read_file(buffer, j_len, j_offset); + uint64_t result = getDispatchTable(env, obj)->m5_read_file( + buffer, j_len, j_offset); - (*env)->ReleaseByteArrayElements(env, j_buffer, buffer, JNI_ABORT); + env->ReleaseByteArrayElements(j_buffer, buffer, JNI_ABORT); return (result & 0x7FFFFFFFFFFFFFFFULL); } @@ -169,68 +243,69 @@ 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); + jbyte *buffer = env->GetByteArrayElements(j_buffer, 0); + const char *filename = env->GetStringUTFChars(j_filename, NULL); - uint64_t result = m5_write_file(buffer, j_len, j_offset, filename); + uint64_t result = getDispatchTable(env, obj)->m5_write_file( + buffer, j_len, j_offset, filename); - (*env)->ReleaseStringUTFChars(env, j_filename, filename); - (*env)->ReleaseByteArrayElements(env, j_buffer, buffer, JNI_ABORT); + 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) { - m5_debug_break(); + getDispatchTable(env, obj)->m5_debug_break(); } JNIEXPORT void JNICALL Java_gem5_Ops_switch_1cpu (JNIEnv *env, jobject obj) { - m5_switch_cpu(); + getDispatchTable(env, obj)->m5_switch_cpu(); } JNIEXPORT void JNICALL Java_gem5_Ops_dist_1toggle_1sync(JNIEnv *env, jobject obj) { - m5_dist_toggle_sync(); + 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(env, j_symbol, NULL); + const char *symbol = env->GetStringUTFChars(j_symbol, NULL); - m5_add_symbol(j_addr, symbol); + getDispatchTable(env, obj)->m5_add_symbol(j_addr, symbol); - (*env)->ReleaseStringUTFChars(env, j_symbol, symbol); + env->ReleaseStringUTFChars(j_symbol, symbol); } JNIEXPORT void JNICALL Java_gem5_Ops_load_1symbol(JNIEnv *env, jobject obj) { - m5_load_symbol(); + getDispatchTable(env, obj)->m5_load_symbol(); } JNIEXPORT void JNICALL Java_gem5_Ops_panic(JNIEnv *env, jobject obj) { - m5_panic(); + getDispatchTable(env, 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); + 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) { - m5_work_end(j_workid, j_threadid); + getDispatchTable(env, obj)->m5_work_end(j_workid, j_threadid); } -- 2.30.2