ttnn-visualizer 0.65.1__py3-none-any.whl → 0.67.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.
ttnn_visualizer/app.py CHANGED
@@ -9,10 +9,13 @@ import os
9
9
  import subprocess
10
10
  import sys
11
11
  import threading
12
+ import time
12
13
  import webbrowser
13
14
  from os import environ
14
15
  from pathlib import Path
15
16
  from typing import cast
17
+ from urllib.error import URLError
18
+ from urllib.request import urlopen
16
19
 
17
20
  import flask
18
21
  from dotenv import load_dotenv
@@ -172,14 +175,33 @@ def open_browser(host, port, instance_id=None):
172
175
  if instance_id:
173
176
  url = f"{url}?instanceId={instance_id}"
174
177
 
175
- print(f"Launching browser with url: {url}")
176
- try:
177
- if os.name == "posix" and "DISPLAY" in os.environ: # Checks for non-headless
178
- subprocess.run(["xdg-open", url], check=True)
179
- else:
180
- webbrowser.open(url)
181
- except webbrowser.Error as e:
182
- print(f"Could not open the default browser: {e}")
178
+ max_attempts = 10
179
+ attempt = 0
180
+ server_ready = False
181
+
182
+ print(f"Waiting for server to be ready at {url}...")
183
+ while attempt < max_attempts and not server_ready:
184
+ try:
185
+ urlopen(url, timeout=1)
186
+ server_ready = True
187
+ except (URLError, ConnectionError, OSError):
188
+ attempt += 1
189
+ time.sleep(0.5)
190
+
191
+ if not server_ready:
192
+ print(f"❌ Server not ready after {max_attempts} attempts.")
193
+ else:
194
+ print(f"Launching browser with url: {url}")
195
+
196
+ try:
197
+ if (
198
+ os.name == "posix" and "DISPLAY" in os.environ
199
+ ): # Checks for non-headless
200
+ subprocess.run(["xdg-open", url], check=True)
201
+ else:
202
+ webbrowser.open(url)
203
+ except webbrowser.Error as e:
204
+ print(f"Could not open the default browser: {e}")
183
205
 
184
206
 
185
207
  def parse_args():
@@ -382,7 +404,7 @@ def main():
382
404
  flask_env = os.getenv("FLASK_ENV", "development")
383
405
  port = config.PORT if flask_env == "production" else config.DEV_SERVER_PORT
384
406
  host = config.HOST if flask_env == "production" else config.DEV_SERVER_HOST
385
- threading.Timer(2, open_browser, [host, port, instance_id]).start()
407
+ threading.Thread(target=open_browser, args=[host, port, instance_id]).start()
386
408
  try:
387
409
  subprocess.run(gunicorn_args)
388
410
  except KeyboardInterrupt:
ttnn_visualizer/models.py CHANGED
@@ -113,6 +113,7 @@ class Tensor(SerializeableDataclass):
113
113
  address: int
114
114
  buffer_type: BufferType
115
115
  device_addresses: list[int]
116
+ size: Optional[int] = None
116
117
 
117
118
  def __post_init__(self):
118
119
  self.memory_config = parse_memory_config(self.memory_config)
@@ -185,26 +185,88 @@ class DatabaseQueries:
185
185
  def query_tensors(
186
186
  self, filters: Optional[Dict[str, Any]] = None
187
187
  ) -> Generator[Tensor, None, None]:
188
- rows = self._query_table("tensors", filters)
188
+ # Check if device_tensors table exists
189
+ device_tensors_exists = self._check_table_exists("device_tensors")
190
+
191
+ # Build the base query with joins to get size and optionally device_tensors
192
+ if device_tensors_exists:
193
+ query = """
194
+ SELECT
195
+ t.*,
196
+ b.max_size_per_bank as size,
197
+ GROUP_CONCAT(dt.device_id || ':' || dt.address, ',') as device_tensors_data
198
+ FROM tensors t
199
+ LEFT JOIN input_tensors it ON it.tensor_id = t.tensor_id
200
+ LEFT JOIN output_tensors ot ON ot.tensor_id = t.tensor_id
201
+ LEFT JOIN buffers b ON b.operation_id = COALESCE(it.operation_id, ot.operation_id)
202
+ AND t.address = b.address
203
+ AND t.device_id = b.device_id
204
+ LEFT JOIN device_tensors dt ON dt.tensor_id = t.tensor_id
205
+ WHERE 1=1
206
+ """
207
+ else:
208
+ query = """
209
+ SELECT
210
+ t.*,
211
+ b.max_size_per_bank as size,
212
+ NULL as device_tensors_data
213
+ FROM tensors t
214
+ LEFT JOIN input_tensors it ON it.tensor_id = t.tensor_id
215
+ LEFT JOIN output_tensors ot ON ot.tensor_id = t.tensor_id
216
+ LEFT JOIN buffers b ON b.operation_id = COALESCE(it.operation_id, ot.operation_id)
217
+ AND t.address = b.address
218
+ AND t.device_id = b.device_id
219
+ WHERE 1=1
220
+ """
221
+ params = []
222
+
223
+ # Apply filters to tensors table
224
+ if filters:
225
+ for column, value in filters.items():
226
+ if value is None:
227
+ continue
228
+
229
+ if isinstance(value, list):
230
+ if len(value) == 0:
231
+ continue
232
+ placeholders = ", ".join(["?"] * len(value))
233
+ query += f" AND t.{column} IN ({placeholders})"
234
+ params.extend(value)
235
+ else:
236
+ query += f" AND t.{column} = ?"
237
+ params.append(value)
238
+
239
+ query += " GROUP BY t.tensor_id"
240
+
241
+ rows = self.query_runner.execute_query(query, params)
189
242
  for row in rows:
243
+ # Extract size and device_tensors_data (last two columns) and tensor data
244
+ tensor_row = row[:-2] # All tensor columns
245
+ size = row[-2] # size column
246
+ device_tensors_data = row[-1] # device_tensors_data column
247
+
190
248
  device_addresses = []
191
249
 
192
- try:
193
- device_tensors = self._query_table(
194
- "device_tensors", filters={"tensor_id": row[0]}
195
- )
196
- except sqlite3.OperationalError as err:
197
- if str(err).startswith("no such table"):
198
- pass
199
- else:
200
- raise err
201
- else:
202
- for device_tensor in sorted(device_tensors, key=lambda x: x[1]):
203
- while len(device_addresses) < device_tensor[1]:
250
+ if device_tensors_data:
251
+ # Parse the concatenated device_id:address pairs
252
+ pairs = device_tensors_data.split(",")
253
+ device_tensor_list = []
254
+ for pair in pairs:
255
+ if pair:
256
+ device_id_str, address_str = pair.split(":")
257
+ device_id = int(device_id_str)
258
+ address = int(address_str)
259
+ device_tensor_list.append((device_id, address))
260
+
261
+ # Sort by device_id and build the list with proper indexing
262
+ for device_id, address in sorted(
263
+ device_tensor_list, key=lambda x: x[0]
264
+ ):
265
+ while len(device_addresses) < device_id:
204
266
  device_addresses.append(None)
205
- device_addresses.append(device_tensor[2])
267
+ device_addresses.append(address)
206
268
 
207
- yield Tensor(*row, device_addresses)
269
+ yield Tensor(*tensor_row, device_addresses, size=size)
208
270
 
209
271
  def query_input_tensors(
210
272
  self, filters: Optional[Dict[str, Any]] = None
@@ -1 +1 @@
1
- import{I as s}from"./index-voJy5fZe.js";import{I as r}from"./index-BZITDwoa.js";import{p as n,I as c}from"./index-DWdLC6fW.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-voJy5fZe.js";import{I as r}from"./index-BZITDwoa.js";import{p as n,I as c}from"./index-BO1FGYnE.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-DiBJY9fQ.js","assets/index-voJy5fZe.js","assets/index-BZITDwoa.js","assets/index-BO1FGYnE.js","assets/index-bdndbd_j.css"])))=>i.map(i=>d[i]);
2
+ import{_ as e}from"./index-BO1FGYnE.js";const s=async(t,a)=>{const{getIconPaths:o}=await e(async()=>{const{getIconPaths:r}=await import("./allPaths-DiBJY9fQ.js");return{getIconPaths:r}},__vite__mapDeps([0,1,2,3,4]));return o(t,a)};export{s as allPathsLoader};