1cc1dc7a3Sopenharmony_ci#!/usr/bin/env python3 2cc1dc7a3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0 3cc1dc7a3Sopenharmony_ci# ----------------------------------------------------------------------------- 4cc1dc7a3Sopenharmony_ci# Copyright 2021 Arm Limited 5cc1dc7a3Sopenharmony_ci# 6cc1dc7a3Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); you may not 7cc1dc7a3Sopenharmony_ci# use this file except in compliance with the License. You may obtain a copy 8cc1dc7a3Sopenharmony_ci# of the License at: 9cc1dc7a3Sopenharmony_ci# 10cc1dc7a3Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 11cc1dc7a3Sopenharmony_ci# 12cc1dc7a3Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 13cc1dc7a3Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14cc1dc7a3Sopenharmony_ci# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15cc1dc7a3Sopenharmony_ci# License for the specific language governing permissions and limitations 16cc1dc7a3Sopenharmony_ci# under the License. 17cc1dc7a3Sopenharmony_ci# ----------------------------------------------------------------------------- 18cc1dc7a3Sopenharmony_ci""" 19cc1dc7a3Sopenharmony_ciThe ``astc_trace_analysis`` utility provides a tool to analyze trace files. 20cc1dc7a3Sopenharmony_ci 21cc1dc7a3Sopenharmony_ciWARNING: Trace files are an engineering tool, and not part of the standard 22cc1dc7a3Sopenharmony_ciproduct, so traces and their associated tools are volatile and may change 23cc1dc7a3Sopenharmony_cisignificantly without notice. 24cc1dc7a3Sopenharmony_ci""" 25cc1dc7a3Sopenharmony_ci 26cc1dc7a3Sopenharmony_ciimport argparse 27cc1dc7a3Sopenharmony_cifrom collections import defaultdict as ddict 28cc1dc7a3Sopenharmony_ciimport json 29cc1dc7a3Sopenharmony_ciimport numpy as np 30cc1dc7a3Sopenharmony_ciimport sys 31cc1dc7a3Sopenharmony_ci 32cc1dc7a3Sopenharmony_ciQUANT_TABLE = { 33cc1dc7a3Sopenharmony_ci 0: 2, 34cc1dc7a3Sopenharmony_ci 1: 3, 35cc1dc7a3Sopenharmony_ci 2: 4, 36cc1dc7a3Sopenharmony_ci 3: 5, 37cc1dc7a3Sopenharmony_ci 4: 6, 38cc1dc7a3Sopenharmony_ci 5: 8, 39cc1dc7a3Sopenharmony_ci 6: 10, 40cc1dc7a3Sopenharmony_ci 7: 12, 41cc1dc7a3Sopenharmony_ci 8: 16, 42cc1dc7a3Sopenharmony_ci 9: 20, 43cc1dc7a3Sopenharmony_ci 10: 24, 44cc1dc7a3Sopenharmony_ci 11: 32 45cc1dc7a3Sopenharmony_ci} 46cc1dc7a3Sopenharmony_ci 47cc1dc7a3Sopenharmony_ciCHANNEL_TABLE = { 48cc1dc7a3Sopenharmony_ci 0: "R", 49cc1dc7a3Sopenharmony_ci 1: "G", 50cc1dc7a3Sopenharmony_ci 2: "B", 51cc1dc7a3Sopenharmony_ci 3: "A" 52cc1dc7a3Sopenharmony_ci} 53cc1dc7a3Sopenharmony_ci 54cc1dc7a3Sopenharmony_ciclass Trace: 55cc1dc7a3Sopenharmony_ci 56cc1dc7a3Sopenharmony_ci def __init__(self, block_x, block_y, block_z): 57cc1dc7a3Sopenharmony_ci self.block_x = block_x 58cc1dc7a3Sopenharmony_ci self.block_y = block_y 59cc1dc7a3Sopenharmony_ci self.block_z = block_z 60cc1dc7a3Sopenharmony_ci self.blocks = [] 61cc1dc7a3Sopenharmony_ci 62cc1dc7a3Sopenharmony_ci def add_block(self, block): 63cc1dc7a3Sopenharmony_ci self.blocks.append(block) 64cc1dc7a3Sopenharmony_ci 65cc1dc7a3Sopenharmony_ci def __getitem__(self, i): 66cc1dc7a3Sopenharmony_ci return self.blocks[i] 67cc1dc7a3Sopenharmony_ci 68cc1dc7a3Sopenharmony_ci def __delitem__(self, i): 69cc1dc7a3Sopenharmony_ci del self.blocks[i] 70cc1dc7a3Sopenharmony_ci 71cc1dc7a3Sopenharmony_ci def __len__(self): 72cc1dc7a3Sopenharmony_ci return len(self.blocks) 73cc1dc7a3Sopenharmony_ci 74cc1dc7a3Sopenharmony_ciclass Block: 75cc1dc7a3Sopenharmony_ci 76cc1dc7a3Sopenharmony_ci def __init__(self, pos_x, pos_y, pos_z, error_target): 77cc1dc7a3Sopenharmony_ci self.pos_x = pos_x 78cc1dc7a3Sopenharmony_ci self.pos_y = pos_y 79cc1dc7a3Sopenharmony_ci self.pos_z = pos_z 80cc1dc7a3Sopenharmony_ci 81cc1dc7a3Sopenharmony_ci self.raw_min = None 82cc1dc7a3Sopenharmony_ci self.raw_max = None 83cc1dc7a3Sopenharmony_ci 84cc1dc7a3Sopenharmony_ci self.ldr_min = None 85cc1dc7a3Sopenharmony_ci self.ldr_max = None 86cc1dc7a3Sopenharmony_ci 87cc1dc7a3Sopenharmony_ci self.error_target = error_target 88cc1dc7a3Sopenharmony_ci self.passes = [] 89cc1dc7a3Sopenharmony_ci self.qualityHit = None 90cc1dc7a3Sopenharmony_ci 91cc1dc7a3Sopenharmony_ci def add_minimums(self, r, g, b, a): 92cc1dc7a3Sopenharmony_ci self.raw_min = (r, g, b, a) 93cc1dc7a3Sopenharmony_ci 94cc1dc7a3Sopenharmony_ci def ldr(x): 95cc1dc7a3Sopenharmony_ci cmax = 65535.0 96cc1dc7a3Sopenharmony_ci return int((r / cmax) * 255.0) 97cc1dc7a3Sopenharmony_ci 98cc1dc7a3Sopenharmony_ci self.ldr_min = (ldr(r), ldr(g), ldr(b), ldr(a)) 99cc1dc7a3Sopenharmony_ci 100cc1dc7a3Sopenharmony_ci def add_maximums(self, r, g, b, a): 101cc1dc7a3Sopenharmony_ci self.raw_max = (r, g, b, a) 102cc1dc7a3Sopenharmony_ci 103cc1dc7a3Sopenharmony_ci def ldr(x): 104cc1dc7a3Sopenharmony_ci cmax = 65535.0 105cc1dc7a3Sopenharmony_ci return int((r / cmax) * 255.0) 106cc1dc7a3Sopenharmony_ci 107cc1dc7a3Sopenharmony_ci self.ldr_max = (ldr(r), ldr(g), ldr(b), ldr(a)) 108cc1dc7a3Sopenharmony_ci 109cc1dc7a3Sopenharmony_ci def add_pass(self, pas): 110cc1dc7a3Sopenharmony_ci self.passes.append(pas) 111cc1dc7a3Sopenharmony_ci 112cc1dc7a3Sopenharmony_ci def __getitem__(self, i): 113cc1dc7a3Sopenharmony_ci return self.passes[i] 114cc1dc7a3Sopenharmony_ci 115cc1dc7a3Sopenharmony_ci def __delitem__(self, i): 116cc1dc7a3Sopenharmony_ci del self.passes[i] 117cc1dc7a3Sopenharmony_ci 118cc1dc7a3Sopenharmony_ci def __len__(self): 119cc1dc7a3Sopenharmony_ci return len(self.passes) 120cc1dc7a3Sopenharmony_ci 121cc1dc7a3Sopenharmony_ci 122cc1dc7a3Sopenharmony_ciclass Pass: 123cc1dc7a3Sopenharmony_ci 124cc1dc7a3Sopenharmony_ci def __init__(self, partitions, partition, planes, target_hit, mode, component): 125cc1dc7a3Sopenharmony_ci self.partitions = partitions 126cc1dc7a3Sopenharmony_ci self.partition_index = 0 if partition is None else partition 127cc1dc7a3Sopenharmony_ci self.planes = planes 128cc1dc7a3Sopenharmony_ci self.plane2_component = component 129cc1dc7a3Sopenharmony_ci self.target_hit = target_hit 130cc1dc7a3Sopenharmony_ci self.search_mode = mode 131cc1dc7a3Sopenharmony_ci self.candidates = [] 132cc1dc7a3Sopenharmony_ci 133cc1dc7a3Sopenharmony_ci def add_candidate(self, candidate): 134cc1dc7a3Sopenharmony_ci self.candidates.append(candidate) 135cc1dc7a3Sopenharmony_ci 136cc1dc7a3Sopenharmony_ci def __getitem__(self, i): 137cc1dc7a3Sopenharmony_ci return self.candidates[i] 138cc1dc7a3Sopenharmony_ci 139cc1dc7a3Sopenharmony_ci def __delitem__(self, i): 140cc1dc7a3Sopenharmony_ci del self.candidates[i] 141cc1dc7a3Sopenharmony_ci 142cc1dc7a3Sopenharmony_ci def __len__(self): 143cc1dc7a3Sopenharmony_ci return len(self.candidates) 144cc1dc7a3Sopenharmony_ci 145cc1dc7a3Sopenharmony_ci 146cc1dc7a3Sopenharmony_ciclass Candidate: 147cc1dc7a3Sopenharmony_ci 148cc1dc7a3Sopenharmony_ci def __init__(self, weight_x, weight_y, weight_z, weight_quant): 149cc1dc7a3Sopenharmony_ci self.weight_x = weight_x 150cc1dc7a3Sopenharmony_ci self.weight_y = weight_y 151cc1dc7a3Sopenharmony_ci self.weight_z = weight_z 152cc1dc7a3Sopenharmony_ci self.weight_quant = weight_quant 153cc1dc7a3Sopenharmony_ci self.refinement_errors = [] 154cc1dc7a3Sopenharmony_ci 155cc1dc7a3Sopenharmony_ci def add_refinement(self, errorval): 156cc1dc7a3Sopenharmony_ci self.refinement_errors.append(errorval) 157cc1dc7a3Sopenharmony_ci 158cc1dc7a3Sopenharmony_ci 159cc1dc7a3Sopenharmony_cidef get_attrib(data, name, multiple=False, hard_fail=True): 160cc1dc7a3Sopenharmony_ci results = [] 161cc1dc7a3Sopenharmony_ci for attrib in data: 162cc1dc7a3Sopenharmony_ci if len(attrib) == 2 and attrib[0] == name: 163cc1dc7a3Sopenharmony_ci results.append(attrib[1]) 164cc1dc7a3Sopenharmony_ci 165cc1dc7a3Sopenharmony_ci if not results: 166cc1dc7a3Sopenharmony_ci if hard_fail: 167cc1dc7a3Sopenharmony_ci print(json.dumps(data, indent=2)) 168cc1dc7a3Sopenharmony_ci assert False, "Attribute %s not found" % name 169cc1dc7a3Sopenharmony_ci if multiple: 170cc1dc7a3Sopenharmony_ci return list() 171cc1dc7a3Sopenharmony_ci return None 172cc1dc7a3Sopenharmony_ci 173cc1dc7a3Sopenharmony_ci if not multiple: 174cc1dc7a3Sopenharmony_ci if len(results) > 1: 175cc1dc7a3Sopenharmony_ci print(json.dumps(data, indent=2)) 176cc1dc7a3Sopenharmony_ci assert False, "Attribute %s found %u times" % (name, len(results)) 177cc1dc7a3Sopenharmony_ci return results[0] 178cc1dc7a3Sopenharmony_ci 179cc1dc7a3Sopenharmony_ci return results 180cc1dc7a3Sopenharmony_ci 181cc1dc7a3Sopenharmony_ci 182cc1dc7a3Sopenharmony_cidef rev_enumerate(seq): 183cc1dc7a3Sopenharmony_ci return zip(reversed(range(len(seq))), reversed(seq)) 184cc1dc7a3Sopenharmony_ci 185cc1dc7a3Sopenharmony_cidef foreach_block(data): 186cc1dc7a3Sopenharmony_ci 187cc1dc7a3Sopenharmony_ci for block in data: 188cc1dc7a3Sopenharmony_ci yield block 189cc1dc7a3Sopenharmony_ci 190cc1dc7a3Sopenharmony_cidef foreach_pass(data): 191cc1dc7a3Sopenharmony_ci 192cc1dc7a3Sopenharmony_ci for block in data: 193cc1dc7a3Sopenharmony_ci for pas in block: 194cc1dc7a3Sopenharmony_ci yield (block, pas) 195cc1dc7a3Sopenharmony_ci 196cc1dc7a3Sopenharmony_cidef foreach_candidate(data): 197cc1dc7a3Sopenharmony_ci 198cc1dc7a3Sopenharmony_ci for block in data: 199cc1dc7a3Sopenharmony_ci for pas in block: 200cc1dc7a3Sopenharmony_ci # Special case - None candidates for 0 partition 201cc1dc7a3Sopenharmony_ci if not len(pas): 202cc1dc7a3Sopenharmony_ci yield (block, pas, None) 203cc1dc7a3Sopenharmony_ci 204cc1dc7a3Sopenharmony_ci for candidate in pas: 205cc1dc7a3Sopenharmony_ci yield (block, pas, candidate) 206cc1dc7a3Sopenharmony_ci 207cc1dc7a3Sopenharmony_cidef get_node(data, name, multiple=False, hard_fail=True): 208cc1dc7a3Sopenharmony_ci results = [] 209cc1dc7a3Sopenharmony_ci for attrib in data: 210cc1dc7a3Sopenharmony_ci if len(attrib) == 3 and attrib[0] == "node" and attrib[1] == name: 211cc1dc7a3Sopenharmony_ci results.append(attrib[2]) 212cc1dc7a3Sopenharmony_ci 213cc1dc7a3Sopenharmony_ci if not results: 214cc1dc7a3Sopenharmony_ci if hard_fail: 215cc1dc7a3Sopenharmony_ci print(json.dumps(data, indent=2)) 216cc1dc7a3Sopenharmony_ci assert False, "Node %s not found" % name 217cc1dc7a3Sopenharmony_ci return None 218cc1dc7a3Sopenharmony_ci 219cc1dc7a3Sopenharmony_ci if not multiple: 220cc1dc7a3Sopenharmony_ci if len(results) > 1: 221cc1dc7a3Sopenharmony_ci print(json.dumps(data, indent=2)) 222cc1dc7a3Sopenharmony_ci assert False, "Node %s found %u times" % (name, len(results)) 223cc1dc7a3Sopenharmony_ci return results[0] 224cc1dc7a3Sopenharmony_ci 225cc1dc7a3Sopenharmony_ci return results 226cc1dc7a3Sopenharmony_ci 227cc1dc7a3Sopenharmony_ci 228cc1dc7a3Sopenharmony_cidef find_best_pass_and_candidate(block): 229cc1dc7a3Sopenharmony_ci explicit_pass = None 230cc1dc7a3Sopenharmony_ci 231cc1dc7a3Sopenharmony_ci best_error = 1e30 232cc1dc7a3Sopenharmony_ci best_pass = None 233cc1dc7a3Sopenharmony_ci best_candidate = None 234cc1dc7a3Sopenharmony_ci 235cc1dc7a3Sopenharmony_ci for pas in block: 236cc1dc7a3Sopenharmony_ci # Special case for constant color blocks - no trial candidates 237cc1dc7a3Sopenharmony_ci if pas.target_hit and pas.partitions == 0: 238cc1dc7a3Sopenharmony_ci return (pas, None) 239cc1dc7a3Sopenharmony_ci 240cc1dc7a3Sopenharmony_ci for candidate in pas: 241cc1dc7a3Sopenharmony_ci errorval = candidate.refinement_errors[-1] 242cc1dc7a3Sopenharmony_ci if errorval <= best_error: 243cc1dc7a3Sopenharmony_ci best_error = errorval 244cc1dc7a3Sopenharmony_ci best_pass = pas 245cc1dc7a3Sopenharmony_ci best_candidate = candidate 246cc1dc7a3Sopenharmony_ci 247cc1dc7a3Sopenharmony_ci # Every other return type must have both best pass and best candidate 248cc1dc7a3Sopenharmony_ci assert (best_pass and best_candidate) 249cc1dc7a3Sopenharmony_ci return (best_pass, best_candidate) 250cc1dc7a3Sopenharmony_ci 251cc1dc7a3Sopenharmony_ci 252cc1dc7a3Sopenharmony_cidef generate_database(data): 253cc1dc7a3Sopenharmony_ci # Skip header 254cc1dc7a3Sopenharmony_ci assert(data[0] == "node") 255cc1dc7a3Sopenharmony_ci assert(data[1] == "root") 256cc1dc7a3Sopenharmony_ci data = data[2] 257cc1dc7a3Sopenharmony_ci 258cc1dc7a3Sopenharmony_ci bx = get_attrib(data, "block_x") 259cc1dc7a3Sopenharmony_ci by = get_attrib(data, "block_y") 260cc1dc7a3Sopenharmony_ci bz = get_attrib(data, "block_z") 261cc1dc7a3Sopenharmony_ci dbStruct = Trace(bx, by, bz) 262cc1dc7a3Sopenharmony_ci 263cc1dc7a3Sopenharmony_ci for block in get_node(data, "block", True): 264cc1dc7a3Sopenharmony_ci px = get_attrib(block, "pos_x") 265cc1dc7a3Sopenharmony_ci py = get_attrib(block, "pos_y") 266cc1dc7a3Sopenharmony_ci pz = get_attrib(block, "pos_z") 267cc1dc7a3Sopenharmony_ci 268cc1dc7a3Sopenharmony_ci minr = get_attrib(block, "min_r") 269cc1dc7a3Sopenharmony_ci ming = get_attrib(block, "min_g") 270cc1dc7a3Sopenharmony_ci minb = get_attrib(block, "min_b") 271cc1dc7a3Sopenharmony_ci mina = get_attrib(block, "min_a") 272cc1dc7a3Sopenharmony_ci 273cc1dc7a3Sopenharmony_ci maxr = get_attrib(block, "max_r") 274cc1dc7a3Sopenharmony_ci maxg = get_attrib(block, "max_g") 275cc1dc7a3Sopenharmony_ci maxb = get_attrib(block, "max_b") 276cc1dc7a3Sopenharmony_ci maxa = get_attrib(block, "max_a") 277cc1dc7a3Sopenharmony_ci 278cc1dc7a3Sopenharmony_ci et = get_attrib(block, "tune_error_threshold") 279cc1dc7a3Sopenharmony_ci 280cc1dc7a3Sopenharmony_ci blockStruct = Block(px, py, pz, et) 281cc1dc7a3Sopenharmony_ci blockStruct.add_minimums(minr, ming, minb, mina) 282cc1dc7a3Sopenharmony_ci blockStruct.add_maximums(maxr, maxg, maxb, maxa) 283cc1dc7a3Sopenharmony_ci dbStruct.add_block(blockStruct) 284cc1dc7a3Sopenharmony_ci 285cc1dc7a3Sopenharmony_ci for pas in get_node(block, "pass", True): 286cc1dc7a3Sopenharmony_ci # Don't copy across passes we skipped due to heuristics 287cc1dc7a3Sopenharmony_ci skipped = get_attrib(pas, "skip", False, False) 288cc1dc7a3Sopenharmony_ci if skipped: 289cc1dc7a3Sopenharmony_ci continue 290cc1dc7a3Sopenharmony_ci 291cc1dc7a3Sopenharmony_ci prts = get_attrib(pas, "partition_count") 292cc1dc7a3Sopenharmony_ci prti = get_attrib(pas, "partition_index", False, False) 293cc1dc7a3Sopenharmony_ci plns = get_attrib(pas, "plane_count") 294cc1dc7a3Sopenharmony_ci chan = get_attrib(pas, "plane_component", False, plns > 2) 295cc1dc7a3Sopenharmony_ci mode = get_attrib(pas, "search_mode", False, False) 296cc1dc7a3Sopenharmony_ci ehit = get_attrib(pas, "exit", False, False) == "quality hit" 297cc1dc7a3Sopenharmony_ci 298cc1dc7a3Sopenharmony_ci passStruct = Pass(prts, prti, plns, ehit, mode, chan) 299cc1dc7a3Sopenharmony_ci blockStruct.add_pass(passStruct) 300cc1dc7a3Sopenharmony_ci 301cc1dc7a3Sopenharmony_ci # Constant color blocks don't have any candidates 302cc1dc7a3Sopenharmony_ci if prts == 0: 303cc1dc7a3Sopenharmony_ci continue 304cc1dc7a3Sopenharmony_ci 305cc1dc7a3Sopenharmony_ci for candidate in get_node(pas, "candidate", True): 306cc1dc7a3Sopenharmony_ci # Don't copy across candidates we couldn't encode 307cc1dc7a3Sopenharmony_ci failed = get_attrib(candidate, "failed", False, False) 308cc1dc7a3Sopenharmony_ci if failed: 309cc1dc7a3Sopenharmony_ci continue 310cc1dc7a3Sopenharmony_ci 311cc1dc7a3Sopenharmony_ci wx = get_attrib(candidate, "weight_x") 312cc1dc7a3Sopenharmony_ci wy = get_attrib(candidate, "weight_y") 313cc1dc7a3Sopenharmony_ci wz = get_attrib(candidate, "weight_z") 314cc1dc7a3Sopenharmony_ci wq = QUANT_TABLE[get_attrib(candidate, "weight_quant")] 315cc1dc7a3Sopenharmony_ci epre = get_attrib(candidate, "error_prerealign", True, False) 316cc1dc7a3Sopenharmony_ci epst = get_attrib(candidate, "error_postrealign", True, False) 317cc1dc7a3Sopenharmony_ci 318cc1dc7a3Sopenharmony_ci candStruct = Candidate(wx, wy, wz, wq) 319cc1dc7a3Sopenharmony_ci passStruct.add_candidate(candStruct) 320cc1dc7a3Sopenharmony_ci for value in epre: 321cc1dc7a3Sopenharmony_ci candStruct.add_refinement(value) 322cc1dc7a3Sopenharmony_ci for value in epst: 323cc1dc7a3Sopenharmony_ci candStruct.add_refinement(value) 324cc1dc7a3Sopenharmony_ci 325cc1dc7a3Sopenharmony_ci return dbStruct 326cc1dc7a3Sopenharmony_ci 327cc1dc7a3Sopenharmony_ci 328cc1dc7a3Sopenharmony_cidef filter_database(data): 329cc1dc7a3Sopenharmony_ci 330cc1dc7a3Sopenharmony_ci for block in data: 331cc1dc7a3Sopenharmony_ci best_pass, best_candidate = find_best_pass_and_candidate(block) 332cc1dc7a3Sopenharmony_ci 333cc1dc7a3Sopenharmony_ci for i, pas in rev_enumerate(block): 334cc1dc7a3Sopenharmony_ci if pas != best_pass: 335cc1dc7a3Sopenharmony_ci del block[i] 336cc1dc7a3Sopenharmony_ci continue 337cc1dc7a3Sopenharmony_ci 338cc1dc7a3Sopenharmony_ci if best_candidate is None: 339cc1dc7a3Sopenharmony_ci continue 340cc1dc7a3Sopenharmony_ci 341cc1dc7a3Sopenharmony_ci for j, candidate in rev_enumerate(pas): 342cc1dc7a3Sopenharmony_ci if candidate != best_candidate: 343cc1dc7a3Sopenharmony_ci del pas[j] 344cc1dc7a3Sopenharmony_ci 345cc1dc7a3Sopenharmony_ci 346cc1dc7a3Sopenharmony_cidef generate_pass_statistics(data): 347cc1dc7a3Sopenharmony_ci pass 348cc1dc7a3Sopenharmony_ci 349cc1dc7a3Sopenharmony_ci 350cc1dc7a3Sopenharmony_cidef generate_feature_statistics(data): 351cc1dc7a3Sopenharmony_ci # ------------------------------------------------------------------------- 352cc1dc7a3Sopenharmony_ci # Config 353cc1dc7a3Sopenharmony_ci print("Compressor Config") 354cc1dc7a3Sopenharmony_ci print("=================") 355cc1dc7a3Sopenharmony_ci 356cc1dc7a3Sopenharmony_ci if data.block_z > 1: 357cc1dc7a3Sopenharmony_ci dat = (data.block_x, data.block_y, data.block_z) 358cc1dc7a3Sopenharmony_ci print(" - Block size: %ux%ux%u" % dat) 359cc1dc7a3Sopenharmony_ci else: 360cc1dc7a3Sopenharmony_ci dat = (data.block_x, data.block_y) 361cc1dc7a3Sopenharmony_ci print(" - Block size: %ux%u" % dat) 362cc1dc7a3Sopenharmony_ci 363cc1dc7a3Sopenharmony_ci print("") 364cc1dc7a3Sopenharmony_ci 365cc1dc7a3Sopenharmony_ci # ------------------------------------------------------------------------- 366cc1dc7a3Sopenharmony_ci # Block metrics 367cc1dc7a3Sopenharmony_ci result = ddict(int) 368cc1dc7a3Sopenharmony_ci 369cc1dc7a3Sopenharmony_ci RANGE_QUANT = 16 370cc1dc7a3Sopenharmony_ci 371cc1dc7a3Sopenharmony_ci for block in foreach_block(data): 372cc1dc7a3Sopenharmony_ci ranges = [] 373cc1dc7a3Sopenharmony_ci for i in range(0, 4): 374cc1dc7a3Sopenharmony_ci ranges.append(block.ldr_max[i] - block.ldr_min[i]) 375cc1dc7a3Sopenharmony_ci 376cc1dc7a3Sopenharmony_ci max_range = max(ranges) 377cc1dc7a3Sopenharmony_ci max_range = int(max_range / RANGE_QUANT) * RANGE_QUANT 378cc1dc7a3Sopenharmony_ci 379cc1dc7a3Sopenharmony_ci result[max_range] += 1 380cc1dc7a3Sopenharmony_ci 381cc1dc7a3Sopenharmony_ci print("Channel Range") 382cc1dc7a3Sopenharmony_ci print("=============") 383cc1dc7a3Sopenharmony_ci keys = sorted(result.keys()) 384cc1dc7a3Sopenharmony_ci for key in keys: 385cc1dc7a3Sopenharmony_ci dat = (key, key + RANGE_QUANT - 1, result[key]) 386cc1dc7a3Sopenharmony_ci print(" - %3u-%3u dynamic range = %6u blocks" % dat) 387cc1dc7a3Sopenharmony_ci 388cc1dc7a3Sopenharmony_ci print("") 389cc1dc7a3Sopenharmony_ci 390cc1dc7a3Sopenharmony_ci # ------------------------------------------------------------------------- 391cc1dc7a3Sopenharmony_ci # Partition usage 392cc1dc7a3Sopenharmony_ci result_totals = ddict(int) 393cc1dc7a3Sopenharmony_ci results = ddict(lambda: ddict(int)) 394cc1dc7a3Sopenharmony_ci 395cc1dc7a3Sopenharmony_ci for _, pas in foreach_pass(data): 396cc1dc7a3Sopenharmony_ci result_totals[pas.partitions] += 1 397cc1dc7a3Sopenharmony_ci results[pas.partitions][pas.partition_index] += 1 398cc1dc7a3Sopenharmony_ci 399cc1dc7a3Sopenharmony_ci print("Partition Count") 400cc1dc7a3Sopenharmony_ci print("===============") 401cc1dc7a3Sopenharmony_ci keys = sorted(result_totals.keys()) 402cc1dc7a3Sopenharmony_ci for key in keys: 403cc1dc7a3Sopenharmony_ci dat = (key, result_totals[key], len(results[key])) 404cc1dc7a3Sopenharmony_ci print(" - %u partition(s) = %6u blocks / %4u indicies" % dat) 405cc1dc7a3Sopenharmony_ci 406cc1dc7a3Sopenharmony_ci print("") 407cc1dc7a3Sopenharmony_ci 408cc1dc7a3Sopenharmony_ci # ------------------------------------------------------------------------- 409cc1dc7a3Sopenharmony_ci # Plane usage 410cc1dc7a3Sopenharmony_ci result_count = ddict(lambda: ddict(int)) 411cc1dc7a3Sopenharmony_ci result_channel = ddict(lambda: ddict(int)) 412cc1dc7a3Sopenharmony_ci 413cc1dc7a3Sopenharmony_ci for _, pas in foreach_pass(data): 414cc1dc7a3Sopenharmony_ci result_count[pas.partitions][pas.planes] += 1 415cc1dc7a3Sopenharmony_ci if (pas.planes > 1): 416cc1dc7a3Sopenharmony_ci result_channel[pas.partitions][pas.plane2_component] += 1 417cc1dc7a3Sopenharmony_ci 418cc1dc7a3Sopenharmony_ci print("Plane Usage") 419cc1dc7a3Sopenharmony_ci print("===========") 420cc1dc7a3Sopenharmony_ci keys = sorted(result_count.keys()) 421cc1dc7a3Sopenharmony_ci for key in keys: 422cc1dc7a3Sopenharmony_ci keys2 = sorted(result_count[key]) 423cc1dc7a3Sopenharmony_ci for key2 in keys2: 424cc1dc7a3Sopenharmony_ci val2 = result_count[key][key2] 425cc1dc7a3Sopenharmony_ci dat = (key, key2, val2) 426cc1dc7a3Sopenharmony_ci print(" - %u partition(s) %u plane(s) = %6u blocks" % dat) 427cc1dc7a3Sopenharmony_ci if key2 == 2: 428cc1dc7a3Sopenharmony_ci keys3 = sorted(result_channel[key]) 429cc1dc7a3Sopenharmony_ci for key3 in keys3: 430cc1dc7a3Sopenharmony_ci dat = (CHANNEL_TABLE[key3], result_channel[key][key3]) 431cc1dc7a3Sopenharmony_ci print(" - %s plane = %6u blocks" % dat) 432cc1dc7a3Sopenharmony_ci 433cc1dc7a3Sopenharmony_ci print("") 434cc1dc7a3Sopenharmony_ci 435cc1dc7a3Sopenharmony_ci # ------------------------------------------------------------------------- 436cc1dc7a3Sopenharmony_ci # Decimation usage 437cc1dc7a3Sopenharmony_ci decim_count = ddict(lambda: ddict(int)) 438cc1dc7a3Sopenharmony_ci quant_count = ddict(lambda: ddict(lambda: ddict(int))) 439cc1dc7a3Sopenharmony_ci 440cc1dc7a3Sopenharmony_ci 441cc1dc7a3Sopenharmony_ci MERGE_ROTATIONS = True 442cc1dc7a3Sopenharmony_ci 443cc1dc7a3Sopenharmony_ci for _, pas, can in foreach_candidate(data): 444cc1dc7a3Sopenharmony_ci # Skip constant color blocks 445cc1dc7a3Sopenharmony_ci if can is None: 446cc1dc7a3Sopenharmony_ci continue 447cc1dc7a3Sopenharmony_ci 448cc1dc7a3Sopenharmony_ci wx = can.weight_x 449cc1dc7a3Sopenharmony_ci wy = can.weight_y 450cc1dc7a3Sopenharmony_ci 451cc1dc7a3Sopenharmony_ci if MERGE_ROTATIONS and wx < wy: 452cc1dc7a3Sopenharmony_ci wx, wy = wy, wx 453cc1dc7a3Sopenharmony_ci 454cc1dc7a3Sopenharmony_ci decim_count[wx][wy] += 1 455cc1dc7a3Sopenharmony_ci quant_count[wx][wy][can.weight_quant] += 1 456cc1dc7a3Sopenharmony_ci 457cc1dc7a3Sopenharmony_ci print("Decimation Usage") 458cc1dc7a3Sopenharmony_ci print("================") 459cc1dc7a3Sopenharmony_ci 460cc1dc7a3Sopenharmony_ci if MERGE_ROTATIONS: 461cc1dc7a3Sopenharmony_ci print(" - Note: data merging grid rotations") 462cc1dc7a3Sopenharmony_ci 463cc1dc7a3Sopenharmony_ci x_keys = sorted(decim_count.keys()) 464cc1dc7a3Sopenharmony_ci for x_key in x_keys: 465cc1dc7a3Sopenharmony_ci y_keys = sorted(decim_count[x_key]) 466cc1dc7a3Sopenharmony_ci 467cc1dc7a3Sopenharmony_ci for y_key in y_keys: 468cc1dc7a3Sopenharmony_ci count = decim_count[x_key][y_key] 469cc1dc7a3Sopenharmony_ci dat = (x_key, y_key, count) 470cc1dc7a3Sopenharmony_ci print(" - %ux%u weights = %6u blocks" % dat) 471cc1dc7a3Sopenharmony_ci 472cc1dc7a3Sopenharmony_ci q_keys = sorted(quant_count[x_key][y_key]) 473cc1dc7a3Sopenharmony_ci for q_key in q_keys: 474cc1dc7a3Sopenharmony_ci count = quant_count[x_key][y_key][q_key] 475cc1dc7a3Sopenharmony_ci dat = (q_key, count) 476cc1dc7a3Sopenharmony_ci print(" - %2u quant range = %6u blocks" % dat) 477cc1dc7a3Sopenharmony_ci 478cc1dc7a3Sopenharmony_ci print("") 479cc1dc7a3Sopenharmony_ci 480cc1dc7a3Sopenharmony_ci # ------------------------------------------------------------------------- 481cc1dc7a3Sopenharmony_ci # Refinement usage 482cc1dc7a3Sopenharmony_ci 483cc1dc7a3Sopenharmony_ci total_count = 0 484cc1dc7a3Sopenharmony_ci better_count = 0 485cc1dc7a3Sopenharmony_ci could_have_count = 0 486cc1dc7a3Sopenharmony_ci success_count = 0 487cc1dc7a3Sopenharmony_ci 488cc1dc7a3Sopenharmony_ci refinement_step = [] 489cc1dc7a3Sopenharmony_ci 490cc1dc7a3Sopenharmony_ci for block, pas, candidate in foreach_candidate(data): 491cc1dc7a3Sopenharmony_ci # Ignore zero partition blocks - they don't use refinement 492cc1dc7a3Sopenharmony_ci if not candidate: 493cc1dc7a3Sopenharmony_ci continue 494cc1dc7a3Sopenharmony_ci 495cc1dc7a3Sopenharmony_ci target_error = block.error_target 496cc1dc7a3Sopenharmony_ci start_error = candidate.refinement_errors[0] 497cc1dc7a3Sopenharmony_ci end_error = candidate.refinement_errors[-1] 498cc1dc7a3Sopenharmony_ci 499cc1dc7a3Sopenharmony_ci rpf = float(start_error - end_error) / float(len(candidate.refinement_errors)) 500cc1dc7a3Sopenharmony_ci rpf = abs(rpf) 501cc1dc7a3Sopenharmony_ci refinement_step.append(rpf / start_error) 502cc1dc7a3Sopenharmony_ci 503cc1dc7a3Sopenharmony_ci total_count += 1 504cc1dc7a3Sopenharmony_ci if end_error <= start_error: 505cc1dc7a3Sopenharmony_ci better_count += 1 506cc1dc7a3Sopenharmony_ci 507cc1dc7a3Sopenharmony_ci if end_error <= target_error: 508cc1dc7a3Sopenharmony_ci success_count += 1 509cc1dc7a3Sopenharmony_ci else: 510cc1dc7a3Sopenharmony_ci for refinement in candidate.refinement_errors: 511cc1dc7a3Sopenharmony_ci if refinement <= target_error: 512cc1dc7a3Sopenharmony_ci could_have_count += 1 513cc1dc7a3Sopenharmony_ci break 514cc1dc7a3Sopenharmony_ci 515cc1dc7a3Sopenharmony_ci 516cc1dc7a3Sopenharmony_ci print("Refinement Usage") 517cc1dc7a3Sopenharmony_ci print("================") 518cc1dc7a3Sopenharmony_ci print(" - %u refinements(s)" % total_count) 519cc1dc7a3Sopenharmony_ci print(" - %u refinements(s) improved" % better_count) 520cc1dc7a3Sopenharmony_ci print(" - %u refinements(s) worsened" % (total_count - better_count)) 521cc1dc7a3Sopenharmony_ci print(" - %u refinements(s) could hit target, but didn't" % could_have_count) 522cc1dc7a3Sopenharmony_ci print(" - %u refinements(s) hit target" % success_count) 523cc1dc7a3Sopenharmony_ci print(" - %f mean step improvement" % np.mean(refinement_step)) 524cc1dc7a3Sopenharmony_ci 525cc1dc7a3Sopenharmony_ci 526cc1dc7a3Sopenharmony_cidef parse_command_line(): 527cc1dc7a3Sopenharmony_ci """ 528cc1dc7a3Sopenharmony_ci Parse the command line. 529cc1dc7a3Sopenharmony_ci 530cc1dc7a3Sopenharmony_ci Returns: 531cc1dc7a3Sopenharmony_ci Namespace: The parsed command line container. 532cc1dc7a3Sopenharmony_ci """ 533cc1dc7a3Sopenharmony_ci parser = argparse.ArgumentParser() 534cc1dc7a3Sopenharmony_ci 535cc1dc7a3Sopenharmony_ci parser.add_argument("trace", type=argparse.FileType("r"), 536cc1dc7a3Sopenharmony_ci help="The trace file to analyze") 537cc1dc7a3Sopenharmony_ci 538cc1dc7a3Sopenharmony_ci return parser.parse_args() 539cc1dc7a3Sopenharmony_ci 540cc1dc7a3Sopenharmony_ci 541cc1dc7a3Sopenharmony_cidef main(): 542cc1dc7a3Sopenharmony_ci """ 543cc1dc7a3Sopenharmony_ci The main function. 544cc1dc7a3Sopenharmony_ci 545cc1dc7a3Sopenharmony_ci Returns: 546cc1dc7a3Sopenharmony_ci int: The process return code. 547cc1dc7a3Sopenharmony_ci """ 548cc1dc7a3Sopenharmony_ci args = parse_command_line() 549cc1dc7a3Sopenharmony_ci 550cc1dc7a3Sopenharmony_ci data = json.load(args.trace) 551cc1dc7a3Sopenharmony_ci db = generate_database(data) 552cc1dc7a3Sopenharmony_ci filter_database(db) 553cc1dc7a3Sopenharmony_ci 554cc1dc7a3Sopenharmony_ci generate_feature_statistics(db) 555cc1dc7a3Sopenharmony_ci 556cc1dc7a3Sopenharmony_ci return 0 557cc1dc7a3Sopenharmony_ci 558cc1dc7a3Sopenharmony_ci 559cc1dc7a3Sopenharmony_ciif __name__ == "__main__": 560cc1dc7a3Sopenharmony_ci sys.exit(main()) 561