xref: /XiangShan/scripts/top-down/top_down.py (revision eb163ef08fc5ac1da1f32d948699bd6de053e444)
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