#!/usr/bin/env python3 import argparse from cmath import nan import json import copy import os import sys import subprocess import shutil from enum import Enum, auto OPT_NMEM_CONFLICT_VAL = False # used for HAPS or real chip DRAM_BASE_SHIFT = 0 # DRAM_BASE_SHIFT = 0x60000000 DEF_OUT_FMT = "1W16C8B" STRING_BUFFER_ADDRESS_DEDUCTION = "buf_addr_deduction" STRING_BUFFER_SIZES = "sizes" STRGIN_BUFFER_ORDER = "order" STRING_FIXED_ADDRESSES = "fixed_addresses" class NoValue(Enum): def __repr__(self): return '<%s.%s>' % (self.__class__.__name__, self.name) class CType(NoValue): MOZART = "520" BEETHOVEN = "720" BACH = "530" SCHUBERT = "630" WAGNER = "730" class Version520(NoValue): SINGLE = "single" MULTI = "multi" MODEL = "model" MODEL_OPT = "model_opt" MODEL_REL = "model_rel" MODEL_DBG = "model_dbg" MODEL_DBG_EDA = "model_dbg_eda" class Version720(NoValue): SINGLE = "single" MULTI = "multi" MODEL = "model" MODEL_OPT = "model_opt" MODEL_REL = "model_rel" MULTI_DBG = "multi_dbg" MODEL_DBG = "model_dbg" MODEL_DBG_EDA = "model_dbg_eda" MODEL_ENC = "model_enc" MODEL_CPU = "model_cpu" """ Versions for 530, 630 and 730. """ class VersionX30(NoValue): SINGLE = "single" MULTI = "multi" MODEL = "model" MODEL_OPT = "model_opt" MODEL_REL = "model_rel" MULTI_DBG = "multi_dbg" MODEL_DBG = "model_dbg" MODEL_DBG_EDA = "model_dbg_eda" MODEL_ENC = "model_enc" MODEL_FARADAY = "model_faraday" MODEL_CPU = "model_cpu" class MemoryBuffer(NoValue): INPUT = "input" OUTPUT = "output" DRAM_BASE = "dram_base" COMMAND = "cmd" WEIGHT = "weight" ADDRESS_DEDUCTION_BASIC_X30 = { STRING_BUFFER_SIZES: { MemoryBuffer.COMMAND: 16, MemoryBuffer.INPUT: 20, MemoryBuffer.OUTPUT: 10, MemoryBuffer.DRAM_BASE: 20, MemoryBuffer.WEIGHT: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.OUTPUT, MemoryBuffer.DRAM_BASE, MemoryBuffer.WEIGHT, ] } ADDRESS_DEDUCTION_MODEL_X30 = { STRING_BUFFER_SIZES: { MemoryBuffer.OUTPUT: 134, MemoryBuffer.DRAM_BASE: 180, }, } ADDRESS_DEDUCTION_MODEL_FARADAY_X30 = { STRING_BUFFER_SIZES: { MemoryBuffer.COMMAND: 8, MemoryBuffer.INPUT: 8, MemoryBuffer.OUTPUT: 4, MemoryBuffer.DRAM_BASE: 16, MemoryBuffer.WEIGHT: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.OUTPUT, MemoryBuffer.DRAM_BASE, MemoryBuffer.WEIGHT, ] } ADDRESS_DEDUCTION_MODEL_DBG_X30 = { STRING_BUFFER_SIZES: { MemoryBuffer.DRAM_BASE: 204, }, } ADDRESS_DEDUCTION_MODEL_REL_X30 = { STRING_BUFFER_SIZES: { MemoryBuffer.INPUT: 150, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.WEIGHT, ], STRING_FIXED_ADDRESSES: { "dram_base_addr": "0x80220000", # = 2050.125MiB } } ADDRESS_DEDUCTION_MODEL_CPU_X30 = { STRING_BUFFER_SIZES: { MemoryBuffer.OUTPUT: 314, MemoryBuffer.WEIGHT: 166, MemoryBuffer.DRAM_BASE: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.OUTPUT, MemoryBuffer.WEIGHT, MemoryBuffer.DRAM_BASE, ] } def dbg_print_args(): bin = os.path.basename(sys.argv[0]) args = {" ".join(sys.argv[1:])} print(f"=> [{bin}] arguments: {args}") def load_json_file(path): with open(path) as f: return json.load(f) def to_mebibyte(hex_value): if hex_value is None: return None return int(hex_value, 16) / (2 ** 20) def to_fw_addr(size): return f"{hex(size)}00000" def deduce_buffer_addresses(config): if STRING_BUFFER_ADDRESS_DEDUCTION not in config: return config deduction_info = config[STRING_BUFFER_ADDRESS_DEDUCTION] del config[STRING_BUFFER_ADDRESS_DEDUCTION] addresses_by_buffer_key = dict() next_start_address = 0 for buffer_id in deduction_info[STRGIN_BUFFER_ORDER]: buffer_key = f"{buffer_id.value}_addr" addresses_by_buffer_key[buffer_key] = to_fw_addr(next_start_address) next_start_address += deduction_info[STRING_BUFFER_SIZES][buffer_id] if STRING_FIXED_ADDRESSES in deduction_info: config = merge_dict(config, deduction_info[STRING_FIXED_ADDRESSES]) for buffer_key, buffer_address in addresses_by_buffer_key.items(): original_value_in_config = config[buffer_key] if buffer_key in config else None if buffer_key in config: if buffer_address != original_value_in_config: print(to_mebibyte(buffer_address), "!=", to_mebibyte(original_value_in_config)) assert(False) config = merge_dict(config, addresses_by_buffer_key) return config def get_version_cfg(ctype, version): bcfg = get_basic_cfg(ctype) if ctype == CType.MOZART.value: config = get_520_version_cfg(bcfg, version) elif ctype == CType.BEETHOVEN.value: config = get_720_version_cfg(bcfg, version) elif ctype == CType.BACH.value: config = get_530_version_cfg(bcfg, version) elif ctype == CType.SCHUBERT.value: config = get_630_version_cfg(bcfg, version) elif ctype == CType.WAGNER.value: config = get_730_version_cfg(bcfg, version) config = deduce_buffer_addresses(config) return config def get_basic_cfg(ctype): BASIC_CFG_520 = { "sram_size": 512, "cmd_optimize": False, "debug_mode": False, "skip_backend": False, "hw_sim": True, "input_fmt": "seq8", STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.COMMAND: 3, MemoryBuffer.INPUT: 5, MemoryBuffer.OUTPUT: 5, MemoryBuffer.DRAM_BASE: 10, MemoryBuffer.WEIGHT: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.OUTPUT, MemoryBuffer.DRAM_BASE, MemoryBuffer.WEIGHT, ] }, "dynamic_fp": True, "dynamic_json_path": "XXXXX.json" } BASIC_CFG_720 = { "sram_size": 1024, STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.COMMAND: 3, MemoryBuffer.INPUT: 5, MemoryBuffer.OUTPUT: 8, MemoryBuffer.DRAM_BASE: 16, MemoryBuffer.WEIGHT: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.OUTPUT, MemoryBuffer.DRAM_BASE, MemoryBuffer.WEIGHT, ] }, "weight_compact": False, "weight_compress": False, "dynamic_fp": True, "dynamic_json_path": "XXXXX.json", "skip_backend": False, "debug_mode": False, "gen_setup_fbs": False, "optimize": { "cmd_size": False, "dma": False, "getw": False, "pooling": False, "parallel": False } } BASIC_CFG_530 = { "sram_size": 512, STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_BASIC_X30, "weight_compact": False, "dynamic_fp": True, "dynamic_json_path": "XXXXX.json", "skip_backend": False, "debug_mode": False, "optimize": { "cmd_size": False, "dma": False, "getw": False, "pooling": False, "parallel": False }, "enable_ncore": True, } BASIC_CFG_630 = { "sram_size": 256, STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_BASIC_X30, "weight_compact": False, "weight_compress": False, "dynamic_fp": True, "dynamic_json_path": "XXXXX.json", "skip_backend": False, "debug_mode": False, "optimize": { "cmd_size": False, "dma": False, "getw": False, "pooling": False, "parallel": False, "nmem_conflict": False }, "enable_ncore": True, } BASIC_CFG_730 = { "sram_size": 1024, STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_BASIC_X30, "weight_compact": False, "weight_compress": False, "dynamic_fp": True, "dynamic_json_path": "XXXXX.json", "skip_backend": False, "debug_mode": False, "optimize": { "cmd_size": False, "dma": False, "getw": False, "pooling": False, "parallel": False, "nmem_conflict": False }, "enable_ncore": True, } if ctype == CType.MOZART.value: return BASIC_CFG_520 elif ctype == CType.BEETHOVEN.value: return BASIC_CFG_720 elif ctype == CType.BACH.value: return BASIC_CFG_530 elif ctype == CType.SCHUBERT.value: return BASIC_CFG_630 elif ctype == CType.WAGNER.value: return BASIC_CFG_730 else: raise ValueError(f"invalid versionctype [{ctype}]") def get_520_version_cfg(basic, version): SINGLE_CFG = merge_dict(basic, { "single_layer_test": True, }) MULTI_CFG = merge_dict(basic, { "single_layer_test": False, }) MODEL_CFG = merge_dict( basic, { # "input_fmt": "seq8", "input_fmt": "rgba8", STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.OUTPUT: 15, MemoryBuffer.DRAM_BASE: 30, }, }, }) MODEL_OPT_CFG = merge_dict(MODEL_CFG, {"cmd_optimize": True}) MODEL_REL_CFG = merge_dict( MODEL_OPT_CFG, { "input_fmt": "rgba8", "hw_sim": False, STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.INPUT: 50, MemoryBuffer.WEIGHT: 1483, MemoryBuffer.DRAM_BASE: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.WEIGHT, MemoryBuffer.DRAM_BASE, ] }, }, ) MODEL_DBG_CFG = merge_dict(MODEL_CFG, { "debug_mode": True, }) MODEL_DBG_EDA_CFG = MODEL_DBG_CFG if version == "single": return SINGLE_CFG elif version == "multi": return MULTI_CFG elif version == "model": return MODEL_CFG elif version == "model_opt": return MODEL_OPT_CFG elif version == "model_rel": return MODEL_REL_CFG elif version == "model_dbg" or version == "model_dbg_eda": return MODEL_DBG_CFG else: raise ValueError(f"invalid version [{version}]") def get_720_version_cfg(basic, version): SINGLE_CFG = merge_dict(basic, { "single_layer_test": True, "output_fmt": DEF_OUT_FMT }) MULTI_CFG = merge_dict(basic, {"optimize": { "getw": True, "parallel": True }}) MODEL_CFG = merge_dict( basic, { STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.OUTPUT: 25, MemoryBuffer.DRAM_BASE: 27, }, }, "optimize": { "dma": True, "getw": True, "pooling": True, "parallel": True } }) MODEL_OPT_CFG = merge_dict(MODEL_CFG, {"optimize": { "cmd_size": True }}) MODEL_REL_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.INPUT: 57, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.INPUT, MemoryBuffer.WEIGHT, ], STRING_FIXED_ADDRESSES : { "dram_base_addr": "0x80220000", # = 2050.125MiB } }, }) MULTI_DBG_CFG = merge_dict(MULTI_CFG, { "debug_mode": True, }) MODEL_DBG_CFG = merge_dict(MODEL_CFG, { "debug_mode": True, }) MODEL_DBG_EDA_CFG = merge_dict(MODEL_CFG, {"optimize": { "getw": False, }}) MODEL_ENC_CFG = merge_dict( MODEL_CFG, { "weight_compress": True, "encryption_flag": True, "encryption_key": "0x1234", # any file with size > 256 bytes can be used "encryption_file": os.path.realpath(__file__), }) MODEL_CPU_CFG = merge_dict( MODEL_OPT_CFG, { "gen_setup_fbs": True, STRING_BUFFER_ADDRESS_DEDUCTION: { STRING_BUFFER_SIZES: { MemoryBuffer.COMMAND: 1, MemoryBuffer.WEIGHT: 1, MemoryBuffer.INPUT: 14, MemoryBuffer.OUTPUT: 496, MemoryBuffer.DRAM_BASE: nan, }, STRGIN_BUFFER_ORDER: [ MemoryBuffer.COMMAND, MemoryBuffer.WEIGHT, MemoryBuffer.INPUT, MemoryBuffer.OUTPUT, MemoryBuffer.DRAM_BASE, ] }, }) if version == "single": return SINGLE_CFG elif version == "multi": return MULTI_CFG elif version == "model": return MODEL_CFG elif version == "model_opt": return MODEL_OPT_CFG elif version == "model_rel": return MODEL_REL_CFG elif version == "multi_dbg": return MULTI_DBG_CFG elif version == "model_dbg": return MODEL_DBG_CFG elif version == "model_dbg_eda": return MODEL_DBG_EDA_CFG elif version == "model_enc": return MODEL_ENC_CFG elif version == "model_cpu": return MODEL_CPU_CFG else: raise ValueError(f"invalid version [{version}]") def get_530_version_cfg(basic, version): SINGLE_CFG = merge_dict(basic, { "single_layer_test": True, "enable_ncore": False, "output_fmt": DEF_OUT_FMT, }) MULTI_CFG = merge_dict(basic, {"optimize": { "getw": True, "pooling": True, "parallel": True }}) MODEL_CFG = merge_dict( basic, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_X30, "optimize": { "dma": True, "getw": True, "pooling": True, "parallel": True } }) MODEL_FARADAY_CFG = merge_dict( MODEL_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_FARADAY_X30, }) MULTI_DBG_CFG = merge_dict(MULTI_CFG, { "debug_mode": True, }) MODEL_DBG_CFG = merge_dict( MODEL_CFG, { "debug_mode": True, STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_DBG_X30, }) MODEL_DBG_EDA_CFG = merge_dict(MODEL_CFG, {"optimize": { "getw": False, }}) MODEL_OPT_CFG = merge_dict(MODEL_CFG, {"optimize": { "cmd_size": True }}) MODEL_REL_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_REL_X30, }) MODEL_ENC_CFG = merge_dict( MODEL_CFG, { "encryption_flag": True, "encryption_key": "0x1234", "encryption_file": "/home/rick/working/kdp720_compiler/resource/keys.bin", }) MODEL_CPU_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_CPU_X30, }) if version == "single": return SINGLE_CFG elif version == "multi": return MULTI_CFG elif version == "model": return MODEL_CFG elif version == "model_opt": return MODEL_OPT_CFG elif version == "model_rel": return MODEL_REL_CFG elif version == "multi_dbg": return MULTI_DBG_CFG elif version == "model_dbg": return MODEL_DBG_CFG elif version == "model_dbg_eda": return MODEL_DBG_EDA_CFG elif version == "model_enc": return MODEL_ENC_CFG elif version == "model_faraday": return MODEL_FARADAY_CFG elif version == "model_cpu": return MODEL_CPU_CFG else: raise ValueError(f"invalid version [{version}]") def get_630_version_cfg(basic, version): SINGLE_CFG = merge_dict(basic, { "single_layer_test": True, "enable_ncore": False, "output_fmt": DEF_OUT_FMT, }) MULTI_CFG = merge_dict(basic, {"optimize": { "getw": True, "pooling": True, "parallel": True, "nmem_conflict": OPT_NMEM_CONFLICT_VAL, }}) MODEL_CFG = merge_dict(basic, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_X30, "optimize": { "dma": True, "getw": True, "pooling": True, "parallel": True, "nmem_conflict": OPT_NMEM_CONFLICT_VAL, } }) MODEL_FARADAY_CFG = merge_dict(MODEL_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_FARADAY_X30, }) MULTI_DBG_CFG = merge_dict(MULTI_CFG, { "debug_mode": True, }) MODEL_DBG_CFG = merge_dict(MODEL_CFG, { "debug_mode": True, # yolov3_keras_3c_608w_608h: needs large data_buffer STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_DBG_X30, }) MODEL_DBG_EDA_CFG = merge_dict(MODEL_CFG, { "optimize": { "getw": False, } }) MODEL_OPT_CFG = merge_dict(MODEL_CFG, { "optimize": { "cmd_size": True } }) MODEL_REL_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_REL_X30, }) MODEL_ENC_CFG = merge_dict(MODEL_CFG, { "weight_compress": True, "encryption_flag": True, "encryption_key": "0x1234", "encryption_file": "/home/rick/working/kdp720_compiler/resource/keys.bin", }) MODEL_CPU_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_CPU_X30, }) if version == "single": return SINGLE_CFG elif version == "multi": return MULTI_CFG elif version == "model": return MODEL_CFG elif version == "model_opt": return MODEL_OPT_CFG elif version == "model_rel": return MODEL_REL_CFG elif version == "multi_dbg": return MULTI_DBG_CFG elif version == "model_dbg": return MODEL_DBG_CFG elif version == "model_dbg_eda": return MODEL_DBG_EDA_CFG elif version == "model_enc": return MODEL_ENC_CFG elif version == "model_faraday": return MODEL_FARADAY_CFG elif version == "model_cpu": return MODEL_CPU_CFG else: raise ValueError(f"invalid version [{version}]") def get_730_version_cfg(basic, version): SINGLE_CFG = merge_dict(basic, { "single_layer_test": True, "enable_ncore": False, "output_fmt": DEF_OUT_FMT, }) MULTI_CFG = merge_dict(basic, { "optimize": { "getw": True, "pooling": True, "parallel": True, "nmem_conflict": OPT_NMEM_CONFLICT_VAL, }}) MODEL_CFG = merge_dict(basic, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_X30, "optimize": { "dma": True, "getw": True, "pooling": True, "parallel": True, "nmem_conflict": OPT_NMEM_CONFLICT_VAL, } }) MODEL_FARADAY_CFG = merge_dict(MODEL_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_FARADAY_X30, }) MULTI_DBG_CFG = merge_dict(MULTI_CFG, { "debug_mode": True, }) MODEL_DBG_CFG = merge_dict(MODEL_CFG, { "debug_mode": True, STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_DBG_X30, }) MODEL_DBG_EDA_CFG = merge_dict(MODEL_CFG, {"optimize": { "getw": False, }}) MODEL_OPT_CFG = merge_dict(MODEL_CFG, {"optimize": { "cmd_size": True }}) MODEL_REL_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_REL_X30, }) MODEL_ENC_CFG = merge_dict(MODEL_CFG, { "weight_compress": True, "encryption_flag": True, "encryption_key": "0x1234", "encryption_file": "/home/rick/working/kdp720_compiler/resource/keys.bin", }) MODEL_CPU_CFG = merge_dict(MODEL_OPT_CFG, { STRING_BUFFER_ADDRESS_DEDUCTION: ADDRESS_DEDUCTION_MODEL_CPU_X30, }) if version == "single": return SINGLE_CFG elif version == "multi": return MULTI_CFG elif version == "model": return MODEL_CFG elif version == "model_opt": return MODEL_OPT_CFG elif version == "model_rel": return MODEL_REL_CFG elif version == "multi_dbg": return MULTI_DBG_CFG elif version == "model_dbg": return MODEL_DBG_CFG elif version == "model_dbg_eda": return MODEL_DBG_EDA_CFG elif version == "model_enc": return MODEL_ENC_CFG elif version == "model_faraday": return MODEL_FARADAY_CFG elif version == "model_cpu": return MODEL_CPU_CFG else: raise ValueError(f"invalid version [{version}]") def get_add_cfg(add_json): cfg = {} if add_json: cfg = json.loads(add_json) return cfg def get_hack_cfg(hack_cfg): cfg = {} if hack_cfg: cfg["hack_cfg"] = os.path.abspath(hack_cfg) hcfg = load_json_file(hack_cfg) if "input_fmt" in hcfg: cfg["input_fmt"] = hcfg["input_fmt"] if "output_fmt" in hcfg: cfg["output_fmt"] = hcfg["output_fmt"] if "pool_opt" in hcfg: if "optimize" not in cfg: cfg["optimize"] = {} cfg["optimize"]["pooling"] = hcfg["pool_opt"] == 1 return cfg def get_radix_cfg(radix_cfg): cfg = {} if radix_cfg is None: cfg["dynamic_fp"] = False else: if not os.path.isfile(radix_cfg): raise FileNotFoundError(radix_cfg) cfg = { "dynamic_fp": True, "dynamic_json_path": os.path.abspath(radix_cfg) } return cfg def delete_elements(data, elements_to_delete=[]): for element in elements_to_delete: if isinstance(element, list): delete_elements(data, element) continue elif isinstance(element, dict): for key, val in element.items(): delete_elements(data[key], [val]) continue if element not in data: continue if isinstance(data, list): data.remove(element) elif isinstance(data, dict): del data[element] def merge_dict(base_dictionary, additional_dictionary, keys_to_delete=[]): if additional_dictionary is None: return base_dictionary result = copy.deepcopy(base_dictionary) delete_elements(result, keys_to_delete) # merges additional_dictionary into result for key in additional_dictionary: if key not in result: result[key] = additional_dictionary[key] continue if isinstance(result[key], dict) and isinstance(additional_dictionary[key], dict): result[key] = merge_dict(result[key], additional_dictionary[key]) continue result[key] = additional_dictionary[key] return result def env_set_cfg(cfg, ctype): if os.getenv("RUN_IP_EVAL") == "1": add_ip_eval_cfg(cfg, ctype) if os.getenv("WT_COMPRESS") == "1": cfg["weight_compress"] = True return cfg def add_ip_eval_cfg(cfg, ctype): key = "ip_evaluator_cfg" if key not in cfg: cfg[key] = get_ip_eval_cfg(ctype) return True return False def remove_ip_eval_cfg(cfg): key = "ip_evaluator_cfg" if key in cfg: del cfg[key] def get_ip_eval_cfg(ctype): fpath = f"ip_eval/ip_eval_{ctype}.json" return get_resource_fpath(fpath) def get_resource_fpath(rel_path): # /home/kai/compiler/test/gen_rtl_test/utils/gen_config.py script_path = os.path.realpath(__file__) proj_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(script_path)))) return os.path.join(proj_dir, "resource", rel_path) def hack_dram_addr(cfg): if DRAM_BASE_SHIFT <= 0: return cfg print(f"Hack dram addr config by adding \"0x{DRAM_BASE_SHIFT:x}\":", file=sys.stderr) for key, val in cfg.items(): if key[-5:] == "_addr": addr = DRAM_BASE_SHIFT + int(val, 16) addr = str(hex(addr)) print(f" {key}: {val} => {addr}", file=sys.stderr) print("", file=sys.stderr) return cfg def save_config(path, cfg): with open(path, "w") as fp: json.dump(cfg, fp, indent=4, sort_keys=True) fp.write('\n') # use opt_compile.py to find best compiler config def gen_best_config(ctype, opt_model, cfg, cfg_path): def get_script_path(): opt_compile_dir = os.getenv("OPT_COMPILE_DIR") if opt_compile_dir and os.path.exists(opt_compile_dir): opt_compile = os.path.join(opt_compile_dir, 'opt_compile.py') else: # get opt_compile.py file path. ex: /home/benson/compiler/test/gen_rtl_test/utils/gen_config.py script_path = os.path.realpath(__file__) proj_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(script_path)))) opt_compile = os.path.join(proj_dir, 'bin/opt_compile/opt_compile.py') assert os.path.exists( opt_compile ), f"environment variable OPT_COMPILE_DIR [{opt_compile_dir}] doesn't exist ! please export OPT_COMPILE_DIR=XXXX" return opt_compile if not opt_model: return 0 print('=> [opt_compile]') assert os.path.exists(opt_model), f"opt_model [{opt_model}] doesn't exist" compiler_dir = os.getenv("COMPILER_BIN_DIR") assert compiler_dir and os.path.exists( compiler_dir ), f"environment variable COMPILER_BIN_DIR [{compiler_dir}] doesn't exist ! please export COMPILER_BIN_DIR=XXXX" #benson2do: remove ctype check when fmap_cut_search is ready for other platforms if ctype != '720': print('[Not support] only support for 720 !') return -1 # create tmp_cfg, and add ip_evaluator_cfg key out_dir = os.path.dirname(os.path.realpath(cfg_path)) tmp_cfg = copy.deepcopy(cfg) is_add_ip_eval = add_ip_eval_cfg(tmp_cfg, ctype) tmp_cfg_path = os.path.join(out_dir, 'tmp_cfg.json') save_config(tmp_cfg_path, tmp_cfg) # run opt_compile.py script = get_script_path() tmp_out_dir = os.path.join(out_dir, 'opt_compile') command = f"{script} {ctype} {opt_model} {tmp_cfg_path} {tmp_out_dir}" print(command) cmd_args = command.split() o = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # export opt.log and image_cut_search/Summary.txt opt_log = f"{tmp_out_dir}/opt.log" if os.path.exists(opt_log): shutil.copy(opt_log, out_dir, follow_symlinks=True) img_cut_search_summary = f"{tmp_out_dir}/image_cut_search/Summary.txt" if os.path.exists(img_cut_search_summary): shutil.copy(img_cut_search_summary, out_dir+"/summary_image_cut_search.txt", follow_symlinks=True) if o.returncode != 0: print('[Failed] failed to run opt_compile !') shutil.rmtree(tmp_out_dir) return -1 # overrite cfg_path with best_cfg best_cfg_path = os.path.join(tmp_out_dir, 'best_config.json') assert os.path.exists(best_cfg_path), f"best_config.json doesn't exist" best_cfg = load_json_file(best_cfg_path) # module dependency: "image_cut_search" sub-module # copy image_cut_search config file to the directory where compiler config lives if 'fmap_cut' in best_cfg and best_cfg['fmap_cut']['mode'] == 'manual': org_fmap_cut_cfg = best_cfg['fmap_cut']['cfg'] new_fmap_cut_cfg = os.path.join(out_dir, 'best_image_cut_config.json') shutil.copyfile(org_fmap_cut_cfg, new_fmap_cut_cfg) best_cfg['fmap_cut']['cfg'] = new_fmap_cut_cfg if is_add_ip_eval: remove_ip_eval_cfg(best_cfg) save_config(cfg_path, best_cfg) shutil.rmtree(tmp_out_dir) return 0 def gen_all(): versions = { CType.MOZART : Version520, CType.BEETHOVEN : Version720, CType.BACH : VersionX30, CType.SCHUBERT : VersionX30, CType.WAGNER : VersionX30, } for ctype in versions: output_directory = f"./{ctype.value}" if not os.path.exists(output_directory): os.makedirs(output_directory, exist_ok=True) for version in versions[ctype]: config = get_version_cfg(ctype.value, version.value) file_name = f"config_{ctype.value}_{version.value}.json" config_path = f"{output_directory}/{file_name}" save_config(config_path, config) ################ ## MAIN ## ################ if __name__ == "__main__": parser = argparse.ArgumentParser(description="generate config.json for compiler") ctypes = "|".join([ctype.value for ctype in CType]) parser.add_argument("-t", "--ctype", help=f"compiler type [{ctypes}]") parser.add_argument( "-v", "--version", help="config version: [single|multi|model|model_rel|model_opt|model_dbg|model_dbg_eda|model_faraday]") parser.add_argument("-f", "--tmpl_cfg", help="path to template config (if exists, version is skipped)") parser.add_argument("-o", "--output", default="config.json", help="path to output config") parser.add_argument("-r", "--radix_cfg", help="path to radix config") parser.add_argument("-k", "--hack_cfg", help="path to hack config") parser.add_argument("-a", "--add_json", help="additional config in json str " + "format, e.g. '{\"single_layer_test\":true,\"hstride\":true}'") parser.add_argument( "-m", "--opt_model", help= "model path. run opt_compile to find best compiler config. please export COMPILER_BIN_DIR=XXXX to specify compiler bin dir, and export OPT_COMPILE_DIR=XXXX to specify opt compile bin dir." ) parser.add_argument("-g", "--gen-all-version", action="store_true", help="Generate basic configs for all version with all ctype to verify or to debug.") # dbg_print_args() args = parser.parse_args() if args.gen_all_version: gen_all() print("Generation done.") sys.exit() ctype = args.ctype tmpl_cfg = args.tmpl_cfg if tmpl_cfg: cfg = load_json_file(tmpl_cfg) else: cfg = get_version_cfg(ctype, args.version) radix_cfg = get_radix_cfg(args.radix_cfg) cfg = merge_dict(cfg, radix_cfg) hack_cfg = get_hack_cfg(args.hack_cfg) cfg = merge_dict(cfg, hack_cfg) add_cfg = get_add_cfg(args.add_json) cfg = merge_dict(cfg, add_cfg) cfg = env_set_cfg(cfg, ctype) cfg = hack_dram_addr(cfg) # save to file cfg_path = args.output save_config(cfg_path, cfg) # find best compiler config and replace the old one if 0 != gen_best_config(ctype, args.opt_model, cfg, cfg_path): sys.exit(-1)