66import customtkinter as ctk
77from tkinter import *
88import tkinter as tk
9+ import tkinter .font as tkfont
910from tkinter .ttk import Separator
1011from thirdparty import *
1112import 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