diff --git a/src/simudator/gui/cpu_graphics_scene.py b/src/simudator/gui/cpu_graphics_scene.py index a64e417b1dfa6a4b9d834bb031373a2f9364a3f1..60a5072200e9cee55cc295990f1ed7204e181cdf 100644 --- a/src/simudator/gui/cpu_graphics_scene.py +++ b/src/simudator/gui/cpu_graphics_scene.py @@ -4,19 +4,10 @@ from json.decoder import JSONDecodeError from qtpy.QtCore import QPointF from qtpy.QtCore import Signal as pyqtSignal from qtpy.QtCore import Slot -from qtpy.QtWidgets import ( - QErrorMessage, - QFileDialog, - QGraphicsItem, - QGraphicsScene, - QMessageBox, -) - -from simudator.core.processor import Processor +from qtpy.QtWidgets import QErrorMessage, QFileDialog, QGraphicsScene, QMessageBox + from simudator.gui.color_scheme import ColorScheme -from simudator.gui.module_graphics_item.module_graphics_item import ModuleGraphicsItem -from simudator.gui.orientation import Orientation -from simudator.gui.port_graphics_item import PortGraphicsItem +from simudator.gui.module_graphics_item.module_widget import ModuleWidget from simudator.gui.signal_graphics_item import SignalGraphicsItem @@ -32,8 +23,8 @@ class CpuGraphicsScene(QGraphicsScene): def __init__(self): super().__init__() - self._module_graphics_items = dict() - self._signal_graphics_items = [] + self._modules: dict[str, ModuleWidget] = {} + self._signals: list[SignalGraphicsItem] = [] self._error_msg_box = QErrorMessage() self.setBackgroundBrush(ColorScheme.Window) @@ -42,49 +33,24 @@ class CpuGraphicsScene(QGraphicsScene): Reset all graphical signals to their default visual representation when initialised. """ - for graphics_signal in self._signal_graphics_items: + for graphics_signal in self._signals: graphics_signal.reset() - def add_module(self, item: ModuleGraphicsItem) -> None: - """ - Add a graphical module item to the processor scene at a position - according to the default layout. - - Parameters - ---------- - item : ModuleGraphicsItem - Graphical module item to add to the scene. + def add_module_widget(self, widget: ModuleWidget) -> None: """ - self._module_graphics_items[item.name] = item - self._place_module_default(item) + Add a module widget to the processor scene. - def _place_module_default(self, item: ModuleGraphicsItem) -> None: - """ - Place a graphical module item at a position according to the default - layout, i.e. placing all module items along a diagonal. + Module widgets are placed by default along a diagonal. Parameters ---------- - item : ModuleGraphicsItem - """ - placement = len(self._module_graphics_items) * self.MODULE_SPACEING - item.setPos(placement, placement) - self.addItem(item) - - def move_module_to(self, item: ModuleGraphicsItem, pos_x: int, pos_y: int) -> None: + widget : ModuleWidget + Module widget to add to the scene. """ - Place an existing graphical module item at some position. - - Parameters - ---------- - item : ModuleGraphicsItem - Graphical module item to place at a position. - pos_x : int - Position on x-axis to place the module item at. - pos_y : int - Position on y-axis to place the module item at. - """ - item.setPos(pos_x * self.MODULE_SPACEING, pos_y * self.MODULE_SPACEING) + self._modules[widget.get_name()] = widget + self.addItem(widget) + placement = len(self._modules) * self.MODULE_SPACEING + widget.setPos(placement, placement) def add_all_signals(self) -> None: """ @@ -95,7 +61,7 @@ class CpuGraphicsScene(QGraphicsScene): # (Every port keeps a reference to a simulation signal which has # a name) signal_to_ports = {} - for module_w in self._module_graphics_items.values(): + for module_w in self._modules.values(): ports = module_w.getPorts() for port in ports: s_name = port.getSignalName() @@ -111,49 +77,26 @@ class CpuGraphicsScene(QGraphicsScene): port_1 = module_graphics_items[0] port_2 = module_graphics_items[1] signal_w = SignalGraphicsItem(port_1, port_2) - self._signal_graphics_items.append(signal_w) + self._signals.append(signal_w) self.addItem(signal_w) port_1.moved.connect(signal_w.move) port_2.moved.connect(signal_w.move) port_1.toggled.connect(signal_w.toggleVisibility) port_2.toggled.connect(signal_w.toggleVisibility) - def get_modules(self) -> list[ModuleGraphicsItem]: - """ - Get a list of all graphical module items in the scene. - - Returns - ------- - list[ModuleGraphicsItem] - List of graphical module items in the scene. - """ - return list(self._module_graphics_items.values()) - - def get_signals(self) -> list[SignalGraphicsItem]: - """ - Get a list of all graphical signal items in the scene. - - Returns - ------- - list[SignalGraphicsItem] - List of graphical signal items in the scene. - """ - return self._signal_graphics_items - - def mousePressEvent(self, event): - super().mousePressEvent(event) - @Slot() def load_layout(self) -> None: """ Prompt the user for a layout file and load the layout from the file. + + If at any point this function would fail, the default layout + is loaded instead. """ # Prompt the user for a file dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptOpen) - dialog.setDirectory("~/simudator") # TODO: does this work when exported? path = dialog.getOpenFileName()[0] # If no file was selected, do nothing @@ -175,23 +118,6 @@ class CpuGraphicsScene(QGraphicsScene): self.parent(), "SimuDator", "File loaded succesfully." ) - def _save_layout_to_file(self, file_path: str) -> None: - """ - Save the layout of the scene to file. - - Parameters - ---------- - file_path : str - Path to the file to save to layout to. - """ - layout_str = "" - for graphics_item in self._module_graphics_items.values(): - layout_str += graphics_item.save_state_as_str() + "\n" - - file = open(file_path, "w") - file.write(layout_str) - file.close() - @Slot(bool) def show_all_signals(self, value: bool) -> None: """ @@ -202,7 +128,7 @@ class CpuGraphicsScene(QGraphicsScene): value : bool ``True`` to show all graphical signals, ``False`` to hide them. """ - for item in self._signal_graphics_items: + for item in self._signals: item.setVisible(value) @Slot(bool) @@ -216,7 +142,7 @@ class CpuGraphicsScene(QGraphicsScene): value : bool ``True`` to show the port names, ``False`` to hide them. """ - for item in self._module_graphics_items.values(): + for item in self._modules.values(): for port in item.ports: port.setNameVisibility(value) @@ -231,12 +157,11 @@ class CpuGraphicsScene(QGraphicsScene): ``True`` to lock the layout, ``False`` to unlock it. """ - for item in self._module_graphics_items.values(): - item.setFlag(QGraphicsItem.ItemIsMovable, not value) - item.setLocked(value) + for widget in self._modules.values(): + widget.set_is_locked(value) - for item in self._signal_graphics_items: - item.setFlag(QGraphicsItem.ItemIsMovable, not value) + for item in self._signals: + item.setFlag(item.GraphicsItemFlag.ItemIsMovable, not value) # We use this value so lines in the signal can not be moved or edited item.is_locked = value @@ -244,7 +169,8 @@ class CpuGraphicsScene(QGraphicsScene): @Slot() def save_layout(self) -> None: """ - Prompt the user for a file and save the scene layout to the file. + Prompt the user for a file and save the scene layout to the + selected file. This overwrites the previous content of the file. """ @@ -255,34 +181,31 @@ class CpuGraphicsScene(QGraphicsScene): path = dialog.getSaveFileName()[0] # Open the given file erasing the previous content - with open(path, "w") as fp: - graphics_modules_data = {} - ports_data = {} - graphics_signals_data = {} - - graphics_modules = self.get_modules() - for graphics_module in graphics_modules: - pos = (graphics_module.x(), graphics_module.y()) - graphics_modules_data[graphics_module.getName()] = pos - - for port in graphics_module.getPorts(): - visibility = port.isVisible() - orientation = int(port.getOrientation()) - data = (port.x(), port.y(), orientation, visibility) - ports_data[port.getID()] = data - - for graphics_signal in self.get_signals(): - visibility = graphics_signal.isVisible() - points = [] - for point in graphics_signal.getPoints(): - points.append((point.x(), point.y())) - data = (points, visibility) - graphics_signals_data[graphics_signal.getID()] = data - - data = (graphics_modules_data, ports_data, graphics_signals_data) - json.dump(data, fp) - - fp.close() + try: + with open(path, "w") as fp: + module_data = {} + signal_data = {} + + for name, module in self._modules.items(): + module_data[name] = module.save_layout_data() + + for graphics_signal in self._signals: + visibility = graphics_signal.isVisible() + points = [] + for point in graphics_signal.getPoints(): + points.append((point.x(), point.y())) + data = (points, visibility) + signal_data[graphics_signal.getID()] = data + + json.dump( + { + "module_data": module_data, + "signal_data": signal_data, + }, + fp, + ) + except OSError: + self._error_msg_box.showMessage("Failed to load layout.", "save_layout_err") @Slot() def load_default_layout(self) -> None: @@ -291,58 +214,38 @@ class CpuGraphicsScene(QGraphicsScene): layout, i.e. along a diagonal. """ counter = 0 - for key in self._module_graphics_items: - module_graphic = self._module_graphics_items[key] - module_graphic.showPorts() + for widget in self._modules.values(): counter += 1 - self.move_module_to(module_graphic, counter, counter) + widget.setPos( + counter * self.MODULE_SPACEING, counter * self.MODULE_SPACEING + ) + self.reset_signals() def load_layout_from_file(self, file_path: str) -> None: """ Load a layout from a file. - If at anypoint this function would error, the default layout - is loaded instead. - Parameters ---------- file_path : str Path to a file containing a layout for the processor scene. """ - graphics_modules = self._module_graphics_items - ports = {} - graphics_signals = {} - - for graphics_module in graphics_modules.values(): - for port in graphics_module.getPorts(): - ports[port.getID()] = port + signals = {} - for graphics_signal in self.get_signals(): - graphics_signals[graphics_signal.getID()] = graphics_signal + for graphics_signal in self._signals: + signals[graphics_signal.getID()] = graphics_signal # Open the file in 'read-only' with open(file_path, 'rb') as fp: data = json.load(fp) - graphics_modules_data = data[0] - ports_data = data[1] - graphics_signals_data = data[2] - for g_module_name, g_module_data in graphics_modules_data.items(): - g_module = graphics_modules[g_module_name] - x = g_module_data[0] - y = g_module_data[1] - self._load_module(g_module, x, y) + for module_name, module_data in data["module_data"].items(): + self._modules[module_name].load_layout_data(module_data) - for port_id, port_data in ports_data.items(): - port = ports[int(port_id)] - self._load_port(port, *port_data) - - for g_signal_id, g_signal_data in graphics_signals_data.items(): - g_signal = graphics_signals[int(g_signal_id)] - self._load_signal(g_signal, *g_signal_data) - - fp.close() + for signal_id, signal_data in data["signal_data"]: + signal = signals[int(signal_id)] + self._load_signal(signal, *signal_data) def _load_signal( self, @@ -372,56 +275,3 @@ class CpuGraphicsScene(QGraphicsScene): # Set the new points signal.setPoints(qpoints) signal.setVisible(visibility) - - def _load_module( - self, - module: ModuleGraphicsItem, - pos_x: float, - pos_y: float, - ) -> None: - """ - Set the position of a graphical module in the scene. Helper method - for loading a layout from file. - - Parameters - ---------- - module : ModuleGraphicsItem - Graphical module of which to set the position. - pos_x : float - Position on the x-axis in the scene. - pos_y : float - Position on the y-axis in the scene. - """ - module.setX(pos_x) - module.setY(pos_y) - - def _load_port( - self, - port: PortGraphicsItem, - pos_x: float, - pos_y: float, - orientation: Orientation, - visibility: bool, - ) -> None: - """ - Set position, orientation and visibility of a port of a graphical - module. Helper method for loading a layout from file. - - Parameters - ---------- - port : PortGraphicsItem - Port to modify. - pos_x : float - Position on the x-axis in the scene. - pos_y : float - Position on the y-axis in the scene. - orientation : Orientation - Orientation of the port. - visibility : bool - Visibility of the port. ``True`` to show the port, ``False`` to - hide it. - """ - port.setOrientation(orientation) - port.setX(pos_x) - port.setY(pos_y) - port.setVisible(visibility) diff --git a/src/simudator/gui/gui.py b/src/simudator/gui/gui.py index 63c39edcea6018b47973b3e2fa9edb5997e1d0e6..75885705fb35e823c1c3f032e5fb147fa8d5b922 100644 --- a/src/simudator/gui/gui.py +++ b/src/simudator/gui/gui.py @@ -282,19 +282,10 @@ class GUI(QMainWindow): dlg.setText(message) dlg.exec() - def add_module_graphics_item(self, item: ModuleGraphicsItem) -> None: - """ - Add a module graphics item to the graphics scene and connect its - QT signals and slots. - """ - self._graphics_scene.add_module(item) - self.connectModuleActions(item.getActionSignals()) - self._processor_handler.changed.connect(item.update) - def add_module_widget(self, widget: ModuleWidget) -> None: """ Add a module widget to the processor scene and connect its QT signals - and slots. + and slots appropriately. Parameters ---------- @@ -302,7 +293,7 @@ class GUI(QMainWindow): The module widget to add to the processor scene. """ self._processor_handler.changed.connect(widget.update) - self._graphics_scene.addItem(widget) + self._graphics_scene.add_module_widget(widget) widget.state_changed.connect(self._processor_handler.handle_module_change) def add_all_signals(self) -> None: diff --git a/src/simudator/gui/module_graphics_item/actions.py b/src/simudator/gui/module_graphics_item/actions.py index c1abb1f5f37d1f974e2816e03fe39a8af5e1a6c8..1e4bb49a7d35d4b9ba0589e0dc7acc04d4db4f66 100644 --- a/src/simudator/gui/module_graphics_item/actions.py +++ b/src/simudator/gui/module_graphics_item/actions.py @@ -49,13 +49,15 @@ def edit_state_action(module: Module, module_widget: ModuleWidget) -> QAction: def toggle_ports_action(module_widget: ModuleWidget) -> QAction: """ Create a QAction for toggling the visibility of port widgets of a module - widget. + widget. The action is connected to the ``locked`` signal of the module + widget to enable or disable the action when the module is locked or + unlocked. Parameters ---------- module_widget : ModuleWidget - The module for which its ports should be toggled to visible or invisible - using a QAction. + The module for which its ports should be toggled to visible or + invisible using a QAction. Returns ------- @@ -63,5 +65,5 @@ def toggle_ports_action(module_widget: ModuleWidget) -> QAction: """ action = QAction("Toggle ports", module_widget) action.triggered.connect(module_widget.toggle_ports) + module_widget.locked.connect(action.setDisabled) return action - diff --git a/src/simudator/gui/module_graphics_item/module_widget.py b/src/simudator/gui/module_graphics_item/module_widget.py index 53bfaf40c443c01069d313908f2fc630c89b69df..37a6e26bb54221fc24a0696c8e21e1257a4cf980 100644 --- a/src/simudator/gui/module_graphics_item/module_widget.py +++ b/src/simudator/gui/module_graphics_item/module_widget.py @@ -1,3 +1,5 @@ +from typing import Any + from qtpy.QtCore import Property, QRectF, Qt from qtpy.QtCore import Signal as pyqtSignal from qtpy.QtCore import Slot @@ -53,6 +55,7 @@ class ModuleWidget(QGraphicsWidget): _DEFAULT_PADDING = 5 state_changed = pyqtSignal() + locked = pyqtSignal(bool) def __init__( self, @@ -78,6 +81,8 @@ class ModuleWidget(QGraphicsWidget): self._text_font = self._DEFAULT_TEXT_FONT self._padding = self._DEFAULT_PADDING + self._is_locked = False + # Set the size of the module depending on the number of state variables width = self._DEFAULT_WIDTH height = self._DEFAULT_HEIGHT @@ -196,6 +201,18 @@ class ModuleWidget(QGraphicsWidget): menu.addActions(self.actions()) menu.exec_(event.screenPos()) + def get_name(self) -> str: + """ + Return the name of this module widget. This is the same name as that of + the module that the widget displays. + + Returns + ------- + str + The name of the module widget. + """ + return self._module.get_state()["name"] + def get_state_vars(self) -> dict[str, FormatInfo]: """ Return a mapping from displayed state variables of the displayed @@ -211,6 +228,39 @@ class ModuleWidget(QGraphicsWidget): """ return self._state_vars + def is_locked(self) -> bool: + """ + Return ``True`` if the module widget is locked, otherwise ``False`` is + returned. + + Returns + ------- + bool + ``True`` if locked, ``False`` otherwise. + """ + return self._is_locked + + def set_is_locked(self, value: bool) -> None: + """ + Set whether the module widget is locked or not. Locking a module widget + makes it unmoveable and emits the ``locked`` signal. Locking a module + widget also locks its port widgets. + + A module widget is not locked by default. + + Parameters + ---------- + value : bool + ``True`` to lock the module widget, ``False`` to unlock it. + """ + self._is_locked = value + self.setFlag(QGraphicsItem.ItemIsMovable, not value) + + for port in self._port_widgets: + port.set_is_locked(value) + + self.locked.emit(value) + @Slot() def set_format(self, state_var: str, format: Format) -> None: """ @@ -229,6 +279,42 @@ class ModuleWidget(QGraphicsWidget): self._state_vars[state_var].selected_format = format self.update() + def save_layout_data(self) -> dict[str, Any]: + """ + Return information about the module widget that is relevant for its + presentation in a processor scene. + + Returns + ------- + dict[str, Any] + Dictionary containing layout-relevant data about the module widget. + """ + port_data = [port.save_layout_data() for port in self._port_widgets] + return { + "x": self.x(), + "y": self.y(), + "ports": port_data, + } + + def load_layout_data(self, data: dict[str, Any]) -> None: + """ + Load layout-relevant information about the module widget. The provided + data should contain x- and y-position and a list of port layout data as + the keys "x", "y" and "ports", respectively. + + Parameters + ---------- + data : dict[str, Any] + Dictionary containing layout data about the port widget. + + """ + self.setX(data["x"]) + self.setY(data["y"]) + + port_data = data["ports"] + for i, port in enumerate(self._port_widgets): + port.load_layout_data(port_data[i]) + def outline_width(self) -> float: """Return the outline pen width. diff --git a/src/simudator/gui/port_widget.py b/src/simudator/gui/port_widget.py index b35555f3a0de8563b985d8eff0dde463d2c36740..d087eb3eba156da3f43b99b3a9f5e300a1d78d2d 100644 --- a/src/simudator/gui/port_widget.py +++ b/src/simudator/gui/port_widget.py @@ -1,4 +1,5 @@ from enum import IntEnum +from typing import Any from qtpy.QtCore import Property, QPointF, QRectF, Qt from qtpy.QtCore import Signal as pyqtSignal @@ -80,6 +81,8 @@ class PortWidget(QGraphicsWidget): self.set_label_visible(True) self.set_text_font(self._DEFAULT_TEXT_FONT) + self._is_locked = False + self.setFlag(QGraphicsItem.ItemIsMovable) def paint( @@ -168,6 +171,33 @@ class PortWidget(QGraphicsWidget): return QRectF(x, y, text_width, text_height) + def is_locked(self) -> bool: + """ + Return ``True`` if the port widget is locked, otherwise ``False`` is + returned. + + Returns + ------- + bool + ``True`` if locked, ``False`` otherwise. + """ + return self._is_locked + + def set_is_locked(self, value: bool) -> None: + """ + Set whether the port widget is locked or not. Locking a port widget + makes it unmoveable and disables the actions in the context menu. + + A port widget is not locked by default. + + Parameters + ---------- + value : bool + ``True`` to lock the port widget, ``False`` to unlock it. + """ + self._is_locked = value + self.setFlag(self.GraphicsItemFlag.ItemIsMovable, not value) + def shape(self) -> QPainterPath: path = QPainterPath() path.addRect(self.boundingRect()) @@ -212,13 +242,13 @@ class PortWidget(QGraphicsWidget): menu = QMenu() hide_signal_action = QAction("Toggle signal visibility", menu) hide_signal_action.triggered.connect(self.signal_toggled) - # hide_signal_action.setEnabled(not self.isEnabled) + hide_signal_action.setDisabled(self._is_locked) hide_port_action = QAction("Toggle port visibility", menu) hide_port_action.triggered.connect( lambda: self.setVisible(not self.isVisible()) ) - # hide_port_action.setEnabled(not self.isLocked) + hide_port_action.setDisabled(self._is_locked) menu.addAction(hide_signal_action) menu.addAction(hide_port_action) @@ -257,6 +287,38 @@ class PortWidget(QGraphicsWidget): self.set_orientation(Orientation.UP) self.update(self.boundingRect()) + def save_layout_data(self) -> dict[str, Any]: + """ + Return information about the port widget that is relevant for its + presentation in a processor scene. + + Returns + ------- + dict[str, Any] + Dictionary containing layout-relevant data about the port widget. + """ + return { + "x": self.x(), + "y": self.y(), + "label_visible": self.label_visible, + } + + def load_layout_data(self, data: dict[str, Any]) -> None: + """ + Load layout-relevant information about the port widget. The provided + data should contain x- and y-position and label visibility as the + keys "x", "y" and "label_visible", respectively. + + Parameters + ---------- + data : dict[str, Any] + Dictionary containing layout data about the port widget. + + """ + self.setX(data["x"]) + self.setY(data["y"]) + self.set_label_visible(data["label_visible"]) + def line_length(self) -> float: """ Return the length of the port line. diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py index eb52e58dabea5bc3e02b62ac1e12a4511046c7d5..cbf307b5f37c76406a5166d12d9dc3c8a5dad0d1 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -1,9 +1,16 @@ import sys from simudator.cli.cli import CLI +from simudator.core.module import Module from simudator.core.modules.integer_register import IntegerRegister from simudator.core.processor import Processor, Signal +from simudator.gui.formatting import Format, FormatInfo from simudator.gui.gui import GUI +from simudator.gui.module_graphics_item.actions import ( + edit_state_action, + toggle_ports_action, +) +from simudator.gui.module_graphics_item.module_widget import ModuleWidget from simudator.processor.mia.gui import ( AluGraphicsItem, ArGraphicsItem, @@ -320,6 +327,22 @@ class MIA_CPU(Processor): micro_memory_state = self._micro_memory.get_state() return micro_memory_state["halt"] + def _create_register_widget(self, module: Module) -> ModuleWidget: + bit_length = module.get_parameter()["bit_length"] + state_vars = { + "value": FormatInfo( + FormatInfo.NUMERICAL_FORMATS, Format.Hex, bit_length=bit_length + ) + } + widget = ModuleWidget(module, state_vars, []) + widget.addActions( + [ + edit_state_action(module, widget), + toggle_ports_action(widget), + ] + ) + return widget + def launch_gui(self): from qtpy import QtCore from qtpy.QtWidgets import QApplication @@ -330,64 +353,52 @@ class MIA_CPU(Processor): self.reset() gui = GUI(self) - asr = self.get_module("ASR") - ir = self.get_module("IR") - pm = self.get_module("PM") + bus = self.get_module("Bus") + upc = self.get_module("uPC") + supc = self.get_module("SuPC") pc = self.get_module("PC") - alu = self.get_module("ALU") ar = self.get_module("AR") + asr = self.get_module("ASR") hr = self.get_module("HR") + um = self.get_module("uM") + alu = self.get_module("ALU") grx = self.get_module("GRx") + ir = self.get_module("IR") + pm = self.get_module("PM") + k1 = self.get_module("K1") + k2 = self.get_module("K2") lc = self.get_module("LC") - - bus_signal_pairs = [ - (asr.signals["in_content"], None), - (ir.signals["in_input"], ir.signals["out_output"]), - (pm.signals["in_input"], pm.signals["out_content"]), - (None, None), - (pc.signals["in_input"], pc.signals["out_content"]), - (None, None), - (alu.signals["in_input_bus"], None), - (None, None), - (None, ar.signals["out_content"]), - (None, None), - (hr.signals["in_content"], hr.signals["out_content"]), - (None, None), - (grx.signals["in_input"], grx.signals["out_content"]), - ] - - gui.add_module_graphics_item( - BusGraphicsItem(self.get_module("Bus"), bus_signal_pairs) - ) - gui.add_module_graphics_item(uPcGraphicsItem(self.get_module("uPC"))) - gui.add_module_graphics_item(SupcGraphicsItem(self.get_module("SuPC"))) - gui.add_module_graphics_item(PcGraphicsItem(self.get_module("PC"))) - gui.add_module_graphics_item(ArGraphicsItem(self.get_module("AR"))) - gui.add_module_graphics_item(AsrGraphicsItem(self.get_module("ASR"))) - gui.add_module_graphics_item(HrGraphicsItem(self.get_module("HR"))) - gui.add_module_graphics_item(MicroMemoryGraphicsItem(self.get_module("uM"))) - gui.add_module_graphics_item(AluGraphicsItem(self.get_module("ALU"))) - gui.add_module_graphics_item(GrxGraphicsItem(self.get_module("GRx"))) - gui.add_module_graphics_item(IrGraphicsItem(self.get_module("IR"))) - - flag_modules = ["Z-Flag", "N-Flag", "C-Flag", "O-Flag", "L-Flag", "LC"] - for name in flag_modules: - module = self.get_module(name) - widget = FlagGraphicsItem(module) - gui.add_module_graphics_item(widget) + z_flag = self.get_module("Z-Flag") + n_flag = self.get_module("N-Flag") + c_flag = self.get_module("C-Flag") + o_flag = self.get_module("O-Flag") + + registers = [ar, asr, hr, supc, z_flag, n_flag, c_flag, o_flag] + for register in registers: + gui.add_module_widget(self._create_register_widget(register)) + + # bus_signal_pairs = [ + # (asr.signals["in_content"], None), + # (ir.signals["in_input"], ir.signals["out_output"]), + # (pm.signals["in_input"], pm.signals["out_content"]), + # (None, None), + # (pc.signals["in_input"], pc.signals["out_content"]), + # (None, None), + # (alu.signals["in_input_bus"], None), + # (None, None), + # (None, ar.signals["out_content"]), + # (None, None), + # (hr.signals["in_content"], hr.signals["out_content"]), + # (None, None), + # (grx.signals["in_input"], grx.signals["out_content"]), + # ] gui.add_signal_viewer(lc.signals["out_flag_l"], "L") - memory_modules = ["PM", "K1", "K2"] - for name in memory_modules: - module = self.get_module(name) - widget = MiaMemoryGraphicsItem(module) - gui.add_module_graphics_item(widget) - - gui.add_all_signals() + # gui.add_all_signals() gui.show() - gui.load_layout("mia_layout") + # gui.load_layout("mia_layout") app.exec() def launch_cli(self):