Refactor lookahead caching to hide cache key's.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
diff --git a/libs/libvtrutil/src/vtr_cache.h b/libs/libvtrutil/src/vtr_cache.h
new file mode 100644
index 0000000..d1496d2
--- /dev/null
+++ b/libs/libvtrutil/src/vtr_cache.h
@@ -0,0 +1,44 @@
+#ifndef VTR_CACHE_H_
+#define VTR_CACHE_H_
+
+#include <memory>
+
+namespace vtr {
+
+// Simple cache
+template<typename CacheKey, typename CacheValue>
+class Cache {
+  public:
+    // Clear cache.
+    void clear() {
+        key_ = CacheKey();
+        value_.reset();
+    }
+
+    // Check if the cache is valid, and return the cached value if present and valid.
+    //
+    // Returns nullptr if the cache is invalid.
+    const CacheValue* get(const CacheKey& key) const {
+        if (key == key_ && value_) {
+            return value_.get();
+        } else {
+            return nullptr;
+        }
+    }
+
+    // Update the cache.
+    const CacheValue* set(const CacheKey& key, std::unique_ptr<CacheValue> value) {
+        key_ = key;
+        value_ = std::move(value);
+
+        return value_.get();
+    }
+
+  private:
+    CacheKey key_;
+    std::unique_ptr<CacheValue> value_;
+};
+
+} // namespace vtr
+
+#endif
diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h
index d348c09..6ed3bca 100644
--- a/vpr/src/base/vpr_context.h
+++ b/vpr/src/base/vpr_context.h
@@ -284,12 +284,11 @@
     std::string routing_id;
 
     // Cache of router lookahead object.
-    std::unique_ptr<RouterLookahead> cached_router_lookahead_;
-
-    // Parameters used for cached router lookahead object.
-    e_router_lookahead cached_router_lookahead_type_;
-    std::string cached_lookahead_file_;
-    std::vector<t_segment_inf> cached_segment_inf_;
+    //
+    // Cache key: (lookahead type, read lookahead (if any), segment definitions).
+    vtr::Cache<std::tuple<e_router_lookahead, std::string, std::vector<t_segment_inf>>,
+               RouterLookahead>
+        cached_router_lookahead_;
 };
 
 //This object encapsulates VPR's state. There is typically a single instance which is
diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h
index 82cd0ae..01dca22 100644
--- a/vpr/src/base/vpr_types.h
+++ b/vpr/src/base/vpr_types.h
@@ -38,6 +38,7 @@
 #include "vtr_vector.h"
 #include "vtr_util.h"
 #include "vtr_flat_map.h"
+#include "vtr_cache.h"
 
 /*******************************************************************************
  * Global data types and constants
diff --git a/vpr/src/route/router_lookahead.cpp b/vpr/src/route/router_lookahead.cpp
index 1de12c1..130b862 100644
--- a/vpr/src/route/router_lookahead.cpp
+++ b/vpr/src/route/router_lookahead.cpp
@@ -196,9 +196,7 @@
 
 void invalidate_router_lookahead_cache() {
     auto& router_ctx = g_vpr_ctx.mutable_routing();
-    router_ctx.cached_router_lookahead_.reset();
-    router_ctx.cached_lookahead_file_.clear();
-    router_ctx.cached_segment_inf_.clear();
+    router_ctx.cached_router_lookahead_.clear();
 }
 
 const RouterLookahead* get_cached_router_lookahead(
@@ -208,23 +206,22 @@
     const std::vector<t_segment_inf>& segment_inf) {
     auto& router_ctx = g_vpr_ctx.routing();
 
+    auto cache_key = std::make_tuple(router_lookahead_type, read_lookahead, segment_inf);
+
     // Check if cache is valid.
-    if (
-        router_ctx.cached_router_lookahead_ && read_lookahead == router_ctx.cached_lookahead_file_ && segment_inf == router_ctx.cached_segment_inf_) {
+    const RouterLookahead* router_lookahead = router_ctx.cached_router_lookahead_.get(cache_key);
+    if (router_lookahead) {
+        return router_lookahead;
     } else {
         // Cache is not valid, compute cached object.
         auto& mut_router_ctx = g_vpr_ctx.mutable_routing();
 
-        invalidate_router_lookahead_cache();
-
-        mut_router_ctx.cached_router_lookahead_ = make_router_lookahead(
-            router_lookahead_type,
-            write_lookahead,
-            read_lookahead,
-            segment_inf);
-        mut_router_ctx.cached_lookahead_file_ = read_lookahead;
-        mut_router_ctx.cached_segment_inf_ = segment_inf;
+        return mut_router_ctx.cached_router_lookahead_.set(
+            cache_key,
+            make_router_lookahead(
+                router_lookahead_type,
+                write_lookahead,
+                read_lookahead,
+                segment_inf));
     }
-
-    return router_ctx.cached_router_lookahead_.get();
 }