4cc774011b82e2e651d263a06412b600ff94ec03
[platform/core/ml/nnfw.git] / compiler / one-cmds / onecc
1 #!/usr/bin/env bash
2 ''''export SCRIPT_PATH="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)" # '''
3 ''''export PY_PATH=${SCRIPT_PATH}/venv/bin/python                                       # '''
4 ''''test -f ${PY_PATH} && exec ${PY_PATH} "$0" "$@"                                     # '''
5 ''''echo "Error: Virtual environment not found. Please run 'one-prepare-venv' command." # '''
6 ''''exit 255                                                                            # '''
7
8 # Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
9 #
10 # Licensed under the Apache License, Version 2.0 (the "License");
11 # you may not use this file except in compliance with the License.
12 # You may obtain a copy of the License at
13 #
14 #    http://www.apache.org/licenses/LICENSE-2.0
15 #
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS,
18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 # See the License for the specific language governing permissions and
20 # limitations under the License.
21
22 import argparse
23 import configparser
24 import os
25 import subprocess
26 import sys
27
28 from onelib.CfgRunner import CfgRunner
29 from onelib.WorkflowRunner import WorkflowRunner
30 import onelib.utils as oneutils
31
32 # TODO Find better way to suppress trackback on error
33 sys.tracebacklimit = 0
34
35 subtool_list = {
36     'compile': {
37         'import': 'Convert given model to circle',
38         'optimize': 'Optimize circle model',
39         'quantize': 'Quantize circle model',
40     },
41     'package': {
42         'pack': 'Package circle and metadata into nnpackage',
43     },
44     'backend': {
45         'codegen': 'Code generation tool',
46         'profile': 'Profile backend model file',
47         'infer': 'Infer backend model file'
48     },
49 }
50
51
52 def _call_driver(driver_name, options):
53     dir_path = os.path.dirname(os.path.realpath(__file__))
54     driver_path = os.path.join(dir_path, driver_name)
55     cmd = [driver_path] + options
56     oneutils.run(cmd)
57
58
59 def _check_subtool_exists():
60     """verify given arguments"""
61     subtool_keys = [n for k, v in subtool_list.items() for n in v.keys()]
62     if len(sys.argv) > 1 and sys.argv[1] in subtool_keys:
63         driver_name = 'one-' + sys.argv[1]
64         options = sys.argv[2:]
65         _call_driver(driver_name, options)
66         sys.exit(0)
67
68
69 def _get_parser():
70     onecc_usage = 'onecc [-h] [-v] [-C CONFIG] [-W WORKFLOW] [-O OPTIMIZATION] [COMMAND <args>]'
71     onecc_desc = 'Run ONE driver via several commands or configuration file'
72     parser = argparse.ArgumentParser(description=onecc_desc, usage=onecc_usage)
73
74     oneutils.add_default_arg(parser)
75
76     opt_name_list = oneutils.get_optimization_list(get_name=True)
77     opt_name_list = ['-' + s for s in opt_name_list]
78     if not opt_name_list:
79         opt_help_message = '(No available optimization options)'
80     else:
81         opt_help_message = '(Available optimization options: ' + ', '.join(
82             opt_name_list) + ')'
83     opt_help_message = 'optimization name to use ' + opt_help_message
84     parser.add_argument('-O', type=str, metavar='OPTIMIZATION', help=opt_help_message)
85
86     parser.add_argument(
87         '-W', '--workflow', type=str, metavar='WORKFLOW', help='run with workflow file')
88
89     # just for help message
90     compile_group = parser.add_argument_group('compile to circle model')
91     for tool, desc in subtool_list['compile'].items():
92         compile_group.add_argument(tool, action='store_true', help=desc)
93
94     package_group = parser.add_argument_group('package circle model')
95     for tool, desc in subtool_list['package'].items():
96         package_group.add_argument(tool, action='store_true', help=desc)
97
98     backend_group = parser.add_argument_group('run backend tools')
99     for tool, desc in subtool_list['backend'].items():
100         backend_group.add_argument(tool, action='store_true', help=desc)
101
102     return parser
103
104
105 def _parse_arg(parser):
106     args = parser.parse_args()
107     # print version
108     if args.version:
109         oneutils.print_version_and_exit(__file__)
110
111     return args
112
113
114 def _verify_arg(parser, args):
115     """verify given arguments"""
116     # check if required arguments is given
117     if not oneutils.is_valid_attr(args, 'config') and not oneutils.is_valid_attr(
118             args, 'workflow'):
119         parser.error('-C/--config or -W/--workflow argument is required')
120     # check if given optimization option exists
121     opt_name_list = oneutils.get_optimization_list(get_name=True)
122     opt_name_list = [oneutils.remove_prefix(s, 'O') for s in opt_name_list]
123     if oneutils.is_valid_attr(args, 'O'):
124         if ' ' in getattr(args, 'O'):
125             parser.error('Not allowed to have space in the optimization name')
126         if not getattr(args, 'O') in opt_name_list:
127             parser.error('Invalid optimization option')
128
129
130 def main():
131     # check if there is subtool argument
132     # if true, it executes subtool with argv
133     # NOTE:
134     # Why call subtool directly without using Argparse?
135     # Because if Argparse is used, options equivalent to onecc including
136     # '--help', '-C' are processed directly onecc itself.
137     # So options cannot be delivered to subtool.
138     _check_subtool_exists()
139
140     # parse arguments
141     # since the configuration file path is required first,
142     # parsing of the configuration file proceeds after this.
143     parser = _get_parser()
144     args = _parse_arg(parser)
145
146     # verify arguments
147     _verify_arg(parser, args)
148
149     bin_dir = os.path.dirname(os.path.realpath(__file__))
150     if oneutils.is_valid_attr(args, 'config'):
151         runner = CfgRunner(args.config)
152         runner.detect_import_drivers(bin_dir)
153         if oneutils.is_valid_attr(args, 'O'):
154             runner.add_opt(getattr(args, 'O'))
155         runner.run(bin_dir)
156     elif oneutils.is_valid_attr(args, 'workflow'):
157         runner = WorkflowRunner(args.workflow)
158         runner.run(bin_dir)
159
160
161 if __name__ == '__main__':
162     oneutils.safemain(main, __file__)