• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3#   Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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
16import os
17import re
18import sys
19from collections import defaultdict
20from pathlib import Path
21
22
23def raise_string_exit(raise_string):
24    # raise Exception(raise_string)
25    sys.exit(0)
26
27
28def get_section_state(lines_split_set, name):
29    """
30    name: 要判断section状态的 段名
31    g_state_lst: 需要判断的字符的列表
32    state: 二进制位表示, bit 0 表示load bit 1 表示debug
33    none    -> 00
34    load    -> 01
35    debug   -> 10
36    laod + debug    -> 11
37    """
38    state = 0
39    default_debug_lst = ['.comment', '.riscv.attributes']  # 默认debug的列表
40    # 在debug默认列表中直接返回  10
41    if name in default_debug_lst:
42        return state | 1 << 1
43    lines_split_set = set(lines_split_set)
44    for i, st in enumerate(g_state_lst):
45        if st in lines_split_set:
46            state |= 1 << i
47    return state
48
49
50def conver_to_utf8(input_file, output_file):
51    """
52    判断文件编码是否是uft-8, 否则将文件转化utf-8重新保存
53    """
54    try:
55        with open(input_file, 'r', encoding='utf-8') as f:
56            f.read()
57    except:
58        try:
59            with open(input_file, 'rb') as infile:
60                raw_data = infile.read()
61                decode_txt = raw_data.decode(errors='replace')
62        except Exception as e:
63            print(f"无法解析读取的文件或编码: {e}")
64        try:
65            with open(output_file, 'w', encoding='utf-8') as outfile:
66                outfile.write(decode_txt)
67        except Exception as e:
68            print(f"无法保存文件: {e}")
69
70
71def parse_lst_file(lst_file):
72    conver_to_utf8(lst_file, lst_file)
73    record_flag = 0
74    section_name_dict = {}
75    record_line = ['Idx', 'Name', 'Size', 'VMA', 'LMA', 'File', 'off', 'Algn']
76    with open(lst_file, 'r', encoding='utf-8') as f:
77        lines = f.readlines()
78    i = 0
79    while i < len(lines):
80        # 字符串以 "Sections:" 开始 且 下一行等于 record_line 则开始记录
81        if lines[i].startswith("Sections:"):
82            if lines[i + 1].split()[:3] == record_line[:3]:
83                record_flag = 1
84                i += 2
85                continue
86            else:
87                raise_string_exit(f"Not found {record_line}")
88        if record_flag:
89            name = lines[i].split()[1]
90            section_state = get_section_state(lines[i + 1].split(), name)
91            section_name_dict[name] = section_state
92            i += 2
93            # 不是以空格 开头 则Sections 解析完毕 跳出
94            if not lines[i].startswith(' '):
95                break
96        else:
97            i += 1
98    return section_name_dict
99
100
101def get_mem_address_len_lst_append_idx(name):
102    # ram, flash, rom 关键字特性列表
103    ram_feat_lst = [
104        'CT_SRAM', 'PRESERVE_SHARE_MEM', 'EM_MUX_RAM', 'ITCM', 'DTCM', 'SRAM', 'APP_ITCM', 'APP_DTCM',
105        'CPUTRACE_RAM'
106    ]
107    flash_feat_lst = ['CT_FLASH', 'PROGRAM_STARTUP', 'PROGRAM', 'FLASH_STARTUP', 'FLASH_PROGRAM']
108    rom_feat_lst = ['CT_ROM', 'ROM', 'ACORE_ROM']
109    # 返回 get_mem_address_len_lst 中的行索引
110    if any(feat in name for feat in ram_feat_lst):
111        return 0
112    elif any(feat in name for feat in flash_feat_lst):
113        return 1
114    elif any(feat in name for feat in rom_feat_lst):
115        return 2
116    else:
117        raise_string_exit(f"Unknown not in ['RAM', 'FLASH', 'ROM'] -- {name}")
118
119
120def get_space_type_state(section_name, start_address, mem_address_range_lst):  #### 函数名 根据地址查找占用空间类型
121    """
122    start_address: 段名 开始地址
123    state:
124    none -> 000
125    ram   -> 001
126    flash   -> 010
127    rom -> 100
128    """
129    state = 0
130    for j, lst in enumerate(mem_address_range_lst):
131        for start, end, _ in lst:
132            if start <= start_address < end:
133                state |= 1 << j
134                # state & 1 表示是否在ram中,  且 含有 LOAD 则添加 flash状态
135                if (state & 1) and (lst_info_dict[section_name] >> g_state_lst.index('LOAD,')) & 1:
136                    state |= 1 << 1
137    return state
138
139
140def state2space_type(state):
141    """
142    占用空间类型状态码 转 字符描述
143    """
144    space_type = []
145    space_type_lst = ['RAM', 'FLASH', 'ROM']  # 占用空间类型列表
146    for i, x in enumerate(space_type_lst):
147        if state >> i & 1:
148            space_type.append(x)
149    return ' + '.join(space_type)
150
151
152def parse_section_info(lines, i, debug_flag, mem_address_range_lst):
153    # 解析段名行的信息
154    line_info_lst = lines[i].split()
155    if len(line_info_lst) == 1:
156        # 段名下为空的跳出 不解析
157        if not lines[i + 1].strip():
158            return "continue", debug_flag
159        # 存在段名太长 信息换行的情况
160        line_info_lst += lines[i + 1].split()
161        # 段名下不包含长度信息 不解析
162        if len(line_info_lst) < 3:
163            return "continue", debug_flag
164    # 段名
165    section_name = line_info_lst[0]
166    if section_name in lst_info_dict:
167        # 如果段名是debugging 跳过不处理
168        if (lst_info_dict[section_name] >> g_state_lst.index('DEBUGGING,')) & 1:
169            debug_flag = 1
170            return "continue", debug_flag
171        else:
172            debug_flag = 0
173    else:
174        # 不在 lst_info_dict 里 且 段名长度为 0, 不处理
175        if int(line_info_lst[2], 16) == 0:
176            debug_flag = 1
177            return "continue", debug_flag
178        else:
179            raise_string_exit(f"Not found {section_name} in lst_info_dict -- {i}")
180    # 起始地址
181    start_address = int(line_info_lst[1], 16)
182    # 段长度
183    section_len = int(line_info_lst[2], 16)
184    state = get_space_type_state(section_name, start_address, mem_address_range_lst)
185    if state & 1 and (state >> 1) & 1:
186        # 用于判断 ram+flash情况下 flash地址与ram地址的差值
187        flash_start_address = int(line_info_lst[-1], 16)
188        diff_address = flash_start_address - start_address
189    else:
190        diff_address = 0
191    # 键名
192    map_info_key = (section_name, start_address, section_len, state)
193    return map_info_key, diff_address, debug_flag
194
195
196def parse_symb_info(lines, i, map_info_key, diff_address, symb_info):
197    """
198    解析符号信息
199    """
200    pattern1 = r'\((.*?)\)'  # 寻找库名(o_name)正则匹配
201    pattern2 = r'(\w+\.a)'  # 寻找文件名(a_name)正则匹配
202    o_name_lst = ('S.obj)', 's.obj)', '.o)', 'c.obj)')  # 库名的后缀匹配
203    special_fill_threshold = 24  # fill地址内存的阈值,小于等于24字节的字段被认为是自动对齐的填充字段,不需要解释
204    symbol_type_lst = ('.text', '.rodata', '.data', '.bss')  # 符号类型的元组,不在里面则为 .other
205    line_info_lst = lines[i].split()
206    if len(line_info_lst) == 1:
207        if lines[i + 1].strip().endswith(o_name_lst):
208            line_info_lst += lines[i + 1].split()
209    if line_info_lst[0] == '*fill*':
210        symb_name = line_info_lst[0]
211        symb_start_address = int(line_info_lst[1], 16)
212        symb_len = int(line_info_lst[2], 16)
213        symb_end_address = symb_start_address + symb_len
214        # fill 大小大于 special_fill_threshold 赋值段名
215        if symb_len > special_fill_threshold:
216            a_name = o_name = map_info_key[0]
217        else:
218            a_name, o_name = symb_info[-2], symb_info[-1]
219        symb_info = [symb_start_address, symb_end_address, symb_len, symb_name, '.fill', a_name, o_name]
220    elif not line_info_lst[-1].endswith(o_name_lst):
221        raise_string_exit(f"Not found {o_name_lst} -- {i}")
222    else:
223        symb_name = line_info_lst[0]
224        symb_start_address = int(line_info_lst[1], 16)
225        symb_len = int(line_info_lst[2], 16)
226        symb_end_address = symb_start_address + symb_len
227        symb_type = '.other'
228        for st in symbol_type_lst:
229            if symb_name.startswith(st) or symb_name.endswith(st):
230                symb_type = st
231                break
232        o_name = re.findall(pattern1, line_info_lst[-1])[-1]
233        a_name = re.findall(pattern2, line_info_lst[-1])[0]
234        symb_info = [symb_start_address, symb_end_address, symb_len, symb_name, symb_type, a_name, o_name]
235    # 根据 state 把 symb_info 加入ram_dict, g_flash_dict, g_rom_dict
236    if map_info_key[-1] & 1:
237        if symb_info[2] != 0:
238            g_ram_dict[map_info_key].append(symb_info)
239    if (map_info_key[-1] >> 1) & 1:
240        # 加入flash_dict 的起始地址需要加 diff_address
241        # ram+flash情况下 diff_address!=0
242        # 单flash 情况下 diff_address=0
243        map_info_key_lst = list(map_info_key)
244        map_info_key_lst[1] += diff_address
245        tmp_key = tuple(map_info_key_lst)
246        tmp_symb_info = symb_info.copy()
247        tmp_symb_info[0] += diff_address
248        tmp_symb_info[1] += diff_address
249        if tmp_symb_info[2] != 0:
250            g_flash_dict[tmp_key].append(tmp_symb_info)
251    if (map_info_key[-1] >> 2) & 1:
252        if symb_info[2] != 0:
253            g_rom_dict[map_info_key].append(symb_info)
254    return symb_info
255
256
257def sort_data_dict(data_dict):
258    """
259    data_dict 按键值的 起始地址大小 从小到大排序
260    """
261    data_dict = dict(sorted(data_dict.items(), key=lambda x: x[0][1]))
262    return data_dict
263
264
265def check_is_overlap(data_dict):
266    """
267    检查同一个段名下的 地址是否重叠  首地址 a 尾地址 b
268    a-b<0 -> 调整
269    a=b -> 跳过
270    a-b>0 -> 报错
271    """
272    for k, lst in data_dict.items():
273        for i in range(1, len(lst)):
274            a, b = lst[i][0], lst[i - 1][1]
275            if a - b < 0:
276                lst[i][0] = b
277                lst[i][2] = lst[i][1] - b
278                lst[i].append('调整!')
279            elif a - b > 0:
280                raise_string_exit("There is a gap between the start address and the end address.")
281    return data_dict
282
283
284def get_tab_len_lst(data_dict):
285    """
286    获得 段与段之间的 段长度差值
287    """
288    tab_len_lst = []
289    for i, k in enumerate(data_dict.keys()):
290        if i == 0:
291            tab_len = [k[0], k[1], k[2], 0]
292        else:
293            tab_len = [k[0], k[1], k[2], k[1] - end_address]
294        end_address = k[1] + k[2]
295        tab_len_lst.append(tab_len)
296    return tab_len_lst
297
298
299def save_dict_csv(data_dict, file_name):
300    """
301    data_dict: 要保存的数据, 保存为csv
302    file_name: 保存csv的文件名  file_name.csv
303    """
304    # data_dict 按键值的 起始地址大小 从小到大排序
305    data_dict = sort_data_dict(data_dict)
306    # 检查同一个段名下的 地址是否重叠
307    data_dict = check_is_overlap(data_dict)
308    with open(OUTPUT_DIR / f'{file_name}.csv', 'w', encoding='utf_8_sig') as f:
309        # data_dict的表头名
310        header = ['起始地址', '结束地址', '符号大小', '符号名', '符号类型', '库名', '文件名', '段名', '段起始地址', '段大小', '占用空间类型', '']
311        f.write(','.join(header) + '\n')
312        for i, (k, info_lst) in enumerate(data_dict.items()):
313            k = list(k)
314            k[-1] = state2space_type(k[-1])
315            k = ','.join(map(str, k))
316            for info in info_lst:
317                if info[-1] == '调整!':
318                    f.write(f"{','.join(map(str, info[:-1]))},{k},调整!\n")
319                else:
320                    f.write(f"{','.join(map(str, info))},{k},\n")
321    # 获得 段与段之间的 段长度差值
322    tab_len_lst = get_tab_len_lst(data_dict)
323    with open(OUTPUT_DIR / f'{file_name}_tab_len.csv', 'w', encoding='utf_8_sig') as f:
324        header = ['段名', '段起始地址', '段大小', 'Tab_Len']
325        f.write(','.join(header) + '\n')
326        for lst in tab_len_lst:
327            f.write(','.join(map(str, lst)) + '\n')
328
329
330def parse_map_file(map_file):
331    with open(map_file, 'r', encoding='utf-8') as f:
332        lines = f.readlines()
333    # [symb_start_address, symb_end_address, symb_len, symb_name, symb_type, a_name, o_name]
334    symb_info = []
335    # 初始化 flag
336    mem_record_flag = link_flag = debug_flag = link_if_flag = 0
337    ## mem_if_flag 是否 判断 字符串以Memory Configuration开头
338    mem_if_flag = 1
339    mem_conf_flag_lst = ['Name', 'Origin', 'Length', 'Attributes']
340    # 记录地址范围的列表,用于判断是否 ram rom flash, 下标0: ram, 1: flash, 2: rom
341    mem_address_range_lst = [[] for _ in range(3)]
342    i = 0
343    while i < len(lines):
344        if not lines[i].strip():
345            i += 1
346            continue
347        # 开始解析 Memory Configuration
348        if mem_if_flag and lines[i].startswith("Memory Configuration"):
349            if lines[i + 2].split() == mem_conf_flag_lst:
350                mem_record_flag = 1
351                mem_if_flag = 0
352                i += 3
353                continue
354            else:
355                raise_string_exit(f"Not found {mem_conf_flag_lst} -- {i}")
356        if mem_record_flag:
357            # 不记录 *default*
358            if lines[i].startswith('*default*'):
359                link_if_flag = 1
360                mem_record_flag = 0
361                i += 2
362                continue
363            elif lines[i].startswith('Linker'):
364                raise_string_exit("Not found *default*")
365            mem_lst = lines[i].split()
366            # mem_info = (起始地址, 结束地址, 地址长度)
367            mem_info = (int(mem_lst[1], 16), int(mem_lst[1], 16) + int(mem_lst[2], 16), int(mem_lst[2], 16))
368            idx = get_mem_address_len_lst_append_idx(mem_lst[0])
369            mem_address_range_lst[idx].append(mem_info)
370        # 开始解析 Linker script and memory map 下的信息
371        if link_if_flag:
372            if lines[i].startswith("Linker script and memory map"):
373                link_flag = 1
374                link_if_flag = 0
375                i += 1
376                continue
377            else:
378                raise_string_exit("Not found Linker script and memory map")
379        if link_flag:
380            # 解析段名行的信息
381            if any(lines[i].startswith(key) for key in lst_info_dict.keys()) or (lines[i].startswith('.') and
382                                                                                 lines[i][1] != '.'):
383                tmp_info = parse_section_info(lines, i, debug_flag, mem_address_range_lst)
384                if tmp_info[0] == "continue":
385                    debug_flag = tmp_info[1]
386                    i += 1
387                    continue
388                else:
389                    map_info_key, diff_address, debug_flag = tmp_info
390            # 解析段名下的符号信息
391            elif debug_flag == 0 and lines[i].startswith((' .', ' *fill')):
392                # 解析符号信息
393                symb_info = parse_symb_info(lines, i, map_info_key, diff_address, symb_info)
394        i += 1
395    save_dict_csv(g_ram_dict, f"{map_file.name}_ram_dict")
396    save_dict_csv(g_flash_dict, f"{map_file.name}_flash_dict")
397    save_dict_csv(g_rom_dict, f"{map_file.name}_rom_dict")
398
399
400def get_group_owner(data_dict, save_name):
401    a_name2resp_group_dict = dict()  # {a_name: PLAT  WIFI  BGLE}
402    with open(OWNER_DIR / 'library_owner.csv', 'r', encoding='utf-8') as f:
403        header = f.readline()
404        lines = f.readlines()
405    for line in lines:
406        a_name, group = line.strip().split(',')
407        a_name2resp_group_dict[a_name] = group
408
409    c_name2wifi_group_dict = dict()  # {c_name: 应用组  算法组  协议组 前端组 系统组}
410    with open(OWNER_DIR / 'wifi_owner.csv', 'r', encoding='utf-8') as f:
411        header = f.readline()
412        lines = f.readlines()
413    for line in lines:
414        c_name, group = line.strip().split(',')
415        c_name2wifi_group_dict[c_name] = group
416    # a_name : [sum_symb_len, group_type]   ---group_type: PLAT  WIFI  BGLE UNKNOWN
417    file_stat_dict = defaultdict(lambda: [0, 'UNKNOWN'])
418    # {c_name : {a_name : [sum_symb_len, group_type, wifi_group_type]}}
419    wifi_stat_dict = defaultdict(lambda: defaultdict(lambda: [0, 'UNKNOWN', '']))
420    for symb_info_list in data_dict.values():
421        for symb_info in symb_info_list:
422            symb_len, a_name, c_name = symb_info[2], symb_info[5], symb_info[6]
423            # 去除后缀 .obj 但 .heap .stack .shere_mem 跳过
424            if not c_name.startswith('.'):
425                c_name = c_name.split('.')[0] + '.c'  #
426            if a_name in a_name2resp_group_dict:
427                file_stat_dict[a_name][1] = a_name2resp_group_dict[a_name]
428                wifi_stat_dict[c_name][a_name][1] = a_name2resp_group_dict[a_name]
429                if a_name2resp_group_dict[a_name] == 'WIFI':
430                    if c_name in c_name2wifi_group_dict:
431                        wifi_stat_dict[c_name][a_name][2] = c_name2wifi_group_dict[c_name]
432                    else:
433                        wifi_stat_dict[c_name][a_name][2] = 'WIFI_UNKNOWN'
434            file_stat_dict[a_name][0] += symb_len
435            wifi_stat_dict[c_name][a_name][0] += symb_len
436    # PLAT  WIFI  BGLE 按 库名 角度统计 大小
437    with open(OUTPUT_DIR / f"{save_name}_library.csv", 'w', encoding='utf_8_sig') as f:
438        header = ['库名', '大小', '负责组']
439        f.write(f"{','.join(header)}\n")
440        group_dict = defaultdict(int)  # 用于下面的 负责组的角度统计 地址大小
441        for a_name, info in file_stat_dict.items():
442            f.write(f"{a_name},{info[0]},{info[1]}\n")
443            group_dict[info[1]] += info[0]
444
445    # 从负责组的角度统计 地址大小
446    with open(OUTPUT_DIR / f"{save_name}_library_summary.csv", 'w', encoding='utf_8_sig') as f:
447        header = ['Group_Owner', 'Size', 'Limit']
448        f.write(f"{','.join(header)}\n")
449       # 各组规格限制 PLAT WIFI BTC BTH UNKNOWN  STACK PKTRAM
450        lim_all = {'ws63-liteos-app.map_ram': {'PLAT' : 35.50, 'WIFI':46.5, 'RADAR':49, 'BTC': 20, 'BTH': 10, 'UNKNOWN': 0.5, 'STACK':7,'PKTRAM':50},
451            'control_ws53.map_ram':{'PLAT' : 16.68, 'WIFI':18.64, 'BTC': 25, 'BTH': 10, 'UNKNOWN': 25, 'STACK':6,'HEAP':27},
452            'control_ws53.map_flash':{'PLAT' : 15, 'WIFI':46.5, 'BTC': 109, 'BTH': 6, 'UNKNOWN': 35},
453            'liteos_ws53_light.map_flash':{'PLAT' : 191, 'WIFI':670, 'BTC': 1, 'BTH': 242.5, 'UNKNOWN': 1},
454            'ws63-liteos-app.map_flash':{'PLAT' : 197, 'WIFI':622.1, 'RADAR':37.5, 'BTC': 143.5, 'BTH': 228, 'UNKNOWN': 0.5}}
455        lim_i = 0
456        for owner, size in group_dict.items():
457            size_t = size/BIT_SIZE
458            if save_name in lim_all:
459                lim = lim_all[save_name]
460                f.write(f"{owner},{size_t},{lim[owner]}\n")
461                if size_t > lim[owner]:
462                    print("Error " + owner + " Exceeded " + save_name + " memory size limit!! Current size is %.3f limit is %.3f" %(size_t, lim[owner]))
463                    sys.exit(1)
464                lim_i += 1
465            else:
466                f.write(f"{owner},{size_t},0\n")
467
468    # 应用组  算法组  协议组 前端组 系统组 按 文件名 库名 角度统计 地址大小
469    with open(OUTPUT_DIR / f"{save_name}_file.csv", 'w', encoding='utf_8_sig') as f:
470        header = ['文件名', '库名', '文件大小', '负责组', 'WIFI_责任组']
471        f.write(f"{','.join(header)}\n")
472        wifi_group_dict = defaultdict(int)  # 用于下面的 WIFI负责组的角度统计 地址大小
473        for c_name, info_dict in wifi_stat_dict.items():
474            for a_name, info in info_dict.items():
475                f.write(f"{c_name},{a_name},{info[0]},{info[1]},{info[2]}\n")
476                if info[1] == 'WIFI':
477                    wifi_group_dict[info[2]] += info[0]
478
479    # 从WIFI负责组的角度统计 地址大小
480    with open(OUTPUT_DIR / f"{save_name}_file_summary.csv", 'w', encoding='utf_8_sig') as f:
481        header = ['Group_Owner', 'Size', 'Limit']
482        f.write(f"{','.join(header)}\n")
483        lim_all = {'control_ws53.map_flash':{'系统组' : 8.0, '协议组':9.5, '应用组': 2, '前端组': 27.1, '算法组': 0.5,'WIFI_UNKNOWN': 5},
484            'liteos_ws53_light.map_flash':{'系统组' : 36, '协议组':212.5, '应用组': 356, '前端组': 15, '算法组': 39,'WIFI_UNKNOWN': 0.5},
485            'ws63-liteos-app.map_flash':{'系统组' : 35.5, '协议组':196.1, '应用组': 314.5, '前端组': 37.1, '算法组': 39.3,'WIFI_UNKNOWN': 0.5}}
486        lim_i = 0
487        for owner, size in wifi_group_dict.items():
488            size_t = size/BIT_SIZE
489            if save_name in lim_all:
490                lim = lim_all[save_name]
491                f.write(f"{owner},{size_t},{lim[owner]}\n")
492                if size_t > lim[owner]:
493                    print("Error " + owner + " Exceeded " + save_name + " memory size limit!! Current size is %.3f limit is %.3f" %(size_t, lim[owner]))
494                    sys.exit(1)
495                lim_i += 1
496            else:
497                f.write(f"{owner},{size_t},0\n")
498
499
500def usage():
501    print("usage:")
502    print("    python3 script target_lst_file target_map_file")
503    print("")
504
505
506if __name__ == "__main__":
507    if len(sys.argv[1:]) != 2:
508        usage()
509        sys.exit(0)
510    root_path = os.path.join(os.path.split(os.path.realpath(__file__))[0], '..', '..', '..')
511    root_path = os.path.abspath(root_path)
512    BIT_SIZE = 1024
513    OWNER_DIR = Path(root_path) / 'protocol/wifi/build/smaller'
514    if not OWNER_DIR.exists():
515        sys.exit(0)
516    DATA_DIR = Path('./')
517    OUTPUT_DIR = Path('./smaller')  # 输出的文件夹下 存放表格数据
518    if not OUTPUT_DIR.exists():
519        OUTPUT_DIR.mkdir()
520    g_state_lst = ['LOAD,', 'DEBUGGING,']  # 状态列表
521    g_ram_dict, g_flash_dict, g_rom_dict = defaultdict(list), defaultdict(list), defaultdict(list)
522    try:
523        lst_info_dict = parse_lst_file(DATA_DIR / sys.argv[1])
524        parse_map_file(DATA_DIR / sys.argv[2])
525    except:
526        sys.exit(0)
527    get_group_owner(g_ram_dict, f"{sys.argv[2]}_ram")
528    get_group_owner(g_flash_dict, f"{sys.argv[2]}_flash")
529    get_group_owner(g_rom_dict, f"{sys.argv[2]}_rom")
530