1*9880d681SAndroid Build Coastguard Worker#!/usr/bin/env python 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Workerimport sys 4*9880d681SAndroid Build Coastguard Workerimport random 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Workerclass TimingScriptGenerator: 7*9880d681SAndroid Build Coastguard Worker """Used to generate a bash script which will invoke the toy and time it""" 8*9880d681SAndroid Build Coastguard Worker def __init__(self, scriptname, outputname): 9*9880d681SAndroid Build Coastguard Worker self.timeFile = outputname 10*9880d681SAndroid Build Coastguard Worker self.shfile = open(scriptname, 'w') 11*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"\" > %s\n" % self.timeFile) 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): 14*9880d681SAndroid Build Coastguard Worker """Echo some comments and invoke both versions of toy""" 15*9880d681SAndroid Build Coastguard Worker rootname = filename 16*9880d681SAndroid Build Coastguard Worker if '.' in filename: 17*9880d681SAndroid Build Coastguard Worker rootname = filename[:filename.rfind('.')] 18*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) 19*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"\" >> %s\n" % self.timeFile) 20*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"With MCJIT (original)\" >> %s\n" % self.timeFile) 21*9880d681SAndroid Build Coastguard Worker self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") 22*9880d681SAndroid Build Coastguard Worker self.shfile.write(" -o %s -a " % self.timeFile) 23*9880d681SAndroid Build Coastguard Worker self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=false < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) 24*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"\" >> %s\n" % self.timeFile) 25*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"With MCJIT (lazy)\" >> %s\n" % self.timeFile) 26*9880d681SAndroid Build Coastguard Worker self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") 27*9880d681SAndroid Build Coastguard Worker self.shfile.write(" -o %s -a " % self.timeFile) 28*9880d681SAndroid Build Coastguard Worker self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true < %s > %s-mcjit-lazy.out 2> %s-mcjit-lazy.err\n" % (filename, rootname, rootname)) 29*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"\" >> %s\n" % self.timeFile) 30*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) 31*9880d681SAndroid Build Coastguard Worker self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") 32*9880d681SAndroid Build Coastguard Worker self.shfile.write(" -o %s -a " % self.timeFile) 33*9880d681SAndroid Build Coastguard Worker self.shfile.write("./toy -suppress-prompts -use-mcjit=false < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) 34*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"\" >> %s\n" % self.timeFile) 35*9880d681SAndroid Build Coastguard Worker self.shfile.write("echo \"\" >> %s\n" % self.timeFile) 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Workerclass KScriptGenerator: 38*9880d681SAndroid Build Coastguard Worker """Used to generate random Kaleidoscope code""" 39*9880d681SAndroid Build Coastguard Worker def __init__(self, filename): 40*9880d681SAndroid Build Coastguard Worker self.kfile = open(filename, 'w') 41*9880d681SAndroid Build Coastguard Worker self.nextFuncNum = 1 42*9880d681SAndroid Build Coastguard Worker self.lastFuncNum = None 43*9880d681SAndroid Build Coastguard Worker self.callWeighting = 0.1 44*9880d681SAndroid Build Coastguard Worker # A mapping of calls within functions with no duplicates 45*9880d681SAndroid Build Coastguard Worker self.calledFunctionTable = {} 46*9880d681SAndroid Build Coastguard Worker # A list of function calls which will actually be executed 47*9880d681SAndroid Build Coastguard Worker self.calledFunctions = [] 48*9880d681SAndroid Build Coastguard Worker # A comprehensive mapping of calls within functions 49*9880d681SAndroid Build Coastguard Worker # used for computing the total number of calls 50*9880d681SAndroid Build Coastguard Worker self.comprehensiveCalledFunctionTable = {} 51*9880d681SAndroid Build Coastguard Worker self.totalCallsExecuted = 0 52*9880d681SAndroid Build Coastguard Worker 53*9880d681SAndroid Build Coastguard Worker def updateTotalCallCount(self, callee): 54*9880d681SAndroid Build Coastguard Worker # Count this call 55*9880d681SAndroid Build Coastguard Worker self.totalCallsExecuted += 1 56*9880d681SAndroid Build Coastguard Worker # Then count all the functions it calls 57*9880d681SAndroid Build Coastguard Worker if callee in self.comprehensiveCalledFunctionTable: 58*9880d681SAndroid Build Coastguard Worker for child in self.comprehensiveCalledFunctionTable[callee]: 59*9880d681SAndroid Build Coastguard Worker self.updateTotalCallCount(child) 60*9880d681SAndroid Build Coastguard Worker 61*9880d681SAndroid Build Coastguard Worker def updateFunctionCallMap(self, caller, callee): 62*9880d681SAndroid Build Coastguard Worker """Maintains a map of functions that are called from other functions""" 63*9880d681SAndroid Build Coastguard Worker if not caller in self.calledFunctionTable: 64*9880d681SAndroid Build Coastguard Worker self.calledFunctionTable[caller] = [] 65*9880d681SAndroid Build Coastguard Worker if not callee in self.calledFunctionTable[caller]: 66*9880d681SAndroid Build Coastguard Worker self.calledFunctionTable[caller].append(callee) 67*9880d681SAndroid Build Coastguard Worker if not caller in self.comprehensiveCalledFunctionTable: 68*9880d681SAndroid Build Coastguard Worker self.comprehensiveCalledFunctionTable[caller] = [] 69*9880d681SAndroid Build Coastguard Worker self.comprehensiveCalledFunctionTable[caller].append(callee) 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Worker def updateCalledFunctionList(self, callee): 72*9880d681SAndroid Build Coastguard Worker """Maintains a list of functions that will actually be called""" 73*9880d681SAndroid Build Coastguard Worker # Update the total call count 74*9880d681SAndroid Build Coastguard Worker self.updateTotalCallCount(callee) 75*9880d681SAndroid Build Coastguard Worker # If this function is already in the list, don't do anything else 76*9880d681SAndroid Build Coastguard Worker if callee in self.calledFunctions: 77*9880d681SAndroid Build Coastguard Worker return 78*9880d681SAndroid Build Coastguard Worker # Add this function to the list of those that will be called. 79*9880d681SAndroid Build Coastguard Worker self.calledFunctions.append(callee) 80*9880d681SAndroid Build Coastguard Worker # If this function calls other functions, add them too 81*9880d681SAndroid Build Coastguard Worker if callee in self.calledFunctionTable: 82*9880d681SAndroid Build Coastguard Worker for subCallee in self.calledFunctionTable[callee]: 83*9880d681SAndroid Build Coastguard Worker self.updateCalledFunctionList(subCallee) 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard Worker def setCallWeighting(self, weight): 86*9880d681SAndroid Build Coastguard Worker """ Sets the probably of generating a function call""" 87*9880d681SAndroid Build Coastguard Worker self.callWeighting = weight 88*9880d681SAndroid Build Coastguard Worker 89*9880d681SAndroid Build Coastguard Worker def writeln(self, line): 90*9880d681SAndroid Build Coastguard Worker self.kfile.write(line + '\n') 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker def writeComment(self, comment): 93*9880d681SAndroid Build Coastguard Worker self.writeln('# ' + comment) 94*9880d681SAndroid Build Coastguard Worker 95*9880d681SAndroid Build Coastguard Worker def writeEmptyLine(self): 96*9880d681SAndroid Build Coastguard Worker self.writeln("") 97*9880d681SAndroid Build Coastguard Worker 98*9880d681SAndroid Build Coastguard Worker def writePredefinedFunctions(self): 99*9880d681SAndroid Build Coastguard Worker self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") 100*9880d681SAndroid Build Coastguard Worker self.writeComment("and just returns the RHS.") 101*9880d681SAndroid Build Coastguard Worker self.writeln("def binary : 1 (x y) y;") 102*9880d681SAndroid Build Coastguard Worker self.writeEmptyLine() 103*9880d681SAndroid Build Coastguard Worker self.writeComment("Helper functions defined within toy") 104*9880d681SAndroid Build Coastguard Worker self.writeln("extern putchard(x);") 105*9880d681SAndroid Build Coastguard Worker self.writeln("extern printd(d);") 106*9880d681SAndroid Build Coastguard Worker self.writeln("extern printlf();") 107*9880d681SAndroid Build Coastguard Worker self.writeEmptyLine() 108*9880d681SAndroid Build Coastguard Worker self.writeComment("Print the result of a function call") 109*9880d681SAndroid Build Coastguard Worker self.writeln("def printresult(N Result)") 110*9880d681SAndroid Build Coastguard Worker self.writeln(" # 'result('") 111*9880d681SAndroid Build Coastguard Worker self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") 112*9880d681SAndroid Build Coastguard Worker self.writeln(" printd(N) :"); 113*9880d681SAndroid Build Coastguard Worker self.writeln(" # ') = '") 114*9880d681SAndroid Build Coastguard Worker self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") 115*9880d681SAndroid Build Coastguard Worker self.writeln(" printd(Result) :"); 116*9880d681SAndroid Build Coastguard Worker self.writeln(" printlf();") 117*9880d681SAndroid Build Coastguard Worker self.writeEmptyLine() 118*9880d681SAndroid Build Coastguard Worker 119*9880d681SAndroid Build Coastguard Worker def writeRandomOperation(self, LValue, LHS, RHS): 120*9880d681SAndroid Build Coastguard Worker shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) 121*9880d681SAndroid Build Coastguard Worker if shouldCallFunc: 122*9880d681SAndroid Build Coastguard Worker funcToCall = random.randrange(1, self.lastFuncNum - 1) 123*9880d681SAndroid Build Coastguard Worker self.updateFunctionCallMap(self.lastFuncNum, funcToCall) 124*9880d681SAndroid Build Coastguard Worker self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) 125*9880d681SAndroid Build Coastguard Worker else: 126*9880d681SAndroid Build Coastguard Worker possibleOperations = ["+", "-", "*", "/"] 127*9880d681SAndroid Build Coastguard Worker operation = random.choice(possibleOperations) 128*9880d681SAndroid Build Coastguard Worker if operation == "-": 129*9880d681SAndroid Build Coastguard Worker # Don't let our intermediate value become zero 130*9880d681SAndroid Build Coastguard Worker # This is complicated by the fact that '<' is our only comparison operator 131*9880d681SAndroid Build Coastguard Worker self.writeln(" if %s < %s then" % (LHS, RHS)) 132*9880d681SAndroid Build Coastguard Worker self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) 133*9880d681SAndroid Build Coastguard Worker self.writeln(" else if %s < %s then" % (RHS, LHS)) 134*9880d681SAndroid Build Coastguard Worker self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) 135*9880d681SAndroid Build Coastguard Worker self.writeln(" else") 136*9880d681SAndroid Build Coastguard Worker self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) 137*9880d681SAndroid Build Coastguard Worker else: 138*9880d681SAndroid Build Coastguard Worker self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) 139*9880d681SAndroid Build Coastguard Worker 140*9880d681SAndroid Build Coastguard Worker def getNextFuncNum(self): 141*9880d681SAndroid Build Coastguard Worker result = self.nextFuncNum 142*9880d681SAndroid Build Coastguard Worker self.nextFuncNum += 1 143*9880d681SAndroid Build Coastguard Worker self.lastFuncNum = result 144*9880d681SAndroid Build Coastguard Worker return result 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Worker def writeFunction(self, elements): 147*9880d681SAndroid Build Coastguard Worker funcNum = self.getNextFuncNum() 148*9880d681SAndroid Build Coastguard Worker self.writeComment("Auto-generated function number %d" % funcNum) 149*9880d681SAndroid Build Coastguard Worker self.writeln("def func%d(X Y)" % funcNum) 150*9880d681SAndroid Build Coastguard Worker self.writeln(" var temp1 = X,") 151*9880d681SAndroid Build Coastguard Worker self.writeln(" temp2 = Y,") 152*9880d681SAndroid Build Coastguard Worker self.writeln(" temp3 in") 153*9880d681SAndroid Build Coastguard Worker # Initialize the variable names to be rotated 154*9880d681SAndroid Build Coastguard Worker first = "temp3" 155*9880d681SAndroid Build Coastguard Worker second = "temp1" 156*9880d681SAndroid Build Coastguard Worker third = "temp2" 157*9880d681SAndroid Build Coastguard Worker # Write some random operations 158*9880d681SAndroid Build Coastguard Worker for i in range(elements): 159*9880d681SAndroid Build Coastguard Worker self.writeRandomOperation(first, second, third) 160*9880d681SAndroid Build Coastguard Worker # Rotate the variables 161*9880d681SAndroid Build Coastguard Worker temp = first 162*9880d681SAndroid Build Coastguard Worker first = second 163*9880d681SAndroid Build Coastguard Worker second = third 164*9880d681SAndroid Build Coastguard Worker third = temp 165*9880d681SAndroid Build Coastguard Worker self.writeln(" " + third + ";") 166*9880d681SAndroid Build Coastguard Worker self.writeEmptyLine() 167*9880d681SAndroid Build Coastguard Worker 168*9880d681SAndroid Build Coastguard Worker def writeFunctionCall(self): 169*9880d681SAndroid Build Coastguard Worker self.writeComment("Call the last function") 170*9880d681SAndroid Build Coastguard Worker arg1 = random.uniform(1, 100) 171*9880d681SAndroid Build Coastguard Worker arg2 = random.uniform(1, 100) 172*9880d681SAndroid Build Coastguard Worker self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) 173*9880d681SAndroid Build Coastguard Worker self.writeEmptyLine() 174*9880d681SAndroid Build Coastguard Worker self.updateCalledFunctionList(self.lastFuncNum) 175*9880d681SAndroid Build Coastguard Worker 176*9880d681SAndroid Build Coastguard Worker def writeFinalFunctionCounts(self): 177*9880d681SAndroid Build Coastguard Worker self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Workerdef generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): 180*9880d681SAndroid Build Coastguard Worker """ Generate a random Kaleidoscope script based on the given parameters """ 181*9880d681SAndroid Build Coastguard Worker print "Generating " + filename 182*9880d681SAndroid Build Coastguard Worker print(" %d functions, %d elements per function, %d functions between execution" % 183*9880d681SAndroid Build Coastguard Worker (numFuncs, elementsPerFunc, funcsBetweenExec)) 184*9880d681SAndroid Build Coastguard Worker print(" Call weighting = %f" % callWeighting) 185*9880d681SAndroid Build Coastguard Worker script = KScriptGenerator(filename) 186*9880d681SAndroid Build Coastguard Worker script.setCallWeighting(callWeighting) 187*9880d681SAndroid Build Coastguard Worker script.writeComment("===========================================================================") 188*9880d681SAndroid Build Coastguard Worker script.writeComment("Auto-generated script") 189*9880d681SAndroid Build Coastguard Worker script.writeComment(" %d functions, %d elements per function, %d functions between execution" 190*9880d681SAndroid Build Coastguard Worker % (numFuncs, elementsPerFunc, funcsBetweenExec)) 191*9880d681SAndroid Build Coastguard Worker script.writeComment(" call weighting = %f" % callWeighting) 192*9880d681SAndroid Build Coastguard Worker script.writeComment("===========================================================================") 193*9880d681SAndroid Build Coastguard Worker script.writeEmptyLine() 194*9880d681SAndroid Build Coastguard Worker script.writePredefinedFunctions() 195*9880d681SAndroid Build Coastguard Worker funcsSinceLastExec = 0 196*9880d681SAndroid Build Coastguard Worker for i in range(numFuncs): 197*9880d681SAndroid Build Coastguard Worker script.writeFunction(elementsPerFunc) 198*9880d681SAndroid Build Coastguard Worker funcsSinceLastExec += 1 199*9880d681SAndroid Build Coastguard Worker if funcsSinceLastExec == funcsBetweenExec: 200*9880d681SAndroid Build Coastguard Worker script.writeFunctionCall() 201*9880d681SAndroid Build Coastguard Worker funcsSinceLastExec = 0 202*9880d681SAndroid Build Coastguard Worker # Always end with a function call 203*9880d681SAndroid Build Coastguard Worker if funcsSinceLastExec > 0: 204*9880d681SAndroid Build Coastguard Worker script.writeFunctionCall() 205*9880d681SAndroid Build Coastguard Worker script.writeEmptyLine() 206*9880d681SAndroid Build Coastguard Worker script.writeFinalFunctionCounts() 207*9880d681SAndroid Build Coastguard Worker funcsCalled = len(script.calledFunctions) 208*9880d681SAndroid Build Coastguard Worker print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) 209*9880d681SAndroid Build Coastguard Worker timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) 210*9880d681SAndroid Build Coastguard Worker 211*9880d681SAndroid Build Coastguard Worker# Execution begins here 212*9880d681SAndroid Build Coastguard Workerrandom.seed() 213*9880d681SAndroid Build Coastguard Worker 214*9880d681SAndroid Build Coastguard WorkertimingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") 215*9880d681SAndroid Build Coastguard Worker 216*9880d681SAndroid Build Coastguard WorkerdataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), 217*9880d681SAndroid Build Coastguard Worker (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), 218*9880d681SAndroid Build Coastguard Worker ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] 219*9880d681SAndroid Build Coastguard Worker 220*9880d681SAndroid Build Coastguard Worker# Generate the code 221*9880d681SAndroid Build Coastguard Workerfor (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: 222*9880d681SAndroid Build Coastguard Worker filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) 223*9880d681SAndroid Build Coastguard Worker generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) 224*9880d681SAndroid Build Coastguard Workerprint "All done!" 225