Enabled data caches.
Fixes some issues:
  - Failure when using tagged loads/stores
  - Write allocation was done regardless of the configuration

PiperOrigin-RevId: 681988267
Change-Id: I53da47e76eb1cf15263bce0c48d976b15d9e2246
diff --git a/mpact/sim/util/memory/cache.cc b/mpact/sim/util/memory/cache.cc
index 0a40bb0..ad9c709 100644
--- a/mpact/sim/util/memory/cache.cc
+++ b/mpact/sim/util/memory/cache.cc
@@ -248,6 +248,7 @@
   auto *cache_context = new CacheContext(context, db, inst, db->latency());
   if (context) context->IncRef();
   if (inst) inst->IncRef();
+  db->IncRef();
   db->set_latency(0);
   memory_->Load(address, db, cache_inst_, cache_context);
   cache_context->DecRef();
@@ -267,6 +268,7 @@
   auto *cache_context = new CacheContext(context, db, inst, db->latency());
   if (context) context->IncRef();
   if (inst) inst->IncRef();
+  db->IncRef();
   db->set_latency(0);
   memory_->Load(address_db, mask_db, el_size, db, cache_inst_, cache_context);
   cache_context->DecRef();
@@ -274,14 +276,33 @@
 
 void Cache::Load(uint64_t address, DataBuffer *db, DataBuffer *tags,
                  Instruction *inst, ReferenceCount *context) {
-  (void)CacheLookup(address, db->size<uint8_t>(), /*is_read=*/true);
+  // Since db can be nullptr (for a tag only load), the size and latency may
+  // have to be computed differently. For size, base it on the number of tags
+  // that are being loaded. For latency, use 0.
+  int size = 0;
+  if (db == nullptr) {
+    int num_tags = tags->size<uint8_t>();
+    size = (address & ~0x7ULL) + (num_tags << 3) - address;
+  } else {
+    size = db->size<uint8_t>();
+  }
+  int latency = db == nullptr ? 0 : db->latency();
+
+  (void)CacheLookup(address, size, /*is_read=*/true);
   if (tagged_memory_ == nullptr) return;
 
-  auto *cache_context =
-      new CacheContext(context, db, tags, inst, db->latency());
+  if (inst == nullptr) {  // Just forward and return.
+    tagged_memory_->Load(address, db, tags, /*inst=*/nullptr, context);
+    return;
+  }
+
+  auto *cache_context = new CacheContext(context, db, inst, latency);
   if (context) context->IncRef();
   if (inst) inst->IncRef();
-  db->set_latency(0);
+  if (db) {
+    db->set_latency(0);
+    db->IncRef();
+  }
   tagged_memory_->Load(address, db, tags, cache_inst_, cache_context);
   cache_context->DecRef();
 }
@@ -319,25 +340,26 @@
 // read.
 void Cache::LoadChild(const Instruction *inst) {
   auto *cache_context = static_cast<CacheContext *>(inst->context());
-  auto *context = cache_context->context;
+  auto *og_context = cache_context->context;
   auto *db = cache_context->db;
   auto *og_inst = cache_context->inst;
   // Reset the db latency to the original value.
-  db->set_latency(cache_context->latency);
   if (nullptr != og_inst) {
-    if (db->latency() > 0) {
-      og_inst->IncRef();
-      og_inst->state()->function_delay_line()->Add(db->latency(),
-                                                   [og_inst, context]() {
-                                                     og_inst->Execute(context);
-                                                     if (context != nullptr)
-                                                       context->DecRef();
-                                                     og_inst->DecRef();
-                                                   });
+    if (cache_context->latency > 0) {
+      if (db != nullptr) db->set_latency(cache_context->latency);
+      og_inst->state()->function_delay_line()->Add(
+          db->latency(), [og_inst, og_context]() {
+            og_inst->Execute(og_context);
+            if (og_context != nullptr) og_context->DecRef();
+            og_inst->DecRef();
+          });
+    } else {
+      og_inst->Execute(og_context);
+      if (og_context != nullptr) og_context->DecRef();
+      og_inst->DecRef();
     }
-    cache_context->DecRef();
-    og_inst->DecRef();
   }
+  if (db) db->DecRef();
 }
 
 // Cache lookup function.
@@ -375,6 +397,7 @@
       if (line.valid && line.tag == block) {
         hit = true;
         line.lru = cycle_counter_->GetValue();
+        line.dirty |= !is_read;
         break;
       }
     }
@@ -386,14 +409,16 @@
       }
     } else {
       if (is_read) {
-        ReplaceBlock(block, is_read);
+        ReplaceBlock(block, /*is_read=*/true);
         miss_count++;
         read_miss_counter_.Increment(1ULL);
       } else {
-        ReplaceBlock(block, is_read);
         write_miss_counter_.Increment(1ULL);
         if (write_allocate_) {
+          ReplaceBlock(block, /*is_read=*/false);
           miss_count++;
+        } else {
+          write_around_counter_.Increment(1ULL);
         }
       }
     }
diff --git a/mpact/sim/util/memory/cache.h b/mpact/sim/util/memory/cache.h
index 4891748..af2e11b 100644
--- a/mpact/sim/util/memory/cache.h
+++ b/mpact/sim/util/memory/cache.h
@@ -79,9 +79,6 @@
     CacheContext(ReferenceCount *context_, DataBuffer *db_, Instruction *inst_,
                  int latency_)
         : context(context_), db(db_), inst(inst_), latency(latency_) {}
-    CacheContext(ReferenceCount *context_, DataBuffer *db_, DataBuffer *tags_,
-                 Instruction *inst_, int latency_)
-        : context(context_), db(db_), inst(inst_), latency(latency_) {}
   };
 
   // Two constructors depending on whether the cache is used with a tagged
@@ -139,7 +136,7 @@
   }
   void set_tagged_memory(TaggedMemoryInterface *tagged_memory) {
     tagged_memory_ = tagged_memory;
-    memory_ = tagged_memory;
+    memory_ = static_cast<MemoryInterface *>(tagged_memory);
   }
 
  private: