Skip to content

Commit

Permalink
Add first-version support for timing asm. Only supports int64_t argum…
Browse files Browse the repository at this point in the history
…ents

currently.

Example use:
timer.add_asm_test("div", div_inputs,  "div %%rcx", ('=a', '=d'), ("d", "a", "c"), ())
  • Loading branch information
kmowery committed Mar 18, 2015
1 parent 22de8b9 commit 79e7052
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 34 deletions.
125 changes: 92 additions & 33 deletions qtt.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/python
import argparse
import subprocess
import string

HOST_C_FILE = "timer.c"

Expand Down Expand Up @@ -33,10 +34,13 @@ class QTT:
all_testcalls = ""
temp_file = ""
testcount = 0
functions = {}
temp_file = "/tmp/qtt_tmp.c"

def gcc_build(self):
replace_file(HOST_C_FILE,self.temp_file,[
("INCLUDES_HERE",self.all_includes),
("FUNCTIONS_HERE", "\n".join(self.functions.values())),
("TESTFUNCTIONS",self.all_tests),
("TESTRUNS",self.all_testcalls)])

Expand Down Expand Up @@ -120,34 +124,11 @@ def add_include(self,includefiles):
def add_library(self,libfiles):
self.all_add_gcc_files.append(libfiles)

def c_snippet(self,cfunction,typestring,arglist,setup,testnum):

ret_s = typestring.split('(')[0]
types_s = typestring.split('(')[1].split(')')[0]
argnames = map(chr, range(0x61, 0x61+(len(types_s.split(',')))))
typedargs_s = ''.join([x+" "+y+',' for (x,y) in zip(types_s.split(','),argnames)])[:-1]
args_s = ''.join([x+"," for x in argnames])[:-1]

# generate tests
testruns_s = ''
if setup != "":
testruns_s += setup+"\n"
# find longest args
m_len = reduce(lambda a,v: max(len(str(v)),a),arglist,0)+5

for args in arglist:
arg_string = ""
if type(args) is tuple:
for a in args:
arg_string += self.arg_to_string(a)+","
else:
arg_string = self.arg_to_string(args)+" "

printable_arg_string = arg_string[:-1].replace('\"','\\"')
testruns_s += "printf(\""+cfunction+" "+printable_arg_string
testruns_s += ' '*(m_len-len(printable_arg_string)+2)+"%f\\n\","
testruns_s +="__run_test_"+str(testnum)+"("+cfunction+","+arg_string[:-1]+"));\n"
# add a c function.
def add_function(self, fname, function):
self.functions[fname] = function

def make_func(self, num, ret_s, types_s, typedargs_s, args_s):
# C test function
# double __run_test(RETTYPE (*function) (RAWTYPES),TYPEDARGS){
# int ctr = 0;
Expand All @@ -172,7 +153,7 @@ def c_snippet(self,cfunction,typestring,arglist,setup,testnum):
# return (end-st-offset)/(float)PERF_ITRS;
# }

functext = "double __run_test_"+str(testnum)+"("+ret_s+" (*function) ("+types_s+"),"+typedargs_s+"){\n"
functext = "double __run_test_"+str(num)+"("+ret_s+" (*function) ("+types_s+"),"+typedargs_s+"){\n"
functext +=" int ctr = 0;\n"
functext +=" uint8_t real = 0;\n"
functext +=" uint64_t st;\n"
Expand All @@ -193,10 +174,40 @@ def c_snippet(self,cfunction,typestring,arglist,setup,testnum):
functext +=" if(real == 0){ real = 1; goto runme;}\n"
functext +=" /* Run everything for real, previous was just warmup */\n"
functext +=" return (end-st-offset)/(float)PERF_ITRS;\n"
functext +="}"
functext +="}\n"
return functext



def c_snippet(self,cfunction,typestring,arglist,setup,testnum):

ret_s = typestring.split('(')[0]
types_s = typestring.split('(')[1].split(')')[0]
argnames = map(chr, range(0x61, 0x61+(len(types_s.split(',')))))
typedargs_s = ''.join([x+" "+y+',' for (x,y) in zip(types_s.split(','),argnames)])[:-1]
args_s = ''.join([x+"," for x in argnames])[:-1]

# generate tests
testruns_s = ''
if setup != "":
testruns_s += setup+"\n"
# find longest args
m_len = reduce(lambda a,v: max(len(str(v)),a),arglist,0)+5

return (testruns_s,functext)
for args in arglist:
arg_string = ""
if type(args) is tuple:
for a in args:
arg_string += self.arg_to_string(a)+","
else:
arg_string = self.arg_to_string(args)+" "

printable_arg_string = arg_string[:-1].replace('\"','\\"')
testruns_s += "printf(\""+cfunction+" "+printable_arg_string
testruns_s += ' '*(m_len-len(printable_arg_string)+2)+"%f\\n\","
testruns_s +="__run_test_"+str(testnum)+"("+cfunction+","+arg_string[:-1]+"));\n"

return (testruns_s,self.make_func(testnum, ret_s, types_s, typedargs_s, args_s))


def add_c_test(self,cfunction,typestring,arglist,libfiles="",includefiles="",tmpfile="/tmp/qtt_tmp.c",setup_string=""):
Expand All @@ -213,10 +224,58 @@ def add_c_test(self,cfunction,typestring,arglist,libfiles="",includefiles="",tmp
self.all_tests += funtext
self.all_testcalls += tests

def add_asm_test(self, fname, arglist, assembly, outputs, inputs, clobbers, tmpfile="/tmp/qtt_tmp.c"):
(tests, funtext) = self.asm_snippet(fname, arglist, assembly, outputs, inputs, clobbers, self.testcount)
self.testcount+=1

self.all_tests += funtext + "\n"
self.all_testcalls += tests + "\n"

def asm_snippet(self, fname, arglist, assembly, outputs, inputs, clobbers, testnum):

# Make single-letter names for the function arguments
input_names = ["in" + l for l,i in zip(string.ascii_letters, inputs)]
output_names = ["out" + l for l,i in zip(string.ascii_letters, outputs)]

types = ", ".join(["int64_t" for i in range(len(input_names))])
typedargs = ", ".join(["int64_t %s"%(s) for s in input_names])
argnames = ", ".join(["%s"%(s) for s in input_names])

output_vars = "\n ".join(["int64_t %s;"%(s) for s in output_names])

output_constraints = ", ".join(['"%s" (%s)'%(const, name)
for const,name in zip(outputs,output_names)])
input_constraints = ", ".join(['"%s" (%s)'%(const, name)
for const,name in zip(inputs,input_names)])
clobbers_constraints = ", ".join(['"%s"'%(name)
for name in clobbers])

test_function_name = "test_%s"%(fname)

asm = """__asm__ volatile(" %s "
: %s
: %s
: %s); """ %( assembly, output_constraints, input_constraints, clobbers_constraints)

function_type = "volatile int64_t"

function = r"""
%s %s(%s) {
%s
%s
return %s;
}""" %(function_type, test_function_name, typedargs, output_vars, asm, output_names[0])

self.add_function(test_function_name, function)

testruns = []
for args in arglist:
args = ", ".join([self.arg_to_string(a) for a in args])

testruns += [r"""printf("%s %-40s %%f\n", __run_test_%d(%s, %s));"""% \
(fname, args, testnum, test_function_name, args)]

def asm_snippet(self,args):
print args.asmcode
print_unimp("ASM snippets")
return ("\n".join(testruns), self.make_func(testnum, function_type, types, typedargs, argnames))


def qtt_getargs():
Expand Down
4 changes: 3 additions & 1 deletion timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include <stdlib.h>
INCLUDES_HERE

#define PERF_ITRS 20000000
FUNCTIONS_HERE

#define PERF_ITRS 200000

static inline uint64_t rdtscp(){
uint64_t v;
Expand Down

0 comments on commit 79e7052

Please sign in to comment.