diff --git a/.clang-format b/.clang-format
index 22e04bab0e95d05981218e51cd6affb85f82a45f..e8824535c7b8151dbc29d629c1221b5cc1cc04ec 100644
--- a/.clang-format
+++ b/.clang-format
@@ -148,4 +148,4 @@ TypenameMacros:
   - LIST
   - LIST_ENTRY
 
-UseTab: ForContinuationAndIndentation
\ No newline at end of file
+UseTab: ForContinuationAndIndentation
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..48ee0308d3ccab3f18b36291d2b8d1183a4a563e
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,11 @@
+repos:
+-   repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v2.3.0
+    hooks:
+    -   id: check-yaml
+    -   id: end-of-file-fixer
+    -   id: trailing-whitespace
+-   repo: https://github.com/psf/black
+    rev: 22.10.0
+    hooks:
+    -   id: black
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d087f8644c61f7e14d89fe3cde7ffc17f12cb87..f10f60c93fe2f52d84f67764f28736493a553250 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,7 +41,7 @@ pybind11_add_module("${TARGET_NAME}"
 	# Main files.
 	"${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp"
 	"${CMAKE_CURRENT_SOURCE_DIR}/src/simulation.cpp"
-	
+
 	# For DOD simulation.
 	"${CMAKE_CURRENT_SOURCE_DIR}/src/simulation/compile.cpp"
 	"${CMAKE_CURRENT_SOURCE_DIR}/src/simulation/run.cpp"
diff --git a/b_asic/GUI/gui_interface.ui b/b_asic/GUI/gui_interface.ui
index 382747818a3286373b825e4115c9b283799156bc..fb0f07cf3dd6e3232d3f1fbe75784d1eea4c7008 100644
--- a/b_asic/GUI/gui_interface.ui
+++ b/b_asic/GUI/gui_interface.ui
@@ -33,11 +33,11 @@
      <bool>false</bool>
     </property>
     <property name="styleSheet">
-     <string notr="true">QGroupBox { 
-     border: 2px solid gray; 
+     <string notr="true">QGroupBox {
+     border: 2px solid gray;
      border-radius: 3px;
-	 margin-top: 0.5em; 
- } 
+	 margin-top: 0.5em;
+ }
 
 QGroupBox::title {
     subcontrol-origin: margin;
diff --git a/docs_sphinx/api/core_operations.rst b/docs_sphinx/api/core_operations.rst
index c362191cfe742245c5b883b07a43cf697e839eeb..de51d4a6034356ac8ba1a0988690f8cf5e7db5d5 100644
--- a/docs_sphinx/api/core_operations.rst
+++ b/docs_sphinx/api/core_operations.rst
@@ -10,4 +10,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/docs_sphinx/api/graph_component.rst b/docs_sphinx/api/graph_component.rst
index 5c599035504cc5e7ce4f065f9632d780be75726d..9d0bbe09aee08e0bfac788c0672a6b458be49e4d 100644
--- a/docs_sphinx/api/graph_component.rst
+++ b/docs_sphinx/api/graph_component.rst
@@ -10,4 +10,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/docs_sphinx/api/index.rst b/docs_sphinx/api/index.rst
index 9fa924758cff84fd65cfd2c5d2770e16eba9c594..a4cc2476e38e199b0509f1df55f2f8d7bedbb5d7 100644
--- a/docs_sphinx/api/index.rst
+++ b/docs_sphinx/api/index.rst
@@ -4,7 +4,7 @@ API
 ===
 .. toctree::
     :maxdepth: 1
-	       
+
     core_operations.rst
     graph_component.rst
     operation.rst
diff --git a/docs_sphinx/api/operation.rst b/docs_sphinx/api/operation.rst
index 2d96ba5a4754467e6859d520174b1f4160dc63e8..22d3c0b4427f8623ed049eb8dda28f5c5021b0b4 100644
--- a/docs_sphinx/api/operation.rst
+++ b/docs_sphinx/api/operation.rst
@@ -5,7 +5,7 @@
 .. inheritance-diagram:: b_asic.operation
    :parts: 1
    :top-classes: b_asic.graph_component.GraphComponent, b_asic.port.SignalSourceProvider
-		 
+
 .. automodule:: b_asic.operation
    :members:
    :undoc-members:
diff --git a/docs_sphinx/api/port.rst b/docs_sphinx/api/port.rst
index f34f4301d8fd1a5de1c053228dd9334327f0b484..40872c7682356d166200e884904120f8e650801e 100644
--- a/docs_sphinx/api/port.rst
+++ b/docs_sphinx/api/port.rst
@@ -10,4 +10,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/docs_sphinx/api/signal.rst b/docs_sphinx/api/signal.rst
index 2997948603598b3a35d621793890e59b48626203..3e928163b6be2ceb234b1c192f636da2abf95cf0 100644
--- a/docs_sphinx/api/signal.rst
+++ b/docs_sphinx/api/signal.rst
@@ -6,4 +6,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/docs_sphinx/api/signal_flow_graph.rst b/docs_sphinx/api/signal_flow_graph.rst
index ee2f7fb0e452f3bd2c67411a5ff0e43960b2dd42..757936e4731d8c422305bd8af85934f8481dcb09 100644
--- a/docs_sphinx/api/signal_flow_graph.rst
+++ b/docs_sphinx/api/signal_flow_graph.rst
@@ -6,4 +6,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/docs_sphinx/api/simulation.rst b/docs_sphinx/api/simulation.rst
index 580596f56b45a9452b726df4a6622e324073eb7f..6c74873cc0051d5566bc61de3c7dbf68d9f14c6b 100644
--- a/docs_sphinx/api/simulation.rst
+++ b/docs_sphinx/api/simulation.rst
@@ -6,4 +6,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/docs_sphinx/api/special_operations.rst b/docs_sphinx/api/special_operations.rst
index d80e446051d42e1b50b6c23fe727a954523bbb25..e3585c98d5bc2449b10ec16b551726b83f6b6d22 100644
--- a/docs_sphinx/api/special_operations.rst
+++ b/docs_sphinx/api/special_operations.rst
@@ -10,4 +10,3 @@
    :members:
    :undoc-members:
    :show-inheritance:
-
diff --git a/examples/secondorderdirectformiir.py b/examples/secondorderdirectformiir.py
index f812d10fe86e8a51808d37c98620763b9cb91103..49cb20d3bee656e51e5de001873a5e32439d6e13 100644
--- a/examples/secondorderdirectformiir.py
+++ b/examples/secondorderdirectformiir.py
@@ -34,7 +34,9 @@ a0 = ConstantMultiplication(0.7, add1, "A0")
 add4 = Addition(a0, add3, "ADD4")
 out1 = Output(add4, "OUT1")
 
-sfg = SFG(inputs=[in1], outputs=[out1], name="Second-order direct form IIR filter")
+sfg = SFG(
+    inputs=[in1], outputs=[out1], name="Second-order direct form IIR filter"
+)
 
 # Set latencies and exection times
 sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2)
diff --git a/examples/thirdorderblwdf.py b/examples/thirdorderblwdf.py
index 65dd4b4d1c705e4e6accfb28e9914d4aec240423..bc2676d4476081c128c198421c35fc1e0feb9ce3 100644
--- a/examples/thirdorderblwdf.py
+++ b/examples/thirdorderblwdf.py
@@ -16,8 +16,7 @@ D1 << s.output(1)
 a = s.output(0) + D0
 out0 = Output(a, "y")
 
-sfg = SFG(inputs=[in0], outputs=[out0],
-          name="Third-order BLWDF")
+sfg = SFG(inputs=[in0], outputs=[out0], name="Third-order BLWDF")
 
 # Set latencies and exection times
 sfg.set_latency_of_type(SymmetricTwoportAdaptor.type_name(), 4)
@@ -29,10 +28,12 @@ sim = Simulation(sfg, [lambda n: 0 if n else 1])
 sim.run_for(1000)
 
 import scipy.signal
+
 w, h = scipy.signal.freqz(sim.results['0'])
 
 import numpy as np
 import matplotlib.pyplot as plt
-plt.plot(w, 20*np.log10(np.abs(h)/2))
+
+plt.plot(w, 20 * np.log10(np.abs(h) / 2))
 
 schedule = Schedule(sfg, cyclic=True)
diff --git a/examples/threepointwinograddft.py b/examples/threepointwinograddft.py
index ea34231bc6020cf2c74d1626d987d421f1e1a5cc..6d81fea8eaa64d1d66949413427bc16481a4ada7 100644
--- a/examples/threepointwinograddft.py
+++ b/examples/threepointwinograddft.py
@@ -1,13 +1,17 @@
 """Three-point Winograd DFT.
 """
 
-from b_asic.core_operations import Addition, ConstantMultiplication, Subtraction
+from b_asic.core_operations import (
+    Addition,
+    ConstantMultiplication,
+    Subtraction,
+)
 from b_asic.special_operations import Input, Output
 from b_asic.signal_flow_graph import SFG
 from b_asic.schedule import Schedule
 from math import cos, pi, sin
 
-u = -2*pi/3
+u = -2 * pi / 3
 c30 = cos(u) - 1
 c31 = sin(u)
 
@@ -27,8 +31,11 @@ out0 = Output(a2, "X0")
 out1 = Output(a4, "X1")
 out2 = Output(a5, "X2")
 
-sfg = SFG(inputs=[in0, in1, in2], outputs=[out0, out1, out2],
-          name="3-point Winograd DFT")
+sfg = SFG(
+    inputs=[in0, in1, in2],
+    outputs=[out0, out1, out2],
+    name="3-point Winograd DFT",
+)
 
 # Set latencies and exection times
 sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2)
diff --git a/setup.py b/setup.py
index 9bd763301bef4edca2ab7753b74398e22894dd14..0c8ec302250cb891772351d37a005026fb3ebbc8 100644
--- a/setup.py
+++ b/setup.py
@@ -15,9 +15,9 @@ class CMakeExtension(Extension):
 
 class CMakeBuild(build_ext):
     def build_extension(self, ext):
-
         CMAKE_EXE = os.environ.get(
-            "CMAKE_EXE", shutil.which("cmake3") or shutil.which("cmake"))
+            "CMAKE_EXE", shutil.which("cmake3") or shutil.which("cmake")
+        )
         if not isinstance(ext, CMakeExtension):
             return super().build_extension(ext)
 
@@ -25,21 +25,27 @@ class CMakeBuild(build_ext):
             raise RuntimeError(
                 f"Cannot build extension {ext.name}: CMake executable not "
                 "found! Set the CMAKE_EXE environment variable or update your "
-                "path.")
+                "path."
+            )
 
         cmake_build_type = "Debug" if self.debug else "Release"
         cmake_output_dir = os.path.abspath(
-            os.path.dirname(self.get_ext_fullpath(ext.name)))
+            os.path.dirname(self.get_ext_fullpath(ext.name))
+        )
         cmake_configure_argv = [
-            CMAKE_EXE, ext.sourcedir,
+            CMAKE_EXE,
+            ext.sourcedir,
             "-DASIC_BUILDING_PYTHON_DISTRIBUTION=ON",
             "-DCMAKE_BUILD_TYPE=" + cmake_build_type,
             "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + cmake_output_dir,
             "-DPYTHON_EXECUTABLE=" + sys.executable,
         ]
         cmake_build_argv = [
-            CMAKE_EXE, "--build", ".",
-            "--config", cmake_build_type
+            CMAKE_EXE,
+            "--build",
+            ".",
+            "--config",
+            cmake_build_type,
         ]
 
         if not os.path.exists(self.build_temp):
@@ -50,8 +56,9 @@ class CMakeBuild(build_ext):
         print(f"=== Configuring {ext.name} ===")
         print(f"Temp dir: {self.build_temp}")
         print(f"Output dir: {cmake_output_dir}")
-        subprocess.check_call(cmake_configure_argv,
-                              cwd=self.build_temp, env=env)
+        subprocess.check_call(
+            cmake_configure_argv, cwd=self.build_temp, env=env
+        )
 
         print(f"=== Building {ext.name} ===")
         print(f"Temp dir: {self.build_temp}")
@@ -63,14 +70,18 @@ class CMakeBuild(build_ext):
 
 
 setuptools.setup(
-    author="Adam Jakobsson, Angus Lothian, Arvid Westerlund, Felix Goding, "
+    author=(
+        "Adam Jakobsson, Angus Lothian, Arvid Westerlund, Felix Goding, "
         "Ivar Härnqvist, Jacob Wahlman, Kevin Scott, Rasmus Karlsson, "
-        "Oscar Gustafsson, Andreas Bolin",
-    author_email="adaja901@student.liu.se, anglo547@student.liu.se, "
+        "Oscar Gustafsson, Andreas Bolin"
+    ),
+    author_email=(
+        "adaja901@student.liu.se, anglo547@student.liu.se, "
         "arvwe160@student.liu.se, felgo673@student.liu.se, "
         "ivaha717@student.liu.se, jacwa448@student.liu.se, "
         "kevsc634@student.liu.se, raska119@student.liu.se, "
-        "oscar.gustafsson@liu.se, andbo467@student.liu.se",
+        "oscar.gustafsson@liu.se, andbo467@student.liu.se"
+    ),
     ext_modules=[CMakeExtension("_b_asic")],
     cmdclass={"build_ext": CMakeBuild},
 )
diff --git a/test/test_operation.py b/test/test_operation.py
index e09aa5fa55bb1758c4fd18bf2e6d2d459b08ba1b..a92f07ce45129cf2f225705c6a260aa21c43f736 100644
--- a/test/test_operation.py
+++ b/test/test_operation.py
@@ -17,7 +17,8 @@ from b_asic import (
 
 class TestOperationOverloading:
     def test_addition_overload(self):
-        """Tests addition overloading for both operation and number argument."""
+        """Tests addition overloading for both operation and number argument.
+        """
         add1 = Addition(None, None, "add1")
         add2 = Addition(None, None, "add2")
 
@@ -37,7 +38,8 @@ class TestOperationOverloading:
         assert add5.input(1).signals == add4.output(0).signals
 
     def test_subtraction_overload(self):
-        """Tests subtraction overloading for both operation and number argument."""
+        """Tests subtraction overloading for both operation and number argument.
+        """
         add1 = Addition(None, None, "add1")
         add2 = Addition(None, None, "add2")
 
@@ -57,7 +59,8 @@ class TestOperationOverloading:
         assert sub3.input(1).signals == sub2.output(0).signals
 
     def test_multiplication_overload(self):
-        """Tests multiplication overloading for both operation and number argument."""
+        """Tests multiplication overloading for both operation and number argument.
+        """
         add1 = Addition(None, None, "add1")
         add2 = Addition(None, None, "add2")
 
@@ -77,7 +80,8 @@ class TestOperationOverloading:
         assert mul3.value == 5
 
     def test_division_overload(self):
-        """Tests division overloading for both operation and number argument."""
+        """Tests division overloading for both operation and number argument.
+        """
         add1 = Addition(None, None, "add1")
         add2 = Addition(None, None, "add2")
 
diff --git a/test/test_process.py b/test/test_process.py
index 80dd2ab6bd77dc295747549fbce2d6dd348374eb..57837ee2692e02be854546b32c89f15b5c445501 100644
--- a/test/test_process.py
+++ b/test/test_process.py
@@ -2,6 +2,7 @@ import pytest
 
 from b_asic.process import PlainMemoryVariable
 
+
 def test_PlainMemoryVariable():
     mem = PlainMemoryVariable(3, 0, {4: 1, 5: 2})
     assert mem.write_port == 0
diff --git a/test/test_sfg.py b/test/test_sfg.py
index b965e80ad014200fdc92e34039238daa7ac4a6f2..ac73cf3f5fa88e67c5ad0c7a69ee19f47dbcfe0e 100644
--- a/test/test_sfg.py
+++ b/test/test_sfg.py
@@ -78,7 +78,8 @@ class TestPrintSfg:
 
         assert (
             sfg.__str__()
-            == "id: no_id, \tname: SFG1, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n"
+            == "id: no_id, \tname: SFG1, \tinputs: {0: '-'}, \toutputs: {0:"
+            " '-'}\n"
             + "Internal Operations:\n"
             + "----------------------------------------------------------------------------------------------------\n"
             + str(sfg.find_by_name("INP1")[0])
@@ -103,7 +104,8 @@ class TestPrintSfg:
 
         assert (
             sfg.__str__()
-            == "id: no_id, \tname: mac_sfg, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n"
+            == "id: no_id, \tname: mac_sfg, \tinputs: {0: '-'}, \toutputs: {0:"
+            " '-'}\n"
             + "Internal Operations:\n"
             + "----------------------------------------------------------------------------------------------------\n"
             + str(sfg.find_by_name("INP1")[0])
@@ -131,7 +133,8 @@ class TestPrintSfg:
 
         assert (
             sfg.__str__()
-            == "id: no_id, \tname: sfg, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n"
+            == "id: no_id, \tname: sfg, \tinputs: {0: '-'}, \toutputs: {0:"
+            " '-'}\n"
             + "Internal Operations:\n"
             + "----------------------------------------------------------------------------------------------------\n"
             + str(sfg.find_by_name("CONST")[0])
@@ -148,7 +151,8 @@ class TestPrintSfg:
     def test_simple_filter(self, sfg_simple_filter):
         assert (
             sfg_simple_filter.__str__()
-            == "id: no_id, \tname: simple_filter, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n"
+            == "id: no_id, \tname: simple_filter, \tinputs: {0: '-'},"
+            " \toutputs: {0: '-'}\n"
             + "Internal Operations:\n"
             + "----------------------------------------------------------------------------------------------------\n"
             + str(sfg_simple_filter.find_by_name("IN1")[0])
@@ -620,7 +624,6 @@ class TestFindComponentsWithTypeName:
 
 class TestGetPrecedenceList:
     def test_inputs_delays(self, precedence_sfg_delays):
-
         precedence_list = precedence_sfg_delays.get_precedence_list()
 
         assert len(precedence_list) == 7
@@ -677,7 +680,6 @@ class TestGetPrecedenceList:
     def test_inputs_constants_delays_multiple_outputs(
         self, precedence_sfg_delays_and_constants
     ):
-
         precedence_list = (
             precedence_sfg_delays_and_constants.get_precedence_list()
         )
@@ -955,7 +957,8 @@ class TestConnectExternalSignalsToComponentsSoloComp:
     def test_connect_external_signals_to_components_operation_tree(
         self, operation_tree
     ):
-        """Replaces an SFG with only a operation_tree component with its inner components"""
+        """Replaces an SFG with only a operation_tree component with its inner components
+        """
         sfg1 = SFG(outputs=[Output(operation_tree)])
         out1 = Output(None, "OUT1")
         out1.input(0).connect(sfg1.outputs[0], "S1")
@@ -968,7 +971,8 @@ class TestConnectExternalSignalsToComponentsSoloComp:
     def test_connect_external_signals_to_components_large_operation_tree(
         self, large_operation_tree
     ):
-        """Replaces an SFG with only a large_operation_tree component with its inner components"""
+        """Replaces an SFG with only a large_operation_tree component with its inner components
+        """
         sfg1 = SFG(outputs=[Output(large_operation_tree)])
         out1 = Output(None, "OUT1")
         out1.input(0).connect(sfg1.outputs[0], "S1")
@@ -1030,7 +1034,8 @@ class TestConnectExternalSignalsToComponentsMultipleComp:
         assert not test_sfg.connect_external_signals_to_components()
 
     def create_sfg(self, op_tree):
-        """Create a simple SFG with either operation_tree or large_operation_tree"""
+        """Create a simple SFG with either operation_tree or large_operation_tree
+        """
         sfg1 = SFG(outputs=[Output(op_tree)])
 
         inp1 = Input("INP1")
@@ -1050,7 +1055,8 @@ class TestConnectExternalSignalsToComponentsMultipleComp:
     def test_connect_external_signals_to_components_many_op(
         self, large_operation_tree
     ):
-        """Replaces an sfg component in a larger SFG with several component operations"""
+        """Replaces an sfg component in a larger SFG with several component operations
+        """
         inp1 = Input("INP1")
         inp2 = Input("INP2")
         inp3 = Input("INP3")
@@ -1357,20 +1363,21 @@ class TestGetComponentsOfType:
 class TestPrecedenceGraph:
     def test_precedence_graph(self, sfg_simple_filter):
         res = (
-            "digraph {\n\trankdir=LR\n\tsubgraph cluster_0 "
-            '{\n\t\tlabel=N1\n\t\t"in1.0" [label=in1]\n\t\t"t1.0" [label=t1]'
-            '\n\t}\n\tsubgraph cluster_1 {\n\t\tlabel=N2\n\t\t"cmul1.0" '
-            "[label=cmul1]\n\t}\n\tsubgraph cluster_2 "
-            '{\n\t\tlabel=N3\n\t\t"add1.0" [label=add1]\n\t}\n\t"in1.0" '
-            '-> add1\n\tadd1 [label=add1 shape=square]\n\tin1 -> "in1.0"'
-            '\n\tin1 [label=in1 shape=square]\n\t"t1.0" -> cmul1\n\tcmul1 '
-            '[label=cmul1 shape=square]\n\t"t1.0" -> out1\n\tout1 '
-            '[label=out1 shape=square]\n\tt1Out -> "t1.0"\n\tt1Out '
-            '[label=t1 shape=square]\n\t"cmul1.0" -> add1\n\tadd1 '
-            '[label=add1 shape=square]\n\tcmul1 -> "cmul1.0"\n\tcmul1 '
-            '[label=cmul1 shape=square]\n\t"add1.0" -> t1In\n\tt1In '
-            '[label=t1 shape=square]\n\tadd1 -> "add1.0"\n\tadd1 '
-            "[label=add1 shape=square]\n}\n"
+            "digraph {\n\trankdir=LR\n\tsubgraph cluster_0"
+            " {\n\t\tlabel=N1\n\t\t\"in1.0\" [label=in1]\n\t\t\"t1.0\""
+            " [label=t1]\n\t}\n\tsubgraph cluster_1"
+            " {\n\t\tlabel=N2\n\t\t\"cmul1.0\" [label=cmul1]\n\t}\n\tsubgraph"
+            " cluster_2 {\n\t\tlabel=N3\n\t\t\"add1.0\""
+            " [label=add1]\n\t}\n\t\"in1.0\" -> add1\n\tadd1 [label=add1"
+            " shape=square]\n\tin1 -> \"in1.0\"\n\tin1 [label=in1"
+            " shape=square]\n\t\"t1.0\" -> cmul1\n\tcmul1 [label=cmul1"
+            " shape=square]\n\t\"t1.0\" -> out1\n\tout1 [label=out1"
+            " shape=square]\n\tt1Out -> \"t1.0\"\n\tt1Out [label=t1"
+            " shape=square]\n\t\"cmul1.0\" -> add1\n\tadd1 [label=add1"
+            " shape=square]\n\tcmul1 -> \"cmul1.0\"\n\tcmul1 [label=cmul1"
+            " shape=square]\n\t\"add1.0\" -> t1In\n\tt1In [label=t1"
+            " shape=square]\n\tadd1 -> \"add1.0\"\n\tadd1 [label=add1"
+            " shape=square]\n}\n"
         )
 
         assert sfg_simple_filter.precedence_graph().source == res