diff --git a/bench/bsp/config/fpga_platform_config.h b/bench/bsp/config/fpga_platform_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0bd0d49ffafaf06db0cbb1b3752f65c5c3ec297
--- /dev/null
+++ b/bench/bsp/config/fpga_platform_config.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2020 Thales.
+// 
+// Copyright and related rights are licensed under the Apache
+// License, Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// https://www.apache.org/licenses/LICENSE-2.0. 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:         Sebastien Jacq - sjthales on github.com
+//
+// Additional contributions by:
+//
+//
+// file Name:      CVA6 FPGA configurtion
+// Project Name:   CVA6 softcore
+// Language:       C header
+//
+// Description:    File which defines the FPGA platform, i.e base address for each 
+//                 peripheral and others information relating to FPAG platform.
+//
+// =========================================================================== #
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       Created
+// =========================================================================== #
+
+#ifndef __FPGA_PLATFORM_CONFIG_H
+#define __FPGA_PLATFORM_CONFIG_H
+
+
+/***************************************************************************//**
+ * Platform frequency
+ */
+
+#define FPGA_UART_0_FREQUENCY 25000000
+
+
+/***************************************************************************//**
+ * Peripheral base address
+ */
+#define FPGA_UART_0_BASE 0x10000000
+
+
+
+#endif /* FPGA_PLATFORM_CONFIG */
diff --git a/bench/bsp/config/link.ld b/bench/bsp/config/link.ld
new file mode 100644
index 0000000000000000000000000000000000000000..5856d17abf1e072ae64c013ed2128624d7470310
--- /dev/null
+++ b/bench/bsp/config/link.ld
@@ -0,0 +1,320 @@
+/* Copyright (c) 2020 Thales.
+   Copyright (C) 2014-2020 Free Software Foundation, Inc.
+   Copyright (C) 2019 ETH Zürich and University of Bologna
+   Copyright (C) 2020 OpenHW Group
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+/* This linker script is adapted from the default linker script for upstream
+   RISC-V GCC.  It has been modified for use in verification of CORE-V cores.
+*/
+/* Additional contributions by:
+           Sebastien Jacq - sjthales on github.com
+
+   Description: linkerscript for the CV32A6 platform
+
+   =========================================================================== 
+   Revisions  :
+   Date        Version  Author       Description
+   2020-10-06  0.1      S.Jacq       modification of the Test for CV32A6 softcore
+   =========================================================================== */
+
+OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
+	      "elf32-littleriscv")
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+
+/* CORE-V */
+MEMORY
+{
+	/* Our testbench is a bit weird in that we initialize the RAM (thus
+	   allowing initialized sections to be placed there). Infact we dump all
+	   sections to ram. */
+
+	ram (rwxai) : ORIGIN = 0x80000000, LENGTH = 0x20000
+	dbg (rwxai) : ORIGIN = 0x1A110800, LENGTH = 0x1000
+}
+
+SECTIONS
+{
+  /* CORE-V Debugger Code: This section address must be the same as the
+     DM_HaltAddress parameter in the RTL */
+  .debugger (ORIGIN(dbg)):
+  {
+    KEEP(*(.debugger));
+  } >dbg
+  .debugger_exception (0x1A111000):
+  {
+    KEEP(*(.debugger_exception));
+  } >dbg
+  /* Debugger Stack*/
+  .debugger_stack         : ALIGN(16)
+  {
+   PROVIDE(__debugger_stack_start = .);
+   . = 0x80;
+  } >dbg
+
+  /* CORE-V: we want a fixed entry point */
+  PROVIDE(__boot_address = 0x80000080);
+
+  /* CORE-V: interrupt vectors */
+  .vectors (ORIGIN(ram)):
+  {
+    PROVIDE(__vector_start = .);
+    KEEP(*(.vectors));
+  } >ram
+
+  /* CORE-V: crt0 init code */
+  .init (__boot_address):
+  {
+    KEEP (*(SORT_NONE(.init)))
+    KEEP (*(.text.start))
+  } >ram
+
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x10000)); . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) } >ram
+  .note.gnu.build-id  : { *(.note.gnu.build-id) } >ram
+  .hash           : { *(.hash) } >ram
+  .gnu.hash       : { *(.gnu.hash) } >ram
+  .dynsym         : { *(.dynsym) } >ram
+  .dynstr         : { *(.dynstr) } >ram
+  .gnu.version    : { *(.gnu.version) } >ram
+  .gnu.version_d  : { *(.gnu.version_d) } >ram
+  .gnu.version_r  : { *(.gnu.version_r) } >ram
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+      *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+      *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+      *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    } >ram
+  .rela.plt       :
+    {
+      *(.rela.plt)
+    } >ram
+
+  .plt            : { *(.plt) }
+  .iplt           : { *(.iplt) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+    *(SORT(.text.sorted.*))
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf.em.  */
+    *(.gnu.warning)
+  } >ram
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  } >ram
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) } >ram
+  .rodata1        : { *(.rodata1) } >ram
+  .sdata2         :
+  {
+    *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+  } >ram
+  .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } >ram
+  .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } >ram
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >ram
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >ram
+  .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) } >ram
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >ram
+  .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) } >ram
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >ram
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) } >ram
+  /* Thread Local Storage sections  */
+  .tdata	  :
+   {
+     PROVIDE_HIDDEN (__tdata_start = .);
+     *(.tdata .tdata.* .gnu.linkonce.td.*)
+   } >ram
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } >ram
+  .preinit_array    :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  } >ram
+  .init_array    :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  } >ram
+  .fini_array    :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  } >ram
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  } >ram
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  } >ram
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  . = DATA_SEGMENT_RELRO_END (0, .);
+  .data           :
+  {
+    __DATA_BEGIN__ = .;
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  } >ram
+  .data1          : { *(.data1) } >ram
+  .got            : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata          :
+  {
+    __SDATA_BEGIN__ = .;
+    *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+  } >ram
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+  __bss_start = .;
+  .sbss           :
+  {
+    *(.dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+  } >ram
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we do not
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 32 / 8 : 1);
+  } >ram
+  . = ALIGN(32 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  . = ALIGN(32 / 8);
+  __bss_end = .;
+    __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
+		            MAX(__DATA_BEGIN__ + 0x800, __bss_end - 0x800));
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+
+  /* Heap grows upward towards end of ram */
+  .heap                    : ALIGN(16)
+  {
+   PROVIDE(__heap_start = .);
+   /* If end of ram is not 16-byte aligned, align to previous 16-byte
+      boundary */
+   PROVIDE(__heap_end = ALIGN(ORIGIN(ram) + LENGTH(ram) - __heap_start - 15, 16));
+   . = __heap_end;
+  } >ram
+
+  /* Stack grows downward from end of ram */
+  .stack (__heap_start)    : ALIGN(16) /* this is a requirement of the ABI(?) */
+  {
+   PROVIDE(__stack_start = __heap_start);
+   . = __heap_end;
+   PROVIDE(__stack_end = .);
+  } >ram
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .debug_addr     0 : { *(.debug_addr) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/bench/bsp/drivers/uart/uart.c b/bench/bsp/drivers/uart/uart.c
new file mode 100644
index 0000000000000000000000000000000000000000..09421f4f12c4e8931858a898687dd9e7cbfd6558
--- /dev/null
+++ b/bench/bsp/drivers/uart/uart.c
@@ -0,0 +1,834 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Thales.
+ * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+// Additional contributions by:
+//         Sebastien Jacq - sjthales on github.com
+//
+// Description: Driver for UART Ip of the CVA6 platform
+//
+// =========================================================================== //
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       modification of the Test for CVA6 softcore
+// =========================================================================== //
+
+
+
+#include "uart.h"
+
+#include "plic.h"
+#include "fpga_platform_config.h"
+
+
+/*******************************************************************************
+ * Defines
+ */
+#define TX_COMPLETE                     0u
+#define TX_FIFO_SIZE                    16u
+
+#define FCR_TRIG_LEVEL_MASK             0xC0u
+
+#define IIRF_MASK                       0x0Fu
+
+#define INVALID_INTERRUPT               0u
+#define INVALID_IRQ_HANDLER             ((uart_irq_handler_t) 0)
+#define NULL_HANDLER                    ((uart_irq_handler_t) 0)
+
+#define UART_DATA_READY             ((uint8_t) 0x01)
+
+
+/*******************************************************************************
+ * Possible values for Interrupt Identification Register Field.
+ */
+#define IIRF_MODEM_STATUS               0x00u
+#define IIRF_THRE                       0x02u
+//#define IIRF_MMI                        0x03u
+#define IIRF_RX_DATA                    0x04u
+#define IIRF_RX_LINE_STATUS             0x06u
+#define IIRF_DATA_TIMEOUT               0x0Cu
+
+
+uart_instance_t g_uart_0 = { .hw_reg = FPGA_UART_0_BASE };
+
+/*******************************************************************************
+ * Global initialization for all modes
+ */
+static void global_init
+(
+    uart_instance_t * this_uart,
+    uint32_t baud_rate,
+    uint8_t line_config
+)
+{
+    
+    /* disable interrupts */
+    this_uart->hw_reg->IER = 0u;
+
+    /* FIFO configuration */
+    this_uart->hw_reg->FCR = 0u;
+
+    /* clear receiver FIFO */
+    this_uart->hw_reg->FCR = FIFO_RX_TRIGGER_LEVEL_14_MASK | CLEAR_RX_FIFO_MASK | CLEAR_TX_FIFO_MASK | RXRDY_TXRDYN_EN_MASK;
+
+    /* clear transmitter FIFO */
+    //this_uart->hw_reg->FCR |= CLEAR_TX_FIFO_MASK;
+
+    /* set default READY mode : Mode 0*/
+    /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO
+     * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */
+   // this_uart->hw_reg->FCR |= RXRDY_TXRDYN_EN_MASK;
+
+    this_uart->hw_reg->MCR = 0u;
+
+
+    
+    /* 
+     * Configure baud rate divisors. This uses the fractional baud rate divisor
+     * where possible to provide the most accurate baud rat possible.
+     */
+    config_baud_divisors(this_uart, baud_rate);
+
+    /* set the line control register (bit length, stop bits, parity) */
+    this_uart->hw_reg->LCR = line_config;
+
+    /* Instance setup */
+    this_uart->baudrate = baud_rate;
+    this_uart->lineconfig = line_config;
+    this_uart->tx_buff_size = TX_COMPLETE;
+    this_uart->tx_buffer = (const uint8_t*)0;
+    this_uart->tx_idx = 0u;
+
+    /* Default handlers for MSS UART interrupts */
+    this_uart->rx_handler       = NULL_HANDLER;
+    this_uart->tx_handler       = NULL_HANDLER;
+    this_uart->linests_handler  = NULL_HANDLER;
+    this_uart->modemsts_handler = NULL_HANDLER;
+
+    /* Initialize the sticky status */
+    this_uart->status = 0u;
+}
+
+/*******************************************************************************
+ * Public Functions
+ *******************************************************************************/
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void 
+UART_init
+(
+    uart_instance_t* this_uart, 
+    uint32_t baud_rate,
+    uint8_t line_config
+)
+{
+    /* Perform generic initialization */
+    global_init(this_uart, baud_rate, line_config);
+
+
+    /* set default tx handler for automated TX using interrupt in USART mode */
+    this_uart->tx_handler = default_tx_handler;
+}
+
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_polled_tx
+(
+    uart_instance_t * this_uart,
+    const uint8_t * pbuff,
+    uint32_t tx_size
+)
+{
+    uint32_t char_idx = 0u;
+   // uint32_t size_sent;
+    uint8_t status;
+    //uint32_t temp_tx_size = tx_size;
+
+    //ASSERT(pbuff != ( (uint8_t*)0));
+    //ASSERT(tx_size > 0u);
+
+    if ((pbuff != ((uint8_t*)0)) && (tx_size > 0u))
+    {
+        /* Remain in this loop until the entire input buffer
+         * has been transferred to the UART.
+         */
+        do
+        {
+            /* Wait until TX FIFO is empty. */
+            do
+            {
+                status = this_uart->hw_reg->LSR;
+               // this_uart->status |= status;
+            }while (0u == (status & UART_THRE));
+
+
+            /* Check if TX FIFO is empty. */
+           // if (status & UART_THRE)
+            //{
+               // uint32_t fill_size = TX_FIFO_SIZE;
+
+                /* Calculate the number of bytes to transmit. */
+                //if (temp_tx_size < TX_FIFO_SIZE)
+                //{
+                //    fill_size = temp_tx_size;
+                //}
+
+                /* Fill the TX FIFO with the calculated the number of bytes. */
+                //for (size_sent = 0u; size_sent < fill_size; ++size_sent)
+                //{
+                    /* Send next character in the buffer. */
+                    this_uart->hw_reg->THR = pbuff[char_idx];
+                    char_idx++;
+                //}
+
+                /* Calculate the number of bytes remaining(not transmitted yet)*/
+                //temp_tx_size -= size_sent;
+            //}
+        }while (char_idx < tx_size);
+    }
+}
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_polled_tx_string
+(
+    uart_instance_t * this_uart,
+    const uint8_t * p_sz_string
+)
+{
+    uint32_t char_idx = 0u;
+    uint32_t fill_size;
+    uint8_t data_byte;
+    volatile uint8_t status;
+
+    //ASSERT(p_sz_string != ((uint8_t*)0));
+
+    if (p_sz_string != ((uint8_t*)0))
+    {
+        /* Get the first data byte from the input buffer */
+        data_byte = p_sz_string[char_idx];
+
+        /* First check for the NULL terminator byte.
+         * Then remain in this loop until the entire string in the input buffer
+         * has been transferred to the UART.
+         */
+        while (0u != data_byte)
+        {
+            /* Wait until TX FIFO is empty. */
+            do
+            {
+                status = this_uart->hw_reg->LSR;
+               // this_uart->status |= status;
+            }while (0u == (status & UART_THRE));
+
+		
+            /* Send bytes from the input buffer until the TX FIFO is full
+             * or we reach the NULL terminator byte.
+             */
+            //fill_size = 0u;
+
+           // while ((0u != data_byte) && (fill_size < TX_FIFO_SIZE))
+            //{
+                /* Send the data byte */
+                this_uart->hw_reg->THR = data_byte;
+                //++fill_size;
+                char_idx++;
+                /* Get the next data byte from the input buffer */
+                data_byte = p_sz_string[char_idx];
+            //}
+        }
+    }
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_irq_tx
+(
+    uart_instance_t * this_uart,
+    const uint8_t * pbuff,
+    uint32_t tx_size
+)
+{
+    //ASSERT(pbuff != ((uint8_t*)0));
+    //ASSERT(tx_size > 0u);
+
+    if ((tx_size > 0u) && (pbuff != ((uint8_t*)0)))
+    {
+        /*Initialize the transmit info for the UART instance with the arguments*/
+        this_uart->tx_buffer = pbuff;
+        this_uart->tx_buff_size = tx_size;
+        this_uart->tx_idx = 0u;
+
+        /* assign default handler for data transfer */
+        this_uart->tx_handler = default_tx_handler;
+
+        /* enables TX interrupt */
+        this_uart->hw_reg->IER |= ETBEI_MASK;
+        enable_irq(this_uart);
+    }
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+int8_t
+UART_tx_complete
+(
+    uart_instance_t * this_uart
+)
+{
+    int8_t ret_value = 0;
+    uint8_t status = 0u;
+
+    /* Read the Line Status Register and update the sticky record. */
+    status = this_uart->hw_reg->LSR;
+    this_uart->status |= status;
+
+    if ((TX_COMPLETE == this_uart->tx_buff_size) &&
+       ((status & UART_TEMT) != 0u))
+    {
+        ret_value = (int8_t)1;
+    }
+
+    return ret_value;
+}
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+size_t
+UART_get_rx
+(
+    uart_instance_t * this_uart,
+    uint8_t * rx_buff,
+    size_t buff_size
+)
+{
+    size_t rx_size = 0u;
+    uint8_t status = 0u;
+
+    //ASSERT(rx_buff != ((uint8_t*)0));
+    //ASSERT(buff_size > 0u);
+
+    if ((rx_buff != (uint8_t*)0) && (buff_size > 0u))
+    {
+        status = this_uart->hw_reg->LSR;
+        this_uart->status |= status;
+
+        while (((status & UART_DATA_READY) != 0u) && (rx_size < buff_size))
+        {
+            rx_buff[rx_size] = this_uart->hw_reg->RBR;
+            ++rx_size;
+            status = this_uart->hw_reg->LSR;
+            this_uart->status |= status;
+        }
+    }
+
+    return rx_size;
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_enable_irq
+(
+    uart_instance_t * this_uart,
+    uart_irq_t irq_mask
+)
+{
+    //ASSERT(UART_INVALID_IRQ > irq_mask);
+
+    enable_irq(this_uart);
+
+    if (UART_INVALID_IRQ > irq_mask)
+    {
+        /* irq_mask encoding: 1- enable
+         * bit 0 - Receive Data Available Interrupt
+         * bit 1 - Transmitter Holding  Register Empty Interrupt
+         * bit 2 - Receiver Line Status Interrupt
+         * bit 3 - Modem Status Interrupt
+         */
+        this_uart->hw_reg->IER |= ((uint8_t)(((uint32_t)irq_mask &
+                                                            (uint32_t)IIRF_MASK)));
+
+    }
+}
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_set_rx_handler
+(
+    uart_instance_t *       this_uart,
+    uart_irq_handler_t      handler,
+    uart_rx_trig_level_t    trigger_level
+)
+{
+    //ASSERT(handler != INVALID_IRQ_HANDLER );
+    //ASSERT(trigger_level < UART_FIFO_INVALID_TRIG_LEVEL);
+
+    if ((handler != INVALID_IRQ_HANDLER) &&
+       (trigger_level < UART_FIFO_INVALID_TRIG_LEVEL))
+    {
+        this_uart->rx_handler = handler;
+
+        /* Set the receive interrupt trigger level. */
+        this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR &
+                                 (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) |
+                                 (uint8_t)trigger_level;
+
+        /* Enable receive interrupt. */
+        this_uart->hw_reg->IER |= ERBFI_MASK;
+
+        enable_irq(this_uart);
+    }
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_set_tx_handler
+(
+    uart_instance_t * this_uart,
+    uart_irq_handler_t handler
+)
+{
+    //ASSERT(handler != INVALID_IRQ_HANDLER);
+
+    if (handler != INVALID_IRQ_HANDLER)
+    {
+        this_uart->tx_handler = handler;
+
+        /* Make TX buffer info invalid */
+        this_uart->tx_buffer = (const uint8_t*)0;
+        this_uart->tx_buff_size = 0u;
+
+        /* Enable transmitter holding register Empty interrupt. */
+        this_uart->hw_reg->IER |= ETBEI_MASK;
+        enable_irq(this_uart);
+    }
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_set_modemstatus_handler
+(
+    uart_instance_t * this_uart,
+    uart_irq_handler_t handler
+)
+{
+    //ASSERT(handler != INVALID_IRQ_HANDLER);
+
+    if (handler != INVALID_IRQ_HANDLER)
+    {
+        this_uart->modemsts_handler = handler;
+
+        /* Enable modem status interrupt. */
+        this_uart->hw_reg->IER |= EDSSI_MASK;
+        enable_irq(this_uart);
+    }
+}
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+size_t
+UART_fill_tx_fifo
+(
+    uart_instance_t * this_uart,
+    const uint8_t * tx_buffer,
+    size_t tx_size
+)
+{
+    uint8_t status = 0u;
+    uint32_t size_sent = 0u;
+
+    //ASSERT(tx_buffer != ( (uint8_t*)0));
+    //ASSERT(tx_size > 0);
+
+    /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
+     * buffer has been written. */
+    if ((tx_buffer != ((uint8_t*)0)) && (tx_size > 0u))
+    {
+        status = this_uart->hw_reg->LSR;
+        this_uart->status |= status;
+
+        if (status & UART_THRE)
+        {
+            uint32_t fill_size = TX_FIFO_SIZE;
+
+            if (tx_size < TX_FIFO_SIZE)
+            {
+                fill_size = tx_size;
+            }
+
+            /* Fill up FIFO */
+            for (size_sent = 0u; size_sent < fill_size; size_sent++)
+            {
+                /* Send next character in the buffer. */
+                this_uart->hw_reg->THR = tx_buffer[size_sent];
+            }
+        }
+    }
+
+    return size_sent;
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+uint8_t
+UART_get_rx_status
+(
+    uart_instance_t * this_uart
+)
+{
+    uint8_t status = UART_INVALID_PARAM;
+
+    /*
+     * Extract UART receive error status.
+     * Bit 1 - Overflow error status
+     * Bit 2 - Parity error status
+     * Bit 3 - Frame error status
+     * Bit 4 - Break interrupt indicator
+     * Bit 7 - FIFO data error status
+     */
+    this_uart->status |= (this_uart->hw_reg->LSR);
+    status = (this_uart->status & STATUS_ERROR_MASK);
+    /* Clear the sticky status after reading */
+    this_uart->status = 0u;
+
+    return status;
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+uint8_t
+UART_get_modem_status
+(
+    const uart_instance_t * this_uart
+)
+{
+    uint8_t status = UART_INVALID_PARAM;
+
+    /*
+     * Extract UART modem status and place in lower bits of "status".
+     * Bit 0 - Delta Clear to Send Indicator
+     * Bit 1 - Delta Clear to Receive Indicator
+     * Bit 2 - Trailing edge of Ring Indicator detector
+     * Bit 3 - Delta Data Carrier Detect indicator
+     * Bit 4 - Clear To Send
+     * Bit 5 - Data Set Ready
+     * Bit 6 - Ring Indicator
+     * Bit 7 - Data Carrier Detect
+     */
+    status = this_uart->hw_reg->MSR;
+
+    return status;
+}
+
+
+/***************************************************************************//**
+ * UART_get_tx_status.
+ * See uart.h for details of how to use this function.
+ */
+uint8_t
+UART_get_tx_status
+(
+    uart_instance_t * this_uart
+)
+{
+    uint8_t status = UART_TX_BUSY;
+
+    /* Read the Line Status Register and update the sticky record. */
+    status = this_uart->hw_reg->LSR;
+    this_uart->status |= status;
+    
+    /*
+     * Extract the transmit status bits from the UART's Line Status Register.
+     * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. 
+               (If = 1, TX FIFO is empty)
+     * Bit 6 - Transmitter Empty (TEMT) status. 
+               (If = 1, both TX FIFO and shift register are empty)
+     */
+    status &= (UART_THRE | UART_TEMT);
+
+    return status;
+}
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_set_break
+(
+    uart_instance_t * this_uart
+)
+{
+    /* set break character on Tx line */
+    this_uart->hw_reg->LCR |= SB_MASK;
+}
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+void
+UART_clear_break
+(
+    uart_instance_t * this_uart
+)
+{
+    /* remove break character from Tx line */
+    this_uart->hw_reg->LCR &= ~SB_MASK;
+}
+
+/***************************************************************************//**
+ * Configure baud divisors using fractional baud rate if possible.
+ */
+static void
+config_baud_divisors
+(
+    uart_instance_t * this_uart,
+    uint32_t baudrate
+)
+{
+    uint32_t baud_value;
+    uint32_t baud_value_by_64;
+    uint32_t baud_value_by_128;
+//    uint32_t fractional_baud_value;
+    uint64_t pclk_freq;
+
+    this_uart->baudrate = baudrate;
+
+    /* Use the system clock value from hw_platform.h */
+    pclk_freq = FPGA_UART_0_FREQUENCY;
+
+    /*
+     * Compute baud value based on requested baud rate and PCLK frequency.
+     * The baud value is computed using the following equation:
+     *      baud_value = PCLK_Frequency / (baud_rate * 16)
+     */
+    baud_value_by_128 = (uint32_t)((8UL * pclk_freq) / baudrate);
+    baud_value_by_64 = baud_value_by_128 / 2u;
+    baud_value = baud_value_by_64 / 64u;
+//    fractional_baud_value = baud_value_by_64 - (baud_value * 64u);
+//    fractional_baud_value += (baud_value_by_128 - (baud_value * 128u))
+ //                            - (fractional_baud_value * 2u);
+
+    /* //ASSERT if integer baud value fits in 16-bit. */
+    //ASSERT(baud_value <= UINT16_MAX);
+
+    if (baud_value <= (uint32_t)UINT16_MAX)
+    {
+        
+        /*
+        * Use Fractional baud rate divisors
+        */
+        /* set divisor latch */
+        this_uart->hw_reg->LCR = DLAB_MASK;
+
+        /* msb of baud value */
+        this_uart->hw_reg->DLM = (uint8_t)(baud_value >> 8);
+        /* lsb of baud value */
+        this_uart->hw_reg->DLL = (uint8_t)baud_value;
+
+        /* reset divisor latch */
+        this_uart->hw_reg->LCR = 0;
+	    }
+}
+
+/***************************************************************************//**
+ * Interrupt service routine triggered by any MSS UART interrupt. This routine
+ * will call the handler function appropriate to the interrupt from the
+ * handlers previously registered with the driver through calls to the
+ * UART_set_*_handler() functions, or it will call the default_tx_handler()
+ * function in response to transmit interrupts if UART_irq_tx() is used to
+ * transmit data.
+ */
+static void
+uart_isr
+(
+    uart_instance_t * this_uart
+)
+{
+    uint8_t iirf;
+
+    iirf = this_uart->hw_reg->IIR & IIRF_MASK;
+
+    switch (iirf)
+    {
+        case IIRF_MODEM_STATUS:  /* Modem status interrupt */
+        {
+            //ASSERT(NULL_HANDLER != this_uart->modemsts_handler);
+            if (NULL_HANDLER != this_uart->modemsts_handler)
+            {
+               (*(this_uart->modemsts_handler))(this_uart);
+            }
+        }
+        break;
+
+        case IIRF_THRE: /* Transmitter Holding Register Empty */
+        {
+            //ASSERT(NULL_HANDLER != this_uart->tx_handler);
+            if (NULL_HANDLER != this_uart->tx_handler)
+            {
+                (*(this_uart->tx_handler))(this_uart);
+            }
+        }
+        break;
+
+        case IIRF_RX_DATA:      /* Received Data Available */
+        case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */
+        {
+            //ASSERT(NULL_HANDLER != this_uart->rx_handler);
+            if (NULL_HANDLER != this_uart->rx_handler)
+            {
+                (*(this_uart->rx_handler))(this_uart);
+            }
+        }
+        break;
+
+        case IIRF_RX_LINE_STATUS:  /* Line Status Interrupt */
+        {
+            //ASSERT(NULL_HANDLER != this_uart->linests_handler);
+            if (NULL_HANDLER != this_uart->linests_handler)
+            {
+               (*(this_uart->linests_handler))(this_uart);
+            }
+        }
+        
+        default:
+        {
+            //ASSERT(INVALID_INTERRUPT); /*Alternative case has been considered*/
+        }
+        break;
+    }
+}
+
+
+
+/***************************************************************************//**
+ * See uart.h for details of how to use this function.
+ */
+static void
+default_tx_handler
+(
+    uart_instance_t * this_uart
+)
+{
+    uint8_t status;
+
+    //ASSERT(( (uint8_t*)0 ) != this_uart->tx_buffer);
+    //ASSERT(0u < this_uart->tx_buff_size);
+
+    if ((((uint8_t*)0 ) != this_uart->tx_buffer) &&
+       (0u < this_uart->tx_buff_size))
+    {
+        /* Read the Line Status Register and update the sticky record. */
+        status = this_uart->hw_reg->LSR;
+        this_uart->status |= status;
+
+        /*
+         * This function should only be called as a result of a THRE interrupt.
+         * Verify that this is true before proceeding to transmit data.
+         */
+        if (status & UART_THRE)
+        {
+            uint32_t cnt;
+            uint32_t fill_size = TX_FIFO_SIZE;
+            uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
+
+            /* Calculate the number of bytes to transmit. */
+            if (tx_remain < TX_FIFO_SIZE)
+            {
+                fill_size = tx_remain;
+            }
+
+            /* Fill the TX FIFO with the calculated the number of bytes. */
+            for (cnt = 0u; cnt < fill_size; ++cnt)
+            {
+                /* Send next character in the buffer. */
+                this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
+                ++this_uart->tx_idx;
+            }
+        }
+
+        /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */
+        if (this_uart->tx_idx == this_uart->tx_buff_size)
+        {
+            this_uart->tx_buff_size = TX_COMPLETE;
+
+            /* disables TX interrupt */
+            this_uart->hw_reg->IER &= ~ETBEI_MASK;
+        }
+    }
+}
+
+
+static void
+enable_irq
+(
+    const uart_instance_t * this_uart
+)
+{
+
+
+   PLIC_IRQn_Type plic_num = 0;
+
+    if (&g_uart_0 == this_uart )
+    {
+        plic_num = UART_0_PLIC_IRQHandler;
+    }
+    else
+    {
+        ASSERT(0); /*Alternative case has been considered*/
+    }
+
+    /* Enable UART instance interrupt in PLIC. */
+    PLIC_EnableIRQ(plic_num);
+}
+
+static void
+disable_irq
+(
+    const uart_instance_t * this_uart
+)
+{
+    PLIC_IRQn_Type plic_num = 0;
+
+    if (&g_uart_0 == this_uart )
+    {
+        plic_num = UART_0_PLIC_IRQHandler;
+    }
+    else
+    {
+        ASSERT(0); /*Alternative case has been considered*/
+    }
+
+    /* Disable UART instance interrupt in PLIC. */
+    PLIC_DisableIRQ(plic_num);
+}
+
diff --git a/bench/bsp/drivers/uart/uart.h b/bench/bsp/drivers/uart/uart.h
new file mode 100644
index 0000000000000000000000000000000000000000..433d0653a67880febe245d00e34e9cb9bf5afd2e
--- /dev/null
+++ b/bench/bsp/drivers/uart/uart.h
@@ -0,0 +1,935 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Thales.
+ * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ *
+ */
+// Additional contributions by:
+//         Sebastien Jacq - sjthales on github.com
+//
+// Description: Driver header for UART Ip of the CVA6 platform
+//
+// =========================================================================== //
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       modification of the Test for CVA6 softcore
+// =========================================================================== //
+
+#ifndef __UART_H_
+#define __UART_H_ 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+
+
+/***************************************************************************//**
+  Baud rates
+  ==========
+  The following definitions are used to specify standard baud rates as a
+  parameter to the UART_init() function.
+  
+  | Constant             | Description      |
+  |----------------------|------------------|
+  | UART_110_BAUD    |    110 baud rate |
+  | UART_300_BAUD    |    300 baud rate |
+  | UART_600_BAUD    |    600 baud rate |
+  | UART_1200_BAUD   |   1200 baud rate |
+  | UART_2400_BAUD   |   2400 baud rate |
+  | UART_4800_BAUD   |   4800 baud rate |
+  | UART_9600_BAUD   |   9600 baud rate |
+  | UART_19200_BAUD  |  19200 baud rate |
+  | UART_38400_BAUD  |  38400 baud rate |
+  | UART_57600_BAUD  |  57600 baud rate |
+  | UART_115200_BAUD | 115200 baud rate |
+  | UART_230400_BAUD | 230400 baud rate |
+  | UART_460800_BAUD | 460800 baud rate |
+  | UART_921600_BAUD | 921600 baud rate |
+  
+ */
+#define UART_110_BAUD       110U
+#define UART_300_BAUD       300U
+#define UART_600_BAUD       600U
+#define UART_1200_BAUD      1200U
+#define UART_2400_BAUD      2400U
+#define UART_4800_BAUD      4800U
+#define UART_9600_BAUD      9600U
+#define UART_19200_BAUD     19200U
+#define UART_38400_BAUD     38400U
+#define UART_57600_BAUD     57600U
+#define UART_115200_BAUD    115200U
+#define UART_230400_BAUD    230400U
+#define UART_460800_BAUD    460800U
+#define UART_921600_BAUD    921600U
+
+/***************************************************************************//**
+  Data Bits Length
+  ================
+  The following defines are used to build the value of the UART_init()
+  function line_config parameter.
+  
+  | Constant             | Description                |
+  |----------------------|----------------------------|
+  | UART_DATA_5_BITS | 5 bits of data transmitted |
+  | UART_DATA_6_BITS | 6 bits of data transmitted |
+  | UART_DATA_7_BITS | 7 bits of data transmitted |
+  | UART_DATA_8_BITS | 8 bits of data transmitted |
+  
+ */
+#define UART_DATA_5_BITS     ((uint8_t) 0x00)
+#define UART_DATA_6_BITS     ((uint8_t) 0x01)
+#define UART_DATA_7_BITS     ((uint8_t) 0x02)
+#define UART_DATA_8_BITS     ((uint8_t) 0x03)
+
+/***************************************************************************//**
+  Parity
+  ======
+  The following defines are used to build the value of the UART_init()
+  function line_config parameter.
+  
+  | Constant                | Description              |
+  |-------------------------|--------------------------|
+  | UART_NO_PARITY      | No parity                |
+  | UART_ODD_PARITY     | Odd Parity               |
+  | UART_EVEN_PARITY    | Even parity              |
+  | UART_STICK_PARITY_0 | Stick parity bit to zero |
+  | UART_STICK_PARITY_1 | Stick parity bit to one  |
+ */
+#define UART_NO_PARITY           ((uint8_t) 0x00)
+#define UART_ODD_PARITY          ((uint8_t) 0x08)
+#define UART_EVEN_PARITY         ((uint8_t) 0x18)
+#define UART_STICK_PARITY_0      ((uint8_t) 0x38)
+#define UART_STICK_PARITY_1      ((uint8_t) 0x28)
+
+/***************************************************************************//**
+  Number of Stop Bits
+  ===================
+  The following defines are used to build the value of the UART_init()
+  function line_config parameter.
+  
+  | Constant                  | Description              |
+  |---------------------------|--------------------------|
+  | UART_ONE_STOP_BIT     | One stop bit             |
+  | UART_ONEHALF_STOP_BIT | One and a half stop bits |
+  | UART_TWO_STOP_BITS    | Two stop bits            |
+  
+ */
+#define UART_ONE_STOP_BIT        ((uint8_t) 0x00)
+#define UART_ONEHALF_STOP_BIT    ((uint8_t) 0x04)
+#define UART_TWO_STOP_BITS       ((uint8_t) 0x04)
+
+/***************************************************************************//**
+  Receiver Error Status
+  =====================
+  The following defines are used to determine the UART receiver error type.
+  These bit mask constants are used with the return value of the
+  UART_get_rx_status() function to find out if any errors occurred while
+  receiving data.
+  
+  
+  | Constant               | Description                                |
+  |------------------------|--------------------------------------------|
+  | UART_NO_ERROR      | No error bit mask (0x00)                   |
+  | UART_OVERUN_ERROR  | Overrun error bit mask (0x02)              |
+  | UART_PARITY_ERROR  | Parity error bit mask (0x04)               |
+  | UART_FRAMING_ERROR | Framing error bit mask (0x08)              |
+  | UART_BREAK_ERROR   | Break error bit mask (0x10)                |
+  | UART_FIFO_ERROR    | FIFO error bit mask (0x80)                 |
+  | UART_INVALID_PARAM | Invalid function parameter bit mask (0xFF) |
+ */
+#define UART_INVALID_PARAM    ((uint8_t)0xFF)
+#define UART_NO_ERROR         ((uint8_t)0x00 )
+#define UART_OVERUN_ERROR     ((uint8_t)0x02)
+#define UART_PARITY_ERROR     ((uint8_t)0x04)
+#define UART_FRAMING_ERROR    ((uint8_t)0x08)
+#define UART_BREAK_ERROR      ((uint8_t)0x10)
+#define UART_FIFO_ERROR       ((uint8_t)0x80)
+
+
+/*******************************************************************************
+ * Receiver error status mask.
+ */
+#define STATUS_ERROR_MASK    ( UART_OVERUN_ERROR   | UART_PARITY_ERROR | \
+                               UART_FRAMING_ERROR  | UART_BREAK_ERROR  | \
+                               UART_FIFO_ERROR)
+
+/***************************************************************************//**
+  Transmitter Status
+  ==================
+  The following definitions are used to determine the UART transmitter status.
+  These bit mask constants are used with the return value of the
+  UART_get_tx_status() function to find out the status of the transmitter.
+    
+  | Constant         | Description                                        |
+  |------------------|----------------------------------------------------|
+  | UART_TX_BUSY | Transmitter busy (0x00)                            |
+  | UART_THRE    | Transmitter holding register empty bit mask (0x20) |
+  | UART_TEMT    | Transmitter empty bit mask (0x40)                  |
+  
+ */
+#define UART_TX_BUSY          ((uint8_t) 0x00)
+#define UART_THRE             ((uint8_t) 0x20)
+#define UART_TEMT             ((uint8_t) 0x40)
+
+/***************************************************************************//**
+  Modem Status
+  ============
+  The following defines are used to determine the modem status. These bit
+  mask constants are used with the return value of the
+  UART_get_modem_status() function to find out the modem status of
+  the UART.
+  
+  | Constant      | Description                                     |
+  |---------------|-------------------------------------------------|
+  | UART_DCTS | Delta clear to send bit mask (0x01)             |
+  | UART_DDSR | Delta data set ready bit mask (0x02)            |
+  | UART_TERI | Trailing edge of ring indicator bit mask (0x04) |
+  | UART_DDCD | Delta data carrier detect bit mask (0x08)       |
+  | UART_CTS  | Clear to send bit mask (0x10)                   |
+  | UART_DSR  | Data set ready bit mask (0x20)                  |
+  | UART_RI   | Ring indicator bit mask (0x40)                  |
+  | UART_DCD  | Data carrier detect bit mask (0x80)             |
+ */
+#define UART_DCTS             ((uint8_t) 0x01)
+#define UART_DDSR             ((uint8_t) 0x02)
+#define UART_TERI             ((uint8_t) 0x04)
+#define UART_DDCD             ((uint8_t) 0x08)
+#define UART_CTS              ((uint8_t) 0x10)
+#define UART_DSR              ((uint8_t) 0x20)
+#define UART_RI               ((uint8_t) 0x40)
+#define UART_DCD              ((uint8_t) 0x80)
+
+/***************************************************************************//**
+  This typedef specifies the irq_mask parameter for the UART_enable_irq()
+  and UART_disable_irq() functions. The driver defines a set of bit masks
+  that are used to build the value of the irq_mask parameter. A bitwise OR of
+  these bit masks is used to enable or disable multipleUART interrupts.
+ */
+typedef uint16_t uart_irq_t;
+
+/***************************************************************************//**
+  UART Interrupts
+  =====================
+  The following defines specify the interrupt masks to enable and disable
+  UART interrupts. They are used to build the value of the irq_mask parameter
+  for the UART_enable_irq() and UART_disable_irq() functions. A bitwise
+  OR of these constants is used to enable or disable multiple interrupts.
+  
+  
+  | Constant           | Description                                                   |
+  |--------------------|---------------------------------------------------------------|
+  | UART_RBF_IRQ   | Receive Data Available Interrupt bit mask (0x001)             |
+  | UART_TBE_IRQ   | Transmitter Holding Register Empty interrupt bit mask (0x002) |
+  | UART_LS_IRQ    | Receiver Line Status interrupt bit mask (0x004)               |
+  | UART_MS_IRQ    | Modem Status interrupt bit mask (0x008)                       |
+
+ */
+#define UART_RBF_IRQ        0x001
+#define UART_TBE_IRQ        0x002
+#define UART_LS_IRQ         0x004
+#define UART_MS_IRQ         0x008
+//#define UART_RTO_IRQ        0x010
+//#define UART_NACK_IRQ       0x020
+//#define UART_PIDPE_IRQ      0x040
+//#define UART_LINB_IRQ       0x080
+//#define UART_LINS_IRQ       0x100
+#define UART_INVALID_IRQ    UINT16_MAX
+
+/***************************************************************************//**
+  This enumeration specifies the receiver FIFO trigger level. This is the number
+  of bytes that must be received before the UART generates a receive data
+  available interrupt. It provides the allowed values for the
+  UART_set_rx_handler() function trigger_level parameter.
+ */
+typedef enum {
+    UART_FIFO_SINGLE_BYTE    = 0x00,
+    UART_FIFO_FOUR_BYTES     = 0x40,
+    UART_FIFO_EIGHT_BYTES    = 0x80,
+    UART_FIFO_FOURTEEN_BYTES = 0xC0,
+    UART_FIFO_INVALID_TRIG_LEVEL
+
+} uart_rx_trig_level_t;
+
+
+
+
+/***************************************************************************//**
+  UART instance type.
+  This is type definition for UART instance. You need to create and
+  maintain a record of this type. This holds all data regarding the UART
+  instance
+ */
+typedef struct  uart_instance uart_instance_t;
+
+/***************************************************************************//**
+  Interrupt handler prototype.
+  This typedef specifies the function prototype for UART interrupt handlers.
+  All interrupt handlers registered with the UART driver must be of this type.
+  The interrupt handlers are registered with the driver through the
+  UART_set_rx_handler(), UART_set_tx_handler(),
+  UART_set_rxstatus_handler(), and UART_set_modemstatus_handler()
+  functions.
+  The this_uart parameter is a pointer to either g_uart0 or g_uart1 to
+  identify the UART to associate with the handler function.
+ */
+typedef void (*uart_irq_handler_t)( uart_instance_t * this_uart );
+
+
+/*******************************************************************************
+ Register Bit definitions
+ */
+
+/* Line Control register bit definitions */
+#define SB                          6u                  /* Set break */
+#define DLAB                        7u                  /* Divisor latch access bit */
+
+/* Line Control register bit masks */
+#define SB_MASK                     (0x01u << SB)        /* Set break */
+#define DLAB_MASK                   (0x01u << DLAB)      /* Divisor latch access bit */
+
+/* FIFO Control register bit definitions */
+#define ENABLE_FIFO                 0u                  /* Enable FIFO */
+#define CLEAR_RX_FIFO               1u                  /* Clear receiver FIFO */
+#define CLEAR_TX_FIFO               2u                  /* Clear transmitter FIFO */
+#define DMA_MODE                    3u                  /* DMA mode */
+#define FIFO64_ENABLE               5u                  /* FIFO64 enable */
+//#define RDYMODE                     3u                  /* Mode 0 or Mode 1 for TXRDY and RXRDY */
+#define FIFO_RX_TRIGGER             6u                  /* FIFO RX trigger */
+
+/* FIFO Control register bit MASKS */
+#define RXRDY_TXRDYN_EN_MASK           (0x01u << 0u)      /* Enable TXRDY and RXRDY signals */
+#define CLEAR_RX_FIFO_MASK             (0x01u << 1u)      /* Clear receiver FIFO */
+#define CLEAR_TX_FIFO_MASK             (0x01u << 2u)      /* Clear transmitter FIFO */
+#define DMA_MODE_MASK                  (0x01u << 3u)      /* DMA mode */
+#define FIFO64_ENABLE_MASK             (0x01u << 5u)      /* FIFO64 enable */
+//#define RDYMODE_MASK                 (0x01u << 3u)      /* Mode 0 or Mode 1 for TXRDY and RXRDY */
+
+#define FIFO_RX_TRIGGER_LEVEL_4_MASK   (0x01u << 6u)
+#define FIFO_RX_TRIGGER_LEVEL_8_MASK   (0x02u << 6u)
+#define FIFO_RX_TRIGGER_LEVEL_14_MASK   (0x03u << 6u)
+
+#define FIFO64_RX_TRIGGER_LEVEL_16_MASK   (0x01u << 6u)
+#define FIFO64_RX_TRIGGER_LEVEL_32_MASK   (0x02u << 6u)
+#define FIFO64_RX_TRIGGER_LEVEL_56_MASK   (0x03u << 6u)
+
+/* Modem Control register bit definitions */
+//#define LOOP                        4u                  /* Local loopback */
+//#define RLOOP                       5u                  /* Remote loopback */
+//#define ECHO                        6u                  /* Automatic echo */
+
+/* Modem Control register bit MASKS */
+//#define LOOP_MASK                   (0x01u << 4u)        /* Local loopback */
+//#define RLOOP_MASK                  (0x01u << 5u)        /* Remote loopback & Automatic echo*/
+//#define ECHO_MASK                   (0x01u << 6u)        /* Automatic echo */
+
+/* Line Status register bit definitions   */
+#define DR                          0u                  /* Data ready */
+#define THRE                        5u                  /* Transmitter holding register empty */
+#define TEMT                        6u                  /* Transmitter empty */
+
+/* Line Status register bit MASKS   */
+#define DR_MASK                     (0x01u << 0u)        /* Data ready */
+#define THRE_MASK                   (0x01u << 5u)        /* Transmitter holding register empty */
+#define TEMT_MASK                   (0x01u << 6u)        /* Transmitter empty */
+
+/* Interrupt Enable register bit definitions */
+#define ERBFI                       0u                  /* Enable receiver buffer full interrupt */
+#define ETBEI                       1u                  /* Enable transmitter buffer empty interrupt */
+#define ELSI                        2u                  /* Enable line status interrupt */
+#define EDSSI                       3u                  /* Enable modem status interrupt */
+
+/* Interrupt Enable register bit MASKS */
+#define ERBFI_MASK                  (0x01u << 0u)      /* Enable receiver buffer full interrupt */
+#define ETBEI_MASK                  (0x01u << 1u)      /* Enable transmitter buffer empty interrupt */
+#define ELSI_MASK                   (0x01u << 2u)      /* Enable line status interrupt */
+#define EDSSI_MASK                  (0x01u << 3u)      /* Enable modem status interrupt */
+
+/* Multimode register 0 bit definitions */
+#define ELIN                        3u                  /* Enable LIN header detection */
+#define ETTG                        5u                  /* Enable transmitter time guard */
+#define ERTO                        6u                  /* Enable receiver time-out */
+#define EFBR                        7u                  /* Enable fractional baud rate mode */
+
+/* Multimode register 0 bit MASKS */
+#define ELIN_MASK                   (0x01u << 3u)      /* Enable LIN header detection */
+#define ETTG_MASK                   (0x01u << 5u)      /* Enable transmitter time guard */
+#define ERTO_MASK                   (0x01u << 6u)      /* Enable receiver time-out */
+#define EFBR_MASK                   (0x01u << 7u)      /* Enable fractional baud rate mode */
+
+/* Multimode register 1 bit definitions */
+#define E_MSB_RX                    0u                  /* MSB / LSB first for receiver */
+#define E_MSB_TX                    1u                  /* MSB / LSB first for transmitter */
+#define EIRD                        2u                  /* Enable IrDA modem */
+#define EIRX                        3u                  /* Input polarity for IrDA modem */
+#define EITX                        4u                  /* Output polarity for IrDA modem */
+#define EITP                        5u                  /* Output pulse width for IrDA modem */
+
+/* Multimode register 1 bit MASKS */
+#define E_MSB_RX_MASK               (0x01u << 0u)      /* MSB / LSB first for receiver */
+#define E_MSB_TX_MASK               (0x01u << 1u)      /* MSB / LSB first for transmitter */
+#define EIRD_MASK                   (0x01u << 2u)      /* Enable IrDA modem */
+#define EIRX_MASK                   (0x01u << 3u)      /* Input polarity for IrDA modem */
+#define EITX_MASK                   (0x01u << 4u)      /* Output polarity for IrDA modem */
+#define EITP_MASK                   (0x01u << 5u)      /* Output pulse width for IrDA modem */
+
+/* Multimode register 2 bit definitions */
+//#define EERR                        0u                  /* Enable ERR / NACK during stop time */
+//#define EAFM                        1u                  /* Enable 9-bit address flag mode */
+//#define EAFC                        2u                  /* Enable address flag clear */
+//#define ESWM                        3u                  /* Enable single wire half-duplex mode */
+
+/* Multimode register 2 bit MASKS */
+//#define EERR_MASK                   (0x01u << 0u)      /* Enable ERR / NACK during stop time */
+//#define EAFM_MASK                   (0x01u << 1u)      /* Enable 9-bit address flag mode */
+//#define EAFC_MASK                   (0x01u << 2u)      /* Enable address flag clear */
+//#define ESWM_MASK                   (0x01u << 3u)      /* Enable single wire half-duplex mode */
+
+/* Multimode Interrupt Enable register and
+   Multimode Interrupt Identification register definitions */
+//#define ERTOI                       0u                  /* Enable receiver timeout interrupt */
+//#define ENACKI                      1u                  /* Enable NACK / ERR interrupt */
+//#define EPID_PEI                    2u                  /* Enable PID parity error interrupt */
+//#define ELINBI                      3u                  /* Enable LIN break interrupt */
+//#define ELINSI                      4u                  /* Enable LIN sync detection interrupt */
+
+/* Multimode Interrupt Enable register and
+   Multimode Interrupt Identification register MASKS */
+//#define ERTOI_MASK                  (0x01u << 0u)      /* Enable receiver timeout interrupt */
+//#define ENACKI_MASK                 (0x01u << 1u)      /* Enable NACK / ERR interrupt */
+//#define EPID_PEI_MASK               (0x01u << 2u)      /* Enable PID parity error interrupt */
+//#define ELINBI_MASK                 (0x01u << 3u)      /* Enable LIN break interrupt */
+//#define ELINSI_MASK                 (0x01u << 4u)      /* Enable LIN sync detection interrupt */
+
+typedef struct
+{
+    union
+    {
+        volatile const  uint8_t    RBR;
+        volatile uint8_t    THR;
+        volatile uint8_t    DLL;
+             uint32_t   RESERVED0;
+    };
+
+    union
+    {
+        volatile uint8_t  DLM;
+        volatile uint8_t  IER;
+             uint32_t RESERVED1;
+    };
+
+    union
+    {
+        volatile uint8_t  IIR;
+        volatile uint8_t  FCR;
+             uint32_t RESERVED2;
+    };
+
+    volatile uint8_t  LCR;
+         uint8_t  RESERVED3[3];
+
+    volatile uint8_t  MCR;
+         uint8_t  RESERVED4[3];
+
+    volatile const  uint8_t  LSR;
+         uint8_t  RESERVED5[3];
+
+    volatile const  uint8_t  MSR;
+         uint8_t  RESERVED6[3];
+
+    volatile uint8_t  SR;
+         uint8_t  RESERVED7[7];
+
+} UART_TypeDef;
+
+
+/***************************************************************************//**
+  uart_instance.
+  There is one instance of this structure for each instance of the
+  microprocessor subsystem's UARTs. Instances of this structure are used to
+  identify a specific UART. A pointer to an initialized instance of the
+  uart_instance_t structure is passed as the first parameter to
+  UART driver functions to identify which UART should perform the
+  requested operation.
+ */
+struct uart_instance{
+    /* CMSIS related defines identifying the UART hardware. */
+    UART_TypeDef *      hw_reg;     /*!< Pointer to UART registers. */
+    uint32_t            baudrate;   /*!< Operating baud rate. */
+    uint8_t             lineconfig; /*!< Line configuration parameters. */
+    uint8_t             status;     /*!< Sticky line status. */
+
+    /* transmit related info (used with interrupt driven transmit): */
+    const uint8_t * tx_buffer;          /*!< Pointer to transmit buffer. */
+    uint32_t        tx_buff_size;       /*!< Transmit buffer size. */
+    uint32_t        tx_idx;             /*!< Index within transmit buffer of next byte to transmit.*/
+
+    /* line status interrupt handler:*/
+    uart_irq_handler_t linests_handler;   /*!< Pointer to user registered line status handler. */
+    /* receive interrupt handler:*/
+    uart_irq_handler_t rx_handler;        /*!< Pointer to user registered receiver handler. */
+    /* transmit interrupt handler:*/
+    uart_irq_handler_t tx_handler;        /*!< Pointer to user registered transmit handler. */
+    /* modem status interrupt handler:*/
+    uart_irq_handler_t modemsts_handler;  /*!< Pointer to user registered modem status handler. */
+
+
+
+};
+
+extern uart_instance_t g_uart_0;
+
+static void default_tx_handler(uart_instance_t * this_uart);
+static void enable_irq(const uart_instance_t * this_uart);
+static void disable_irq(const uart_instance_t * this_uart);
+
+static void config_baud_divisors
+(
+    uart_instance_t * this_uart,
+    uint32_t baudrate    
+);
+
+/***************************************************************************//**
+  The UART_init() function initializes and configures the
+  UART with the configuration passed as a parameter. The configuration
+  parameters are the baud_rate which is used to generate the baud value and the
+  line_config which is used to specify the line configuration (bit length,
+  stop bits and parity).
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function.
+  @param baud_rate
+    The baud_rate parameter specifies the baud rate. It can be specified for
+    common baud rates using the following defines:
+    - UART_110_BAUD
+    - UART_300_BAUD
+    - UART_600_BAUD
+    - UART_1200_BAUD
+    - UART_2400_BAUD
+    - UART_4800_BAUD
+    - UART_9600_BAUD
+    - UART_19200_BAUD
+    - UART_38400_BAUD
+    - UART_57600_BAUD
+    - UART_115200_BAUD
+    - UART_230400_BAUD
+    - UART_460800_BAUD
+    - UART_921600_BAUD
+    
+    Alternatively, any nonstandard baud rate can be specified by simply passing
+    the actual required baud rate as the value for this parameter.
+  @param line_config
+    The line_config parameter is the line configuration specifying the bit length,
+    number of stop bits and parity settings.
+    
+    This is a bitwise OR of one value from each of the following groups of
+    allowed values:
+    
+    One of the following to specify the transmit/receive data bit length:
+     - UART_DATA_5_BITS
+     - UART_DATA_6_BITS,
+     - UART_DATA_7_BITS
+     - UART_DATA_8_BITS
+     
+    One of the following to specify the parity setting:
+     - UART_NO_PARITY
+     - UART_EVEN_PARITY
+     - UART_ODD_PARITY
+     - UART_STICK_PARITY_0
+     - UART_STICK_PARITY_1
+        
+    One of the following to specify the number of stop bits:
+     - UART_ONE_STOP_BIT
+     - UART_ONEHALF_STOP_BIT
+     - UART_TWO_STOP_BITS
+  @return
+    This function does not return a value.
+  Example:
+  @code
+  #include "uart.h"
+  int main(void)
+  {
+    UART_init(&g_uart0_lo,
+             UART_57600_BAUD,
+             UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                   
+     return(0);
+  }
+  @endcode
+ */
+void
+UART_init
+(
+    uart_instance_t* this_uart,
+    uint32_t baud_rate,
+    uint8_t line_config
+);
+
+/***************************************************************************//**
+  The function UART_polled_tx() is used to transmit data. It transfers the
+  contents of the transmitter data buffer, passed as a function parameter, into
+  the UART's hardware transmitter FIFO. It returns when the full content of the
+  transmit data buffer has been transferred to the UART's transmit FIFO. It is
+  safe to release or reuse the memory used as the transmitter data buffer once
+  this function returns.
+  Note:     This function reads the UART's line status register (LSR) to poll
+  for the active state of the transmitter holding register empty (THRE) bit
+  before transferring data from the data buffer to the transmitter FIFO. It
+  transfers data to the transmitter FIFO in blocks of 16 bytes or less and
+  allows the FIFO to empty before transferring the next block of data.
+  Note:     The actual transmission over the serial connection will still be
+  in progress when this function returns. Use the UART_get_tx_status()
+  function if you need to know when the transmitter is empty.
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function. 
+  @param pbuff
+    The pbuff parameter is a pointer to a buffer containing the data to
+    be transmitted.
+  @param tx_size
+    The tx_size parameter specifies the size, in bytes, of the data to
+    be transmitted.
+  @return
+    This function does not return a value.
+  Example:
+  @code
+  #include "uart.h"
+  int main(void)
+  {
+     uint8_t message[12] = "Hello World";
+     UART_init(&g_uart0_lo,
+              UART_57600_BAUD,
+              SS_UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+     UART_polled_tx(&g_uart0_lo, message, sizeof(message));
+     
+     return(0);
+  }
+  @endcode
+ */
+void
+UART_polled_tx
+(
+    uart_instance_t * this_uart,
+    const uint8_t * pbuff,
+    uint32_t tx_size
+);
+
+/***************************************************************************//**
+  The function UART_polled_tx_string() is used to transmit a NULL ('\0')
+  terminated string. It transfers the text string, from the buffer starting at
+  the address pointed to by p_sz_string into the UART's hardware transmitter
+  FIFO. It returns when the complete string has been transferred to the UART's
+  transmit FIFO. It is safe to release or reuse the memory used as the string
+  buffer once this function returns.
+  Note:     This function reads the UART's line status register (LSR) to poll
+  for the active state of the transmitter holding register empty (THRE) bit
+  before transferring data from the data buffer to the transmitter FIFO. It
+  transfers data to the transmitter FIFO in blocks of 16 bytes or less and
+  allows the FIFO to empty before transferring the next block of data.
+  Note:     The actual transmission over the serial connection will still be
+  in progress when this function returns. Use the UART_get_tx_status()
+  function if you need to know when the transmitter is empty.
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function.
+  @param p_sz_string
+    The p_sz_string parameter is a pointer to a buffer containing the NULL
+    ('\0') terminated string to be transmitted.
+  @return
+    This function does not return a value.
+  Example:
+  @code
+  #include "uart.h"
+  int main(void)
+  {
+     uint8_t message[12] = "Hello World";
+     UART_init(&g_uart0_lo,
+             UART_57600_BAUD,
+             UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                   
+     UART_polled_tx_string(&g_uart0_lo, message);
+     
+     return(0);
+  }
+  @endcode
+ */
+void
+UART_polled_tx_string
+(
+    uart_instance_t * this_uart,
+    const uint8_t * p_sz_string
+);
+
+/***************************************************************************//**
+  The function UART_irq_tx() is used to initiate an interrupt-driven
+  transmit. It returns immediately after making a note of the transmit buffer
+  location and enabling transmit interrupts both at the UART and the PolarFire
+  SoC Core Complex PLIC level. This function takes a pointer via the pbuff
+  parameter to a memory buffer containing the data to transmit. The memory
+  buffer specified through this pointer must remain allocated and contain the
+  data to transmit until the transmit completion has been detected through calls
+  to function UART_tx_complete(). The actual transmission over the serial 
+  connection is still in progress until calls to the UART_tx_complete() 
+  function indicate transmit completion.
+  Note:     The UART_irq_tx() function enables both the transmit holding
+  register empty (THRE) interrupt in the UART and the UART instance
+  interrupt in the PolarFire SoC Core Complex PLIC as part of its implementation.
+  Note:     The UART_irq_tx() function assigns an internal default transmit
+  interrupt handler function to the UART's THRE interrupt. This interrupt
+  handler overrides any custom interrupt handler that you may have previously
+  registered using the UART_set_tx_handler() function.
+  Note:     The UART_irq_tx() function's default transmit interrupt
+  handler disables the UART's THRE interrupt when all of the data has
+  been transferred to the UART's transmit FIFO.
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function.
+  @param pbuff
+    The pbuff parameter is a pointer to a buffer containing the data
+    to be transmitted.
+  @param tx_size
+    The tx_size parameter specifies the size, in bytes, of the data
+    to be transmitted.
+  @return
+    This function does not return a value.
+  Example:
+  @code
+  #include "uart.h"
+  int main(void)
+  {
+     uint8_t tx_buff[10] = "abcdefghi";
+     
+     UART_init(&g_uart0_lo,
+              UART_57600_BAUD,
+              UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                   
+     UART_irq_tx(&g_uart0_lo, tx_buff, sizeof(tx_buff));
+     
+     while(0 == UART_tx_complete(&g_uart0_lo))
+     {
+         ;
+     }
+     return(0);
+  }
+  @endcode
+ */
+void
+UART_irq_tx
+(
+    uart_instance_t * this_uart,
+    const uint8_t * pbuff,
+    uint32_t tx_size
+);
+
+/***************************************************************************//**
+  The UART_tx_complete() function is used to find out if the
+  interrupt-driven transmit previously initiated through a call to
+  UART_irq_tx() is complete. This is typically used to find out when it is
+  safe to reuse or release the memory buffer holding transmit data.
+  Note:     The transfer of all of the data from the memory buffer to the UART's
+  transmit FIFO and the actual transmission over the serial connection are both
+  complete when a call to the UART_tx_complete() function indicates transmit
+  completion.
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function.
+  @return
+    This function return a non-zero value if transmit has completed, otherwise
+    it returns zero.
+  Example:
+    See the UART_irq_tx() function for an example that uses the
+    UART_tx_complete() function.
+ */
+int8_t
+UART_tx_complete
+(
+   uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+  The UART_get_rx() function reads the content of the UART receiver's FIFO
+  and stores it in the receive buffer that is passed via the rx_buff function
+  parameter. It copies either the full contents of the FIFO into the receive
+  buffer, or just enough data from the FIFO to fill the receive buffer,
+  dependent upon the size of the receive buffer passed by the buff_size
+  parameter. The UART_get_rx() function returns the number of bytes copied
+  into the receive buffer .This function is non-blocking and will return 0
+  immediately if no data has been received.
+  Note:     The UART_get_rx() function reads and accumulates the receiver
+  status of the UART instance before reading each byte from the receiver's
+  data register/FIFO. This allows the driver to maintain a sticky record of any
+  receiver errors that occur as the UART receives each data byte; receiver
+  errors would otherwise be lost after each read from the receiver's data
+  register. A call to the UART_get_rx_status() function returns any receiver
+  errors accumulated during the execution of the UART_get_rx() function.
+  Note:     If you need to read the error status for each byte received, set
+  the buff_size to 1 and read the receive line error status for each byte
+  using the UART_get_rx_status() function.
+  The UART_get_rx() function can be used in polled mode, where it is called
+  at regular intervals to find out if any data has been received, or in
+  interrupt driven-mode, where it is called as part of a receive handler that is
+  called by the driver as a result of data being received.
+  Note:     In interrupt driven mode you should call the UART_get_rx()
+  function as part of the receive handler function that you register with
+  the UART driver through a call to UART_set_rx_handler().
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function.
+  @param rx_buff
+    The rx_buff parameter is a pointer to a buffer where the received
+    data is copied.
+  @param buff_size
+    The buff_size parameter specifies the size of the receive buffer in bytes.
+  @return
+    This function returns the number of bytes that were copied into the
+    rx_buff buffer. It returns 0 if no data has been received.
+  Polled mode example:
+  @code
+   int main( void )
+   {
+      uint8_t rx_buff[RX_BUFF_SIZE];
+      uint32_t rx_idx  = 0;
+      UART_init(&g_uart0_lo,
+             UART_57600_BAUD,
+             UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                    
+      while(1)
+      {
+          rx_size = UART_get_rx(&g_uart0_lo, rx_buff, sizeof(rx_buff));
+          if(rx_size > 0)
+          {
+              process_rx_data(rx_buff, rx_size);
+          }
+          task_a();
+          task_b();
+      }
+      return 0;
+   }
+  @endcode
+  Interrupt driven example:
+  @code
+   int main( void )
+   {
+      UART_init(&g_uart1,
+              UART_57600_BAUD,
+              UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                    
+      UART_set_rx_handler(&g_uart1,
+                              uart1_rx_handler,
+                              UART_FIFO_SINGLE_BYTE);
+      
+      while(1)
+      {
+          task_a();
+          task_b();
+      }
+      return 0;
+   }
+   void uart1_rx_handler(uart_instance_t * this_uart)
+   {
+      uint8_t rx_buff[RX_BUFF_SIZE];
+      uint32_t rx_idx  = 0;
+      rx_size = UART_get_rx(this_uart, rx_buff, sizeof(rx_buff));
+      process_rx_data(rx_buff, rx_size);
+   }
+  @endcode
+ */
+size_t
+UART_get_rx
+(
+   uart_instance_t * this_uart,
+   uint8_t * rx_buff,
+   size_t buff_size
+);
+
+/***************************************************************************//**
+  The UART_set_rx_handler() function is used to register a receive handler
+  function that is called by the driver when a UART receive data available (RDA)
+  interrupt occurs. You must create and register the receive handler function
+  to suit your application and it must include a call to the UART_get_rx()
+  function to actually read the received data.
+  Note:     The UART_set_rx_handler() function enables both the RDA
+  interrupt in the UART instance. It also enables the corresponding 
+  UART instance interrupt in the PolarFire SoC Core Complex PLIC  as part
+  of its implementation.
+  Note:     You can disable the RDA interrupt when required by calling the 
+  UART_disable_irq() function. This is your choice and is dependent upon
+  your application.
+  
+  @param this_uart
+    The this_uart parameter is a pointer to an uart_instance_t
+    structure identifying the UART hardware block that will perform
+    the requested function.
+  @param handler
+    The handler parameter is a pointer to a receive interrupt handler function
+    provided by your application that will be called as a result of a UART RDA
+    interrupt. This handler function must be of type uart_irq_handler_t.
+  @param trigger_level
+    The trigger_level parameter is the receive FIFO trigger level. This
+    specifies the number of bytes that must be received before the UART
+    triggers an RDA interrupt.
+  @return
+    This function does not return a value.
+  Example:
+  @code
+  #include "uart.h"
+  #define RX_BUFF_SIZE    64
+  uint8_t g_rx_buff[RX_BUFF_SIZE];
+  void uart0_rx_handler(uart_instance_t * this_uart)
+  {
+      UART_get_rx(this_uart, &g_rx_buff[g_rx_idx], sizeof(g_rx_buff));
+  }
+  int main(void)
+  {
+      UART_init(&g_uart0_lo,
+             UART_57600_BAUD,
+             UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                    
+      UART_set_rx_handler(&g_uart0_lo,
+                              uart0_rx_handler,
+                              UART_FIFO_SINGLE_BYTE);
+                              
+      while(1)
+      {
+         ;
+      }
+      return(0);
+   }
+  @endcode
+ */
+void
+UART_set_rx_handler
+(
+    uart_instance_t *       this_uart,
+    uart_irq_handler_t          handler,
+    uart_rx_trig_level_t    trigger_level
+);
+
+
+#endif /*__UART_H_*/
+
diff --git a/bench/bsp/hal/crt0.S b/bench/bsp/hal/crt0.S
new file mode 100644
index 0000000000000000000000000000000000000000..b4ab3ca5690c4395089b01b5788c75a712a9a15e
--- /dev/null
+++ b/bench/bsp/hal/crt0.S
@@ -0,0 +1,75 @@
+/* Copyright (c) 2017  SiFive Inc. All rights reserved.
+ * Copyright (c) 2019  ETH Zürich and University of Bologna
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the FreeBSD License.   This program is distributed in the hope that
+ * it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
+ * including the implied warranties of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.  A copy of this license is available at
+ * http://www.opensource.org/licenses.
+ */
+/* Make sure the vector table gets linked into the binary.  */
+.global vector_table
+
+/* Entry point for bare metal programs */
+.section .text.start
+.global _start
+.type _start, @function
+
+_start:
+/* initialize global pointer */
+.option push
+.option norelax
+1:	auipc gp, %pcrel_hi(__global_pointer$)
+	addi  gp, gp, %pcrel_lo(1b)
+.option pop
+
+
+
+
+/* initialize stack pointer */
+	la sp, __stack_end
+
+/* set vector table address */
+	la a0, __vector_start
+	ori a0, a0, 1 /*vector mode = vectored */
+	csrw mtvec, a0
+
+/* clear the bss segment */
+	la a0, _edata
+	la a2, _end
+	sub a2, a2, a0
+	li a1, 0
+	call memset
+
+/* new-style constructors and destructors */
+	la a0, __libc_fini_array
+	call atexit
+	call __libc_init_array
+
+/* call main */
+//	lw a0, 0(sp)                    /* a0 = argc */
+//	addi a1, sp, __SIZEOF_POINTER__ /* a1 = argv */
+//	li a2, 0                        /* a2 = envp = NULL */
+// Initialize these variables to 0. Cannot use argc or argv
+// since the stack is not initialized
+	li a0, 0
+	li a1, 0
+	li a2, 0
+
+	call main
+	tail exit
+
+.size  _start, .-_start
+
+.global _init
+.type   _init, @function
+.global _fini
+.type   _fini, @function
+_init:
+_fini:
+ /* These don't have to do anything since we use init_array/fini_array. Prevent
+    missing symbol error */
+	ret
+.size  _init, .-_init
+.size _fini, .-_fini
diff --git a/bench/bsp/hal/encoding.h b/bench/bsp/hal/encoding.h
new file mode 100644
index 0000000000000000000000000000000000000000..06e4ca975b80abfd9bf34657dc5300ba8356a35f
--- /dev/null
+++ b/bench/bsp/hal/encoding.h
@@ -0,0 +1,251 @@
+
+#ifndef RISCV_CSR_ENCODING_H
+#define RISCV_CSR_ENCODING_H
+
+#define MSTATUS_UIE         0x00000001
+#define MSTATUS_SIE         0x00000002
+#define MSTATUS_HIE         0x00000004
+#define MSTATUS_MIE         0x00000008
+#define MSTATUS_UPIE        0x00000010
+#define MSTATUS_SPIE        0x00000020
+#define MSTATUS_HPIE        0x00000040
+#define MSTATUS_MPIE        0x00000080
+#define MSTATUS_SPP         0x00000100
+#define MSTATUS_HPP         0x00000600
+#define MSTATUS_MPP         0x00001800
+#define MSTATUS_FS          0x00006000
+#define MSTATUS_XS          0x00018000
+#define MSTATUS_MPRV        0x00020000
+#define MSTATUS_SUM         0x00040000
+#define MSTATUS_MXR         0x00080000
+#define MSTATUS_TVM         0x00100000
+#define MSTATUS_TW          0x00200000
+#define MSTATUS_TSR         0x00400000
+#define MSTATUS32_SD        0x80000000
+#define MSTATUS64_SD        0x8000000000000000
+
+#define MCAUSE32_CAUSE       0x7FFFFFFF
+#define MCAUSE64_CAUSE       0x7FFFFFFFFFFFFFFF
+#define MCAUSE32_INT         0x80000000
+#define MCAUSE64_INT         0x8000000000000000
+
+#define SSTATUS_UIE         0x00000001
+#define SSTATUS_SIE         0x00000002
+#define SSTATUS_UPIE        0x00000010
+#define SSTATUS_SPIE        0x00000020
+#define SSTATUS_SPP         0x00000100
+#define SSTATUS_FS          0x00006000
+#define SSTATUS_XS          0x00018000
+#define SSTATUS_SUM         0x00040000
+#define SSTATUS_MXR         0x00080000
+#define SSTATUS32_SD        0x80000000
+#define SSTATUS64_SD        0x8000000000000000
+
+#define DCSR_XDEBUGVER      (3U<<30)
+#define DCSR_NDRESET        (1<<29)
+#define DCSR_FULLRESET      (1<<28)
+#define DCSR_EBREAKM        (1<<15)
+#define DCSR_EBREAKH        (1<<14)
+#define DCSR_EBREAKS        (1<<13)
+#define DCSR_EBREAKU        (1<<12)
+#define DCSR_STOPCYCLE      (1<<10)
+#define DCSR_STOPTIME       (1<<9)
+#define DCSR_CAUSE          (7<<6)
+#define DCSR_DEBUGINT       (1<<5)
+#define DCSR_HALT           (1<<3)
+#define DCSR_STEP           (1<<2)
+#define DCSR_PRV            (3<<0)
+
+#define DCSR_CAUSE_NONE     0
+#define DCSR_CAUSE_SWBP     1
+#define DCSR_CAUSE_HWBP     2
+#define DCSR_CAUSE_DEBUGINT 3
+#define DCSR_CAUSE_STEP     4
+#define DCSR_CAUSE_HALT     5
+
+#define MCONTROL_TYPE(xlen)    (0xfULL<<((xlen)-4))
+#define MCONTROL_DMODE(xlen)   (1ULL<<((xlen)-5))
+#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
+
+#define MCONTROL_SELECT     (1U<<19)
+#define MCONTROL_TIMING     (1U<<18)
+#define MCONTROL_ACTION     (0x3fU<<12)
+#define MCONTROL_CHAIN      (1U<<11)
+#define MCONTROL_MATCH      (0xfU<<7)
+#define MCONTROL_M          (1U<<6)
+#define MCONTROL_H          (1U<<5)
+#define MCONTROL_S          (1U<<4)
+#define MCONTROL_U          (1U<<3)
+#define MCONTROL_EXECUTE    (1U<<2)
+#define MCONTROL_STORE      (1U<<1)
+#define MCONTROL_LOAD       (1U<<0)
+
+#define MCONTROL_TYPE_NONE      0
+#define MCONTROL_TYPE_MATCH     2
+
+#define MCONTROL_ACTION_DEBUG_EXCEPTION   0
+#define MCONTROL_ACTION_DEBUG_MODE        1
+#define MCONTROL_ACTION_TRACE_START       2
+#define MCONTROL_ACTION_TRACE_STOP        3
+#define MCONTROL_ACTION_TRACE_EMIT        4
+
+#define MCONTROL_MATCH_EQUAL     0
+#define MCONTROL_MATCH_NAPOT     1
+#define MCONTROL_MATCH_GE        2
+#define MCONTROL_MATCH_LT        3
+#define MCONTROL_MATCH_MASK_LOW  4
+#define MCONTROL_MATCH_MASK_HIGH 5
+
+#define MIP_SSIP            (1U << IRQ_S_SOFT)
+#define MIP_HSIP            (1U << IRQ_H_SOFT)
+#define MIP_MSIP            (1U << IRQ_M_SOFT)
+#define MIP_STIP            (1U << IRQ_S_TIMER)
+#define MIP_HTIP            (1U << IRQ_H_TIMER)
+#define MIP_MTIP            (1U << IRQ_M_TIMER)
+#define MIP_SEIP            (1U << IRQ_S_EXT)
+#define MIP_HEIP            (1U << IRQ_H_EXT)
+#define MIP_MEIP            (1U << IRQ_M_EXT)
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+
+#define PRV_U 0
+#define PRV_S 1
+#define PRV_H 2
+#define PRV_M 3
+
+#define SPTBR32_MODE 0x80000000
+#define SPTBR32_ASID 0x7FC00000
+#define SPTBR32_PPN  0x003FFFFF
+#define SPTBR64_MODE 0xF000000000000000
+#define SPTBR64_ASID 0x0FFFF00000000000
+#define SPTBR64_PPN  0x00000FFFFFFFFFFF
+
+#define SPTBR_MODE_OFF  0
+#define SPTBR_MODE_SV32 1
+#define SPTBR_MODE_SV39 8
+#define SPTBR_MODE_SV48 9
+#define SPTBR_MODE_SV57 10
+#define SPTBR_MODE_SV64 11
+
+#define PMP_R     0x01
+#define PMP_W     0x02
+#define PMP_X     0x04
+#define PMP_A     0x18
+#define PMP_L     0x80
+#define PMP_SHIFT 2
+
+#define PMP_TOR   0x08
+#define PMP_NA4   0x10
+#define PMP_NAPOT 0x18
+
+#define IRQ_S_SOFT   1
+#define IRQ_H_SOFT   2
+#define IRQ_M_SOFT   3
+#define IRQ_S_TIMER  5
+#define IRQ_H_TIMER  6
+#define IRQ_M_TIMER  7
+#define IRQ_S_EXT    9
+#define IRQ_H_EXT    10
+#define IRQ_M_EXT    11
+#define IRQ_COP      12
+#define IRQ_HOST     13
+
+#define DEFAULT_RSTVEC     0x00001000
+#define CLINT_BASE         0x02000000
+#define CLINT_SIZE         0x000c0000
+#define EXT_IO_BASE        0x40000000
+#define DRAM_BASE          0x80000000
+
+// page table entry (PTE) fields
+#define PTE_V     0x001 // Valid
+#define PTE_R     0x002 // Read
+#define PTE_W     0x004 // Write
+#define PTE_X     0x008 // Execute
+#define PTE_U     0x010 // User
+#define PTE_G     0x020 // Global
+#define PTE_A     0x040 // Accessed
+#define PTE_D     0x080 // Dirty
+#define PTE_SOFT  0x300 // Reserved for Software
+
+#define PTE_PPN_SHIFT 10
+
+#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
+
+#ifdef __riscv
+
+#if __riscv_xlen == 64
+# define MSTATUS_SD             MSTATUS64_SD
+# define SSTATUS_SD             SSTATUS64_SD
+# define RISCV_PGLEVEL_BITS     9
+# define SPTBR_MODE             SPTBR64_MODE
+# define MCAUSE_INT             MCAUSE64_INT                //ML added- should we be using later encoding.h?
+# define MCAUSE_CAUSE           MCAUSE64_CAUSE              //ML added- should we be using later encoding.h?
+#else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
+# define RISCV_PGLEVEL_BITS 10
+# define SPTBR_MODE SPTBR32_MODE
+# define MCAUSE_INT             MCAUSE32_INT                //ML added- should we be using later encoding.h?
+# define MCAUSE_CAUSE           MCAUSE32_CAUSE              //ML added- should we be using later encoding.h?
+#endif
+#define RISCV_PGSHIFT 12
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
+
+#ifndef __ASSEMBLER__
+
+#ifdef __GNUC__
+
+#define read_reg(reg) ({ unsigned long __tmp; \
+  asm volatile ("mv %0, " #reg : "=r"(__tmp)); \
+  __tmp; })
+
+#define read_csr(reg) ({ unsigned long __tmp; \
+  asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+  __tmp; })
+
+#define write_csr(reg, val) ({ \
+  asm volatile ("csrw " #reg ", %0" :: "rK"(val)); })
+
+#define swap_csr(reg, val) ({ unsigned long __tmp; \
+  asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \
+  __tmp; })
+
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
+  asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+  __tmp; })
+
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
+  asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+  __tmp; })
+
+#if 0
+#define csr_write(csr, val)                 \
+({                              \
+    unsigned long __v = (unsigned long)(val);       \
+    asm volatile ("csrw " __ASM_STR(csr) ", %0" \
+                  : : "rK" (__v)            \
+                  : "memory");          \
+})
+
+#define csr_write(csr, val)                 \
+({                              \
+    unsigned long __v = (unsigned long)(val);       \
+    __asm__ __volatile__ ("csrw " __ASM_STR(csr) ", %0" \
+                  : : "rK" (__v)            \
+                  : "memory");          \
+})
+#endif
+
+#define rdtime() read_csr(time)
+#define rdcycle() read_csr(cycle)
+#define rdinstret() read_csr(instret)
+
+#endif //__GNUC__
+
+#endif //__ASSEMBLER__
+
+#endif //__riscv
+
+#endif // RISCV_CSR_ENCODING_H
+
diff --git a/bench/bsp/hal/hal_assert.h b/bench/bsp/hal/hal_assert.h
new file mode 100644
index 0000000000000000000000000000000000000000..a72872836663051ebd3efae73d2fe4dfacd5f984
--- /dev/null
+++ b/bench/bsp/hal/hal_assert.h
@@ -0,0 +1,19 @@
+
+#ifndef HAL_ASSERT_HEADER
+#define HAL_ASSERT_HEADER
+
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+
+#define ASSERT(CHECK)
+
+
+#define HAL_ASSERT(CHECK)
+
+
+
+
+#endif  /* HAL_ASSERT_HEADER */
diff --git a/bench/bsp/hal/handlers.S b/bench/bsp/hal/handlers.S
new file mode 100644
index 0000000000000000000000000000000000000000..ebd676f7defb0ba1b6eee45def54ccd4044569a3
--- /dev/null
+++ b/bench/bsp/hal/handlers.S
@@ -0,0 +1,130 @@
+/*
+* Copyright 2019 ETH Zürich and University of Bologna
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the 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.
+*/
+
+/* Exception codes */
+#define EXCEPTION_ILLEGAL_INSN 2
+#define EXCEPTION_BREAKPOINT 3
+#define EXCEPTION_ECALL_M 11
+
+.section .text.handlers
+.global __no_irq_handler
+.global sw_irq_handler
+.global verification_irq_handler
+
+/* exception handling */
+__no_irq_handler:
+	la a0, no_exception_handler_msg
+	jal ra, puts
+	j __no_irq_handler
+
+sw_irq_handler:
+	/* While we are still using puts in handlers, save all caller saved
+	   regs.  Eventually, some of these saves could be deferred.  */
+	addi sp,sp,-64
+	sw ra, 0(sp)
+	sw a0, 4(sp)
+	sw a1, 8(sp)
+	sw a2, 12(sp)
+	sw a3, 16(sp)
+	sw a4, 20(sp)
+	sw a5, 24(sp)
+	sw a6, 28(sp)
+	sw a7, 32(sp)
+	sw t0, 36(sp)
+	sw t1, 40(sp)
+	sw t2, 44(sp)
+	sw t3, 48(sp)
+	sw t4, 52(sp)
+	sw t5, 56(sp)
+	sw t6, 60(sp)
+	csrr t0, mcause
+	li t1, EXCEPTION_ILLEGAL_INSN
+	beq t0, t1, handle_illegal_insn
+	li t1, EXCEPTION_ECALL_M
+	beq t0, t1, handle_ecall
+	li t1, EXCEPTION_BREAKPOINT
+	beq t0, t1, handle_ebreak
+	j handle_unknown
+
+handle_ecall:
+	jal ra, handle_syscall
+	j end_handler_incr_mepc
+
+handle_ebreak:
+	/* TODO support debug handling requirements.  */
+	la a0, ebreak_msg
+	jal ra, puts
+	j end_handler_incr_mepc
+
+handle_illegal_insn:
+	la a0, illegal_insn_msg
+	jal ra, puts
+	j end_handler_incr_mepc
+
+handle_unknown:
+	la a0, unknown_msg
+	jal ra, puts
+	/* We don't know what interrupt/exception is being handled, so don't
+	   increment mepc.  */
+	j end_handler_ret
+
+end_handler_incr_mepc:
+	csrr t0, mepc
+	lb t1, 0(t0)
+	li a0, 0x3
+	and t1, t1, a0
+	/* Increment mepc by 2 or 4 depending on whether the instruction at mepc
+	   is compressed or not.  */
+	bne t1, a0, end_handler_incr_mepc2
+	addi t0, t0, 2
+end_handler_incr_mepc2:
+	addi t0, t0, 2
+	csrw mepc, t0
+end_handler_ret:
+	lw ra, 0(sp)
+	lw a0, 4(sp)
+	lw a1, 8(sp)
+	lw a2, 12(sp)
+	lw a3, 16(sp)
+	lw a4, 20(sp)
+	lw a5, 24(sp)
+	lw a6, 28(sp)
+	lw a7, 32(sp)
+	lw t0, 36(sp)
+	lw t1, 40(sp)
+	lw t2, 44(sp)
+	lw t3, 48(sp)
+	lw t4, 52(sp)
+	lw t5, 56(sp)
+	lw t6, 60(sp)
+	addi sp,sp,64
+	mret
+/* this interrupt can be generated for verification purposes, random or when the
+   PC is equal to a given value*/
+verification_irq_handler:
+	mret
+
+.section .rodata
+illegal_insn_msg:
+	.string "illegal instruction exception handler entered\n"
+ecall_msg:
+	.string "ecall exception handler entered\n"
+ebreak_msg:
+	.string "ebreak exception handler entered\n"
+unknown_msg:
+	.string "unknown exception handler entered\n"
+no_exception_handler_msg:
+	.string "no exception handler installed\n"
diff --git a/bench/bsp/hal/plic.h b/bench/bsp/hal/plic.h
new file mode 100644
index 0000000000000000000000000000000000000000..93747f019d497b845a415e7ab2273e98707d7b1b
--- /dev/null
+++ b/bench/bsp/hal/plic.h
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Thales.
+ * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MPFS HAL Embedded Software
+ *
+ */
+/*******************************************************************************
+ *
+ * @author Microchip-FPGA Embedded Systems Solutions
+ *
+ * Definitions and functions associated with PLIC interrupts.
+ */
+// Additional contributions by:
+//         Sebastien Jacq - sjthales on github.com
+//
+// Description: Definitions and functions associated with PLIC interrupts
+//              for the CVA6 platform
+//
+// =========================================================================== //
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       modification of the Test for CVA6 softcore
+// =========================================================================== //
+
+#ifndef MSS_PLIC_H
+#define MSS_PLIC_H
+
+#include <stdint.h>
+#include "encoding.h"
+
+#include "hal_assert.h"
+
+/*
+ *Return value from External IRQ handler. This will be used to disable the
+ *Return External interrupt.
+ */
+#define EXT_IRQ_KEEP_ENABLED                                0U
+#define EXT_IRQ_DISABLE                                     1U
+
+
+
+/***************************************************************************//**
+ * PLIC source Interrupt numbers:
+ */
+
+typedef enum
+{
+    NoInterrupt_IRQHandler         = 0,    
+    UART_0_PLIC_IRQHandler         = 1,
+    QSPI_0_PLIC_IRQHandler         = 2,
+    ETH_0_PLIC_IRQHandler          = 3, 
+    External_4_IRQHandler  = 4,
+    External_5_IRQHandler  = 5,
+    External_6_IRQHandler  = 6,
+    External_7_IRQHandler  = 7,
+    External_8_IRQHandler  = 8,
+    External_9_IRQHandler  = 9,
+    External_10_IRQHandler = 10,
+    External_11_IRQHandler = 11,
+    External_12_IRQHandler = 12,
+    External_13_IRQHandler = 13,
+    External_14_IRQHandler = 14,
+    External_15_IRQHandler = 15,
+    External_16_IRQHandler = 16,
+    External_17_IRQHandler = 17,
+    External_18_IRQHandler = 18,
+    External_19_IRQHandler = 19,
+    External_20_IRQHandler = 20,
+    External_21_IRQHandler = 21,
+    External_22_IRQHandler = 22,
+    External_23_IRQHandler = 23,
+    External_24_IRQHandler = 24,
+    External_25_IRQHandler = 25,
+    External_26_IRQHandler = 26,
+    External_27_IRQHandler = 27,
+    External_28_IRQHandler = 28,
+    External_29_IRQHandler = 29,
+    External_30_IRQHandler = 30
+} PLIC_IRQn_Type;
+
+
+#define MAX_PLIC_INT External_30_IRQHandler
+
+typedef struct
+{
+    volatile uint32_t PRIORITY_THRESHOLD;
+    volatile uint32_t CLAIM_COMPLETE;
+    volatile uint32_t reserved[(0x1000/4)-2];
+} IRQ_Target_Type;
+
+typedef struct
+{
+    volatile uint32_t ENABLES[31U];
+} Target_Enables_Type;
+
+
+#define PLIC_SET_UP_REGISTERS 2U
+#define PLIC_NUM_SOURCES      30U     
+#define PLIC_NUM_PRIORITIES   7U
+#define NUM_CLAIM_REGS        2U
+
+
+
+typedef struct
+{
+    
+    volatile uint32_t RESERVED0;
+    /*-------------------- Source Priority --------------------*/
+    volatile uint32_t SOURCE_PRIORITY[PLIC_NUM_SOURCES];
+    volatile uint32_t RESERVED1[(0x1000/4) - (PLIC_NUM_SOURCES + 1)];
+
+    /*-------------------- Pending array --------------------*/
+    volatile const uint32_t PENDING_ARRAY[PLIC_SET_UP_REGISTERS];
+    volatile uint32_t RESERVED2[(0x1000/4) - PLIC_SET_UP_REGISTERS];
+
+    /*-------------------- Target enables --------------------*/
+    //volatile Target_Enables_Type TARGET_ENABLES[PLIC_SET_UP_REGISTERS];
+    //volatile uint32_t RESERVED3[(0x200000-0x2000) - PLIC_SET_UP_REGISTERS];
+    
+    /*-----------------Target Mode Enables--------------------*/
+    volatile uint32_t HART0_MMODE_ENA[PLIC_SET_UP_REGISTERS];
+    volatile uint32_t RESERVED3a[(0x80/4) - PLIC_SET_UP_REGISTERS];
+
+    volatile uint32_t HART0_SMODE_ENA[PLIC_SET_UP_REGISTERS];
+    volatile uint32_t RESERVED3[(0x80/4) - PLIC_SET_UP_REGISTERS];
+
+    volatile uint32_t RESERVED4[(0x200000-0x2000)/4 - PLIC_SET_UP_REGISTERS];
+
+    /*--- Target Priority threshold and claim/complete---------*/
+    IRQ_Target_Type TARGET[NUM_CLAIM_REGS];
+
+
+    
+} PLIC_Type;
+
+
+
+
+#define TARGET_OFFSET_HART0_M 0U
+#define TARGET_OFFSET_HART0_S 1U
+
+/***************************************************************************//**
+ * PLIC: Platform Level Interrupt Controller
+ */
+#define PLIC_BASE_ADDR 0x0C000000UL
+
+#define PLIC    ((PLIC_Type *)PLIC_BASE_ADDR)
+
+/*-------------------------------------------------------------------------*//**
+ * The function PLIC_init() initializes the PLIC controller and enables the
+ * global external interrupt bit.
+ */
+
+/*-----------------Hart Mode Enables--------------------*/
+
+static inline void PLIC_init(void)
+{
+    uint32_t inc;
+    uint64_t hart_id  = read_csr(mhartid);
+
+    /* Disable all interrupts for the current hart. */
+    for(inc = 0UL; inc < PLIC_SET_UP_REGISTERS; inc++)
+    {
+        PLIC->HART0_MMODE_ENA[inc] = 0U;
+        PLIC->HART0_SMODE_ENA[inc] = 0U;
+    }
+
+    PLIC->TARGET[TARGET_OFFSET_HART0_M].PRIORITY_THRESHOLD  = 0U;
+    /* Disable supervisor level */
+    PLIC->TARGET[TARGET_OFFSET_HART0_S].PRIORITY_THRESHOLD  = 7U;
+    
+    /* Enable machine external interrupts. */
+    set_csr(mie, MIP_MEIP);
+}
+
+
+/***************************************************************************//**
+ * The function PLIC_EnableIRQ() enables the external interrupt for the
+ * interrupt number indicated by the parameter IRQn.
+ */
+static inline void PLIC_EnableIRQ(PLIC_IRQn_Type IRQn)
+{
+    uint64_t hart_id  = read_csr(mhartid);
+
+    uint32_t current;
+
+    switch(hart_id)
+    {
+        case 0:
+            current  = PLIC->HART0_MMODE_ENA[IRQn / 32U];
+            current |= (uint32_t)1 << (IRQn % 32U);
+            PLIC->HART0_MMODE_ENA[IRQn / 32U]  = current;
+            break;
+        default:
+            break;
+    }
+}
+
+/***************************************************************************//**
+ * The function PLIC_DisableIRQ() disables the external interrupt for the
+ * interrupt number indicated by the parameter IRQn.
+ * NOTE:
+ *     This function can be used to disable the external interrupt from outside
+ *     external interrupt handler function.
+ *     This function MUST NOT be used from within the External Interrupt
+ *     handler.
+ *     If you wish to disable the external interrupt while the interrupt handler
+ *     for that external interrupt is executing then you must use the return
+ *     value EXT_IRQ_DISABLE to return from the extern interrupt handler.
+ */
+static inline void PLIC_DisableIRQ(PLIC_IRQn_Type IRQn)
+{
+    uint32_t current;
+    uint64_t hart_id  = read_csr(mhartid);
+
+    switch(hart_id)
+    {
+        case 0:
+            current = PLIC->HART0_MMODE_ENA[IRQn / 32U];
+            current &= ~((uint32_t)1 << (IRQn % 32U));
+            PLIC->HART0_MMODE_ENA[IRQn / 32U] = current;
+            break;
+            default:
+            break;
+    }
+}
+
+/***************************************************************************//**
+ * The function PLIC_SetPriority() sets the priority for the external interrupt
+ * for the interrupt number indicated by the parameter IRQn.
+ */
+static inline void PLIC_SetPriority(PLIC_IRQn_Type IRQn, uint32_t priority)
+{
+    if((IRQn > NoInterrupt_IRQHandler) && (IRQn < PLIC_NUM_SOURCES))
+    {
+        PLIC->SOURCE_PRIORITY[IRQn-1] = priority;
+    }
+}
+
+/***************************************************************************//**
+ * The function PLIC_GetPriority() returns the priority for the external
+ * interrupt for the interrupt number indicated by the parameter IRQn.
+ */
+static inline uint32_t PLIC_GetPriority(PLIC_IRQn_Type IRQn)
+{
+    uint32_t ret_val = 0U;
+
+    if((IRQn > NoInterrupt_IRQHandler) && (IRQn < PLIC_NUM_SOURCES))
+    {
+        ret_val = PLIC->SOURCE_PRIORITY[IRQn-1];
+    }
+
+    return(ret_val);
+}
+
+
+/*static inline uint32_t PLIC_pending(PLIC_IRQn_Type IRQn)
+{
+    return (PLIC->PENDING_ARRAY[IRQn/32U] & (0x01U<<(IRQn%32U)));
+}*/
+
+/***************************************************************************//**
+ * The function PLIC_ClaimIRQ() claims the interrupt from the PLIC controller.
+ */
+static inline uint32_t PLIC_ClaimIRQ(void)
+{
+    unsigned long hart_id = read_csr(mhartid);
+
+    return PLIC->TARGET[hart_id].CLAIM_COMPLETE;
+}
+
+/***************************************************************************//**
+ * The function PLIC_CompleteIRQ() indicates to the PLIC controller the
+ * interrupt is processed and claim is complete.
+ */
+static inline void PLIC_CompleteIRQ(uint32_t source)
+{
+    unsigned long hart_id = read_csr(mhartid);
+
+    PLIC->TARGET[hart_id].CLAIM_COMPLETE = source;
+}
+
+/***************************************************************************//**
+ *
+ * The function PLIC_SetPriority_Threshold() sets the threshold for a particular
+ * hart. The default threshold on reset is 0.
+ * The PFSoC Core Complex supports setting of an interrupt priority threshold
+ * via the threshold register. The threshold is a WARL field, where the PFSoC
+ * Core Complex supports a maximum threshold of 7.
+ * The PFSoC Core Complex will mask all PLIC interrupts of a priority less than
+ * or equal to threshold. For example, a threshold value of zero permits all
+ * interrupts with non-zero priority, whereas a value of 7 masks all
+ * interrupts.
+ */
+static inline void PLIC_SetPriority_Threshold(uint32_t threshold)
+{
+    uint64_t hart_id  = read_csr(mhartid);
+    //const unsigned long lookup[5U] = {0U, 1U, 3U, 5U, 7U};
+
+    //ASSERT(threshold <= 7);
+
+    PLIC->TARGET[hart_id].PRIORITY_THRESHOLD  = threshold;
+}
+
+/***************************************************************************//**
+ *  PLIC_ClearPendingIRQ(void)
+ *  This is only called by the startup hart and only once
+ *  Clears any pending interrupts as PLIC can be in unknown state on startup
+ */
+static inline void PLIC_ClearPendingIRQ(void)
+{
+    volatile uint32_t int_num  = PLIC_ClaimIRQ();
+    volatile int32_t wait_possible_int;
+
+    while ( int_num != NoInterrupt_IRQHandler)
+    {
+        uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+
+        PLIC_CompleteIRQ(int_num);
+        wait_possible_int = 0xFU;
+        while (wait_possible_int)
+        {
+            wait_possible_int--;
+        }
+        int_num  = PLIC_ClaimIRQ(); /* obtain interrupt, auto clears  */
+    }
+}
+
+/***************************************************************************//**
+ * This function is only called from one hart on startup
+ */
+static inline void PLIC_init_on_reset(void)
+{
+    uint32_t inc;
+
+    /* default all priorities so effectively disabled */
+    for(inc = 0U; inc < PLIC_NUM_SOURCES; ++inc)
+    {
+        /* priority must be greater than threshold to be enabled, so setting to
+         * 7 disables */
+        PLIC->SOURCE_PRIORITY[inc]  = 0U;
+    }
+
+    for(inc = 0U; inc < NUM_CLAIM_REGS; ++inc)
+    {
+        PLIC->TARGET[inc].PRIORITY_THRESHOLD  = 7U;
+    }
+
+    /* and clear all the enables */
+    for(inc = 0UL; inc < PLIC_SET_UP_REGISTERS; inc++)
+    {
+        PLIC->HART0_MMODE_ENA[inc] = 0U;
+        PLIC->HART0_SMODE_ENA[inc] = 0U;
+    }
+
+    /* clear any pending interrupts- in case already there */
+    PLIC_ClearPendingIRQ();
+}
+
+
+#endif  /* MSS_PLIC_H */
+
diff --git a/bench/bsp/hal/riscv_hal_stubs.c b/bench/bsp/hal/riscv_hal_stubs.c
new file mode 100755
index 0000000000000000000000000000000000000000..4f5ace513c6b9c4cb041f12ad25a4dd917e21530
--- /dev/null
+++ b/bench/bsp/hal/riscv_hal_stubs.c
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Thales.
+ * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MPFS HAL Embedded Software
+ *
+ */
+
+/*******************************************************************************
+ *
+ * @author Microchip-FPGA Embedded Systems Solutions
+ * @brief MPFS MSS Interrupt Function stubs.
+ *
+ */
+// Additional contributions by:
+//         Sebastien Jacq - sjthales on github.com
+//
+// Description: The functions below will only be linked with the application 
+//              code if the user does not provide an implementation for these 
+//              functions. These functions are defined with weak linking so that 
+//              they can be overridden by a function with same prototype in the 
+//              user's application code.
+//
+// =========================================================================== //
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       modification of the Test for CVA6 softcore
+// =========================================================================== //
+
+
+
+#include <unistd.h>
+
+
+__attribute__((weak))  uint8_t NoInterrupt_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t UART_0_PLIC_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t QSPI_0_PLIC_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t ETH_0_PLIC_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_4_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_5_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_6_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_7_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_8_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_9_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_10_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_11_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_12_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_13_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_14_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_15_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_16_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_17_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_18_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_19_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_20_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_21_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_22_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_23_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_24_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_25_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_26_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_27_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_28_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_29_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_30_IRQHandler(void)
+{
+    return(0);
+}
+
+__attribute__((weak))  uint8_t External_31_IRQHandler(void)
+{
+    return(0);
+}
+
+
diff --git a/bench/bsp/hal/syscalls.c b/bench/bsp/hal/syscalls.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f73838f37f6856b10f42b2cf11edcbc590d8d57
--- /dev/null
+++ b/bench/bsp/hal/syscalls.c
@@ -0,0 +1,438 @@
+/* An extremely minimalist syscalls.c for newlib
+ * Based on riscv newlib libgloss/riscv/sys_*.c
+ *
+ * Copyright (c) 2020 Thales.
+ * Copyright 2019 Clifford Wolf
+ * Copyright 2019 ETH Zürich and University of Bologna
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+// Additional contributions by:
+//         Sebastien Jacq - sjthales on github.com
+//
+// =========================================================================== //
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       modification of the Test for CVA6 softcore
+// =========================================================================== //
+
+#include <sys/stat.h>
+#include <sys/timeb.h>
+#include <sys/times.h>
+#include <sys/utime.h>
+#include <newlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <machine/syscall.h>
+#include <assert.h>
+#undef errno
+extern int errno;
+
+/* write to this reg for outputting strings */
+#define STDOUT_REG 0x10000000
+/* write test result of program to this reg */
+#define RESULT_REG 0x20000000
+/* write exit value of program to this reg */
+#define EXIT_REG 0x80040000
+
+#define STDOUT_FILENO 1
+
+/* It turns out that older newlib versions use different symbol names which goes
+ * against newlib recommendations. Anyway this is fixed in later version.
+ */
+#if __NEWLIB__ <= 2 && __NEWLIB_MINOR__ <= 5
+#define _sbrk sbrk
+#define _write write
+#define _close close
+#define _lseek lseek
+#define _read read
+#define _fstat fstat
+#define _isatty isatty
+#endif
+
+/************************************************************************************/
+/**********************       STDIO_THRU_UART        ********************************/
+/************************************************************************************/
+#ifdef STDIO_THRU_UART
+#include "uart.h"
+
+#ifndef STDIO_BAUD_RATE
+#define STDIO_BAUD_RATE  UART_115200_BAUD
+#endif
+
+static uart_instance_t * const gp_my_uart = &g_uart_0;
+
+/*------------------------------------------------------------------------------
+ * Global flag used to indicate if the UART driver needs to be initialized.
+ */
+static int g_stdio_uart_init_done = 0;
+
+#endif /* STDIO_THRU_UART */
+/***********************************************************************************/
+/**********************    END STDIO_THRU_UART      ********************************/
+/************************************************************************************/
+
+
+
+/* Upstream newlib now defines this in libgloss/riscv/internal_syscall.h.  */
+long
+__syscall_error(long a0)
+{
+  errno = -a0;
+  return -1;
+}
+
+void unimplemented_syscall()
+{
+  const char *p = "Unimplemented system call called!\n";
+  while (*p)
+    *(volatile int *)STDOUT_REG = *(p++);
+}
+
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _access(const char *file, int mode)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _chdir(const char *path)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _chmod(const char *path, mode_t mode)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _chown(const char *path, uid_t owner, gid_t group)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _close(int file)
+{
+  return -1;
+}
+
+int _execve(const char *name, char *const argv[], char *const env[])
+{
+  errno = ENOMEM;
+  return -1;
+}
+
+void _exit(int exit_status)
+{
+  *(volatile int *)EXIT_REG = exit_status;
+  asm volatile("wfi");
+  /* _exit should not return */
+  while (1) {};
+}
+
+int _faccessat(int dirfd, const char *file, int mode, int flags)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _fork(void)
+{
+  errno = EAGAIN;
+  return -1;
+}
+
+int _fstat(int file, struct stat *st)
+{
+  st->st_mode = S_IFCHR;
+  return 0;
+  // errno = -ENOSYS;
+  // return -1;
+}
+
+int _fstatat(int dirfd, const char *file, struct stat *st, int flags)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _ftime(struct timeb *tp)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+char *_getcwd(char *buf, size_t size)
+{
+  errno = -ENOSYS;
+  return NULL;
+}
+
+int _getpid()
+{
+  return 1;
+}
+
+int _gettimeofday(struct timeval *tp, void *tzp)
+{
+  errno = -ENOSYS;
+  return -1;
+}
+
+int _isatty(int file)
+{
+  return (file == STDOUT_FILENO);
+}
+
+int _kill(int pid, int sig)
+{
+  errno = EINVAL;
+  return -1;
+}
+
+int _link(const char *old_name, const char *new_name)
+{
+  errno = EMLINK;
+  return -1;
+}
+
+off_t _lseek(int file, off_t ptr, int dir)
+{
+  return 0;
+}
+
+int _lstat(const char *file, struct stat *st)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _open(const char *name, int flags, int mode)
+{
+  return -1;
+}
+
+int _openat(int dirfd, const char *name, int flags, int mode)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+ssize_t _read(int file, void *ptr, size_t len)
+{
+  return 0;
+}
+
+int _stat(const char *file, struct stat *st)
+{
+  st->st_mode = S_IFCHR;
+  return 0;
+  // errno = ENOSYS;
+  // return -1;
+}
+
+long _sysconf(int name)
+{
+
+  return -1;
+}
+
+clock_t _times(struct tms *buf)
+{
+  return -1;
+}
+
+int _unlink(const char *name)
+{
+  errno = ENOENT;
+  return -1;
+}
+
+int _utime(const char *path, const struct utimbuf *times)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+int _wait(int *status)
+{
+  errno = ECHILD;
+  return -1;
+}
+
+ssize_t _write(int file, const void *ptr, size_t len)
+{
+
+#ifdef STDIO_THRU_UART
+  /*--------------------------------------------------------------------------
+  * Initialize the UART driver if it is the first time this function is
+  * called.
+  */
+
+    if(!g_stdio_uart_init_done)
+    {
+        UART_init(gp_my_uart,
+                  STDIO_BAUD_RATE,
+                  UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT);
+                      
+        g_stdio_uart_init_done = 1;
+    }
+    
+    /*--------------------------------------------------------------------------
+     * Output text to the UART.
+     */
+    UART_polled_tx(gp_my_uart, (uint8_t *)ptr, len);
+    
+    return len;
+
+
+#else /* STDIO_THRU_UART */
+
+  const char *cptr = (char *)ptr;
+  if (file != STDOUT_FILENO)
+    {
+      errno = ENOSYS;
+      return -1;
+    }
+
+  const void *eptr = cptr + len;
+  while (cptr != eptr)
+    *(volatile int *)STDOUT_REG = *cptr++;
+  return len;
+#endif /* STDIO_THRU_UART */
+
+}
+
+extern char __heap_start[];
+extern char __heap_end[];
+static char *brk = __heap_start;
+
+int _brk(void *addr)
+{
+  brk = addr;
+  return 0;
+}
+
+void *_sbrk(ptrdiff_t incr)
+{
+  char *old_brk = brk;
+  register long sp asm("sp");
+
+  char *new_brk = brk += incr;
+  if (new_brk < (char *) sp && new_brk < __heap_end)
+    {
+      brk = new_brk;
+
+      return old_brk;
+    }
+  else
+    {
+      errno = ENOMEM;
+      return (void *) -1;
+    }
+}
+
+void handle_syscall (long a0,
+		     long a1,
+		     long a2,
+		     long a3,
+		     __attribute__((unused)) long a4,
+		     __attribute__((unused)) long a5,
+		     __attribute__((unused)) long a6,
+		     long a7) {
+  #ifdef __riscv_32e
+    register long syscall_id asm("t0");
+  #else
+    long syscall_id = a7;
+  #endif
+
+  switch (syscall_id) {
+    case SYS_exit:
+      _exit (a0);
+      break;
+    case SYS_read:
+      _read (a0, (void *) a1, a2);
+      break;
+    case SYS_write:
+      _write (a0, (const void *) a1, a2);
+      break;
+    case SYS_getpid:
+      _getpid ();
+      break;
+    case SYS_kill:
+      _kill (a0, a1);
+      break;
+    case SYS_open:
+      _open ((const char *) a0, a1, a2);
+      break;
+    case SYS_openat:
+      _openat (a0, (const char *) a1, a2, a3);
+      break;
+    case SYS_close:
+      _close (a0);
+      break;
+    case SYS_lseek:
+      _lseek (a0, a1, a2);
+      break;
+    case SYS_brk:
+      _brk ((void *) a0);
+      break;
+    case SYS_link:
+      _link ((const char *) a0, (const char *) a1);
+      break;
+    case SYS_unlink:
+      _unlink ((const char *) a0);
+      break;
+    case SYS_chdir:
+      _chdir ((const char *) a0);
+      break;
+    case SYS_getcwd:
+      _getcwd ((char *) a0, a1);
+      break;
+    case SYS_stat:
+      _stat ((const char *) a0, (struct stat *) a1);
+      break;
+    case SYS_fstat:
+      _fstat (a0, (struct stat *) a1);
+      break;
+    case SYS_lstat:
+      _lstat ((const char *) a0, (struct stat *) a1);
+      break;
+    case SYS_fstatat:
+      _fstatat (a0, (const char *) a1, (struct stat *) a2, a3);
+      break;
+    case SYS_access:
+      _access ((const char *) a0, a1);
+      break;
+    case SYS_faccessat:
+      _faccessat (a0, (const char *) a1, a2, a3);
+      break;
+    case SYS_gettimeofday:
+      _gettimeofday ((struct timeval *) a0, (void *) a1);
+      break;
+    case SYS_times:
+      _times ((struct tms *) a0);
+      break;
+    default:
+      unimplemented_syscall ();
+      break;
+  }
+}
diff --git a/bench/bsp/hal/vectors.S b/bench/bsp/hal/vectors.S
new file mode 100644
index 0000000000000000000000000000000000000000..53280060b28dde8f4857efe0627485d194de54bd
--- /dev/null
+++ b/bench/bsp/hal/vectors.S
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2020 Thales.
+* Copyright 2019 ETH Zürich and University of Bologna
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the 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.
+*/
+// Additional contributions by:
+//         Sebastien Jacq - sjthales on github.com
+//
+// Description: interrupt vector table
+//
+// =========================================================================== //
+// Revisions  :
+// Date        Version  Author       Description
+// 2020-10-06  0.1      S.Jacq       modification of the Test for CVA6 softcore
+// =========================================================================== //
+
+.section .vectors, "ax"
+.option norvc
+.global vector_table
+
+vector_table:
+	j sw_irq_handler
+	j UART_0_PLIC_IRQHandler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j __no_irq_handler
+	j verification_irq_handler
diff --git a/bench/utils/bin2mem.py b/bench/utils/bin2mem.py
new file mode 100755
index 0000000000000000000000000000000000000000..a8700696897d9b23c1a6f5b7c4dd542876a7b060
--- /dev/null
+++ b/bench/utils/bin2mem.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2020 Thales.
+# 
+# Copyright and related rights are licensed under the Apache
+# License, Version 2.0 (the "License"); you may not use this file except in
+# compliance with the License.  You may obtain a copy of the License at
+# https://www.apache.org/licenses/LICENSE-2.0. 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:         Sebastien Jacq - sjthales on github.com
+#
+# Additional contributions by:
+#
+#
+# script Name:    bin2mem
+# Project Name:   CVA6 softcore
+# Language:       Python
+#
+# Description:    Script to generate mem data file for simulation from binary 
+#                 application file.
+#
+# =========================================================================== #
+# Revisions  :
+# Date        Version  Author       Description
+# 2020-10-06  0.1      S.Jacq       Created
+# =========================================================================== #
+
+import sys
+import math
+import binascii
+
+###############################################################################
+# Start of file
+###############################################################################
+if(len(sys.argv) < 2):
+    print "Usage bin2mem.py FILENAME"
+    quit()
+
+filename = sys.argv[1].strip('.bin') + ".mem"
+
+mem_file  = open(filename,    'wb')
+
+with open(sys.argv[1], "rb") as f:
+    bytes_read = f.read(8)
+    while bytes_read:
+    	bytes_read_inv = bytes_read[::-1]
+    	mem_file.write("%s\n" %binascii.hexlify(bytes_read_inv) )
+	bytes_read = f.read(8)
+    
+###############################################################################
+# close all files
+###############################################################################
+
+mem_file.close()
+
+