| #!/usr/bin/env python3 | |
| # | |
| #----------------------------------------------------------- | |
| # Simulation hints management for the | |
| # characterization tool | |
| #----------------------------------------------------------- | |
| # Written by Tim Edwards | |
| # efabless, inc. | |
| # March 21, 2017 | |
| # Version 0.1 | |
| #-------------------------------------------------------- | |
| import re | |
| import tkinter | |
| from tkinter import ttk | |
| class SimHints(tkinter.Toplevel): | |
| """Characterization tool simulation hints management.""" | |
| def __init__(self, parent=None, fontsize = 11, *args, **kwargs): | |
| '''See the __init__ for Tkinter.Toplevel.''' | |
| tkinter.Toplevel.__init__(self, parent, *args, **kwargs) | |
| s = ttk.Style() | |
| s.configure('normal.TButton', font=('Helvetica', fontsize), border = 3, relief = 'raised') | |
| self.protocol("WM_DELETE_WINDOW", self.close) | |
| self.parent = parent | |
| self.withdraw() | |
| self.title('Simulation hints management') | |
| self.sframe = tkinter.Frame(self) | |
| self.sframe.grid(column = 0, row = 0, sticky = "news") | |
| self.sframe.stitle = ttk.Label(self.sframe, | |
| style='title.TLabel', text = 'Hints') | |
| self.sframe.stitle.pack(side = 'top', fill = 'x', expand = 'true') | |
| self.sframe.sbar = ttk.Separator(self.sframe, orient='horizontal') | |
| self.sframe.sbar.pack(side = 'top', fill = 'x', expand = 'true') | |
| self.sframe.curparam = ttk.Label(self.sframe, | |
| style='title.TLabel', text = 'None') | |
| self.sframe.curparam.pack(side = 'top', fill = 'x', expand = 'true') | |
| self.sframe.sbar2 = ttk.Separator(self.sframe, orient='horizontal') | |
| self.sframe.sbar2.pack(side = 'top', fill = 'x', expand = 'true') | |
| # Keep current parameter | |
| self.param = None | |
| #-------------------------------------------------------- | |
| # reltol option | |
| #-------------------------------------------------------- | |
| self.sframe.do_reltol = tkinter.Frame(self.sframe) | |
| self.sframe.do_reltol.pack(side = 'top', anchor = 'w', fill = 'x', expand = 'true') | |
| self.do_reltol = tkinter.IntVar(self.sframe) | |
| self.do_reltol.set(0) | |
| self.sframe.do_reltol.enable = ttk.Checkbutton(self.sframe.do_reltol, | |
| text='Set reltol', variable = self.do_reltol, | |
| command=self.apply_reltol) | |
| self.sframe.do_reltol.value = ttk.Entry(self.sframe.do_reltol) | |
| self.sframe.do_reltol.value.delete(0, 'end') | |
| self.sframe.do_reltol.value.insert(0, '1.0E-3') | |
| # Return or leave window applies hint, if enabled | |
| self.sframe.do_reltol.value.bind('<Return>', self.apply_reltol) | |
| self.sframe.do_reltol.value.bind('<Leave>', self.apply_reltol) | |
| self.sframe.do_reltol.enable.pack(side = 'left', anchor = 'w') | |
| self.sframe.do_reltol.value.pack(side = 'left', anchor = 'w', fill='x', expand='true') | |
| #-------------------------------------------------------- | |
| # rshunt option | |
| #-------------------------------------------------------- | |
| self.sframe.do_rshunt = tkinter.Frame(self.sframe) | |
| self.sframe.do_rshunt.pack(side = 'top', anchor = 'w', fill = 'x', expand = 'true') | |
| self.do_rshunt = tkinter.IntVar(self.sframe) | |
| self.do_rshunt.set(0) | |
| self.sframe.do_rshunt.enable = ttk.Checkbutton(self.sframe.do_rshunt, | |
| text='Use shunt resistance', variable = self.do_rshunt, | |
| command=self.apply_rshunt) | |
| self.sframe.do_rshunt.value = ttk.Entry(self.sframe.do_rshunt) | |
| self.sframe.do_rshunt.value.delete(0, 'end') | |
| self.sframe.do_rshunt.value.insert(0, '1.0E20') | |
| # Return or leave window applies hint, if enabled | |
| self.sframe.do_rshunt.value.bind('<Return>', self.apply_rshunt) | |
| self.sframe.do_rshunt.value.bind('<Leave>', self.apply_rshunt) | |
| self.sframe.do_rshunt.enable.pack(side = 'left', anchor = 'w') | |
| self.sframe.do_rshunt.value.pack(side = 'left', anchor = 'w', fill='x', expand='true') | |
| #-------------------------------------------------------- | |
| # nodeset option | |
| #-------------------------------------------------------- | |
| self.sframe.do_nodeset = tkinter.Frame(self.sframe) | |
| self.sframe.do_nodeset.pack(side = 'top', anchor = 'w', fill = 'x', expand = 'true') | |
| self.do_nodeset = tkinter.IntVar(self.sframe) | |
| self.do_nodeset.set(0) | |
| self.sframe.do_nodeset.enable = ttk.Checkbutton(self.sframe.do_nodeset, | |
| text='Use nodeset', variable = self.do_nodeset, | |
| command=self.apply_nodeset) | |
| self.sframe.do_nodeset.value = ttk.Entry(self.sframe.do_nodeset) | |
| self.sframe.do_nodeset.value.delete(0, 'end') | |
| # Return or leave window applies hint, if enabled | |
| self.sframe.do_nodeset.value.bind('<Return>', self.apply_nodeset) | |
| self.sframe.do_nodeset.value.bind('<Leave>', self.apply_nodeset) | |
| self.sframe.do_nodeset.enable.pack(side = 'left', anchor = 'w') | |
| self.sframe.do_nodeset.value.pack(side = 'left', anchor = 'w', fill='x', expand='true') | |
| #-------------------------------------------------------- | |
| # itl1 option | |
| #-------------------------------------------------------- | |
| self.sframe.do_itl1 = tkinter.Frame(self.sframe) | |
| self.sframe.do_itl1.pack(side = 'top', anchor = 'w', fill = 'x', expand = 'true') | |
| self.do_itl1 = tkinter.IntVar(self.sframe) | |
| self.do_itl1.set(0) | |
| self.sframe.do_itl1.enable = ttk.Checkbutton(self.sframe.do_itl1, | |
| text='Set gmin iterations', variable = self.do_itl1, | |
| command=self.apply_itl1) | |
| self.sframe.do_itl1.value = ttk.Entry(self.sframe.do_itl1) | |
| self.sframe.do_itl1.value.delete(0, 'end') | |
| self.sframe.do_itl1.value.insert(0, '100') | |
| # Return or leave window applies hint, if enabled | |
| self.sframe.do_itl1.value.bind('<Return>', self.apply_itl1) | |
| self.sframe.do_itl1.value.bind('<Leave>', self.apply_itl1) | |
| self.sframe.do_itl1.enable.pack(side = 'left', anchor = 'w') | |
| self.sframe.do_itl1.value.pack(side = 'left', anchor = 'w', fill='x', expand='true') | |
| #-------------------------------------------------------- | |
| # include option | |
| # Disabled for now. This needs to limit the selection of | |
| # files to include to a drop-down selection list. | |
| #-------------------------------------------------------- | |
| self.sframe.do_include = tkinter.Frame(self.sframe) | |
| # self.sframe.do_include.pack(side = 'top', anchor = 'w', fill = 'x', expand = 'true') | |
| self.do_include = tkinter.IntVar(self.sframe) | |
| self.do_include.set(0) | |
| self.sframe.do_include.enable = ttk.Checkbutton(self.sframe.do_include, | |
| text='Include netlist', variable = self.do_include, | |
| command=self.apply_include) | |
| self.sframe.do_include.value = ttk.Entry(self.sframe.do_include) | |
| self.sframe.do_include.value.delete(0, 'end') | |
| # Return or leave window applies hint, if enabled | |
| self.sframe.do_include.value.bind('<Return>', self.apply_include) | |
| self.sframe.do_include.value.bind('<Leave>', self.apply_include) | |
| self.sframe.do_include.enable.pack(side = 'left', anchor = 'w') | |
| self.sframe.do_include.value.pack(side = 'left', anchor = 'w', fill='x', expand='true') | |
| #-------------------------------------------------------- | |
| # alternative method option | |
| #-------------------------------------------------------- | |
| self.sframe.do_method = tkinter.Frame(self.sframe) | |
| self.sframe.do_method.pack(side = 'top', anchor = 'w', fill = 'x', expand = 'true') | |
| self.do_method = tkinter.IntVar(self.sframe) | |
| self.do_method.set(0) | |
| self.sframe.do_method.enable = ttk.Checkbutton(self.sframe.do_method, | |
| text='Use alternate method', variable = self.do_method, | |
| command=self.apply_method) | |
| self.sframe.do_method.value = ttk.Entry(self.sframe.do_method) | |
| self.sframe.do_method.value.delete(0, 'end') | |
| self.sframe.do_method.value.insert(0, '0') | |
| # Return or leave window applies hint, if enabled | |
| self.sframe.do_method.value.bind('<Return>', self.apply_method) | |
| self.sframe.do_method.value.bind('<Leave>', self.apply_method) | |
| self.sframe.do_method.enable.pack(side = 'left', anchor = 'w') | |
| self.sframe.do_method.value.pack(side = 'left', anchor = 'w', fill='x', expand='true') | |
| #-------------------------------------------------------- | |
| self.bbar = ttk.Frame(self) | |
| self.bbar.grid(column = 0, row = 1, sticky = "news") | |
| self.bbar.apply_button = ttk.Button(self.bbar, text='Apply', | |
| command=self.apply_hints, style = 'normal.TButton') | |
| self.bbar.apply_button.grid(column=0, row=0, padx = 5) | |
| self.bbar.close_button = ttk.Button(self.bbar, text='Close', | |
| command=self.close, style = 'normal.TButton') | |
| self.bbar.close_button.grid(column=1, row=0, padx = 5) | |
| def apply_reltol(self, value = ''): | |
| # "value" is passed from binding callback but is not used | |
| have_reltol = self.do_reltol.get() | |
| if have_reltol: | |
| if not 'hints' in self.param: | |
| phints = {} | |
| else: | |
| phints = self.param['hints'] | |
| phints['reltol'] = self.sframe.do_reltol.value.get() | |
| self.param['hints'] = phints | |
| else: | |
| if 'hints' in self.param: | |
| self.param['hints'].pop('reltol', None) | |
| def apply_rshunt(self, value = ''): | |
| # "value" is passed from binding callback but is not used | |
| have_rshunt = self.do_rshunt.get() | |
| if have_rshunt: | |
| if not 'hints' in self.param: | |
| phints = {} | |
| else: | |
| phints = self.param['hints'] | |
| phints['rshunt'] = self.sframe.do_rshunt.value.get() | |
| self.param['hints'] = phints | |
| else: | |
| if 'hints' in self.param: | |
| self.param['hints'].pop('rshunt', None) | |
| def apply_itl1(self, value = ''): | |
| # "value" is passed from binding callback but is not used | |
| have_itl1 = self.do_itl1.get() | |
| if have_itl1: | |
| if not 'hints' in self.param: | |
| phints = {} | |
| else: | |
| phints = self.param['hints'] | |
| phints['itl1'] = self.sframe.do_itl1.value.get() | |
| self.param['hints'] = phints | |
| else: | |
| if 'hints' in self.param: | |
| self.param['hints'].pop('itl1', None) | |
| def apply_nodeset(self, value = ''): | |
| # "value" is passed from binding callback but is not used | |
| have_nodeset = self.do_nodeset.get() | |
| if have_nodeset: | |
| if not 'hints' in self.param: | |
| phints = {} | |
| else: | |
| phints = self.param['hints'] | |
| phints['nodeset'] = self.sframe.do_nodeset.value.get() | |
| self.param['hints'] = phints | |
| else: | |
| if 'hints' in self.param: | |
| self.param['hints'].pop('nodeset', None) | |
| def apply_include(self, value = ''): | |
| # "value" is passed from binding callback but is not used | |
| have_include = self.do_include.get() | |
| if have_include: | |
| if not 'hints' in self.param: | |
| phints = {} | |
| else: | |
| phints = self.param['hints'] | |
| phints['include'] = self.sframe.do_include.value.get() | |
| self.param['hints'] = phints | |
| else: | |
| if 'hints' in self.param: | |
| self.param['hints'].pop('include', None) | |
| def apply_method(self, value = ''): | |
| # "value" is passed from binding callback but is not used | |
| have_method = self.do_method.get() | |
| if have_method: | |
| if not 'hints' in self.param: | |
| phints = {} | |
| else: | |
| phints = self.param['hints'] | |
| phints['method'] = self.sframe.do_method.value.get() | |
| self.param['hints'] = phints | |
| else: | |
| if 'hints' in self.param: | |
| self.param['hints'].pop('method', None) | |
| def apply_hints(self, value = ''): | |
| self.apply_reltol(value) | |
| self.apply_rshunt(value) | |
| self.apply_itl1(value) | |
| self.apply_nodeset(value) | |
| self.apply_include(value) | |
| self.apply_method(value) | |
| # Update 'Simulate' button in characterization tool with a mark | |
| # indicating hints are present. Also remove the hints record | |
| # from the parameter dictionary if it is empty. | |
| if 'method' in self.param: | |
| if 'hints' in self.param: | |
| if self.param['hints'] == {}: | |
| self.param.pop('hints', None) | |
| simtext = 'Simulate' | |
| else: | |
| simtext = '\u2022Simulate' | |
| else: | |
| simtext = 'Simulate' | |
| self.simbutton.config(text=simtext) | |
| def grid_configure(self, padx, pady): | |
| pass | |
| def redisplay(self): | |
| pass | |
| def populate(self, param, simbutton = False): | |
| if 'display' in param: | |
| self.sframe.curparam.config(text=param['display']) | |
| else: | |
| self.sframe.curparam.config(text=param['method']) | |
| # Set the current parameter | |
| self.param = param | |
| # Remember the simulate button so we can mark or unmark hints | |
| self.simbutton = simbutton | |
| # Regenerate view and update for the indicated param. | |
| if 'hints' in param: | |
| phints = param['hints'] | |
| if 'reltol' in phints: | |
| # (1) Reltol adjustment | |
| self.do_reltol.set(1) | |
| self.sframe.do_reltol.value.delete(0, 'end') | |
| self.sframe.do_reltol.value.insert(0, phints['reltol']) | |
| else: | |
| self.do_reltol.set(0) | |
| if 'rshunt' in phints: | |
| # (2) Gshunt option | |
| self.do_rshunt.set(1) | |
| self.sframe.do_rshunt.value.delete(0, 'end') | |
| self.sframe.do_rshunt.value.insert(0, phints['rshunt']) | |
| else: | |
| self.do_rshunt.set(0) | |
| if 'nodeset' in phints: | |
| # (3) Nodeset | |
| self.do_nodeset.set(1) | |
| self.sframe.do_nodeset.value.delete(0, 'end') | |
| self.sframe.do_nodeset.value.insert(0, phints['nodeset']) | |
| else: | |
| self.do_nodeset.set(0) | |
| if 'itl1' in phints: | |
| # (4) Gmin iterations (ITL1) | |
| self.do_itl1.set(1) | |
| self.sframe.do_itl1.value.delete(0, 'end') | |
| self.sframe.do_itl1.value.insert(0, phints['itl1']) | |
| else: | |
| self.do_itl1.set(0) | |
| if 'include' in phints: | |
| # (5) Include library (from dropdown list) | |
| self.do_include.set(1) | |
| self.sframe.do_include.value.delete(0, 'end') | |
| self.sframe.do_include.value.insert(0, phints['include']) | |
| else: | |
| self.do_include.set(0) | |
| if 'method' in phints: | |
| # (6) Alternative method (where indicated) | |
| self.do_method.set(1) | |
| self.sframe.do_method.value.delete(0, 'end') | |
| self.sframe.do_method.value.insert(0, phints['method']) | |
| else: | |
| self.do_method.set(0) | |
| else: | |
| # No hints, so set everything to unchecked | |
| self.do_reltol.set(0) | |
| self.do_rshunt.set(0) | |
| self.do_nodeset.set(0) | |
| self.do_itl1.set(0) | |
| self.do_include.set(0) | |
| self.do_method.set(0) | |
| def close(self): | |
| # pop down settings window | |
| self.withdraw() | |
| def open(self): | |
| # pop up settings window | |
| self.deiconify() | |
| self.lift() |