diff --git a/CMakeLists.txt b/CMakeLists.txt
index 256d9973098f7681fb9c63602f8f9f0b614fa008..e0d087c07656292751f53b55abd2bdea0feeaeaa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@ project(
 find_package(fmt 5.2.1 REQUIRED)
 find_package(pybind11 CONFIG REQUIRED)
 
-set(LIBRARY_NAME "b_asic") # Name of the python folder.
+set(LIBRARY_NAME "b_asic") # Name of the python library directory.
 set(TARGET_NAME "_${LIBRARY_NAME}") # Name of this extension module.
 
 # Set output directory for compiled binaries.
diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py
index 06c190caa1a8560f90626ded013855dbd017077b..30dbba97c10e069b2216f44c2dd3c5771207094d 100644
--- a/b_asic/signal_flow_graph.py
+++ b/b_asic/signal_flow_graph.py
@@ -3,17 +3,20 @@ B-ASIC Signal Flow Graph Module.
 TODO: More info.
 """
 
-from typing import List, Iterable, Sequence, Dict, Optional, DefaultDict, MutableSet
+from typing import List, Iterable, Sequence, Dict, Optional, DefaultDict, MutableSet, Tuple
 from numbers import Number
 from collections import defaultdict, deque
 
 from b_asic.port import SignalSourceProvider, OutputPort
-from b_asic.operation import Operation, AbstractOperation, ResultKey, DelayMap, MutableResultMap, MutableDelayMap
+from b_asic.operation import Operation, AbstractOperation, ResultKey, DelayMap, MutableResultMap, MutableDelayMap, ResultKey
 from b_asic.signal import Signal
 from b_asic.graph_component import GraphID, GraphIDNumber, GraphComponent, Name, TypeName
 from b_asic.special_operations import Input, Output
 
 
+DelayQueue = List[Tuple[str, ResultKey, OutputPort]]
+
+
 class GraphIDGenerator:
     """A class that generates Graph IDs for objects."""
 
@@ -173,7 +176,7 @@ class SFG(AbstractOperation):
                 else:
                     output_string += "-, "
                 
-                if component.type_name is "c":
+                if component.type_name == "c":
                     output_string += "value: " + str(component.value) + ", input: ["
                 else:
                     output_string += "input: [" 
@@ -230,7 +233,13 @@ class SFG(AbstractOperation):
         for op, arg in zip(self._input_operations, self.truncate_inputs(input_values, bits_override) if truncate else input_values):
             op.value = arg
         
-        value = self._evaluate_source(self._output_operations[index].input(0).signals[0].source, results, delays, prefix, bits_override, truncate)
+        deferred_delays = []
+        value = self._evaluate_source(self._output_operations[index].input(0).signals[0].source, results, delays, prefix, bits_override, truncate, deferred_delays)
+        while deferred_delays:
+            new_deferred_delays = []
+            for key_base, key, src in deferred_delays:
+                self._do_evaluate_source(key_base, key, src, results, delays, prefix, bits_override, truncate, new_deferred_delays)
+            deferred_delays = new_deferred_delays
         results[self.key(index, prefix)] = value
         return value
 
@@ -422,22 +431,26 @@ class SFG(AbstractOperation):
         # The old SFG will be deleted by Python GC
         return self()
 
-    def _evaluate_source(self, src: OutputPort, results: MutableResultMap, delays: MutableDelayMap, prefix: str, bits_override: Optional[int], truncate: bool) -> Number:
-        src_prefix = prefix
-        if src_prefix:
-            src_prefix += "."
-        src_prefix += src.operation.graph_id
-
-        key = src.operation.key(src.index, src_prefix)
+    def _evaluate_source(self, src: OutputPort, results: MutableResultMap, delays: MutableDelayMap, prefix: str, bits_override: Optional[int], truncate: bool, deferred_delays: DelayQueue) -> Number:
+        key_base = (prefix + "." + src.operation.graph_id) if prefix else src.operation.graph_id
+        key = src.operation.key(src.index, key_base)
         if key in results:
             value = results[key]
             if value is None:
-                raise RuntimeError(f"Direct feedback loop detected when evaluating operation.")
+                raise RuntimeError("Direct feedback loop detected when evaluating operation.")
             return value
+        
+        value = src.operation.current_output(src.index, delays, key_base)
+        results[key] = value
+        if value is None:
+            value = self._do_evaluate_source(key_base, key, src, results, delays, prefix, bits_override, truncate, deferred_delays)
+        else:
+            deferred_delays.append((key_base, key, src)) # Evaluate later. Use current value for now.
+        return value
 
-        results[key] = src.operation.current_output(src.index, delays, src_prefix)
-        input_values = [self._evaluate_source(input_port.signals[0].source, results, delays, prefix, bits_override, truncate) for input_port in src.operation.inputs]
-        value = src.operation.evaluate_output(src.index, input_values, results, delays, src_prefix, bits_override, truncate)
+    def _do_evaluate_source(self, key_base: str, key: ResultKey, src: OutputPort, results: MutableResultMap, delays: MutableDelayMap, prefix: str, bits_override: Optional[int], truncate: bool, deferred_delays: DelayQueue) -> Number:
+        input_values = [self._evaluate_source(input_port.signals[0].source, results, delays, prefix, bits_override, truncate, deferred_delays) for input_port in src.operation.inputs]
+        value = src.operation.evaluate_output(src.index, input_values, results, delays, key_base, bits_override, truncate)
         results[key] = value
         return value
 
diff --git a/legacy/simulation_oop/core_operations.h b/legacy/simulation_oop/core_operations.h
index ca871b7f7ea03d87d5e085e5581a1776b2964a57..b2263986a6c3b484ebcf10a48d48ec939dadac86 100644
--- a/legacy/simulation_oop/core_operations.h
+++ b/legacy/simulation_oop/core_operations.h
@@ -24,7 +24,7 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map&, delay_map&, std::optional<std::size_t>, bool) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const&) const final {
 		ASIC_DEBUG_MSG("Evaluating constant.");
 		return m_value;
 	}
@@ -42,9 +42,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating addition.");
-		return this->evaluate_lhs(results, delays, bits_override, truncate) + this->evaluate_rhs(results, delays, bits_override, truncate);
+		return this->evaluate_lhs(context) + this->evaluate_rhs(context);
 	}
 };
 
@@ -58,9 +58,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating subtraction.");
-		return this->evaluate_lhs(results, delays, bits_override, truncate) - this->evaluate_rhs(results, delays, bits_override, truncate);
+		return this->evaluate_lhs(context) - this->evaluate_rhs(context);
 	}
 };
 
@@ -74,9 +74,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating multiplication.");
-		return this->evaluate_lhs(results, delays, bits_override, truncate) * this->evaluate_rhs(results, delays, bits_override, truncate);
+		return this->evaluate_lhs(context) * this->evaluate_rhs(context);
 	}
 };
 
@@ -90,9 +90,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating division.");
-		return this->evaluate_lhs(results, delays, bits_override, truncate) / this->evaluate_rhs(results, delays, bits_override, truncate);
+		return this->evaluate_lhs(context) / this->evaluate_rhs(context);
 	}
 };
 
@@ -106,13 +106,13 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating min.");
-		auto const lhs = this->evaluate_lhs(results, delays, bits_override, truncate);
+		auto const lhs = this->evaluate_lhs(context);
 		if (lhs.imag() != 0) {
 			throw std::runtime_error{"Min does not support complex numbers."};
 		}
-		auto const rhs = this->evaluate_rhs(results, delays, bits_override, truncate);
+		auto const rhs = this->evaluate_rhs(context);
 		if (rhs.imag() != 0) {
 			throw std::runtime_error{"Min does not support complex numbers."};
 		}
@@ -130,13 +130,13 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating max.");
-		auto const lhs = this->evaluate_lhs(results, delays, bits_override, truncate);
+		auto const lhs = this->evaluate_lhs(context);
 		if (lhs.imag() != 0) {
 			throw std::runtime_error{"Max does not support complex numbers."};
 		}
-		auto const rhs = this->evaluate_rhs(results, delays, bits_override, truncate);
+		auto const rhs = this->evaluate_rhs(context);
 		if (rhs.imag() != 0) {
 			throw std::runtime_error{"Max does not support complex numbers."};
 		}
@@ -154,9 +154,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating sqrt.");
-		return std::sqrt(this->evaluate_input(results, delays, bits_override, truncate));
+		return std::sqrt(this->evaluate_input(context));
 	}
 };
 
@@ -170,9 +170,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating conj.");
-		return std::conj(this->evaluate_input(results, delays, bits_override, truncate));
+		return std::conj(this->evaluate_input(context));
 	}
 };
 
@@ -186,9 +186,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating abs.");
-		return std::abs(this->evaluate_input(results, delays, bits_override, truncate));
+		return std::abs(this->evaluate_input(context));
 	}
 };
 
@@ -203,9 +203,9 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating cmul.");
-		return this->evaluate_input(results, delays, bits_override, truncate) * m_value;
+		return this->evaluate_input(context) * m_value;
 	}
 
 	number m_value;
@@ -221,12 +221,12 @@ public:
 	}
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final {
+	[[nodiscard]] number evaluate_output_impl(std::size_t index, evaluation_context const& context) const final {
 		ASIC_DEBUG_MSG("Evaluating bfly.");
 		if (index == 0) {
-			return this->evaluate_lhs(results, delays, bits_override, truncate) + this->evaluate_rhs(results, delays, bits_override, truncate);
+			return this->evaluate_lhs(context) + this->evaluate_rhs(context);
 		}
-		return this->evaluate_lhs(results, delays, bits_override, truncate) - this->evaluate_rhs(results, delays, bits_override, truncate);
+		return this->evaluate_lhs(context) - this->evaluate_rhs(context);
 	}
 };
 
diff --git a/legacy/simulation_oop/custom_operation.cpp b/legacy/simulation_oop/custom_operation.cpp
index 9308e0b6fc0e9836ba550c23c68e4d266a1a02cf..9153eb5b651f3a481747f3b652f790ce581e70dc 100644
--- a/legacy/simulation_oop/custom_operation.cpp
+++ b/legacy/simulation_oop/custom_operation.cpp
@@ -1,11 +1,13 @@
 #include "custom_operation.h"
+
 #include <pybind11/stl.h>
 
 namespace py = pybind11;
 
 namespace asic {
 
-custom_operation::custom_operation(result_key key, pybind11::object evaluate_output, pybind11::object truncate_input, std::size_t output_count)
+custom_operation::custom_operation(result_key key, pybind11::object evaluate_output, pybind11::object truncate_input,
+								   std::size_t output_count)
 	: nary_operation(std::move(key))
 	, m_evaluate_output(std::move(evaluate_output))
 	, m_truncate_input(std::move(truncate_input))
@@ -15,9 +17,9 @@ std::size_t custom_operation::output_count() const noexcept {
 	return m_output_count;
 }
 
-number custom_operation::evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number custom_operation::evaluate_output_impl(std::size_t index, evaluation_context const& context) const {
 	using namespace pybind11::literals;
-	auto input_values = this->evaluate_inputs(results, delays, bits_override, truncate);
+	auto input_values = this->evaluate_inputs(context);
 	return m_evaluate_output(index, std::move(input_values), "truncate"_a = false).cast<number>();
 }
 
diff --git a/legacy/simulation_oop/custom_operation.h b/legacy/simulation_oop/custom_operation.h
index a083bc3166d9c975cfb6f862b539bebc0a8b1049..8a11aaacbc8c17500069522d9d8f56d9c416d804 100644
--- a/legacy/simulation_oop/custom_operation.h
+++ b/legacy/simulation_oop/custom_operation.h
@@ -22,7 +22,7 @@ public:
 	[[nodiscard]] std::size_t output_count() const noexcept final;
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output_impl(std::size_t index, evaluation_context const& context) const final;
 	[[nodiscard]] number truncate_input(std::size_t index, number value, std::size_t bits) const final;
 
 	pybind11::object m_evaluate_output;
diff --git a/legacy/simulation_oop/operation.cpp b/legacy/simulation_oop/operation.cpp
index 33fc5d5bb76606331ab94a5c354395ae65b840e6..a9738a0a05287f6ab2d430d4c73560a4c6bd57c5 100644
--- a/legacy/simulation_oop/operation.cpp
+++ b/legacy/simulation_oop/operation.cpp
@@ -1,4 +1,5 @@
 #include "operation.h"
+
 #include "../debug.h"
 
 #include <pybind11/pybind11.h>
@@ -21,9 +22,9 @@ std::optional<number> signal_source::current_output(delay_map const& delays) con
 	return m_operation->current_output(m_index, delays);
 }
 
-number signal_source::evaluate_output(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number signal_source::evaluate_output(evaluation_context const& context) const {
 	ASIC_ASSERT(m_operation);
-	return m_operation->evaluate_output(m_index, results, delays, bits_override, truncate);
+	return m_operation->evaluate_output(m_index, context);
 }
 
 std::optional<std::size_t> signal_source::bits() const noexcept {
@@ -37,19 +38,20 @@ std::optional<number> abstract_operation::current_output(std::size_t, delay_map
 	return std::nullopt;
 }
 
-number abstract_operation::evaluate_output(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number abstract_operation::evaluate_output(std::size_t index, evaluation_context const& context) const {
 	ASIC_ASSERT(index < this->output_count());
+	ASIC_ASSERT(context.results);
 	auto const key = this->key_of_output(index);
-	if (auto const it = results.find(key); it != results.end()) {
+	if (auto const it = context.results->find(key); it != context.results->end()) {
 		if (it->second) {
 			return *it->second;
 		}
 		throw std::runtime_error{"Direct feedback loop detected when evaluating simulation operation."};
 	}
-	auto& result = results.try_emplace(key, this->current_output(index, delays))
+	auto& result = context.results->try_emplace(key, this->current_output(index, *context.delays))
 					   .first->second; // Use a reference to avoid potential iterator invalidation caused by evaluate_output_impl.
-	auto const value = this->evaluate_output_impl(index, results, delays, bits_override, truncate);
-	ASIC_ASSERT(&results.at(key) == &result);
+	auto const value = this->evaluate_output_impl(index, context);
+	ASIC_ASSERT(&context.results->at(key) == &result);
 	result = value;
 	return value;
 }
@@ -91,10 +93,14 @@ bool unary_operation::connected() const noexcept {
 	return static_cast<bool>(m_in);
 }
 
-number unary_operation::evaluate_input(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
-	auto const value = m_in.evaluate_output(results, delays, bits_override, truncate);
-	auto const bits = bits_override.value_or(m_in.bits().value_or(0));
-	return (truncate && bits) ? this->truncate_input(0, value, bits) : value;
+signal_source const& unary_operation::input() const noexcept {
+	return m_in;
+}
+
+number unary_operation::evaluate_input(evaluation_context const& context) const {
+	auto const value = m_in.evaluate_output(context);
+	auto const bits = context.bits_override.value_or(m_in.bits().value_or(0));
+	return (context.truncate && bits) ? this->truncate_input(0, value, bits) : value;
 }
 
 binary_operation::binary_operation(result_key key)
@@ -105,16 +111,24 @@ void binary_operation::connect(signal_source lhs, signal_source rhs) {
 	m_rhs = std::move(rhs);
 }
 
-number binary_operation::evaluate_lhs(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
-	auto const value = m_lhs.evaluate_output(results, delays, bits_override, truncate);
-	auto const bits = bits_override.value_or(m_lhs.bits().value_or(0));
-	return (truncate && bits) ? this->truncate_input(0, value, bits) : value;
+signal_source const& binary_operation::lhs() const noexcept {
+	return m_lhs;
+}
+
+signal_source const& binary_operation::rhs() const noexcept {
+	return m_rhs;
 }
 
-number binary_operation::evaluate_rhs(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
-	auto const value = m_rhs.evaluate_output(results, delays, bits_override, truncate);
-	auto const bits = bits_override.value_or(m_rhs.bits().value_or(0));
-	return (truncate && bits) ? this->truncate_input(0, value, bits) : value;
+number binary_operation::evaluate_lhs(evaluation_context const& context) const {
+	auto const value = m_lhs.evaluate_output(context);
+	auto const bits = context.bits_override.value_or(m_lhs.bits().value_or(0));
+	return (context.truncate && bits) ? this->truncate_input(0, value, bits) : value;
+}
+
+number binary_operation::evaluate_rhs(evaluation_context const& context) const {
+	auto const value = m_rhs.evaluate_output(context);
+	auto const bits = context.bits_override.value_or(m_rhs.bits().value_or(0));
+	return (context.truncate && bits) ? this->truncate_input(0, value, bits) : value;
 }
 
 nary_operation::nary_operation(result_key key)
@@ -124,13 +138,17 @@ void nary_operation::connect(std::vector<signal_source> inputs) {
 	m_inputs = std::move(inputs);
 }
 
-std::vector<number> nary_operation::evaluate_inputs(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+span<signal_source const> nary_operation::inputs() const noexcept {
+	return m_inputs;
+}
+
+std::vector<number> nary_operation::evaluate_inputs(evaluation_context const& context) const {
 	auto values = std::vector<number>{};
 	values.reserve(m_inputs.size());
 	for (auto const& input : m_inputs) {
-		auto const value = input.evaluate_output(results, delays, bits_override, truncate);
-		auto const bits = bits_override.value_or(input.bits().value_or(0));
-		values.push_back((truncate && bits) ? this->truncate_input(0, value, bits) : value);
+		auto const value = input.evaluate_output(context);
+		auto const bits = context.bits_override.value_or(input.bits().value_or(0));
+		values.push_back((context.truncate && bits) ? this->truncate_input(0, value, bits) : value);
 	}
 	return values;
 }
diff --git a/legacy/simulation_oop/operation.h b/legacy/simulation_oop/operation.h
index 152383104a1a954c0f5edebf7de5e9288341650e..344eacc1482c40021b3d0ff686cbef5c71085f58 100644
--- a/legacy/simulation_oop/operation.h
+++ b/legacy/simulation_oop/operation.h
@@ -2,6 +2,7 @@
 #define ASIC_SIMULATION_OPERATION_H
 
 #include "../number.h"
+#include "../span.h"
 
 #include <cstddef>
 #include <cstdint>
@@ -16,17 +17,20 @@
 
 namespace asic {
 
+class operation;
+class signal_source;
+
 using result_key = std::string;
 using result_map = std::unordered_map<result_key, std::optional<number>>;
 using delay_map = std::unordered_map<result_key, number>;
-
-class operation {
-public:
-	virtual ~operation() = default;
-	[[nodiscard]] virtual std::size_t output_count() const noexcept = 0;
-	[[nodiscard]] virtual std::optional<number> current_output(std::size_t index, delay_map const& delays) const = 0;
-	[[nodiscard]] virtual number evaluate_output(std::size_t index, result_map& results, delay_map& delays,
-												 std::optional<std::size_t> bits_override, bool truncate) const = 0;
+using delay_queue = std::vector<std::pair<result_key, signal_source const*>>;
+
+struct evaluation_context final {
+	result_map* results;
+	delay_map* delays;
+	delay_queue* deferred_delays;
+	std::optional<std::size_t> bits_override;
+	bool truncate;
 };
 
 class signal_source final {
@@ -37,8 +41,7 @@ public:
 	[[nodiscard]] explicit operator bool() const noexcept;
 
 	[[nodiscard]] std::optional<number> current_output(delay_map const& delays) const;
-	[[nodiscard]] number evaluate_output(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override,
-										 bool truncate) const;
+	[[nodiscard]] number evaluate_output(evaluation_context const& context) const;
 
 	[[nodiscard]] std::optional<std::size_t> bits() const noexcept;
 
@@ -48,18 +51,24 @@ private:
 	std::optional<std::size_t> m_bits;
 };
 
+class operation {
+public:
+	virtual ~operation() = default;
+	[[nodiscard]] virtual std::size_t output_count() const noexcept = 0;
+	[[nodiscard]] virtual std::optional<number> current_output(std::size_t index, delay_map const& delays) const = 0;
+	[[nodiscard]] virtual number evaluate_output(std::size_t index, evaluation_context const& context) const = 0;
+};
+
 class abstract_operation : public operation {
 public:
 	explicit abstract_operation(result_key key);
 	virtual ~abstract_operation() = default;
 
 	[[nodiscard]] std::optional<number> current_output(std::size_t, delay_map const&) const override;
-	[[nodiscard]] number evaluate_output(std::size_t index, result_map& results, delay_map& delays,
-										 std::optional<std::size_t> bits_override, bool truncate) const override;
+	[[nodiscard]] number evaluate_output(std::size_t index, evaluation_context const& context) const override;
 
 protected:
-	[[nodiscard]] virtual number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays,
-													  std::optional<std::size_t> bits_override, bool truncate) const = 0;
+	[[nodiscard]] virtual number evaluate_output_impl(std::size_t index, evaluation_context const& context) const = 0;
 	[[nodiscard]] virtual number truncate_input(std::size_t index, number value, std::size_t bits) const;
 
 	[[nodiscard]] result_key const& key_base() const;
@@ -78,9 +87,8 @@ public:
 
 protected:
 	[[nodiscard]] bool connected() const noexcept;
-
-	[[nodiscard]] number evaluate_input(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override,
-										bool truncate) const;
+	[[nodiscard]] signal_source const& input() const noexcept;
+	[[nodiscard]] number evaluate_input(evaluation_context const& context) const;
 
 private:
 	signal_source m_in;
@@ -94,10 +102,10 @@ public:
 	void connect(signal_source lhs, signal_source rhs);
 
 protected:
-	[[nodiscard]] number evaluate_lhs(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override,
-									  bool truncate) const;
-	[[nodiscard]] number evaluate_rhs(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override,
-									  bool truncate) const;
+	[[nodiscard]] signal_source const& lhs() const noexcept;
+	[[nodiscard]] signal_source const& rhs() const noexcept;
+	[[nodiscard]] number evaluate_lhs(evaluation_context const& context) const;
+	[[nodiscard]] number evaluate_rhs(evaluation_context const& context) const;
 
 private:
 	signal_source m_lhs;
@@ -112,8 +120,8 @@ public:
 	void connect(std::vector<signal_source> inputs);
 
 protected:
-	[[nodiscard]] std::vector<number> evaluate_inputs(result_map& results, delay_map& delays, std::optional<std::size_t> bits_override,
-													  bool truncate) const;
+	[[nodiscard]] span<signal_source const> inputs() const noexcept;
+	[[nodiscard]] std::vector<number> evaluate_inputs(evaluation_context const& context) const;
 
 private:
 	std::vector<signal_source> m_inputs;
diff --git a/legacy/simulation_oop/signal_flow_graph.cpp b/legacy/simulation_oop/signal_flow_graph.cpp
index 5e237e6866b76dd383643e53c239257afee67b58..d62ff6d33c09f04abee63659e8fcf4c0f18ac5c7 100644
--- a/legacy/simulation_oop/signal_flow_graph.cpp
+++ b/legacy/simulation_oop/signal_flow_graph.cpp
@@ -1,4 +1,5 @@
 #include "signal_flow_graph.h"
+
 #include "../debug.h"
 
 namespace py = pybind11;
@@ -30,12 +31,12 @@ std::size_t signal_flow_graph_operation::output_count() const noexcept {
 	return m_output_operations.size();
 }
 
-number signal_flow_graph_operation::evaluate_output(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number signal_flow_graph_operation::evaluate_output(std::size_t index, evaluation_context const& context) const {
 	ASIC_DEBUG_MSG("Evaluating SFG.");
-	return m_output_operations.at(index).evaluate_output(0, results, delays, bits_override, truncate);
+	return m_output_operations.at(index).evaluate_output(0, context);
 }
 
-number signal_flow_graph_operation::evaluate_output_impl(std::size_t, result_map&, delay_map&, std::optional<std::size_t>, bool) const {
+number signal_flow_graph_operation::evaluate_output_impl(std::size_t, evaluation_context const&) const {
 	return number{};
 }
 
@@ -66,7 +67,8 @@ std::shared_ptr<custom_operation> signal_flow_graph_operation::add_custom_operat
 																					std::string_view prefix, result_key key) {
 	auto const input_count = op.attr("input_count").cast<std::size_t>();
 	auto const output_count = op.attr("output_count").cast<std::size_t>();
-	auto const new_op = add_operation<custom_operation>(op, added, key, op.attr("evaluate_output"), op.attr("truncate_input"), output_count);
+	auto const new_op = add_operation<custom_operation>(
+		op, added, key, op.attr("evaluate_output"), op.attr("truncate_input"), output_count);
 	auto inputs = std::vector<signal_source>{};
 	inputs.reserve(input_count);
 	for (auto const i : range(input_count)) {
diff --git a/legacy/simulation_oop/signal_flow_graph.h b/legacy/simulation_oop/signal_flow_graph.h
index 83c62482b8534d933051ee1e4961701fe00e3838..f06788249e367d3e8e0602f04c6dcf91c71b7a96 100644
--- a/legacy/simulation_oop/signal_flow_graph.h
+++ b/legacy/simulation_oop/signal_flow_graph.h
@@ -34,10 +34,10 @@ public:
 	[[nodiscard]] std::vector<std::shared_ptr<input_operation>> const& inputs() noexcept;
 	[[nodiscard]] std::size_t output_count() const noexcept final;
 
-	[[nodiscard]] number evaluate_output(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output(std::size_t index, evaluation_context const& context) const final;
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output_impl(std::size_t index, evaluation_context const& context) const final;
 
 	[[nodiscard]] static signal_source make_source(pybind11::handle op, std::size_t input_index, added_operation_cache& added,
 												   std::string_view prefix);
diff --git a/legacy/simulation_oop/simulation.cpp b/legacy/simulation_oop/simulation.cpp
index 52fd9c2ec40fd7650f516f6e241fa52b2daea797..35805bf99f9a0d295e65a5334e8d6b8440eaf5a1 100644
--- a/legacy/simulation_oop/simulation.cpp
+++ b/legacy/simulation_oop/simulation.cpp
@@ -1,5 +1,7 @@
 #include "simulation.h"
 
+#include "../debug.h"
+
 namespace py = pybind11;
 
 namespace asic {
@@ -52,19 +54,41 @@ std::vector<number> simulation::step(bool save_results, std::optional<std::size_
 	return this->run_for(1, save_results, bits_override, truncate);
 }
 
-std::vector<number> simulation::run_until(iteration_t iteration, bool save_results, std::optional<std::size_t> bits_override, bool truncate) {
+std::vector<number> simulation::run_until(iteration_t iteration, bool save_results, std::optional<std::size_t> bits_override,
+										  bool truncate) {
 	auto result = std::vector<number>{};
 	while (m_iteration < iteration) {
 		ASIC_DEBUG_MSG("Running simulation iteration.");
 		for (auto&& [input, function] : zip(m_sfg.inputs(), m_input_functions)) {
 			input->value(function(m_iteration));
 		}
-		auto results = result_map{};
+
 		result.clear();
 		result.reserve(m_sfg.output_count());
+
+		auto results = result_map{};
+		auto deferred_delays = delay_queue{};
+		auto context = evaluation_context{};
+		context.results = &results;
+		context.delays = &m_delays;
+		context.deferred_delays = &deferred_delays;
+		context.bits_override = bits_override;
+		context.truncate = truncate;
+
 		for (auto const i : range(m_sfg.output_count())) {
-			result.push_back(m_sfg.evaluate_output(i, results, m_delays, bits_override, truncate));
+			result.push_back(m_sfg.evaluate_output(i, context));
 		}
+
+		while (!deferred_delays.empty()) {
+			auto new_deferred_delays = delay_queue{};
+			context.deferred_delays = &new_deferred_delays;
+			for (auto const& [key, src] : deferred_delays) {
+				ASIC_ASSERT(src);
+				m_delays[key] = src->evaluate_output(context);
+			}
+			deferred_delays = std::move(new_deferred_delays);
+		}
+
 		if (save_results) {
 			for (auto const& [key, value] : results) {
 				m_results[key].push_back(value.value());
@@ -75,7 +99,8 @@ std::vector<number> simulation::run_until(iteration_t iteration, bool save_resul
 	return result;
 }
 
-std::vector<number> simulation::run_for(iteration_t iterations, bool save_results, std::optional<std::size_t> bits_override, bool truncate) {
+std::vector<number> simulation::run_for(iteration_t iterations, bool save_results, std::optional<std::size_t> bits_override,
+										bool truncate) {
 	if (iterations > std::numeric_limits<iteration_t>::max() - m_iteration) {
 		throw py::value_error("Simulation iteration type overflow!");
 	}
diff --git a/legacy/simulation_oop/simulation.h b/legacy/simulation_oop/simulation.h
index 987f2d9da320934d398f59c6a9c09d9647f2bf08..38e2771b877772bd28048cae16d791bb4e0b45e3 100644
--- a/legacy/simulation_oop/simulation.h
+++ b/legacy/simulation_oop/simulation.h
@@ -8,7 +8,6 @@
 #include "signal_flow_graph.h"
 #include "special_operations.h"
 
-#include <pybind11/pybind11.h>
 #include <cstddef>
 #include <cstdint>
 #include <fmt/format.h>
@@ -18,6 +17,7 @@
 #include <optional>
 #include <pybind11/functional.h>
 #include <pybind11/numpy.h>
+#include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
 #include <string_view>
 #include <unordered_map>
@@ -40,8 +40,10 @@ public:
 	void set_inputs(std::vector<std::optional<input_provider_t>> input_providers);
 
 	[[nodiscard]] std::vector<number> step(bool save_results, std::optional<std::size_t> bits_override, bool truncate);
-	[[nodiscard]] std::vector<number> run_until(iteration_t iteration, bool save_results, std::optional<std::size_t> bits_override, bool truncate);
-	[[nodiscard]] std::vector<number> run_for(iteration_t iterations, bool save_results, std::optional<std::size_t> bits_override, bool truncate);
+	[[nodiscard]] std::vector<number> run_until(iteration_t iteration, bool save_results, std::optional<std::size_t> bits_override,
+												bool truncate);
+	[[nodiscard]] std::vector<number> run_for(iteration_t iterations, bool save_results, std::optional<std::size_t> bits_override,
+											  bool truncate);
 	[[nodiscard]] std::vector<number> run(bool save_results, std::optional<std::size_t> bits_override, bool truncate);
 
 	[[nodiscard]] iteration_t iteration() const noexcept;
diff --git a/legacy/simulation_oop/special_operations.cpp b/legacy/simulation_oop/special_operations.cpp
index a4595471d08ababb54b7672a3781170aebcd55cf..1f7a6519a90ba08224585e36093694becf495c4d 100644
--- a/legacy/simulation_oop/special_operations.cpp
+++ b/legacy/simulation_oop/special_operations.cpp
@@ -1,4 +1,5 @@
 #include "special_operations.h"
+
 #include "../debug.h"
 
 namespace asic {
@@ -18,10 +19,10 @@ void input_operation::value(number value) noexcept {
 	m_value = value;
 }
 
-number input_operation::evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number input_operation::evaluate_output_impl(std::size_t, evaluation_context const& context) const {
 	ASIC_DEBUG_MSG("Evaluating input.");
 	if (this->connected()) {
-		return this->evaluate_input(results, delays, bits_override, truncate);
+		return this->evaluate_input(context);
 	}
 	return m_value;
 }
@@ -33,9 +34,9 @@ std::size_t output_operation::output_count() const noexcept {
 	return 1;
 }
 
-number output_operation::evaluate_output_impl(std::size_t, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number output_operation::evaluate_output_impl(std::size_t, evaluation_context const& context) const {
 	ASIC_DEBUG_MSG("Evaluating output.");
-	return this->evaluate_input(results, delays, bits_override, truncate);
+	return this->evaluate_input(context);
 }
 
 delay_operation::delay_operation(result_key key, number initial_value)
@@ -54,25 +55,23 @@ std::optional<number> delay_operation::current_output(std::size_t index, delay_m
 	return m_initial_value;
 }
 
-number delay_operation::evaluate_output(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const {
+number delay_operation::evaluate_output(std::size_t index, evaluation_context const& context) const {
 	ASIC_DEBUG_MSG("Evaluating delay.");
 	ASIC_ASSERT(index == 0);
-	auto const key = this->key_of_output(index);
-	// Use a reference to avoid iterator invalidation by evaluate_input.
-	auto& delay = delays.try_emplace(key, m_initial_value).first->second;
-	const auto& [it, inserted] = results.try_emplace(key, delay);
-	if (!inserted) {
-		return it->second.value();
+	ASIC_ASSERT(context.results);
+	ASIC_ASSERT(context.delays);
+	ASIC_ASSERT(context.deferred_delays);
+	auto key = this->key_of_output(index);
+	auto const value = context.delays->try_emplace(key, m_initial_value).first->second;
+	auto const& [it, inserted] = context.results->try_emplace(key, value);
+	if (inserted) {
+		context.deferred_delays->emplace_back(std::move(key), &this->input());
+		return value;
 	}
-	// Use a reference to avoid iterator invalidation by evaluate_input.
-	auto& result = it->second;
-	const auto value = delay;
-	delay = this->evaluate_input(results, delays, bits_override, truncate);
-	result = value;
-	return value;
+	return it->second.value();
 }
 
-[[nodiscard]] number delay_operation::evaluate_output_impl(std::size_t, result_map&, delay_map&, std::optional<std::size_t>, bool) const {
+[[nodiscard]] number delay_operation::evaluate_output_impl(std::size_t, evaluation_context const&) const {
 	return number{};
 }
 
diff --git a/legacy/simulation_oop/special_operations.h b/legacy/simulation_oop/special_operations.h
index 78ddfd240cb8156e3046aba337121db84cdb56ae..88fb087e84378e36f423364d2c7d83a083828784 100644
--- a/legacy/simulation_oop/special_operations.h
+++ b/legacy/simulation_oop/special_operations.h
@@ -20,7 +20,7 @@ public:
 	void value(number value) noexcept;
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output_impl(std::size_t index, evaluation_context const& context) const final;
 
 	number m_value{};
 };
@@ -32,7 +32,7 @@ public:
 	[[nodiscard]] std::size_t output_count() const noexcept final;
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output_impl(std::size_t index, evaluation_context const& context) const final;
 };
 
 class delay_operation final : public unary_operation {
@@ -42,10 +42,10 @@ public:
 	[[nodiscard]] std::size_t output_count() const noexcept final;
 
 	[[nodiscard]] std::optional<number> current_output(std::size_t index, delay_map const& delays) const final;
-	[[nodiscard]] number evaluate_output(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output(std::size_t index, evaluation_context const& context) const final;
 
 private:
-	[[nodiscard]] number evaluate_output_impl(std::size_t index, result_map& results, delay_map& delays, std::optional<std::size_t> bits_override, bool truncate) const final;
+	[[nodiscard]] number evaluate_output_impl(std::size_t index, evaluation_context const& context) const final;
 
 	number m_initial_value;
 };
diff --git a/src/debug.h b/src/debug.h
index f1ad2d193d2021b6c54784bc1089c5f6c32aea96..a11aa057db644dbe2d29399398a1f48ca599876f 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -3,13 +3,9 @@
 
 #ifndef NDEBUG
 #define ASIC_ENABLE_DEBUG_LOGGING 1
-#else
-#define ASIC_ENABLE_DEBUG_LOGGING 0
-#endif // NDEBUG
-
-#ifndef NDEBUG
 #define ASIC_ENABLE_ASSERTS 1
 #else
+#define ASIC_ENABLE_DEBUG_LOGGING 0
 #define ASIC_ENABLE_ASSERTS 0
 #endif // NDEBUG
 
@@ -50,13 +46,18 @@ inline void log_debug_msg(std::string_view file, int line, Format&& format, Args
 #endif // ASIC_ENABLE_DEBUG_LOGGING
 
 #if ASIC_ENABLE_ASSERTS
-inline void log_assert(std::string_view file, int line, bool condition, std::string_view condition_string) {
-	if (!condition) {
+inline void fail_assert(std::string_view file, int line, std::string_view condition_string) {
 #if ASIC_ENABLE_DEBUG_LOGGING
-		log_debug_msg(file, line, "Assertion failed: {}", condition_string);
+	log_debug_msg(file, line, "Assertion failed: {}", condition_string);
 #endif // ASIC_ENABLE_DEBUG_LOGGING
-		fmt::print(stderr, "{}:{}: Assertion failed: {}\n", std::filesystem::path{file}.filename().generic_string(), line, condition_string);
-		std::abort();
+	fmt::print(stderr, "{}:{}: Assertion failed: {}\n", std::filesystem::path{file}.filename().generic_string(), line, condition_string);
+	std::abort();
+}
+
+template <typename BoolConvertible>
+inline void check_assert(std::string_view file, int line, std::string_view condition_string, BoolConvertible&& condition) {
+	if (!static_cast<bool>(condition)) {
+		fail_assert(file, line, condition_string);
 	}
 }
 #endif // ASIC_ENABLE_ASSERTS
@@ -71,7 +72,7 @@ inline void log_assert(std::string_view file, int line, bool condition, std::str
 #endif // ASIC_ENABLE_DEBUG_LOGGING
 
 #if ASIC_ENABLE_ASSERTS
-#define ASIC_ASSERT(condition) (asic::detail::log_assert(__FILE__, __LINE__, (condition), #condition))
+#define ASIC_ASSERT(condition) (asic::detail::check_assert(__FILE__, __LINE__, #condition, (condition)))
 #else
 #define ASIC_ASSERT(condition) ((void)0)
 #endif
diff --git a/src/simulation/compile.cpp b/src/simulation/compile.cpp
index 31538a87d293ffa109108dac6d8d1107f9c07685..33f9cc0c1f5f26dc5f4b2d0b70d7cc0dbae8a163 100644
--- a/src/simulation/compile.cpp
+++ b/src/simulation/compile.cpp
@@ -10,6 +10,7 @@
 #include <limits>
 #include <optional>
 #include <string_view>
+#include <tuple>
 #include <unordered_map>
 #include <utility>
 
@@ -38,9 +39,20 @@ public:
 	simulation_code compile(pybind11::handle sfg) {
 		ASIC_DEBUG_MSG("Compiling code...");
 		this->initialize_code(sfg.attr("input_count").cast<std::size_t>(), sfg.attr("output_count").cast<std::size_t>());
+		auto deferred_delays = delay_queue{};
 		for (auto const i : range(m_code.output_count)) {
-			this->add_operation_output(sfg, i, std::string_view{}, sfg_info_stack{});
+			this->add_operation_output(sfg, i, std::string_view{}, sfg_info_stack{}, deferred_delays);
 		}
+
+		while (!deferred_delays.empty()) {
+			auto new_deferred_delays = delay_queue{};
+			for (auto const& [delay_index, op, prefix, sfg_stack] : deferred_delays) {
+				this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
+				this->add_instruction(instruction_type::update_delay, no_result_index, -1).index = delay_index;
+			}
+			deferred_delays = new_deferred_delays;
+		}
+
 		this->resolve_invalid_result_indices();
 		ASIC_DEBUG_MSG("Compiled code:\n{}\n", format_compiled_simulation_code(m_code));
 		return std::move(m_code);
@@ -66,6 +78,7 @@ private:
 	};
 
 	using sfg_info_stack = std::vector<sfg_info>;
+	using delay_queue = std::vector<std::tuple<std::size_t, py::handle, std::string, sfg_info_stack>>;
 	using added_output_cache = std::unordered_set<PyObject const*>;
 	using added_result_cache = std::unordered_map<PyObject const*, result_index_t>;
 	using added_custom_operation_cache = std::unordered_map<PyObject const*, std::size_t>;
@@ -172,12 +185,13 @@ private:
 		return delay_index;
 	}
 
-	void add_source(py::handle op, std::size_t input_index, std::string_view prefix, sfg_info_stack const& sfg_stack) {
+	void add_source(py::handle op, std::size_t input_index, std::string_view prefix, sfg_info_stack const& sfg_stack,
+					delay_queue& deferred_delays) {
 		auto const signal = py::object{op.attr("inputs")[py::int_{input_index}].attr("signals")[py::int_{0}]};
 		auto const src = py::handle{signal.attr("source")};
 		auto const operation = py::handle{src.attr("operation")};
 		auto const index = src.attr("index").cast<std::size_t>();
-		this->add_operation_output(operation, index, prefix, sfg_stack);
+		this->add_operation_output(operation, index, prefix, sfg_stack, deferred_delays);
 		if (!signal.attr("bits").is_none()) {
 			auto const bits = signal.attr("bits").cast<std::size_t>();
 			if (bits > 64) {
@@ -189,54 +203,56 @@ private:
 	}
 
 	void add_unary_operation_output(py::handle op, result_index_t result_index, std::string_view prefix, sfg_info_stack const& sfg_stack,
-									instruction_type type) {
-		this->add_source(op, 0, prefix, sfg_stack);
+									delay_queue& deferred_delays, instruction_type type) {
+		this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
 		this->add_instruction(type, result_index, 0);
 	}
 
 	void add_binary_operation_output(py::handle op, result_index_t result_index, std::string_view prefix, sfg_info_stack const& sfg_stack,
-									 instruction_type type) {
-		this->add_source(op, 0, prefix, sfg_stack);
-		this->add_source(op, 1, prefix, sfg_stack);
+									 delay_queue& deferred_delays, instruction_type type) {
+		this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
+		this->add_source(op, 1, prefix, sfg_stack, deferred_delays);
 		this->add_instruction(type, result_index, -1);
 	}
 
-	void add_operation_output(py::handle op, std::size_t output_index, std::string_view prefix, sfg_info_stack const& sfg_stack) {
+	void add_operation_output(py::handle op, std::size_t output_index, std::string_view prefix, sfg_info_stack const& sfg_stack,
+							  delay_queue& deferred_delays) {
 		auto const type_name = op.attr("type_name").cast<std::string_view>();
 		if (type_name == "out") {
-			this->add_source(op, 0, prefix, sfg_stack);
+			this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
 		} else if (auto const result_index = this->begin_operation_output(op, output_index, prefix)) {
 			if (type_name == "c") {
 				this->add_instruction(instruction_type::push_constant, *result_index, 1).value = op.attr("value").cast<number>();
 			} else if (type_name == "add") {
-				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::addition);
+				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::addition);
 			} else if (type_name == "sub") {
-				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::subtraction);
+				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::subtraction);
 			} else if (type_name == "mul") {
-				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::multiplication);
+				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::multiplication);
 			} else if (type_name == "div") {
-				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::division);
+				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::division);
 			} else if (type_name == "min") {
-				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::min);
+				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::min);
 			} else if (type_name == "max") {
-				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::max);
+				this->add_binary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::max);
 			} else if (type_name == "sqrt") {
-				this->add_unary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::square_root);
+				this->add_unary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::square_root);
 			} else if (type_name == "conj") {
-				this->add_unary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::complex_conjugate);
+				this->add_unary_operation_output(
+					op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::complex_conjugate);
 			} else if (type_name == "abs") {
-				this->add_unary_operation_output(op, *result_index, prefix, sfg_stack, instruction_type::absolute);
+				this->add_unary_operation_output(op, *result_index, prefix, sfg_stack, deferred_delays, instruction_type::absolute);
 			} else if (type_name == "cmul") {
-				this->add_source(op, 0, prefix, sfg_stack);
+				this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
 				this->add_instruction(instruction_type::constant_multiplication, *result_index, 0).value = op.attr("value").cast<number>();
 			} else if (type_name == "bfly") {
 				if (output_index == 0) {
-					this->add_source(op, 0, prefix, sfg_stack);
-					this->add_source(op, 1, prefix, sfg_stack);
+					this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
+					this->add_source(op, 1, prefix, sfg_stack, deferred_delays);
 					this->add_instruction(instruction_type::addition, *result_index, -1);
 				} else {
-					this->add_source(op, 0, prefix, sfg_stack);
-					this->add_source(op, 1, prefix, sfg_stack);
+					this->add_source(op, 0, prefix, sfg_stack, deferred_delays);
+					this->add_source(op, 1, prefix, sfg_stack, deferred_delays);
 					this->add_instruction(instruction_type::subtraction, *result_index, -1);
 				}
 			} else if (type_name == "in") {
@@ -248,22 +264,25 @@ private:
 				if (sfg_stack.size() == 1) {
 					this->add_instruction(instruction_type::push_input, *result_index, 1).index = input_index;
 				} else {
-					this->add_source(info.sfg, input_index, prefix.substr(0, info.prefix_length), pop_sfg(sfg_stack));
+					this->add_source(info.sfg, input_index, prefix.substr(0, info.prefix_length), pop_sfg(sfg_stack), deferred_delays);
 					this->add_instruction(instruction_type::forward_value, *result_index, 0);
 				}
 			} else if (type_name == "t") {
 				auto const delay_index = this->add_delay_info(op.attr("initial_value").cast<number>(), *result_index);
-				this->add_source(op, 0, prefix, sfg_stack);
-				this->add_instruction(instruction_type::delay, *result_index, 0).index = delay_index;
+				deferred_delays.emplace_back(delay_index, op, std::string{prefix}, sfg_stack);
+				this->add_instruction(instruction_type::push_delay, *result_index, 1).index = delay_index;
 			} else if (type_name == "sfg") {
-				this->add_source(
-					op.attr("output_operations")[py::int_{output_index}], 0, key_base(op, prefix), push_sfg(sfg_stack, op, prefix.size()));
+				this->add_source(op.attr("output_operations")[py::int_{output_index}],
+								 0,
+								 key_base(op, prefix),
+								 push_sfg(sfg_stack, op, prefix.size()),
+								 deferred_delays);
 				this->add_instruction(instruction_type::forward_value, *result_index, 0);
 			} else {
 				auto const custom_operation_index = this->try_add_custom_operation(op);
 				auto const& custom_operation = m_code.custom_operations[custom_operation_index];
 				for (auto const i : range(custom_operation.input_count)) {
-					this->add_source(op, i, prefix, sfg_stack);
+					this->add_source(op, i, prefix, sfg_stack, deferred_delays);
 				}
 				auto const custom_source_index = m_code.custom_sources.size();
 				auto& custom_source = m_code.custom_sources.emplace_back();
diff --git a/src/simulation/format_code.h b/src/simulation/format_code.h
index f50a3b7771c4a1da1eca5ff480c3fab8176dc370..5ebbb95d1f11eb18b915dbab9fbccbb82d83304c 100644
--- a/src/simulation/format_code.h
+++ b/src/simulation/format_code.h
@@ -12,7 +12,7 @@
 
 namespace asic {
 
-[[maybe_unused]] [[nodiscard]] inline std::string format_number(number const& value) {
+[[nodiscard]] inline std::string format_number(number const& value) {
 	if (value.imag() == 0) {
 		return fmt::to_string(value.real());
 	}
@@ -25,7 +25,7 @@ namespace asic {
 	return fmt::format("{}+{}j", value.real(), value.imag());
 }
 
-[[maybe_unused]] [[nodiscard]] inline std::string format_compiled_simulation_code_result_keys(simulation_code const& code) {
+[[nodiscard]] inline std::string format_compiled_simulation_code_result_keys(simulation_code const& code) {
 	auto result = std::string{};
 	for (auto const& [i, result_key] : enumerate(code.result_keys)) {
 		result += fmt::format("{:>2}: \"{}\"\n", i, result_key);
@@ -33,7 +33,7 @@ namespace asic {
 	return result;
 }
 
-[[maybe_unused]] [[nodiscard]] inline std::string format_compiled_simulation_code_delays(simulation_code const& code) {
+[[nodiscard]] inline std::string format_compiled_simulation_code_delays(simulation_code const& code) {
 	auto result = std::string{};
 	for (auto const& [i, delay] : enumerate(code.delays)) {
 		ASIC_ASSERT(delay.result_index < code.result_keys.size());
@@ -46,11 +46,12 @@ namespace asic {
 	return result;
 }
 
-[[maybe_unused]] [[nodiscard]] inline std::string format_compiled_simulation_code_instruction(instruction const& instruction) {
+[[nodiscard]] inline std::string format_compiled_simulation_code_instruction(instruction const& instruction) {
 	switch (instruction.type) {
 		// clang-format off
 		case instruction_type::push_input:              return fmt::format("push_input inputs[{}]", instruction.index);
 		case instruction_type::push_result:             return fmt::format("push_result results[{}]", instruction.index);
+		case instruction_type::push_delay:              return fmt::format("push_delay delays[{}]", instruction.index);
 		case instruction_type::push_constant:           return fmt::format("push_constant {}", format_number(instruction.value));
 		case instruction_type::truncate:                return fmt::format("truncate {:#018x}", instruction.bit_mask);
 		case instruction_type::addition:                return "addition";
@@ -63,15 +64,15 @@ namespace asic {
 		case instruction_type::complex_conjugate:       return "complex_conjugate";
 		case instruction_type::absolute:                return "absolute";
 		case instruction_type::constant_multiplication: return fmt::format("constant_multiplication {}", format_number(instruction.value));
-		case instruction_type::delay:                   return fmt::format("delay delays[{}]", instruction.index);
+		case instruction_type::update_delay:            return fmt::format("update_delay delays[{}]", instruction.index);
 		case instruction_type::custom:                  return fmt::format("custom custom_sources[{}]", instruction.index);
 		case instruction_type::forward_value:           return "forward_value";
-			// clang-format on
+		// clang-format on
 	}
 	return std::string{};
 }
 
-[[maybe_unused]] [[nodiscard]] inline std::string format_compiled_simulation_code_instructions(simulation_code const& code) {
+[[nodiscard]] inline std::string format_compiled_simulation_code_instructions(simulation_code const& code) {
 	auto result = std::string{};
 	for (auto const& [i, instruction] : enumerate(code.instructions)) {
 		auto instruction_string = format_compiled_simulation_code_instruction(instruction);
@@ -84,7 +85,7 @@ namespace asic {
 	return result;
 }
 
-[[maybe_unused]] [[nodiscard]] inline std::string format_compiled_simulation_code(simulation_code const& code) {
+[[nodiscard]] inline std::string format_compiled_simulation_code(simulation_code const& code) {
 	return fmt::format(
 		"==============================================\n"
 		"> Code stats\n"
diff --git a/src/simulation/instruction.h b/src/simulation/instruction.h
index 5fd95f92fb42ad54e1c6cf1c8d07e662129cdd6c..d650c651394a243c52eee7e5ad2fe463f96bdad7 100644
--- a/src/simulation/instruction.h
+++ b/src/simulation/instruction.h
@@ -12,6 +12,7 @@ namespace asic {
 enum class instruction_type : std::uint8_t {
 	push_input,              // push(inputs[index])
 	push_result,             // push(results[index])
+	push_delay,              // push(delays[index])
 	push_constant,           // push(value)
 	truncate,                // push(trunc(pop(), bit_mask))
 	addition,                // push(pop() + pop())
@@ -24,7 +25,7 @@ enum class instruction_type : std::uint8_t {
 	complex_conjugate,       // push(conj(pop()))
 	absolute,                // push(abs(pop()))
 	constant_multiplication, // push(pop() * value)
-	delay,                   // auto const value = pop(); push(delays[index]); delays[index] = value
+	update_delay,            // delays[index] = pop()
 	custom,                  // Custom operation. Uses custom_source[index].
 	forward_value            // Forward the current value on the stack (push(pop()), i.e. do nothing).
 };
diff --git a/src/simulation/run.cpp b/src/simulation/run.cpp
index 7120f8e42b06de161d5dc81e38c8c08eb9457a5b..4fa0d6ad075621762d4ef4b780071025b6ec6b98 100644
--- a/src/simulation/run.cpp
+++ b/src/simulation/run.cpp
@@ -85,6 +85,9 @@ simulation_state run_simulation(simulation_code const& code, span<number const>
 			case instruction_type::push_result:
 				push(state.results[instruction.index]);
 				break;
+			case instruction_type::push_delay:
+				push(delays[instruction.index]);
+				break;
 			case instruction_type::push_constant:
 				push(instruction.value);
 				break;
@@ -135,12 +138,9 @@ simulation_state run_simulation(simulation_code const& code, span<number const>
 			case instruction_type::constant_multiplication:
 				push(pop() * instruction.value);
 				break;
-			case instruction_type::delay: {
-				auto const value = delays[instruction.index];
+			case instruction_type::update_delay:
 				delays[instruction.index] = pop();
-				push(value);
 				break;
-			}
 			case instruction_type::custom: {
 				using namespace pybind11::literals;
 				auto const& src = code.custom_sources[instruction.index];
diff --git a/test/fixtures/signal_flow_graph.py b/test/fixtures/signal_flow_graph.py
index 1424d5ca2e9150fbb4365204a591f7a7764d2328..959fd944db5ddc12eba5fba3019bee9b2b8eb254 100644
--- a/test/fixtures/signal_flow_graph.py
+++ b/test/fixtures/signal_flow_graph.py
@@ -98,13 +98,33 @@ def sfg_accumulator():
     data_out = Output(t)
     return SFG(inputs = [data_in, reset], outputs = [data_out])
 
+
+@pytest.fixture
+def sfg_simple_accumulator():
+    """Valid SFG with two inputs and one output.
+         .                .
+    in1----->add1-----+----->out1
+         .    ^       |   .
+         .    |       |   .
+         .    +--t1<--+   .
+         .                .
+    """
+    in1 = Input()
+    t1 = Delay()
+    add1 = in1 + t1
+    t1 << add1
+    out1 = Output(add1)
+    return SFG(inputs = [in1], outputs = [out1])
+
 @pytest.fixture
 def sfg_simple_filter():
     """A valid SFG that is used as a filter in the first lab for TSTE87.
-                +----<cmul1----+
-                |              |
-                |              |
-    in1>------add1>----t1>-----+------out1>
+         .                 .
+         .   +--cmul1<--+  .
+         .   |          |  .
+         .   v          |  .
+    in1---->add1----->t1+---->out1
+         .                 .
     """
     in1 = Input()
     t1 = Delay()
diff --git a/test/test_fast_simulation.py b/test/test_fast_simulation.py
index 7ab490362cc6dc246c0d1ab1c62cd34a4bc1ee8a..ece9add5891cb47cba7b63f80682bc65d970470e 100644
--- a/test/test_fast_simulation.py
+++ b/test/test_fast_simulation.py
@@ -179,6 +179,12 @@ class TestRun:
         assert output4[0] == 0
         assert output5[0] == 7
         
+    def test_simple_accumulator(self, sfg_simple_accumulator):
+        data_in = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        simulation = FastSimulation(sfg_simple_accumulator, [data_in])
+        simulation.run()
+        assert list(simulation.results["0"]) == [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
+
     def test_simple_filter(self, sfg_simple_filter):
         input0 = np.array([1, 2, 3, 4, 5])
         simulation = FastSimulation(sfg_simple_filter, [input0])
diff --git a/test/test_simulation.py b/test/test_simulation.py
index e5f8a76e005d12acd28a67969539313e1bafd783..e1075a74a2c839eefcfa122ff02ec6d11314b11e 100644
--- a/test/test_simulation.py
+++ b/test/test_simulation.py
@@ -1,7 +1,7 @@
 import pytest
 import numpy as np
 
-from b_asic import SFG, Output, Simulation
+from b_asic import SFG, Simulation
 
 
 class TestRunFor:
@@ -176,6 +176,12 @@ class TestRun:
         assert output3[0] == 28
         assert output4[0] == 0
         assert output5[0] == 7
+
+    def test_simple_accumulator(self, sfg_simple_accumulator):
+        data_in = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        simulation = Simulation(sfg_simple_accumulator, [data_in])
+        simulation.run()
+        assert list(simulation.results["0"]) == [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
         
     def test_simple_filter(self, sfg_simple_filter):
         input0 = np.array([1, 2, 3, 4, 5])