-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a generator for a whamm hotness monitor
- Loading branch information
1 parent
eb66016
commit bacb588
Showing
6 changed files
with
2,092 additions
and
347 deletions.
There are no files selected for viewing
295 changes: 295 additions & 0 deletions
295
test/monitors/whamm/monitors/generators/gen_hotness-mon/GenHotnessMon.v3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,295 @@ | ||
var MON_NAME = "hotness-mon.wat"; | ||
var TABS = 4; | ||
|
||
def main(args: Array<string>) -> int { | ||
var fd: int; | ||
if (args.length != 1) { | ||
System.puts("Check gen_hotness-mon.sh, must pass workdir arg!\n"); | ||
return 1; | ||
} else { | ||
var workdir = args[0]; | ||
var path = StringBuilder.new().put2("%s/%s", workdir, MON_NAME); | ||
fd = System.fileOpen(path.toString(), false); | ||
} | ||
|
||
var wat = WatWriter.new(TABS); | ||
|
||
write_docs(wat); | ||
wat.module_start(); | ||
setup(wat); | ||
|
||
alloc_func(wat); | ||
count_func(wat); | ||
flush_func(wat); | ||
|
||
var ran_select = false; | ||
for (opcode in Opcode) { | ||
var mnemonic = opcode.mnemonic; | ||
|
||
if (Strings.equal(mnemonic,"<invalid>")) { | ||
continue; | ||
} | ||
if (Strings.equal(mnemonic,"select")) { | ||
if (!ran_select) { | ||
ran_select = true; | ||
} else { | ||
// skip second select opcode (0x1B and 0x1C) | ||
continue; | ||
} | ||
} | ||
gen_probe(wat, mnemonic); | ||
} | ||
|
||
wat.module_end(); | ||
|
||
// Output wat to file | ||
var str = wat.str(); | ||
System.fileWriteK(fd, str, 0, str.length); | ||
System.fileClose(fd); | ||
return 0; | ||
} | ||
|
||
def gen_probe(wat: WatWriter, opcode_name: string) { | ||
var sig = StringBuilder.new().put1("(export \"wasm:opcode:%s ($alloc(fid, pc))\") (param $entry i32)", opcode_name).toString(); | ||
wat.func_start(sig) | ||
.w("(call $count_probe (local.get $entry))") | ||
.func_end(); | ||
} | ||
|
||
def write_docs(wat: WatWriter) { | ||
wat.ws([";; === Whamm Hotness Monitor ===", | ||
";; Instrument EVERY location in the application and track each", | ||
";; time it is executed dynamically with an in-memory counter.\n", | ||
";; --> Output format: <fid>, pc=<pc>, [<counter>]\n"]); | ||
} | ||
|
||
def setup(wat: WatWriter) { | ||
// imports | ||
wat.ws(["(import \"wizeng\" \"puti\" (func $puti (param i32)))", | ||
"(import \"wizeng\" \"puts\" (func $puts (param i32 i32)))\n", | ||
|
||
// memory/globals | ||
"(memory (export \"mem\") 2) ;; no expansion checks", | ||
"(global $last_entry (mut i32) (i32.const 0))\n", | ||
|
||
// data(data (i32.const 0xc00) "func=") | ||
"(data (i32.const 0xd00) \", pc=\")", | ||
"(data (i32.const 0xe00) \"\\n\")", | ||
"(data (i32.const 0xf00) \", [\")", | ||
"(data (i32.const 0xf10) \",\")", | ||
"(data (i32.const 0xf20) \"]\")\n"]); | ||
} | ||
|
||
def alloc_func(wat: WatWriter) { | ||
wat.func_start("(export \"$alloc\") (param $func i32) (param $pc i32) (result i32)") | ||
.ws(["(local $entry i32)\n", | ||
|
||
"global.get $last_entry", | ||
"local.set $entry\n", | ||
|
||
"local.get $entry", | ||
"local.get $func", | ||
"i32.store\n", | ||
|
||
"local.get $entry", | ||
"local.get $pc", | ||
"i32.store offset=4\n", | ||
|
||
"local.get $entry", | ||
"i32.const 1", | ||
"i32.store offset=8\n", | ||
|
||
"local.get $entry", | ||
"i32.const 20", | ||
"i32.add", | ||
"global.set $last_entry\n", | ||
|
||
"local.get $entry"]) | ||
.func_end(); | ||
} | ||
|
||
def count_func(wat: WatWriter) { | ||
wat.func_start("$count_probe (param $entry i32)") | ||
.ws(["local.get $entry", | ||
"local.get $entry", | ||
"i64.load offset=12 ;; count number of times fired", | ||
"i64.const 1", | ||
"i64.add", | ||
"i64.store offset=12"]) | ||
.func_end(); | ||
} | ||
|
||
def flush_func(wat: WatWriter) { | ||
wat.func_start("$flush (export \"wasm:exit\")") | ||
.ws(["(local $entry i32)", | ||
"(local $options i32)", | ||
"(block $end_loop"]).indent() | ||
.w("(loop $loop_entry").indent() | ||
.ws([";; check at the end of memory", | ||
"local.get $entry", | ||
"global.get $last_entry", | ||
"i32.eq", | ||
"br_if $end_loop\n", | ||
|
||
"(call $puts (i32.const 0xc00) (i32.const 5))", | ||
"local.get $entry", | ||
"i32.load ;; func", | ||
"call $puti", | ||
"local.get $entry", | ||
"i32.const 4", | ||
"i32.add", | ||
"local.set $entry\n", | ||
|
||
"(call $puts (i32.const 0xd00) (i32.const 5))", | ||
"local.get $entry", | ||
"i32.load ;; pc", | ||
"call $puti", | ||
"local.get $entry", | ||
"i32.const 4", | ||
"i32.add", | ||
"local.set $entry\n", | ||
|
||
"local.get $entry", | ||
"i32.load ;; number of options", | ||
"local.get $entry", | ||
"i32.const 4", | ||
"i32.add", | ||
"local.set $entry\n", | ||
|
||
"local.set $options\n", | ||
|
||
"(call $puts (i32.const 0xf00) (i32.const 3))\n", | ||
|
||
"(loop $loop_options"]).indent() | ||
.ws(["local.get $entry", | ||
"i32.load", | ||
"call $puti\n", | ||
|
||
"local.get $entry", | ||
"i32.const 8", | ||
"i32.add", | ||
"local.set $entry\n", | ||
|
||
"local.get $options", | ||
"i32.const -1", | ||
"i32.add\n", | ||
|
||
"local.tee $options\n", | ||
|
||
"i32.eqz", | ||
"(if"]).indent() | ||
.w("(then").indent() | ||
.w("(call $puts (i32.const 0xf20) (i32.const 1))").dedent() | ||
.ws([")", | ||
"(else"]).indent() | ||
.ws(["(call $puts (i32.const 0xf10) (i32.const 1))", | ||
"br $loop_options"]).dedent() | ||
.w(")").dedent() | ||
.w(")").dedent() | ||
.ws([")\n", | ||
"(call $puts (i32.const 0xe00) (i32.const 1))", | ||
"br $loop_entry"]).dedent() | ||
.w(")").dedent() | ||
.w(")") | ||
.func_end(); | ||
} | ||
|
||
class WatWriter(spaces_per_tab: int) { | ||
var buf = StringBuilder.new(); | ||
var curr_indent = 0; | ||
|
||
// Functions | ||
def func_start(sig: string) -> WatWriter { | ||
sexp_start("func ", false); | ||
if (sig != null) { | ||
buf.puts(sig); | ||
} | ||
nl(); | ||
indent(); | ||
return this; | ||
} | ||
def func_end() -> WatWriter { | ||
dedent(); | ||
sexp_end(); | ||
return this; | ||
} | ||
|
||
// Modules | ||
def module_start() -> WatWriter { | ||
sexp_start("module", true); | ||
indent(); | ||
return this; | ||
} | ||
def module_end() -> WatWriter { | ||
reset_indent(); | ||
sexp_end(); | ||
return this; | ||
} | ||
|
||
// S-Expressions | ||
def sexp_start(name: string, wnl: bool) -> WatWriter { | ||
w_nonl(StringBuilder.new().put1("(%s", name).toString()); | ||
if (wnl) { | ||
nl(); | ||
} | ||
return this; | ||
} | ||
def sexp_end() -> WatWriter { | ||
w(")"); | ||
return this; | ||
} | ||
|
||
// Writing logic | ||
private def w_nonl(s: string) { | ||
w2("%s%s", gen_tabs(), s); | ||
} | ||
def w(s: string) -> WatWriter { | ||
w_nonl(s); | ||
nl(); | ||
return this; | ||
} | ||
def ws(a: Array<string>) -> WatWriter { | ||
for (str in a) { | ||
w(str); | ||
} | ||
|
||
return this; | ||
} | ||
def w1(fmt: string, s: string) -> WatWriter { | ||
buf.put1(fmt, s); | ||
return this; | ||
} | ||
def w2(fmt: string, s0: string, s1: string) -> WatWriter { | ||
buf.put2(fmt, s0, s1); | ||
return this; | ||
} | ||
private def nl() -> WatWriter { | ||
buf.putc('\n'); | ||
return this; | ||
} | ||
|
||
// Tabbing logic | ||
def indent() -> WatWriter { | ||
curr_indent++; | ||
return this; | ||
} | ||
def dedent() -> WatWriter { | ||
curr_indent--; | ||
return this; | ||
} | ||
def reset_indent() -> WatWriter { | ||
curr_indent = 0; | ||
return this; | ||
} | ||
private def gen_tabs() -> string { | ||
var tabs = StringBuilder.new(); | ||
for (i < curr_indent * spaces_per_tab) { | ||
tabs.putc(' '); | ||
} | ||
return tabs.toString(); | ||
} | ||
|
||
def str() -> string { | ||
return buf.toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.