Skip to content

Commit

Permalink
tools: add support for parsing benchmark using extra python script
Browse files Browse the repository at this point in the history
User can specify parsescript in run_config section to specify an
extra python script to parse benchmark in run log

Function should like below(take parse_benchmark_runlog as example):

def parse_benchmark(lines, lgf=""):
    return program_type, subtype, result

json config like below:

{$
     "run_config": {$
         "target" : "qemu",$
         "parsescript": "parse.py",$
         "hardware" : {$
             "baudrate": 115200,$
             "timeout": 60$
         },$
         "qemu": {$
             "qemu32": "qemu-system-riscv32",$
             "qemu64": "qemu-system-riscv64",$
             "timeout": 60$
         }$
     }
}

Signed-off-by: Huaqi Fang <578567190@qq.com>
  • Loading branch information
fanghuaqi committed Oct 12, 2022
1 parent ecd5a95 commit 5f546fa
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 6 deletions.
21 changes: 15 additions & 6 deletions tools/scripts/nsdk_cli/nsdk_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,13 +477,16 @@ def build_target_in_directory(self, rootdir, make_options="", target="", \
return cmdsts, build_status
return cmdsts, build_status

def analyze_runlog(self, logfile):
def analyze_runlog(self, logfile, parsescript=None):
result = {"type": "unknown", "value": {}}
if os.path.isfile(logfile):
result_lines = open(logfile).readlines()
program_found, subtype, result_parsed = parse_benchmark_runlog(result_lines, lgf=logfile)
if program_found == PROGRAM_UNKNOWN:
program_found, subtype, result_parsed = parse_benchmark_use_pyscript(result_lines, logfile, parsescript)
if program_found != PROGRAM_UNKNOWN:
result = {"type": program_found, "subtype": subtype, "value": result_parsed}

return result

def run_app_onhw(self, appdir, runcfg:dict(), show_output=True, logfile=None, uploadlog=None):
Expand Down Expand Up @@ -597,6 +600,8 @@ def run_app_onqemu(self, appdir, runcfg:dict(), show_output=True, logfile=None):
build_download = build_info["DOWNLOAD"]
build_smp = build_info.get("SMP", "")
build_arch_ext = build_config.get("ARCH_EXT", "")
if build_arch_ext == "":
build_arch_ext = build_info.get("ARCH_EXT", "")
if build_smp != "":
qemu_extraopt = "%s -smp %s" % (qemu_extraopt, build_smp)
if qemu_machine is None:
Expand Down Expand Up @@ -665,7 +670,7 @@ def run_app_onxlspike(self, appdir, runcfg:dict(), show_output=True, logfile=Non
riscv_arch = build_info["RISCV_ARCH"]
# replace e with i for xlspike
riscv_arch = riscv_arch.replace("e", "i")
#build_arch_ext = build_config.get("ARCH_EXT", "")
#build_arch_ext = build_info.get("ARCH_EXT", "")
build_smp = build_info.get("SMP", "")
if build_smp != "":
xlspike_extraopt = "%s -p%s" % (xlspike_extraopt, build_smp)
Expand Down Expand Up @@ -792,6 +797,10 @@ def run_app_with_config(self, appdir, appconfig:dict, show_output=True, buildlog
# get run config
app_runcfg = appconfig.get("run_config", dict())
app_runtarget = app_runcfg.get("target", "hardware")
app_parsescript = app_runcfg.get("parsescript", None)
if app_parsescript is not None:
if os.path.isfile(app_parsescript) == False:
app_parsescript = os.path.join(appdir, app_parsescript)
# get run checks
DEFAULT_CHECKS = { "PASS": [ ], "FAIL": [ "MCAUSE:" ] }
app_runchecks = appconfig.get("checks", DEFAULT_CHECKS)
Expand All @@ -809,7 +818,7 @@ def run_app_with_config(self, appdir, appconfig:dict, show_output=True, buildlog
runstatus, uploader = self.run_app_onhw(appdir, runcfg, show_output, runlog, uploadlog)
# If run successfully, then do log analyze
if runlog and runstatus:
appsts["result"] = self.analyze_runlog(runlog)
appsts["result"] = self.analyze_runlog(runlog, app_parsescript)
appsts["logs"]["run"] = runlog
appsts["logs"]["upload"] = uploadlog
appsts["status_code"]["run"] = RUNSTATUS_OK if runstatus else RUNSTATUS_FAIL
Expand All @@ -819,7 +828,7 @@ def run_app_with_config(self, appdir, appconfig:dict, show_output=True, buildlog
runstatus, runner = self.run_app_onqemu(appdir, runcfg, show_output, runlog)
# If run successfully, then do log analyze
if runlog and runstatus:
appsts["result"] = self.analyze_runlog(runlog)
appsts["result"] = self.analyze_runlog(runlog, app_parsescript)
appsts["logs"]["run"] = runlog
appsts["status_code"]["run"] = RUNSTATUS_OK if runstatus else RUNSTATUS_FAIL
if runner:
Expand All @@ -828,7 +837,7 @@ def run_app_with_config(self, appdir, appconfig:dict, show_output=True, buildlog
runstatus, runner = self.run_app_onxlspike(appdir, runcfg, show_output, runlog)
# If run successfully, then do log analyze
if runlog and runstatus:
appsts["result"] = self.analyze_runlog(runlog)
appsts["result"] = self.analyze_runlog(runlog, app_parsescript)
appsts["logs"]["run"] = runlog
appsts["status_code"]["run"] = RUNSTATUS_OK if runstatus else RUNSTATUS_FAIL
if runner:
Expand All @@ -837,7 +846,7 @@ def run_app_with_config(self, appdir, appconfig:dict, show_output=True, buildlog
runstatus, runner = self.run_app_onncycm(appdir, runcfg, show_output, runlog)
# If run successfully, then do log analyze
if runlog and runstatus:
appsts["result"] = self.analyze_runlog(runlog)
appsts["result"] = self.analyze_runlog(runlog, app_parsescript)
appsts["logs"]["run"] = runlog
appsts["status_code"]["run"] = RUNSTATUS_OK if runstatus else RUNSTATUS_FAIL
if runner:
Expand Down
35 changes: 35 additions & 0 deletions tools/scripts/nsdk_cli/nsdk_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

try:
import time
import random
import shutil
import signal
import psutil
Expand All @@ -22,6 +23,7 @@
import glob
import json
import yaml
import importlib.util
except Exception as exc:
print("Import Error: %s" % (exc))
print("Please install requried packages using: pip3 install -r %s" % (requirement_file))
Expand Down Expand Up @@ -256,6 +258,26 @@ def kill_subprocess(proc):
pass
pass

def import_module(module_name, file_path):
if file_path is None or os.path.isfile(file_path) == False:
return None
try:
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
except:
module = None
return module

def import_function(func_name, file_path):
module_name = "tempmodule_%s" % (random.randint(0, 10000))
tmpmodule = import_module(module_name, file_path)
if tmpmodule is None:
return None
if func_name not in dir(tmpmodule):
return None
return getattr(tmpmodule, func_name)

COMMAND_RUNOK=0
COMMAND_INVALID=1
COMMAND_FAIL=2
Expand Down Expand Up @@ -900,6 +922,19 @@ def parse_benchmark_runlog(lines, lgf=""):
program_type, subtype, result = parse_benchmark_compatiable(lines)
return program_type, subtype, result

def parse_benchmark_use_pyscript(lines, lgf, pyscript):
# function should named parse_benchmark
# function argument and return like parse_benchmark_runlog
parsefunc = import_function("parse_benchmark", pyscript)
if parsefunc is None:
return PROGRAM_UNKNOWN, PROGRAM_UNKNOWN, None
try:
program_type, subtype, result = parsefunc(lines, lgf)
return program_type, subtype, result
except Exception as exc:
print("ERROR: Parse using %s script error: %s" %(pyscript, exc))
return PROGRAM_UNKNOWN, PROGRAM_UNKNOWN, None

def check_tool_exist(tool):
exist = False
if sys.platform == 'win32':
Expand Down

0 comments on commit 5f546fa

Please sign in to comment.