ttnn-visualizer 0.46.0__py3-none-any.whl → 0.48.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. ttnn_visualizer/app.py +36 -1
  2. ttnn_visualizer/csv_queries.py +2 -1
  3. ttnn_visualizer/file_uploads.py +1 -1
  4. ttnn_visualizer/models.py +1 -0
  5. ttnn_visualizer/queries.py +1 -1
  6. ttnn_visualizer/settings.py +1 -0
  7. ttnn_visualizer/sockets.py +31 -0
  8. ttnn_visualizer/static/assets/{allPaths-esBqnTg5.js → allPaths-DyhSRH--.js} +1 -1
  9. ttnn_visualizer/static/assets/allPathsLoader-DXd_rN1a.js +2 -0
  10. ttnn_visualizer/static/assets/{index-BuHal8Ii.css → index-CZ0Uonoz.css} +2 -2
  11. ttnn_visualizer/static/assets/{index-BANm1CMY.js → index-T8PVeTUn.js} +227 -227
  12. ttnn_visualizer/static/assets/{splitPathsBySizeLoader-DYuDhweD.js → splitPathsBySizeLoader-Gsi3qlIM.js} +1 -1
  13. ttnn_visualizer/static/index.html +2 -2
  14. ttnn_visualizer/tests/test_serializers.py +6 -0
  15. ttnn_visualizer/utils.py +190 -28
  16. ttnn_visualizer/views.py +90 -31
  17. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/METADATA +2 -1
  18. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/RECORD +23 -23
  19. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/licenses/LICENSE +95 -50
  20. ttnn_visualizer/static/assets/allPathsLoader-KPOKJ-lr.js +0 -2
  21. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/WHEEL +0 -0
  22. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/entry_points.txt +0 -0
  23. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/licenses/LICENSE_understanding.txt +0 -0
  24. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/top_level.txt +0 -0
ttnn_visualizer/app.py CHANGED
@@ -25,6 +25,7 @@ from ttnn_visualizer.exceptions import (
25
25
  )
26
26
  from ttnn_visualizer.instances import create_instance_from_local_paths
27
27
  from ttnn_visualizer.settings import Config, DefaultConfig
28
+ from ttnn_visualizer.utils import create_path_resolver
28
29
  from werkzeug.debug import DebuggedApplication
29
30
  from werkzeug.middleware.proxy_fix import ProxyFix
30
31
 
@@ -78,6 +79,7 @@ def create_app(settings_override=None):
78
79
  js_config = {
79
80
  "SERVER_MODE": app.config["SERVER_MODE"],
80
81
  "BASE_PATH": app.config["BASE_PATH"],
82
+ "TT_METAL_HOME": app.config["TT_METAL_HOME"],
81
83
  }
82
84
  js = f"window.TTNN_VISUALIZER_CONFIG = {json.dumps(js_config)};"
83
85
 
@@ -192,6 +194,9 @@ def parse_args():
192
194
  parser.add_argument(
193
195
  "--performance-path", help="Specify a performance path", default=None
194
196
  )
197
+ parser.add_argument(
198
+ "--tt-metal-home", help="Specify a TT-Metal home path", default=None
199
+ )
195
200
  return parser.parse_args()
196
201
 
197
202
 
@@ -220,10 +225,40 @@ def main():
220
225
 
221
226
  instance_id = session.instance_id
222
227
 
228
+ if args.tt_metal_home:
229
+ config.TT_METAL_HOME = args.tt_metal_home
230
+
231
+ # Display mode information
232
+ app = create_app()
233
+ with app.app_context():
234
+ resolver = create_path_resolver(app)
235
+ mode_info = resolver.get_mode_info()
236
+
237
+ if mode_info["mode"] == "tt_metal":
238
+ print(
239
+ "🚀 TT-METAL MODE: Working directly with tt-metal generated directory"
240
+ )
241
+ print(f" TT_METAL_HOME: {mode_info['tt_metal_home']}")
242
+ print(f" Profiler reports: {mode_info['profiler_base']}")
243
+ print(f" Performance reports: {mode_info['performance_base']}")
244
+
245
+ # Validate setup
246
+ is_valid, message = resolver.validate_tt_metal_setup()
247
+ if is_valid:
248
+ print(f" ✓ {message}")
249
+ else:
250
+ print(f" ⚠️ Warning: {message}")
251
+ else:
252
+ print(
253
+ "📁 UPLOAD/SYNC MODE: Using local data directory for uploaded/synced reports"
254
+ )
255
+ print(f" Local directory: {mode_info['local_dir']}")
256
+ print(f" Remote directory: {mode_info['remote_dir']}")
257
+
223
258
  # Check if DEBUG environment variable is set
224
259
  debug_mode = os.environ.get("DEBUG", "false").lower() == "true"
225
260
  if config.PRINT_ENV:
226
- print("ENVIRONMENT:")
261
+ print("\nENVIRONMENT:")
227
262
  for key, value in config.to_dict().items():
228
263
  print(f"{key}={value}")
229
264
 
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
  #
3
- # SPDX-FileCopyrightText: © 2025 Tenstorrent Inc.
3
+ # SPDX-FileCopyrightText: © 2025 Tenstorrent AI ULC
4
+
4
5
  import csv
5
6
  import json
6
7
  import os
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
  #
3
- # SPDX-FileCopyrightText: © 2025 Tenstorrent Inc.
3
+ # SPDX-FileCopyrightText: © 2025 Tenstorrent AI ULC
4
4
 
5
5
  import logging
6
6
  import os
ttnn_visualizer/models.py CHANGED
@@ -78,6 +78,7 @@ class Buffer(SerializeableDataclass):
78
78
  address: int
79
79
  max_size_per_bank: int
80
80
  buffer_type: BufferType
81
+ buffer_layout: Optional[int] = None
81
82
 
82
83
 
83
84
  @dataclasses.dataclass
@@ -146,7 +146,7 @@ class DatabaseQueries:
146
146
  ) -> Generator[Buffer, None, None]:
147
147
  rows = self._query_table("buffers", filters)
148
148
  for row in rows:
149
- yield Buffer(*row)
149
+ yield Buffer(*row[:6])
150
150
 
151
151
  def query_stack_traces(
152
152
  self, filters: Optional[Dict[str, Any]] = None
@@ -42,6 +42,7 @@ class DefaultConfig(object):
42
42
  APPLICATION_DIR = os.path.abspath(os.path.join(__file__, "..", os.pardir))
43
43
  APP_DATA_DIRECTORY = os.getenv("APP_DATA_DIRECTORY", APPLICATION_DIR)
44
44
  STATIC_ASSETS_DIR = Path(APPLICATION_DIR).joinpath("ttnn_visualizer", "static")
45
+ TT_METAL_HOME = os.getenv("TT_METAL_HOME", None)
45
46
  SEND_FILE_MAX_AGE_DEFAULT = 0
46
47
 
47
48
  LAUNCH_BROWSER_ON_START = str_to_bool(os.getenv("LAUNCH_BROWSER_ON_START", "true"))
@@ -17,6 +17,7 @@ logger = getLogger(__name__)
17
17
 
18
18
  class Messages(object):
19
19
  FILE_TRANSFER_PROGRESS = "fileTransferProgress"
20
+ REPORT_GENERATED = "reportGenerated"
20
21
 
21
22
 
22
23
  class FileStatus(Enum):
@@ -27,6 +28,12 @@ class FileStatus(Enum):
27
28
  STARTED = "STARTED"
28
29
 
29
30
 
31
+ class ExitStatus(Enum):
32
+ PASS = "PASS"
33
+ FAIL = "FAIL"
34
+ ERROR = "ERROR"
35
+
36
+
30
37
  @dataclass
31
38
  class FileProgress(SerializeableDataclass):
32
39
  current_file_name: str
@@ -40,6 +47,16 @@ class FileProgress(SerializeableDataclass):
40
47
  self.percent_of_current = round(self.percent_of_current, 2)
41
48
 
42
49
 
50
+ @dataclass
51
+ class ReportGenerated(SerializeableDataclass):
52
+ report_name: str
53
+ profiler_path: str | None = None
54
+ performance_path: str | None = None
55
+ exit_status: ExitStatus | None = None
56
+ message_type: str = "report_generated"
57
+ timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat())
58
+
59
+
43
60
  # For tracking connected clients subscriber ID
44
61
  tab_clients = {}
45
62
 
@@ -77,6 +94,20 @@ def emit_file_status(progress: FileProgress, instance_id=None):
77
94
  debounce_timer.start()
78
95
 
79
96
 
97
+ def emit_report_generated(report_generated: ReportGenerated):
98
+ """Emit a report update notification to all connected clients."""
99
+ try:
100
+ if socketio is not None and hasattr(socketio, "emit"):
101
+ data = report_generated.to_dict()
102
+ socketio.emit(Messages.REPORT_GENERATED, data)
103
+ logger.info(
104
+ f"Report update notification sent: {report_generated.report_name}"
105
+ )
106
+ except NameError:
107
+ logger.warning("SocketIO not available - skipping report update notification")
108
+ pass # Can silently pass since we know the NameError is from sockets being disabled
109
+
110
+
80
111
  def register_handlers(socketio_instance):
81
112
  global socketio
82
113
  socketio = socketio_instance
@@ -1 +1 @@
1
- import{I as s}from"./index-03c8d4Gh.js";import{I as r}from"./index-PKNBViIU.js";import{p as n,I as c}from"./index-BANm1CMY.js";function p(t,a){const o=n(t);return a===c.STANDARD?s[o]:r[o]}export{s as IconSvgPaths16,r as IconSvgPaths20,p as getIconPaths};
1
+ import{I as s}from"./index-03c8d4Gh.js";import{I as r}from"./index-PKNBViIU.js";import{p as n,I as c}from"./index-T8PVeTUn.js";function p(t,a){const o=n(t);return a===c.STANDARD?s[o]:r[o]}export{s as IconSvgPaths16,r as IconSvgPaths20,p as getIconPaths};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/allPaths-DyhSRH--.js","assets/index-03c8d4Gh.js","assets/index-PKNBViIU.js","assets/index-T8PVeTUn.js","assets/index-CZ0Uonoz.css"])))=>i.map(i=>d[i]);
2
+ import{_ as e}from"./index-T8PVeTUn.js";const s=async(t,a)=>{const{getIconPaths:o}=await e(async()=>{const{getIconPaths:r}=await import("./allPaths-DyhSRH--.js");return{getIconPaths:r}},__vite__mapDeps([0,1,2,3,4]));return o(t,a)};export{s as allPathsLoader};