[mask_rom, address_translation] Add driver for address translation.

Signed-off-by: Douglas Reis <doreis@lowrisc.org>
diff --git a/sw/device/silicon_creator/lib/drivers/BUILD b/sw/device/silicon_creator/lib/drivers/BUILD
index 326eea7..42691ac 100644
--- a/sw/device/silicon_creator/lib/drivers/BUILD
+++ b/sw/device/silicon_creator/lib/drivers/BUILD
@@ -175,6 +175,17 @@
         "//hw/ip/rv_core_ibex/data:rv_core_ibex_regs",
         "//hw/top_earlgrey/sw/autogen:top_earlgrey",
         "//sw/device/lib/base:abs_mmio",
+        "//sw/device/silicon_creator/lib/base:sec_mmio",
+    ],
+)
+
+cc_test(
+    name = "ibex_unittest",
+    srcs = ["ibex_unittest.cc"],
+    deps = [
+        ":ibex",
+        "//sw/device/silicon_creator/testing:mask_rom_test",
+        "@googletest//:gtest_main",
     ],
 )
 
diff --git a/sw/device/silicon_creator/lib/drivers/ibex.c b/sw/device/silicon_creator/lib/drivers/ibex.c
index 0da85f7..9adeca2 100644
--- a/sw/device/silicon_creator/lib/drivers/ibex.c
+++ b/sw/device/silicon_creator/lib/drivers/ibex.c
@@ -5,6 +5,7 @@
 #include "sw/device/silicon_creator/lib/drivers/ibex.h"
 
 #include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/silicon_creator/lib/base/sec_mmio.h"
 
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
 #include "rv_core_ibex_regs.h"
@@ -16,3 +17,33 @@
 uint32_t ibex_fpga_version(void) {
   return abs_mmio_read32(kBase + RV_CORE_IBEX_FPGA_INFO_REG_OFFSET);
 }
+
+void ibex_addr_remap_0_set(uint32_t matching_addr, uint32_t remap_addr,
+                           size_t size) {
+  uint32_t mask = matching_addr | ((size - 1) >> 1);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_MATCHING_0_REG_OFFSET, mask);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_MATCHING_0_REG_OFFSET, mask);
+
+  sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_REMAP_ADDR_0_REG_OFFSET,
+                   remap_addr);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_REMAP_ADDR_0_REG_OFFSET,
+                   remap_addr);
+
+  sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_EN_0_REG_OFFSET, 1);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_EN_0_REG_OFFSET, 1);
+}
+
+void ibex_addr_remap_1_set(uint32_t matching_addr, uint32_t remap_addr,
+                           size_t size) {
+  uint32_t mask = matching_addr | ((size - 1) >> 1);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_MATCHING_1_REG_OFFSET, mask);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_MATCHING_1_REG_OFFSET, mask);
+
+  sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_REMAP_ADDR_1_REG_OFFSET,
+                   remap_addr);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_REMAP_ADDR_1_REG_OFFSET,
+                   remap_addr);
+
+  sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_EN_1_REG_OFFSET, 1);
+  sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_EN_1_REG_OFFSET, 1);
+}
diff --git a/sw/device/silicon_creator/lib/drivers/ibex.h b/sw/device/silicon_creator/lib/drivers/ibex.h
index 3615c1c..74c1ab8 100644
--- a/sw/device/silicon_creator/lib/drivers/ibex.h
+++ b/sw/device/silicon_creator/lib/drivers/ibex.h
@@ -5,6 +5,7 @@
 #ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_IBEX_H_
 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_IBEX_H_
 
+#include <stddef.h>
 #include <stdint.h>
 
 #ifdef __cplusplus
@@ -18,6 +19,46 @@
  */
 uint32_t ibex_fpga_version(void);
 
+/**
+ * The following constants represent the expected number of sec_mmio register
+ * writes performed by functions in provided in this module. See
+ * `SEC_MMIO_WRITE_INCREMENT()` for more details.
+ *
+ * Example:
+ * ```
+ *  ibex_addr_remap_0_set(...);
+ *  SEC_MMIO_WRITE_INCREMENT(kAddressTranslationSecMmioConfigure);
+ * ```
+ */
+enum {
+  kAddressTranslationSecMmioConfigure = 6,
+};
+
+/**
+ * Configure the instruction and data bus in the address translation slot 0.
+ *
+ * @param matching_addr When an incoming transaction matches the matching
+ * region, it is redirected to the new address. If a transaction does not match,
+ * then it is directly passed through.
+ * @param remap_addr  The region where the matched transtaction will be
+ * redirected to.
+ * @param size The size of the regions mapped.
+ */
+void ibex_addr_remap_0_set(uint32_t matching_addr, uint32_t remap_addr,
+                           size_t size);
+
+/**
+ * Configure the instruction and data bus in the address translation slot 1.
+ *
+ * @param matching_addr When an incoming transaction matches the matching
+ * region, it is redirected to the new address. If a transaction does not match,
+ * then it is directly passed through.
+ * @param remap_addr  The region where the matched transtaction will be
+ * redirected to.
+ * @param size The size of the regions mapped.
+ */
+void ibex_addr_remap_1_set(uint32_t matching_addr, uint32_t remap_addr,
+                           size_t size);
 #ifdef __cplusplus
 }
 #endif
diff --git a/sw/device/silicon_creator/lib/drivers/ibex_unittest.cc b/sw/device/silicon_creator/lib/drivers/ibex_unittest.cc
new file mode 100644
index 0000000..7236ff9
--- /dev/null
+++ b/sw/device/silicon_creator/lib/drivers/ibex_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/silicon_creator/lib/drivers/ibex.h"
+
+#include <array>
+
+#include "gtest/gtest.h"
+#include "sw/device/lib/base/testing/mock_abs_mmio.h"
+#include "sw/device/silicon_creator/lib/base/mock_sec_mmio.h"
+#include "sw/device/silicon_creator/testing/mask_rom_test.h"
+
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+#include "rv_core_ibex_regs.h"
+
+namespace ibex_unittest {
+namespace {
+
+class AddressTranslationTest : public mask_rom_test::MaskRomTest {
+ protected:
+  uint32_t base_ = TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR;
+  mask_rom_test::MockSecMmio sec_;
+};
+
+TEST_F(AddressTranslationTest, Slot0Sucess) {
+  uint32_t matching_addr = 0x9000000;
+  uint32_t remap_addr = 0x2000000;
+  uint32_t size = 0x8000;
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_IBUS_ADDR_MATCHING_0_REG_OFFSET,
+                     0x9003fff);
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_DBUS_ADDR_MATCHING_0_REG_OFFSET,
+                     0x9003fff);
+
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_IBUS_REMAP_ADDR_0_REG_OFFSET,
+                     remap_addr);
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_DBUS_REMAP_ADDR_0_REG_OFFSET,
+                     remap_addr);
+
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_IBUS_ADDR_EN_0_REG_OFFSET, 1);
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_DBUS_ADDR_EN_0_REG_OFFSET, 1);
+
+  ibex_addr_remap_0_set(matching_addr, remap_addr, size);
+}
+
+TEST_F(AddressTranslationTest, Slot1Sucess) {
+  uint32_t matching_addr = 0xB040000;
+  uint32_t remap_addr = 0x6000000;
+  uint32_t size = 0x80000;
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_IBUS_ADDR_MATCHING_1_REG_OFFSET,
+                     0xb07ffff);
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_DBUS_ADDR_MATCHING_1_REG_OFFSET,
+                     0xb07ffff);
+
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_IBUS_REMAP_ADDR_1_REG_OFFSET,
+                     remap_addr);
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_DBUS_REMAP_ADDR_1_REG_OFFSET,
+                     remap_addr);
+
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_IBUS_ADDR_EN_1_REG_OFFSET, 1);
+  EXPECT_SEC_WRITE32(base_ + RV_CORE_IBEX_DBUS_ADDR_EN_1_REG_OFFSET, 1);
+
+  ibex_addr_remap_1_set(matching_addr, remap_addr, size);
+}
+}  // namespace
+}  // namespace ibex_unittest
diff --git a/sw/device/silicon_creator/lib/drivers/meson.build b/sw/device/silicon_creator/lib/drivers/meson.build
index 791aefe..76eb277 100644
--- a/sw/device/silicon_creator/lib/drivers/meson.build
+++ b/sw/device/silicon_creator/lib/drivers/meson.build
@@ -489,6 +489,7 @@
   suite: 'mask_rom',
 )
 
+
 # Mask ROM otbn driver
 sw_silicon_creator_lib_driver_otbn = declare_dependency(
   link_with: static_library(
@@ -615,6 +616,26 @@
   ),
 )
 
+
+test('sw_silicon_creator_lib_driver_ibex_unittest', executable(
+    'sw_silicon_creator_lib_driver_ibex_unittest',
+    sources: [
+       hw_ip_ibex_reg_h,
+      'ibex_unittest.cc',
+      'ibex.c',
+    ],
+    dependencies: [
+      sw_vendor_gtest,
+      sw_lib_testing_hardened,
+      sw_silicon_creator_lib_base_mock_sec_mmio,
+    ],
+    native: true,
+    c_args: ['-DMOCK_ABS_MMIO', '-DOT_OFF_TARGET_TEST'],
+    cpp_args: ['-DMOCK_ABS_MMIO', '-DOT_OFF_TARGET_TEST'],
+  ),
+  suite: 'mask_rom',
+)
+
 test('sw_silicon_creator_lib_driver_spi_device_unittest', executable(
     'sw_silicon_creator_lib_driver_spi_device_unittest',
     sources: [