From d93d7b9fa414876f1f4cd210485699288bc5be3f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 17 Sep 2017 14:59:09 -0700 Subject: [PATCH] Only merge stores that aren't yet pending This fixes a deadlock (and possibly memory corruption, though that is unconfirmed). The following sequence manifests it, assuming t0 is 32-byte aligned: sw t0, 0(t0) sw t0, 16(t0) lw t1, 4(t0) lw t2, 4(t0) --- src/main/scala/rocket/DCache.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 8cf787bd..7ab17aca 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -294,6 +294,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s2_correct = s2_data_error && !any_pstore_valid && !RegNext(any_pstore_valid) && Bool(usingDataScratchpad) // pending store buffer val s2_valid_correct = s2_valid_hit_pre_data_ecc && s2_correct + val s2_store_valid = s2_valid_hit && s2_write && !s2_sc_fail val pstore1_cmd = RegEnable(s1_req.cmd, s1_valid_not_nacked && s1_write) val pstore1_addr = RegEnable(s1_paddr, s1_valid_not_nacked && s1_write) val pstore1_data = RegEnable(io.cpu.s1_data.data, s1_valid_not_nacked && s1_write) @@ -302,7 +303,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val pstore1_storegen_data = Wire(init = pstore1_data) val pstore1_rmw = Bool(usingRMW) && RegEnable(needsRead(s1_req), s1_valid_not_nacked && s1_write) val pstore1_valid = Wire(Bool()) - val pstore1_merge = pstore1_valid && s2_store_merge + val pstore1_merge = s2_store_valid && s2_store_merge val pstore2_valid = Reg(Bool()) any_pstore_valid := pstore1_valid || pstore2_valid val pstore_drain_structural = pstore1_valid && pstore2_valid && ((s1_valid && s1_write) || pstore1_rmw) @@ -312,7 +313,6 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { (Bool(usingRMW) && pstore_drain_structural || (((pstore1_valid && !pstore1_rmw) || pstore2_valid) && (pstore_drain_opportunistic || pstore_drain_on_miss))) pstore1_valid := { - val s2_store_valid = s2_valid_hit && s2_write && !s2_sc_fail val pstore1_held = Reg(Bool()) assert(!s2_store_valid || !pstore1_held) pstore1_held := (s2_store_valid && !s2_store_merge || pstore1_held) && pstore2_valid && !pstore_drain