No public description

PiperOrigin-RevId: 819273859
Change-Id: Ia3707c1db285a8807c64e377bf4a5aaf00570bfc
diff --git a/riscv/riscv_top.cc b/riscv/riscv_top.cc
index 8472281..b0ae232 100644
--- a/riscv/riscv_top.cc
+++ b/riscv/riscv_top.cc
@@ -279,6 +279,7 @@
   run_status_ = RunStatus::kSingleStep;
   int count = 0;
   halted_ = false;
+  paused_ = false;
   halt_reason_ = *HaltReason::kNone;
   // First check to see if the previous halt was due to a breakpoint. If so,
   // need to step over the breakpoint.
@@ -289,6 +290,7 @@
       run_status_ = RunStatus::kHalted;
       return status;
     }
+    paused_ |= halted_;
     count++;
   }
 
@@ -303,7 +305,7 @@
   // be executed.
   uint64_t next_pc = pc_operand->AsUint64(0);
   pc = next_pc;
-  while (!halted_ && (count < num)) {
+  while (!paused_ && (count < num)) {
     SetPc(pc);
     auto* inst = rv_decode_cache_->GetDecodedInstruction(pc);
     // Set the next_pc to the next sequential instruction.
@@ -323,6 +325,7 @@
         state_->TakeAvailableInterrupt(epc);  // Will set state_->branch().
       }
     } while (!executed);
+    paused_ |= halted_;
     count++;
     // Update counters.
     counter_opcode_[inst->opcode()].Increment(1);
@@ -334,7 +337,7 @@
       AddToBranchTrace(pc, pc_val);
       next_pc = pc_val;
     }
-    if (!halted_) {
+    if (!paused_) {
       pc = next_pc;
       continue;
     }
@@ -343,10 +346,11 @@
       auto status = StepPastBreakpoint();
       if (!status.ok()) {
         run_status_ = RunStatus::kHalted;
+        halted_ = true;
         return status;
       }
       // Reset the halt reason and continue;
-      halted_ = false;
+      paused_ = halted_;
       halt_reason_ = *HaltReason::kNone;
       need_to_step_over_ = false;
       continue;
@@ -391,6 +395,7 @@
   std::thread([this]() {
     run_status_ = RunStatus::kRunning;
     halted_ = false;
+    paused_ = false;
     halt_reason_ = *HaltReason::kNone;
     run_started_->Notify();
     auto pc_operand = state_->pc_operand();
@@ -401,7 +406,7 @@
     // This holds the value of the current pc, and post-loop, the address of
     // the most recently executed instruction.
     uint64_t pc = next_pc;
-    while (!halted_) {
+    while (!paused_) {
       auto* inst = rv_decode_cache_->GetDecodedInstruction(pc);
       SetPc(pc);
       next_pc = pc + inst->size();
@@ -423,6 +428,7 @@
           state_->TakeAvailableInterrupt(epc);  // Will set state_->branch().
         }
       } while (!executed);
+      paused_ |= halted_;
       // Update counters.
       counter_opcode_[inst->opcode()].Increment(1);
       counter_num_instructions_.Increment(1);
@@ -433,7 +439,7 @@
         AddToBranchTrace(pc, pc_val);
         next_pc = pc_val;
       }
-      if (!halted_) {
+      if (!paused_) {
         pc = next_pc;
         continue;
       }
@@ -447,7 +453,7 @@
           break;
         };
         // Reset the halt reason and continue;
-        halted_ = false;
+        paused_ = halted_;
         halt_reason_ = *HaltReason::kNone;
         need_to_step_over_ = false;
         continue;
@@ -814,7 +820,16 @@
                            const Instruction* inst) {
   // First set the halt_reason_, then the halt flag.
   halt_reason_ = halt_reason;
-  halted_ = true;
+  // Action point halts are always called from the thread that is executing the
+  // instructions. In this case we set paused_ to true, and not halted_, since
+  // we want to keep running after the action point by resetting paused_. If we
+  // use halted_ there would be a race condition between clearing halted_ and
+  // an asynchronous halt request from a different thread.
+  if (halt_reason == *HaltReason::kActionPoint) {
+    paused_ = true;
+  } else {
+    halted_ = true;
+  }
   // If the halt reason is either sw breakpoint or action point, set
   // need_to_step_over to true.
   if ((halt_reason_ == *HaltReason::kSoftwareBreakpoint) ||
diff --git a/riscv/riscv_top.h b/riscv/riscv_top.h
index 171ef9c..22ca7f9 100644
--- a/riscv/riscv_top.h
+++ b/riscv/riscv_top.h
@@ -179,6 +179,9 @@
   HaltReasonValueType halt_reason_ = *HaltReason::kNone;
   // Halting flag. This is set to true when execution must halt.
   bool halted_ = false;
+  // Paused flag. This is set to true when execution must pause due to an action
+  // point or breakpoint.
+  bool paused_ = false;
   // Set to true if the next instruction requires a step-over.
   bool need_to_step_over_ = false;
   absl::Notification* run_halted_ = nullptr;