blob: 327ad4f9fb417e54759aa56fbb85efc36c5650fe [file] [log] [blame]
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +02001# Process the test results
2# Test status (like passed, or failed with error code)
3
4import argparse
5import re
6import TestScripts.NewParser as parse
7import TestScripts.CodeGen
8from collections import deque
9import os.path
10import csv
Christophe Favergeonf76a8032019-08-09 09:15:50 +010011import TestScripts.ParseTrace
Christophe Favergeon30c03792019-10-03 12:47:41 +010012import colorama
13from colorama import init,Fore, Back, Style
Christophe Favergeon512b1482020-02-07 11:25:11 +010014import sys
15
16resultStatus=0
Christophe Favergeonf76a8032019-08-09 09:15:50 +010017
Christophe Favergeon30c03792019-10-03 12:47:41 +010018init()
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +020019
Christophe Favergeon2942a332020-01-20 14:18:48 +010020
Christophe Favergeon6f8eee92019-10-09 12:21:27 +010021def errorStr(id):
22 if id == 1:
23 return("UNKNOWN_ERROR")
24 if id == 2:
25 return("Equality error")
26 if id == 3:
27 return("Absolute difference error")
28 if id == 4:
29 return("Relative difference error")
30 if id == 5:
31 return("SNR error")
32 if id == 6:
33 return("Different length error")
34 if id == 7:
35 return("Assertion error")
36 if id == 8:
37 return("Memory allocation error")
38 if id == 9:
39 return("Empty pattern error")
40 if id == 10:
41 return("Buffer tail corrupted")
Christophe Favergeonf055bd32019-10-15 12:30:30 +010042 if id == 11:
43 return("Close float error")
Christophe Favergeon6f8eee92019-10-09 12:21:27 +010044
45 return("Unknown error %d" % id)
46
47
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +020048def findItem(root,path):
49 """ Find a node in a tree
50
51 Args:
52 path (list) : A list of node ID
53 This list is describing a path in the tree.
54 By starting from the root and following this path,
55 we can find the node in the tree.
56 Raises:
57 Nothing
58 Returns:
59 TreeItem : A node
60 """
61 # The list is converted into a queue.
62 q = deque(path)
63 q.popleft()
64 c = root
65 while q:
66 n = q.popleft()
67 # We get the children based on its ID and continue
68 c = c[n-1]
69 return(c)
70
71def joinit(iterable, delimiter):
72 # Intersperse a delimiter between element of a list
73 it = iter(iterable)
74 yield next(it)
75 for x in it:
76 yield delimiter
77 yield x
78
79# Return test result as a text tree
80class TextFormatter:
81 def start(self):
82 None
83
84 def printGroup(self,elem,theId):
85 if elem is None:
86 elem = root
87 message=elem.data["message"]
88 if not elem.data["deprecated"]:
89 kind = "Suite"
90 ident = " " * elem.ident
91 if elem.kind == TestScripts.Parser.TreeElem.GROUP:
92 kind = "Group"
93 #print(elem.path)
Christophe Favergeon30c03792019-10-03 12:47:41 +010094 print(Style.BRIGHT + ("%s%s : %s (%d)" % (ident,kind,message,theId)) + Style.RESET_ALL)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +020095
Christophe Favergeon4f462732019-11-13 14:11:14 +010096 def printTest(self,elem, theId, theError,errorDetail,theLine,passed,cycles,params):
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +020097 message=elem.data["message"]
Christophe Favergeon4fa1e232020-05-15 12:28:17 +020098 func=elem.data["class"]
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +020099 if not elem.data["deprecated"]:
100 kind = "Test"
101 ident = " " * elem.ident
Christophe Favergeon30c03792019-10-03 12:47:41 +0100102 p=Fore.RED + "FAILED" + Style.RESET_ALL
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200103 if passed == 1:
Christophe Favergeon30c03792019-10-03 12:47:41 +0100104 p= Fore.GREEN + "PASSED" + Style.RESET_ALL
Christophe Favergeon4fa1e232020-05-15 12:28:17 +0200105 print("%s%s %s(%s - %d)%s : %s (cycles = %d)" % (ident,message,Style.BRIGHT,func,theId,Style.RESET_ALL,p,cycles))
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200106 if params:
107 print("%s %s" % (ident,params))
108 if passed != 1:
Christophe Favergeon6f8eee92019-10-09 12:21:27 +0100109 print(Fore.RED + ("%s %s at line %d" % (ident, errorStr(theError), theLine)) + Style.RESET_ALL)
Christophe Favergeon4f462732019-11-13 14:11:14 +0100110 if (len(errorDetail)>0):
111 print(Fore.RED + ident + " " + errorDetail + Style.RESET_ALL)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200112
113 def pop(self):
114 None
115
116 def end(self):
117 None
118
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100119# Return test result as a text tree
120class HTMLFormatter:
121 def __init__(self):
122 self.nb=1
123 self.suite=False
124
125 def start(self):
126 print("<html><head><title>Test Results</title></head><body>")
127
128 def printGroup(self,elem,theId):
129 if elem is None:
130 elem = root
131 message=elem.data["message"]
132 if not elem.data["deprecated"]:
133 kind = "Suite"
134 ident = " " * elem.ident
135 if elem.kind == TestScripts.Parser.TreeElem.GROUP:
136 kind = "Group"
137 if kind == "Group":
138 print("<h%d> %s (%d) </h%d>" % (self.nb,message,theId,self.nb))
139 else:
140 print("<h%d> %s (%d) </h%d>" % (self.nb,message,theId,self.nb))
141 self.suite=True
142 print("<table style=\"width:100%\">")
143 print("<tr>")
144 print("<td>Name</td>")
145 print("<td>ID</td>")
146 print("<td>Status</td>")
Christophe Favergeon59aeeea2019-11-20 13:39:05 +0100147 print("<td>Params</td>")
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100148 print("<td>Cycles</td>")
149 print("</tr>")
150 self.nb = self.nb + 1
151
152 def printTest(self,elem, theId, theError,errorDetail,theLine,passed,cycles,params):
153 message=elem.data["message"]
154 if not elem.data["deprecated"]:
155 kind = "Test"
156 ident = " " * elem.ident
157 p="<font color=\"red\">FAILED</font>"
158 if passed == 1:
159 p= "<font color=\"green\">PASSED</font>"
160 print("<tr>")
Christophe Favergeon4fa1e232020-05-15 12:28:17 +0200161 print("<td><pre>%s</pre></td>" % (message,))
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100162 print("<td>%d</td>" % theId)
163 print("<td>%s</td>" % p)
Christophe Favergeon59aeeea2019-11-20 13:39:05 +0100164 if params:
165 print("<td>%s</td>\n" % (params))
166 else:
167 print("<td></td>\n")
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100168 print("<td>%d</td>" % cycles)
169 print("</tr>")
Christophe Favergeon59aeeea2019-11-20 13:39:05 +0100170
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100171 if passed != 1:
172
173 print("<tr><td colspan=4><font color=\"red\">%s at line %d</font></td></tr>" % (errorStr(theError), theLine))
174 if (len(errorDetail)>0):
175 print("<tr><td colspan=4><font color=\"red\">" + errorDetail + "</font></td></tr>")
176
177 def pop(self):
178 if self.suite:
179 print("</table>")
180 self.nb = self.nb - 1
181 self.suite=False
182
183 def end(self):
184 print("</body></html>")
185
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200186# Return test result as a CSV
187class CSVFormatter:
188
189 def __init__(self):
190 self.name=[]
191 self._start=True
192
193 def start(self):
194 print("CATEGORY,NAME,ID,STATUS,CYCLES,PARAMS")
195
196 def printGroup(self,elem,theId):
197 if elem is None:
198 elem = root
199 # Remove Root from category name in CSV file.
200 if not self._start:
201 self.name.append(elem.data["class"])
202 else:
203 self._start=False
204 message=elem.data["message"]
205 if not elem.data["deprecated"]:
206 kind = "Suite"
207 ident = " " * elem.ident
208 if elem.kind == TestScripts.Parser.TreeElem.GROUP:
209 kind = "Group"
210
Christophe Favergeon4f462732019-11-13 14:11:14 +0100211 def printTest(self,elem, theId, theError, errorDetail,theLine,passed,cycles,params):
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200212 message=elem.data["message"]
213 if not elem.data["deprecated"]:
214 kind = "Test"
215 name=elem.data["class"]
216 category= "".join(list(joinit(self.name,":")))
217 print("%s,%s,%d,%d,%d,\"%s\"" % (category,name,theId,passed,cycles,params))
218
219 def pop(self):
220 if self.name:
221 self.name.pop()
222
223 def end(self):
224 None
225
226class MathematicaFormatter:
227
228 def __init__(self):
229 self._hasContent=[False]
230 self._toPop=[]
231
232 def start(self):
233 None
234
235 def printGroup(self,elem,theId):
236 if self._hasContent[len(self._hasContent)-1]:
237 print(",",end="")
238
239 print("<|")
240 self._hasContent[len(self._hasContent)-1] = True
241 self._hasContent.append(False)
242 if elem is None:
243 elem = root
244 message=elem.data["message"]
245 if not elem.data["deprecated"]:
246
247 kind = "Suite"
248 ident = " " * elem.ident
249 if elem.kind == TestScripts.Parser.TreeElem.GROUP:
250 kind = "Group"
251 print("\"%s\" ->" % (message))
252 #if kind == "Suite":
253 print("{",end="")
254 self._toPop.append("}")
255 #else:
256 # self._toPop.append("")
257
Christophe Favergeon4f462732019-11-13 14:11:14 +0100258 def printTest(self,elem, theId, theError,errorDetail,theLine,passed,cycles,params):
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200259 message=elem.data["message"]
260 if not elem.data["deprecated"]:
261 kind = "Test"
262 ident = " " * elem.ident
263 p="FAILED"
264 if passed == 1:
265 p="PASSED"
266 parameters=""
267 if params:
268 parameters = "%s" % params
269 if self._hasContent[len(self._hasContent)-1]:
270 print(",",end="")
271 print("<|\"NAME\" -> \"%s\",\"ID\" -> %d,\"STATUS\" -> \"%s\",\"CYCLES\" -> %d,\"PARAMS\" -> \"%s\"|>" % (message,theId,p,cycles,parameters))
272 self._hasContent[len(self._hasContent)-1] = True
273 #if passed != 1:
274 # print("%s Error = %d at line %d" % (ident, theError, theLine))
275
276 def pop(self):
277 print(self._toPop.pop(),end="")
278 print("|>")
279 self._hasContent.pop()
280
281 def end(self):
282 None
283
284NORMAL = 1
285INTEST = 2
286TESTPARAM = 3
Christophe Favergeon4f462732019-11-13 14:11:14 +0100287ERRORDESC = 4
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200288
289def createMissingDir(destPath):
290 theDir=os.path.normpath(os.path.dirname(destPath))
291 if not os.path.exists(theDir):
292 os.makedirs(theDir)
293
294def correctPath(path):
295 while (path[0]=="/") or (path[0] == "\\"):
296 path = path[1:]
297 return(path)
298
299def extractDataFiles(results,outputDir):
300 infile = False
301 f = None
302 for l in results:
303 if re.match(r'^.*D:[ ].*$',l):
304 if infile:
305 if re.match(r'^.*D:[ ]END$',l):
306 infile = False
307 if f:
308 f.close()
309 else:
310 if f:
311 m = re.match(r'^.*D:[ ](.*)$',l)
312 data = m.group(1)
313 f.write(data)
314 f.write("\n")
315
316 else:
317 m = re.match(r'^.*D:[ ](.*)$',l)
318 path = str(m.group(1))
319 infile = True
320 destPath = os.path.join(outputDir,correctPath(path))
321 createMissingDir(destPath)
322 f = open(destPath,"w")
323
324
325
326def writeBenchmark(elem,benchFile,theId,theError,passed,cycles,params,config):
327 if benchFile:
Christophe Favergeon4fa1e232020-05-15 12:28:17 +0200328 testname=elem.data["class"]
329 #category= elem.categoryDesc()
330 name=elem.data["message"]
331 category=elem.getSuiteMessage()
Christophe Favergeon37b86222019-07-17 11:49:00 +0200332 old=""
333 if "testData" in elem.data:
334 if "oldID" in elem.data["testData"]:
335 old=elem.data["testData"]["oldID"]
Christophe Favergeon4fa1e232020-05-15 12:28:17 +0200336 benchFile.write("\"%s\",\"%s\",\"%s\",%d,\"%s\",%s,%d,%s\n" % (category,testname,name,theId,old,params,cycles,config))
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200337
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100338def getCyclesFromTrace(trace):
339 if not trace:
340 return(0)
341 else:
342 return(TestScripts.ParseTrace.getCycles(trace))
343
Christophe Favergeon5cacf9d2019-08-14 10:41:17 +0200344def analyseResult(resultPath,root,results,embedded,benchmark,trace,formatter):
Christophe Favergeon512b1482020-02-07 11:25:11 +0100345 global resultStatus
Christophe Favergeonbe7efb42019-08-09 10:17:03 +0100346 calibration = 0
347 if trace:
348 # First cycle in the trace is the calibration data
349 # The noramlisation factor must be coherent with the C code one.
350 calibration = int(getCyclesFromTrace(trace) / 20)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200351 formatter.start()
352 path = []
353 state = NORMAL
354 prefix=""
355 elem=None
356 theId=None
357 theError=None
Christophe Favergeon4f462732019-11-13 14:11:14 +0100358 errorDetail=""
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200359 theLine=None
360 passed=0
361 cycles=None
362 benchFile = None
363 config=""
364 if embedded:
Christophe Favergeon830283b2020-04-27 14:51:08 +0200365 prefix = ".*[S]+:[ ]"
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200366
367 # Parse the result file.
368 # NORMAL mode is when we are parsing suite or group.
369 # Otherwise we are parsing a test and we need to analyse the
370 # test result.
371 # TESTPARAM is used to read parameters of the test.
372 # Format of output is:
373 #node ident : s id or g id or t or u
374 #test status : id error linenb status Y or N (Y when passing)
375 #param for this test b x,x,x,x or b alone if not param
376 #node end : p
377 # In FPGA mode:
378 #Prefix S:[ ] before driver dump
379 # D:[ ] before data dump (output patterns)
380
381 for l in results:
382 l = l.strip()
383 if not re.match(r'^.*D:[ ].*$',l):
384 if state == NORMAL:
385 if len(l) > 0:
386 # Line starting with g or s is a suite or group.
387 # In FPGA mode, those line are prefixed with 'S: '
388 # and data file with 'D: '
389 if re.match(r'^%s[gs][ ]+[0-9]+.*$' % prefix,l):
390 # Extract the test id
391 theId=re.sub(r'^%s[gs][ ]+([0-9]+).*$' % prefix,r'\1',l)
392 theId=int(theId)
393 path.append(theId)
394 # From a list of id, find the TreeElem in the Parsed tree
395 # to know what is the node.
396 elem = findItem(root,path)
397 # Display formatted output for this node
398 if elem.params:
399 #print(elem.params.full)
400 benchPath = os.path.join(benchmark,elem.fullPath(),"fullBenchmark.csv")
401 createMissingDir(benchPath)
402 if benchFile:
403 printf("ERROR BENCH FILE %s ALREADY OPEN" % benchPath)
404 benchFile.close()
405 benchFile=None
406 benchFile=open(benchPath,"w")
407 header = "".join(list(joinit(elem.params.full,",")))
408 # A test and a benchmark are different
409 # so we don't dump a status and error
410 # A status and error in a benchmark would
411 # impact the cycles since the test
412 # would be taken into account in the measurement
413 # So benchmark are always passing and contain no test
414 #benchFile.write("ID,%s,PASSED,ERROR,CYCLES\n" % header)
415 csvheaders = ""
416
Christophe Favergeon5cacf9d2019-08-14 10:41:17 +0200417 with open(os.path.join(resultPath,'currentConfig.csv'), 'r') as f:
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200418 reader = csv.reader(f)
419 csvheaders = next(reader, None)
420 configList = list(reader)
421 #print(configList)
422 config = "".join(list(joinit(configList[0],",")))
423 configHeaders = "".join(list(joinit(csvheaders,",")))
Christophe Favergeon4fa1e232020-05-15 12:28:17 +0200424 benchFile.write("CATEGORY,TESTNAME,NAME,ID,OLDID,%s,CYCLES,%s\n" % (header,configHeaders))
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200425
426 formatter.printGroup(elem,theId)
427
428 # If we have detected a test, we switch to test mode
429 if re.match(r'^%s[t][ ]*$' % prefix,l):
430 state = INTEST
431
432
433 # Pop
434 # End of suite or group
435 if re.match(r'^%sp.*$' % prefix,l):
436 if benchFile:
437 benchFile.close()
438 benchFile=None
439 path.pop()
440 formatter.pop()
441 elif state == INTEST:
442 if len(l) > 0:
443 # In test mode, we are looking for test status.
444 # A line starting with S
445 # (There may be empty lines or line for data files)
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100446 passRe = r'^%s([0-9]+)[ ]+([0-9]+)[ ]+([0-9]+)[ ]+([t0-9]+)[ ]+([YN]).*$' % prefix
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200447 if re.match(passRe,l):
448 # If we have found a test status then we will start again
449 # in normal mode after this.
450
451 m = re.match(passRe,l)
452
453 # Extract test ID, test error code, line number and status
454 theId=m.group(1)
455 theId=int(theId)
456
457 theError=m.group(2)
458 theError=int(theError)
459
460 theLine=m.group(3)
461 theLine=int(theLine)
462
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100463 maybeCycles = m.group(4)
464 if maybeCycles == "t":
Christophe Favergeonbe7efb42019-08-09 10:17:03 +0100465 cycles = getCyclesFromTrace(trace) - calibration
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100466 else:
467 cycles = int(maybeCycles)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200468
469 status=m.group(5)
470 passed=0
471
472 # Convert status to number as used by formatter.
473 if status=="Y":
474 passed = 1
475 if status=="N":
476 passed = 0
477 # Compute path to this node
478 newPath=path.copy()
479 newPath.append(theId)
480 # Find the node in the Tree
481 elem = findItem(root,newPath)
482
483
Christophe Favergeon4f462732019-11-13 14:11:14 +0100484 state = ERRORDESC
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200485 else:
486 if re.match(r'^%sp.*$' % prefix,l):
487 if benchFile:
488 benchFile.close()
489 benchFile=None
490 path.pop()
491 formatter.pop()
492 if re.match(r'^%s[t][ ]*$' % prefix,l):
493 state = INTEST
494 else:
495 state = NORMAL
Christophe Favergeon4f462732019-11-13 14:11:14 +0100496 elif state == ERRORDESC:
497 if len(l) > 0:
498 if re.match(r'^.*E:.*$',l):
499 if re.match(r'^.*E:[ ].*$',l):
500 m = re.match(r'^.*E:[ ](.*)$',l)
501 errorDetail = m.group(1)
502 else:
503 errorDetail = ""
504 state = TESTPARAM
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200505 else:
506 if len(l) > 0:
507 state = INTEST
508 params=""
509 if re.match(r'^.*b[ ]+([0-9,]+)$',l):
510 m=re.match(r'^.*b[ ]+([0-9,]+)$',l)
511 params=m.group(1).strip()
512 # Format the node
513 #print(elem.fullPath())
514 #createMissingDir(destPath)
515 writeBenchmark(elem,benchFile,theId,theError,passed,cycles,params,config)
516 else:
517 params=""
518 writeBenchmark(elem,benchFile,theId,theError,passed,cycles,params,config)
519 # Format the node
Christophe Favergeon512b1482020-02-07 11:25:11 +0100520 if not passed:
521 resultStatus=1
Christophe Favergeon4f462732019-11-13 14:11:14 +0100522 formatter.printTest(elem,theId,theError,errorDetail,theLine,passed,cycles,params)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200523
524
525 formatter.end()
526
527
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100528def analyze(root,results,args,trace):
Christophe Favergeon5cacf9d2019-08-14 10:41:17 +0200529 # currentConfig.csv should be in the same place
530 resultPath=os.path.dirname(args.r)
531
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100532 if args.c:
Christophe Favergeon5cacf9d2019-08-14 10:41:17 +0200533 analyseResult(resultPath,root,results,args.e,args.b,trace,CSVFormatter())
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100534 elif args.html:
535 analyseResult(resultPath,root,results,args.e,args.b,trace,HTMLFormatter())
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100536 elif args.m:
Christophe Favergeon5cacf9d2019-08-14 10:41:17 +0200537 analyseResult(resultPath,root,results,args.e,args.b,trace,MathematicaFormatter())
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100538 else:
Christophe Favergeon2942a332020-01-20 14:18:48 +0100539 print("")
540 print(Fore.RED + "The cycles displayed by this script must not be trusted." + Style.RESET_ALL)
541 print(Fore.RED + "They are just an indication. The timing code has not yet been validated." + Style.RESET_ALL)
542 print("")
543
Christophe Favergeon5cacf9d2019-08-14 10:41:17 +0200544 analyseResult(resultPath,root,results,args.e,args.b,trace,TextFormatter())
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100545
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200546parser = argparse.ArgumentParser(description='Parse test description')
547
Christophe Favergeon6f8eee92019-10-09 12:21:27 +0100548parser.add_argument('-f', nargs='?',type = str, default="Output.pickle", help="Test description file path")
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200549# Where the result file can be found
550parser.add_argument('-r', nargs='?',type = str, default=None, help="Result file path")
551parser.add_argument('-c', action='store_true', help="CSV output")
Christophe Favergeone972cbd2019-11-19 15:54:13 +0100552parser.add_argument('-html', action='store_true', help="HTML output")
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200553parser.add_argument('-e', action='store_true', help="Embedded test")
554# -o needed when -e is true to know where to extract the output files
555parser.add_argument('-o', nargs='?',type = str, default="Output", help="Output dir path")
556
557parser.add_argument('-b', nargs='?',type = str, default="FullBenchmark", help="Full Benchmark dir path")
558parser.add_argument('-m', action='store_true', help="Mathematica output")
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100559parser.add_argument('-t', nargs='?',type = str, default=None, help="External trace file")
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200560
561args = parser.parse_args()
562
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100563
Christophe Favergeon512b1482020-02-07 11:25:11 +0100564
565
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200566if args.f is not None:
Christophe Favergeon6f8eee92019-10-09 12:21:27 +0100567 #p = parse.Parser()
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200568 # Parse the test description file
Christophe Favergeon6f8eee92019-10-09 12:21:27 +0100569 #root = p.parse(args.f)
570 root=parse.loadRoot(args.f)
Christophe Favergeonf76a8032019-08-09 09:15:50 +0100571 if args.t:
572 with open(args.t,"r") as trace:
573 with open(args.r,"r") as results:
574 analyze(root,results,args,iter(trace))
575 else:
576 with open(args.r,"r") as results:
577 analyze(root,results,args,None)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200578 if args.e:
579 # In FPGA mode, extract output files from stdout (result file)
580 with open(args.r,"r") as results:
581 extractDataFiles(results,args.o)
Christophe Favergeon512b1482020-02-07 11:25:11 +0100582
583 sys.exit(resultStatus)
Christophe Favergeon3b2a0ee2019-06-12 13:29:14 +0200584
585else:
586 parser.print_help()