diff --git a/Makefile b/Makefile
index 588f335a7b9cee25b4b163778ada0e8f67d5ea5e..af8868aa8dbb68f9dfdc05174fa19b83efb03672 100644
--- a/Makefile
+++ b/Makefile
@@ -68,8 +68,8 @@ ariane_pkg := $(addprefix $(root-dir), $(ariane_pkg))
 
 # utility modules
 util := $(wildcard src/util/*.svh)                          \
-        src/util/instruction_tracer_pkg.sv                  \
         src/util/instruction_tracer_if.sv                   \
+        src/util/instruction_tracer.sv                      \
         src/tech_cells_generic/src/cluster_clock_gating.sv  \
         tb/common/mock_uart.sv                              \
         src/util/sram.sv
@@ -456,12 +456,13 @@ check-torture:
 	diff -s $(riscv-torture-dir)/$(test-location).spike.sig $(riscv-torture-dir)/$(test-location).rtlsim.sig
 
 fpga_filter := $(addprefix $(root-dir), bootrom/bootrom.sv)
+fpga_filter += $(addprefix $(root-dir), src/util/instruction_tracer.sv)
 
-fpga: $(ariane_pkg) $(util) $(src) $(fpga_src) $(util) $(uart_src)
+fpga: $(ariane_pkg) $(util) $(src) $(fpga_src) $(uart_src)
 	@echo "[FPGA] Generate sources"
 	@echo read_vhdl        {$(uart_src)}    > fpga/scripts/add_sources.tcl
 	@echo read_verilog -sv {$(ariane_pkg)} >> fpga/scripts/add_sources.tcl
-	@echo read_verilog -sv {$(util)}       >> fpga/scripts/add_sources.tcl
+	@echo read_verilog -sv {$(filter-out $(fpga_filter), $(util))}     >> fpga/scripts/add_sources.tcl
 	@echo read_verilog -sv {$(filter-out $(fpga_filter), $(src))} 	   >> fpga/scripts/add_sources.tcl
 	@echo read_verilog -sv {$(fpga_src)}   >> fpga/scripts/add_sources.tcl
 	@echo "[FPGA] Generate Bitstream"
diff --git a/fpga/src/ariane_xilinx.sv b/fpga/src/ariane_xilinx.sv
index 1a3e674549d8e8eeb67ddd2be739c586b0487c37..d03212354a8dfffff5ffe0c98f1b6ccb7cd6ea6e 100644
--- a/fpga/src/ariane_xilinx.sv
+++ b/fpga/src/ariane_xilinx.sv
@@ -86,7 +86,6 @@ module ariane_xilinx (
 // 24 MByte in 8 byte words
 localparam NumWords = (24 * 1024 * 1024) / 8;
 localparam NBSlave = 2; // debug, ariane
-localparam logic [63:0] CacheStartAddr = 64'h8000_0000;
 localparam AxiAddrWidth = 64;
 localparam AxiDataWidth = 64;
 localparam AxiIdWidthMaster = 4;
@@ -347,7 +346,7 @@ ariane_axi::req_t    axi_ariane_req;
 ariane_axi::resp_t   axi_ariane_resp;
 
 ariane #(
-    .CachedAddrBeg ( CacheStartAddr   )
+    .ArianeCfg ( ariane_soc::ArianeSocCfg )
 ) i_ariane (
     .clk_i        ( clk                 ),
     .rst_ni       ( ndmreset_n          ),
diff --git a/include/ariane_pkg.sv b/include/ariane_pkg.sv
index 8a02aa916db3c35b0c7f8792d2478462addb3df7..58a6aa43069bd8124b6bebcb0296bc6ff9935e6e 100644
--- a/include/ariane_pkg.sv
+++ b/include/ariane_pkg.sv
@@ -31,46 +31,101 @@ package ariane_pkg;
     // This is the new user config interface system. If you need to parameterize something
     // within Ariane add a field here and assign a default value to the config. Please make
     // sure to add a propper parameter check to the `check_cfg` function.
+    localparam NrMaxRules = 16;
+
     typedef struct packed {
-      int                     NrNonIdempotentRules;  // Number of non idempotent rules
-      logic [15:0][63:0]      NonIdempotentAddrBase; // base which needs to match
-      logic [15:0][63:0]      NonIdempotentLength; // bit mask which bits to consider when matching the rule
-      int                     NrExecuteRegionRules;  // Number of regions which have execute property
-      logic [15:0][63:0]      ExecuteRegionAddrBase; // base which needs to match
-      logic [15:0][63:0]      ExecuteRegionLength; // bit mask which bits to consider when matching the rule
+      // PMAs
+      int                               NrNonIdempotentRules;  // Number of non idempotent rules
+      logic [NrMaxRules-1:0][63:0]      NonIdempotentAddrBase; // base which needs to match
+      logic [NrMaxRules-1:0][63:0]      NonIdempotentLength;   // bit mask which bits to consider when matching the rule
+      int                               NrExecuteRegionRules;  // Number of regions which have execute property
+      logic [NrMaxRules-1:0][63:0]      ExecuteRegionAddrBase; // base which needs to match
+      logic [NrMaxRules-1:0][63:0]      ExecuteRegionLength;   // bit mask which bits to consider when matching the rule
+      int                               NrCachedRegionRules;   // Number of regions which have cached property
+      logic [NrMaxRules-1:0][63:0]      CachedRegionAddrBase;  // base which needs to match
+      logic [NrMaxRules-1:0][63:0]      CachedRegionLength;    // bit mask which bits to consider when matching the rule
+      // cache config
+      bit                               Axi64BitCompliant;     // set to 1 when using in conjunction with 64bit AXI bus adapter
+      bit                               SwapEndianess;         // set to 1 to swap endianess inside L1.5 openpiton adapter
+      //
+      logic [63:0]                      DmBaseAddress;         // offset of the debug module
     } ariane_cfg_t;
 
     localparam ariane_cfg_t ArianeDefaultConfig = '{
+      // idempotent region
       NrNonIdempotentRules: 2,
       NonIdempotentAddrBase: {64'b0, 64'b0},
       NonIdempotentLength:   {64'b0, 64'b0},
       NrExecuteRegionRules: 3,
       //                      DRAM,          Boot ROM,   Debug Module
       ExecuteRegionAddrBase: {64'h8000_0000, 64'h1_0000, 64'h0},
-      ExecuteRegionLength:   {64'h40000000,  64'h10000,  64'h1000}
+      ExecuteRegionLength:   {64'h40000000,  64'h10000,  64'h1000},
+      // cached region
+      NrCachedRegionRules:    1,
+      CachedRegionAddrBase:  {64'h8000_0000},
+      CachedRegionLength:    {64'h40000000},
+      //  cache config
+      Axi64BitCompliant:      1'b1,
+      SwapEndianess:          1'b0,
+      // debug
+      DmBaseAddress:          64'h0
     };
 
     // Function being called to check parameters
     function automatic void check_cfg (ariane_cfg_t Cfg);
       // pragma translate_off
       `ifndef VERILATOR
-        assert(Cfg.NrNonIdempotentRules <= 16);
-        assert(Cfg.NrExecuteRegionRules <= 16);
+        assert(Cfg.NrNonIdempotentRules <= NrMaxRules);
+        assert(Cfg.NrExecuteRegionRules <= NrMaxRules);
+        assert(Cfg.NrCachedRegionRules  <= NrMaxRules);
       `endif
       // pragma translate_on
     endfunction
 
     // Generate a mask for a given power of two length
     function logic [63:0] gen_mask (input logic [63:0] len);
-      // pragma translate_off
-      `ifndef VERILATOR
-      // check that the region we want is actually power of two aligned
-      assert (2**$clog2(len) == len) else $error("Length must be a power of two");
-      `endif
-      // pragma translate_on
       return {64{1'b1}} << $clog2(len);
     endfunction
 
+    function automatic logic range_check(logic[63:0] base, logic[63:0] len, logic[63:0] address);
+      // if len is a power of two, and base is properly aligned, this chack can be simplified
+      automatic logic[63:0] mask;
+      // mask = gen_mask(len);
+      // if ((64'b1<<$clog2(len) == len) && (mask & base == base)) begin
+      //   return (address & mask) == (base & mask);
+      // end else begin
+        return (address >= base) && (address < (base+len));
+      // end
+    endfunction : range_check
+
+    function automatic logic is_inside_nonidempotent_regions (ariane_cfg_t Cfg, logic[63:0] address);
+      logic[NrMaxRules-1:0] pass;
+      pass = '0;
+      for (int unsigned k=0; k<Cfg.NrNonIdempotentRules; k++) begin
+        pass[k] = range_check(Cfg.NonIdempotentAddrBase[k], Cfg.NonIdempotentLength[k], address);
+      end
+      return |pass;
+    endfunction : is_inside_nonidempotent_regions
+
+    function automatic logic is_inside_execute_regions (ariane_cfg_t Cfg, logic[63:0] address);
+      // if we don't specify any region we assume everything is accessible
+      logic[NrMaxRules-1:0] pass;
+      pass = '0;
+      for (int unsigned k=0; k<Cfg.NrExecuteRegionRules; k++) begin
+        pass[k] = range_check(Cfg.ExecuteRegionAddrBase[k], Cfg.ExecuteRegionLength[k], address);
+      end
+      return |pass;
+    endfunction : is_inside_execute_regions
+
+    function automatic logic is_inside_cacheable_regions (ariane_cfg_t Cfg, logic[63:0] address);
+      automatic logic[NrMaxRules-1:0] pass;
+      pass = '0;
+      for (int unsigned k=0; k<Cfg.NrCachedRegionRules; k++) begin
+        pass[k] = range_check(Cfg.CachedRegionAddrBase[k], Cfg.CachedRegionLength[k], address);
+      end
+      return |pass;
+    endfunction : is_inside_cacheable_regions
+
     // TODO: Slowly move those parameters to the new system.
     localparam NR_SB_ENTRIES = 8; // number of scoreboard entries
     localparam TRANS_ID_BITS = $clog2(NR_SB_ENTRIES); // depending on the number of scoreboard entries we need that many bits
diff --git a/openpiton/ariane_verilog_wrap.sv b/openpiton/ariane_verilog_wrap.sv
index 2ef30be09404acbbf30c21de8d3af995361a2dc4..ceb0d5a4592f47553f0c29e164aabf4a7eef1854 100644
--- a/openpiton/ariane_verilog_wrap.sv
+++ b/openpiton/ariane_verilog_wrap.sv
@@ -14,10 +14,23 @@
 
 
 module ariane_verilog_wrap #(
-  parameter logic [63:0] DmBaseAddress = 64'h0,            // debug module base address
-  parameter bit          SwapEndianess = 1,                // swap endianess in l15 adapter
-  parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
-  parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000  // begin of cached region
+  // debug module base address
+  parameter logic [63:0]               DmBaseAddress         = 64'h0,
+  // swap endianess in l15 adapter
+  parameter bit                        SwapEndianess         = 1,
+  // PMA configuration
+  // idempotent region
+  parameter int                        NrNonIdempotentRules  = 0,
+  parameter logic [NrMaxRules*64-1:0]  NonIdempotentAddrBase = '0,
+  parameter logic [NrMaxRules*64-1:0]  NonIdempotentLength   = '0,
+  // executable regions
+  parameter int                        NrExecuteRegionRules  = 0,
+  parameter logic [NrMaxRules*64-1:0]  ExecuteRegionAddrBase = '0,
+  parameter logic [NrMaxRules*64-1:0]  ExecuteRegionLength   = '0,
+  // cacheable regions
+  parameter int                        NrCachedRegionRules   = 0,
+  parameter logic [NrMaxRules*64-1:0]  CachedRegionAddrBase  = '0,
+  parameter logic [NrMaxRules*64-1:0]  CachedRegionLength    = '0
 ) (
   input                       clk_i,
   input                       reset_l,      // this is an openpiton-specific name, do not change (hier. paths in TB use this)
@@ -150,11 +163,27 @@ module ariane_verilog_wrap #(
   // ariane instance
   /////////////////////////////
 
+  localparam ariane_pkg::ariane_cfg_t ArianeOpenPitonCfg = '{
+    // idempotent region
+    NrNonIdempotentRules:  NrNonIdempotentRules,
+    NonIdempotentAddrBase: NonIdempotentAddrBase,
+    NonIdempotentLength:   NonIdempotentLength,
+    NrExecuteRegionRules:  NrExecuteRegionRules,
+    ExecuteRegionAddrBase: ExecuteRegionAddrBase,
+    ExecuteRegionLength:   ExecuteRegionLength,
+    // cached region
+    NrCachedRegionRules:   NrCachedRegionRules,
+    CachedRegionAddrBase:  CachedRegionAddrBase,
+    CachedRegionLength:    CachedRegionLength,
+    // cache config
+    Axi64BitCompliant:      1'b0,
+    SwapEndianess:          SwapEndianess,
+    // debug
+    DmBaseAddress:          DmBaseAddress
+  };
+
   ariane #(
-    .DmBaseAddress ( DmBaseAddress ),
-    .SwapEndianess ( SwapEndianess ),
-    .CachedAddrEnd ( CachedAddrEnd ),
-    .CachedAddrBeg ( CachedAddrBeg )
+    .ArianeCfg ( ArianeOpenPitonCfg )
   ) ariane (
     .clk_i       ( clk_i      ),
     .rst_ni      ( spc_grst_l ),
diff --git a/src/ariane.sv b/src/ariane.sv
index 05851595fdf24e3366e091d2638e325102894f58..23a90d2ff065ee86a8e49bc37d786b49bcdb4f29 100644
--- a/src/ariane.sv
+++ b/src/ariane.sv
@@ -13,20 +13,11 @@
 // Description: Ariane Top-level module
 
 import ariane_pkg::*;
-// pragma translate_off
-`ifndef VERILATOR
-import instruction_tracer_pkg::*;
-`endif
-// pragma translate_on
-
 
 module ariane #(
-  parameter logic [63:0] DmBaseAddress = 64'h0,            // debug module base address
-  parameter int unsigned AxiIdWidth    = 4,
-  parameter bit          SwapEndianess = 0,                // swap endianess in l15 adapter
-  parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
-  parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
-  parameter ariane_pkg::ariane_cfg_t Cfg = ariane_pkg::ArianeDefaultConfig
+  parameter int unsigned             AxiIdWidth    = 4,
+  parameter bit                      SwapEndianess = 0,                // swap endianess in l15 adapter
+  parameter ariane_pkg::ariane_cfg_t ArianeCfg     = ariane_pkg::ArianeDefaultConfig
 ) (
   input  logic                         clk_i,
   input  logic                         rst_ni,
@@ -231,7 +222,7 @@ module ariane #(
   // Frontend
   // --------------
   frontend #(
-    .DmBaseAddress       ( DmBaseAddress )
+    .DmBaseAddress       ( ArianeCfg.DmBaseAddress )
   ) i_frontend (
     .flush_i             ( flush_ctrl_if                 ), // not entirely correct
     .flush_bp_i          ( 1'b0                          ),
@@ -341,7 +332,7 @@ module ariane #(
   // EX
   // ---------
   ex_stage #(
-    .Cfg ( Cfg )
+    .ArianeCfg ( ArianeCfg )
   ) ex_stage_i (
     .clk_i                  ( clk_i                       ),
     .rst_ni                 ( rst_ni                      ),
@@ -465,7 +456,7 @@ module ariane #(
   // ---------
   csr_regfile #(
     .AsidWidth              ( ASID_WIDTH                    ),
-    .DmBaseAddress          ( DmBaseAddress                 )
+    .DmBaseAddress          ( ArianeCfg.DmBaseAddress       )
   ) csr_regfile_i (
     .flush_o                ( flush_csr_ctrl                ),
     .halt_csr_o             ( halt_csr_ctrl                 ),
@@ -580,9 +571,7 @@ module ariane #(
   // this is a cache subsystem that is compatible with OpenPiton
   wt_cache_subsystem #(
     .AxiIdWidth           ( AxiIdWidth    ),
-    .CachedAddrBeg        ( CachedAddrBeg ),
-    .CachedAddrEnd        ( CachedAddrEnd ),
-    .SwapEndianess        ( SwapEndianess )
+    .ArianeCfg            ( ArianeCfg     )
   ) i_cache_subsystem (
     // to D$
     .clk_i                 ( clk_i                       ),
@@ -620,7 +609,10 @@ module ariane #(
 `else
 
   std_cache_subsystem #(
-      .CACHE_START_ADDR    ( CachedAddrBeg )
+    // note: this only works with one cacheable region
+    // not as important since this cache subsystem is about to be
+    // deprecated
+    .CACHE_START_ADDR    ( ArianeCfg.CachedRegionAddrBase )
   ) i_cache_subsystem (
     // to D$
     .clk_i                 ( clk_i                       ),
@@ -658,7 +650,7 @@ module ariane #(
   // -------------------
   // pragma translate_off
   `ifndef VERILATOR
-  initial ariane_pkg::check_cfg(Cfg);
+  initial ariane_pkg::check_cfg(ArianeCfg);
   `endif
   // pragma translate_on
 
@@ -748,25 +740,11 @@ module ariane #(
   // assign current privilege level
   assign tracer_if.priv_lvl          = priv_lvl;
   assign tracer_if.debug_mode        = debug_mode;
-  instr_tracer instr_tracer_i (tracer_if, hart_id_i);
-
-  program instr_tracer (
-      instruction_tracer_if tracer_if,
-      input logic [63:0]    hart_id_i
-    );
 
-    instruction_tracer it = new (tracer_if, 1'b0);
-
-    initial begin
-      #15ns;
-      it.create_file(hart_id_i);
-      it.trace();
-    end
-
-    final begin
-      it.close();
-    end
-  endprogram
+  instruction_tracer instr_tracer_i (
+    .tracer_if(tracer_if),
+    .hart_id_i
+  );
 
 // mock tracer for Verilator, to be used with spike-dasm
 `else
diff --git a/src/cache_subsystem/wt_cache_subsystem.sv b/src/cache_subsystem/wt_cache_subsystem.sv
index 32093206b993e9ad315a953a6701c3401bac982c..d38335c8fe9ab3cd995f1b42f8b1ce485f446965 100644
--- a/src/cache_subsystem/wt_cache_subsystem.sv
+++ b/src/cache_subsystem/wt_cache_subsystem.sv
@@ -22,10 +22,8 @@ import ariane_pkg::*;
 import wt_cache_pkg::*;
 
 module wt_cache_subsystem #(
-  parameter int unsigned AxiIdWidth    = 10,
-  parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
-  parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
-  parameter bit          SwapEndianess = 0                 // swap endianess in l15 adapter
+  parameter int unsigned             AxiIdWidth      = 10,
+  parameter ariane_pkg::ariane_cfg_t ArianeCfg       = ariane_pkg::ArianeDefaultConfig  // contains cacheable regions
 ) (
   input logic                            clk_i,
   input logic                            rst_ni,
@@ -75,15 +73,9 @@ module wt_cache_subsystem #(
   wt_cache_pkg::dcache_rtrn_t adapter_dcache;
 
   wt_icache #(
-`ifdef PITON_ARIANE
-    .Axi64BitCompliant  ( 1'b0          ),
-`else
-    .Axi64BitCompliant  ( 1'b1          ),
-`endif
     // use ID 0 for icache reads
     .RdTxId             ( 0             ),
-    .CachedAddrBeg      ( CachedAddrBeg ),
-    .CachedAddrEnd      ( CachedAddrEnd )
+    .ArianeCfg          ( ArianeCfg     )
   ) i_wt_icache (
     .clk_i              ( clk_i                   ),
     .rst_ni             ( rst_ni                  ),
@@ -107,16 +99,10 @@ module wt_cache_subsystem #(
   // they have equal prio and are RR arbited
   // Port 2 is write only and goes into the merging write buffer
   wt_dcache #(
-`ifdef PITON_ARIANE
-  	.Axi64BitCompliant  ( 1'b0          ),
-`else
-  	.Axi64BitCompliant  ( 1'b1          ),
-`endif
     // use ID 1 for dcache reads and amos. note that the writebuffer
     // uses all IDs up to DCACHE_MAX_TX-1 for write transactions.
     .RdAmoTxId       ( 1             ),
-    .CachedAddrBeg   ( CachedAddrBeg ),
-    .CachedAddrEnd   ( CachedAddrEnd )
+    .ArianeCfg       ( ArianeCfg     )
   ) i_wt_dcache (
     .clk_i           ( clk_i                   ),
     .rst_ni          ( rst_ni                  ),
@@ -144,7 +130,7 @@ module wt_cache_subsystem #(
 
 `ifdef PITON_ARIANE
   wt_l15_adapter #(
-    .SwapEndianess   ( SwapEndianess )
+    .SwapEndianess   ( ArianeCfg.SwapEndianess )
   ) i_adapter (
     .clk_i              ( clk_i                   ),
     .rst_ni             ( rst_ni                  ),
diff --git a/src/cache_subsystem/wt_dcache.sv b/src/cache_subsystem/wt_dcache.sv
index bb0709fa8fe25ac8e59fc438b07344910b86e0ec..34a400641f1cc944e8c51f08dfca4d9e899bb947 100644
--- a/src/cache_subsystem/wt_dcache.sv
+++ b/src/cache_subsystem/wt_dcache.sv
@@ -16,12 +16,11 @@ import ariane_pkg::*;
 import wt_cache_pkg::*;
 
 module wt_dcache #(
-  parameter bit                          Axi64BitCompliant  = 1'b0,             // set this to 1 when using in conjunction with 64bit AXI bus adapter
   // ID to be used for read and AMO transactions.
   // note that the write buffer uses all IDs up to DCACHE_MAX_TX-1 for write transactions
   parameter logic [CACHE_ID_WIDTH-1:0]   RdAmoTxId          = 1,
-  parameter logic [63:0]                 CachedAddrBeg      = 64'h00_8000_0000, // begin of cached region
-  parameter logic [63:0]                 CachedAddrEnd      = 64'h80_0000_0000  // end of cached region
+  // contains cacheable regions
+  parameter ariane_pkg::ariane_cfg_t     ArianeCfg          = ariane_pkg::ArianeDefaultConfig
 ) (
   input  logic                           clk_i,       // Clock
   input  logic                           rst_ni,      // Asynchronous reset active low
@@ -110,9 +109,9 @@ module wt_dcache #(
 ///////////////////////////////////////////////////////
 
   wt_dcache_missunit #(
-    .Axi64BitCompliant ( Axi64BitCompliant ),
-    .AmoTxId           ( RdAmoTxId         ),
-    .NumPorts          ( NumPorts          )
+    .Axi64BitCompliant ( ArianeCfg.Axi64BitCompliant ),
+    .AmoTxId           ( RdAmoTxId                   ),
+    .NumPorts          ( NumPorts                    )
   ) i_wt_dcache_missunit (
     .clk_i              ( clk_i              ),
     .rst_ni             ( rst_ni             ),
@@ -170,8 +169,7 @@ module wt_dcache #(
 
     wt_dcache_ctrl #(
       .RdTxId        ( RdAmoTxId     ),
-      .CachedAddrBeg ( CachedAddrBeg ),
-      .CachedAddrEnd ( CachedAddrEnd )
+      .ArianeCfg     ( ArianeCfg     )
     ) i_wt_dcache_ctrl (
       .clk_i           ( clk_i             ),
       .rst_ni          ( rst_ni            ),
@@ -213,8 +211,7 @@ module wt_dcache #(
   assign rd_prio[2] = 1'b0;
 
   wt_dcache_wbuffer #(
-    .CachedAddrBeg ( CachedAddrBeg ),
-    .CachedAddrEnd ( CachedAddrEnd )
+    .ArianeCfg     ( ArianeCfg     )
   ) i_wt_dcache_wbuffer (
     .clk_i           ( clk_i               ),
     .rst_ni          ( rst_ni              ),
@@ -268,8 +265,8 @@ module wt_dcache #(
 ///////////////////////////////////////////////////////
 
   wt_dcache_mem #(
-    .Axi64BitCompliant ( Axi64BitCompliant ),
-    .NumPorts          ( NumPorts          )
+    .Axi64BitCompliant ( ArianeCfg.Axi64BitCompliant ),
+    .NumPorts          ( NumPorts                    )
   ) i_wt_dcache_mem (
     .clk_i             ( clk_i              ),
     .rst_ni            ( rst_ni             ),
diff --git a/src/cache_subsystem/wt_dcache_ctrl.sv b/src/cache_subsystem/wt_dcache_ctrl.sv
index 2eea9aa839e8892b2c22c728e4bdb6ada037590b..b99c61f3ee4d240836f74667e73bacf3757fdbe4 100644
--- a/src/cache_subsystem/wt_dcache_ctrl.sv
+++ b/src/cache_subsystem/wt_dcache_ctrl.sv
@@ -16,9 +16,8 @@ import ariane_pkg::*;
 import wt_cache_pkg::*;
 
 module wt_dcache_ctrl #(
-  parameter logic [CACHE_ID_WIDTH-1:0]  RdTxId        = 1,                // ID to use for read transactions
-  parameter logic [63:0]                CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
-  parameter logic [63:0]                CachedAddrEnd = 64'h80_0000_0000  // end of cached region
+  parameter logic [CACHE_ID_WIDTH-1:0]  RdTxId    = 1,                              // ID to use for read transactions
+  parameter ariane_pkg::ariane_cfg_t    ArianeCfg = ariane_pkg::ArianeDefaultConfig // contains cacheable regions
 ) (
   input  logic                            clk_i,          // Clock
   input  logic                            rst_ni,         // Asynchronous reset active low
@@ -84,9 +83,9 @@ module wt_dcache_ctrl #(
   assign miss_paddr_o          = {address_tag_q, address_idx_q, address_off_q};
   assign miss_size_o           = (miss_nc_o) ? data_size_q : 3'b111;
 
-  assign miss_nc_o = (address_tag_q <  (CachedAddrBeg>>DCACHE_INDEX_WIDTH)) ||
-                     (address_tag_q >= (CachedAddrEnd>>DCACHE_INDEX_WIDTH)) ||
-                     (!cache_en_i);
+  // noncacheable if request goes to I/O space, or if cache is disabled
+  assign miss_nc_o = (~cache_en_i) | (~ariane_pkg::is_inside_cacheable_regions(ArianeCfg, {address_tag_q, {DCACHE_INDEX_WIDTH{1'b0}}}));
+
 
   assign miss_we_o    = '0;
   assign miss_wdata_o = '0;
diff --git a/src/cache_subsystem/wt_dcache_wbuffer.sv b/src/cache_subsystem/wt_dcache_wbuffer.sv
index dbc370dc8c5ddbb519ea07f4cc13ee5da771b15e..865411bf46b92c1a02af5b8ba99595a311bb4df2 100644
--- a/src/cache_subsystem/wt_dcache_wbuffer.sv
+++ b/src/cache_subsystem/wt_dcache_wbuffer.sv
@@ -52,8 +52,7 @@ import ariane_pkg::*;
 import wt_cache_pkg::*;
 
 module wt_dcache_wbuffer #(
-  parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
-  parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000  // end of cached region
+  parameter ariane_pkg::ariane_cfg_t    ArianeCfg          = ariane_pkg::ArianeDefaultConfig     // contains cacheable regions
 ) (
   input  logic                               clk_i,          // Clock
   input  logic                               rst_ni,         // Asynchronous reset active low
@@ -136,9 +135,8 @@ module wt_dcache_wbuffer #(
 
   assign miss_nc_o = nc_pending_q;
 
-  assign addr_is_nc = (req_port_i.address_tag <  (CachedAddrBeg>>DCACHE_INDEX_WIDTH)) ||
-                      (req_port_i.address_tag >= (CachedAddrEnd>>DCACHE_INDEX_WIDTH)) ||
-                      (!cache_en_i);
+  // noncacheable if request goes to I/O space, or if cache is disabled
+  assign addr_is_nc = (~cache_en_i) | (~ariane_pkg::is_inside_cacheable_regions(ArianeCfg, {req_port_i.address_tag, {DCACHE_INDEX_WIDTH{1'b0}}}));
 
   assign miss_we_o       = 1'b1;
   assign miss_vld_bits_o = '0;
diff --git a/src/cache_subsystem/wt_icache.sv b/src/cache_subsystem/wt_icache.sv
index 9d5f3840b56a91c7f555c0ed5593f6d2443a92a9..effafa49a5a9f70e5de9d98db5ca55f53c40cbbf 100644
--- a/src/cache_subsystem/wt_icache.sv
+++ b/src/cache_subsystem/wt_icache.sv
@@ -28,10 +28,8 @@ import ariane_pkg::*;
 import wt_cache_pkg::*;
 
 module wt_icache  #(
-  parameter logic [CACHE_ID_WIDTH-1:0]  RdTxId             = 0,                // ID to be used for read transactions
-  parameter bit                         Axi64BitCompliant  = 1'b0,             // set this to 1 when using in conjunction with 64bit AXI bus adapter
-  parameter logic [63:0]                CachedAddrBeg      = 64'h00_8000_0000, // begin of cached region
-  parameter logic [63:0]                CachedAddrEnd      = 64'h80_0000_0000  // end of cached region
+  parameter logic [CACHE_ID_WIDTH-1:0]  RdTxId             = 0,                                  // ID to be used for read transactions
+  parameter ariane_pkg::ariane_cfg_t    ArianeCfg          = ariane_pkg::ArianeDefaultConfig     // contains cacheable regions
 ) (
   input  logic                      clk_i,
   input  logic                      rst_ni,
@@ -103,9 +101,7 @@ module wt_icache  #(
   assign cl_tag_d  = (areq_i.fetch_valid) ? areq_i.fetch_paddr[ICACHE_TAG_WIDTH+ICACHE_INDEX_WIDTH-1:ICACHE_INDEX_WIDTH] : cl_tag_q;
 
   // noncacheable if request goes to I/O space, or if cache is disabled
-  assign paddr_is_nc = (cl_tag_d <  (CachedAddrBeg>>ICACHE_INDEX_WIDTH)) ||
-                       (cl_tag_d >= (CachedAddrEnd>>ICACHE_INDEX_WIDTH)) ||
-                       (!cache_en_q);
+  assign paddr_is_nc = (~cache_en_q) | (~ariane_pkg::is_inside_cacheable_regions(ArianeCfg, {cl_tag_d, {ICACHE_INDEX_WIDTH{1'b0}}}));
 
   // pass exception through
   assign dreq_o.ex = areq_i.fetch_exception;
@@ -119,7 +115,7 @@ module wt_icache  #(
   assign cl_index    = vaddr_d[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
 
 
-  if (Axi64BitCompliant) begin : gen_axi_offset
+  if (ArianeCfg.Axi64BitCompliant) begin : gen_axi_offset
     // if we generate a noncacheable access, the word will be at offset 0 or 4 in the cl coming from memory
     assign cl_offset_d = ( dreq_o.ready & dreq_i.req)      ? {dreq_i.vaddr>>2, 2'b0} :
                          ( paddr_is_nc  & mem_data_req_o ) ? cl_offset_q[2]<<2 : // needed since we transfer 32bit over a 64bit AXI bus in this case
diff --git a/src/ex_stage.sv b/src/ex_stage.sv
index 273e65d38cadf11196157da1dc01295f0232077d..f1f813340ebe1aab8328227fd1dc040efa8614a0 100644
--- a/src/ex_stage.sv
+++ b/src/ex_stage.sv
@@ -16,7 +16,7 @@
 import ariane_pkg::*;
 
 module ex_stage #(
-    parameter ariane_pkg::ariane_cfg_t Cfg = ariane_pkg::ArianeDefaultConfig
+    parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
 ) (
     input  logic                                   clk_i,    // Clock
     input  logic                                   rst_ni,   // Asynchronous reset active low
@@ -252,7 +252,7 @@ module ex_stage #(
     assign lsu_data  = lsu_valid_i ? fu_data_i  : '0;
 
     load_store_unit #(
-      .Cfg ( Cfg )
+      .ArianeCfg ( ArianeCfg )
     ) lsu_i (
         .clk_i,
         .rst_ni,
diff --git a/src/load_store_unit.sv b/src/load_store_unit.sv
index 90819d376a7a5577ce20ee8984477a47204b12c7..481eaab4e2d71f3f2a84b49eb47057c1e677669c 100644
--- a/src/load_store_unit.sv
+++ b/src/load_store_unit.sv
@@ -16,7 +16,7 @@ import ariane_pkg::*;
 
 module load_store_unit #(
     parameter int unsigned ASID_WIDTH = 1,
-    parameter ariane_pkg::ariane_cfg_t Cfg = ariane_pkg::ArianeDefaultConfig
+    parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
 )(
     input  logic                     clk_i,
     input  logic                     rst_ni,
@@ -121,7 +121,7 @@ module load_store_unit #(
         .INSTR_TLB_ENTRIES      ( 16                     ),
         .DATA_TLB_ENTRIES       ( 16                     ),
         .ASID_WIDTH             ( ASID_WIDTH             ),
-        .Cfg                    ( Cfg                    )
+        .ArianeCfg              ( ArianeCfg              )
     ) i_mmu (
             // misaligned bypass
         .misaligned_ex_i        ( misaligned_exception   ),
diff --git a/src/mmu.sv b/src/mmu.sv
index eb88cdf5d732a67c885a31e9cb9327275f575d00..00ef8e278fcad2f05e9464d67ef00c609ab21004 100644
--- a/src/mmu.sv
+++ b/src/mmu.sv
@@ -17,10 +17,10 @@
 import ariane_pkg::*;
 
 module mmu #(
-      parameter int unsigned INSTR_TLB_ENTRIES = 4,
-      parameter int unsigned DATA_TLB_ENTRIES  = 4,
-      parameter int unsigned ASID_WIDTH        = 1,
-      parameter ariane_pkg::ariane_cfg_t Cfg = ariane_pkg::ArianeDefaultConfig
+      parameter int unsigned INSTR_TLB_ENTRIES     = 4,
+      parameter int unsigned DATA_TLB_ENTRIES      = 4,
+      parameter int unsigned ASID_WIDTH            = 1,
+      parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
 ) (
         input  logic                            clk_i,
         input  logic                            rst_ni,
@@ -243,15 +243,9 @@ module mmu #(
         end
     end
 
-    always_comb begin : execute_addr_check
-        // if we don't specify any region we assume everything is accessible
-        match_any_execute_region = (Cfg.NrExecuteRegionRules == 0);
-        // check for execute flag on memory
-        for (int i = 0; i < Cfg.NrExecuteRegionRules; i++) begin
-            match_any_execute_region |= (Cfg.ExecuteRegionAddrBase[i] & ariane_pkg::gen_mask(Cfg.ExecuteRegionLength[i]))
-                                    == (icache_areq_o.fetch_paddr & ariane_pkg::gen_mask(Cfg.ExecuteRegionLength[i]));
-        end
-    end
+    // check for execute flag on memory
+    assign match_any_execute_region = ariane_pkg::is_inside_execute_regions(ArianeCfg, icache_areq_o.fetch_paddr);
+
     //-----------------------
     // Data Interface
     //-----------------------
diff --git a/src/util/instruction_tracer.svh b/src/util/instruction_tracer.svh
deleted file mode 100644
index a056e237b24d4d6b28c04de915883b27003fb976..0000000000000000000000000000000000000000
--- a/src/util/instruction_tracer.svh
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2018 ETH Zurich and University of Bologna.
-// Copyright and related rights are licensed under the Solderpad Hardware
-// License, Version 0.51 (the "License"); you may not use this file except in
-// compliance with the License.  You may obtain a copy of the License at
-// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
-// or agreed to in writing, software, hardware and materials distributed under
-// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-//
-// Author: Florian Zaruba, ETH Zurich
-// Date: 16.05.2017
-// Description: Instruction Tracer Main Class
-
-
-class instruction_tracer;
-    // interface to the core
-    virtual instruction_tracer_if tracer_if;
-    // keep the decoded instructions in a queue
-    logic [31:0] decode_queue [$];
-    // keep the issued instructions in a queue
-    logic [31:0] issue_queue [$];
-    // issue scoreboard entries
-    scoreboard_entry_t issue_sbe_queue [$];
-    scoreboard_entry_t issue_sbe;
-    // store resolved branches, get (mis-)predictions
-    branchpredict_t bp [$];
-    // shadow copy of the register files
-    logic [63:0] gp_reg_file [32];
-    logic [63:0] fp_reg_file [32];
-    // 64 bit clock tick count
-    longint unsigned clk_ticks;
-    int f, commit_log;
-    // address mapping
-    // contains mappings of the form vaddr <-> paddr
-    // should it print the instructions to the console
-    logic display_instructions;
-    logic [63:0] store_mapping[$], load_mapping[$], address_mapping;
-
-    // static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
-
-
-    function new(virtual instruction_tracer_if tracer_if, logic display_instructions);
-
-        this.tracer_if = tracer_if;
-        this.display_instructions = display_instructions;
-
-    endfunction : new
-
-    function void create_file(logic [63:0] hart_id);
-        string fn, fn_commit_log;
-        $sformat(fn, "trace_hart_%04.0f.log", hart_id);
-        $sformat(fn_commit_log, "trace_hart_%04.0f_commit.log", hart_id);
-        $display("[TRACER] Output filename is: %s", fn);
-
-        this.f = $fopen(fn,"w");
-        if (ENABLE_SPIKE_COMMIT_LOG) this.commit_log = $fopen(fn_commit_log, "w");
-    endfunction : create_file
-
-    task trace();
-        logic [31:0] decode_instruction, issue_instruction, issue_commit_instruction;
-        scoreboard_entry_t commit_instruction;
-        // initialize register 0
-        gp_reg_file  = '{default:0};
-        fp_reg_file  = '{default:0};
-
-        forever begin
-            automatic branchpredict_t bp_instruction = '0;
-            // new cycle, we are only interested if reset is de-asserted
-            @(tracer_if.pck iff tracer_if.pck.rstn);
-            // increment clock tick
-            clk_ticks++;
-
-            // -------------------
-            // Instruction Decode
-            // -------------------
-            // we are decoding an instruction
-            if (tracer_if.pck.fetch_valid && tracer_if.pck.fetch_ack) begin
-                decode_instruction = tracer_if.pck.instruction;
-                decode_queue.push_back(decode_instruction);
-            end
-            // -------------------
-            // Instruction Issue
-            // -------------------
-            // we got a new issue ack, so put the element from the decode queue to
-            // the issue queue
-            if (tracer_if.pck.issue_ack && !tracer_if.pck.flush_unissued) begin
-                issue_instruction = decode_queue.pop_front();
-                issue_queue.push_back(issue_instruction);
-                // also save the scoreboard entry to a separate issue queue
-                issue_sbe_queue.push_back(scoreboard_entry_t'(tracer_if.pck.issue_sbe));
-            end
-
-            // --------------------
-            // Address Translation
-            // --------------------
-            if (tracer_if.pck.st_valid) begin
-                store_mapping.push_back(tracer_if.pck.st_paddr);
-            end
-
-            if (tracer_if.pck.ld_valid && !tracer_if.pck.ld_kill) begin
-                load_mapping.push_back(tracer_if.pck.ld_paddr);
-            end
-            // ----------------------
-            // Store predictions
-            // ----------------------
-            if (tracer_if.pck.resolve_branch.valid) begin
-                bp.push_back(tracer_if.pck.resolve_branch);
-            end
-            // --------------
-            //  Commit
-            // --------------
-            // we are committing an instruction
-            for (int i = 0; i < 2; i++) begin
-                if (tracer_if.pck.commit_ack[i]) begin
-                    commit_instruction = scoreboard_entry_t'(tracer_if.pck.commit_instr[i]);
-                    issue_commit_instruction = issue_queue.pop_front();
-                    issue_sbe = issue_sbe_queue.pop_front();
-                    // check if the instruction retiring is a load or store, get the physical address accordingly
-                    if (tracer_if.pck.commit_instr[i].fu == LOAD)
-                        address_mapping = load_mapping.pop_front();
-                    else if (tracer_if.pck.commit_instr[i].fu == STORE)
-                        address_mapping = store_mapping.pop_front();
-
-                    if (tracer_if.pck.commit_instr[i].fu == CTRL_FLOW)
-                        bp_instruction = bp.pop_front();
-                    // the scoreboards issue entry still contains the immediate value as a result
-                    // check if the write back is valid, if not we need to source the result from the register file
-                    // as the most recent version of this register will be there.
-                    if (tracer_if.pck.we_gpr[i] || tracer_if.pck.we_fpr[i]) begin
-                        printInstr(issue_sbe, issue_commit_instruction, tracer_if.pck.wdata[i], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
-                    end else if (is_rd_fpr(commit_instruction.op)) begin
-                        printInstr(issue_sbe, issue_commit_instruction, fp_reg_file[commit_instruction.rd], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
-                    end else begin
-                        printInstr(issue_sbe, issue_commit_instruction, gp_reg_file[commit_instruction.rd], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
-                    end
-                end
-            end
-            // --------------
-            // Exceptions
-            // --------------
-            if (tracer_if.pck.exception.valid && !(tracer_if.pck.debug_mode && tracer_if.pck.exception.cause == riscv::BREAKPOINT)) begin
-                // print exception
-                printException(tracer_if.pck.commit_instr[0].pc, tracer_if.pck.exception.cause, tracer_if.pck.exception.tval);
-            end
-            // ----------------------
-            // Commit Registers
-            // ----------------------
-            // update shadow reg files here
-            for (int i = 0; i < 2; i++) begin
-                if (tracer_if.pck.we_gpr[i] && tracer_if.pck.waddr[i] != 5'b0) begin
-                    gp_reg_file[tracer_if.pck.waddr[i]] = tracer_if.pck.wdata[i];
-                end else if (tracer_if.pck.we_fpr[i]) begin
-                    fp_reg_file[tracer_if.pck.waddr[i]] = tracer_if.pck.wdata[i];
-                end
-            end
-            // --------------
-            // Flush Signals
-            // --------------
-            // flush un-issued instructions
-            if (tracer_if.pck.flush_unissued) begin
-                this.flushDecode();
-            end
-            // flush whole pipeline
-            if (tracer_if.pck.flush) begin
-                this.flush();
-            end
-        end
-
-    endtask
-
-    // flush all decoded instructions
-    function void flushDecode ();
-        decode_queue = {};
-    endfunction
-
-    // flush everything, we took an exception/interrupt
-    function void flush ();
-        this.flushDecode();
-        // clear all elements in the queue
-        issue_queue     = {};
-        issue_sbe_queue = {};
-        // also clear mappings
-        store_mapping   = {};
-        load_mapping    = {};
-        bp              = {};
-    endfunction
-
-    function void printInstr(scoreboard_entry_t sbe, logic [31:0] instr, logic [63:0] result, logic [63:0] paddr, riscv::priv_lvl_t priv_lvl, logic debug_mode, branchpredict_t bp);
-        instruction_trace_item iti = new ($time, clk_ticks, sbe, instr, this.gp_reg_file, this.fp_reg_file, result, paddr, priv_lvl, debug_mode, bp);
-        // print instruction to console
-        string print_instr = iti.printInstr();
-        if (ENABLE_SPIKE_COMMIT_LOG && !debug_mode) begin
-            $fwrite(this.commit_log, riscv::spikeCommitLog(sbe.pc, priv_lvl, instr, sbe.rd, result, is_rd_fpr(sbe.op)));
-        end
-        uvm_report_info( "Tracer",  print_instr, UVM_HIGH);
-        $fwrite(this.f, {print_instr, "\n"});
-    endfunction
-
-    function void printException(logic [63:0] pc, logic [63:0] cause, logic [63:0] tval);
-        exception_trace_item eti = new (pc, cause, tval);
-        string print_ex = eti.printException();
-        uvm_report_info( "Tracer",  print_ex, UVM_HIGH);
-        $fwrite(this.f, {print_ex, "\n"});
-    endfunction
-
-    function void close();
-        if (f) $fclose(this.f);
-        if (ENABLE_SPIKE_COMMIT_LOG && this.commit_log) $fclose(this.commit_log);
-    endfunction
-
-endclass : instruction_tracer
diff --git a/src/util/instruction_tracer_pkg.sv b/src/util/instruction_tracer_pkg.sv
deleted file mode 100644
index f17d6c88cdbc50b6f38dc6c8ebd145bd8c860f72..0000000000000000000000000000000000000000
--- a/src/util/instruction_tracer_pkg.sv
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 ETH Zurich and University of Bologna.
-// Copyright and related rights are licensed under the Solderpad Hardware
-// License, Version 0.51 (the "License"); you may not use this file except in
-// compliance with the License.  You may obtain a copy of the License at
-// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
-// or agreed to in writing, software, hardware and materials distributed under
-// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-//
-// Author: Florian Zaruba, ETH Zurich
-// Date: 16.05.2017
-// Description: Instruction Tracer Package
-
-package instruction_tracer_pkg;
-
-    import ariane_pkg::*;
-    //pragma translate_off
-    import uvm_pkg::*;
-    `include "uvm_macros.svh"
-    `include "instruction_tracer_defines.svh"
-    `include "instruction_trace_item.svh"
-    `include "exception_trace_item.svh"
-    `include "instruction_tracer.svh"
-    //pragma translate_on
-
-endpackage
diff --git a/tb/ariane_soc_pkg.sv b/tb/ariane_soc_pkg.sv
index 316b9866de0eb150e111f73413bf580dc2fd5dff..bfe408f21962eb322a3b4ef8d9801ab4ac7ce72b 100644
--- a/tb/ariane_soc_pkg.sv
+++ b/tb/ariane_soc_pkg.sv
@@ -11,58 +11,78 @@
 // Author: Florian Zaruba, ETH Zurich
 // Description: Contains SoC information as constants
 package ariane_soc;
-    // M-Mode Hart, S-Mode Hart
-    localparam int unsigned NumTargets = 2;
-    // Uart, SPI, Ethernet, reserved
-    localparam int unsigned NumSources = 30;
-    localparam int unsigned MaxPriority = 7;
+  // M-Mode Hart, S-Mode Hart
+  localparam int unsigned NumTargets = 2;
+  // Uart, SPI, Ethernet, reserved
+  localparam int unsigned NumSources = 30;
+  localparam int unsigned MaxPriority = 7;
 
-    localparam NrSlaves = 2; // actually masters, but slaves on the crossbar
+  localparam NrSlaves = 2; // actually masters, but slaves on the crossbar
 
-    // 4 is recommended by AXI standard, so lets stick to it, do not change
-    localparam IdWidth   = 4;
-    localparam IdWidthSlave = IdWidth + $clog2(NrSlaves);
+  // 4 is recommended by AXI standard, so lets stick to it, do not change
+  localparam IdWidth   = 4;
+  localparam IdWidthSlave = IdWidth + $clog2(NrSlaves);
 
-    typedef enum int unsigned {
-        DRAM     = 0,
-        GPIO     = 1,
-        Ethernet = 2,
-        SPI      = 3,
-        UART     = 4,
-        PLIC     = 5,
-        CLINT    = 6,
-        ROM      = 7,
-        Debug    = 8
-    } axi_slaves_t;
+  typedef enum int unsigned {
+    DRAM     = 0,
+    GPIO     = 1,
+    Ethernet = 2,
+    SPI      = 3,
+    UART     = 4,
+    PLIC     = 5,
+    CLINT    = 6,
+    ROM      = 7,
+    Debug    = 8
+  } axi_slaves_t;
 
-    localparam NB_PERIPHERALS = Debug + 1;
+  localparam NB_PERIPHERALS = Debug + 1;
 
-    localparam logic[63:0] DebugLength    = 64'h1000;
-    localparam logic[63:0] ROMLength      = 64'h10000;
-    localparam logic[63:0] CLINTLength    = 64'hC0000;
-    localparam logic[63:0] PLICLength     = 64'h3FF_FFFF;
-    localparam logic[63:0] UARTLength     = 64'h1000;
-    localparam logic[63:0] SPILength      = 64'h800000;
-    localparam logic[63:0] EthernetLength = 64'h10000;
-    localparam logic[63:0] GPIOLength     = 64'h1000;
-    localparam logic[63:0] DRAMLength     = 64'h40000000; // 1GByte of DDR (split between two chips on Genesys2)
-    localparam logic[63:0] SRAMLength     = 64'h1800000;  // 24 MByte of SRAM
-    // Instantiate AXI protocol checkers
-    localparam bit GenProtocolChecker = 1'b0;
 
-    typedef enum logic [63:0] {
-        DebugBase    = 64'h0000_0000,
-        ROMBase      = 64'h0001_0000,
-        CLINTBase    = 64'h0200_0000,
-        PLICBase     = 64'h0C00_0000,
-        UARTBase     = 64'h1000_0000,
-        SPIBase      = 64'h2000_0000,
-        EthernetBase = 64'h3000_0000,
-        GPIOBase     = 64'h4000_0000,
-        DRAMBase     = 64'h8000_0000
-    } soc_bus_start_t;
+  localparam logic[63:0] DebugLength    = 64'h1000;
+  localparam logic[63:0] ROMLength      = 64'h10000;
+  localparam logic[63:0] CLINTLength    = 64'hC0000;
+  localparam logic[63:0] PLICLength     = 64'h3FF_FFFF;
+  localparam logic[63:0] UARTLength     = 64'h1000;
+  localparam logic[63:0] SPILength      = 64'h800000;
+  localparam logic[63:0] EthernetLength = 64'h10000;
+  localparam logic[63:0] GPIOLength     = 64'h1000;
+  localparam logic[63:0] DRAMLength     = 64'h40000000; // 1GByte of DDR (split between two chips on Genesys2)
+  localparam logic[63:0] SRAMLength     = 64'h1800000;  // 24 MByte of SRAM
+  // Instantiate AXI protocol checkers
+  localparam bit GenProtocolChecker = 1'b0;
 
-    localparam NrRegion = 1;
-    localparam logic [NrRegion-1:0][NB_PERIPHERALS-1:0] ValidRule = {{NrRegion * NB_PERIPHERALS}{1'b1}};
+  typedef enum logic [63:0] {
+    DebugBase    = 64'h0000_0000,
+    ROMBase      = 64'h0001_0000,
+    CLINTBase    = 64'h0200_0000,
+    PLICBase     = 64'h0C00_0000,
+    UARTBase     = 64'h1000_0000,
+    SPIBase      = 64'h2000_0000,
+    EthernetBase = 64'h3000_0000,
+    GPIOBase     = 64'h4000_0000,
+    DRAMBase     = 64'h8000_0000
+  } soc_bus_start_t;
+
+  localparam NrRegion = 1;
+  localparam logic [NrRegion-1:0][NB_PERIPHERALS-1:0] ValidRule = {{NrRegion * NB_PERIPHERALS}{1'b1}};
+
+  localparam ariane_pkg::ariane_cfg_t ArianeSocCfg = '{
+    // idempotent region
+    NrNonIdempotentRules:  0,
+    NonIdempotentAddrBase: {64'b0},
+    NonIdempotentLength:   {64'b0},
+    NrExecuteRegionRules:  3,
+    ExecuteRegionAddrBase: {DRAMBase,   ROMBase,   DebugBase},
+    ExecuteRegionLength:   {DRAMLength, ROMLength, DebugLength},
+    // cached region
+    NrCachedRegionRules:    1,
+    CachedRegionAddrBase:  {DRAMBase},
+    CachedRegionLength:    {DRAMLength},
+    //  cache config
+    Axi64BitCompliant:      1'b1,
+    SwapEndianess:          1'b0,
+    // debug
+    DmBaseAddress:          DebugBase
+  };
 
 endpackage
diff --git a/tb/ariane_testharness.sv b/tb/ariane_testharness.sv
index 67cbb0dffbe17f7ab4107ed3c4edd8be30754224..be0fc9dd029f76d80953d134f89756928e8f3fc3 100644
--- a/tb/ariane_testharness.sv
+++ b/tb/ariane_testharness.sv
@@ -659,11 +659,8 @@ module ariane_testharness #(
   ariane_axi::resp_t   axi_ariane_resp;
 
   ariane #(
-    .AxiIdWidth    ( ariane_soc::IdWidth                             ),
-    .SwapEndianess ( 0                                               ),
-    .CachedAddrBeg ( ariane_soc::DRAMBase                            ),
-    .CachedAddrEnd ( (ariane_soc::DRAMBase + ariane_soc::DRAMLength) ),
-    .DmBaseAddress ( ariane_soc::DebugBase                           )
+    .AxiIdWidth ( ariane_soc::IdWidth      ),
+    .ArianeCfg  ( ariane_soc::ArianeSocCfg )
   ) i_ariane (
     .clk_i                ( clk_i               ),
     .rst_ni               ( ndmreset_n          ),
diff --git a/tb/tb_wt_dcache/hdl/tb.sv b/tb/tb_wt_dcache/hdl/tb.sv
index 310814476ffe6fb981b385eae1a52f2021e16543..3b817bf9976f40d5a2afe9cdb888a108224784cd 100644
--- a/tb/tb_wt_dcache/hdl/tb.sv
+++ b/tb/tb_wt_dcache/hdl/tb.sv
@@ -40,6 +40,26 @@ module tb;
   parameter logic [63:0] CachedAddrBeg = MemBytes>>3;//1/8th of the memory is NC
   parameter logic [63:0] CachedAddrEnd = 64'hFFFF_FFFF_FFFF_FFFF;
 
+  localparam ariane_cfg_t ArianeDefaultConfig = '{
+    // idempotent region
+    NrNonIdempotentRules:  0,
+    NonIdempotentAddrBase: {64'b0},
+    NonIdempotentLength:   {64'b0},
+    // executable region
+    NrExecuteRegionRules:  0,
+    ExecuteRegionAddrBase: {64'h0},
+    ExecuteRegionLength:   {64'h0},
+    // cached region
+    NrCachedRegionRules:   1,
+    CachedRegionAddrBase:  {CachedAddrBeg},//1/8th of the memory is NC
+    CachedRegionLength:    {CachedAddrEnd-CachedAddrBeg+64'b1},
+    // cache config
+    Axi64BitCompliant:     1'b1,
+    SwapEndianess:         1'b0,
+    // debug
+    DmBaseAddress:         64'h0
+  };
+
   // contention and invalidation rates (in %)
   parameter MemRandHitRate   = 75;
   parameter MemRandInvRate   = 10;
@@ -204,9 +224,7 @@ module tb;
 ///////////////////////////////////////////////////////////////////////////////
 
   wt_dcache  #(
-    .CachedAddrBeg     ( CachedAddrBeg ),
-    .CachedAddrEnd     ( CachedAddrEnd ),
-    .Axi64BitCompliant ( 1'b1          )
+    .ArianeCfg ( ArianeDefaultConfig )
   ) i_dut (
     .clk_i           ( clk_i           ),
     .rst_ni          ( rst_ni          ),
diff --git a/tb/tb_wt_icache/hdl/tb.sv b/tb/tb_wt_icache/hdl/tb.sv
index 7f7c4485b907379701c84782bd01cb5106ce490a..0a6b62ec77091f9a9c4a73741d464aac88f04f0a 100644
--- a/tb/tb_wt_icache/hdl/tb.sv
+++ b/tb/tb_wt_icache/hdl/tb.sv
@@ -39,6 +39,26 @@ module tb;
   parameter logic [63:0] CachedAddrBeg = MemBytes/4;
   parameter logic [63:0] CachedAddrEnd = 64'hFFFF_FFFF_FFFF_FFFF;
 
+  localparam ariane_cfg_t Cfg = '{
+    // idempotent region
+    NrNonIdempotentRules: 0,
+    NonIdempotentAddrBase: {64'b0},
+    NonIdempotentLength:   {64'b0},
+    // executable region
+    NrExecuteRegionRules: 0,
+    ExecuteRegionAddrBase: {64'h0},
+    ExecuteRegionLength:   {64'h0},
+    // cached region
+    NrCachedRegionRules:  1,
+    CachedRegionAddrBase: {CachedAddrBeg},
+    CachedRegionLength:   {CachedAddrEnd-CachedAddrBeg+64'b1},
+    // cache config
+    Axi64BitCompliant:     1'b0,
+    SwapEndianess:         1'b0,
+    // debug
+    DmBaseAddress:         64'h0
+  };
+
   // rates are in percent
   parameter TlbRandHitRate   = 50;
   parameter MemRandHitRate   = 50;
@@ -240,8 +260,7 @@ module tb;
 ///////////////////////////////////////////////////////////////////////////////
 
   wt_icache  #(
-    .CachedAddrBeg(CachedAddrBeg),
-    .CachedAddrEnd(CachedAddrEnd)
+    .ArianeCfg(Cfg)
     ) dut (
     .clk_i          ( clk_i          ),
     .rst_ni         ( rst_ni         ),