import argparse import pickle import sys import subprocess import os import colorama from colorama import init,Fore, Back, Style parser = argparse.ArgumentParser(description='Parse test description') parser.add_argument('-avh', nargs='?',type = str, default="C:/Keil_v5/ARM/VHT", help="AVH folder") parser.add_argument('-d', action='store_true', help="Debug log") parser.add_argument('-n', action='store_true', help="No force rebuild") parser.add_argument('-r', action='store_true', help="Raw results only") parser.add_argument('-c', action='store_true', help="Display cycles (so passing test are displayed)") args = parser.parse_args() DEBUG=False if args.d: DEBUG=True init() sys.path.append("..") from TestScripts.Parser import TreeElem ERROR_OCCURED = False def printTitle(s): print("\n" + Fore.GREEN + Style.BRIGHT + s + Style.RESET_ALL) def printSubTitle(s): print("\n" + Fore.YELLOW + Style.BRIGHT + s + Style.RESET_ALL) def printError(s): print("\n" + Fore.RED + Style.BRIGHT + s + Style.RESET_ALL) # Load Output.pickle files for the test description def loadRoot(f): root = None with open(f,"rb") as inf: root=pickle.load(inf) return(root) # Get test suites from the test descriptions def getSuites(node,filterList,currentList=[]): if node.kind==TreeElem.SUITE: currentList.append(node.data["class"]) if node.kind==TreeElem.GROUP: if not node.data["class"] in filterList: for c in node.children: getSuites(c,filterList,currentList) class Result: def __init__(self,msg,error=False): self._error = error self._msg = msg @property def error(self): return self._error @property def msg(self): return self._msg # Run a command and get error or result # For the test report we don't need the stderr # in case of error since the test report is giving # all the details. So, there is an option to # disable the dump of stderr def run(*args,mustPrint=False,dumpStdErr=True): global ERROR_OCCURED global DEBUG try: if DEBUG: print(" ".join(args)) result=subprocess.run(args,text=True,capture_output=True,timeout=600) if result.returncode !=0 : ERROR_OCCURED = True if dumpStdErr: return(Result(result.stderr + "\n\nSTDOUT:\n\n" + result.stdout,error=True)) else: return(Result(result.stdout,error=True)) if mustPrint: print(result.stdout) return(Result(result.stdout)) except Exception as e: printError("Exception occured") ERROR_OCCURED = True return(Result(str(e),error=True)) # Configuration file for AVH core configFiles={ "CS310":"ARM_VHT_Corstone_310_config.txt", "CS300":"ARM_VHT_Corstone_300_config.txt", "M55":"ARM_VHT_MPS2_M55_config.txt", "M33_DSP_FP":"ARM_VHT_MPS2_M33_DSP_FP_config.txt", "M7DP":"ARM_VHT_MPS2_M7DP_config.txt", "M4FP":"ARM_VHT_MPS2_M4FP_config.txt", "M3":"ARM_VHT_MPS2_M3_config.txt", "M23":"ARM_VHT_MPS2_M23_config.txt", "M0plus":"ARM_VHT_MPS2_M0plus_config.txt", } # Windows executable # (At some point this script will also support # unix) avhExe={ "CS310":"VHT_Corstone_SSE-310.exe", "CS300":"VHT_Corstone_SSE-300_Ethos-U55.exe", "M55":"VHT_MPS2_Cortex-M55.exe", "M33_DSP_FP":"VHT_MPS2_Cortex-M33.exe", "M7DP":"VHT_MPS2_Cortex-M7.exe", "M4FP":"VHT_MPS2_Cortex-M4.exe", "M3":"VHT_MPS2_Cortex-M3.exe", "M23":"VHT_MPS2_Cortex-M23.exe", "M0plus":"VHT_MPS2_Cortex-M0plus.exe", } AVHROOT = args.avh # Run AVH def runAVH(build,core): axf="out/test/%s/Release/test.Release+%s.axf" % (build,build) elf="out/test/%s/Release/test.Release+%s.elf" % (build,build) app = axf if os.path.exists(axf): app = axf if os.path.exists(elf): app = elf config = os.path.join("configs",configFiles[core]) avh = os.path.join(AVHROOT,avhExe[core]) res=run(avh,"-f",config,app) return(res) #################### # Test descriptions to use tests=["../Output.pickle","../Output_f16.pickle"] # Test group to avoid filterList=["NNTests","ExampleTests"] allSuites=[] # Load all the test suite to run for t in tests: root=loadRoot(t) suites=[] getSuites(root,filterList,suites) allSuites += [(x,t) for x in suites ] # Test suite and output pickle needed to decode the result #print(allSuites) #allSuites=[("ComplexTestsF32","../Output.pickle"), #("DistanceTestsF32","../Output.pickle"), #("UnaryTestsF32","../Output.pickle"), #("QuaternionTestsF32","../Output.pickle"), #("StatsTestsF32","../Output.pickle") #] allSuites=[("InterpolationTestsF32","../Output.pickle"), ("InterpolationTestsQ31","../Output.pickle"), ("InterpolationTestsQ15","../Output.pickle"), ("InterpolationTestsQ7","../Output.pickle"), ("InterpolationTestsF16","../Output_f16.pickle"), ] #allSuites=[("StatsTestsQ7","../Output.pickle")] # Solution and build file for all # the tests # It is a pair : csolution target type and AVH identification # AVH identification is used to find the executable # and the configuration file solutions={ 'testac6.csolution.yml':[ # ("VHT-Corstone-310","CS310"), ("VHT-Corstone-300","CS300"), # #("VHT_M33","M33_DSP_FP"), ("VHT_M7","M7DP"), ("VHT_M7_UNROLLED","M7DP"), # #("VHT_M4","M4FP"), # #("VHT_M3","M3"), # #("VHT_M23","M23"), ("VHT_M0P","M0plus") ], 'testgcc.csolution.yml':[ #("VHT-Corstone-310","CS310"), #("VHT_M55","M55"), ##("VHT_M33","M33_DSP_FP"), ("VHT_M7","M7DP"), ("VHT_M7_UNROLLED","M7DP"), ##("VHT_M4","M4FP"), ##("VHT_M3","M3"), ##("VHT_M23","M23"), ("VHT_M0P","M0plus") ] } # Override previous solutions for more restricted testing. #solutions={ # 'testac6.csolution.yml':[ # # ("VHT-Corstone-310","CS310"), # ("VHT-Corstone-300","CS300") # ], # 'testgcc.csolution.yml':[ # #("VHT-Corstone-310","CS310"), # #("VHT_M55","M55"), # ##("VHT_M33","M33_DSP_FP"), # ("VHT_M7","M7DP"), # ] #} HTMLHEADER="""
CMSIS-DSP Test summary
""" HTMLFOOTER=""" """ # Run the tests and log the result # in a summary.html file with open("summary.html","w") as f: print(HTMLHEADER,file=f) for s in solutions: printTitle("Process solution %s" % s) res=run("csolution","convert","-s",s) if res.error: printError("Error csolution") print("

Error converting csolution %s

" % s,file=f)
            print(res.msg,file=f)
            print("
",file=f) continue print("

Solution %s

" % s,file=f) maxNbBuilds=len(solutions[s]) buildNb=0 for build,core in solutions[s]: buildNb = buildNb + 1 print("

Core %s

" % build,file=f) printTitle("Process core %s (%d/%d)" % (build,buildNb,maxNbBuilds)) buildFile="test.Release+%s.cprj" % build nb = 0 maxNb = len(allSuites) for s,pickle in allSuites: nb = nb + 1 printSubTitle("Process suite %s (%d/%d)" % (s,nb,maxNb)) res=run(sys.executable,"../processTests.py","-gen","..","-p","../Patterns","-d","../Parameters","-f",pickle,"-e",s,mustPrint=True) if res.error: printError("Error processTests") print("

Error generating %s

" % s,file=f)
                    print(res.msg,file=f)
                    print("
",file=f) continue if nb==1: # -r is needed for first # build when we switch # between different solutions # (Like one using AC6 and the other # using gcc) if args.n: res=run("cbuild",buildFile) else: res=run("cbuild","-r",buildFile) else: res=run("cbuild",buildFile) if res.error: printError("Error cbuild") print("

Error building %s

" % s,file=f)
                    print(res.msg,file=f)
                    print("
",file=f) continue printSubTitle("Run AVH") res=runAVH(build,core) if res.error: printError("Error running AVH") print("

Error running %s

" % s,file=f)
                    print(res.msg,file=f)
                    print("
",file=f) continue else: with open("results.txt","w") as o: print(res.msg,file=o) # Dump raw result if args.r: print(res.msg) # If raw result, no post processing if not args.r: res=run(sys.executable,"../processResult.py","-f",pickle,"-e","-ahtml","-r","results.txt",dumpStdErr=False) if res.error: printError("Error processResult") print("

Error processing %s result

" % s,file=f)
                        print(res.msg,file=f)
                        print("
",file=f) continue else: # When no error the section is # included in final file on when # cycles are requested if args.c: print(res.msg,file=f) print(HTMLFOOTER,file=f) if ERROR_OCCURED: sys.exit("Error occurred") else: sys.exit(0)