Source code for pybert.pybert_view

"""
Default view definition for PyBERT class.

Original author: David Banas <capn.freako@gmail.com>

Original date:   August 24, 2014 (Copied from pybert.py, as part of a major code cleanup.)

Copyright (c) 2014 David Banas; all rights reserved World wide.
"""
import pickle
from threading import Thread

from enable.component_editor import ComponentEditor
from pyface.api import OK, FileDialog
from pyface.image_resource import ImageResource
from traits.api import (Instance, HasTraits)
from traitsui.api import (
    Action,
    CheckListEditor,
    FileEditor,
    Group,
    Handler,
    HGroup,
    Item,
    ObjectColumn,
    TableEditor,
    TextEditor,
    VGroup,
    View,
    Label,
    EnumEditor,
    spring,
)
from pybert.pybert_cfg import PyBertCfg
from pybert.pybert_cntrl import my_run_sweeps
from pybert.pybert_data import PyBertData


[docs]class RunSimThread(Thread): """Used to run the simulation in its own thread, in order to preserve GUI responsiveness."""
[docs] def run(self): """Run the simulation(s).""" my_run_sweeps(self.the_pybert)
[docs]class MyHandler(Handler): """This handler is instantiated by the View and handles user button clicks.""" run_sim_thread = Instance(RunSimThread)
[docs] def do_run_simulation(self, info): """Spawn a simulation thread and run with the current settings.""" the_pybert = info.object if self.run_sim_thread and self.run_sim_thread.isAlive(): pass else: self.run_sim_thread = RunSimThread() self.run_sim_thread.the_pybert = the_pybert self.run_sim_thread.start()
[docs] def do_stop_simulation(self): """Kill the simulation thread.""" if self.run_sim_thread and self.run_sim_thread.isAlive(): self.run_sim_thread.stop()
[docs] def do_save_cfg(self, info): """Pickle out the current configuration.""" the_pybert = info.object dlg = FileDialog(action="save as", wildcard="*.pybert_cfg", default_path=the_pybert.cfg_file) if dlg.open() == OK: the_PyBertCfg = PyBertCfg(the_pybert) try: with open(dlg.path, "wb") as the_file: pickle.dump(the_PyBertCfg, the_file) the_pybert.cfg_file = dlg.path except Exception as err: error_message = "The following error occured:\n\t{}\nThe configuration was NOT saved.".format(err) the_pybert.handle_error(error_message)
[docs] def do_load_cfg(self, info): """Read in the pickled configuration.""" the_pybert = info.object dlg = FileDialog(action="open", wildcard="*.pybert_cfg", default_path=the_pybert.cfg_file) if dlg.open() == OK: try: with open(dlg.path, "rb") as the_file: the_PyBertCfg = pickle.load(the_file) if not isinstance(the_PyBertCfg, PyBertCfg): raise Exception("The data structure read in is NOT of type: PyBertCfg!") for prop, value in vars(the_PyBertCfg).items(): if prop == "tx_taps": for count, (enabled, val) in enumerate(value): setattr(the_pybert.tx_taps[count], "enabled", enabled) setattr(the_pybert.tx_taps[count], "value", val) elif prop == "tx_tap_tuners": for count, (enabled, val) in enumerate(value): setattr(the_pybert.tx_tap_tuners[count], "enabled", enabled) setattr(the_pybert.tx_tap_tuners[count], "value", val) else: setattr(the_pybert, prop, value) the_pybert.cfg_file = dlg.path except Exception as err: error_message = "The following error occurred:\n\t{}\nThe configuration was NOT loaded.".format(err) the_pybert.handle_error(error_message)
[docs] def do_save_data(self, info): """Pickle out all the generated data.""" the_pybert = info.object dlg = FileDialog(action="save as", wildcard="*.pybert_data", default_path=the_pybert.data_file) if dlg.open() == OK: try: plotdata = PyBertData(the_pybert) with open(dlg.path, "wb") as the_file: pickle.dump(plotdata, the_file) the_pybert.data_file = dlg.path except Exception as err: error_message = "The following error occurred:\n\t{}\nThe waveform data was NOT saved.".format(err) the_pybert.handle_error(error_message)
[docs] def do_load_data(self, info): """Read in the pickled data.'""" the_pybert = info.object dlg = FileDialog(action="open", wildcard="*.pybert_data", default_path=the_pybert.data_file) if dlg.open() == OK: try: with open(dlg.path, "rb") as the_file: the_plotdata = pickle.load(the_file) if not isinstance(the_plotdata, PyBertData): raise Exception("The data structure read in is NOT of type: ArrayPlotData!") for prop, value in the_plotdata.the_data.arrays.items(): the_pybert.plotdata.set_data(prop + "_ref", value) the_pybert.data_file = dlg.path # Add reference plots, if necessary. # - time domain for (container, suffix, has_both) in [ (the_pybert.plots_h.component_grid.flat, "h", False), (the_pybert.plots_s.component_grid.flat, "s", True), (the_pybert.plots_p.component_grid.flat, "p", False), ]: if "Reference" not in container[0].plots: (ix, prefix) = (0, "chnl") item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkcyan", name="Inc_ref") for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_out_" + suffix + "_ref" container[ix].plot( ("t_ns_chnl", item_name), type="line", color="darkmagenta", name="Cum_ref" ) if has_both: for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_" + suffix + "_ref" container[ix].plot( ("t_ns_chnl", item_name), type="line", color="darkcyan", name="Inc_ref" ) # - frequency domain for (container, suffix, has_both) in [(the_pybert.plots_H.component_grid.flat, "H", True)]: if "Reference" not in container[0].plots: (ix, prefix) = (0, "chnl") item_name = prefix + "_" + suffix + "_ref" container[ix].plot( ("f_GHz", item_name), type="line", color="darkcyan", name="Inc_ref", index_scale="log" ) for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_out_" + suffix + "_ref" container[ix].plot( ("f_GHz", item_name), type="line", color="darkmagenta", name="Cum_ref", index_scale="log", ) if has_both: for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_" + suffix + "_ref" container[ix].plot( ("f_GHz", item_name), type="line", color="darkcyan", name="Inc_ref", index_scale="log", ) except Exception as err: print(item_name) error_message = "The following error occured:\n\t{}\nThe waveform data was NOT loaded.".format(err) the_pybert.handle_error(error_message)
# These are the "globally applicable" buttons referred to in pybert.py, # just above the button definitions (approx. line 580). run_sim = Action(name="Run", action="do_run_simulation") stop_sim = Action(name="Stop", action="do_stop_simulation") save_data = Action(name="Save Results", action="do_save_data") load_data = Action(name="Load Results", action="do_load_data") save_cfg = Action(name="Save Config.", action="do_save_cfg") load_cfg = Action(name="Load Config.", action="do_load_cfg") # Main window layout definition. traits_view = View( Group( VGroup( HGroup( VGroup( HGroup( # Simulation Control VGroup( Item( name="bit_rate", label="Bit Rate (Gbps)", tooltip="bit rate", show_label=True, enabled_when="True", editor=TextEditor(auto_set=False, enter_set=True, evaluate=float), ), Item( name="nbits", label="Nbits", tooltip="# of bits to run", editor=TextEditor(auto_set=False, enter_set=True, evaluate=int), ), Item( name="nspb", label="Nspb", tooltip="# of samples per bit", editor=TextEditor(auto_set=False, enter_set=True, evaluate=int), ), Item( name="mod_type", label="Modulation", tooltip="line signalling/modulation scheme", editor=CheckListEditor(values=[(0, "NRZ"), (1, "Duo-binary"), (2, "PAM-4")]), ), ), VGroup( Item(name="do_sweep", label="Do Sweep", tooltip="Run parameter sweeps."), Item( name="sweep_aves", label="SweepAves", tooltip="# of trials, per sweep, for averaging.", enabled_when="do_sweep == True", ), Item( name="pattern_len", label="PatLen", tooltip="length of random pattern to use to construct bit stream", editor=TextEditor(auto_set=False, enter_set=True, evaluate=int), ), Item( name="eye_bits", label="EyeBits", tooltip="# of bits to use to form eye diagrams", editor=TextEditor(auto_set=False, enter_set=True, evaluate=int), ), ), VGroup( Item(name="vod", label="Vod (V)", tooltip="Tx output voltage into matched load"), Item(name="rn", label="Rn (V)", tooltip="standard deviation of random noise"), Item(name="pn_mag", label="Pn (V)", tooltip="peak magnitude of periodic noise"), Item(name="pn_freq", label="f(Pn) (MHz)", tooltip="frequency of periodic noise"), ), ), label="Simulation Control", show_border=True, ), VGroup( Item( name="thresh", label="Pj Threshold (sigma)", tooltip="Threshold for identifying periodic jitter spectral elements. (sigma)", ), Item( name="impulse_length", label="Impulse Response Length (ns)", tooltip="Manual impulse response length override", ), Item(name="debug", label="Debug", tooltip="Enable to log extra information to console."), label="Analysis Parameters", show_border=True, ), ), HGroup( VGroup( VGroup( HGroup( Item( name="tx_ibis_file", label="File", springy=True, editor=FileEditor(dialog_style="open", filter=["*.ibs"]), ), Item(name="tx_ibis_valid", label="Valid", style="simple", enabled_when="False"), ), HGroup( Item(name="tx_use_ibis", label="Use IBIS"), Item(name="btn_sel_tx", show_label=False), Item(name="btn_view_tx", show_label=False), enabled_when="tx_ibis_valid == True", ), label="IBIS", show_border=True, ), VGroup( Item( name="rs", label="Tx_Rs (Ohms)", tooltip="Tx differential source impedance", ), Item( name="cout", label="Tx_Cout (pF)", tooltip="Tx parasitic output capacitance (each pin)", ), label="Native", show_border=True, enabled_when="tx_use_ibis == False", ), label="Tx", show_border=True, ), VGroup( # Interconnect VGroup( # From File VGroup( HGroup( Item( name="ch_file", label="File", springy=True, editor=FileEditor(dialog_style="open"), ), Item(name="chnl_valid", label="Valid", style="simple", enabled_when="False"), ), HGroup( Item( name="use_ch_file", label="Use file", enabled_when="chnl_valid == True", ), spring, Item(name="padded", label="Zero-padded", enabled_when="use_ch_file == True"), Item(name="windowed", label="Windowed", enabled_when="use_ch_file == True"), ), ), HGroup( Item( name="Zref", label="Zref", tooltip="Reference Impedance.", ), Item(label="Ohms"), Item( name="f_step", label="f_step", tooltip="Frequency step to use in generating H(f).", ), Item(label="MHz"), enabled_when="use_ch_file == True", ), label="From File", show_border=True, ), HGroup( # Native (i.e. - Howard Johnson's) interconnect model. VGroup( Item( name="l_ch", label="Length (m)", tooltip="interconnect length", ), Item( name="Theta0", label="Loss Tan.", tooltip="dielectric loss tangent", ), Item( name="Z0", label="Z0 (Ohms)", tooltip="characteristic differential impedance", ), Item( name="v0", label="v_rel (c)", tooltip="normalized propagation velocity", ), ), VGroup( Item( name="Rdc", label="Rdc (Ohms)", tooltip="d.c. resistance", ), Item( name="w0", label="w0 (rads./s)", tooltip="transition frequency", ), Item( name="R0", label="R0 (Ohms)", tooltip="skin effect resistance", ), ), label="Native", show_border=True, enabled_when="use_ch_file == False", ), label="Interconnect", show_border=True, ), VGroup( VGroup( HGroup( Item( name="rx_ibis_file", label="File", springy=True, editor=FileEditor(dialog_style="open", filter=["*.ibs"]), ), Item(name="rx_ibis_valid", label="Valid", style="simple", enabled_when="False"), ), HGroup( Item(name="rx_use_ibis", label="Use IBIS"), Item(name="btn_sel_rx", show_label=False), Item(name="btn_view_rx", show_label=False), enabled_when="rx_ibis_valid == True", ), label="IBIS", show_border=True, ), VGroup( Item( name="rin", label="Rx_Rin (Ohms)", tooltip="Rx differential input impedance", ), Item( name="cin", label="Rx_Cin (pF)", tooltip="Rx parasitic input capacitance (each pin)", ), Item( name="cac", label="Rx_Cac (uF)", tooltip="Rx a.c. coupling capacitance (each pin)", ), label="Native", show_border=True, enabled_when="rx_use_ibis == False", ), label="Rx", show_border=True, ), label="Channel", show_border=True, ), # spring, label="Config.", id="config", ), # "Equalization" tab. VGroup( # Channel Parameters HGroup( VGroup( VGroup( HGroup( VGroup( HGroup( Item(name="tx_ami_file", label="AMI File:", style="readonly", springy=True), Item(name="tx_ami_valid", label="Valid", style="simple", enabled_when="False"), ), HGroup( Item(name="tx_dll_file", label="DLL File:", style="readonly", springy=True), Item(name="tx_dll_valid", label="Valid", style="simple", enabled_when="False"), ), ), VGroup( Item( name="tx_use_ami", label="Use AMI", tooltip="You must select both files, first.", enabled_when="tx_ami_valid == True and tx_dll_valid == True", ), Item( name="tx_use_getwave", label="Use GetWave", tooltip="Use the model's GetWave() function.", enabled_when="tx_use_ami and tx_has_getwave", ), Item( "btn_cfg_tx", show_label=False, tooltip="Configure Tx AMI parameters.", enabled_when="tx_ami_valid == True", ), ), ), label="IBIS-AMI", show_border=True, ), VGroup( Item( name="tx_taps", editor=TableEditor( columns=[ ObjectColumn(name="name", editable=False), ObjectColumn(name="enabled", style="simple"), ObjectColumn(name="min_val", horizontal_alignment="center"), ObjectColumn(name="max_val", horizontal_alignment="center"), ObjectColumn(name="value", format="%+05.3f", horizontal_alignment="center"), ObjectColumn(name="steps", horizontal_alignment="center"), ], configurable=False, reorderable=False, sortable=False, selection_mode="cell", # auto_size=True, rows=4, ), show_label=False, ), label="Native", show_border=True, enabled_when="tx_use_ami == False", ), label="Tx Equalization", show_border=True, ), VGroup( VGroup( HGroup( VGroup( HGroup( Item(name="rx_ami_file", label="AMI File:", style="readonly", springy=True), Item(name="rx_ami_valid", label="Valid", style="simple", enabled_when="False"), ), HGroup( Item(name="rx_dll_file", label="DLL File:", style="readonly", springy=True), Item(name="rx_dll_valid", label="Valid", style="simple", enabled_when="False"), ), ), VGroup( Item( name="rx_use_ami", label="Use AMI", tooltip="You must select both files, first.", enabled_when="rx_ami_valid == True and rx_dll_valid == True", ), Item( name="rx_use_getwave", label="Use GetWave", tooltip="Use the model's GetWave() function.", enabled_when="rx_use_ami and rx_has_getwave", ), Item( "btn_cfg_rx", show_label=False, tooltip="Configure Rx AMI parameters.", enabled_when="rx_ami_valid == True", ), ), ), label="IBIS-AMI", show_border=True, ), VGroup( VGroup( VGroup( HGroup( Item( name="use_ctle_file", label="fromFile", tooltip="Select CTLE impulse/step response from file.", ), Item(name="ctle_file", label="Filename", enabled_when="use_ctle_file == True", editor=FileEditor(dialog_style="open"),), ), HGroup( Item( name="peak_freq", label="CTLE fp (GHz)", tooltip="CTLE peaking frequency (GHz)", enabled_when="use_ctle_file == False", ), Item( name="rx_bw", label="Bandwidth (GHz)", tooltip="unequalized signal path bandwidth (GHz).", enabled_when="use_ctle_file == False", ), ), HGroup( Item( name="peak_mag", label="CTLE boost (dB)", tooltip="CTLE peaking magnitude (dB)", format_str="%4.1f", enabled_when="use_ctle_file == False", ), Item( name="ctle_mode", label="CTLE mode", tooltip="CTLE Operating Mode", enabled_when="use_ctle_file == False", ), Item( name="ctle_offset", tooltip="CTLE d.c. offset (dB)", show_label=False, enabled_when='ctle_mode == "Manual"', ), ), label="CTLE", show_border=True, enabled_when="rx_use_ami == False", ), ), VGroup( HGroup( Item(name="delta_t", label="Delta-t (ps)", tooltip="magnitude of CDR proportional branch"), Item(name="alpha", label="Alpha", tooltip="relative magnitude of CDR integral branch"), ), HGroup( Item( name="n_lock_ave", label="Lock Nave.", tooltip="# of UI estimates to average, when determining lock", ), Item( name="rel_lock_tol", label="Lock Tol.", tooltip="relative tolerance for determining lock" ), Item( name="lock_sustain", label="Lock Sus.", tooltip="length of lock determining hysteresis vector", ), ), label="CDR", show_border=True, enabled_when='rx_use_ami == False or rx_use_getwave == False', ), VGroup( ), VGroup( HGroup( Item( name="use_dfe", label="Use DFE", tooltip="Include DFE in simulation.", enabled_when="rx_use_ami == False or rx_use_getwave == False", ), ), HGroup( Item(name="n_taps", label="Taps", tooltip="# of taps"), Item(name="gain", label="Gain", tooltip="error feedback gain"), Item(name="decision_scaler", label="Level", tooltip="target output magnitude"), enabled_when="use_dfe == True", ), HGroup( Item(name="n_ave", label="Nave.", tooltip="# of CDR adaptations per DFE adaptation"), Item( name="sum_bw", label="BW (GHz)", tooltip="summing node bandwidth", enabled_when="sum_ideal == False", ), Item( name="sum_ideal", label="Ideal", tooltip="Use ideal DFE. (performance boost)", enabled_when="use_dfe == True", ), enabled_when="use_dfe == True", ), label="DFE", show_border=True, ), label="Native", show_border=True, ), label="Rx Equalization", show_border=True, ), springy=True, ), HGroup( ), label="Equalization", id="channel", ), # "Optimizer" tab. VGroup( HGroup( Group( Item( name="tx_tap_tuners", editor=TableEditor( columns=[ ObjectColumn(name="name", editable=False), ObjectColumn(name="enabled"), ObjectColumn(name="min_val"), ObjectColumn(name="max_val"), ObjectColumn(name="value", format="%+05.3f"), ], configurable=False, reorderable=False, sortable=False, selection_mode="cell", auto_size=False, rows=4, orientation="horizontal", is_grid_cell=True, ), show_label=False, ), label="Tx Equalization", show_border=True, springy=True, ), # HGroup( VGroup( Item( name="peak_mag_tune", label="CTLE: boost (dB)", tooltip="CTLE peaking magnitude (dB)", format_str="%4.1f", ), HGroup( Item(name="peak_freq_tune", label="fp (GHz)", tooltip="CTLE peaking frequency (GHz)" ), Item( name="rx_bw_tune", label="BW (GHz)", tooltip="unequalized signal path bandwidth (GHz).", ), ), HGroup( Item(name="ctle_mode_tune", label="mode", tooltip="CTLE Operating Mode"), Item( name="ctle_offset_tune", tooltip="CTLE d.c. offset (dB)", show_label=False, enabled_when='ctle_mode_tune == "Manual"', ), ), HGroup( Item(name="use_dfe_tune", label="DFE: Enable", tooltip="Include ideal DFE in optimization."), Item(name="n_taps_tune", label="Taps", tooltip="Number of DFE taps."), ), label="Rx Equalization", show_border=True, ), # ), VGroup( Item( name="max_iter", label="Max. Iterations", tooltip="Maximum number of iterations to allow, during optimization.", ), Item( name="rel_opt", label="Rel. Opt.:", format_str="%7.4f", tooltip="Relative optimization metric.", style="readonly", ), Item( name="przf_err", label="PRZF Err.:", format_str="%5.3f", tooltip="Pulse Response Zero Forcing approximation error.", style="readonly", ), label="Tuning Options", show_border=True, ), springy=False, ), Item( label="Note: Only CTLE boost will be optimized; please, set peak frequency, bandwidth, and mode appropriately.", ), Item("plot_h_tune", editor=ComponentEditor(), show_label=False, springy=True), HGroup( Item("btn_rst_eq", show_label=False, tooltip="Reset all values to those on the 'Config.' tab."), Item("btn_save_eq", show_label=False, tooltip="Store all values to 'Config.' tab."), Item("btn_opt_tx", show_label=False, tooltip="Run Tx tap weight optimization."), Item("btn_opt_rx", show_label=False, tooltip="Run Rx CTLE optimization."), Item("btn_coopt", show_label=False, tooltip="Run co-optimization."), Item("btn_abort", show_label=False, tooltip="Abort all optimizations."), ), label="Optimizer", id="eq_tune", ), Group( # Responses Group(Item("plots_h", editor=ComponentEditor(), show_label=False), label="Impulses", id="plots_h"), Group(Item("plots_s", editor=ComponentEditor(), show_label=False), label="Steps", id="plots_s"), Group(Item("plots_p", editor=ComponentEditor(), show_label=False), label="Pulses", id="plots_p"), Group(Item("plots_H", editor=ComponentEditor(), show_label=False), label="Freq. Resp.", id="plots_H"), layout='tabbed', label='Responses', id='responses' ), Group( # Results Group(Item("plots_dfe", editor=ComponentEditor(), show_label=False), label="DFE", id="plots_dfe"), Group(Item("plots_out", editor=ComponentEditor(), show_label=False), label="Outputs", id="plots_out"), Group(Item("plots_eye", editor=ComponentEditor(), show_label=False), label="Eyes", id="plots_eye"), Group(Item("plots_bathtub", editor=ComponentEditor(), show_label=False), label="Bathtubs", id="plots_bathtub"), Group(Item("sweep_info", style="readonly", show_label=False), label="Sweep Info"), layout='tabbed', label='Results', id='results' ), Group( # Jitter Group( Item("plots_jitter_dist", editor=ComponentEditor(), show_label=False), label="Jitter Dist.", id="plots_jitter_dist", ), Group( Item("plots_jitter_spec", editor=ComponentEditor(), show_label=False), label="Jitter Spec.", id="plots_jitter_spec", ), Group(Item("jitter_info", style="readonly", show_label=False), label="Jitter Info"), layout='tabbed', label='Jitter', id='jitter' ), Group( # Help Group( Item("ident", style="readonly", show_label=False), Item("perf_info", style="readonly", show_label=False), label="About", ), Group(Item("instructions", style="readonly", show_label=False), label="Guide"), Group(Item("console_log", show_label=False, style="custom"), label="Console", id="console"), layout='tabbed', label='Help', id='help' ), layout="tabbed", springy=True, id="tabs", ), resizable=False, handler=MyHandler(), buttons=[run_sim, save_cfg, load_cfg, save_data, load_data], statusbar="status_str", title="PyBERT", width=0.95, height=0.9, icon=ImageResource("icon.png"), )