WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

Commit 4f4cc9b7 authored by Zixian Cai's avatar Zixian Cai
Browse files

Merge branch 'core'

parents f3cef718 a35d622b
......@@ -20,7 +20,7 @@ __VERSION__ = "0.0.1"
if resource_isdir(__name__, "suite"):
SUITE_DIR = Path(resource_filename(__name__, "suite"))
CALLBACKS_DIR = Path(resource_filename(__name__, "callbacks"))
else:
SUITE_DIR = Path(__file__) / 'suite'
CALLBACKS_DIR = SUITE_DIR / 'callbacks'
CALLBACKS_DIR = Path(__file__) / 'callbacks'
......@@ -17,9 +17,8 @@ limitations under the License.
This header file defines callback interface for C.
*/
struct Callback; // allow for implementation defined struct
struct Callback* cb_init(const char* param_s);
void cb_begin(struct Callback* cb, void* data); // data is implementation defined
void cb_end(struct Callback* cb, void* data);
void cb_report(struct Callback* cb);
extern void* cb_init(const char* param_s); // use void* to hide implementation details
extern void cb_begin(void* cb); // data is implementation defined
extern void cb_end(void* cb);
extern void cb_report(void* cb);
......@@ -16,44 +16,78 @@ limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include "callback.h"
#define DEFAULT_FLOAT_FORMAT_PREC 6
#define DEFAULT_FLOAT_FORMAT_PREC 6 // 1 microsec
#include <time.h>
#ifdef __MACH__
// Use mach_absolute_time on macOS
typedef uint64_t timestamp_t;
#include <mach/mach_time.h>
static inline void get_nano_timestamp(timestamp_t* tstamp) {
*tstamp = mach_absolute_time();
}
static double get_elapsed_time(timestamp_t* t0, timestamp_t* t1) {
mach_timebase_info_data_t tb;
timestamp_t elapsed;
uint64_t elapsed_nano;
mach_timebase_info(&tb);
elapsed = *t1 - *t0;
elapsed_nano = elapsed * tb.numer / tb.denom;
return ((double)elapsed_nano) * 1e-9;
}
#else
// Use clock_gettime on Linux
typedef struct timespec timestamp_t;
static inline void get_nano_timestamp(timestamp_t* tstamp) {
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, tstamp);
}
static double get_elapsed_time(timestamp_t* t0, timestamp_t* t1) {
return ((double)(t1->tv_sec - t0->tv_sec)) +
((double)(t1->tv_nsec - t0->tv_nsec)) * 1e-9;
}
#endif
// records a series of readings
struct Callback {
int fltfmtprec; // float format precision
clock_t t; // begin time / time diff
int fltfmtprec; // float format precision
timestamp_t t0; // begin time
timestamp_t t1; // end time
};
typedef struct Callback Callback;
/**
* param_s: accept an at most two digit integer string for float format precision
*/
struct Callback *cb_init(const char *param_s) {
void* cb_init(const char *param_s) {
Callback *cb;
cb = (Callback *)malloc(sizeof(Callback));
cb->fltfmtprec = strlen(param_s) > 0 ? atoi(param_s) : DEFAULT_FLOAT_FORMAT_PREC;
return cb;
return (void*)cb;
}
// NOTE: assuming current strategy of only one data point per run.
void cb_begin(struct Callback *cb, void *data) {
void cb_begin(void *p) {
Callback *cb = (Callback*)p;
// call time measurement function
cb->t = clock();
get_nano_timestamp(&cb->t0);
}
void cb_end(struct Callback *cb, void *data) {
cb->t = clock() - cb->t;
void cb_end(void *p) {
Callback *cb = (Callback*)p;
get_nano_timestamp(&cb->t1);
}
void cb_report(struct Callback *cb) {
void cb_report(void *p) {
char fmtstr [6]; // NOTE: assume precision number is at most two digit
Callback *cb = (Callback*)p;
sprintf(fmtstr, "%%.%dlf", cb->fltfmtprec);
printf(fmtstr, ((double)cb->t) / ((double)CLOCKS_PER_SEC));
printf(fmtstr, get_elapsed_time(&cb->t0, &cb->t1));
printf("\n");
}
......@@ -19,21 +19,19 @@ limitations under the License.
#include "callback.h"
struct Callback {}; // nothing
struct Callback* cb_init(const char* param_s) {
void* cb_init(const char* param_s) {
printf("initialised PrintCallback with: %s\n", param_s);
return malloc(sizeof(struct Callback));
return NULL;
}
void cb_begin(struct Callback* cb, void* data) {
void cb_begin(void* cb) {
printf("begin measurement.\n");
}
void cb_end(struct Callback* cb, void* data) {
void cb_end(void* cb) {
printf("end measurement.\n");
}
void cb_report(struct Callback* cb) {
void cb_report(void* cb) {
printf("report.\n");
}
......@@ -20,35 +20,44 @@ limitations under the License.
void mubench_init_callback_symbols(MuIRBuilder *bldr)
{
// generate symbols
t_callback = bldr->gen_sym(bldr, "@mubench.t_callback");
t_callback_r = bldr->gen_sym(bldr, "@mubench.t_callback_r");
t_logargs = bldr->gen_sym(bldr, "@mubench.t_logargs");
t_logargs_r = bldr->gen_sym(bldr, "@mubench.t_logargs_r");
t_void = bldr->gen_sym(bldr, "@mubench.t_void");
t_callback_p = bldr->gen_sym(bldr, "@mubench.t_callback_p");
sig_cb_init = bldr->gen_sym(bldr, "@mubench.sig_cb_init");
sig_cb_log = bldr->gen_sym(bldr, "@mubench.sig_cb_log");
sig_cb_begin = bldr->gen_sym(bldr, "@mubench.sig_cb_begin");
sig_cb_end = bldr->gen_sym(bldr, "@mubench.sig_cb_end");
sig_cb_report = bldr->gen_sym(bldr, "@mubench.sig_cb_report");
cb_init = bldr->gen_sym(bldr, "@mubench.cb_init");
cb_begin = bldr->gen_sym(bldr, "@mubench.cb_begin");
cb_end = bldr->gen_sym(bldr, "@mubench.cb_end");
cb_report = bldr->gen_sym(bldr, "@mubench.cb_report");
t_fp_cb_init = bldr->gen_sym(bldr, "@mubench.t_fp_cb_init");
t_fp_cb_begin = bldr->gen_sym(bldr, "@mubench.t_fp_cb_begin");
t_fp_cb_end = bldr->gen_sym(bldr, "@mubench.t_fp_cb_end");
t_fp_cb_report = bldr->gen_sym(bldr, "@mubench.t_fp_cb_report");
extern_cb_init = bldr->gen_sym(bldr, "@mubench.extern_cb_init");
extern_cb_begin = bldr->gen_sym(bldr, "@mubench.extern_cb_begin");
extern_cb_end = bldr->gen_sym(bldr, "@mubench.extern_cb_end");
extern_cb_report = bldr->gen_sym(bldr, "@mubench.extern_cb_report");
t_cchar = bldr->gen_sym(bldr, "@mubench.t_cchar");
t_cchara = bldr->gen_sym(bldr, "@mubench.t_cchara");
t_ccharp = bldr->gen_sym(bldr, "@mubench.t_ccharp");
// define types
bldr->new_type_ref(bldr, t_callback_r, t_callback);
bldr->new_type_ref(bldr, t_logargs_r, t_logargs);
bldr->new_type_void(bldr, t_void);
bldr->new_type_uptr(bldr, t_callback_p, t_void);
bldr->new_funcsig(bldr, sig_cb_init,
(MuTypeNode[1]){t_ccharp}, 1,
(MuTypeNode[1]){t_callback_r}, 1);
bldr->new_funcsig(bldr, sig_cb_log,
(MuTypeNode[2]){t_callback_r, t_logargs_r}, 2, NULL, 0);
(MuTypeNode[1]){t_callback_p}, 1);
bldr->new_funcsig(bldr, sig_cb_begin,
(MuTypeNode[1]){t_callback_p}, 1, NULL, 0);
bldr->new_funcsig(bldr, sig_cb_end,
(MuTypeNode[1]){t_callback_p}, 1, NULL, 0);
bldr->new_funcsig(bldr, sig_cb_report,
(MuTypeNode[1]){t_callback_r}, 1, NULL, 0);
bldr->new_func(bldr, cb_init, sig_cb_init);
bldr->new_func(bldr, cb_begin, sig_cb_log);
bldr->new_func(bldr, cb_end, sig_cb_log);
bldr->new_func(bldr, cb_report, sig_cb_report);
(MuTypeNode[1]){t_callback_p}, 1, NULL, 0);
bldr->new_type_ufuncptr(bldr, t_fp_cb_init, sig_cb_init);
bldr->new_type_ufuncptr(bldr, t_fp_cb_begin, sig_cb_begin);
bldr->new_type_ufuncptr(bldr, t_fp_cb_end, sig_cb_end);
bldr->new_type_ufuncptr(bldr, t_fp_cb_report, sig_cb_report);
bldr->new_const_extern(bldr, extern_cb_init, t_fp_cb_init, "cb_init");
bldr->new_const_extern(bldr, extern_cb_begin, t_fp_cb_begin, "cb_begin");
bldr->new_const_extern(bldr, extern_cb_end, t_fp_cb_end, "cb_end");
bldr->new_const_extern(bldr, extern_cb_report, t_fp_cb_report, "cb_report");
bldr->new_type_int(bldr, t_cchar, 8);
bldr->new_type_hybrid(bldr, t_cchara, NULL, 0, t_cchar);
bldr->new_type_uptr(bldr, t_ccharp, t_cchara);
......
......@@ -31,35 +31,39 @@ extern "C" {
/**
The interface consists of the following definitions:
.type @mubench.t_callback_r = ref<@mubench.t_callback>
.type @mubench.t_logargs_r = ref<@mubench.t_logargs>
.type @mubench.t_void = void
.type @mubench.t_callback_p = uptr<@mubench.t_void>
.type @mubench.t_cchar = int<8>
.type @mubench.t_cchara = hybrid<@mubench.t_cchar>
.type @mubench.t_ccharp = uptr<@mubench.t_cchara>
.funcsig @mubench.sig_cb_init = (@mubench.t_charp) -> (@mubench.t_callback_r)
.funcsig @mubench.sig_cb_log = (@mubench.t_callback_r @mubench.t_logargs_r) -> ()
.funcsig @mubench.sig_cb_report = (@mubench.t_callback_r) -> ()
.funcdecl @mubench.cb_init <@mubench.sig_cb_init>
.funcdecl @mubench.cb_begin <@mubench.sig_cb_log>
.funcdecl @mubench.cb_end <@mubench.sig_cb_log>
.funcdecl @mubench.cb_report <@mubench.sig_cb_report>
relying on subsequent functions to define:
.type @mubench.t_callback
.type @mubench.t_logargs
.funcsig @mubench.sig_cb_init = (@mubench.t_charp) -> (@mubench.t_callback_p)
.funcsig @mubench.sig_cb_begin = (@mubench.t_callback_p) -> ()
.funcsig @mubench.sig_cb_end = (@mubench.t_callback_p) -> ()
.funcsig @mubench.sig_cb_report = (@mubench.t_callback_p) -> ()
.type @mubench.t_fp_cb_init = ufuncptr<@mubench.sig_cb_init>
.type @mubench.t_fp_cb_begin = ufuncptr<@mubench.sig_cb_begin>
.type @mubench.t_fp_cb_end = ufuncptr<@mubench.sig_cb_end>
.type @mubench.t_fp_cb_report = ufuncptr<@mubench.sig_cb_report>
.const @mubench.extern_cb_init <@mubench.t_fp_cb_init> = EXTERN "cb_init"
.const @mubench.extern_cb_begin <@mubench.t_fp_cb_begin> = EXTERN "cb_begin"
.const @mubench.extern_cb_end <@mubench.t_fp_cb_end> = EXTERN "cb_end"
.const @mubench.extern_cb_report <@mubench.t_fp_cb_report> = EXTERN "cb_report"
*/
MuID t_callback;
MuID t_callback_r;
MuID t_logargs;
MuID t_logargs_r;
MuID t_void;
MuID t_callback_p;
MuID sig_cb_init;
MuID sig_cb_log;
MuID sig_cb_begin;
MuID sig_cb_end;
MuID sig_cb_report;
MuID cb_init;
MuID cb_begin;
MuID cb_end;
MuID cb_report;
MuID t_fp_cb_init;
MuID t_fp_cb_begin;
MuID t_fp_cb_end;
MuID t_fp_cb_report;
MuID extern_cb_init;
MuID extern_cb_begin;
MuID extern_cb_end;
MuID extern_cb_report;
MuID t_cchar;
MuID t_cchara;
MuID t_ccharp;
......@@ -70,25 +74,6 @@ MuID t_ccharp;
*/
void mubench_init_callback_symbols(MuIRBuilder* bldr);
/**
* Implementation defined function.
* This function is called before calling build_benchmark.
* Build callback functions, concrete types and other global definitions.
* Must define the following types:
@mubench.callback
@mubench.args
*/
void mubench_build_callback(MuIRBuilder* bldr);
/**
* Implementation defined function.
* Allocate memory to parr,
* fill it with global definitions that should be included in the boot image.
* Return the length of the array.
* NOTE: array memory should be freed by the caller when it's no long needed.
*/
int mubench_get_callback_global_defs(MuID* *parr);
#ifdef __cplusplus
}
#endif
......
......@@ -85,7 +85,6 @@ int main(int argc, char **argv)
bldr = ctx->new_ir_builder(ctx);
mubench_init_callback_symbols(bldr);
mubench_build_callback(bldr);
prim_func_id = mubench_build_benchmark(bldr);
bldr->load(bldr);
hmain = ctx->handle_from_func(ctx, prim_func_id);
......@@ -93,24 +92,36 @@ int main(int argc, char **argv)
// get the global definitions and merge them into one array
MuID predef_ids[] = {
t_callback, t_callback_r, t_logargs, t_logargs_r,
sig_cb_init, sig_cb_log, sig_cb_report,
cb_init, cb_begin, cb_end, cb_report,
t_cchar, t_cchara, t_ccharp};
t_void,
t_callback_p,
sig_cb_init,
sig_cb_begin,
sig_cb_end,
sig_cb_report,
t_fp_cb_init,
t_fp_cb_begin,
t_fp_cb_end,
t_fp_cb_report,
extern_cb_init,
extern_cb_begin,
extern_cb_end,
extern_cb_report,
t_cchar,
t_cchara,
t_ccharp
};
int npredefs = sizeof(predef_ids) / sizeof(MuID);
ngdefs_cb = mubench_get_callback_global_defs(&gdefs_cb);
ngdefs_bench = mubench_get_benchmark_global_defs(&gdefs_bench);
gdefs = (MuID *)malloc((npredefs + ngdefs_cb + ngdefs_bench) * sizeof(MuID));
gdefs = (MuID *)malloc((npredefs + ngdefs_bench) * sizeof(MuID));
memcpy(gdefs, predef_ids, sizeof(predef_ids));
memcpy(gdefs + npredefs, gdefs_cb, ngdefs_cb * sizeof(MuID));
memcpy(gdefs + npredefs + ngdefs_cb, gdefs_bench, ngdefs_bench * sizeof(MuID));
memcpy(gdefs + npredefs, gdefs_bench, ngdefs_bench * sizeof(MuID));
// get relocation info
mubench_get_reloc_info(&sym_flds, &sym_strs, &nsyms, &reloc_flds, &reloc_strs, &nrelocs);
ctx->make_boot_image(ctx, gdefs, (npredefs + ngdefs_cb + ngdefs_bench),
ctx->make_boot_image(ctx, gdefs, (npredefs + ngdefs_bench),
hmain, NULL, NULL,
sym_flds, sym_strs, nsyms, reloc_flds, reloc_strs, nrelocs,
argv[2]);
......@@ -121,7 +132,6 @@ int main(int argc, char **argv)
// free memory
free(gdefs);
free(gdefs_cb);
free(gdefs_bench);
if (sym_flds)
{
......
......@@ -13,23 +13,35 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""
A simple print callback class as an example.
"""
def get_callback(libcb_path):
import ctypes
import py
import sys
from callback import Callback
import json
libcb = ctypes.CDLL(libcb_path)
def external(name, args, result):
fp = getattr(libcb, name)
fp.argtypes = args
fp.restype = result
return fp
class PrintCallback(Callback):
def __init__(self, param_s):
print("initialised PrintCallback with: %s" % param_s)
c_cb_init = external("cb_init", [ctypes.c_char_p], ctypes.c_void_p)
c_cb_begin = external("cb_begin", [ctypes.c_void_p], None)
c_cb_end = external("cb_end", [ctypes.c_void_p], None)
c_cb_report = external("cb_report", [ctypes.c_void_p], None)
def begin(self, **kwds):
print("begin measurement")
class Callback:
def __init__(self, param_s):
self.cb = c_cb_init(param_s)
def end(self, **kwds):
print("end measurement")
def begin(self):
c_cb_begin(self.cb)
def report(self):
json.dump({}, fp)
def end(self):
c_cb_end(self.cb)
def report(self):
c_cb_report(self.cb)
return Callback
......@@ -13,48 +13,41 @@
# See the License for the specific language governing permissions and
# limitations under the License.
class Callback:
"""
Callback root class used by RPython
"""
def __init__(self, param_s):
"""
:param param_s: parameter string for initialisation
"""
pass
def begin(self, kwds=None):
"""
Begin measurement.
"""
pass
def end(self, kwds=None):
"""
End measurement.
"""
pass
def report(self):
"""
Report data to file.
"""
pass
def get_callback(cb_name):
"""
Import callback classes from submodule files,
and dynamically select which class to return.
NOTE: new Callback class implementations should be added here
"""
from callback.cb_print import PrintCallback
from callback.cb_clock import ClockCallback
name_dic = {
'print': PrintCallback,
'clock': ClockCallback,
}
cb_cls = name_dic[cb_name]
return cb_cls
def get_callback(libcb_path):
from rpython.rtyper.lltypesystem import rffi
import py
import sys
libcb = py.path.local(libcb_path)
libext = '.dylib' if sys.platform == 'darwin' else '.so'
libname = libcb.basename[3:libcb.basename.index(libext)]
callback_dir = py.path.local(__file__).join('..', '..')
eci = rffi.ExternalCompilationInfo(libraries=[libname],
library_dirs=[libcb.dirname],
includes=['callback.h'],
include_dirs=[callback_dir])
def external(name, args, result, compilation_info=eci, **kwds):
return rffi.llexternal(name, args, result,
compilation_info=compilation_info,
_nowrapper=True, **kwds)
c_cb_init = external("cb_init", [rffi.CCHARP], rffi.VOIDP)
c_cb_begin = external("cb_begin", [rffi.VOIDP], rffi.lltype.Void)
c_cb_end = external("cb_end", [rffi.VOIDP], rffi.lltype.Void)
c_cb_report = external("cb_report", [rffi.VOIDP], rffi.lltype.Void)
class Callback:
def __init__(self, param_s):
with rffi.scoped_str2charp(param_s) as buf:
self.cb = c_cb_init(buf)
def begin(self):
c_cb_begin(self.cb)
def end(self):
c_cb_end(self.cb)
def report(self):
c_cb_report(self.cb)
return Callback
\ No newline at end of file
......@@ -12,10 +12,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import time
import logging
import subprocess as subproc
from pathlib import Path
from mubench import CALLBACKS_DIR
from mubench.util import expandenv
from mubench.exceptions import ExecutionFailure
from types import SimpleNamespace
......@@ -26,6 +30,7 @@ class Language:
name = None
src_ext = None
compiled = True
default_cc = 'clang'
@classmethod
def check_lang(cls, lc):
......@@ -55,7 +60,7 @@ class Language:
raise NotImplementedError
@classmethod
def run_in_subproc(cls, cmd, env=None):
def run_in_subproc(cls, cmd, env=None): # TODO: maybe put this in util.py
cmd = list(map(str, cmd))
logger.info(" ".join(cmd))
t0 = time.perf_counter()
......
......@@ -34,7 +34,7 @@ class C(Language):
@classmethod
def compile(cls, task):
callback_dir = CALLBACKS_DIR / cls.name
callback_dir = CALLBACKS_DIR
cc = task.compiler
cmd = []
......@@ -42,20 +42,23 @@ class C(Language):
# flags
flags = []
include_flags = ['-I%(callback_dir)s' % locals()]
cc_flags = list(map(lambda a: expandenv(a, task.env), cc.get('flags', [])))
flags.extend(cc_flags)
include_flags = ['-I%(callback_dir)s' % locals()]
flags.extend(include_flags)
libcb = task.callback['dylib']
liblink_flags = ['-L%s' % libcb.parent, '-lcb_%(name)s' % task.callback]
flags.extend(liblink_flags)
target = cls.get_default_target(task)
flags.extend(['-o', str(target)])
cmd.extend(flags)
cmd.append(task.srcfile)
# callback selected at compile time, initialised at runtime
callback_file = callback_dir / ('cb_%(name)s.c' % task.callback)
cmd.append(callback_file)
cls.run_in_subproc(cmd, task.env)
assert target.exists()
......
......@@ -77,22 +77,26 @@ class Mu(Language):
def set_default_args(defl_d, vmargs):
# include default args if not specified, otherwise use custom-defined value
for key, val in defl_d.items():
if not any([key in arg for arg in vmargs]):
if not key in vmargs:
vmargs.append('%(key)s=%(val)s' % locals())
return vmargs
vmargs = list(map(lambda a: expandenv(a, task.env), cc.get('vmargs', [])))
libcb = task.taskset.callback['dylib']
if lc['impl'] == 'holstein':
separators = '\n'
default_args = {}
default_args = {
'extraLibs': str(libcb)
}
else: # zebu
separators = ' '
emit_dir = task.output_dir / ('%s_%s-emit' % (task.taskset.name, task.name))
default_args = {
'--aot-emit-dir': str(emit_dir)
'--aot-emit-dir': str(emit_dir),
'--bootimage-external-libpath': str(libcb.parent),
'--bootimage-external-lib': "cb_%(name)s" % task.callback # libcb_%(name)s.so/dylib
}