Adds instruction fence.tso separate from fence.
Change operands expected by fence.

PiperOrigin-RevId: 692223730
Change-Id: I62c2907bab5d571bbd916d6e5b6e8dfda2ee4c7e
diff --git a/riscv/riscv32g.bin_fmt b/riscv/riscv32g.bin_fmt
index cdf2dce..22d8f8d 100644
--- a/riscv/riscv32g.bin_fmt
+++ b/riscv/riscv32g.bin_fmt
@@ -169,7 +169,8 @@
   sra    : RType  : func7 == 0b010'0000, func3==0b101, opcode == 0b011'0011;
   or     : RType  : func7 == 0b000'0000, func3==0b110, opcode == 0b011'0011;
   and    : RType  : func7 == 0b000'0000, func3==0b111, opcode == 0b011'0011;
-  fence  : Fence  : func3 == 0b000, opcode == 0b000'1111;
+  fence     : Fence : fm == 0b0000, succ != 0b0000, func3 == 0b000, opcode == 0b000'1111;
+  fence_tso : Fence : fm == 0b1000, pred == 0b0011, succ == 0b0011, func3 == 0b000, opcode == 0b000'1111;
   ecall  : Inst32Format : bits == 0b0000'0000'0000'00000'000'00000, opcode == 0b111'0011;
   ebreak : Inst32Format : bits == 0b0000'0000'0001'00000'000'00000, opcode == 0b111'0011;
   // RiscV32 Instruction fence.
diff --git a/riscv/riscv32g.isa b/riscv/riscv32g.isa
index 4415c40..72c368e 100644
--- a/riscv/riscv32g.isa
+++ b/riscv/riscv32g.isa
@@ -200,9 +200,12 @@
       resources: { next_pc, rs1, rs2 : },
       disasm: "sb", "%rs2, %S_imm12(%rs1)",
       semfunc: "&RV32::RiscVISb";
-    fence{: I_imm12 : },
+    fence{: pred, succ : },
       disasm: "fence",
       semfunc: "&RiscVIFence";
+    fence_tso{},
+      disasm: "fence.tso",
+      semfunc: "&RiscVIFenceTso";
     ecall{},
       disasm: "ecall",
       semfunc: "&RiscVIEcall";
diff --git a/riscv/riscv32g_encoding.cc b/riscv/riscv32g_encoding.cc
index f86e785..3ac5fa4 100644
--- a/riscv/riscv32g_encoding.cc
+++ b/riscv/riscv32g_encoding.cc
@@ -15,7 +15,6 @@
 #include "riscv/riscv32g_encoding.h"
 
 #include <cstdint>
-#include <new>
 #include <string>
 #include <utility>
 
@@ -306,6 +305,11 @@
         return new generic::ImmediateOperand<int32_t>(
             encoding::inst32_format::ExtractJImm(inst_word_));
       }));
+  source_op_getters_.insert(
+      std::make_pair(static_cast<int>(SourceOpEnum::kPred), [this]() {
+        return new generic::ImmediateOperand<uint32_t>(
+            encoding::inst32_format::ExtractPred(inst_word_));
+      }));
   source_op_getters_.insert(std::make_pair(
       static_cast<int>(SourceOpEnum::kRd),
       [this]() -> SourceOperandInterface * {
@@ -367,6 +371,11 @@
             encoding::inst32_format::ExtractSImm(inst_word_));
       }));
   source_op_getters_.insert(
+      std::make_pair(static_cast<int>(SourceOpEnum::kSucc), [this]() {
+        return new generic::ImmediateOperand<uint32_t>(
+            encoding::inst32_format::ExtractSucc(inst_word_));
+      }));
+  source_op_getters_.insert(
       std::make_pair(static_cast<int>(SourceOpEnum::kUImm20), [this]() {
         return new generic::ImmediateOperand<int32_t>(
             encoding::inst32_format::ExtractUImm(inst_word_));
diff --git a/riscv/riscv64g.bin_fmt b/riscv/riscv64g.bin_fmt
index cd553e3..9870382 100644
--- a/riscv/riscv64g.bin_fmt
+++ b/riscv/riscv64g.bin_fmt
@@ -202,7 +202,8 @@
   sraw   : RType  : func7 == 0b010'0000, func3==0b101, opcode == 0b011'1011;
   or     : RType  : func7 == 0b000'0000, func3==0b110, opcode == 0b011'0011;
   and    : RType  : func7 == 0b000'0000, func3==0b111, opcode == 0b011'0011;
-  fence  : Fence  : func3 == 0b000, opcode == 0b000'1111;
+  fence     : Fence : fm == 0b0000, succ != 0b0000, func3 == 0b000, opcode == 0b000'1111;
+  fence_tso : Fence : fm == 0b1000, pred == 0b0011, succ == 0b0011, func3 == 0b000, opcode == 0b000'1111;
   ecall  : Inst32Format : bits == 0b0000'0000'0000'00000'000'00000, opcode == 0b111'0011;
   ebreak : Inst32Format : bits == 0b0000'0000'0001'00000'000'00000, opcode == 0b111'0011;
   // RiscV32 Instruction fence.
diff --git a/riscv/riscv64g.isa b/riscv/riscv64g.isa
index eb0461d..8d7fcff 100644
--- a/riscv/riscv64g.isa
+++ b/riscv/riscv64g.isa
@@ -266,9 +266,12 @@
       resources: { next_pc, rs1, rs2 : },
       disasm: "sb", "%rs2, %S_imm12(%rs1)",
       semfunc: "&RV64::RiscVISb";
-    fence{: I_imm12 : },
+    fence{: pred, succ : },
       disasm: "fence",
       semfunc: "&RiscVIFence";
+    fence_tso{},
+      disasm: "fence.tso",
+      semfunc: "&RiscVIFenceTso";
     ecall{},
       disasm: "ecall",
       semfunc: "&RiscVIEcall";
diff --git a/riscv/riscv64g_encoding.cc b/riscv/riscv64g_encoding.cc
index 6f1c68d..cebbc65 100644
--- a/riscv/riscv64g_encoding.cc
+++ b/riscv/riscv64g_encoding.cc
@@ -15,7 +15,6 @@
 #include "riscv/riscv64g_encoding.h"
 
 #include <cstdint>
-#include <new>
 #include <string>
 #include <utility>
 
@@ -329,6 +328,11 @@
             encoding64::inst32_format::ExtractJImm(inst_word_));
       }));
   source_op_getters_.insert(
+      std::make_pair(static_cast<int>(SourceOpEnum::kPred), [this]() {
+        return new generic::ImmediateOperand<uint32_t>(
+            encoding64::fence::ExtractPred(inst_word_));
+      }));
+  source_op_getters_.insert(
       std::make_pair(static_cast<int>(SourceOpEnum::kRm),
                      [this]() -> SourceOperandInterface * {
                        uint32_t rm = (inst_word_ >> 12) & 0x7;
@@ -404,6 +408,11 @@
             encoding64::s_type::ExtractSImm(inst_word_));
       }));
   source_op_getters_.insert(
+      std::make_pair(static_cast<int>(SourceOpEnum::kSucc), [this]() {
+        return new generic::ImmediateOperand<uint32_t>(
+            encoding64::fence::ExtractSucc(inst_word_));
+      }));
+  source_op_getters_.insert(
       std::make_pair(static_cast<int>(SourceOpEnum::kUImm20), [this]() {
         return new generic::ImmediateOperand<int32_t>(
             encoding64::u_type::ExtractUImm(inst_word_));
diff --git a/riscv/riscv64g_vec_encoding.cc b/riscv/riscv64g_vec_encoding.cc
index 524b005..a7505ed 100644
--- a/riscv/riscv64g_vec_encoding.cc
+++ b/riscv/riscv64g_vec_encoding.cc
@@ -15,7 +15,6 @@
 #include "riscv/riscv64g_vec_encoding.h"
 
 #include <cstdint>
-#include <new>
 #include <string>
 #include <utility>
 #include <vector>
@@ -422,6 +421,11 @@
             encoding64::inst32_format::ExtractJImm(inst_word_));
       }));
   source_op_getters_.insert(
+      std::make_pair(static_cast<int>(SourceOpEnum::kPred), [this]() {
+        return new generic::ImmediateOperand<uint32_t>(
+            encoding64::fence::ExtractPred(inst_word_));
+      }));
+  source_op_getters_.insert(
       std::make_pair(static_cast<int>(SourceOpEnum::kRm),
                      [this]() -> SourceOperandInterface * {
                        uint32_t rm = (inst_word_ >> 12) & 0x7;
@@ -497,6 +501,11 @@
             encoding64::s_type::ExtractSImm(inst_word_));
       }));
   source_op_getters_.insert(
+      std::make_pair(static_cast<int>(SourceOpEnum::kSucc), [this]() {
+        return new generic::ImmediateOperand<uint32_t>(
+            encoding64::fence::ExtractSucc(inst_word_));
+      }));
+  source_op_getters_.insert(
       std::make_pair(static_cast<int>(SourceOpEnum::kUImm20), [this]() {
         uint32_t uimm = encoding64::u_type::ExtractUImm(inst_word_);
         return new generic::ImmediateOperand<int32_t>(
diff --git a/riscv/riscv_getters.h b/riscv/riscv_getters.h
index 1aaccb6..5230372 100644
--- a/riscv/riscv_getters.h
+++ b/riscv/riscv_getters.h
@@ -16,7 +16,6 @@
 #define THIRD_PARTY_MPACT_RISCV_RISCV_GETTERS_H_
 
 #include <cstdint>
-#include <new>
 #include <string>
 
 #include "absl/strings/str_cat.h"
@@ -226,6 +225,10 @@
     return new ImmediateOperand<int32_t>(
         Extractors::Inst32Format::ExtractJImm(common->inst_word()));
   });
+  Insert(getter_map, *Enum::kPred, [common]() {
+    return new ImmediateOperand<uint32_t>(
+        Extractors::Fence::ExtractPred(common->inst_word()));
+  });
   Insert(getter_map, *Enum::kRd, [common]() -> SourceOperandInterface * {
     int num = Extractors::RType::ExtractRd(common->inst_word());
     if (num == 0) return new generic::IntLiteralOperand<0>({1});
@@ -274,6 +277,10 @@
     return new ImmediateOperand<int32_t>(
         Extractors::SType::ExtractSImm(common->inst_word()));
   });
+  Insert(getter_map, *Enum::kSucc, [common]() {
+    return new ImmediateOperand<uint32_t>(
+        Extractors::Fence::ExtractSucc(common->inst_word()));
+  });
   Insert(getter_map, *Enum::kUImm20, [common]() {
     return new ImmediateOperand<int32_t>(
         Extractors::Inst32Format::ExtractUImm(common->inst_word()));
diff --git a/riscv/riscv_i_instructions.cc b/riscv/riscv_i_instructions.cc
index 648d4b1..a72fe68 100644
--- a/riscv/riscv_i_instructions.cc
+++ b/riscv/riscv_i_instructions.cc
@@ -16,7 +16,6 @@
 
 #include <cstdint>
 #include <functional>
-#include <iostream>
 #include <limits>
 #include <type_traits>
 
@@ -541,12 +540,17 @@
 }  // namespace RV64
 
 void RiscVIFence(const Instruction *instruction) {
-  uint32_t bits = instruction->Source(0)->AsUint32(0);
-  int fm = (bits >> 8) & 0xf;
-  int predecessor = (bits >> 4) & 0xf;
-  int successor = bits & 0xf;
+  int pred = generic::GetInstructionSource<uint32_t>(instruction, 0) & 0xf;
+  int succ = generic::GetInstructionSource<uint32_t>(instruction, 1) & 0xf;
   auto *state = static_cast<RiscVState *>(instruction->state());
-  state->Fence(instruction, fm, predecessor, successor);
+  // Fence mode is 0x0
+  state->Fence(instruction, /*fence_mode=*/0x0, pred, succ);
+}
+
+void RiscVIFenceTso(const Instruction *instruction) {
+  auto *state = static_cast<RiscVState *>(instruction->state());
+  state->Fence(instruction, /*fence_mode=*/0b1000, /*pred=*/0b0011,
+               /*succ=*/0b0011);
 }
 
 void RiscVIEcall(const Instruction *instruction) {
diff --git a/riscv/riscv_i_instructions.h b/riscv/riscv_i_instructions.h
index ace0445..05cdbd9 100644
--- a/riscv/riscv_i_instructions.h
+++ b/riscv/riscv_i_instructions.h
@@ -15,6 +15,8 @@
 #ifndef MPACT_RISCV_RISCV_RISCV_I_INSTRUCTIONS_H_
 #define MPACT_RISCV_RISCV_RISCV_I_INSTRUCTIONS_H_
 
+#include <cstdint>
+
 #include "mpact/sim/generic/instruction.h"
 
 // This file contains the declarations of the instruction semantic functions
@@ -182,10 +184,11 @@
 
 }  // namespace RV64
 
-// The Fence instruction takes a single source operand (index 0) which consists
-// of an immediate value containing the right justified concatenation of the FM,
-// predecessor, and successor bit fields of the instruction.
+// The Fence instruction takes two source operands, the 4 bit values of the
+// predecessor and successor sets.
 void RiscVIFence(const Instruction *instruction);
+// The Fence.tso takes no operands.
+void RiscVIFenceTso(const Instruction *instruction);
 // Ecall and EBreak take no source or destination operands.
 void RiscVIEcall(const Instruction *instruction);
 void RiscVIEbreak(const Instruction *instruction);
diff --git a/riscv/riscv_zimop.isa b/riscv/riscv_zimop.isa
index 499d5b8..770757c 100644
--- a/riscv/riscv_zimop.isa
+++ b/riscv/riscv_zimop.isa
@@ -20,7 +20,7 @@
 
 includes {
   #include "riscv/riscv_i_instructions.h"
-  #include "riscv/riscv_zimop_instructions.isa"
+  #include "riscv/riscv_zimop_instructions.h"
 }
 
 slot riscv32_zimop {