diff --git a/src/simudator/core/module.py b/src/simudator/core/module.py index f1cf900406eda3bb8959d4d25b949ce0bc59df0d..edd367fca29fef303741a9c5024218ca738ce15f 100644 --- a/src/simudator/core/module.py +++ b/src/simudator/core/module.py @@ -41,9 +41,17 @@ class Module: state_dict["name"] = self.name return state_dict + def get_gui_state(self) -> dict: + """ + Returns a dict of the module states that should be displayed in a GUI. + """ + state_dict = dict() + state_dict["name"] = self.name + return state_dict + def set_state(self, state: dict) -> None: """ - Sets the modules state to one given in dict. Dict format vill be + Sets the modules state to one given in dict. Dict format will be diffrent for each type of module so use get_state to get correct format. """ self.name = state["name"] diff --git a/src/simudator/core/modules/flag.py b/src/simudator/core/modules/flag.py index 53d9597e70972defc60ebf2f3e18e58e5843d8c5..70b88d52176467283be58aa46ce441b6008dfda2 100644 --- a/src/simudator/core/modules/flag.py +++ b/src/simudator/core/modules/flag.py @@ -71,14 +71,21 @@ class Flag(Module): state["mask"] = self.mask return state + def get_gui_state(self) -> dict: + state = super().get_gui_state() + state["value"] = self.value + return state + def set_state(self, state: dict[str: Any]) -> None: """ Sets the register state to one given in dict. """ self.name = state["name"] self.value = state["value"] - self.bit_length = state["bit_length"] - self.mask = state["mask"] + if "bit_length" in state: + self.bit_length = state["bit_length"] + if "mask" in state: + self.mask = state["mask"] def reset(self) -> None: """ diff --git a/src/simudator/core/modules/memory.py b/src/simudator/core/modules/memory.py index d3504318ee103983f7251c83b88cb1cc2451eaa6..017c2de2f4084dd3f52b73e757b2b915aa31f0ec 100644 --- a/src/simudator/core/modules/memory.py +++ b/src/simudator/core/modules/memory.py @@ -81,11 +81,20 @@ class Memory(Module): state["memory"] = self.memory[:] return state + def get_gui_state(self) -> dict: + state = super().get_gui_state() + state["current_adress"] = self.current_adress + state["memory"] = self.memory[:] + return state + def set_state(self, state: dict) -> None: super().set_state(state) - self.is_write = state["is_write"] - self.current_adress = state["current_adress"] - self.memory = state["memory"] + if "is_write" in state: + self.is_write = state["is_write"] + if "current_adress" in state: + self.current_adress = state["current_adress"] + if "memory" in state: + self.memory = state["memory"] def reset(self) -> None: """ diff --git a/src/simudator/gui/breakpoint_window.py b/src/simudator/gui/breakpoint_window.py index 58b2a8306d5b8c18624a786d801b80d989746e02..bf713be52d56593502b42f2706a231868a7b6737 100644 --- a/src/simudator/gui/breakpoint_window.py +++ b/src/simudator/gui/breakpoint_window.py @@ -8,6 +8,7 @@ from PyQt5.QtWidgets import ( QWidget, ) +from simudator.core.breakpoint import Breakpoint from simudator.core.processor import Processor @@ -16,9 +17,12 @@ class BreakpointWindow(QWidget): def __init__(self, cpu: Processor): super().__init__() self.cpu = cpu + + # Make layouts layout = QHBoxLayout() button_layout = QVBoxLayout() + # Make buttons for editing breakpoints self.toggle_enabled_button = QPushButton("Toggle Enabled") self.toggle_enabled_button.clicked.connect(self.toggleEnabledClicked) button_layout.addWidget(self.toggle_enabled_button) @@ -26,22 +30,30 @@ class BreakpointWindow(QWidget): self.remove_button = QPushButton("Remove") self.remove_button.clicked.connect(self.removeItemClicked) button_layout.addWidget(self.remove_button) - layout.addLayout(button_layout) + # Add list of breakpoints self.breakpoint_list = QListWidget() - layout.addWidget(self.breakpoint_list) + self.setLayout(layout) + # Update so we fill the list with breakpoints self.update() - def update(self): + def update(self) -> None: + """ + Updates list with breakpoints by removing the current items + and then filling with new once according to the cpu's content. + """ + # Remove so we don't have dubble of all items self.removeAllItems() + # Get icons for showing if enabled i_icon = self.style().standardIcon(QStyle.SP_DialogApplyButton) stop_icon = self.style().standardIcon(QStyle.SP_DialogCancelButton) + # Add an list item for each breakpoint in cpu for bp_id, breakpoint in self.cpu.breakpoints.items(): bp_str = str(bp_id) + ": " + breakpoint.__str__() bp_item = QListWidgetItem(bp_str) @@ -53,11 +65,18 @@ class BreakpointWindow(QWidget): bp_item.setIcon(stop_icon) self.breakpoint_list.addItem(bp_item) - def removeAllItems(self): + def removeAllItems(self) -> None: + """ + Removes all list items from the breakpoint list. + """ for row in range(self.breakpoint_list.count()): self.breakpoint_list.takeItem(0) - def toggleEnabledClicked(self): + def toggleEnabledClicked(self) -> None: + """ + Called when the toggle enabled buttons is pressed. + Toggles the selected breakpoint so it is enabled or disabled. + """ current_bp = self.getSelectedItem() if current_bp is None: @@ -66,7 +85,11 @@ class BreakpointWindow(QWidget): current_bp.set_enabled(not current_bp.is_enabled) self.update() - def removeItemClicked(self): + def removeItemClicked(self) -> None: + """ + Called when the remove button is preseed. + Will remove the selected breakpoint from the cpu's breakpoint list. + """ bp_id = self.getSelectedItemId() # Do nothing if id is None @@ -76,7 +99,11 @@ class BreakpointWindow(QWidget): del self.cpu.breakpoints[bp_id] self.update() - def getSelectedItemId(self): + def getSelectedItemId(self) -> int: + """ + Gives the id of the selected breakpoint. + Used to fetch the corresponding breakpoint from the cpu. + """ current_bp_item = self.breakpoint_list.currentItem() # Return None if list is empty @@ -85,7 +112,10 @@ class BreakpointWindow(QWidget): return int(current_bp_item.text()[0]) - def getSelectedItem(self): + def getSelectedItem(self) -> Breakpoint: + """ + Returns the selected breakpoint. + """ bp_id = self.getSelectedItemId() # Do nothing if there are no breakpoints or if id is nonetype diff --git a/src/simudator/gui/dialogs/module_state_dialog.py b/src/simudator/gui/dialogs/module_state_dialog.py index a51738db2b64a6ae689956be04e1adfbd5ed467c..a9f7271ddbed79e80966da0e51cb6fb5ec52ce22 100644 --- a/src/simudator/gui/dialogs/module_state_dialog.py +++ b/src/simudator/gui/dialogs/module_state_dialog.py @@ -24,7 +24,7 @@ class ModuleStateDialog(QDialog): super().__init__(parent, flags) self.module = module - states = module.get_state() + states = module.get_gui_state() # Remove the 'name' state of the module from the drop down menu so # that the user cannot e.g. edit or add a breakpoint of a module @@ -60,7 +60,7 @@ class ModuleStateDialog(QDialog): def updateState(self) -> None: selectedState = self.stateSelectWidget.currentText() - value = self.module.get_state()[selectedState] + value = self.module.get_gui_state()[selectedState] self.valueWidget.setText(str(value)) def signalOK(self) -> None: diff --git a/src/simudator/gui/gui.py b/src/simudator/gui/gui.py index 0a3214fa47f1e543ee603d79b95c85e082936a81..112d349e299c0dd1143d1bef30c49358b466b5fe 100644 --- a/src/simudator/gui/gui.py +++ b/src/simudator/gui/gui.py @@ -87,7 +87,7 @@ class View(QGraphicsView): class GUI(QMainWindow): """ This is the main class for the GUI. It handles creating the widnow for - the gui, aswell as the toolbat for controlling the simultaion. + the gui, aswell as the toolbar for controlling the simultaion. It takes a processor and visualizes its modules as boxes with the signals as lines between them. Graphics items for the modules and signals need to be created and added individually. @@ -132,50 +132,9 @@ class GUI(QMainWindow): app.setStyleSheet("Qwidget.QMainWindow { background-color: yellow }") self.setAttribute(QtCore.Qt.WA_StyledBackground) - # Add this so we can save the window in scope later + # Add this so we can save the window in scope later, otherwise it disappears self.breakpoint_window = None - #"QGraphicsItem { background-color: blue }") - #self.setStyleSheet("background-color: yellow") - - def abc(self, event): - """ - Zoom in/out while scrolling in the upper/lower - edge of the view. Ignores scrolls in the horizontal plane. - """ - print(123) - - # Only zoom when ctrl is pressed - modifiers = QtWidgets.QApplication.keyboardModifiers() - if modifiers == QtCore.Qt.ControlModifier: - - # Factor above 1 zooms in, below zooms out - factor = 1.02 - if event.pixelDelta().y() < 0: - factor = 0.98 - - # If event got triggered due to the x axis, do nothing - if event.pixelDelta().x() != 0: - return - - view_pos = event.globalPosition() - view_pos_x = int(view_pos.x()) - view_pos_y = int(view_pos.y()) - - scene_pos = self.graphics_view.mapToScene(view_pos_x, view_pos_y) - - self.graphics_view.centerOn(scene_pos) - self.graphics_view.scale(factor, factor) - - old_pos = self.graphics_view.mapToScene(view_pos_x, view_pos_y) - new_pos = self.graphics_view.mapToScene( - self.graphics_view.viewport().rect().center() - ) - - delta = old_pos - new_pos - - self.graphics_view.centerOn(scene_pos - delta) - def createToolBar(self) -> None: """ Creates the toolbar containing the file, layout and toolbar @@ -341,10 +300,17 @@ class GUI(QMainWindow): } def updateCpuListeners(self) -> None: + """ + Updates the graphics items in the scene and the clock. + Used after the cpu has run or when the user has edited somehting. + """ self.cpu_graphics_scene.updateGraphicsItems() self.clock_label.setText("Clockcycle: " + str(self.cpu.get_clock())) def stateBreakpointDialog(self) -> None: + """ + Opens dialog window for user to create a breakpoint. + """ action = self.moduleActions['add_br'] module_name = action.data() module = self.cpu.get_module(module_name) @@ -352,11 +318,17 @@ class GUI(QMainWindow): state_br_dialog.okSignal.connect(self.addStateBreakpoint) def lambdaBreakpointDialog(self) -> None: + """ + Opens dialog window for user to create a breakpoint. + """ lambdas = self.cpu.get_breakpoint_lambdas() lambda_br_dialog = LambdaBreakpointDialog(lambdas, self) lambda_br_dialog.accepted.connect(self.addLambdaBreakpoint) def memoryBreakpointDialog(self) -> None: + """ + Opens dialog window for user to create a breakpoint. + """ action = self.moduleActions['add_mem_br'] module_name = action.data() module = self.cpu.get_module(module_name) @@ -364,10 +336,17 @@ class GUI(QMainWindow): memory_br_dialog.accepted.connect(self.addMemoryBreakpoint) def updateBreakpointWindow(self) -> None: + """ + Updates the breakpoint window when new breakpoints are added. + """ + # Don't do anything if window is closed if self.breakpoint_window is not None: self.breakpoint_window.update() def editModuleStateDialog(self) -> None: + """ + Opens dialog where user can edit the state of a module. + """ action = self.moduleActions['edit_state'] module_name = action.data() module = self.cpu.get_module(module_name) @@ -375,6 +354,9 @@ class GUI(QMainWindow): state_br_dialog.okSignal.connect(self.editModuleState) def editMemoryContentDialog(self) -> None: + """ + Opens dialog where user can edit the contents of a memory. + """ action = self.moduleActions['edit_memory'] module_name = action.data() module = self.cpu.get_module(module_name) @@ -465,6 +447,9 @@ class GUI(QMainWindow): self.undo_action.setDisabled(is_disable) def stepToolBarButtonClick(self): + """ + Runs the cpu a specified number of times according to the jump value box. + """ # Don't do steps if cpu is running if self.cpu_running: @@ -482,6 +467,9 @@ class GUI(QMainWindow): self.updateCpuListeners() def runToolBarButtonClick(self) -> None: + """ + Runs the cpu until it is stopped by user input, breakpoint or similar. + """ # Don't run if already running if self.cpu_running: @@ -496,33 +484,27 @@ class GUI(QMainWindow): @pyqtSlot(int) def cpuHaltedFunction(self, steps: int) -> None: + """ + Called from other thread when cpu has halted. + Will inform the user and update visuals. + """ + # If a breakpoint halted the program inform thr user + if self.cpu.breakpoint_reached: + self.messageBox("Reached breakpoint: " + self.cpu.last_breakpoint.__str__()) # Only show halted message for larger steps that take time # This is done so a user dosent have to close # the message box after every small step - if self.cpu.breakpoint_reached: - self.messageBox("Reached breakpoint: " + self.cpu.last_breakpoint.__str__()) elif steps > self.HALT_MESSAGE_THRESHOLD: self.messageBox("The processor halted.") self.updateCpuListeners() self.cpu_running = False self.setDisabledWhenRunning(False) - def stepNToolBarButtonClick(self) -> None: - cycles, ok = QInputDialog(self).getInt(self, - "Input number of cycles to run", - "Input number of cycles to run", - ) - if ok: - if cycles < 1: - self.errorBox("Please input a number larger than 0.") - return - self.cpu.unstop() - for _ in range(cycles): - self.cpu.do_tick() - self.updateCpuListeners() - def stopToolBarButtonClick(self) -> None: + """ + Tells the cpu to stop. It will then stop at an appropriate in its own thread. + """ self.cpu.stop() self.updateCpuListeners() @@ -778,18 +760,30 @@ class GUI(QMainWindow): self.cpu.save_state_to_file(path) def openBreakpointWindow(self): + """ + Opens window for editing breakpoints. + """ self.breakpoint_window = BreakpointWindow(self.cpu) self.breakpoint_window.show() def showPortNamesBarButtonClick(self): + """ + Toggles showing port names in the graphics scene. + """ self.cpu_graphics_scene.setPortNamesVisibility( self.port_vis_action.isChecked()) def showSignalsMenuButtonClick(self): + """ + Toggle shoing the signals in the graphics scene. + """ self.cpu_graphics_scene.setAllSignalsVisibility( self.signal_vis_action.isChecked()) def toggleLayoutLockMenuButtonClick(self): + """ + Toggles so the layout can not be edited. + """ self.cpu_graphics_scene.setLayoutLock( self.lock_layout_action.isChecked()) @@ -850,10 +844,16 @@ class GUI(QMainWindow): self.errorBox("Unable to undo the cycle.") def addModuleGraphicsItem(self, graphics_item: ModuleGraphicsItem): + """ + Adds an item to the graphics scene. + """ self.cpu_graphics_scene.addModuleGraphicsItem(graphics_item) graphics_item.addActions(self.moduleActions.values()) def addAllSignals(self) -> None: + """ + Add signals depending on modules in the graphics scene. + """ self.cpu_graphics_scene.addAllSignals() diff --git a/src/simudator/gui/module_graphics_item/mia/mia_flag_graphic.py b/src/simudator/gui/module_graphics_item/mia/mia_flag_graphic.py index 853528cea64a89fb1f9253a73e31b9210c2e9f41..9d182af4e12888690bfc5cbff66e8f1c588bade8 100644 --- a/src/simudator/gui/module_graphics_item/mia/mia_flag_graphic.py +++ b/src/simudator/gui/module_graphics_item/mia/mia_flag_graphic.py @@ -1,12 +1,15 @@ from simudator.gui.module_graphics_item.mia.mia_register_graphic import ( RegisterGraphicsItem, ) +from simudator.processor.mia.mia_register import MiaRegister class FlagGraphicsItem(RegisterGraphicsItem): """ Graphics module for mia's flag module. """ + def __init__(self, module: MiaRegister): + super().__init__(module) def draw_graphics_item(self): self.draw_rect() diff --git a/src/simudator/gui/module_graphics_item/mia/mia_ir_graphic.py b/src/simudator/gui/module_graphics_item/mia/mia_ir_graphic.py index 23edfdad8ed331df4b60959ac3ffac1883b5f6a3..13562f63be7fbb654ba21de8e407caa22d60383e 100644 --- a/src/simudator/gui/module_graphics_item/mia/mia_ir_graphic.py +++ b/src/simudator/gui/module_graphics_item/mia/mia_ir_graphic.py @@ -1,5 +1,6 @@ from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsSimpleTextItem +from simudator.core.module import Module from simudator.gui.module_graphics_item.module_graphics_item import ModuleGraphicsItem @@ -20,6 +21,10 @@ class IrGraphicsItem(ModuleGraphicsItem): TEXT_HEIGHT_MARGIN = 8 BIG_TEXT_HEIGHT_MARGIN = 12 + def __init__(self, module: Module, name: str = None): + super().__init__(module, name) + self.draw_ports() + def draw_graphics_item(self): # Add small rect diff --git a/src/simudator/gui/module_graphics_item/mia/mia_register_graphic.py b/src/simudator/gui/module_graphics_item/mia/mia_register_graphic.py index 9e47836a490c7d581797b04758752dbf72aa1d4b..92f0254e8902a250fec9828f3063595322277e9b 100644 --- a/src/simudator/gui/module_graphics_item/mia/mia_register_graphic.py +++ b/src/simudator/gui/module_graphics_item/mia/mia_register_graphic.py @@ -19,6 +19,11 @@ class RegisterGraphicsItem(ModuleGraphicsItem): def __init__(self, module: MiaRegister): super().__init__(module) + self.draw_rect() + + def draw_graphics_item(self) -> None: + self.draw_rect() + self.draw_ports() def draw_rect(self): """ diff --git a/src/simudator/gui/module_graphics_item/module_graphics_item.py b/src/simudator/gui/module_graphics_item/module_graphics_item.py index eed66c67338029ff4e8a88b5f36bd2987a16d062..2884b68070e1f186f6a3c7b481d822799bd2d0c2 100644 --- a/src/simudator/gui/module_graphics_item/module_graphics_item.py +++ b/src/simudator/gui/module_graphics_item/module_graphics_item.py @@ -86,7 +86,7 @@ class ModuleGraphicsItem(QGraphicsObject, QGraphicsItem): # Calculate height according to number of signals and states in_signals = len(self.input_signals) out_signals = len(self.output_signals) - states = len(self.state) + states = len(self.module.get_gui_state()) inputs_height = (in_signals + 1) * self.SIGNAL_MARGIN outputs_height = (out_signals + 1) * self.SIGNAL_MARGIN members_height = states * self.CHAR_HEIGHT + self.STATE_MEMBER_MARGIN @@ -110,9 +110,10 @@ class ModuleGraphicsItem(QGraphicsObject, QGraphicsItem): # Create state lables self.state_lables = {} - for state_tuple in enumerate(self.state): + gui_states = self.module.get_gui_state() + for state_tuple in enumerate(gui_states): if state_tuple[1] != "name": - text = state_tuple[1] + ": " + str(self.state[state_tuple[1]]) + text = state_tuple[1] + ": " + str(gui_states[state_tuple[1]]) state_text = QGraphicsSimpleTextItem(text, self) state_text.setPos(width/20, state_tuple[0]*self.CHAR_HEIGHT) @@ -152,8 +153,9 @@ class ModuleGraphicsItem(QGraphicsObject, QGraphicsItem): widets will have to override it. """ self.state = self.module.get_state() + gui_state = self.module.get_gui_state() - for name, value in self.state.items(): + for name, value in gui_state.items(): if name != "name": lable = self.state_lables[name] lable.setText(name + ": " + str(value)) diff --git a/src/simudator/gui/orientation.py b/src/simudator/gui/orientation.py index e3f14c4516c9e864747d17e68477f377b88ecc31..fed1d171ca6d5c80d52dc585b35d46a7128cbd5a 100644 --- a/src/simudator/gui/orientation.py +++ b/src/simudator/gui/orientation.py @@ -2,6 +2,9 @@ from enum import IntEnum class Orientation(IntEnum): + """ + Used to give and track ports orientations. + """ UP = 0 LEFT = 1 DOWN = 2 diff --git a/src/simudator/gui/port_graphics_item.py b/src/simudator/gui/port_graphics_item.py index 095d24f15f114d8563efb2b8d01087da76a883fd..43856d2ab12c32587fb7d16934aeb29f3bdbe786 100644 --- a/src/simudator/gui/port_graphics_item.py +++ b/src/simudator/gui/port_graphics_item.py @@ -30,6 +30,12 @@ class PyQtSignalHolder(QObject): class PortGraphicsItem(QGraphicsItemGroup): + """ + Graphics item that visualises the connection between a module and a signal. + Does this by drawing a small line that goes out from the + module and the name of the signal. The port can be moved around + the edge of the of the module grapics item. + """ LINE_LENGTH = 8 CHAR_HEIGHT = 18 @@ -71,6 +77,9 @@ class PortGraphicsItem(QGraphicsItemGroup): self.setZValue(1.0) def drawPort(self) -> None: + """ + Draws the port as a small line and a label with the signals name. + """ # Create a horizontal and vertical line # We create two so we dont have to delete them when changing orientation @@ -89,6 +98,10 @@ class PortGraphicsItem(QGraphicsItemGroup): self.addToGroup(self.name_label) def setOrientation(self, orientation: int) -> None: + """ + Sets the ports orientation by showing the vertical or horizontal line + and moving the name label appropriatly. + """ self.orientation = orientation if orientation == Orientation.UP: @@ -172,6 +185,10 @@ class PortGraphicsItem(QGraphicsItemGroup): event.accept() def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None: + """ + Moves the port if left click is held. Will move it around + the edge of it parent modules baserect. + """ if not self.left_click and self.parent is not None: return if self.isLocked: @@ -235,6 +252,7 @@ class PortGraphicsItem(QGraphicsItemGroup): menu.exec_(event.screenPos()) event.accept() + # TODO: Need comments here of what does what def toggleVisibility(self) -> None: self.setVisible(not self.isVisible()) self.toggled.emit() diff --git a/src/simudator/gui/run_continuously_thread.py b/src/simudator/gui/run_continuously_thread.py index 225513638f30b1271b2fc1969360f9d107cd4ec5..1c5dfd32e4979cfd5cee0501a9b35bacc993005e 100644 --- a/src/simudator/gui/run_continuously_thread.py +++ b/src/simudator/gui/run_continuously_thread.py @@ -2,6 +2,12 @@ from PyQt5.QtCore import QRunnable class RunThread(QRunnable): + """ + This class is used to run the cpu on a seperate thread. + This allows the user to interact with the GUI will th cpu is running. + When the cpu halts this thread will emit to it's given signal + the GUI can then handel what should happend after execution on its own. + """ def __init__(self, cpu, signal, run_continuously=True, steps=0): super().__init__() diff --git a/src/simudator/processor/mia/ir.py b/src/simudator/processor/mia/ir.py index a129f77f97bbc0756b5fda3bb402e28bc4c98432..1b7f37a26c1efcbded17c294eb6ecf2b734b1386 100644 --- a/src/simudator/processor/mia/ir.py +++ b/src/simudator/processor/mia/ir.py @@ -85,13 +85,22 @@ class IR(Module, MiaBusConnector): } return state + def get_gui_state(self) -> dict: + state = super().get_gui_state() + state["value"] = self.instruction + return state + def set_state(self, state: dict) -> None: super().set_state(state) self.instruction = state["value"] - self.op = state["op"] - self.grx = state["grx"] - self.m = state["m"] - self.a = state["a"] + if "op" in state: + self.op = state["op"] + if "grx" in state: + self.grx = state["grx"] + if "m" in state: + self.m = state["m"] + if "a" in state: + self.a = state["a"] def reset(self) -> None: """ diff --git a/src/simudator/processor/mia/lc.py b/src/simudator/processor/mia/lc.py index a9f528caa65d07c8dde66e6bf670bf2fbc823d11..cff9e9e3477bc8fcbd9456d0d8f9e972806c4110 100644 --- a/src/simudator/processor/mia/lc.py +++ b/src/simudator/processor/mia/lc.py @@ -168,11 +168,16 @@ class LC(Module): """ self.name = state["name"] self.value = state["value"] - self.bit_length = state["bit_length"] - self.mask = state["mask"] - self.read_from_bus = state["read_from_bus"] - self.read_from_uADR = state["read_from_uADR"] - self.decrement_by_one = state["decrement_by_one"] + if "bit_length" in state: + self.bit_length = state["bit_length"] + if "mask" in state: + self.mask = state["mask"] + if "read_from_bus" in state: + self.read_from_bus = state["read_from_bus"] + if "read_from_uADR" in state: + self.read_from_uADR = state["read_from_uADR"] + if "decrement_by_one" in state: + self.decrement_by_one = state["decrement_by_one"] def reset(self) -> None: """ diff --git a/src/simudator/processor/mia/mia_grx.py b/src/simudator/processor/mia/mia_grx.py index 4f39e44e65dafabca1a0e6e95eba2b999bb2dbae..b897a6a946350c6989ce16d031e592b4aed602cd 100644 --- a/src/simudator/processor/mia/mia_grx.py +++ b/src/simudator/processor/mia/mia_grx.py @@ -95,26 +95,32 @@ class GRX(Module, MiaBusConnector): def update_logic(self) -> None: self.output_register() - def get_state(self) -> dict[Any]: + def get_state(self) -> dict[str, Any]: """ Returns a dict of the grx state. These states are changable via set_states. """ state = { "name": self.name, - "bus_id": self.bus_id, "bit_length": self.bit_length, "registers": self.registers[:], } return state - def set_state(self, state: dict[str: Any]): + def get_gui_state(self) -> dict: + state = { + "name": self.name, + "registers": self.registers[:], + } + return state + + def set_state(self, state: dict[str, Any]): """ Sets the grx state to one given in dict. """ self.name = state["name"] - self.bus_id = state["bus_id"] - self.bit_length = state["bit_length"] + if "bit_length" in state: + self.bit_length = state["bit_length"] self.registers = state["registers"] def reset(self) -> None: diff --git a/src/simudator/processor/mia/mia_register.py b/src/simudator/processor/mia/mia_register.py index 1b34d991d3f81fc083fae80f2fc21503d72ed665..08d577d9904a0fa4f4e6cc9087bdac5a2cb44e7e 100644 --- a/src/simudator/processor/mia/mia_register.py +++ b/src/simudator/processor/mia/mia_register.py @@ -42,13 +42,18 @@ class MiaRegister(Register): state["mask"] = self.mask return state + def get_gui_state(self) -> dict: + state = super().get_state() + return state + def set_state(self, state: dict[str: Any]) -> None: """ Sets the register state to one given in dict. """ super().set_state(state) - self.bit_length = state["bit_length"] - self.mask = 2**self.bit_length -1 + if "bit_length" in state: + self.bit_length = state["bit_length"] + self.mask = 2**self.bit_length -1 def reset(self) -> None: self.value = 0 diff --git a/src/simudator/processor/mia/micro_memory.py b/src/simudator/processor/mia/micro_memory.py index 55a283b46bb4af931fda22aa5c3f7551773bab11..578d8fc53492f19ec5b518cffbb7dc16d421847c 100644 --- a/src/simudator/processor/mia/micro_memory.py +++ b/src/simudator/processor/mia/micro_memory.py @@ -1,3 +1,5 @@ +from typing import Any + from simudator.core.module import Module from simudator.core.signal import Signal @@ -262,10 +264,16 @@ class MicroMemory(Module): state["halt"] = self.halt return state + def get_gui_state(self) -> dict[str, Any]: + state = super().get_state() + state["memory"] = self.memory[:] + return state + def set_state(self, state: dict) -> None: super().set_state(state) self.memory = state["memory"] - self.halt = state["halt"] + if "halt" in state: + self.halt = state["halt"] def get_input_signals(self) -> [Signal]: return [self.upc_s, diff --git a/src/simudator/processor/mia/micro_pc.py b/src/simudator/processor/mia/micro_pc.py index f9572bd23814e843f1c5a479c22d9ff8a1f3158d..f95e1d426f7f25852c6ade71d5a88bdf9af2d1d0 100644 --- a/src/simudator/processor/mia/micro_pc.py +++ b/src/simudator/processor/mia/micro_pc.py @@ -19,16 +19,19 @@ class MicroPC(Module): from_supc: Signal, to_um: Signal, from_um: Signal, + bit_length: int = 8, name: str = "uPC") -> None: super().__init__(name) + self.value = 0 + self.bit_length = bit_length + # Input signals self.control_signal = control_signal self.from_k1 = from_k1 self.from_k2 = from_k2 self.from_supc = from_supc self.from_um = from_um - self.value = 0 # Output signals self.to_supc = to_supc @@ -70,12 +73,21 @@ class MicroPC(Module): def get_state(self) -> dict: state = super().get_state() state["value"] = self.value + state["bit_length"] = self.bit_length return state + def get_gui_state(self) -> dict: + state = { + "name": self.name, + "value": self.value, + } + return state def set_state(self, state: dict) -> None: super().set_state(state) self.value = state["value"] + if "bit_length" in state: + self.bit_length = state["bit_length"] def reset(self) -> None: """ diff --git a/src/simudator/processor/mia/pc.py b/src/simudator/processor/mia/pc.py index f063667be747e2aca7965d3528bf1391bfb95fa2..ceb8b1429390a54320a8265cda6a26f8b7089136 100644 --- a/src/simudator/processor/mia/pc.py +++ b/src/simudator/processor/mia/pc.py @@ -91,6 +91,14 @@ class PC(Module, MiaBusConnector): state["name"] = self.name state["value"] = self.value state["increment"] = self.increase_by_one + state["bit_length"] = 8 + return state + + def get_gui_state(self) -> dict: + state = { + "name": self.name, + "value": self.value, + } return state def set_state(self, state: dict[str: Any]) -> None: @@ -99,7 +107,8 @@ class PC(Module, MiaBusConnector): """ self.name = state["name"] self.value = state["value"] - self.increase_by_one = state["increment"] + if "increment" in state: + self.increase_by_one = state["increment"] def reset(self) -> None: """