Skip to content

Commit c365ffe

Browse files
authored
GUI updates (#272)
1 parent dddde55 commit c365ffe

3 files changed

Lines changed: 203 additions & 105 deletions

File tree

tools/socgen/NoCConfiguration.py

Lines changed: 173 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import customtkinter as ctk
77
from tkinter import *
88
import tkinter as tk
9+
import tkinter.font as tkfont
910
from tkinter.ttk import Separator
1011
from thirdparty import *
1112
import Pmw
@@ -244,9 +245,8 @@ class Tile():
244245

245246
def update_tile(self, soc):
246247
selection = self.ip_type.get()
247-
self.ip_list.forget()
248248
self.ip_list.configure(values=soc.list_of_ips)
249-
self.ip_list.pack(pady=10)
249+
250250
if soc.IPs.PROCESSORS.count(selection):
251251
self.frame.configure(fg_color="#ef6865")
252252
elif soc.IPs.MISC.count(selection):
@@ -258,26 +258,57 @@ def update_tile(self, soc):
258258
elif soc.IPs.ACCELERATORS.count(selection):
259259
self.frame.configure(fg_color="#78cbbb")
260260
self.point_label.configure(text_color="black")
261+
try:
262+
self.point_label.grid()
263+
self.impl_slot.grid()
264+
except Exception:
265+
pass
261266
self.vendor = soc.IPs.VENDOR[selection]
262267
dma_width = str(soc.noc.dma_noc_width.get())
263-
display_points = [
264-
point for point in soc.IPs.POINTS[selection] if "dma" +
265-
str(dma_width) in point]
268+
display_points = [p for p in soc.IPs.POINTS[selection] if "dma"+str(dma_width) in p]
269+
270+
if not self.point_select.winfo_manager():
271+
self.point_select.pack(fill="x") # hide label for non-accelerators
272+
266273
self.point_select.configure(values=display_points)
267-
point = self.point.get()
268-
self.point_select.set("")
269-
for p in display_points:
270-
if point == p:
271-
self.point_select.set(point)
272-
break
274+
if display_points:
275+
cur = self.point.get()
276+
if cur in display_points:
277+
self.point_select.set(cur)
273278
else:
274-
self.point_select.set(str(display_points[0]))
275-
self.point_select.configure(state="normal")
279+
self.point.set(display_points[0])
280+
self.point_select.set(display_points[0])
281+
self.point_select.configure(state="normal")
282+
else:
283+
self.point.set("")
284+
self.point_select.set("")
285+
self.point_select.configure(state="disabled")
276286
else:
277-
self.frame.configure(fg_color='white')
278-
if self.ip_type.get() != "empty":
279-
self.ip_type.set("empty")
280-
287+
self.frame.configure(fg_color="white")
288+
self.vendor = ""
289+
self.point.set("")
290+
self.point_select.configure(values=[], state="disabled")
291+
for fn in (getattr(self.point_select, "pack_forget", None),
292+
getattr(self.point_select, "grid_remove", None),
293+
getattr(self.point_select, "place_forget", None)):
294+
try:
295+
if callable(fn):
296+
fn()
297+
except Exception:
298+
pass
299+
try:
300+
if self.point_label.winfo_ismapped():
301+
self.point_label.grid_remove()
302+
if self.impl_slot.winfo_ismapped():
303+
self.impl_slot.grid_remove()
304+
except Exception:
305+
pass
306+
try:
307+
lbl = getattr(self.point_select, "_text_label", None)
308+
if lbl is not None:
309+
lbl.configure(text="")
310+
except Exception:
311+
pass
281312
try:
282313
if soc.IPs.ACCELERATORS.count(selection) and soc.cache_en.get(
283314
) == 1 and soc.noc.dma_noc_width.get() == soc.ARCH_BITS:
@@ -474,73 +505,140 @@ def changed(self, *args):
474505

475506
def update_frame(self):
476507
if self.noc.cols > 0 and self.noc.rows > 0:
508+
self.COLS.delete(0, END)
477509
self.COLS.insert(0, str(self.noc.cols))
510+
self.ROWS.delete(0, END)
478511
self.ROWS.insert(0, str(self.noc.rows))
479512
self.create_noc()
480513
self.changed()
481514

515+
def _tile_checkbox(self, parent, text, variable, cmd):
516+
return ctk.CTkCheckBox(
517+
parent,
518+
text=text,
519+
variable=variable,
520+
command=cmd,
521+
font=("Arial", 10), # previous font
522+
fg_color="green",
523+
border_color="grey",
524+
corner_radius=0,
525+
checkbox_width=18,
526+
checkbox_height=18,
527+
hover=False
528+
)
529+
530+
def _ellipsize(self, text, font_obj, max_px):
531+
if not text:
532+
return ""
533+
if font_obj.measure(text) <= max_px:
534+
return text
535+
ell = "…"
536+
# Binary-ish shrink until it fits
537+
lo, hi = 0, len(text)
538+
while lo < hi:
539+
mid = (lo + hi) // 2
540+
candidate = text[:mid] + ell
541+
if font_obj.measure(candidate) <= max_px:
542+
lo = mid + 1
543+
else:
544+
hi = mid
545+
mid = max(0, lo - 1)
546+
return (text[:mid] + ell) if mid < len(text) else text
547+
548+
def _bind_trunc(self, optionmenu, var, max_px):
549+
lbl = getattr(optionmenu, "_text_label", None)
550+
if lbl is None:
551+
return # fallback: do nothing if CTk internals change
552+
553+
f = tkfont.Font(font=lbl.cget("font"))
554+
555+
def apply(*_):
556+
full = var.get()
557+
lbl.configure(text=self._ellipsize(full, f, max_px))
558+
559+
apply()
560+
try:
561+
var.trace_add("write", apply)
562+
except Exception:
563+
var.trace("w", lambda *args: apply())
564+
565+
def _fixed_slot(self, parent, w, h=28):
566+
slot = ctk.CTkFrame(parent, width=w, height=h, fg_color="transparent")
567+
slot.pack_propagate(False)
568+
return slot
569+
482570
def create_tile(self, frame, tile):
483-
# computing the width of the widget
484-
list_items = self.soc.list_of_ips
485-
width = 0
486-
for x in range(0, len(list_items)):
487-
if len(list_items[x]) > width:
488-
width = len(list_items[x])
489571
tile.frame = frame
572+
BTN_W = 120 # same for both dropdowns
573+
PADDED_TEXT_MAX = BTN_W - 24 # room for padding & arrow;
574+
575+
# Content Wrapper
576+
OUTSET = 8 # thickness of the colored border
577+
R_OUT, R_IN = 10, 8 # outer/inner corner radii
578+
579+
# the inner card that guarantees straight edges
580+
content = ctk.CTkFrame(frame, fg_color="#e8e8e8", corner_radius=R_IN)
581+
content.pack(fill="both", expand=True, padx=OUTSET, pady=OUTSET)
490582

491-
# creating tile
492-
tile.type_frame = ctk.CTkFrame(frame, fg_color="#e8e8e8")
493-
tile.type_frame.pack(anchor="center", pady=(15, 0))
583+
content.grid_columnconfigure(0, weight=1, minsize=100) # text column grows
584+
content.grid_columnconfigure(1, weight=0, minsize=BTN_W) # dropdown column fixed
494585

495-
impl_frame = ctk.CTkFrame(frame, width=0, height=0, fg_color="#e8e8e8")
496-
impl_frame.pack(anchor="center")
586+
# header row
587+
header_lbl = ctk.CTkLabel(content, text="Tile", font=("Arial", 11))
588+
header_lbl.grid(row=0, column=0, sticky="w", padx=8, pady=(8, 4))
497589

498-
config_frame = ctk.CTkFrame(frame, fg_color="#e8e8e8")
499-
config_frame.pack(anchor="center", padx=15, pady=(0, 15))
590+
ip_slot = self._fixed_slot(content, BTN_W)
591+
ip_slot.grid(row=0, column=1, sticky="e", padx=8, pady=(8, 4))
500592

501-
tile_type_label = StyledComponents.LabelPack(
502-
tile.type_frame, text="Tile", font=(
503-
"Arial", 11), text_color="black")
504593
tile.ip_list = StyledComponents.OptionMenu(
505-
tile.type_frame,
594+
ip_slot,
506595
variable=tile.ip_type,
507-
values=list_items,
508-
command=self.changed)
509-
tile.ip_list.pack(side="right", padx=20, pady=10)
510-
511-
tile.point_label = StyledComponents.LabelPack(
512-
impl_frame, text="Impl.", font=(
513-
"Arial", 10), text_color="grey", side="left", padx=(
514-
12, 0), pady=10)
596+
values=self.soc.list_of_ips,
597+
width=BTN_W, # fixed so the card width never changes
598+
anchor="w",
599+
command=self.changed,
600+
)
601+
tile.ip_list.pack(fill="x") # inside fixed slot
602+
self._bind_trunc(tile.ip_list, tile.ip_type, PADDED_TEXT_MAX)
603+
604+
# ---- implementation row -------------------------------------------------
605+
tile.point_label = ctk.CTkLabel(
606+
content, text="Impl.", font=("Arial", 10), text_color="grey"
607+
)
608+
tile.point_label.grid(row=1, column=0, sticky="w", padx=8, pady=4)
609+
610+
impl_slot = self._fixed_slot(content, BTN_W)
611+
impl_slot.grid(row=1, column=1, sticky="e", padx=8, pady=4)
612+
613+
tile.impl_slot = impl_slot
515614
tile.point_select = StyledComponents.OptionMenu(
516-
impl_frame,
615+
impl_slot,
517616
variable=tile.point,
518617
values=[],
618+
width=BTN_W, # same fixed width as header dropdown
519619
state="disabled",
520-
command=self.changed)
521-
tile.point_select.pack(side="right", padx=(18, 1), pady=10)
522-
523-
tile.has_l2_selection = StyledComponents.CheckBox(
524-
config_frame,
525-
variable=tile.has_l2,
526-
text="Cache",
527-
row=0,
528-
column=0,
529-
command=self.changed)
530-
tile.has_ddr_selection = StyledComponents.CheckBox(
531-
config_frame,
532-
variable=tile.has_ddr,
533-
text="DDR",
534-
row=0,
535-
column=1,
536-
command=self.changed)
537-
tile.has_tdvfs_selection = StyledComponents.CheckBox(
538-
config_frame,
539-
variable=tile.has_tdvfs,
540-
text="DVFS",
541-
row=1,
542-
column=0,
543-
command=self.changed)
620+
anchor="w",
621+
command=self.changed,
622+
)
623+
#tile.point_select.pack(fill="x")
624+
#tile.point_select.grid(row=1, column=1, sticky="e", padx=8, pady=4)
625+
tile.point_label.grid_remove()
626+
tile.impl_slot.grid_remove()
627+
self._bind_trunc(tile.point_select, tile.point, PADDED_TEXT_MAX)
628+
629+
# ---- config row (checkboxes) -------------------------------------------
630+
cfg = ctk.CTkFrame(content, fg_color="transparent")
631+
cfg.grid(row=2, column=0, columnspan=2, sticky="ew", padx=8, pady=(6, 8))
632+
633+
# two columns inside for neat alignment
634+
cfg.grid_columnconfigure(0, weight=1, uniform="cfg")
635+
cfg.grid_columnconfigure(1, weight=1, uniform="cfg")
636+
tile.cb_cache = self._tile_checkbox(cfg, "Cache", tile.has_l2, self.changed)
637+
tile.cb_cache.grid(row=0, column=0, sticky="w", padx=(0, 16), pady=(4, 4))
638+
tile.cb_ddr = self._tile_checkbox(cfg, "DDR", tile.has_ddr, self.changed)
639+
tile.cb_ddr.grid(row=0, column=1, sticky="w", padx=(0, 0), pady=(4, 4))
640+
tile.cb_dvfs = self._tile_checkbox(cfg, "DVFS", tile.has_tdvfs, self.changed)
641+
tile.cb_dvfs.grid(row=1, column=0, sticky="w", padx=(0, 16), pady=(4, 8))
544642

545643
def __init__(self, soc, left_panel, right_panel):
546644
self.soc = soc
@@ -560,15 +658,15 @@ def __init__(self, soc, left_panel, right_panel):
560658
"Arial", 10), row=1, column=0, padx=20, pady=20, sticky="e")
561659
self.noc_rows = StyledComponents.Entry(self.noc_select_frame)
562660
self.ROWS = self.noc_rows
563-
self.noc_rows.insert(0, "2")
661+
self.noc_rows.insert(0, str(self.noc.rows or 2)) # use saved, fallback to 2
564662
self.noc_rows.grid(row=1, column=1, padx=5, pady=20)
565663

566664
self.noc_columns_label = StyledComponents.LabelGrid(
567665
self.noc_select_frame, text="Columns:", font=(
568666
"Arial", 10), row=1, column=2, padx=20, pady=20, sticky="e")
569667
self.noc_columns = StyledComponents.Entry(self.noc_select_frame)
570668
self.COLS = self.noc_columns
571-
self.noc_columns.insert(0, "2")
669+
self.noc_columns.insert(0, str(self.noc.cols or 2)) # use saved, fallback to 2
572670
self.noc_columns.grid(row=1, column=3, padx=5, pady=20)
573671

574672
self.update_noc_button = StyledComponents.Button(
@@ -973,7 +1071,6 @@ def set_message(self, message, soc_config_frame, gen_soc_config):
9731071
self.gen_soc_config = gen_soc_config
9741072

9751073
def create_noc(self):
976-
# self.pack(side=LEFT,fill=BOTH,expand=YES)
9771074
if isInt(self.ROWS.get()) == False or isInt(self.COLS.get()) == False:
9781075
return
9791076
# destroy current topology
@@ -987,23 +1084,24 @@ def create_noc(self):
9871084
self.right_panel, int(
9881085
self.ROWS.get()), int(
9891086
self.COLS.get()))
1087+
TILE_W, TILE_H = 280, 170
9901088
for y in range(0, int(self.ROWS.get())):
9911089
self.row_frames.append(ctk.CTkFrame(self.right_panel))
9921090
self.row_frames[y].pack(side=TOP)
9931091
self.noc_tiles.append([])
9941092
for x in range(0, int(self.COLS.get())):
995-
self.noc_tiles[y].append(ctk.CTkFrame(self.row_frames[y]))
996-
self.noc_tiles[y][x].pack(side=LEFT)
997-
# Label(self.noc_tiles[y][x], text="("+str(y)+","+str(x)+")").pack()
998-
self.create_tile(self.noc_tiles[y][x], self.noc.topology[y][x])
1093+
f = ctk.CTkFrame(self.row_frames[y], width=TILE_W, height=TILE_H, corner_radius=10)
1094+
f.pack(side=LEFT, padx=10, pady=10)
1095+
f.pack_propagate(False) # freeze outer size so the inner card can’t warp it
1096+
self.noc_tiles[y].append(f)
1097+
self.create_tile(f, self.noc.topology[y][x])
9991098
if len(self.noc.topology[y][x].ip_type.get()) == 0:
10001099
self.noc.topology[y][x].ip_type.set(
10011100
"empty") # default value
10021101
# set call-backs and default value
10031102
for y in range(0, int(self.ROWS.get())):
10041103
for x in range(0, int(self.COLS.get())):
10051104
tile = self.noc.topology[y][x]
1006-
# tile.ip_type.trace('w', self.changed)
10071105
self.soc.IPs = Components(
10081106
self.soc.TECH,
10091107
self.noc.dma_noc_width.get(),

0 commit comments

Comments
 (0)