diff --git a/src/simudator/cli/cli.py b/src/simudator/cli/cli.py
index a375743567c885d6d9f284ab2d6413db0828b4b2..8cece34ab1733200d85c52e342092bc5f697c8fc 100644
--- a/src/simudator/cli/cli.py
+++ b/src/simudator/cli/cli.py
@@ -6,16 +6,16 @@ from os.path import exists, isdir
 from simudator.core.processor import Processor
 
 HELP_TEXT = """Here is a list of possible commands:
-CLI control: 
+CLI control:
    - h, help : Shows this message.
 
    - q, quit : Closes the program. Nothing will be saved.
 
-Simulation control: 
+Simulation control:
    - n [x], next [x]: Simulates x ticks.
      If no x is given, simulates one tick.
 
-   - rc, run_continuously: 
+   - rc, run_continuously:
      Continuously simulate ticks until a HALT is signalled
      or a breakpoint is reached.
 
@@ -30,72 +30,78 @@ State information:
    - p, print: Prints all states of all modules.
 
    - pl, printlist [add/remove] [module name] ...:
-     Add or remove the given modules to a list of modules to print. If no 
+     Add or remove the given modules to a list of modules to print. If no
      arguments are given, i.e. "pl" or "printlist" on their own, all the modules 
      in the list will be printed.
 
-   - pp, pretty print: Prints relevant processor state information in a 
+   - pp, pretty print: Prints relevant processor state information in a
      readable and compact format.
 
-   - ppv, pretty print verbose: Prints all processor state information in a 
+   - ppv, pretty print verbose: Prints all processor state information in a
      readable and compact format.
 
-Breakpoints: 
+Breakpoints:
    - p br, print breaks: Prints all breakpoints.
 
-   - p br lam, print break lambdas: 
-     Prints all available lambdas of this processor to use for lambda 
-     breakpoints. 
+   - p br lam, print break lambdas:
+     Prints all available lambdas of this processor to use for lambda
+     breakpoints.
 
    - br state, break state [module name] [state name] [value]:
-     Add a breakpoint for the module with the given name. The breakpoint brakes 
+     Add a breakpoint for the module with the given name. The breakpoint brakes
      when the specified state of the module has the specified value.
 
-   - br mem, break memory [module name] [adress] [value]:
-     Add a breakpoint for a memory module with the given name. The breakpoint 
-     breaks when the specified adress of the memory has the specified value.
+   - br mem, break memory [module name] [address] [value]:
+     Add a breakpoint for a memory module with the given name. The breakpoint
+     breaks when the specified address of the memory has the specified value.
 
    - br lam, break lambda [lambda_name] [keyword argument] ...:
-     Add a breakpoint that uses the referenced lambda to evaluate when to 
-     break. Any module names in the keyword arguments will be substituted with 
+     Add a breakpoint that uses the referenced lambda to evaluate when to
+     break. Any module names in the keyword arguments will be substituted with
      the actual module. Strings must be enclosed with quotation marks.
 
    - rm br [id], remove break [id]:
      Remove the breakpoint with the given ID.
 
-File I/O: 
+File I/O:
    - l, load [path]:
      Loads a processors state from a given file path.
 
    - sf, save to file [path]:
-     Saves the processor state to the specified file. 
+     Saves the processor state to the specified file.
 """
 
 
 class CLI:
     """
     Terminal based program for controlling a processor.
+
     Mostly used for testing and debugging.
+
+    Parameters
+    ----------
+    processor : Processor
     """
 
     def __init__(self, processor: Processor):
-        self.running = True
-        self.processor = processor
-        self.print_list = []
+        self._running = True
+        self._processor = processor
+        self._print_list = []
 
     def run(self) -> None:
-        """
-        Runs the CLI.
-        Will put the user in an input loop where they can send commands to the program
+        """Run the CLI.
+
+        Put the user in an input loop where they can send commands to the
+        program.
         """
 
         print("Welcome to simuDAtor!")
 
-        while self.running:
+        while self._running:
             # Get user commands here
             user_input = input("> ")
 
-            # Note: Keep the order of the cases consistent with the help text 
+            # Note: Keep the order of the cases consistent with the help text
             # for convenience
             match user_input.split():
                 # CLI control -------------------------------------------------
@@ -106,7 +112,7 @@ class CLI:
                 case ["q"] | ["quit"]:
                     # Ends the loop
                     print("Goodbye")
-                    self.running = False
+                    self._running = False
 
                 # Simulation control ------------------------------------------
                 case ["n"] | ["next"]:
@@ -114,7 +120,7 @@ class CLI:
                     # this could take time for larger simulations,
                     # could be good to add loading icon and stop user input
 
-                    self.processor.do_tick()
+                    self._processor.do_tick()
 
                 case ["n", _] | ["next", _]:
                     # runs a given number of ticks
@@ -123,32 +129,32 @@ class CLI:
 
                     try:
                         for _ in range(int(user_input.split()[1])):
-                            self.processor.do_tick()
-                            if self.processor.is_stopped:
+                            self._processor.do_tick()
+                            if self._processor.is_stopped:
                                 break
-                        if self.processor.breakpoint_reached:
-                            bp = self.processor.last_breakpoint
+                        if self._processor.breakpoint_reached:
+                            bp = self._processor.last_breakpoint
                             print(f"Reached breakpoint: {bp}")
-                        if self.processor.should_halt():
+                        if self._processor.should_halt():
                             print("The processor halted")
                     except ValueError:
                         print("Invalid value")
 
                 case ["rc"] | ["run_continuously"]:
-                    self.processor.run_continuously()
-                    if self.processor.breakpoint_reached:
-                        bp = self.processor.last_breakpoint
+                    self._processor.run_continuously()
+                    if self._processor.breakpoint_reached:
+                        bp = self._processor.last_breakpoint
                         print(f"Reached breakpoint: {bp}")
 
-                    if self.processor.should_halt():
+                    if self._processor.should_halt():
                         print("The processor halted")
 
                 case ["u"] | ["undo"]:
                     # undo one clock cycles
 
-                    current_cycle = self.processor.get_clock()
+                    current_cycle = self._processor.get_clock()
                     try:
-                        self.processor.load_cycle(max(current_cycle - 1, 0))
+                        self._processor.load_cycle(max(current_cycle - 1, 0))
                     except IndexError:
                         print("Index out of range")
 
@@ -162,46 +168,46 @@ class CLI:
                         print("Invalid value")
                         continue
 
-                    current_cycle = self.processor.get_clock()
+                    current_cycle = self._processor.get_clock()
                     try:
-                        self.processor.load_cycle(max(current_cycle - number, 0))
+                        self._processor.load_cycle(max(current_cycle - number, 0))
                     except IndexError:
                         print("Index out of range")
 
                 case ["r"] | ["resets"]:
                     # self.processor.load_cycle(0)
-                    self.processor.reset()
+                    self._processor.reset()
 
                 # State information -------------------------------------------
                 case ["c"] | ["clock"]:
                     # shows current clockcycle
-                    print("Clock is at: ", str(self.processor.get_clock()))
+                    print("Clock is at: ", str(self._processor.get_clock()))
 
                 case ["p"] | ["print"]:
                     print("\n")
                     # prints all module states, is most prbably hard to read
-                    for module in self.processor.get_modules():
+                    for module in self._processor.get_modules():
                         module.print_module()
                         print("\n")
 
                 case ["pl", *_] | ["printlist", *_]:
-                    self.print_list_command(user_input.split())
+                    self._print_list_command(user_input.split())
 
                 case ["pp"] | ["pretty print"]:
                     # pretty print the modules of the processor
-                    self.processor.pretty_print()
+                    self._processor.pretty_print()
 
                 case ["ppv"] | ["pretty print verbose"]:
                     # pretty print the modules of the processor
                     # with all available information
-                    self.processor.pretty_print_verbose()
+                    self._processor.pretty_print_verbose()
 
                 # Breakpoints -------------------------------------------------
                 case ["p", "br"] | ["print", "breaks"]:
-                    self.processor.print_breakpoints()
+                    self._processor.print_breakpoints()
 
                 case ["p", "br", "lam"] | ["print", "break", "lambdas"]:
-                    lambdas = self.processor.get_breakpoint_lambdas()
+                    lambdas = self._processor.get_breakpoint_lambdas()
                     if not lambdas:
                         print("There are no lambdas for this processor.")
                     else:
@@ -212,7 +218,7 @@ class CLI:
                     state_name = user_input.split()[3]
                     val = ast.literal_eval(user_input.split()[4])
                     try:
-                        self.processor.add_state_breakpoint(
+                        self._processor.add_state_breakpoint(
                             module_name, state_name, val
                         )
                     except ValueError as e:
@@ -221,9 +227,11 @@ class CLI:
                 case ["br", "mem", _, _, _] | ["break", "memory", _, _, _]:
                     module_name = user_input.split()[2]
                     try:
-                        adress = ast.literal_eval(user_input.split()[3])
+                        address = ast.literal_eval(user_input.split()[3])
                         value = ast.literal_eval(user_input.split()[4])
-                        self.processor.add_memory_breakpoint(module_name, adress, value)
+                        self._processor.add_memory_breakpoint(
+                            module_name, address, value
+                        )
                     except ValueError as e:
                         print(e)
 
@@ -235,14 +243,14 @@ class CLI:
                         key, value = kwarg.split('=')
                         kwargs[key] = ast.literal_eval(value)
                     try:
-                        self.processor.add_lambda_breakpoint(lambda_name, **kwargs)
+                        self._processor.add_lambda_breakpoint(lambda_name, **kwargs)
                     except ValueError as e:
                         print(e)
 
                 case ["rm", "br", _] | ["remove", "break", _]:
                     try:
                         bp_id = int(user_input.split()[2])
-                        if not self.processor.remove_breakpoint(bp_id):
+                        if not self._processor.remove_breakpoint(bp_id):
                             print(f"No breakpoint with ID {bp_id}")
                     except ValueError:
                         print("Breakpoint ID must be an integer")
@@ -251,36 +259,38 @@ class CLI:
                 case ["l", _] | ["load", _]:
                     # load processor state from file
                     try:
-                        self.processor.reset()
-                        self.processor.load_state_from_file(user_input.split()[1])
+                        self._processor.reset()
+                        self._processor.load_state_from_file(user_input.split()[1])
                     except FileNotFoundError:
                         print("No file called ", user_input.split()[1], " was found")
 
                 case ["sf"] | ["save to file"]:
                     file_path = "cpu_save_file"
-                    self.processor.save_state_to_file(file_path)
+                    self._processor.save_state_to_file(file_path)
 
                 case ["sf", _] | ["save to file", _]:
                     file_path = user_input.split()[1]
-                    self.check_file_path(file_path)
+                    self._save_to_file(file_path)
 
                 # -------------------------------------------------------------
                 case _:
                     # message for unknown command
                     print("Unknown command. Write \"help\" for assistance.")
 
-    def check_file_path(self, file_path) -> None:
-        """
-        Checks the file path user gave as input. If it is a directory
-        this funciton will simply return and not write anything. If it
-        is a file that already exists it will demand a 'yes' or 'no' from
-        user to decide if it should write over the existing file.
-        If the given file does not exist it will simply create the file.
+    def _save_to_file(self, file_path: str) -> None:
+        """Save the processor state to the given file path.
+
+        No save is made if the file path is a directory. If the file already
+        exists, the user is given the choice to overwrite the file.
+
+        Parameters
+        ----------
+        file_path : str
         """
 
         # Given file does not exist, save_state_to_file will create it
         if not exists(file_path):
-            self.processor.save_state_to_file(file_path)
+            self._processor.save_state_to_file(file_path)
 
         else:
             # We dont touch directories
@@ -299,17 +309,27 @@ class CLI:
                     print("Please give an input of 'yes' or 'no'!")
 
             if overwrite == "yes":
-                self.processor.save_state_to_file(file_path)
-                return
-            else:
-                return
-
-    def print_list_command(self, user_input):
+                self._processor.save_state_to_file(file_path)
+
+    def _print_list_command(self, user_input: list[str]) -> None:
+        """Add/remove modules to internal list or print all modules in the
+        internal list.
+
+        Parameters
+        ----------
+        user_input : list[str]
+            A print list command split by spaces. Should be on the format
+            ``["printlist", "add", MODULE_NAME, ...]`` or
+            ``["printlist", "remove", MODULE_NAME, ...]`` to add or remove
+            modules, where MODULE_NAME is the name of a module as a string,
+            or ``["printlist"]`` to print all added modules.
+            (``"printlist"`` can be substituted with ``"pl"``)
+        """
         # no additional commands so only print
         if len(user_input) == 1:
             print("\n")
-            for name in self.print_list:
-                self.processor.get_module(name).print_module()
+            for name in self._print_list:
+                self._processor.get_module(name).print_module()
                 print("\n")
             return
 
@@ -319,17 +339,19 @@ class CLI:
             for name in names:
                 # check if name exists
                 try:
-                    self.processor.get_module(name)
-                    if name not in self.print_list:
-                        self.print_list.append(name)
+                    self._processor.get_module(name)
+                    if name not in self._print_list:
+                        self._print_list.append(name)
                 except KeyError:
-                    print("No module named", name,)
-
+                    print(
+                        "No module named",
+                        name,
+                    )
 
         elif user_input[1] == "remove":
             for name in names:
-                if name in self.print_list:
-                    self.print_list.remove(name)
+                if name in self._print_list:
+                    self._print_list.remove(name)
                 else:
                     print(name, "not in print list")
         else:
diff --git a/src/simudator/core/breakpoint.py b/src/simudator/core/breakpoint.py
index 0727aba719f10c7dfe7786f231d0e3e91cf8fb14..4bf78fb64a631ef3a0fb562c72113305f1329bc0 100644
--- a/src/simudator/core/breakpoint.py
+++ b/src/simudator/core/breakpoint.py
@@ -1,12 +1,34 @@
 class Breakpoint:
 
-    __slots__ = "is_enabled"
+    __slots__ = "_is_enabled"
+    """
+    Base class for beakpoints, intended to be subclassed.
+
+    Attributes
+    ----------
+    is_enabled : bool
+        Used to check and toggle if a breakpoint is on or off.
+    """
 
     def __init__(self):
         self.is_enabled = True
 
     def is_break(self) -> bool:
+        """Check if the breakpoint has been reached.
+
+        Returns
+        -------
+        bool
+            ``True`` if the breakpoint has been reached, ``False`` otherwise.
+        """
         return False
 
     def set_enabled(self, is_enabled: bool) -> None:
+        """Toggle the breakpoint on or off.
+
+        Parameters
+        ----------
+        is_enabled : bool
+            ``True`` to toggle on, ``False`` to toggle off.
+        """
         self.is_enabled = is_enabled
diff --git a/src/simudator/core/breakpoint_lambda.py b/src/simudator/core/breakpoint_lambda.py
index 28c1bf8204169bfb6f33946fb90e18e0a81999c6..52bff4bb3f88d631197bbc45cfd08f45f977c093 100644
--- a/src/simudator/core/breakpoint_lambda.py
+++ b/src/simudator/core/breakpoint_lambda.py
@@ -5,16 +5,31 @@ from simudator.core.breakpoint import Breakpoint
 
 class LambdaBreakpoint(Breakpoint):
 
-    __slots__ = ("lambda_func", "kwargs")
+    __slots__ = ("_lambda_func", "_kwargs")
+    """
+    A breakpoint that uses a given function to decide whether the breakpoint
+    has been reached or not.
+
+    Parameters
+    ----------
+    lambda_func : Callable
+        The function used to decide if the breakpoint has been reached.
+
+        ``lambda_func(**kwargs) -> bool``
+        Should return ``True`` if the breakpoint has been reached, ``False``
+        otherwise.
+    **kwargs
+        Arguments to pass to `lambda_func`.
+    """
 
     def __init__(self, lambda_func: Callable[..., bool], **kwargs) -> None:
         super().__init__()
-        self.lambda_func = lambda_func
-        self.kwargs = kwargs
+        self._lambda_func = lambda_func
+        self._kwargs = kwargs
 
     def is_break(self):
-        return self.lambda_func(**self.kwargs)
+        return self._lambda_func(**self._kwargs)
 
     def __str__(self) -> str:
-        s = f"Lambda {self.lambda_func.__name__} with kwargs {self.kwargs}"
+        s = f"Lambda {self._lambda_func.__name__} with kwargs {self._kwargs}"
         return s
diff --git a/src/simudator/core/breakpoint_memory.py b/src/simudator/core/breakpoint_memory.py
index 8a0af7b8ee2a7b7eccb5865f41af05393fa09b56..8dbd66348eea3a2da753a1c1402bde9f638301e9 100644
--- a/src/simudator/core/breakpoint_memory.py
+++ b/src/simudator/core/breakpoint_memory.py
@@ -6,17 +6,31 @@ from simudator.core.modules import Memory
 
 class MemoryBreakpoint(Breakpoint):
 
-    __slots__ = ("memory", "address", "value")
+    __slots__ = ("_memory", "_address", "_value")
+
+    """
+    A breakpoint class for memory modules to break when a certain address
+    of the memory has a certain value.
+
+    Parameters
+    ----------
+    memory : Memory
+        Memory module to check the contents of.
+    address : int
+        Address of the memory module to break at.
+    value : Any
+        Value of the address that triggers the breakpoint.
+    """
 
     def __init__(self, memory: Memory, address: int, value: Any) -> None:
         super().__init__()
-        self.memory = memory
-        self.address = address
-        self.value = value
+        self._memory = memory
+        self._address = address
+        self._value = value
 
     def is_break(self):
-        memory_content = self.memory.get_state()["memory"]
-        return memory_content[self.address] == self.value
+        memory_content = self._memory.get_state()["memory"]
+        return memory_content[self._address] == self._value
 
     def __str__(self) -> str:
-        return f"{self.memory.name} {self.address}: {self.value}"
+        return f"{self._memory.name} {self._address}: {self._value}"
diff --git a/src/simudator/core/breakpoint_state.py b/src/simudator/core/breakpoint_state.py
index d32d9daf980164cebc07590f64ef5a17fed1e73a..58b042cbabf727bfb5ec1f523617592c0035595c 100644
--- a/src/simudator/core/breakpoint_state.py
+++ b/src/simudator/core/breakpoint_state.py
@@ -6,16 +6,29 @@ from simudator.core.module import Module
 
 class StateBreakpoint(Breakpoint):
 
-    __slots__ = ("module", "state", "value")
+    __slots__ = ("_module", "_state", "_value")
+    """
+    A breakpoint class to break when the state variable for a module reaches
+    a specified value.
+
+    Parameters
+    ----------
+    module : Module
+        Module to check the state of.
+    state : str
+        Name of the state variable of the module to check the value of.
+    value : Any
+        Value of the state variable to break at.
+    """
 
     def __init__(self, module: Module, state: str, value: Any) -> None:
         super().__init__()
-        self.module = module
-        self.state = state
-        self.value = value
+        self._module = module
+        self._state = state
+        self._value = value
 
     def is_break(self):
-        return self.module.get_state()[self.state] == self.value
+        return self._module.get_state()[self._state] == self._value
 
     def __str__(self) -> str:
-        return self.module.name + " " + self.state + " == " + str(self.value)
+        return self._module.name + " " + self._state + " == " + str(self._value)
diff --git a/src/simudator/core/module.py b/src/simudator/core/module.py
index f0869bedd6b28ec80fb5af60663c9a504355bcc2..6ae3b787de0d85be3457f5d7d9db3042e1b993df 100644
--- a/src/simudator/core/module.py
+++ b/src/simudator/core/module.py
@@ -8,6 +8,24 @@ class Module:
     This class specifies the basic functionality of all module types.
     The modules are processor components in the processor,
     such as ALU, busses, registers and more.
+
+    Parameters
+    ----------
+    signals : dict[str, Signal]
+        Dictionary containing all signals connected to the module. Input
+        signals should have keys beginning with 'in\_' and output signals keys
+        beginning with 'out\_'.
+    name : str
+        Name of the module.
+
+    Attributes
+    ----------
+    name : str
+        Name of the module.
+    signals : dict[str, Signal]
+        The signals connected to this module. The key for a signal can be
+        regarded as the name of a signal 'port' of the module. The keys should
+        be prefixed with 'in\_' for input signals and 'out\_' for output signals.
     """
 
     __slots__ = ("name", "signals")
@@ -21,29 +39,38 @@ class Module:
                 signal.add_destination(self)
 
     def update_register(self) -> None:
+        """Simulate module behaviour for saving input into the internal state
+        during a clock tick.
+
+        This method should be used for any module that has any 'internal'
+        registers. Exact behaviour is specified in each module subclass.
         """
-        Simulates module behaviour for saving input into the internal state
-        during a clock tick. Exact behaviour is specified in each module type.
-        """
-        raise NotImplemented
+        raise NotImplementedError
 
     def output_register(self) -> None:
+        """Simulate module behaviour for outputting data from internal
+        registers, if any, to output signals during a clock tick.
+
+        Exact behaviour is specified in each module subclass.
         """
-        Simulates module behaviour for giving data to output signals
-        during a clock tick. Exact behaviour is specified in each module type.
-        """
-        raise NotImplemented
+        raise NotImplementedError
 
     def update_logic(self) -> None:
         """
-        Simulates behaviour for sending output using the internal state
+        Simulate behaviour for sending output using the internal state
         during a clock tick. Exact behaviour is specified in each module type.
         """
-        raise NotImplemented
+        raise NotImplementedError
 
     def get_state(self) -> dict:
         """
-        Returns a dict of the module states.
+        Return the state of the module.
+
+        Returns
+        -------
+        dict[str, Any]
+            State of the module represented as a dictionary with one key for
+            each state variable.
         """
         state_dict = dict()
         state_dict["name"] = self.name
@@ -51,7 +78,12 @@ class Module:
 
     def get_gui_state(self) -> dict:
         """
-        Returns a dict of the module states that should be displayed in a GUI.
+        Return the state of the module as should be displayed in a GUI.
+
+        See Also
+        --------
+        get_state :
+            Similar method that includes state variables not related to the GUI.
         """
         state_dict = dict()
         state_dict["name"] = self.name
@@ -59,42 +91,56 @@ class Module:
 
     def set_state(self, state: dict) -> None:
         """
-        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.
+        Set the state of the module.
+
+        Parameters
+        ----------
+        state : dict[str, Any]
+            Module state represented as a dictionary.
         """
         self.name = state["name"]
 
     def get_output_signals(self) -> list[Signal]:
-        """
-        Returns the modules output signals. Assumes all output signals are
-        stored with a key beginning in 'out' in the signals dictionary.
+        """Return the output signals of the module.
+
+        Assumes all output signals are stored with a key beginning in 'out\_' in
+        the signals dictionary.
+
+        Returns
+        -------
+        list[Signal]
+            List of all output signals of this module.
         """
         return [signal for key, signal in self.signals.items() if key[0:3] == "out"]
 
     def get_input_signals(self) -> list[Signal]:
-        """
-        Returns the modules input signals. Assumes all input signals are stored
-        with a key beginning in 'in' in the signals dictionary.
+        """Return the input signals of the module.
+
+        Assumes all input signals are stored with a key beginning in 'in\_' in
+        the signals dictionary.
+
+        Returns
+        -------
+        list[Signal]
+            List of all input signals of this module.
         """
         return [signal for key, signal in self.signals.items() if key[0:2] == "in"]
 
     def reset(self) -> None:
-        """
-        Resets the module to its default state.
-        """
-        raise NotImplemented
+        """Reset the module to its default state."""
+        raise NotImplementedError
 
-    def load_from_str(self, state_string):
-        """
-        Sets the moudles state according to a string
-        Each module type will decide how the string should be formated.
+    def load_from_str(self, state_string) -> None:
+        """Set the module state according to a string.
+
+        Each module subclass decides the format of the string.
         """
-        raise NotImplemented
+        raise NotImplementedError
 
     def get_longest_line_len(self, ignore_keys=None) -> int:
-        """
-        Helper function for pretty_print that returns the length of
-        the longest line to print for a module.
+        """Return the length of the longest line when printing the module.
+
+        Helper function for pretty_print.
         """
 
         if ignore_keys == None:
@@ -112,17 +158,23 @@ class Module:
         return longest_line_len
 
     def print_module(self) -> None:
-        """
-        Prints the module directly to terminal
-        """
+        """Print the module."""
         print(self.name)
 
     def save_state_to_file(self, file_path: str) -> bool:
+        """Save the modules state to file.
+
+        Parameters
+        ----------
+        file_path : str
+            Path to the file to save to.
+
+        Returns
+        -------
+        bool
+            True if saving succeeded, False otherwise.
         """
-        Tries to save the modules state to a given file.
-        Returns true on success and false if something went wrong.
-        """
-        raise NotImplemented
+        raise NotImplementedError
 
     def __str__(self) -> str:
         return self.name
diff --git a/src/simudator/core/modules/demux.py b/src/simudator/core/modules/demux.py
index 014cfa5d589e89424038ca97711e598f0bf2a89c..2aeb731c2e414cd161b71ec38ea2743d0be6ffbf 100644
--- a/src/simudator/core/modules/demux.py
+++ b/src/simudator/core/modules/demux.py
@@ -6,12 +6,31 @@ from simudator.core.signal import Signal
 
 class Demux(Module):
     """
-    A general demux that allows an arbitrary amount of outputs to map
-    to a single input. The output side is controlled by the control
-    signal 'from_demux_s'.
+    A general demultiplexer that allows an arbitrary amount of outputs to map
+    to a single input.
+
+    Assumes the value sent from input to outputs is an integer.
+
+    Parameters
+    ----------
+    control : Signal
+        Control signal of which the value is used to index which
+        output signal to output to.
+    bit_length : int
+        Maximum number of bits for the value outputted by the demux. All extra
+        bits of the input value are discarded.
+    input : Signal
+        Input signal of which the value is forwarded to the currently
+        selected output signal.
+    outputs : list[Signal]
+        List of output signals to demultiplex the input signal value to.
+    name : str
+        Name of the demultiplexer module.
+    value : Any
+        Initial value to output to the currently selected output signal.
     """
 
-    __slots__ = ("bit_length", "mask", "value")
+    __slots__ = ("_bit_length", "_value")
 
     def __init__(
         self,
@@ -33,51 +52,51 @@ class Demux(Module):
 
         super().__init__(signals, name)
 
-        # mask and bit_length
-        self.bit_length = bit_length
-        self.mask = 2**self.bit_length - 1
+        self._bit_length = bit_length
 
         # Value to be read/written
-        self.value = value
+        self._value = value
 
     def update_register(self) -> None:
         """
-        Read the input value and update the value of the demux.
+        Read the input signal value and update the value of the demux.
         """
+
         input_value = self.signals["in_input"].get_value()
-        self.value = input_value & self.mask
+        mask = 2**self._bit_length - 1
+        self._value = input_value & mask
 
-    def output_register(self):
-        """
-        Read which signal to write to from the control signal
-        'from_demux_s' and forward the input to that output signal.
+    def output_register(self) -> None:
+        """Read which signal to write to from the control signal and forward
+        the input to that output signal.
         """
         output_index = self.signals["in_control"].get_value()
         output_signal_key = f"out_output_{output_index}"
-        self.signals[output_signal_key].update_value(self.value)
+        self.signals[output_signal_key].update_value(self._value)
 
-    def update_logic(self):
-        """
-        The demux has no logic
+    def update_logic(self) -> None:
+        """Do nothing.
+
+        The demux has no logic.
         """
         pass
 
     def get_state(self) -> dict[str, Any]:
-        """
-        Returns a dict of the demux state.
-        """
         state = super().get_state()
-        state["value"] = self.value
-        state["bit_length"] = self.bit_length
-        state["mask"] = self.mask
+        state["value"] = self._value
+        state["bit_length"] = self._bit_length
 
         return state
 
-    def set_state(self, state: dict) -> None:
-        """
-        Sets the name and value of the demux.
+    def set_state(self, state: dict[str, Any]) -> None:
+        """Set the name and value of the demux.
+
+        Parameters
+        ----------
+        state : dict[str, Any]
+            The state of the demux to load. Should contain the keys "value" and
+            "bit_length", both with values of type ``int``.
         """
         super().set_state(state)
-        self.value = state["value"]
-        self.bit_length = state["bit_length"]
-        self.mask = state["mask"]
+        self._value = state["value"]
+        self._bit_length = state["bit_length"]
diff --git a/src/simudator/core/modules/memory.py b/src/simudator/core/modules/memory.py
index 5cdce8bb5fbd2889388573d81e75c5147087fbc4..8f946bac71d900be0c087eeb00fdf1995cee9ab5 100644
--- a/src/simudator/core/modules/memory.py
+++ b/src/simudator/core/modules/memory.py
@@ -1,5 +1,7 @@
 from __future__ import annotations
 
+from typing import Any
+
 from simudator.core.module import Module
 from simudator.core.signal import Signal
 
@@ -7,51 +9,66 @@ from simudator.core.signal import Signal
 class Memory(Module):
     """
     A general size memory module.
+
+    Parameters
+    ----------
+    input : Signal
+        Signal of which the value may be written to the current address.
+    output : Signal
+        Signal to which the content of the current address is written.
+    control : Signal
+        Signal used to enable or disable write to the current address. Assumed
+        to output ``bool``.
+    address : Signal
+        Signal used to address the memory. Assumed to output ``int``.
+    size : int
+        Size of the address space of the memory.
+    name : str
+        Name of the module.
     """
 
     __slots__ = (
-        "memory",
-        "current_address",
-        "is_write",
-        "address_padding",
-        "value_padding",
+        "_memory",
+        "_current_address",
+        "_is_write",
     )
+    """
+    Constants used to textually pad the values of the memory when saving to
+    file.
+    """
+    MEMORY_VALUE_PADDING = 2
+    MEMORY_ADDRESS_PADDING = 2
 
     def __init__(
         self,
-        input_signal: Signal,
-        output_signal: Signal,
-        control_signal: Signal,
-        address_signal: Signal,
+        input: Signal,
+        output: Signal,
+        control: Signal,
+        address: Signal,
         size: int,
-        value_padding: int = 2,
-        address_padding: int = 2,
         name="Memory",
     ) -> None:
 
         # signals
         signals = {
-            "in_input": input_signal,
-            "in_control": control_signal,
-            "in_address": address_signal,
-            "out_content": output_signal,
+            "in_input": input,
+            "in_control": control,
+            "in_address": address,
+            "out_content": output,
         }
 
         # Init super class
         super().__init__(signals, name)
 
         # Internal state
-        self.memory = [0 for _ in range(size)]
-        self.current_address = 0
-        self.is_write = False
-
-        # Values used to format the strings when saving state to file
-        self.address_padding = address_padding
-        self.value_padding = value_padding
+        self._memory = [0 for _ in range(size)]
+        self._current_address = 0
+        self._is_write = False
 
     def update_register(self):
-        if self.is_write:
-            self.memory[self.current_address] = self.signals["in_input"].get_value()
+        if self._is_write:
+            value = self.signals["in_input"].get_value()
+            self._memory[self._current_address] = value
 
     def output_register(self) -> None:
         pass
@@ -63,44 +80,44 @@ class Memory(Module):
         ctrl_sig = self.signals["in_control"]
         out_sig = self.signals["out_content"]
         if adr_sig.get_value() is not None and ctrl_sig.get_value() is not None:
-            self.is_write = ctrl_sig.get_value()
-            self.current_address = adr_sig.get_value()
-            out_sig.update_value(self.memory[self.current_address])
+            self._is_write = ctrl_sig.get_value()
+            self._current_address = adr_sig.get_value()
+            out_sig.update_value(self._memory[self._current_address])
 
     def print_module(self) -> None:
         print("", self.name, "\n -----")
-        for address, value in enumerate(self.memory):
+        for address, value in enumerate(self._memory):
             if value:
                 print("", str(hex(address)), "", str(hex(value)), "\n")
 
-    def get_state(self) -> dict:
+    def get_state(self) -> dict[str, Any]:
         state = super().get_state()
-        state["is_write"] = self.is_write
-        state["current_address"] = self.current_address
-        state["memory"] = self.memory[:]
+        state["is_write"] = self._is_write
+        state["current_address"] = self._current_address
+        state["memory"] = self._memory[:]
         return state
 
-    def get_gui_state(self) -> dict:
+    def get_gui_state(self) -> dict[str, Any]:
         state = super().get_gui_state()
-        state["current_address"] = self.current_address
-        state["memory"] = self.memory[:]
+        state["current_address"] = self._current_address
+        state["memory"] = self._memory[:]
         return state
 
-    def set_state(self, state: dict) -> None:
+    def set_state(self, state: dict[str, Any]) -> None:
         super().set_state(state)
         if "is_write" in state:
-            self.is_write = state["is_write"]
+            self._is_write = state["is_write"]
         if "current_address" in state:
-            self.current_address = state["current_address"]
+            self._current_address = state["current_address"]
         if "memory" in state:
-            self.memory = state["memory"]
+            self._memory = state["memory"]
 
     def reset(self) -> None:
         """
         Reset the memory to 0 for each address.
         """
-        for i in range(len(self.memory)):
-            self.memory[i] = 0
+        for i in range(len(self._memory)):
+            self._memory[i] = 0
 
     def get_longest_line_len(self, ignore_keys=None) -> int:
         """
@@ -113,7 +130,7 @@ class Memory(Module):
 
         longest_memory_line = 0
 
-        for value in self.memory:
+        for value in self._memory:
             value_len = len(str(value))
             if value_len > longest_memory_line:
                 longest_memory_line = value_len
@@ -125,19 +142,16 @@ class Memory(Module):
         Helper function for pretty_print that returns the length of
         the largest address in the memory to print for a module.
         """
-        return len(str(len(self.memory)))
+        return len(str(len(self._memory)))
 
-    def save_state_to_file(self, file_path: str) -> None:
-        """
-        Tries to save the modules state to a given file.
-        """
+    def save_state_to_file(self, file_path: str) -> bool:
         file = open(file_path, "a")
         file.write(self.name + ":\n")
-        for index, value in enumerate(self.memory):
+        for index, value in enumerate(self._memory):
             # Write the address in hex and add ': ' to the end
-            file.write(hex(index)[2:].rjust(self.address_padding, "0") + ": ")
+            file.write(hex(index)[2:].rjust(Memory.MEMORY_ADDRESS_PADDING, "0") + ": ")
             # Write the value in hex
-            file.write(hex(value)[2:].rjust(self.value_padding, "0"))
+            file.write(hex(value)[2:].rjust(Memory.MEMORY_VALUE_PADDING, "0"))
             file.write("\n")
 
         file.write("\n")
diff --git a/src/simudator/core/modules/mux.py b/src/simudator/core/modules/mux.py
index 23e13ef535d3663f7a7a58f7c7f09f96b6a4094e..018698e17e42ecc83ba737939135a370906cb14b 100644
--- a/src/simudator/core/modules/mux.py
+++ b/src/simudator/core/modules/mux.py
@@ -6,16 +6,33 @@ from simudator.core.signal import Signal
 
 class Mux(Module):
     """
-    A general mux that allows an arbitrary amount of input to map
-    to a single output. The input side is controlled by the control
-    signal 'to_mux_s'.
+    A general mux that allows an arbitrary amount of input to map to a single
+    output.
+
+    Parameters
+    ----------
+    control : Signal
+        Control signal of which the value is used to index which
+        input signal to read from.
+    bit_length : int
+        Maximum number of bits for the value outputted by the mux. All extra
+        bits of the input value are discarded.
+    inputs : list[Signal]
+        List of input signals to select from to output onto the output signal.
+    output : Signal
+        Signal onto which the value of the currently selected input is
+        outputted.
+    name : str
+        Name of the multiplexer module.
+    value : Any
+        Initial value to output to the output signal.
     """
 
-    __slots__ = ("bit_length", "mask", "value")
+    __slots__ = ("_bit_length", "_value")
 
     def __init__(
         self,
-        to_mux: Signal,
+        control: Signal,
         bit_length: int,
         output: Signal,
         inputs: list[Signal] = [],
@@ -25,7 +42,7 @@ class Mux(Module):
 
         # Signals
         signals = {
-            "in_control": to_mux,
+            "in_control": control,
             "out": output,
         }
         for i, s in enumerate(inputs):
@@ -35,62 +52,61 @@ class Mux(Module):
         super().__init__(signals, name)
 
         # mask and bit_length
-        self.bit_length = bit_length
-        self.mask = 2**self.bit_length - 1
+        self._bit_length = bit_length
 
         # Value to be read/written
-        self.value = value
+        self._value = value
 
     def update_register(self) -> None:
-        """
-        Read which signal to read from the control signal
-        'to_mux_s' and forward that signal to the output.
+        """Read which signal to read from the control signal and forward that
+        signal to the output.
         """
         input_index = self.signals["in_control"].get_value()
         input_signal_key = f"in_input_{input_index}"
         input_value = self.signals[input_signal_key].get_value()
-        self.value = input_value & self.mask
+        mask = 2**self._bit_length - 1
+        self._value = input_value & mask
 
     def output_register(self):
+        """Output the value of the currently selected input signal to the
+        output signal.
         """
-        Output the value of the mux to its output.
-        """
-        self.signals["out"].update_value(self.value)
+        self.signals["out"].update_value(self._value)
 
     def update_logic(self):
-        """
+        """Do nothing.
+
         The mux has no logic.
         """
         pass
 
     def get_state(self) -> dict[str, Any]:
-        """
-        Returns a dict of the mux state.
-        """
         state = super().get_state()
-        state["value"] = self.value
-        state["bit_length"] = self.bit_length
-        state["mask"] = self.mask
+        state["value"] = self._value
+        state["bit_length"] = self._bit_length
 
         return state
 
-    def set_state(self, state: dict) -> None:
-        """
-        Sets the name and value of the mux.
+    def set_state(self, state: dict[str, Any]) -> None:
+        """Set the name, value and bit length of the demux.
+
+        Parameters
+        ----------
+        state : dict[str, Any]
+            The state of the demux to load. Should contain the keys "name",
+            "value" and "bit_length" with values of type ``str``, ``int`` and
+            ``int`` respectively.
         """
         super().set_state(state)
-        self.value = state["value"]
-        self.bit_length = state["bit_length"]
-        self.mask = state["mask"]
+        self._value = state["value"]
+        self._bit_length = state["bit_length"]
 
     def print_module(self) -> None:
         print(
             self.name,
             "\n-----",
             "\nvalue: ",
-            self.value,
+            self._value,
             "\nbit length: ",
-            self.bit_length,
-            "\nmask: ",
-            self.mask,
+            self._bit_length,
         )
diff --git a/src/simudator/core/modules/register.py b/src/simudator/core/modules/register.py
index b23e57cc04188b5670cd847e674227f83460fa64..e2b70cd4d6e0096ae841e8cbc370e0bb58cc7d3c 100644
--- a/src/simudator/core/modules/register.py
+++ b/src/simudator/core/modules/register.py
@@ -8,10 +8,21 @@ from simudator.core.signal import Signal
 
 class Register(Module):
     """
-    A simple module that can store a value.
+    A simple module that can store and output a value.
+
+    Parameters
+    ----------
+    input : Signal
+        Signal from which the value is stored in the register.
+    output : Signal
+        Signal onto which the value of the register is outputted.
+    value : Any
+        Initial value of the register.
+    name : str
+        Name of the register.
     """
 
-    __slots__ = "value"
+    __slots__ = "_value"
 
     def __init__(
         self,
@@ -29,39 +40,33 @@ class Register(Module):
 
         # init the instance
         super().__init__(signals, name)
-        self.value = value
+        self._value = value
 
     def update_register(self) -> None:
-        """
-        Propagate the input signal to the registers internal state.
-        Throw away bits larger than the length of the register.
+        """Update the internal value of the register with the input signal.
+
+        Any extra bits that do not fit the bit length of the register are
+        thrown away.
         """
         input_value = self.signals["in_content"].get_value()
         if input_value is None:
             return
-        self.value = input_value
+        self._value = input_value
 
     def output_register(self) -> None:
-        """
-        Propagate the value of the register to the output signal.
-        It is the response of the destination to know when it should
-        read the output.
-        """
-        self.signals["out_content"].update_value(self.value)
+        """Output the value of the register onto the output signal."""
+        self.signals["out_content"].update_value(self._value)
 
     def update_logic(self):
-        """
+        """Do nothing.
+
         The register has no logic.
         """
         pass
 
     def get_state(self) -> dict[str, Any]:
-        """
-        Returns a dict of the register state.
-        These states are changable via set_states.
-        """
         state = super().get_state()
-        state["value"] = self.value
+        state["value"] = self._value
         return state
 
     def get_gui_state(self) -> dict:
@@ -70,25 +75,27 @@ class Register(Module):
 
     def set_state(self, state: dict[str, Any]) -> None:
         """
-        Sets the register state to one given in dict.
+        Set the state of the register.
+
+        Parameters
+        ----------
+        state : dict[str, Any]
+            The state of the register to load. Should contain the keys "name"
+            and "value" with values of type ``str`` and ``int`` respectively.
         """
         self.name = state["name"]
-        self.value = state["value"]
+        self._value = state["value"]
 
     def reset(self) -> None:
         """
-        Resets the register to 0.
+        Reset the register to 0.
         """
-        self.value = 0
+        self._value = 0
 
-    def save_state_to_file(self, file_path: str) -> None:
-        """
-        Tries to save the modules state to a given file.
-        Returns true on success and false if something went wrong.
-        """
+    def save_state_to_file(self, file_path: str) -> bool:
         file = open(file_path, "a")
         file.write(self.name + ":\n")
-        file.write("value: " + str(self.value) + "\n\n")
+        file.write("value: " + str(self._value) + "\n\n")
         file.close()
 
     def print_module(self) -> None:
@@ -97,78 +104,74 @@ class Register(Module):
             self.name,
             "\n -----",
             "\n value: ",
-            self.value,
+            self._value,
         )
 
 
 class IntegerRegister(Register):
     """
-    A simple module that can store an integer value with a given bit-length.
+    A register intended to store integers only.
+
+    Parameters
+    ----------
+    input : Signal
+        Signal from which the value is stored in the register.
+    output : Signal
+        Signal onto which the value of the register is outputted.
+    bit_length : int
+        Maximum number of bits of the input to store in the register. All extra
+        bits of the input value are discarded.
+    value : Any
+        Initial value of the register.
+    name : str
+        Name of the register.
     """
 
-    __slots__ = ("bit_length", "mask")
+    __slots__ = "_bit_length"
 
     def __init__(
         self,
-        input_signal: Signal,
-        output_signal: Signal,
+        input: Signal,
+        output: Signal,
         bit_length: int,
         value: int = 0,
         name: str | None = None,
     ) -> None:
 
-        # set the registers name
+        # set the name
         if name is None:
             name = f"{bit_length}-bit register"
 
-        super().__init__(input_signal, output_signal, value=value, name=name)
+        super().__init__(input, output, value=value, name=name)
 
         # set the bit length of the register
-        self.bit_length = bit_length
-
-        # set the registers mask. An 8 bit register should
-        # have the mask 1111 1111, aka one '1' for every bit
-        self.mask = 2**bit_length - 1
+        self._bit_length = bit_length
 
     def update_register(self) -> None:
-        """
-        Propagate the input signal to the registers internal state.
-        Throw away bits larger than the length of the register.
-        """
         super().update_register()
-        self.value = self.value & self.mask
+        mask = 2**self._bit_length - 1
+        self._value = self._value & mask
 
     def get_state(self) -> dict[str, Any]:
-        """
-        Returns a dict of the register state.
-        These states are changable via set_states.
-        """
         state = super().get_state()
-        state["bit_length"] = self.bit_length
+        state["bit_length"] = self._bit_length
         return state
 
     def set_state(self, state: dict[str, Any]) -> None:
-        """
-        Sets the register state to one given in dict.
-        """
         super().set_state(state)
         if "bit_length" in state:
-            self.bit_length = state["bit_length"]
-            self.mask = 2**self.bit_length - 1
+            self._bit_length = state["bit_length"]
 
-    def save_state_to_file(self, file_path: str) -> None:
-        """
-        Tries to save the modules state to a given file.
-        """
+    def save_state_to_file(self, file_path: str) -> bool:
         file = open(file_path, "a")
         file.write(self.name + ":\n")
-        file.write("value: " + hex(self.value)[2:] + "\n\n")
+        file.write("value: " + hex(self._value)[2:] + "\n\n")
         file.close()
 
-    def load_from_str(self, state_string):
+    def load_from_str(self, state_string) -> None:
         string_pair = state_string.split(": ")
         # TODO: Maybe check if it starts with value: ?
-        self.value = int(string_pair[1], 16)
+        self._value = int(string_pair[1], 16)
 
 
 class Flag(IntegerRegister):
@@ -188,8 +191,8 @@ class Flag(IntegerRegister):
 
         # set the flags name
         super().__init__(
-            input_signal=input_signal,
-            output_signal=output_signal,
+            input=input_signal,
+            output=output_signal,
             bit_length=bit_length,
             value=value,
             name=name,
@@ -203,20 +206,21 @@ class Flag(IntegerRegister):
         to activate (ex: loop counter reaches zero -> set L flag to 1)
         """
         input_value = self.signals["in_content"].get_value()
-        self.value = input_value & self.mask
+        mask = 2**self._bit_length - 1
+        self._value = input_value & mask
 
     def get_gui_state(self) -> dict:
         state = super().get_gui_state()
-        state["value"] = self.value
+        state["value"] = self._value
         return state
 
-    def save_state_to_file(self, file_path: str) -> None:
+    def save_state_to_file(self, file_path: str) -> bool:
         """
         Tries to save the modules state to a given file.
         """
         file = open(file_path, "a")
         file.write(self.name + ":\n")
-        file.write("value: " + str(self.value) + "\n\n")
+        file.write("value: " + str(self._value) + "\n\n")
         file.close()
 
     def print_module(self) -> None:
@@ -225,9 +229,7 @@ class Flag(IntegerRegister):
             self.name,
             "\n -----",
             "\n value: ",
-            self.value,
+            self._value,
             "\n bit length: ",
-            self.bit_length,
-            "\n mask: ",
-            self.mask,
+            self._bit_length,
         )
diff --git a/src/simudator/core/processor.py b/src/simudator/core/processor.py
index 8b7d31aaa2f97635bdf98fff9b09c2af6dc202ca..0106327f75025ec87a47c75555a0041cfb301486 100644
--- a/src/simudator/core/processor.py
+++ b/src/simudator/core/processor.py
@@ -17,42 +17,67 @@ from .signal import Signal
 class Processor:
     """
     Main class for controlling the processor.
+
     Uses modules and signals to simulate processor components behaviour.
     """
 
-    __slots__ = ("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", "is_stopped", 
-                 "new_instruction", "current_instructions", 
-                 "ignore_keys", "lambdas", "assembly_cycles",
-                 "line_separator")
-
-    def __init__(self):
+    __slots__ = (
+        "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",
+        "is_stopped",
+        "new_instruction",
+        "current_instructions",
+        "ignore_keys",
+        "lambdas",
+        "assembly_cycles",
+        "line_separator",
+    )
+
+    LINE_SEPARATOR = "-"
+    MAX_LINE_LEN = 170
+    CYCLES_TO_SAVE = 10000
+
+    def __init__(self) -> None:
+        # For simulation
         self.modules: dict[str, Module] = dict()
         self.signals = []
         self.clock = 0
         self.update_queue = []
-        self.module_history: list[dict[str, dict[str, Any]]] = []
-        self.signal_history: list[list] = []  # TODO: Is this needed?
+        self.is_stopped = False
+
+        # Breakpoint handling
         self.breakpoint_id_counter = 1
         self.breakpoints: dict[int, Breakpoint] = {}
         self.breakpoint_reached = False
         self.last_breakpoint = None
-        self.cycles_to_save = 10000
+        self.lambdas: dict[str, Callable[..., bool]] = {}
+
+        # Saving processor state for saving/loading to file and undoing ticks
         self.removed_cycles = 0
-        self.max_line_len = 170
-        self.line_separator = "-"
-        self.is_stopped = False
+        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?
+
+        # For showing which instructions are being done and signalling
+        # the start of a new one
         self.new_instruction = 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.
+        # 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]] = []
 
         # TODO: keeping track of what pieces of info not to show
@@ -68,14 +93,9 @@ class Processor:
             "decrement_by_one",
             "bus_id",
         ]
-        self.lambdas: dict[str, Callable[..., bool]] = {}
-
-        # List containing all clock cycles where a new asm instruction started
-        self.assembly_cycles = [0]
 
     def do_tick(self) -> None:
-        """
-        Simulate one clock cycle of the processor.
+        """Simulate one clock cycle of the processor.
 
         Run each module's tick function, then handle the following updates.
         Also check for breakpoints that are reached in this cycle, and save
@@ -116,51 +136,74 @@ class Processor:
             self.new_instruction = False
 
     def get_current_instructions(self) -> list[tuple[str, int, int]]:
-        """
-        Return a list of the current instructions with their positions.
+        """Return a list of the current instructions with their positions.
 
-        Each entry in the list is a tuple of a instruction with its column and row position
-        for the pipeline diagram.
+        Each entry in the list is a tuple of a instruction with its column and
+        row position for the pipeline diagram.
+
+        Returns
+        -------
+        list[tuple[str, int, int]]
+            A list of instructions represented as tuples. Each tuple contains
+            the instruction and its position in the pipeline.
         """
-        raise NotImplemented
+        raise NotImplementedError
 
     def get_pipeline_dimensions(self) -> tuple[int, int]:
-        """
-        Return a tuple on the form (x, y) for the processors preffered pipeline display size.
+        """Return the dimensions of the pipeline of the processor.
 
-        (x, y) represents the number of columns respective rows the pipeline should have.
+        Returns
+        -------
+        width : int
+            The width of the pipeline (number of cycles to display at a time).
+        depth : int
+           Depth of the pipeline.
         """
-        raise NotImplemented
+        raise NotImplementedError
 
     def get_asm_instruction(self) -> str:
-        """
-        Return a string containing the 'code' for the current assembly instruction.
+        """Return a string containing the 'code' for the current assembly
+        instruction.
 
-        What 'code' refers to is up to each processor to define, could be a memory address,
-        an instruction label or something else.
+        What 'code' refers to is up to each processor to define. It could be a
+        memory address, an instruction label or something else.
+
+        Returns
+        -------
+        str
+            The current assembly instruction.
         """
-        raise NotImplemented
+        raise NotImplementedError
 
     def run_asm_instruction(self, num_instructions=1) -> None:
-        """
-        Runs assembler instructions on the processors 'num_instructions' times.
+        """Run a number of assembly instructions.
 
-        Default argument is one, but it is possible to specify any number of instructions.
-        This should be implemented per processor and thus we raise NotImplemented.
+        Defaults to running 1 instruction unless some other number is provided.
+
+        Parameters
+        ----------
+        num_instructions : int
+            Number of assembly instructions to perform.
+
+        Notes
+        -----
+        This should be implemented per processor and thus we
+        raise NotImplementedError.
         """
 
-        raise NotImplemented
+        raise NotImplementedError
 
     def undo_asm_instruction(self, num_instructions=1) -> None:
         """
-        Undos 'num_instructions' numbers of assembler instructions on the CPU.
+        Undo a number of assembly instructions on the CPU.
 
-        Default argument is one, but it is possible to specify any number of instructions.
-        Undo assembler instruction assumes the CPU is always at the end of the list
-        'self.assembly_cycles'.
+        Default argument is one, but it is possible to specify any number of
+        instructions.
 
-        Undos asm instructions by finding the corresponding clock cycle before
-        said number of asm intructions started and loading that clock cycle.
+        Parameters
+        ----------
+        num_instructions : int
+            Number of assembly instructions to undo.
         """
 
         current_clock_cycle = self.clock
@@ -185,7 +228,7 @@ class Processor:
         # Need +1 here since we save the start state to enable to
         # 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 happened when we load a new file.
+        # that has uPC set to 0, which wont happen when we load a new file.
         self.assembly_cycles = self.assembly_cycles[: index + 1]
 
     def run_continuously(self) -> None:
@@ -198,48 +241,51 @@ class Processor:
 
     def should_halt(self) -> bool:
         """
-        Return True when the processor should halt, otherwise False.
+        Return whether the processor should halt this clock cycle or not.
+
+        Returns
+        -------
+        bool
+            ``True`` if the processor should halt, ``False`` otherwise.
 
-        Note
+        Notes
         ----
         Each processor should implement the condition for True in its subclass.
-        If we instead raise NotImplemented as we do in all other cases when the
-        functionality should be implemented in the subclass we lose the ability
-        to test modules on the base processor class.
+        If we instead raise NotImplementedError as we do in all other cases
+        when the functionality should be implemented in the subclass we lose
+        the ability to test modules on the base processor class.
         """
         return False
 
     def stop(self) -> None:
-        """
-        Signal to stop the execution of the processor until the processor is
+        """Signal to stop the execution of the processor until the processor is
         instructed to run continuously or do some ticks again.
         """
         self.is_stopped = True
 
     def unstop(self) -> None:
-        """
-        Reset the stop execution signal.
-        """
+        """Reset the stop execution signal."""
         self.is_stopped = False
 
     def is_new_instruction(self) -> bool:
         """
         Return true on the same clock cycle the CPU starts a new instruction.
 
-        Should be implemented per CPU, return field new_instruction. It is up to each
-        processor to set this field to True/False correctly.
+        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
 
     def stop_at_breakpoints(self) -> None:
-        """
-        Stop the execution if any breakpoint has been reached during this cycle.
+        """Stop the execution if any breakpoint has been reached during this
+        clock cycle.
 
         Also record the breakpoint that was reached.
         """
         self.breakpoint_reached = False
         for _, bp in self.breakpoints.items():
-            # TODO: Can make this more efficient by only checking enabled breakpoints
+            # TODO: Can make this more efficient by only checking enabled
+            # breakpoints
             if bp.is_break() and bp.is_enabled:
                 self.breakpoint_reached = True
                 self.last_breakpoint = bp
@@ -248,8 +294,7 @@ class Processor:
             self.stop()
 
     def reset(self):
-        """
-        Reset the processor to its start state.
+        """Reset the processor to its start state.
 
         This resets all modules and removes any saved states for undoing clock
         cycles. A round of value propagation is done to reset signals too.
@@ -269,45 +314,83 @@ class Processor:
             module.update_logic()
 
     def add_modules_to_update(self, module: Module) -> None:
-        """
-        Queues module to be updated at the end of clock cycle.
+        """Queue a module to be updated at the end of clock cycle.
+
+        Parameters
+        ----------
+        module : Module
+            Module to queue for update.
+
+        See Also
+        --------
+        Module.update_logic :
+            Method for updating a module.
         """
         if module not in self.update_queue:
             self.update_queue.append(module)
 
     def add_module(self, module: Module) -> None:
-        """
-        Add module into the processor.
+        """Add module to be simulated by the processor.
+
+        Parameters
+        ----------
+        module : Module
+            Module to add.
         """
         self.modules[module.name] = module
 
     def get_module(self, name: str) -> Module:
-        """
-        Get module with specific name.
+        """Get module with specific name.
+
+        Parameters
+        ----------
+        name : str
+            Name of the module to get.
+
+        Returns
+        -------
+        Module
+            The module with the specified name.
         """
         return self.modules[name]
 
     def get_modules(self) -> list[Module]:
-        """
-        Get list of all modules.
+        """Get list of all modules.
+
+        Returns
+        -------
+        list[Module]
+            List of all modules in the processor.
         """
         return list(self.modules.values())
 
     def add_signals(self, signals: list[Signal]) -> None:
-        """
-        Add signals into the processor.
+        """Add signals to the processor.
+
+        Parameters
+        ----------
+        list[Signal]
+            List of signals to add for simulation.
         """
         self.signals += signals
 
     def get_clock(self) -> int:
-        """
-        Get current clockcycle.
+        """Get the current clockcycle number.
+
+        Returns
+        -------
+        int
+            Current clock cycle number of the processor.
         """
         return self.clock
 
     def set_clock(self, value: int) -> None:
-        """
-        Set current clockcycle.
+        """Set current clockcycle number.
+
+        Parameters
+        ----------
+        value : int
+            Cycle number to set the clock to.
         """
         self.clock = value
 
@@ -320,7 +403,7 @@ class Processor:
 
         # Only save a specified number of cycles,
         # saving every cycle can easily eat all ram
-        if len(self.module_history) > self.cycles_to_save:
+        if len(self.module_history) > Processor.CYCLES_TO_SAVE:
             self.module_history.pop(0)
             self.removed_cycles += 1
 
@@ -329,10 +412,15 @@ class Processor:
         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 cycle.
+        """Load the state of all modules as they were at the specified clock
+        cycle.
 
         This does not erase the history of states for the later cycles.
+
+        Parameters
+        ----------
+        cycle : int
+            Number of the cycle to load.
         """
 
         cycle_index = cycle - self.removed_cycles
@@ -357,13 +445,13 @@ class Processor:
             module = self.update_queue.pop(0)
             module.update_logic()
 
-    def load_state_from_file(self, file_path) -> None:
-        """
-        Loads states for modules from a file.
+    def load_state_from_file(self, file_path: str) -> None:
+        """Load states for modules from a file.
 
-        Appends the lines from the loaded file to a long string. This string
-        is given to each module in the function 'load_from_str'. Each module
-        will thus load itself.
+        Parameters
+        ----------
+        file_path : str
+            Path to the file containing the processor state to load.
         """
         self.reset()
 
@@ -376,6 +464,9 @@ class Processor:
         else:
             raise ValueError  # Else raise error
 
+        # Appends the lines from the loaded file to a long string. This string
+        # is given to each module in the function 'load_from_str'. Each module
+        # will thus load itself.
         module_name = None
         module_str = ""
 
@@ -407,10 +498,14 @@ class Processor:
             module.load_from_str(module_str)
 
     def save_state_to_file(self, file_path: str) -> None:
-        """
-        Saves the current state of the cpu to a given file.
+        """Save the current state of the cpu to file.
 
         Will overwrite the given file.
+
+        Parameters
+        ----------
+        file_path : str
+            Path to the file to write to.
         """
         file = open(file_path, "w")
         file.write("")
@@ -421,13 +516,21 @@ class Processor:
             module.save_state_to_file(file_path)
 
     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:
         """
-        Prints the most relevant information about each module
-        compact and pretty. Fields of modules can be ignored with the
-        optional argument 'ignore_keys'.
+        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 = []
@@ -457,14 +560,15 @@ class Processor:
         module_to_line_length = {}
         # get the longest line length for all other_modules
         for module in other_modules:
-            line_len = module.get_longest_line_len(ignore_keys) + 3  # +3 for padding
+            # +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(self.line_separator * self.max_line_len)
+        print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
 
         # print each group separate
         for group in groups:
@@ -495,32 +599,38 @@ class Processor:
                             real_keys[row] + ": " + str(module_state[real_keys[row]])
                         )
 
-                    # padd the string so each string has the same
-                    # length
+                    # 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(self.line_separator * self.max_line_len)
+            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: Module) -> None:
+    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(self.line_separator * self.max_line_len)
+        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.memory):
+        for i, value in enumerate(module.get_state()["memory"]):
 
             # create a new string containing the address and the value
-            # of the memory address formattet to fit with the largest
+            # 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
@@ -528,7 +638,7 @@ class Processor:
 
             # only add the string if there is space for it, else
             # print the string and start a new
-            if len(string + new_row) + 1 > self.max_line_len:
+            if len(string + new_row) + 1 > Processor.MAX_LINE_LEN:
                 print(string)
                 string = new_row
             else:
@@ -539,16 +649,21 @@ class Processor:
                 else:
                     string = new_row
         print(string)
-        print(self.line_separator * self.max_line_len)
+        print(Processor.LINE_SEPARATOR * Processor.MAX_LINE_LEN)
         print()
 
     def pretty_print_names(self, module_to_line_length: dict[Module, int]) -> None:
         """
-        Prints the name of the modules in one row, but pretty.
+        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.
 
-        Adds spacing between the names so that the modules
-        longest field will have space to be printed below.
+        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
@@ -563,9 +678,20 @@ class Processor:
     def group_pp_modules(
         self, module_to_line_length: dict[Module, int]
     ) -> list[dict[Module, int]]:
-        """
-        Groups the modules to be pretty printed into groups with a
-        total line length lower than 'self.max_line_len'.
+        """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 = [{}]
@@ -574,7 +700,7 @@ class Processor:
         for module in module_to_line_length:
 
             # Make sure the line is not to long
-            if line_len + module_to_line_length[module] < self.max_line_len:
+            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]
 
@@ -588,8 +714,21 @@ class Processor:
 
     def fields_to_list(self, module: Module, ignore_keys=[]) -> list[str]:
         """
-        Return a list containing all the keys for a module except the name.
-        Optinal argument to ignore specific keys.
+        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
@@ -597,12 +736,29 @@ class Processor:
             if key != "name" and key not in ignore_keys
         ]
 
-    def get_most_fields(self, modules: dict[Module: int], ignore_keys=[]) -> int:
-        """
-        Return the most number of a fields a module has.
+    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))
@@ -614,6 +770,24 @@ class Processor:
     def add_state_breakpoint(
         self, module_name: str, state_name: str, value: Any
     ) -> None:
+        """Add a module state breakpoint to the processor.
+
+        Parameters
+        ----------
+            module_name : str
+                Name of the module for which a breakpoint will be added.
+            state_name : str
+                Name of the state variable of the module to put a breakpoint
+                on.
+            value : Any
+                Value of the state variable that triggers the breakpoint.
+
+        Raises
+        ------
+        ValueError
+            If the module does not exist or if the state variable does not
+            exist in the module.
+        """
 
         if module_name not in self.modules:
             raise ValueError(f"No module named {module_name}")
@@ -628,12 +802,20 @@ class Processor:
         self.breakpoint_id_counter += 1
 
     def remove_breakpoint(self, id: int) -> bool:
+        """Remove a specific breakpoint.
+
+        Parameters
+        ----------
+        id : int
+            ID of the breakpoint to be removed.
+        """
         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:
             print("There are no breakpoints.")
         else:
@@ -641,6 +823,22 @@ class Processor:
                 print(f"BP {bp_id}: {bp}")
 
     def add_memory_breakpoint(self, module_name: str, address: int, value: Any) -> None:
+        """Add a breakpoint for a memory module.
+
+        Parameters
+        ----------
+        module_name : str
+            Name of the memory module for which a breakpoint will be added.
+        address : int
+            Address of the memory module to break at.
+        value : Any
+            Value of the address that triggers the breakpoint.
+
+        Raises
+        ------
+        ValueError
+            If the module does not exist or is not a memory.
+        """
 
         if module_name not in self.modules:
             raise ValueError(f"No module named {module_name}")
@@ -654,9 +852,37 @@ class Processor:
         self.breakpoint_id_counter += 1
 
     def get_breakpoint_lambdas(self) -> list[str]:
+        """Get all functions available for lambda breakpoints.
+
+        Returns
+        -------
+        list[str]
+            List of names of all functions of the processor that are available
+            for adding lambda breakpoints.
+        """
+
         return list(self.lambdas.keys())
 
     def add_lambda_breakpoint(self, lambda_name: str, **kwargs) -> None:
+        """Add a lambda breakpoint to the processor.
+
+        Module names used in the keyword arguments are substituted by the
+        actual modules before being passed on to the lambda breakpoint
+        function.
+
+        Parameters
+        ----------
+        lambda_name : str
+            Name of the lambda breakpoint function to be used by the
+            breakpoint.
+        **kwargs
+            Arguments to pass to the breakpoint function.
+
+        Raises
+        ------
+        ValueError
+            If the  lambda breakpoint function does not exist.
+        """
         # Substitute any module names for the module instances
         # This is to be able to externally create general lambda breakpoints
         # that can take any values as arguments while also having a way to take
@@ -675,4 +901,13 @@ class Processor:
         self.breakpoint_id_counter += 1
 
     def set_enabled_breakpoint(self, bp_id: int, is_enabled: bool) -> None:
+        """Toggle a breakpoint to enabled or disabled.
+
+        Parameters
+        ----------
+        bp_id : int
+            ID of the breakpoint to toggle.
+        is_enabled : bool
+            ``True`` to enable, ``False`` to disable the breakpoint.
+        """
         self.breakpoints[bp_id].set_enabled(is_enabled)
diff --git a/src/simudator/core/signal.py b/src/simudator/core/signal.py
index 18e3193b9a85a2a4db629c117bef53b24ad197f0..8db1d14133278add895bc9b776f778addb5116df 100644
--- a/src/simudator/core/signal.py
+++ b/src/simudator/core/signal.py
@@ -5,57 +5,79 @@ from typing import Any
 
 class Signal:
     """
-    Handles datatransportation between modules in the processor.
-    Each signal has one source module and can have multiple
-    destination modules.
+    Signal class to send data between modules in a processor.
+
+    Parameters
+    ----------
+    processor : Processor
+        Processor that the signal belongs to. Needed to queue processor modules
+        for update.
+    name : str
+        Name of the signal.
+    value : Any
+        Initial value of the signal.
     """
 
-    __slots__ = ("processor", "name", "source", "destinations", "value")
+    __slots__ = ("_processor", "_name", "_source", "_destinations", "_value")
 
     def __init__(self, processor: Processor, name: str = "Signal", value=None):
-        self.processor = processor
-        self.name = name
-        self.source = None
-        self.destinations = set()
-        self.value = value
+        self._processor = processor
+        self._name = name
+        self._source = None
+        self._destinations = set()
+        self._value = value
 
     def add_destination(self, module: Module) -> None:
-        """
-        Add a destination module that the signal will send new
+        """Add a module as a destination that the signal will send new
         values to.
         """
-        self.destinations.add(module)
-
-    def set_source(self, module: Module) -> None:
-        """
-        Set source module that will send values through the signal.
-        """
-        self.source = module
+        self._destinations.add(module)
 
     def update_value(self, value) -> None:
         """
-        Sets value in signal and queues destination moduels for update.
+        Set the value of the signal and queue destination modules for update.
+
+        Parameters
+        ----------
+        value : Any
+            Value to set the signal to.
         """
-        if value != self.value:
-            self.value = value
+        if value != self._value:
+            self._value = value
             # Inform the processor on what modules have been given
             # signal so they can update
-            for destination in self.destinations:
-                self.processor.add_modules_to_update(destination)
+            for destination in self._destinations:
+                self._processor.add_modules_to_update(destination)
 
     def get_value(self) -> Any:
-        """
-        Get the signals current value.
-        """
-        return self.value
+        """Get the current value of the signal.
 
-    def set_value(self, value) -> None:
+        Returns
+        -------
+        Any
+            Value of the signal.
         """
-        Set the value of the signal without queuing the destination
-        modules of the signal for update. This method should not
-        be called by a module.
+        return self._value
+
+    def set_value(self, value: Any) -> None:
+        """Set the value of the signal without queuing the destination
+        modules of the signal for update.
+
+        This method should not be called by a module.
+
+        Parameters
+        ----------
+        value : any
+            Value to set the signal to.
         """
-        self.value = value
+        self._value = value
 
     def get_name(self) -> str:
-        return self.name
+        """Return the name of the signal.
+
+        Returns
+        -------
+        str
+            Name of the signal.
+        """
+        return self._name
diff --git a/src/simudator/processor/mia/modules/ar.py b/src/simudator/processor/mia/modules/ar.py
index bca9795267a761968984bd26eef6069031551c36..a1e2c6ff115f840fb9bc4b260fa07eb6a7679a6f 100644
--- a/src/simudator/processor/mia/modules/ar.py
+++ b/src/simudator/processor/mia/modules/ar.py
@@ -33,7 +33,7 @@ class AR(IntegerRegister, MiaBusConnector):
 
     def output_register(self) -> None:
         # always update alu
-        self.signals["out_alu"].update_value(self.value)
+        self.signals["out_alu"].update_value(self._value)
 
         # only update bus when asked too
         if self.write_to_bus():
@@ -53,7 +53,7 @@ class AR(IntegerRegister, MiaBusConnector):
             self.name,
             "\n -----",
             "\n value: ",
-            hex(self.value),
+            hex(self._value),
             "\n bit length: ",
             self.bit_length,
         )
diff --git a/src/simudator/processor/mia/modules/asr.py b/src/simudator/processor/mia/modules/asr.py
index ae096c07b38ddf85e82366c617e474a8eb56a3e9..08fa4c07a4c453198c0dab1d43b7b729d60f8f1e 100644
--- a/src/simudator/processor/mia/modules/asr.py
+++ b/src/simudator/processor/mia/modules/asr.py
@@ -41,7 +41,7 @@ class ASR(IntegerRegister, MiaBusConnector):
             self.name,
             "\n -----",
             "\n value: ",
-            hex(self.value),
+            hex(self._value),
             "\n bit length: ",
             self.bit_length,
         )
diff --git a/src/simudator/processor/mia/modules/hr.py b/src/simudator/processor/mia/modules/hr.py
index 506c4d5b14a543f9e3c3095cfa03cf73461735b7..bd74491b83632dcbe52679eaba363326fece177c 100644
--- a/src/simudator/processor/mia/modules/hr.py
+++ b/src/simudator/processor/mia/modules/hr.py
@@ -21,11 +21,11 @@ class HR(IntegerRegister, MiaBusConnector):
         bus_output_signal: Signal,
         bus_control_signal: Signal,
         bus_id: int,
-        bit_lenght: int,
+        bit_length: int,
         name="HR",
     ) -> None:
         IntegerRegister.__init__(
-            self, bus_input_signal, bus_output_signal, bit_lenght, name=name
+            self, bus_input_signal, bus_output_signal, bit_length, name=name
         )
         MiaBusConnector.__init__(self, bus_control_signal, bus_id)
 
@@ -45,7 +45,8 @@ class HR(IntegerRegister, MiaBusConnector):
 
         elif self.signals["in_alu"].get_value() is not None:
             input_value = self.signals["in_alu"].get_value()
-            self.value = input_value & self.mask
+            mask = 2**self._bit_length - 1
+            self._value = input_value & mask
 
     def output_register(self) -> None:
         """
@@ -54,7 +55,7 @@ class HR(IntegerRegister, MiaBusConnector):
         output the alu signal.
         """
 
-        self.signals["out_alu"].update_value(self.value)
+        self.signals["out_alu"].update_value(self._value)
 
         if self.write_to_bus():
             IntegerRegister.output_register(self)
@@ -71,7 +72,7 @@ class HR(IntegerRegister, MiaBusConnector):
             self.name,
             "\n -----",
             "\n value: ",
-            hex(self.value),
+            hex(self._value),
             "\n bit length: ",
-            self.bit_length,
+            self._bit_length,
         )
diff --git a/src/simudator/processor/mia/modules/mia_memory.py b/src/simudator/processor/mia/modules/mia_memory.py
index 988f506b9934f616751b4aca28aac7e5cb5b49a0..4b2ca42c137f718c4260e5ab9064f2a5a8b2d573 100644
--- a/src/simudator/processor/mia/modules/mia_memory.py
+++ b/src/simudator/processor/mia/modules/mia_memory.py
@@ -11,7 +11,7 @@ class MiaMemory(MiaBusConnector, Memory):
     to/from the mia bus.
     """
 
-    # Python does not allow multiple inherintence if more than one of the 
+    # Python does not allow multiple inherintence if more than one of the
     # parent classes uses __slots__. Thus we also includes the __slots__
     # from MiaBusConnector.
     __slots__ = ("label_adress_mapping", "bus_id", "bus_control_s")
@@ -24,8 +24,6 @@ class MiaMemory(MiaBusConnector, Memory):
         bus_control_s: Signal,
         size: int = 1,
         bus_id: int = 0,
-        value_padding: int = 2,
-        address_padding: int = 2,
         name: str = "PM",
     ) -> None:
         MiaBusConnector.__init__(self, bus_control_s, bus_id)
@@ -37,8 +35,6 @@ class MiaMemory(MiaBusConnector, Memory):
             address_signal,
             size,
             name=name,
-            value_padding=value_padding,
-            address_padding=address_padding,
         )
         self.bus_control_s.add_destination(self)
 
@@ -49,14 +45,16 @@ class MiaMemory(MiaBusConnector, Memory):
         Updates the value of the current address.
         """
         if self.read_from_bus():
-            self.memory[self.current_address] = self.signals["in_input"].get_value()
+            self._memory[self._current_address] = self.signals["in_input"].get_value()
 
     def output_register(self) -> None:
         """
         Outputs the value of the current address.
         """
         if self.write_to_bus():
-            self.signals["out_content"].update_value(self.memory[self.current_address])
+            self.signals["out_content"].update_value(
+                self._memory[self._current_address]
+            )
         else:
             self.signals["out_content"].update_value(None)
 
@@ -67,17 +65,17 @@ class MiaMemory(MiaBusConnector, Memory):
         """
         address_value = self.signals["in_address"].get_value()
         if address_value is not None:
-            self.current_address = address_value
+            self._current_address = address_value
             if self.write_to_bus():
                 self.signals["out_content"].update_value(
-                    self.memory[self.current_address]
+                    self._memory[self._current_address]
                 )
             else:
                 self.signals["out_content"].update_value(None)
 
     def reset(self) -> None:
-        size = len(self.memory)
-        self.memory = [0 for i in range(size)]
+        size = len(self._memory)
+        self._memory = [0 for _ in range(size)]
 
     def load_from_str(self, state_string) -> None:
         """
@@ -95,7 +93,7 @@ class MiaMemory(MiaBusConnector, Memory):
                 # Last character of the adress is a semicolon
                 adress = int(line_data[0][:-1], 16)
 
-                self.memory[adress] = value
+                self._memory[adress] = value
 
                 # There is an asm instruction label
                 if len(line_data) == 3:
diff --git a/src/simudator/processor/mia/modules/micro_pc.py b/src/simudator/processor/mia/modules/micro_pc.py
index f574fc345be55899556ef5587332c4d0e90bf376..adcd99ffefb2c09e95fb0f3d68544a09c9eea770 100644
--- a/src/simudator/processor/mia/modules/micro_pc.py
+++ b/src/simudator/processor/mia/modules/micro_pc.py
@@ -22,12 +22,10 @@ class MicroPC(Module):
         from_supc: Signal,
         to_um: Signal,
         from_um: Signal,
-        bit_length: int = 8,
         name: str = "uPC",
     ) -> None:
 
         self.value = 0
-        self.bit_length = bit_length
 
         # Signals
         signals = {
@@ -71,7 +69,6 @@ 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:
@@ -84,8 +81,6 @@ class MicroPC(Module):
     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/test/test_core/test_demux.py b/test/test_core/test_demux.py
index acf92510f17faaf59c475e6426384214ac68eec8..e4c59c3d04f7dc5f73d11c131cfabf87b5301120 100644
--- a/test/test_core/test_demux.py
+++ b/test/test_core/test_demux.py
@@ -38,7 +38,6 @@ def test_get_state():
     assert state["name"] == "Demux"
     assert state["value"] == 7
     assert state["bit_length"] == 5
-    assert state["mask"] == 31
 
 
 def test_set_state():
@@ -46,7 +45,6 @@ def test_set_state():
     state["name"] = "Demux"
     state["value"] = 6
     state["bit_length"] = 2
-    state["mask"] = 3
 
     cpu = Processor()
     from_demux = Signal(cpu)
@@ -57,10 +55,10 @@ def test_set_state():
 
     demux.set_state(state)
 
-    assert demux.name == "Demux"
-    assert demux.value == 6
-    assert demux.bit_length == 2
-    assert demux.mask == 3
+    state = demux.get_state()
+    assert state["name"] == "Demux"
+    assert state["value"] == 6
+    assert state["bit_length"] == 2
 
 
 def test_writing_to_output():
diff --git a/test/test_core/test_register.py b/test/test_core/test_register.py
index ae6f51127da4fb86673387e86e9abb1b2b83d000..1d1d85589a2a2851b7e9cf9710282b2c4eca8180 100644
--- a/test/test_core/test_register.py
+++ b/test/test_core/test_register.py
@@ -26,7 +26,7 @@ def test_set_state():
     register.set_state(state)
 
     assert register.name == "Reg"
-    assert register.value == 14
+    assert register._value == 14
 
 
 def test_get_state():
@@ -51,4 +51,4 @@ def test_signal_propagation():
     input_s.update_value(10)
     cpu.do_tick()
 
-    assert register.value == 10
+    assert register._value == 10
diff --git a/test/test_mia/test_lc.py b/test/test_mia/test_lc.py
index aaa591c611a661a94302578b79dd0c2ba4400d0d..407979aead137cf1d3d965f5377442dbc7f822c6 100644
--- a/test/test_mia/test_lc.py
+++ b/test/test_mia/test_lc.py
@@ -84,7 +84,7 @@ def test_write_to_l_flag():
     # The loop counter will now change its value from 1 to 0 which
     # should set the L flag to 1 in the same cycle
     cpu.do_tick()
-    assert l_flag.value == 1
+    assert l_flag._value == 1
 
 
 def test_reset_l_flag():
@@ -110,7 +110,7 @@ def test_reset_l_flag():
     mM_uADR_s.update_value(10)
 
     cpu.do_tick()
-    assert l_flag.value == 0
+    assert l_flag._value == 0
 
 
 def test_lc_do_nothing():
diff --git a/test/test_mia/test_step.py b/test/test_mia/test_step.py
index 028945db7c22021a701b68765ee734d70608f9e0..e83de422418ab74ad1b6adce9b5bdba52f6e0423 100644
--- a/test/test_mia/test_step.py
+++ b/test/test_mia/test_step.py
@@ -1,3 +1,4 @@
+from simudator.core.processor import Processor
 from simudator.processor.mia.mia import MIA_CPU
 
 
@@ -16,7 +17,7 @@ def test_increment_10():
 def test_max_undo():
     cpu = MIA_CPU()
     cpu.load_state_from_file("mia_uppg3.txt")
-    max_undo = cpu.cycles_to_save
+    max_undo = Processor.CYCLES_TO_SAVE
 
     for _ in range(2 * max_undo):
         cpu.do_tick()