import wx import util class LEON2RegisterConfig(): CONFIG_HEX = 0 CONFIG_DEC = 1 # tuples contain register prefix and offsets of the register # sets within the global gprs field register_offsets = ( ("g", 0), ("o", 8), ("l", 16), ("i", 24) ) cpu_registers = ("pc", "npc", "wim", "psr", "fsr", "tbr", "y") mmu_registers = ( ("ctrl", "mmu_control_reg"), ("ctxt ptr", "mmu_ctxt_ptr"), ("ctxt reg", "mmu_ctxt_reg"), ("fault addr", "mmu_fault_address"), ("fault class", "mmu_fault_class"), ("fault stat", "mmu_fault_status"), ("flt st rd", "mmu_fault_status_read") ) def __init__(self, display_format): self.display_format = display_format @property def display_format(self): def fget(self): return self.display_format def fset(self, value): if value in (self.CONFIG_DEC, self.CONFIG_HEX): self.display_format = value @property def display_format_str(self): if self.display_format == self.CONFIG_HEX: return "%08X" else: return "%d" @property def reg_offs(self): return self.register_offsets @property def cpu_regs(self): return self.cpu_registers @property def mmu_regs(self): return self.mmu_registers # Register view for LEON2 processor class LEON2RegisterView(ThreadedWindow): def switch_display_format(self, event): if self.rb_dec.GetValue() == True: self.leon2cfg.display_format = LEON2RegisterConfig.CONFIG_DEC else: self.leon2cfg.display_format = LEON2RegisterConfig.CONFIG_HEX self.update(True) def value_from_str(self, valstr, cfg): if cfg == LEON2RegisterConfig.CONFIG_DEC: return int(valstr) else: return int(valstr, 16) def create_config_view(self, parent): config_view = wx.StaticBoxSizer(wx.StaticBox(parent, label="Options"), wx.HORIZONTAL) sbox = wx.StaticBoxSizer(wx.StaticBox(parent, label="Display format"), wx.VERTICAL) self.rb_dec = wx.RadioButton(parent, -1, "Decimal", style = wx.RB_GROUP) self.rb_dec.SetValue(False) self.rb_hex = wx.RadioButton(parent, -1, "Hexadecimal") self.rb_hex.SetValue(True) sbox.Add(self.rb_dec) sbox.Add(self.rb_hex) self.frame.Bind(wx.EVT_RADIOBUTTON, self.switch_display_format, id=self.rb_dec.GetId()) self.frame.Bind(wx.EVT_RADIOBUTTON, self.switch_display_format, id=self.rb_hex.GetId()) config_view.Add(sbox) return config_view def create_gpr_view(self, parent): gpr_view = wx.StaticBoxSizer(wx.StaticBox(parent, label="General purpose registers"), wx.VERTICAL) gpr_grid = wx.FlexGridSizer(9, 5) gpr_grid.Add(wx.StaticText(parent)) # empty text as dummy for top left corner for (reg, off) in self.leon2cfg.reg_offs: gpr_grid.Add(wx.StaticText(parent, label=reg.capitalize()), 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) for i in range(8): gpr_grid.Add(wx.StaticText(parent, label=str(i)), 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) for char in ('g', 'o', 'l', 'i'): _id = "%c%d" % (char, i) self.textctrls[_id] = wx.TextCtrl(parent) gpr_grid.Add(self.textctrls[_id], 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) gpr_view.Add(gpr_grid) return gpr_view def create_other_view(self, parent): other_view = wx.StaticBoxSizer(wx.StaticBox(parent, label = "Control registers"), wx.VERTICAL) cpu_reg_grid = wx.FlexGridSizer(3,6) for name in self.leon2cfg.cpu_regs: cpu_reg_grid.Add(wx.StaticText(parent, label=name.upper()), 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT) self.textctrls[name] = wx.TextCtrl(parent) cpu_reg_grid.Add(self.textctrls[name], 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) other_view.Add(cpu_reg_grid) return other_view def create_mmu_view(self, parent): mmu_view = wx.StaticBoxSizer(wx.StaticBox(parent, label = "MMU registers"), wx.VERTICAL) mmu_reg_grid = wx.FlexGridSizer(4,4) for (label, reg) in self.leon2cfg.mmu_regs: mmu_reg_grid.Add(wx.StaticText(parent, label=label.upper()), 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT) self.textctrls[label] = wx.TextCtrl(parent) mmu_reg_grid.Add(self.textctrls[label], 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) mmu_view.Add(mmu_reg_grid) return mmu_view def __init__(self, conf_cpu = conf.system_cmp0.cpu): ThreadedWindow.__init__(self) self.leon2cfg = LEON2RegisterConfig(LEON2RegisterConfig.CONFIG_HEX) self.cpu = conf_cpu # Create basic wx stuff. The panel is important as we are going # to place all other stuff in it. self.app = wx.App(False) self.frame = wx.Frame(None, wx.ID_ANY, "LEON2 GPR view", size = (360,450)) self.panel = wx.Panel(self.frame) self.main_vbox = wx.BoxSizer(wx.VERTICAL) self.panel.SetSizer(self.main_vbox) # we maintain a dictionary of : mappings self.textctrls = {} # Layout main vbox: # +-------------------+ # | config box | # +-------------------+ # | GPR box | # +-------------------+ # | Control registers | # +-------------------+ # | MMU registers | # +-------------------+ self.main_vbox.Add(self.create_config_view(self.panel)) self.main_vbox.Add(self.create_gpr_view(self.panel)) self.main_vbox.Add(self.create_other_view(self.panel)) self.main_vbox.Add(self.create_mmu_view(self.panel)) self.update(True) def change_bg_if_changed(self, ctrl, val_new): vn = self.value_from_str(val_new, self.leon2cfg.display_format) vo = self.value_from_str(ctrl.Value, self.leon2cfg.display_format) if ctrl.Value != "" and vn != vo: ctrl.SetBackgroundColour("Yellow") else: ctrl.SetBackgroundColour("White") def cpu_attr_to_value(self, attr_name): fmt = self.leon2cfg.display_format_str exec("val_new = fmt %% conf.%s.%s" % (self.cpu.name, attr_name)) return val_new def do_value_update(self, ctrl, val, format_changed): if not format_changed: self.change_bg_if_changed(ctrl, val) ctrl.SetValue(val) def update(self, format_changed = False): registers = self.cpu.gprs fmt = self.leon2cfg.display_format_str # update GPRs for (reg, off) in self.leon2cfg.reg_offs: for i in range(8): ctrl = self.textctrls["%s%d" % (reg, i)] val_new = fmt % registers[off + i] self.do_value_update(ctrl, val_new, format_changed) # update control regs for reg in self.leon2cfg.cpu_regs: ctrl = self.textctrls[reg] val_new = self.cpu_attr_to_value(reg) self.do_value_update(ctrl, val_new, format_changed) # update MMU view for (lbl, name) in self.leon2cfg.mmu_regs: ctrl = self.textctrls[lbl] val_new = self.cpu_attr_to_value(name) self.do_value_update(ctrl, val_new, format_changed) def leon2_regview(): win = LEON2RegisterView() win.show() return win def l2_step(win, num=1): if num > 0: run_command("stepi %d" % num) else: run_command("rstepi %d" % -num) wx.CallAfter(win.update) return win def l2_cont(win, steps=0): if steps > 0: run_command("continue %d" % steps) elif steps < 0: run_command("reverse %d" % -steps) else: run_command("continue") wx.CallAfter(win.update) return win def dump_regs_to_file(cpu, f): for r in cpu.gprs: f.write(str(r) + " ") for r in LEON2RegisterConfig.cpu_registers: _cmd = "f.write(str(conf.%s) + \" \")" % (cpu.name + "." + r) exec(_cmd) f.write("\n") def l2_register_trace(cpu = conf.system_cmp0.cpu, steps = 1, logfile = "trace.log", ): f = file(logfile, "w") f.write("# 32 GPRs + CPU registers: ") f.write("# ") for r in LEON2RegisterConfig.cpu_registers: f.write("%s " % r) f.write("\n") for i in range(steps): f.write(str(i) + " ") dump_regs_to_file(cpu, f) run_command("c 1")