blob: 7cc5f11bf08eb0d9c41ac2ecdffbd5458a05e444 [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001# Copyright (c) 2021 Arm Limited. All rights reserved.
2# SPDX-License-Identifier: Apache-2.0
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""
17Utility script to convert a set of pairs of npy files in a given location into
18corresponding cpp files and a single hpp file referencing the vectors
19from the cpp files.
20"""
21import datetime
22import math
23import os
24import numpy as np
25
26from argparse import ArgumentParser
27from jinja2 import Environment, FileSystemLoader
28
29parser = ArgumentParser()
30parser.add_argument("--data_folder_path", type=str, help="path to ifm-ofm npy folder to convert.")
31parser.add_argument("--source_folder_path", type=str, help="path to source folder to be generated.")
32parser.add_argument("--header_folder_path", type=str, help="path to header folder to be generated.")
33parser.add_argument("--usecase", type=str, default="", help="Test data file suffix.")
34parser.add_argument("--namespaces", action='append', default=[])
35parser.add_argument("--license_template", type=str, help="Header template file",
36 default="header_template.txt")
37parser.add_argument("-v", "--verbosity", action="store_true")
38
39args = parser.parse_args()
40
41env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')),
42 trim_blocks=True,
43 lstrip_blocks=True)
44
45
46def write_hpp_file(header_filename, cc_file_path, header_template_file, num_iofms,
47 ifm_array_names, ifm_size, ofm_array_names, ofm_size, iofm_data_type):
48 header_file_path = os.path.join(args.header_folder_path, header_filename)
49
50 print(f"++ Generating {header_file_path}")
51 header_template = env.get_template(header_template_file)
52 hdr = header_template.render(script_name=os.path.basename(__file__),
53 gen_time=datetime.datetime.now(),
54 year=datetime.datetime.now().year)
55 env.get_template('TestData.hpp.template').stream(common_template_header=hdr,
56 fm_count=num_iofms,
57 ifm_var_names=ifm_array_names,
58 ifm_var_size=ifm_size,
59 ofm_var_names=ofm_array_names,
60 ofm_var_size=ofm_size,
61 data_type=iofm_data_type,
62 namespaces=args.namespaces) \
63 .dump(str(header_file_path))
64
65 env.get_template('TestData.cc.template').stream(common_template_header=hdr,
66 include_h=header_filename,
67 ifm_var_names=ifm_array_names,
68 ofm_var_names=ofm_array_names,
69 data_type=iofm_data_type,
70 namespaces=args.namespaces) \
71 .dump(str(cc_file_path))
72
73
74def write_individual_cc_file(filename, cc_filename, header_filename, header_template_file, array_name, iofm_data_type):
75 print(f"++ Converting {filename} to {os.path.basename(cc_filename)}")
76 header_template = env.get_template(header_template_file)
77 hdr = header_template.render(script_name=os.path.basename(__file__),
78 gen_time=datetime.datetime.now(),
79 file_name=os.path.basename(filename),
80 year=datetime.datetime.now().year)
81
82 # Convert the image and write it to the cc file
83 fm_data = (np.load(os.path.join(args.data_folder_path, filename))).flatten()
84 type(fm_data.dtype)
85 hex_line_generator = (', '.join(map(hex, sub_arr))
86 for sub_arr in np.array_split(fm_data, math.ceil(len(fm_data) / 20)))
87
88 env.get_template('testdata.cc.template').stream(common_template_header=hdr,
89 include_h=header_filename,
90 var_name=array_name,
91 fm_data=hex_line_generator,
92 data_type=iofm_data_type,
93 namespaces=args.namespaces) \
94 .dump(str(cc_filename))
95
96
97def get_npy_vec_size(filename: str) -> int:
98 """
99 Gets the size of the array in the npy file
100 Args:
101 filename: npy file path.
102 Return:
103 size in bytes
104 """
105 data = np.load(os.path.join(args.data_folder_path, filename))
106 return (data.size * data.dtype.itemsize)
107
108
109def main(args):
110 # Keep the count of the images converted
111 ifm_array_names = []
112 ofm_array_names = []
113
114 add_usecase_fname = ("_" + args.usecase) if (args.usecase is not "") else ""
115 header_filename = "TestData" + add_usecase_fname + ".hpp"
116 common_cc_filename = "TestData" + add_usecase_fname + ".cc"
117
118 # In the data_folder_path there should be pairs of ifm-ofm
119 # It's assumed the ifm-ofm nameing convention: ifm0.npy-ofm0.npy, ifm1.npy-ofm1.npy
120 i_ofms_count = int(len([name for name in os.listdir(os.path.join(args.data_folder_path)) if name.lower().endswith('.npy')]) / 2)
121
122 iofm_data_type = "int8_t"
123 if (i_ofms_count > 0):
124 iofm_data_type = "int8_t" if (np.load(os.path.join(args.data_folder_path, "ifm0.npy")).dtype == np.int8) else "uint8_t"
125
126 ifm_size = -1
127 ofm_size = -1
128
129 for idx in range(i_ofms_count):
130 # Save the fm cc file
131 base_name = "ifm" + str(idx)
132 filename = base_name+".npy"
133 array_name = base_name + add_usecase_fname
134 cc_filename = os.path.join(args.source_folder_path, array_name + ".cc")
135 ifm_array_names.append(array_name)
136 write_individual_cc_file(filename, cc_filename, header_filename, args.license_template, array_name, iofm_data_type)
137 if ifm_size == -1:
138 ifm_size = get_npy_vec_size(filename)
139 elif ifm_size != get_npy_vec_size(filename):
140 raise Exeception(f"ifm size changed for index {idx}")
141
142 # Save the fm cc file
143 base_name = "ofm" + str(idx)
144 filename = base_name+".npy"
145 array_name = base_name + add_usecase_fname
146 cc_filename = os.path.join(args.source_folder_path, array_name + ".cc")
147 ofm_array_names.append(array_name)
148 write_individual_cc_file(filename, cc_filename, header_filename, args.license_template, array_name, iofm_data_type)
149 if ofm_size == -1:
150 ofm_size = get_npy_vec_size(filename)
151 elif ofm_size != get_npy_vec_size(filename):
152 raise Exeception(f"ofm size changed for index {idx}")
153
154 common_cc_filepath = os.path.join(args.source_folder_path, common_cc_filename)
155 write_hpp_file(header_filename, common_cc_filepath, args.license_template,
156 i_ofms_count, ifm_array_names, ifm_size, ofm_array_names, ofm_size, iofm_data_type)
157
158
159if __name__ == '__main__':
160 if args.verbosity:
161 print("Running gen_test_data_cpp with args: "+str(args))
162 main(args)