1*eb163ef0SHaojin Tangimport csv 2*eb163ef0SHaojin Tangimport sys 3*eb163ef0SHaojin Tangfrom pyecharts.charts import Page, Sunburst 4*eb163ef0SHaojin Tangfrom pyecharts import options as opts 5*eb163ef0SHaojin Tang 6*eb163ef0SHaojin Tang 7*eb163ef0SHaojin Tangclass TopDown: 8*eb163ef0SHaojin Tang """TopDown node""" 9*eb163ef0SHaojin Tang def __init__(self, name, percentage): 10*eb163ef0SHaojin Tang self.name = name 11*eb163ef0SHaojin Tang if isinstance(percentage, TopDown): 12*eb163ef0SHaojin Tang self.percentage = percentage.percentage 13*eb163ef0SHaojin Tang else: 14*eb163ef0SHaojin Tang self.percentage = percentage 15*eb163ef0SHaojin Tang self.down = {} 16*eb163ef0SHaojin Tang self.top = None 17*eb163ef0SHaojin Tang self.level = 0 18*eb163ef0SHaojin Tang 19*eb163ef0SHaojin Tang def __add__(self, rhs): 20*eb163ef0SHaojin Tang if isinstance(rhs, TopDown): 21*eb163ef0SHaojin Tang return self.percentage + rhs.percentage 22*eb163ef0SHaojin Tang return self.percentage + rhs 23*eb163ef0SHaojin Tang 24*eb163ef0SHaojin Tang def __radd__(self, lhs): 25*eb163ef0SHaojin Tang if isinstance(lhs, TopDown): 26*eb163ef0SHaojin Tang return lhs.percentage + self.percentage 27*eb163ef0SHaojin Tang return lhs + self.percentage 28*eb163ef0SHaojin Tang 29*eb163ef0SHaojin Tang def __sub__(self, rhs): 30*eb163ef0SHaojin Tang if isinstance(rhs, TopDown): 31*eb163ef0SHaojin Tang return self.percentage - rhs.percentage 32*eb163ef0SHaojin Tang return self.percentage - rhs 33*eb163ef0SHaojin Tang 34*eb163ef0SHaojin Tang def __rsub__(self, lhs): 35*eb163ef0SHaojin Tang if isinstance(lhs, TopDown): 36*eb163ef0SHaojin Tang return lhs.percentage - self.percentage 37*eb163ef0SHaojin Tang return lhs - self.percentage 38*eb163ef0SHaojin Tang 39*eb163ef0SHaojin Tang def __mul__(self, rhs): 40*eb163ef0SHaojin Tang if isinstance(rhs, TopDown): 41*eb163ef0SHaojin Tang return self.percentage * rhs.percentage 42*eb163ef0SHaojin Tang return self.percentage * rhs 43*eb163ef0SHaojin Tang 44*eb163ef0SHaojin Tang def __rmul__(self, lhs): 45*eb163ef0SHaojin Tang if isinstance(lhs, TopDown): 46*eb163ef0SHaojin Tang return lhs.percentage * self.percentage 47*eb163ef0SHaojin Tang return lhs * self.percentage 48*eb163ef0SHaojin Tang 49*eb163ef0SHaojin Tang def __truediv__(self, rhs): 50*eb163ef0SHaojin Tang if isinstance(rhs, TopDown): 51*eb163ef0SHaojin Tang return self.percentage / rhs.percentage 52*eb163ef0SHaojin Tang return self.percentage / rhs 53*eb163ef0SHaojin Tang 54*eb163ef0SHaojin Tang def __rtruediv__(self, lhs): 55*eb163ef0SHaojin Tang if isinstance(lhs, TopDown): 56*eb163ef0SHaojin Tang return lhs.percentage / self.percentage 57*eb163ef0SHaojin Tang return lhs / self.percentage 58*eb163ef0SHaojin Tang 59*eb163ef0SHaojin Tang def add_down(self, name, percentage): 60*eb163ef0SHaojin Tang """Add a leaf node 61*eb163ef0SHaojin Tang 62*eb163ef0SHaojin Tang Args: 63*eb163ef0SHaojin Tang name (str): Name of leaf node 64*eb163ef0SHaojin Tang percentage (float): Percentage of leaf node 65*eb163ef0SHaojin Tang 66*eb163ef0SHaojin Tang Returns: 67*eb163ef0SHaojin Tang TopDown: leaf 68*eb163ef0SHaojin Tang """ 69*eb163ef0SHaojin Tang self.down[name] = TopDown(name, percentage) 70*eb163ef0SHaojin Tang self.down[name].top = self 71*eb163ef0SHaojin Tang self.down[name].level = self.level + 1 72*eb163ef0SHaojin Tang return self.down[name] 73*eb163ef0SHaojin Tang 74*eb163ef0SHaojin Tang def draw(self): 75*eb163ef0SHaojin Tang """Draw the TopDown sunburst chart 76*eb163ef0SHaojin Tang 77*eb163ef0SHaojin Tang Returns: 78*eb163ef0SHaojin Tang _type_: _description_ 79*eb163ef0SHaojin Tang """ 80*eb163ef0SHaojin Tang if not self.down: 81*eb163ef0SHaojin Tang return [opts.SunburstItem(name=self.name, value=self.percentage)] 82*eb163ef0SHaojin Tang items = [] 83*eb163ef0SHaojin Tang for value in self.down.values(): 84*eb163ef0SHaojin Tang items.append(value.draw()[0]) 85*eb163ef0SHaojin Tang if self.top: 86*eb163ef0SHaojin Tang return [opts.SunburstItem(name=self.name, value=self.percentage, children=items)] 87*eb163ef0SHaojin Tang return items 88*eb163ef0SHaojin Tang 89*eb163ef0SHaojin Tang 90*eb163ef0SHaojin Tangdef process_one(path, head): 91*eb163ef0SHaojin Tang """Process one chart 92*eb163ef0SHaojin Tang 93*eb163ef0SHaojin Tang Args: 94*eb163ef0SHaojin Tang path (String): csv path 95*eb163ef0SHaojin Tang head (String): chart head 96*eb163ef0SHaojin Tang 97*eb163ef0SHaojin Tang Returns: 98*eb163ef0SHaojin Tang Sunburst chart 99*eb163ef0SHaojin Tang """ 100*eb163ef0SHaojin Tang with open(path, encoding='UTF-8') as file: 101*eb163ef0SHaojin Tang csv_file = dict(csv.reader(file)) 102*eb163ef0SHaojin Tang 103*eb163ef0SHaojin Tang def use(name): 104*eb163ef0SHaojin Tang return float(csv_file[name]) 105*eb163ef0SHaojin Tang 106*eb163ef0SHaojin Tang csv_file['total_slots'] = use('total_cycles') * 6 107*eb163ef0SHaojin Tang csv_file['ifu2id_allNO_slots'] = use('ifu2id_allNO_cycle') * 6 108*eb163ef0SHaojin Tang csv_file['ifu2id_hvButNotFull_slots'] = use('fetch_bubbles') - use('ifu2id_allNO_slots') 109*eb163ef0SHaojin Tang 110*eb163ef0SHaojin Tang stall_cycles_core = use('stall_cycle_fp') + use('stall_cycle_int') + use('stall_cycle_rob') + use('stall_cycle_int_dq') + use('stall_cycle_fp_dq') + use('ls_dq_bound_cycles') 111*eb163ef0SHaojin Tang 112*eb163ef0SHaojin Tang top = TopDown("Top", 1.0) 113*eb163ef0SHaojin Tang 114*eb163ef0SHaojin Tang# top 115*eb163ef0SHaojin Tang frontend_bound = top.add_down("Frontend Bound", use('decode_bubbles') / use('total_slots')) 116*eb163ef0SHaojin Tang bad_speculation = top.add_down("Bad Speculation", (use('slots_issued') - use('slots_retired') + use('recovery_bubbles')) / use('total_slots')) 117*eb163ef0SHaojin Tang retiring = top.add_down("Retiring", use('slots_retired') / use('total_slots')) 118*eb163ef0SHaojin Tang backend_bound = top.add_down("Backend Bound", top - frontend_bound - bad_speculation - retiring) 119*eb163ef0SHaojin Tang 120*eb163ef0SHaojin Tang#top->frontend_bound 121*eb163ef0SHaojin Tang fetch_latency = frontend_bound.add_down("Fetch Latency", use('fetch_bubbles') / use('total_slots')) 122*eb163ef0SHaojin Tang fetch_bandwidth = frontend_bound.add_down("Fetch Bandwidth", frontend_bound - fetch_latency) 123*eb163ef0SHaojin Tang 124*eb163ef0SHaojin Tang# top->frontend_bound->fetch_latency 125*eb163ef0SHaojin Tang itlb_miss = fetch_latency.add_down("iTLB Miss", use('itlb_miss_cycles') / use('total_cycles')) 126*eb163ef0SHaojin Tang icache_miss = fetch_latency.add_down("iCache Miss", use('icache_miss_cycles') / use('total_cycles')) 127*eb163ef0SHaojin Tang stage2_redirect_cycles = fetch_latency.add_down("Stage2 Redirect", use('stage2_redirect_cycles') / use('total_cycles')) 128*eb163ef0SHaojin Tang if2id_bandwidth = fetch_latency.add_down("IF2ID Bandwidth", use('ifu2id_hvButNotFull_slots') / use('total_slots')) 129*eb163ef0SHaojin Tang fetch_latency_others = fetch_latency.add_down("Fetch Latency Others", fetch_latency - itlb_miss - icache_miss - stage2_redirect_cycles - if2id_bandwidth) 130*eb163ef0SHaojin Tang 131*eb163ef0SHaojin Tang# top->frontend_bound->fetch_latency->stage2_redirect_cycles 132*eb163ef0SHaojin Tang branch_resteers = stage2_redirect_cycles.add_down("Branch Resteers", use('branch_resteers_cycles') / use('total_cycles')) 133*eb163ef0SHaojin Tang robFlush_bubble = stage2_redirect_cycles.add_down("RobFlush Bubble", use('robFlush_bubble_cycles') / use('total_cycles')) 134*eb163ef0SHaojin Tang ldReplay_bubble = stage2_redirect_cycles.add_down("LdReplay Bubble", use('ldReplay_bubble_cycles') / use('total_cycles')) 135*eb163ef0SHaojin Tang 136*eb163ef0SHaojin Tang# top->bad_speculation 137*eb163ef0SHaojin Tang branch_mispredicts = bad_speculation.add_down("Branch Mispredicts", bad_speculation) 138*eb163ef0SHaojin Tang 139*eb163ef0SHaojin Tang# top->backend_bound 140*eb163ef0SHaojin Tang memory_bound = backend_bound.add_down("Memory Bound", backend_bound * (use('store_bound_cycles') + use('load_bound_cycles')) / ( 141*eb163ef0SHaojin Tang stall_cycles_core + use('store_bound_cycles') + use('load_bound_cycles'))) 142*eb163ef0SHaojin Tang core_bound = backend_bound.add_down("Core Bound", backend_bound - memory_bound) 143*eb163ef0SHaojin Tang 144*eb163ef0SHaojin Tang# top->backend_bound->memory_bound 145*eb163ef0SHaojin Tang stores_bound = memory_bound.add_down("Stores Bound", use('store_bound_cycles') / use('total_cycles')) 146*eb163ef0SHaojin Tang loads_bound = memory_bound.add_down("Loads Bound", use('load_bound_cycles') / use('total_cycles')) 147*eb163ef0SHaojin Tang 148*eb163ef0SHaojin Tang# top->backend_bound->core_bound 149*eb163ef0SHaojin Tang integer_dq = core_bound.add_down("Integer DQ", core_bound * use('stall_cycle_int_dq') / stall_cycles_core) 150*eb163ef0SHaojin Tang floatpoint_dq = core_bound.add_down("Floatpoint DQ", core_bound * use('stall_cycle_fp_dq') / stall_cycles_core) 151*eb163ef0SHaojin Tang rob = core_bound.add_down("ROB", core_bound * use('stall_cycle_rob') / stall_cycles_core) 152*eb163ef0SHaojin Tang integer_prf = core_bound.add_down("Integer PRF", core_bound * use('stall_cycle_int') / stall_cycles_core) 153*eb163ef0SHaojin Tang floatpoint_prf = core_bound.add_down("Floatpoint PRF", core_bound * use('stall_cycle_fp') / stall_cycles_core) 154*eb163ef0SHaojin Tang lsu_ports = core_bound.add_down("LSU Ports", core_bound * use('ls_dq_bound_cycles') / stall_cycles_core) 155*eb163ef0SHaojin Tang 156*eb163ef0SHaojin Tang# top->backend_bound->memory_bound->loads_bound 157*eb163ef0SHaojin Tang l1d_loads_bound = loads_bound.add_down("L1D Loads", use('l1d_loads_bound_cycles') / use('total_cycles')) 158*eb163ef0SHaojin Tang l2_loads_bound = loads_bound.add_down("L2 Loads", use('l2_loads_bound_cycles') / use('total_cycles')) 159*eb163ef0SHaojin Tang l3_loads_bound = loads_bound.add_down("L3 Loads", use('l3_loads_bound_cycles') / use('total_cycles')) 160*eb163ef0SHaojin Tang ddr_loads_bound = loads_bound.add_down("DDR Loads", use('ddr_loads_bound_cycles') / use('total_cycles')) 161*eb163ef0SHaojin Tang 162*eb163ef0SHaojin Tang# top->backend_bound->memory_bound->loads_bound->l1d_loads_bound 163*eb163ef0SHaojin Tang l1d_loads_mshr_bound = l1d_loads_bound.add_down("L1D Loads MSHR", use('l1d_loads_mshr_bound') / use('total_cycles')) 164*eb163ef0SHaojin Tang l1d_loads_tlb_bound = l1d_loads_bound.add_down("L1D Loads TLB", use('l1d_loads_tlb_bound') / use('total_cycles')) 165*eb163ef0SHaojin Tang l1d_loads_store_data_bound = l1d_loads_bound.add_down("L1D Loads sdata", use('l1d_loads_store_data_bound') / use('total_cycles')) 166*eb163ef0SHaojin Tang l1d_loads_bank_conflict_bound = l1d_loads_bound.add_down("L1D Loads\nBank Conflict", use('l1d_loads_bank_conflict_bound') / use('total_cycles')) 167*eb163ef0SHaojin Tang l1d_loads_vio_check_redo_bound = l1d_loads_bound.add_down("L1D Loads VioRedo", use('l1d_loads_vio_check_redo_bound') / use('total_cycles')) 168*eb163ef0SHaojin Tang 169*eb163ef0SHaojin Tang 170*eb163ef0SHaojin Tang return ( 171*eb163ef0SHaojin Tang Sunburst(init_opts=opts.InitOpts(width="1000px", height="1200px")) 172*eb163ef0SHaojin Tang .add(series_name="", data_pair=top.draw(), radius=[0, "90%"]) 173*eb163ef0SHaojin Tang .set_global_opts(title_opts=opts.TitleOpts(title=head)) 174*eb163ef0SHaojin Tang .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}"))) 175*eb163ef0SHaojin Tang 176*eb163ef0SHaojin Tang 177*eb163ef0SHaojin Tangtitle = sys.argv[1] 178*eb163ef0SHaojin Tangdirectory = sys.argv[2] 179*eb163ef0SHaojin Tangsuffix = sys.argv[3] 180*eb163ef0SHaojin Tangprint(title) 181*eb163ef0SHaojin Tang( 182*eb163ef0SHaojin Tang Page(page_title=title, layout=Page.SimplePageLayout) 183*eb163ef0SHaojin Tang .add(process_one(directory + "/csv/" + title + ".log.csv", title + "_" + suffix)) 184*eb163ef0SHaojin Tang .render(directory + "/html/" + title + ".html")) 185