Skip to content

Commit

Permalink
Fix multi memtile buffer viz (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
mariodruiz authored Oct 24, 2024
1 parent 544c36a commit cd371b7
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 45 deletions.
1 change: 1 addition & 0 deletions npu/build/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .port import BufferPort, RTPPort
from typing import Optional, Callable, List, Dict
import re
import warnings


class Kernel(KernelMeta):
Expand Down
3 changes: 2 additions & 1 deletion npu/lib/cached/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
# SPDX-License-Identifier: MIT

*.o
*.md5
*.md5
*.o.lst
123 changes: 81 additions & 42 deletions npu/utils/appviz.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
'inbuf': [config.light_blue, config.lilac],
'outbuf': [config.dark_blue, config.pink]},
3: {'kernel': config.red,
'inbuf': [config.light_red, config.green],
'inbuf': [config.light_red, config.magenta],
'outbuf': [config.red, config.light_orange]}
}

_it2mt_color = [config.green, config.artichoke]
_mt2it_color = [config.purple, config.orchid]


class AppViz:
""" Visualize the Dataflow Graph in a column of the NPU"""
Expand All @@ -38,8 +41,13 @@ def __init__(self, metadata: str):
self._drawn_kernels = self._draw_kernels()
self._ct2mt_counter = 0
self._mt2ct_counter = 0
self._mt2ct_passthrough = {'found': False, 'color': None}
self._it2ct_counter = 0
self._ct2it_counter = 0
self._it2mt_counter = 0
self._mt2it_counter = 0
self._mt2ct_pt = {}
self._dbuf_colors = {}
self._ct2mt_dict = {}
self._draw_connections_sorted()
self._draw_key()

Expand Down Expand Up @@ -112,11 +120,10 @@ def _draw_connections_sorted(self) -> None:
# Draw animations starting in the MT second. Run twice for ping-pong
for i in range(2):
for k, c in conn.items():
if c['srcport'] == 'MTout':
if c['srcport'] == 'MTout' and c['sinkport'] != 'ITin':
self._draw_connection(c, bool(i))
if i == 1:
tmpconn.pop(k)
self._ct2mt_counter = 0
self._mt2ct_counter = 0
conn = copy(tmpconn)

Expand All @@ -127,6 +134,7 @@ def _draw_connections_sorted(self) -> None:
self._draw_connection(c, bool(i))
if i == 1:
tmpconn.pop(k)
self._ct2mt_counter = 0
conn = copy(tmpconn)

# Draw remaining animations
Expand Down Expand Up @@ -155,7 +163,7 @@ def _draw_connection(self, c, dbuf: bool = False) -> None:
self._col_svg.aie_tiles[dst_row].add_buffer(
self._drawn_kernels[src['name']]['kcolor'],
self._kanimate_duration/2,
start_empty= bool(i))
start_empty=bool(i))

self._draw_ct2ct_data_movement(src, dst)

Expand All @@ -168,6 +176,7 @@ def _draw_connection(self, c, dbuf: bool = False) -> None:
self._kanimate_duration/2,
start_empty=bool(i))
self._draw_ub_ic_ingress(dst, bufcol)
self._it2ct_counter += 1

if src['type'] == 'CT' and dst['type'] == 'IT':
src_row = self._drawn_kernels[src['name']]['row']
Expand All @@ -177,7 +186,8 @@ def _draw_connection(self, c, dbuf: bool = False) -> None:
bufcol,
self._kanimate_duration/2,
start_empty=not bool(i))
self._draw_ub_ic_egress(src)
self._draw_ub_ic_egress(src, bufcol)
self._ct2it_counter += 1

if src['type'] == 'CT' and dst['type'] == 'MT':
src_row = self._drawn_kernels[src['name']]['row']
Expand All @@ -187,20 +197,25 @@ def _draw_connection(self, c, dbuf: bool = False) -> None:
else:
bufcol = self._dbuf_colors[c['name']]

if (key := c['sinkkernel']) not in self._ct2mt_dict.keys():
self._ct2mt_dict[key] = {'idx': len(self._ct2mt_dict)}

dst_it_color = _mt2it_color[self._ct2mt_dict[key]['idx']]

self._col_svg.mem_tiles[0].add_buffer(
bufcol,
self._kanimate_duration/2,
start_empty=dbuf,
color2=config.purple,
delay= self._ct2mt_counter/5)
start_empty=not dbuf,
color2=dst_it_color,
delay=self._ct2mt_counter/5)
if not dbuf:
for i in range(2):
self._col_svg.aie_tiles[src_row].add_buffer(
bufcol,
self._kanimate_duration/2,
start_empty=bool(i))

self._draw_ct2mem_ic(src)
self._draw_ct2mem_ic(src, bufcol)
else:
self._ct2mt_counter += 1

Expand All @@ -215,37 +230,38 @@ def _draw_connection(self, c, dbuf: bool = False) -> None:
show_mem_buffer = True
mtmode = src.get('mtmode')
if mtmode == 'passthrough':
if self._mt2ct_passthrough['found']:
dst_buf_color = self._mt2ct_passthrough['color']
if not self._mt2ct_pt.get(src['name']):
self._mt2ct_pt[src['name']] = {'color': dst_buf_color}
elif self._mt2ct_pt[src['name']]:
dst_buf_color = self._mt2ct_pt[src['name']]['color']
show_mem_buffer = False
else:
self._mt2ct_passthrough['found'] = True
self._mt2ct_passthrough['color'] = dst_buf_color

idx = int(c['srckernel'][-1]) % 2
src_color = _it2mt_color[idx]

if show_mem_buffer:
for i in range(int(self._mt2ct_passthrough['found']) + 1):
for i in range(int(bool(self._mt2ct_pt)) + 1):
self._col_svg.mem_tiles[0].add_buffer(
config.green,
src_color,
self._kanimate_duration/2,
start_empty=dbuf ^ bool(i),
start_empty=not (dbuf ^ bool(i)),
color2=dst_buf_color,
delay=self._mt2ct_counter/5)
self._col_svg.aie_tiles[dst_row].add_buffer(
dst_buf_color,
self._kanimate_duration/2,
start_empty=dbuf)
if not dbuf:
self._draw_mem2ct_ic(dst, c, dst_buf_color, mtmode)
self._draw_mem2ct_ic(dst, dst_buf_color, mtmode)
else:
self._mt2ct_counter += 1

self._draw_ub2mem_ic(src, dst)
self._draw_mem2ub_ic(src, dst)

def _draw_ct2mem_ic(self, src) -> None:
def _draw_ct2mem_ic(self, src, src_color) -> None:
"""Display animation originating from CT and destination MT"""

src_color = self._drawn_kernels[src['name']]['kcolor']
src_row = self._loc_conv[src['tloc'][1]]
delay = self._ct2mt_counter / 5

Expand All @@ -265,7 +281,7 @@ def _draw_ct2mem_ic(self, src) -> None:
color=src_color)
self._ct2mt_counter += 1

def _draw_mem2ct_ic(self, dst, c, dst_color, mtmode=None) -> None:
def _draw_mem2ct_ic(self, dst, dst_color, mtmode=None) -> None:
"""Display animation originating from MT and destination CT"""

dst_row = self._loc_conv[dst['tloc'][1]]
Expand All @@ -291,44 +307,59 @@ def _draw_ub2mem_ic(self, src, dst) -> None:
"""Display animation originating from IT and destination MT"""

if src['type'] == 'IT' and dst['type'] == 'MT':
src_color = config.green
if self._it2mt_counter > 1:
warnings.warn("Cannot display more than two input buffers "
"from the interface tile to the memory tile")
return
src_color = _it2mt_color[self._it2mt_counter]
self._col_svg.mem_tiles[0].add_ic_animation(
diagonal_to_tile=1,
north=1,
duration=self._kanimate_duration*1,
color=src_color)
duration=self._kanimate_duration/2,
color=src_color,
delay=self._it2mt_counter/5)
self._col_svg.if_tiles[0].add_dma_animation(
south_up=1,
duration=self._kanimate_duration/2,
color=src_color)
color=src_color,
delay=self._it2mt_counter/5)
self._col_svg.if_tiles[0].add_ic_animation(
diagonal_from_tile=1,
duration=self._kanimate_duration/2,
color=src_color)
color=src_color,
delay=self._it2mt_counter/5)
self._it2mt_counter += 1

def _draw_mem2ub_ic(self, src, dst) -> None:
"""Display animation originating from MT and destination IT"""

if src['type'] == 'MT' and dst['type'] == 'IT':
dst_color = config.purple
if self._mt2it_counter > 1:
warnings.warn("Cannot display more than two output buffers "
"from the memory tile to the interface tile")
return
dst_color = _mt2it_color[self._mt2it_counter]
self._col_svg.mem_tiles[0].add_ic_animation(
diagonal_from_tile=1,
south=1,
duration=self._kanimate_duration*1,
color=dst_color)
duration=self._kanimate_duration/2,
color=dst_color,
delay=self._mt2it_counter/5)
self._col_svg.if_tiles[0].add_ic_animation(
diagonal_to_tile=1,
duration=self._kanimate_duration/2,
color=dst_color)
color=dst_color,
delay=self._mt2it_counter/5)
self._col_svg.if_tiles[0].add_dma_animation(
south_down=1,
duration=self._kanimate_duration/2,
color=dst_color)
color=dst_color,
delay=self._mt2it_counter/5)
self._mt2it_counter += 1

def _draw_ub_ic_egress(self, src) -> None:
def _draw_ub_ic_egress(self, src, src_color) -> None:
"""Display animation originating from CT and destination IT"""

src_color = self._drawn_kernels[src['name']]['kcolor']
src_row = self._loc_conv[src['tloc'][1]]

for i in range(3, src_row-1, -1):
Expand All @@ -337,39 +368,46 @@ def _draw_ub_ic_egress(self, src) -> None:
diagonal_from_tile=diagonal_from_tile,
south=1,
duration=self._kanimate_duration/2,
color=src_color)
color=src_color,
delay=self._ct2it_counter/5)

self._col_svg.mem_tiles[0].add_ic_animation(
south=1,
duration=self._kanimate_duration/2,
color=src_color)
color=src_color,
delay=self._ct2it_counter/5)

self._col_svg.if_tiles[0].add_ic_animation(
diagonal_to_tile=1,
duration=self._kanimate_duration/2,
color=src_color)
color=src_color,
delay=self._ct2it_counter/5)

self._col_svg.if_tiles[0].add_dma_animation(
south_down=1,
duration=self._kanimate_duration/2,
color=src_color)
color=src_color,
delay=self._ct2it_counter/5)

def _draw_ub_ic_ingress(self, dst, kcolor) -> None:
"""Display animation originating from IT and destination CT"""

self._col_svg.if_tiles[0].add_ic_animation(
diagonal_from_tile=1,
duration=self._kanimate_duration/2,
color=kcolor)
color=kcolor,
delay=self._it2ct_counter/5)
self._col_svg.if_tiles[0].add_dma_animation(
south_up=1,
duration=self._kanimate_duration/2,
color=kcolor)
color=kcolor,
delay=self._it2ct_counter/5)

self._col_svg.mem_tiles[0].add_ic_animation(
north=1,
duration=self._kanimate_duration/2,
color=kcolor)
color=kcolor,
delay=self._it2ct_counter/5)

dst_row = self._loc_conv[dst['tloc'][1]]
for i in range(3, dst_row-1, -1):
Expand All @@ -378,7 +416,8 @@ def _draw_ub_ic_ingress(self, dst, kcolor) -> None:
diagonal_to_tile=diagonal_to_tile,
north=1,
duration=self._kanimate_duration/2,
color=kcolor)
color=kcolor,
delay=self._it2ct_counter/5)

def _draw_ct2ct_data_movement(self, src, dst) -> None:
"""Display animation originating from CT and destination CT
Expand Down
4 changes: 4 additions & 0 deletions npu/utils/svg_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@
red = "#C00000"
yellow = "#F0E442"
green = "#009E73"
artichoke = "#8F9779"
pink = "#CC79A7" # "#CC79A7"
dark_orange = "#D55E00"
dark_pink = "#DC267F"
purple = "#4B0092"
orchid = "#AF69EE"
lilac = "#E0C2FF"
magenta = "#FF00FF"
violet = "#8F00FF"

light_orange = "#F7E2B2"
light_red = "#C36D6D"
Expand Down
2 changes: 2 additions & 0 deletions tests/test_memtile_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def callgraph(self, x_in, x_out):
trace_app.save(f'{imgdir}{trace_app.name}_{datatype_txt}.svg')
app = AppRunner(f"{trace_app.name}.xclbin")

np.random.seed(512)
test_data = np.random.randn(*array_in.shape).astype(datatype)
bo_in = app.allocate(shape=(4, size), dtype=datatype)
bo_out = app.allocate(shape=(4, size), dtype=datatype)
Expand Down Expand Up @@ -135,6 +136,7 @@ def callgraph(self, x_in, x_out):
trace_app.save(f'{imgdir}{trace_app.name}_{datatype_txt}.svg')
app = AppRunner(f"{trace_app.name}.xclbin")

np.random.seed(256)
test_data = np.random.randn(*array_in.shape).astype(datatype)
bo_in = app.allocate(shape=array_in.shape, dtype=datatype)
bo_out = app.allocate(shape=array_out.shape, dtype=datatype)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def setval_behavioral(obj):
objin = getattr(obj, inname)
objout.array = objin.array

class DataParallelPassthrough(AppBuilder):
class DataParallelMTSplit(AppBuilder):
def __init__(self):
self.split = MTSplit(4)
self.concat = MTConcat()
Expand All @@ -296,7 +296,7 @@ def callgraph(self, xin, xout):
x = self.concat(xs)
xout[t] = x

app_builder = DataParallelPassthrough()
app_builder = DataParallelMTSplit()
_ = app_builder.to_metadata(x_in, x_out)
svgfile = f'{imgdir}{app_builder.name}_{inname}_{outname}.svg'
app_builder.save(svgfile)
Expand Down
Loading

0 comments on commit cd371b7

Please sign in to comment.