diff --git a/src/simudator/cli/cli.py b/src/simudator/cli/cli.py
index 8cece34ab1733200d85c52e342092bc5f697c8fc..25017547485eddca37d2b7846442f12c377d712f 100644
--- a/src/simudator/cli/cli.py
+++ b/src/simudator/cli/cli.py
@@ -3,6 +3,7 @@ from __future__ import annotations
 import ast
 from os.path import exists, isdir
 
+from simudator.cli.printing import pretty_print, pretty_print_verbose
 from simudator.core.processor import Processor
 
 HELP_TEXT = """Here is a list of possible commands:
@@ -195,12 +196,12 @@ class CLI:
 
                 case ["pp"] | ["pretty print"]:
                     # pretty print the modules of the processor
-                    self._processor.pretty_print()
+                    pretty_print(self._processor)
 
                 case ["ppv"] | ["pretty print verbose"]:
                     # pretty print the modules of the processor
                     # with all available information
-                    self._processor.pretty_print_verbose()
+                    pretty_print_verbose(self._processor)
 
                 # Breakpoints -------------------------------------------------
                 case ["p", "br"] | ["print", "breaks"]:
diff --git a/src/simudator/cli/printing.py b/src/simudator/cli/printing.py
new file mode 100644
index 0000000000000000000000000000000000000000..42530c15ce3f01555278069070a2a8767fafb0af
--- /dev/null
+++ b/src/simudator/cli/printing.py
@@ -0,0 +1,262 @@
+from simudator.core.module import Module
+from simudator.core.modules.memory import Memory
+from simudator.core.processor import Processor
+from simudator.processor.mia.modules.bus import Bus
+from simudator.processor.mia.modules.micro_memory import MicroMemory
+
+
+def pretty_print(processor: Processor) -> None:
+    """Print the processor state in a readable and compact format."""
+    pretty_print_verbose(processor, processor._ignore_keys)
+
+
+def pretty_print_verbose(
+    processor: Processor, ignore_keys: list[str] | None = None
+) -> None:
+    """
+    Print the most relevant information about each module in a compact and
+    readable format.
+
+    State variables of modules can be ignored with the optional argument.
+
+    Parameters
+    ----------
+    ignore_keys : list[str]
+        List of names of state variables of modules to exclude when
+        printing module states.
+    """
+    # TODO: ignore keys per module and not for all modules
+    memory_modules = []
+    other_modules = []
+
+    if ignore_keys is None:
+        ignore_keys = []
+
+    # TODO: remove isinstance(module, micro_memory)
+    for module in processor.get_modules():
+        if not isinstance(module, Bus):
+            if isinstance(module, Memory) or isinstance(module, MicroMemory):
+                memory_modules.append(module)
+            else:
+                other_modules.append(module)
+
+    # sort the modules by name to ensure that they appear in the
+    # same order
+    memory_modules.sort(key=lambda x: x.name, reverse=True)
+    other_modules.sort(key=lambda x: x.name, reverse=True)
+
+    # specify which keys to ignore from the modules 'get_state'
+    # function
+    # TODO: ignore fields per module, this will ignore 'mask'
+    # for every module
+
+    module_to_line_length = {}
+    # get the longest line length for all other_modules
+    for module in other_modules:
+        # +3 for padding
+        line_len = module.get_longest_line_len(ignore_keys) + 3
+
+        # TODO: what to do if two or more modules has the same name
+        module_to_line_length[module] = line_len
+
+    groups = group_pp_modules(module_to_line_length)
+
+    print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
+
+    # print each group separate
+    for group in groups:
+        pretty_print_names(group)
+
+        # Build a new string containing the information to show
+        # the user
+        for row in range(get_most_fields(group, ignore_keys)):
+            string = ""
+            total_padding = 0
+
+            # Get the information from each module
+            for module in group:
+                module_state = module.get_state()
+                keys = fields_to_list(module)
+
+                # Get the keys that we want to print to the user
+                # If this is not done, the keys we want to print
+                # could end up on an index that is higher than the
+                # number of rows printed and will therefore be missed
+                real_keys = [key for key in keys if key not in ignore_keys]
+
+                # Dont go out of index
+                # Needed since one module might want to print 4
+                # fields and another only 1
+                if row < len(real_keys) and real_keys[row] not in ignore_keys:
+                    string += real_keys[row] + ": " + str(module_state[real_keys[row]])
+
+                # pad the string so each string has the same length
+                total_padding += module_to_line_length[module]
+                string = string.ljust(total_padding)
+                # replace last to chars with a separator and padding
+                string = string[0:-2] + "| "
+
+            print(string)
+        print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
+
+    for memory_module in memory_modules:
+        pretty_print_memory(memory_module)
+
+
+def pretty_print_memory(module: Memory) -> None:
+    """Print a memory module in a compact and readable format.
+
+    Parameters
+    ----------
+    module : Memory
+        Memory module to print the state of.
+    """
+    print(module.name)
+    print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
+
+    longest_line_len = module.get_longest_line_len()
+    # longest_line_len = processor.get_longest_memory_value(module.memory)
+    string = ""
+    last_mem_len = module.get_largest_mem_adr()
+
+    for i, value in enumerate(module.get_state()["memory"]):
+
+        # create a new string containing the address and the value
+        # of the memory address formatted to fit with the largest
+        # address and largest memory value
+        new_row = (str(i).ljust(last_mem_len) + ": " + str(value)).ljust(
+            longest_line_len + last_mem_len + 3
+        ) + "|"
+
+        # only add the string if there is space for it, else
+        # print the string and start a new
+        if len(string + new_row) + 1 > Processor.MAX_LINE_LEN:
+            print(string)
+            string = new_row
+        else:
+            # First iteration string will be
+            # empty and should not be padded
+            if string:
+                string += " " + new_row
+            else:
+                string = new_row
+    print(string)
+    print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
+    print()
+
+
+def pretty_print_names(module_to_line_length: dict[Module, int]) -> None:
+    """
+    Print the name of the modules in one row with formatting.
+
+    Adds spacing between the names so that the longest state variable of
+    each module has space to be printed below the name.
+
+    Parameters
+    ----------
+    module_to_line_length : dict[Module, int]
+        Mapping from module to length of the longest state variable of
+        the module.
+    """
+    name_string = ""
+    total_len = 0
+    for module in module_to_line_length:
+        name_string += module.name
+        total_len += module_to_line_length[module]
+        name_string = name_string.ljust(total_len)
+        name_string = name_string[0:-2] + "| "
+
+    print(name_string)
+
+
+def group_pp_modules(
+    module_to_line_length: dict[Module, int]
+) -> list[dict[Module, int]]:
+    """Group the modules to be pretty printed into groups with a
+    total line length lower than 'Processor.MAX_LINE_LEN'.
+
+    Parameters
+    ----------
+    module_to_line_length : dict[Module, int]
+        Mapping from module to length of the longest state variable of
+        the module (takes as the line length).
+
+    Returns
+    -------
+    list[dict[Module, int]]
+        List of mappings from module to line length, each mapping
+        representing a group of modules for printing.
+    """
+
+    groups = [{}]
+    group_index = 0
+    line_len = 0
+    for module in module_to_line_length:
+
+        # Make sure the line is not to long
+        if line_len + module_to_line_length[module] < Processor.MAX_LINE_LEN:
+            line_len += module_to_line_length[module]
+            groups[group_index][module] = module_to_line_length[module]
+
+        # If it would have been, start a new group
+        else:
+            groups.append({})
+            group_index += 1
+            groups[group_index][module] = module_to_line_length[module]
+            line_len = module_to_line_length[module]
+    return groups
+
+
+def fields_to_list(module: Module, ignore_keys=[]) -> list[str]:
+    """
+    Return a list containing all state variable names, excluding module
+    name, for a module.
+    Optional argument to ignore specific state variables.
+
+    Parameters
+    ----------
+    module : Module
+        Module to get state variable names from.
+    ignore_keys : list[str]
+        List of state variable names to exclude.
+
+    Returns
+    -------
+    list[str]
+        List of state variable names, excluding module name, of a module.
+    """
+    return [
+        key for key in module.get_state() if key != "name" and key not in ignore_keys
+    ]
+
+
+def get_most_fields(modules: dict[Module, int], ignore_keys=None) -> int:
+    """Get the maximum number of state variables among all modules.
+
+    Can optionally ignore keys.
+
+    Parameters
+    ----------
+    modules : dict[Module, int]
+        Mapping from module to length of the longest state variable of
+        the module. Used as a list of modules to take the maximum over.
+    ignore_keys : list[str]
+        State variables to exclude.
+
+    Returns
+    -------
+    int
+        The maximum of the number of module state variables among all
+        modules of the processor.
+    """
+
+    if ignore_keys is None:
+        ignore_keys = []
+
+    fields = 0
+    for module in modules:
+        module_fields = len(fields_to_list(module, ignore_keys))
+        if module_fields > fields:
+            fields = module_fields
+
+    return fields
diff --git a/src/simudator/core/processor.py b/src/simudator/core/processor.py
index 35044c6cea2684e02ff4bc9e28be9839b3aec122..2485c5389b0f328ace9742e30eb5b25a93e485de 100644
--- a/src/simudator/core/processor.py
+++ b/src/simudator/core/processor.py
@@ -7,9 +7,6 @@ from simudator.core.breakpoint_lambda import LambdaBreakpoint
 from simudator.core.breakpoint_memory import MemoryBreakpoint
 from simudator.core.breakpoint_state import StateBreakpoint
 from simudator.core.module import Module
-from simudator.core.modules.memory import Memory
-from simudator.processor.mia.modules.bus import Bus
-from simudator.processor.mia.modules.micro_memory import MicroMemory
 
 from .signal import Signal
 
@@ -19,30 +16,38 @@ class Processor:
     Main class for controlling the processor.
 
     Uses modules and signals to simulate processor components behaviour.
+
+    Attributes
+    ----------
+    is_stopped : bool
+        Used to indicate that the processor has stopped, e.g. from a halt
+        instruction.
+    breakpoint_reached : bool
+        Used to indicate that the processor has reached a breakpoint at
+        the current clock cycle.
+    last_breakpoint : Breakpoint | None
+        Stores the last reached breakpoint if any.
+
     """
 
     __slots__ = (
-        "modules",
-        "signals",
-        "clock",
-        "update_queue",
-        "module_history",
-        "signal_history",
-        "breakpoint_id_counter",
-        "breakpoints",
+        "_modules",
+        "_signals",
+        "_clock",
+        "_update_queue",
+        "_module_history",
+        "_signal_history",
+        "_breakpoint_id_counter",
+        "_breakpoints",
         "breakpoint_reached",
         "last_breakpoint",
-        "cycles_to_save",
-        "removed_cycles",
-        "max_line_len",
-        "line_separator",
+        "_removed_cycles",
         "is_stopped",
-        "new_instruction",
-        "current_instructions",
-        "ignore_keys",
-        "lambdas",
-        "assembly_cycles",
-        "line_separator",
+        "_new_instruction",
+        "_current_instructions",
+        "_ignore_keys",
+        "_lambdas",
+        "_assembly_cycles",
     )
 
     LINE_SEPARATOR = "-"
@@ -51,47 +56,42 @@ class Processor:
 
     def __init__(self) -> None:
         # For simulation
-        self.modules: dict[str, Module] = dict()
-        self.signals = []
-        self.clock = 0
-        self.update_queue = []
-        self.is_stopped = False
+        self._modules: dict[str, Module] = dict()
+        self._signals: list[Signal] = []
+        self._clock: int = 0
+        self._update_queue: list[Module] = []
+        self.is_stopped: bool = False
 
         # Breakpoint handling
-        self.breakpoint_id_counter = 1
-        self.breakpoints: dict[int, Breakpoint] = {}
-        self.breakpoint_reached = False
-        self.last_breakpoint = None
-        self.lambdas: dict[str, Callable[..., bool]] = {}
+        self._breakpoint_id_counter: int = 1
+        self._breakpoints: dict[int, Breakpoint] = {}
+        self.breakpoint_reached: bool = False
+        self.last_breakpoint: Breakpoint | None = None
+        self._lambdas: dict[str, Callable[..., bool]] = {}
 
         # Saving processor state for saving/loading to file and undoing ticks
-        self.removed_cycles = 0
-        self.assembly_cycles = [0]  # Map asm instruction to clock cycle
-        self.module_history: list[dict[str, dict[str, Any]]] = []
-        self.signal_history: list[list] = []  # TODO: Is this needed?
+        self._removed_cycles: int = 0
+        self._assembly_cycles: list[int] = [0]  # Map asm instruction to clock cycle
+        self._module_history: list[dict[str, dict[str, Any]]] = []
+        self._signal_history: list[list] = []  # TODO: Is this needed?
 
         # For showing which instructions are being done and signalling
         # the start of a new one
-        self.new_instruction = False
+        self._new_instruction: bool = False
 
         # It is the responsibility of the CPU to tell the gui:s pipeline
         # diagram what information to be displayed and how to display it.
         # Thus each CPU keeps track of its current instructions together with
         # each instructions position in the pipeline diagram.
-        self.current_instructions: list[tuple[str, int, int]] = []
+        self._current_instructions: list[tuple[str, int, int]] = []
 
         # TODO: keeping track of what pieces of info not to show
         # show not be done at the processor level.
         # Maybe implement a 'get_pretty_print_state' at module
         # level?
-        self.ignore_keys = [
+        self._ignore_keys: list[str] = [
             "bit_length",
             "mask",
-            "increment",
-            "read_from_bus",
-            "read_from_uADR",
-            "decrement_by_one",
-            "bus_id",
         ]
 
     def do_tick(self) -> None:
@@ -101,25 +101,25 @@ class Processor:
         Also check for breakpoints that are reached in this cycle, and save
         clock cycles when new assembly instructions are started.
         """
-        if len(self.module_history) > self.clock - self.removed_cycles:
+        if len(self._module_history) > self._clock - self._removed_cycles:
             # If a previous stored cycle has been loaded, discard
             # all stored cycles from that cycle and onward in
             # the history of saved cycles
-            self.module_history = self.module_history[0 : self.clock]
-            self.signal_history = self.signal_history[0 : self.clock]
+            self._module_history = self._module_history[0 : self._clock]
+            self._signal_history = self._signal_history[0 : self._clock]
 
         self.unstop()
         self.save_cycle()
-        self.clock += 1
+        self._clock += 1
 
-        for module in self.modules.values():
+        for module in self._modules.values():
             module.update_register()
 
-        for module in self.modules.values():
+        for module in self._modules.values():
             module.output_register()
 
-        while self.update_queue:
-            module = self.update_queue.pop(0)
+        while self._update_queue:
+            module = self._update_queue.pop(0)
             module.update_logic()
 
         self.stop_at_breakpoints()
@@ -129,11 +129,11 @@ class Processor:
         # Set new_instruction and save clock cycle for each
         # new assembly instruction
         if self.is_new_instruction():
-            self.new_instruction = True
-            self.current_instructions = self.get_current_instructions()
-            self.assembly_cycles.append(self.get_clock())
+            self._new_instruction = True
+            self._current_instructions = self.get_current_instructions()
+            self._assembly_cycles.append(self.get_clock())
         else:
-            self.new_instruction = False
+            self._new_instruction = False
 
     def get_current_instructions(self) -> list[tuple[str, int, int]]:
         """Return a list of the current instructions with their positions.
@@ -207,14 +207,14 @@ class Processor:
             Number of assembly instructions to undo.
         """
 
-        current_clock_cycle = self.clock
-        index = len(self.assembly_cycles)
-        saved_cycle = self.assembly_cycles[index - 1]
+        current_clock_cycle = self._clock
+        index = len(self._assembly_cycles)
+        saved_cycle = self._assembly_cycles[index - 1]
 
         # Make sure we are undoing the instruction(s) we are currently on
         while saved_cycle >= current_clock_cycle:
             index -= 1
-            saved_cycle = self.assembly_cycles[index - 1]
+            saved_cycle = self._assembly_cycles[index - 1]
 
         index -= num_instructions
 
@@ -222,7 +222,7 @@ class Processor:
         if index < 0:
             raise IndexError
 
-        clockcycle = self.assembly_cycles[index]
+        clockcycle = self._assembly_cycles[index]
 
         self.load_cycle(clockcycle)
 
@@ -230,7 +230,7 @@ class Processor:
         # load the start state. This is done since we only append clock
         # cycles to the list self.assembly_cycles when we reach a new state
         # that has uPC set to 0, which wont happen when we load a new file.
-        self.assembly_cycles = self.assembly_cycles[: index + 1]
+        self._assembly_cycles = self._assembly_cycles[: index + 1]
 
     def run_continuously(self) -> None:
         """
@@ -275,7 +275,7 @@ class Processor:
         Should be implemented per CPU, return field new_instruction. It is up
         to each processor to set this field to True/False correctly.
         """
-        return self.new_instruction
+        return self._new_instruction
 
     def stop_at_breakpoints(self) -> None:
         """Stop the execution if any breakpoint has been reached during this
@@ -284,7 +284,7 @@ class Processor:
         Also record the breakpoint that was reached.
         """
         self.breakpoint_reached = False
-        for _, bp in self.breakpoints.items():
+        for _, bp in self._breakpoints.items():
             # TODO: Can make this more efficient by only checking enabled
             # breakpoints
             if bp.is_break() and bp.is_enabled:
@@ -300,18 +300,18 @@ class Processor:
         This resets all modules and removes any saved states for undoing clock
         cycles. A round of value propagation is done to reset signals too.
         """
-        self.clock = 0
-        self.module_history.clear()
-        self.signal_history.clear()
-        self.removed_cycles = 0
-        self.assembly_cycles = [0]
+        self._clock = 0
+        self._module_history.clear()
+        self._signal_history.clear()
+        self._removed_cycles = 0
+        self._assembly_cycles = [0]
 
-        for module in self.modules.values():
+        for module in self._modules.values():
             module.reset()
             module.output_register()
 
-        while self.update_queue:
-            module = self.update_queue.pop(0)
+        while self._update_queue:
+            module = self._update_queue.pop(0)
             module.update_logic()
 
     def add_modules_to_update(self, module: Module) -> None:
@@ -327,8 +327,8 @@ class Processor:
         Module.update_logic :
             Method for updating a module.
         """
-        if module not in self.update_queue:
-            self.update_queue.append(module)
+        if module not in self._update_queue:
+            self._update_queue.append(module)
 
     def add_module(self, module: Module) -> None:
         """Add module to be simulated by the processor.
@@ -338,7 +338,7 @@ class Processor:
         module : Module
             Module to add.
         """
-        self.modules[module.name] = module
+        self._modules[module.name] = module
 
     def get_module(self, name: str) -> Module:
         """Get module with specific name.
@@ -353,7 +353,7 @@ class Processor:
         Module
             The module with the specified name.
         """
-        return self.modules[name]
+        return self._modules[name]
 
     def get_modules(self) -> list[Module]:
         """Get list of all modules.
@@ -363,7 +363,7 @@ class Processor:
         list[Module]
             List of all modules in the processor.
         """
-        return list(self.modules.values())
+        return list(self._modules.values())
 
     def add_signals(self, signals: list[Signal]) -> None:
         """Add signals to the processor.
@@ -373,7 +373,7 @@ class Processor:
         list[Signal]
             List of signals to add for simulation.
         """
-        self.signals += signals
+        self._signals += signals
 
     def get_clock(self) -> int:
         """Get the current clockcycle number.
@@ -383,7 +383,7 @@ class Processor:
         int
             Current clock cycle number of the processor.
         """
-        return self.clock
+        return self._clock
 
     def set_clock(self, value: int) -> None:
         """Set current clockcycle number.
@@ -393,7 +393,7 @@ class Processor:
         value : int
             Cycle number to set the clock to.
         """
-        self.clock = value
+        self._clock = value
 
     def save_cycle(self) -> None:
         """
@@ -404,13 +404,13 @@ class Processor:
 
         # Only save a specified number of cycles,
         # saving every cycle can easily eat all ram
-        if len(self.module_history) > Processor.CYCLES_TO_SAVE:
-            self.module_history.pop(0)
-            self.removed_cycles += 1
+        if len(self._module_history) > Processor.CYCLES_TO_SAVE:
+            self._module_history.pop(0)
+            self._removed_cycles += 1
 
-        for module in self.modules.values():
+        for module in self._modules.values():
             module_states[module.name] = module.get_state()
-        self.module_history.append(module_states)
+        self._module_history.append(module_states)
 
     def load_cycle(self, cycle: int) -> None:
         """Load the state of all modules as they were at the specified clock
@@ -424,26 +424,26 @@ class Processor:
             Number of the cycle to load.
         """
 
-        cycle_index = cycle - self.removed_cycles
+        cycle_index = cycle - self._removed_cycles
 
         if cycle_index < 0:
             raise ValueError("The cycle to be loaded is not saved")
 
         try:
-            module_states = self.module_history[cycle_index]
+            module_states = self._module_history[cycle_index]
         except IndexError:
             raise IndexError
 
         for module_name, module_state in module_states.items():
-            self.modules[module_name].set_state(module_state)
+            self._modules[module_name].set_state(module_state)
 
-        self.clock = cycle
+        self._clock = cycle
 
-        for module in self.modules.values():
+        for module in self._modules.values():
             module.output_register()
 
-        while self.update_queue:
-            module = self.update_queue.pop(0)
+        while self._update_queue:
+            module = self._update_queue.pop(0)
             module.update_logic()
 
     def load_state_from_file(self, file_path: str) -> None:
@@ -512,7 +512,7 @@ class Processor:
         file.write("")
         file.close()
 
-        for module in self.modules.values():
+        for module in self._modules.values():
             res = module.save_state_to_file(file_path)
 
             if not res:
@@ -520,257 +520,18 @@ class Processor:
 
         return True
 
-    def pretty_print(self) -> None:
-        """Print the processor state in a readable and compact format."""
-        self.pretty_print_verbose(self.ignore_keys)
-
-    def pretty_print_verbose(self, ignore_keys=None) -> None:
-        """
-        Print the most relevant information about each module in a compact and
-        readable format.
-
-        State variables of modules can be ignored with the optional argument.
-
-        Parameters
-        ----------
-        ignore_keys : list[str]
-            List of names of state variables of modules to exclude when
-            printing module states.
-        """
-        # TODO: ignore keys per module and not for all modules
-        memory_modules = []
-        other_modules = []
-
-        if ignore_keys is None:
-            ignore_keys = []
-
-        # TODO: remove isinstance(module, micro_memory)
-        for module in self.modules.values():
-            if not isinstance(module, Bus):
-                if isinstance(module, Memory) or isinstance(module, MicroMemory):
-                    memory_modules.append(module)
-                else:
-                    other_modules.append(module)
-
-        # sort the modules by name to ensure that they appear in the
-        # same order
-        memory_modules.sort(key=lambda x: x.name, reverse=True)
-        other_modules.sort(key=lambda x: x.name, reverse=True)
-
-        # specify which keys to ignore from the modules 'get_state'
-        # function
-        # TODO: ignore fields per module, this will ignore 'mask'
-        # for every module
-
-        module_to_line_length = {}
-        # get the longest line length for all other_modules
-        for module in other_modules:
-            # +3 for padding
-            line_len = module.get_longest_line_len(ignore_keys) + 3
-
-            # TODO: what to do if two or more modules has the same name
-            module_to_line_length[module] = line_len
-
-        groups = self.group_pp_modules(module_to_line_length)
-
-        print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
-
-        # print each group separate
-        for group in groups:
-            self.pretty_print_names(group)
-
-            # Build a new string containing the information to show
-            # the user
-            for row in range(self.get_most_fields(group, ignore_keys)):
-                string = ""
-                total_padding = 0
-
-                # Get the information from each module
-                for module in group:
-                    module_state = module.get_state()
-                    keys = self.fields_to_list(module)
-
-                    # Get the keys that we want to print to the user
-                    # If this is not done, the keys we want to print
-                    # could end up on an index that is higher than the
-                    # number of rows printed and will therefore be missed
-                    real_keys = [key for key in keys if key not in ignore_keys]
-
-                    # Dont go out of index
-                    # Needed since one module might want to print 4
-                    # fields and another only 1
-                    if row < len(real_keys) and real_keys[row] not in ignore_keys:
-                        string += (
-                            real_keys[row] + ": " + str(module_state[real_keys[row]])
-                        )
-
-                    # pad the string so each string has the same length
-                    total_padding += module_to_line_length[module]
-                    string = string.ljust(total_padding)
-                    # replace last to chars with a separator and padding
-                    string = string[0:-2] + "| "
-
-                print(string)
-            print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
-
-        for memory_module in memory_modules:
-            self.pretty_print_memory(memory_module)
-
-    def pretty_print_memory(self, module: Memory) -> None:
-        """Print a memory module in a compact and readable format.
-
-        Parameters
-        ----------
-        module : Memory
-            Memory module to print the state of.
-        """
-        print(module.name)
-        print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
-
-        longest_line_len = module.get_longest_line_len()
-        # longest_line_len = self.get_longest_memory_value(module.memory)
-        string = ""
-        last_mem_len = module.get_largest_mem_adr()
-
-        for i, value in enumerate(module.get_state()["memory"]):
-
-            # create a new string containing the address and the value
-            # of the memory address formatted to fit with the largest
-            # address and largest memory value
-            new_row = (str(i).ljust(last_mem_len) + ": " + str(value)).ljust(
-                longest_line_len + last_mem_len + 3
-            ) + "|"
-
-            # only add the string if there is space for it, else
-            # print the string and start a new
-            if len(string + new_row) + 1 > Processor.MAX_LINE_LEN:
-                print(string)
-                string = new_row
-            else:
-                # First iteration string will be
-                # empty and should not be padded
-                if string:
-                    string += " " + new_row
-                else:
-                    string = new_row
-        print(string)
-        print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
-        print()
-
-    def pretty_print_names(self, module_to_line_length: dict[Module, int]) -> None:
-        """
-        Print the name of the modules in one row with formatting.
-
-        Adds spacing between the names so that the longest state variable of
-        each module has space to be printed below the name.
-
-        Parameters
-        ----------
-        module_to_line_length : dict[Module, int]
-            Mapping from module to length of the longest state variable of
-            the module.
-        """
-        name_string = ""
-        total_len = 0
-        for module in module_to_line_length:
-            name_string += module.name
-            total_len += module_to_line_length[module]
-            name_string = name_string.ljust(total_len)
-            name_string = name_string[0:-2] + "| "
-
-        print(name_string)
-
-    def group_pp_modules(
-        self, module_to_line_length: dict[Module, int]
-    ) -> list[dict[Module, int]]:
-        """Group the modules to be pretty printed into groups with a
-        total line length lower than 'Processor.MAX_LINE_LEN'.
-
-        Parameters
-        ----------
-        module_to_line_length : dict[Module, int]
-            Mapping from module to length of the longest state variable of
-            the module (takes as the line length).
-
-        Returns
-        -------
-        list[dict[Module, int]]
-            List of mappings from module to line length, each mapping
-            representing a group of modules for printing.
-        """
-
-        groups = [{}]
-        group_index = 0
-        line_len = 0
-        for module in module_to_line_length:
-
-            # Make sure the line is not to long
-            if line_len + module_to_line_length[module] < Processor.MAX_LINE_LEN:
-                line_len += module_to_line_length[module]
-                groups[group_index][module] = module_to_line_length[module]
-
-            # If it would have been, start a new group
-            else:
-                groups.append({})
-                group_index += 1
-                groups[group_index][module] = module_to_line_length[module]
-                line_len = module_to_line_length[module]
-        return groups
-
-    def fields_to_list(self, module: Module, ignore_keys=[]) -> list[str]:
+    def get_breakpoints(self) -> dict[int, Breakpoint]:
         """
-        Return a list containing all state variable names, excluding module
-        name, for a module.
-        Optional argument to ignore specific state variables.
-
-        Parameters
-        ----------
-        module : Module
-            Module to get state variable names from.
-        ignore_keys : list[str]
-            List of state variable names to exclude.
+        Get the breakpoints in the processor as a map from breakpoint id to
+        breakpoint.
 
         Returns
         -------
-        list[str]
-            List of state variable names, excluding module name, of a module.
+        dict[int, Breakpoint]
+            Map from breakpoint id to breakpoint, containing all breakpoints
+            in the processor.
         """
-        return [
-            key
-            for key in module.get_state()
-            if key != "name" and key not in ignore_keys
-        ]
-
-    def get_most_fields(self, modules: dict[Module, int], ignore_keys=None) -> int:
-        """Get the maximum number of state variables among all modules.
-
-        Can optionally ignore keys.
-
-        Parameters
-        ----------
-        modules : dict[Module, int]
-            Mapping from module to length of the longest state variable of
-            the module. Used as a list of modules to take the maximum over.
-        ignore_keys : list[str]
-            State variables to exclude.
-
-        Returns
-        -------
-        int
-            The maximum of the number of module state variables among all
-            modules of the processor.
-        """
-
-        if ignore_keys is None:
-            ignore_keys = []
-
-        fields = 0
-        for module in modules:
-            module_fields = len(self.fields_to_list(module, ignore_keys))
-            if module_fields > fields:
-                fields = module_fields
-
-        return fields
+        return self._breakpoints
 
     def add_state_breakpoint(
         self, module_name: str, state_name: str, value: Any
@@ -794,17 +555,17 @@ class Processor:
             exist in the module.
         """
 
-        if module_name not in self.modules:
+        if module_name not in self._modules:
             raise ValueError(f"No module named {module_name}")
 
-        module = self.modules[module_name]
+        module = self._modules[module_name]
 
         if state_name not in module.get_state():
             raise ValueError(f"No state named {state_name} in " f"module {module_name}")
 
         bp = StateBreakpoint(module, state_name, value)
-        self.breakpoints[self.breakpoint_id_counter] = bp
-        self.breakpoint_id_counter += 1
+        self._breakpoints[self._breakpoint_id_counter] = bp
+        self._breakpoint_id_counter += 1
 
     def remove_breakpoint(self, id: int) -> bool:
         """Remove a specific breakpoint.
@@ -814,17 +575,17 @@ class Processor:
         id : int
             ID of the breakpoint to be removed.
         """
-        if id in self.breakpoints:
-            del self.breakpoints[id]
+        if id in self._breakpoints:
+            del self._breakpoints[id]
             return True
         return False
 
     def print_breakpoints(self) -> None:
         """Print all breakpoints of the processor."""
-        if not self.breakpoints:
+        if not self._breakpoints:
             print("There are no breakpoints.")
         else:
-            for bp_id, bp in self.breakpoints.items():
+            for bp_id, bp in self._breakpoints.items():
                 print(f"BP {bp_id}: {bp}")
 
     def add_memory_breakpoint(self, module_name: str, address: int, value: Any) -> None:
@@ -845,16 +606,16 @@ class Processor:
             If the module does not exist or is not a memory.
         """
 
-        if module_name not in self.modules:
+        if module_name not in self._modules:
             raise ValueError(f"No module named {module_name}")
 
-        module = self.modules[module_name]
+        module = self._modules[module_name]
         if "memory" not in module.get_state():
             raise ValueError(f"Module {module_name} is not a memory.")
 
         bp = MemoryBreakpoint(module, address, value)
-        self.breakpoints[self.breakpoint_id_counter] = bp
-        self.breakpoint_id_counter += 1
+        self._breakpoints[self._breakpoint_id_counter] = bp
+        self._breakpoint_id_counter += 1
 
     def get_breakpoint_lambdas(self) -> list[str]:
         """Get all functions available for lambda breakpoints.
@@ -866,7 +627,7 @@ class Processor:
             for adding lambda breakpoints.
         """
 
-        return list(self.lambdas.keys())
+        return list(self._lambdas.keys())
 
     def add_lambda_breakpoint(self, lambda_name: str, **kwargs) -> None:
         """Add a lambda breakpoint to the processor.
@@ -894,16 +655,16 @@ class Processor:
         # modules as arguments without having direct access to them
         for key in kwargs.keys():
             value = kwargs[key]
-            if value in self.modules:
-                kwargs[key] = self.modules[value]
+            if value in self._modules:
+                kwargs[key] = self._modules[value]
 
-        if lambda_name not in self.lambdas:
+        if lambda_name not in self._lambdas:
             raise ValueError(f"No lambda named {lambda_name}.")
 
-        lambda_func = self.lambdas[lambda_name]
+        lambda_func = self._lambdas[lambda_name]
         bp = LambdaBreakpoint(lambda_func, **kwargs)
-        self.breakpoints[self.breakpoint_id_counter] = bp
-        self.breakpoint_id_counter += 1
+        self._breakpoints[self._breakpoint_id_counter] = bp
+        self._breakpoint_id_counter += 1
 
     def set_enabled_breakpoint(self, bp_id: int, is_enabled: bool) -> None:
         """Toggle a breakpoint to enabled or disabled.
@@ -915,4 +676,4 @@ class Processor:
         is_enabled : bool
             ``True`` to enable, ``False`` to disable the breakpoint.
         """
-        self.breakpoints[bp_id].set_enabled(is_enabled)
+        self._breakpoints[bp_id].set_enabled(is_enabled)
diff --git a/src/simudator/gui/breakpoint_window.py b/src/simudator/gui/breakpoint_window.py
index ca19345436f974868d30ba1bdd3539bd02b60068..649364e0b6690d87e959c3161a9df2f72770c008 100644
--- a/src/simudator/gui/breakpoint_window.py
+++ b/src/simudator/gui/breakpoint_window.py
@@ -53,7 +53,7 @@ class BreakpointWindow(QWidget):
         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():
+        for bp_id, breakpoint in self.cpu.get_breakpoints().items():
             bp_str = str(bp_id) + ": " + breakpoint.__str__()
             bp_item = QListWidgetItem(bp_str)
 
@@ -95,7 +95,7 @@ class BreakpointWindow(QWidget):
         if bp_id is None:
             return
 
-        del self.cpu.breakpoints[bp_id]
+        self.cpu.remove_breakpoint(bp_id)
         self.update()
 
     def getSelectedItemId(self) -> int:
@@ -120,4 +120,4 @@ class BreakpointWindow(QWidget):
         # Do nothing if there are no breakpoints or if id is nonetype
         if bp_id is None or bp_id == -1:
             return
-        return self.cpu.breakpoints[bp_id]
+        return self.cpu.get_breakpoints()[bp_id]
diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py
index b90e2f5efdc0b4514ea70a73595531ab1905b540..39087f65727b12c8ddfc8318aa01f86c92b9bafc 100644
--- a/src/simudator/processor/mia/mia.py
+++ b/src/simudator/processor/mia/mia.py
@@ -40,7 +40,16 @@ class MIA_CPU(Processor):
         super().__init__()
         # Creating all signals
         # Signals follow the naming convention 'to_from'
-        self.max_line_len = 100
+
+        # Add state variable names to skip when pretty printing the MIA
+        # processor in the CLI
+        self._ignore_keys += [
+            "increment",
+            "read_from_bus",
+            "read_from_uADR",
+            "decrement_by_one",
+            "bus_id",
+        ]
 
         # A signal used by all modules connected to the bus
         bus_control = Signal(self, "bus_control", (0, 0))
@@ -262,9 +271,9 @@ class MIA_CPU(Processor):
         for module in ALLTHEMODULES:
             self.add_module(module)
 
-        self.micro_memory = uM
+        self._micro_memory = uM
 
-        self.lambdas = {}
+        self._lambdas = {}
 
     def is_new_instruction(self) -> bool:
         return self.get_module("uPC").value == 0
@@ -307,7 +316,7 @@ class MIA_CPU(Processor):
         return (2, 2)
 
     def should_halt(self) -> bool:
-        micro_memory_state = self.micro_memory.get_state()
+        micro_memory_state = self._micro_memory.get_state()
         return micro_memory_state["halt"]
 
     def launch_gui(self):