diff --git a/bsp/sparkfun-redv/README.md b/bsp/sparkfun-redv/README.md
new file mode 100644
index 00000000..52cc3132
--- /dev/null
+++ b/bsp/sparkfun-redv/README.md
@@ -0,0 +1,13 @@
+Sparkfun RED-V is a low-cost, Arduino-compatible development board featuring the Freedom E310. It’s one of the best ways to start prototyping and developing your RISC‑V applications.
+
+This target is ideal for getting familiar with the RISC-V ISA instruction set and the freedom-metal libraries. It supports:
+
+- 1 hart with RV32IMAC core
+- 4 hardware breakpoints
+- Physical Memory Protection with 8 regions
+- 16 local interrupts signal that can be connected to off core complex devices
+- Up to 127 PLIC interrupt signals that can be connected to off core complex devices, with 7 priority levels
+- GPIO memory with 16 interrupt lines
+- SPI memory with 1 interrupt line
+- Serial port with 1 interrupt line
+- 1 blue LED
diff --git a/bsp/sparkfun-redv/core.dts b/bsp/sparkfun-redv/core.dts
new file mode 100644
index 00000000..26819954
--- /dev/null
+++ b/bsp/sparkfun-redv/core.dts
@@ -0,0 +1,250 @@
+/dts-v1/;
+/ {
+        #address-cells = <1>;
+        #size-cells = <1>;
+        compatible = "sparkfun,redv";
+        model = "sparkfun,rev";
+        cpus {
+                #address-cells = <1>;
+                #size-cells = <0>;
+                compatible = "sifive,fe310-g000";
+                L6: cpu@0 {
+                        clocks = <&hfclk>;
+                        compatible = "sifive,rocket0", "riscv";
+                        device_type = "cpu";
+                        i-cache-block-size = <64>;
+                        i-cache-sets = <128>;
+                        i-cache-size = <16384>;
+                        next-level-cache = <&spi0>;
+                        reg = <0>;
+                        riscv,isa = "rv32imac";
+                        riscv,pmpregions = <8>;
+                        sifive,itim = <&itim>;
+                        sifive,dtim = <&dtim>;
+                        status = "okay";
+                        timebase-frequency = <16000000>;
+                        hardware-exec-breakpoint-count = <4>;
+                        hlic: interrupt-controller {
+                                #interrupt-cells = <1>;
+                                compatible = "riscv,cpu-intc";
+                                interrupt-controller;
+                        };
+                };
+        };
+        soc {
+                #address-cells = <1>;
+                #size-cells = <1>;
+                #clock-cells = <1>;
+                compatible = "sifive,hifive1";
+                ranges;
+                hfxoscin: clock@0 {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <16000000>;
+                };
+                hfxoscout: clock@1 {
+                        compatible = "sifive,fe310-g000,hfxosc";
+                        clocks = <&hfxoscin>;
+                        reg = <&prci 0x4>;
+                        reg-names = "config";
+                };
+                hfroscin: clock@2 {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <72000000>;
+                };
+                hfroscout: clock@3 {
+                        compatible = "sifive,fe310-g000,hfrosc";
+                        clocks = <&hfroscin>;
+                        reg = <&prci 0x0>;
+                        reg-names = "config";
+                };
+                hfclk: clock@4 {
+                        compatible = "sifive,fe310-g000,pll";
+                        clocks = <&hfxoscout &hfroscout>;
+                        clock-names = "pllref", "pllsel0";
+                        reg = <&prci 0x8 &prci 0xc>;
+                        reg-names = "config", "divider";
+			clock-frequency = <16000000>;
+                };
+                lfrosc: clock@5 {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <32768>;
+                };
+                psdlfaltclk: clock@6 {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <32768>;
+                };
+                lfclk: clock@7 {
+                        compatible = "sifive,fe310-g000,lfrosc";
+                        clocks = <&lfrosc &psdlfaltclk>;
+                        clock-names = "lfrosc", "psdlfaltclk";
+                        reg = <&aon 0x70 &aon 0x7C>;
+                        reg-names = "config", "mux";
+                };
+                debug-controller@0 {
+                        compatible = "sifive,debug-011", "riscv,debug-011";
+                        interrupts-extended = <&hlic 65535>;
+                        reg = <0x0 0x1000>;
+                        reg-names = "control";
+                };
+                /* Missing: Error device */
+                maskrom@1000 {
+                        reg = <0x1000 0x2000>;
+                        reg-names = "mem";
+                };
+                otp@20000 {
+                        reg = <0x20000 0x2000 0x10010000 0x1000>;
+                        reg-names = "mem", "control";
+                };
+                clint: clint@2000000 {
+                        compatible = "riscv,clint0";
+                        interrupts-extended = <&hlic 3 &hlic 7>;
+                        reg = <0x2000000 0x10000>;
+                        reg-names = "control";
+                };
+                itim: itim@8000000 {
+                        compatible = "sifive,itim0";
+                        reg = <0x8000000 0x2000>;
+                        reg-names = "mem";
+                };
+                plic: interrupt-controller@c000000 {
+                        #interrupt-cells = <1>;
+                        compatible = "riscv,plic0";
+                        interrupt-controller;
+                        interrupts-extended = <&hlic 11>;
+                        reg = <0xc000000 0x4000000>;
+                        reg-names = "control";
+                        riscv,max-priority = <7>;
+                        riscv,ndev = <52>;
+                };
+                aon: aon@10000000 {
+                        compatible = "sifive,aon0";
+                        reg = <0x10000000 0x8000>;
+                        reg-names = "mem";
+                        interrupt-parent = <&plic>;
+                        interrupts = <1 2>;
+                        clocks = <&lfclk>;
+                };
+                prci: prci@10008000 {
+                        compatible = "sifive,fe310-g000,prci";
+                        reg = <0x10008000 0x8000>;
+                        reg-names = "mem";
+                };
+                gpio0: gpio@10012000 {
+                        compatible = "sifive,gpio0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
+                                      23 24 25 26 27 28 29 30 31 32 33 34 35 36
+                                      27 28 29>;
+                        reg = <0x10012000 0x1000>;
+                        reg-names = "control";
+                };
+                led@0 {
+                        compatible = "sifive,gpio-leds";
+                        label = "LD0";
+                        gpios = <&gpio0 5>;
+                        linux,default-trigger = "none";
+                };
+                uart0: serial@10013000 {
+                        compatible = "sifive,uart0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <3>;
+                        reg = <0x10013000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0 0x30000>;
+                };
+                spi0: spi@10014000 {
+                        compatible = "sifive,spi0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <5>;
+                        reg = <0x10014000 0x1000 0x20000000 0x7A120>;
+                        reg-names = "control", "mem";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0 0x0>;
+                        #address-cells = <1>;
+                        #size-cells = <1>;
+                        flash@0 {
+                                compatible = "jedec,spi-nor";
+                                reg = <0x20000000 0x424000>;
+                        };
+                };
+                pwm0: pwm@10015000 {
+                        compatible = "sifive,pwm0";
+                        sifive,comparator-widthbits = <8>;
+                        sifive,ncomparators = <4>;
+                        interrupt-parent = <&plic>;
+                        interrupts = <40 41 42 43>;
+                        reg = <0x10015000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0F 0x0F>;
+                };
+                i2c0: i2c@10016000 {
+                        compatible = "sifive,i2c0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <52>;
+                        reg = <0x10016000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0 0x3000>;
+                };
+                uart1: serial@10023000 {
+                        compatible = "sifive,uart0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <4>;
+                        reg = <0x10023000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0 0x840000>;
+                };
+                spi1: spi@10024000 {
+                        compatible = "sifive,spi0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <6>;
+                        reg = <0x10024000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0 0x0003C>;
+                };
+                pwm1: pwm@10025000 {
+                        compatible = "sifive,pwm0";
+                        sifive,comparator-widthbits = <16>;
+                        sifive,ncomparators = <4>;
+                        interrupt-parent = <&plic>;
+                        interrupts = <44 45 46 47>;
+                        reg = <0x10025000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x780000 0x780000>;
+                };
+                spi2: spi@10034000 {
+                        compatible = "sifive,spi0";
+                        interrupt-parent = <&plic>;
+                        interrupts = <7>;
+                        reg = <0x10034000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x0 0xFC000000>;
+                };
+                pwm2: pwm@10035000 {
+                        compatible = "sifive,pwm0";
+                        sifive,comparator-widthbits = <16>;
+                        sifive,ncomparators = <4>;
+                        interrupt-parent = <&plic>;
+                        interrupts = <48 49 50 51>;
+                        reg = <0x10035000 0x1000>;
+                        reg-names = "control";
+                        clocks = <&hfclk>;
+                        pinmux = <&gpio0 0x3C00 0x3C00>;
+                };
+                dtim: dtim@80000000 {
+                        compatible = "sifive,dtim0";
+                        reg = <0x80000000 0x4000>;
+                        reg-names = "mem";
+                };
+        };
+};
diff --git a/bsp/sparkfun-redv/design.dts b/bsp/sparkfun-redv/design.dts
new file mode 100644
index 00000000..098c25c4
--- /dev/null
+++ b/bsp/sparkfun-redv/design.dts
@@ -0,0 +1,10 @@
+/include/ "core.dts"
+/ {
+	chosen {
+		metal,entry = <&spi0 1 65536>;
+		metal,boothart = <&L6>;
+		stdout-path = "/soc/serial@10013000:115200";
+		metal,itim = <&itim 0 0>;
+		metal,ram = <&dtim 0 0>;
+	};
+};
diff --git a/bsp/sparkfun-redv/design.reglist b/bsp/sparkfun-redv/design.reglist
new file mode 100644
index 00000000..921dd83a
--- /dev/null
+++ b/bsp/sparkfun-redv/design.reglist
@@ -0,0 +1,54 @@
+zero
+ra
+sp
+gp
+tp
+t0
+t1
+t2
+fp
+s1
+a0
+a1
+a2
+a3
+a4
+a5
+a6
+a7
+s2
+s3
+s4
+s5
+s6
+s7
+s8
+s9
+s10
+s11
+t3
+t4
+t5
+t6
+pc
+mstatus
+misa
+mie
+mtvec
+mscratch
+mepc
+mcause
+mtval
+mip
+mvendorid
+marchid
+mimpid
+mhartid
+tselect
+tdata1
+tdata2
+tdata3
+dcsr
+dpc
+dscratch
+priv
diff --git a/bsp/sparkfun-redv/design.svd b/bsp/sparkfun-redv/design.svd
new file mode 100644
index 00000000..3ad2768b
--- /dev/null
+++ b/bsp/sparkfun-redv/design.svd
@@ -0,0 +1,3169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<device schemaVersion="1.3" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd">
+  <name>sifive_hifive1_revb</name>
+  <version>0.1</version>
+  <description>From sifive,hifive1-revb,model device generator</description>
+  <addressUnitBits>8</addressUnitBits>
+  <width>32</width>
+  <size>32</size>
+  <access>read-write</access>
+  <peripherals>
+    <peripheral>
+      <name>riscv_clint0_0</name>
+      <description>From riscv,clint0,control peripheral generator</description>
+      <baseAddress>0x2000000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x10000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>msip_0</name>
+          <description>MSIP Register for hart 0</description>
+          <addressOffset>0x0</addressOffset>
+        </register>
+        <register>
+          <name>mtimecmp_0</name>
+          <description>MTIMECMP Register for hart 0</description>
+          <addressOffset>0x4000</addressOffset>
+          <size>64</size>
+        </register>
+        <register>
+          <name>mtime</name>
+          <description>MTIME Register</description>
+          <addressOffset>0xBFF8</addressOffset>
+          <size>64</size>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>riscv_plic0_0</name>
+      <description>From riscv,plic0,control peripheral generator</description>
+      <baseAddress>0xC000000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x4000000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>priority_1</name>
+          <description>PRIORITY Register for interrupt id 1</description>
+          <addressOffset>0x4</addressOffset>
+        </register>
+        <register>
+          <name>priority_2</name>
+          <description>PRIORITY Register for interrupt id 2</description>
+          <addressOffset>0x8</addressOffset>
+        </register>
+        <register>
+          <name>priority_3</name>
+          <description>PRIORITY Register for interrupt id 3</description>
+          <addressOffset>0xC</addressOffset>
+        </register>
+        <register>
+          <name>priority_4</name>
+          <description>PRIORITY Register for interrupt id 4</description>
+          <addressOffset>0x10</addressOffset>
+        </register>
+        <register>
+          <name>priority_5</name>
+          <description>PRIORITY Register for interrupt id 5</description>
+          <addressOffset>0x14</addressOffset>
+        </register>
+        <register>
+          <name>priority_6</name>
+          <description>PRIORITY Register for interrupt id 6</description>
+          <addressOffset>0x18</addressOffset>
+        </register>
+        <register>
+          <name>priority_7</name>
+          <description>PRIORITY Register for interrupt id 7</description>
+          <addressOffset>0x1C</addressOffset>
+        </register>
+        <register>
+          <name>priority_8</name>
+          <description>PRIORITY Register for interrupt id 8</description>
+          <addressOffset>0x20</addressOffset>
+        </register>
+        <register>
+          <name>priority_9</name>
+          <description>PRIORITY Register for interrupt id 9</description>
+          <addressOffset>0x24</addressOffset>
+        </register>
+        <register>
+          <name>priority_10</name>
+          <description>PRIORITY Register for interrupt id 10</description>
+          <addressOffset>0x28</addressOffset>
+        </register>
+        <register>
+          <name>priority_11</name>
+          <description>PRIORITY Register for interrupt id 11</description>
+          <addressOffset>0x2C</addressOffset>
+        </register>
+        <register>
+          <name>priority_12</name>
+          <description>PRIORITY Register for interrupt id 12</description>
+          <addressOffset>0x30</addressOffset>
+        </register>
+        <register>
+          <name>priority_13</name>
+          <description>PRIORITY Register for interrupt id 13</description>
+          <addressOffset>0x34</addressOffset>
+        </register>
+        <register>
+          <name>priority_14</name>
+          <description>PRIORITY Register for interrupt id 14</description>
+          <addressOffset>0x38</addressOffset>
+        </register>
+        <register>
+          <name>priority_15</name>
+          <description>PRIORITY Register for interrupt id 15</description>
+          <addressOffset>0x3C</addressOffset>
+        </register>
+        <register>
+          <name>priority_16</name>
+          <description>PRIORITY Register for interrupt id 16</description>
+          <addressOffset>0x40</addressOffset>
+        </register>
+        <register>
+          <name>priority_17</name>
+          <description>PRIORITY Register for interrupt id 17</description>
+          <addressOffset>0x44</addressOffset>
+        </register>
+        <register>
+          <name>priority_18</name>
+          <description>PRIORITY Register for interrupt id 18</description>
+          <addressOffset>0x48</addressOffset>
+        </register>
+        <register>
+          <name>priority_19</name>
+          <description>PRIORITY Register for interrupt id 19</description>
+          <addressOffset>0x4C</addressOffset>
+        </register>
+        <register>
+          <name>priority_20</name>
+          <description>PRIORITY Register for interrupt id 20</description>
+          <addressOffset>0x50</addressOffset>
+        </register>
+        <register>
+          <name>priority_21</name>
+          <description>PRIORITY Register for interrupt id 21</description>
+          <addressOffset>0x54</addressOffset>
+        </register>
+        <register>
+          <name>priority_22</name>
+          <description>PRIORITY Register for interrupt id 22</description>
+          <addressOffset>0x58</addressOffset>
+        </register>
+        <register>
+          <name>priority_23</name>
+          <description>PRIORITY Register for interrupt id 23</description>
+          <addressOffset>0x5C</addressOffset>
+        </register>
+        <register>
+          <name>priority_24</name>
+          <description>PRIORITY Register for interrupt id 24</description>
+          <addressOffset>0x60</addressOffset>
+        </register>
+        <register>
+          <name>priority_25</name>
+          <description>PRIORITY Register for interrupt id 25</description>
+          <addressOffset>0x64</addressOffset>
+        </register>
+        <register>
+          <name>priority_26</name>
+          <description>PRIORITY Register for interrupt id 26</description>
+          <addressOffset>0x68</addressOffset>
+        </register>
+        <register>
+          <name>priority_27</name>
+          <description>PRIORITY Register for interrupt id 27</description>
+          <addressOffset>0x6C</addressOffset>
+        </register>
+        <register>
+          <name>priority_28</name>
+          <description>PRIORITY Register for interrupt id 28</description>
+          <addressOffset>0x70</addressOffset>
+        </register>
+        <register>
+          <name>priority_29</name>
+          <description>PRIORITY Register for interrupt id 29</description>
+          <addressOffset>0x74</addressOffset>
+        </register>
+        <register>
+          <name>priority_30</name>
+          <description>PRIORITY Register for interrupt id 30</description>
+          <addressOffset>0x78</addressOffset>
+        </register>
+        <register>
+          <name>priority_31</name>
+          <description>PRIORITY Register for interrupt id 31</description>
+          <addressOffset>0x7C</addressOffset>
+        </register>
+        <register>
+          <name>priority_32</name>
+          <description>PRIORITY Register for interrupt id 32</description>
+          <addressOffset>0x80</addressOffset>
+        </register>
+        <register>
+          <name>priority_33</name>
+          <description>PRIORITY Register for interrupt id 33</description>
+          <addressOffset>0x84</addressOffset>
+        </register>
+        <register>
+          <name>priority_34</name>
+          <description>PRIORITY Register for interrupt id 34</description>
+          <addressOffset>0x88</addressOffset>
+        </register>
+        <register>
+          <name>priority_35</name>
+          <description>PRIORITY Register for interrupt id 35</description>
+          <addressOffset>0x8C</addressOffset>
+        </register>
+        <register>
+          <name>priority_36</name>
+          <description>PRIORITY Register for interrupt id 36</description>
+          <addressOffset>0x90</addressOffset>
+        </register>
+        <register>
+          <name>priority_37</name>
+          <description>PRIORITY Register for interrupt id 37</description>
+          <addressOffset>0x94</addressOffset>
+        </register>
+        <register>
+          <name>priority_38</name>
+          <description>PRIORITY Register for interrupt id 38</description>
+          <addressOffset>0x98</addressOffset>
+        </register>
+        <register>
+          <name>priority_39</name>
+          <description>PRIORITY Register for interrupt id 39</description>
+          <addressOffset>0x9C</addressOffset>
+        </register>
+        <register>
+          <name>priority_40</name>
+          <description>PRIORITY Register for interrupt id 40</description>
+          <addressOffset>0xA0</addressOffset>
+        </register>
+        <register>
+          <name>priority_41</name>
+          <description>PRIORITY Register for interrupt id 41</description>
+          <addressOffset>0xA4</addressOffset>
+        </register>
+        <register>
+          <name>priority_42</name>
+          <description>PRIORITY Register for interrupt id 42</description>
+          <addressOffset>0xA8</addressOffset>
+        </register>
+        <register>
+          <name>priority_43</name>
+          <description>PRIORITY Register for interrupt id 43</description>
+          <addressOffset>0xAC</addressOffset>
+        </register>
+        <register>
+          <name>priority_44</name>
+          <description>PRIORITY Register for interrupt id 44</description>
+          <addressOffset>0xB0</addressOffset>
+        </register>
+        <register>
+          <name>priority_45</name>
+          <description>PRIORITY Register for interrupt id 45</description>
+          <addressOffset>0xB4</addressOffset>
+        </register>
+        <register>
+          <name>priority_46</name>
+          <description>PRIORITY Register for interrupt id 46</description>
+          <addressOffset>0xB8</addressOffset>
+        </register>
+        <register>
+          <name>priority_47</name>
+          <description>PRIORITY Register for interrupt id 47</description>
+          <addressOffset>0xBC</addressOffset>
+        </register>
+        <register>
+          <name>priority_48</name>
+          <description>PRIORITY Register for interrupt id 48</description>
+          <addressOffset>0xC0</addressOffset>
+        </register>
+        <register>
+          <name>priority_49</name>
+          <description>PRIORITY Register for interrupt id 49</description>
+          <addressOffset>0xC4</addressOffset>
+        </register>
+        <register>
+          <name>priority_50</name>
+          <description>PRIORITY Register for interrupt id 50</description>
+          <addressOffset>0xC8</addressOffset>
+        </register>
+        <register>
+          <name>priority_51</name>
+          <description>PRIORITY Register for interrupt id 51</description>
+          <addressOffset>0xCC</addressOffset>
+        </register>
+        <register>
+          <name>priority_52</name>
+          <description>PRIORITY Register for interrupt id 52</description>
+          <addressOffset>0xD0</addressOffset>
+        </register>
+        <register>
+          <name>pending_0</name>
+          <description>PENDING Register for interrupt ids 31 to 0</description>
+          <addressOffset>0x1000</addressOffset>
+        </register>
+        <register>
+          <name>pending_1</name>
+          <description>PENDING Register for interrupt ids 52 to 32</description>
+          <addressOffset>0x1004</addressOffset>
+        </register>
+        <register>
+          <name>enable_0_0</name>
+          <description>ENABLE Register for interrupt ids 31 to 0 for hart 0</description>
+          <addressOffset>0x2000</addressOffset>
+        </register>
+        <register>
+          <name>enable_1_0</name>
+          <description>ENABLE Register for interrupt ids 52 to 32 for hart 0</description>
+          <addressOffset>0x2004</addressOffset>
+        </register>
+        <register>
+          <name>threshold_0</name>
+          <description>PRIORITY THRESHOLD Register for hart 0</description>
+          <addressOffset>0x200000</addressOffset>
+        </register>
+        <register>
+          <name>claimplete_0</name>
+          <description>CLAIM and COMPLETE Register for hart 0</description>
+          <addressOffset>0x200004</addressOffset>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_aon0_0</name>
+      <description>From sifive,aon0,mem peripheral generator</description>
+      <baseAddress>0x10000000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x8000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>backup_0</name>
+          <description>Backup Register 0</description>
+          <addressOffset>0x80</addressOffset>
+        </register>
+        <register>
+          <name>backup_1</name>
+          <description>Backup Register 1</description>
+          <addressOffset>0x84</addressOffset>
+        </register>
+        <register>
+          <name>backup_2</name>
+          <description>Backup Register 2</description>
+          <addressOffset>0x88</addressOffset>
+        </register>
+        <register>
+          <name>backup_3</name>
+          <description>Backup Register 3</description>
+          <addressOffset>0x8C</addressOffset>
+        </register>
+        <register>
+          <name>backup_4</name>
+          <description>Backup Register 4</description>
+          <addressOffset>0x90</addressOffset>
+        </register>
+        <register>
+          <name>backup_5</name>
+          <description>Backup Register 5</description>
+          <addressOffset>0x94</addressOffset>
+        </register>
+        <register>
+          <name>backup_6</name>
+          <description>Backup Register 6</description>
+          <addressOffset>0x98</addressOffset>
+        </register>
+        <register>
+          <name>backup_7</name>
+          <description>Backup Register 7</description>
+          <addressOffset>0x9C</addressOffset>
+        </register>
+        <register>
+          <name>backup_8</name>
+          <description>Backup Register 8</description>
+          <addressOffset>0xA0</addressOffset>
+        </register>
+        <register>
+          <name>backup_9</name>
+          <description>Backup Register 9</description>
+          <addressOffset>0xA4</addressOffset>
+        </register>
+        <register>
+          <name>backup_10</name>
+          <description>Backup Register 10</description>
+          <addressOffset>0xA8</addressOffset>
+        </register>
+        <register>
+          <name>backup_11</name>
+          <description>Backup Register 11</description>
+          <addressOffset>0xAC</addressOffset>
+        </register>
+        <register>
+          <name>backup_12</name>
+          <description>Backup Register 12</description>
+          <addressOffset>0xB0</addressOffset>
+        </register>
+        <register>
+          <name>backup_13</name>
+          <description>Backup Register 13</description>
+          <addressOffset>0xB4</addressOffset>
+        </register>
+        <register>
+          <name>backup_14</name>
+          <description>Backup Register 14</description>
+          <addressOffset>0xB8</addressOffset>
+        </register>
+        <register>
+          <name>backup_15</name>
+          <description>Backup Register 15</description>
+          <addressOffset>0xBC</addressOffset>
+        </register>
+        <register>
+          <name>wdogcfg</name>
+          <description>wdog Configuration</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>wdogscale</name>
+              <description>Counter scale value.</description>
+              <bitRange>[3:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wdogrsten</name>
+              <description>Controls whether the comparator output can set the wdogrst bit and hence cause a full reset.</description>
+              <bitRange>[8:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wdogzerocmp</name>
+              <description>Reset counter to zero after match.</description>
+              <bitRange>[9:9]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wdogenalways</name>
+              <description>Enable Always - run continuously</description>
+              <bitRange>[12:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wdogcoreawake</name>
+              <description>Increment the watchdog counter if the processor is not asleep</description>
+              <bitRange>[13:13]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wdogip0</name>
+              <description>Interrupt 0 Pending</description>
+              <bitRange>[28:28]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>wdogcount</name>
+          <description>Counter Register</description>
+          <addressOffset>0x8</addressOffset>
+        </register>
+        <register>
+          <name>wdogs</name>
+          <description>Scaled value of Counter</description>
+          <addressOffset>0x10</addressOffset>
+        </register>
+        <register>
+          <name>wdogfeed</name>
+          <description>Feed register</description>
+          <addressOffset>0x18</addressOffset>
+        </register>
+        <register>
+          <name>wdogkey</name>
+          <description>Key Register</description>
+          <addressOffset>0x1C</addressOffset>
+        </register>
+        <register>
+          <name>wdogcmp0</name>
+          <description>Comparator 0</description>
+          <addressOffset>0x20</addressOffset>
+        </register>
+        <register>
+          <name>rtccfg</name>
+          <description>rtc Configuration</description>
+          <addressOffset>0x40</addressOffset>
+          <fields>
+            <field>
+              <name>rtcscale</name>
+              <description>Counter scale value.</description>
+              <bitRange>[3:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rtcenalways</name>
+              <description>Enable Always - run continuously</description>
+              <bitRange>[12:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rtcip0</name>
+              <description>Interrupt 0 Pending</description>
+              <bitRange>[28:28]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rtccountlo</name>
+          <description>Low bits of Counter</description>
+          <addressOffset>0x48</addressOffset>
+        </register>
+        <register>
+          <name>rtccounthi</name>
+          <description>High bits of Counter</description>
+          <addressOffset>0x4C</addressOffset>
+        </register>
+        <register>
+          <name>rtcs</name>
+          <description>Scaled value of Counter</description>
+          <addressOffset>0x50</addressOffset>
+        </register>
+        <register>
+          <name>rtccmp0</name>
+          <description>Comparator 0</description>
+          <addressOffset>0x60</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi0</name>
+          <description>Wakeup program instruction 0</description>
+          <addressOffset>0x100</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi1</name>
+          <description>Wakeup program instruction 1</description>
+          <addressOffset>0x104</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi2</name>
+          <description>Wakeup program instruction 2</description>
+          <addressOffset>0x108</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi3</name>
+          <description>Wakeup program instruction 3</description>
+          <addressOffset>0x10C</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi4</name>
+          <description>Wakeup program instruction 4</description>
+          <addressOffset>0x110</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi5</name>
+          <description>Wakeup program instruction 5</description>
+          <addressOffset>0x114</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi6</name>
+          <description>Wakeup program instruction 6</description>
+          <addressOffset>0x118</addressOffset>
+        </register>
+        <register>
+          <name>pmuwakeupi7</name>
+          <description>Wakeup program instruction 7</description>
+          <addressOffset>0x11C</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi0</name>
+          <description>Sleep program instruction 0</description>
+          <addressOffset>0x120</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi1</name>
+          <description>Sleep program instruction 1</description>
+          <addressOffset>0x124</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi2</name>
+          <description>Sleep program instruction 2</description>
+          <addressOffset>0x128</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi3</name>
+          <description>Sleep program instruction 3</description>
+          <addressOffset>0x12C</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi4</name>
+          <description>Sleep program instruction 4</description>
+          <addressOffset>0x130</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi5</name>
+          <description>Sleep program instruction 5</description>
+          <addressOffset>0x134</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi6</name>
+          <description>Sleep program instruction 6</description>
+          <addressOffset>0x138</addressOffset>
+        </register>
+        <register>
+          <name>pmusleepi7</name>
+          <description>Sleep program instruction 7</description>
+          <addressOffset>0x13C</addressOffset>
+        </register>
+        <register>
+          <name>pmuie</name>
+          <description>PMU Interrupt Enables</description>
+          <addressOffset>0x140</addressOffset>
+        </register>
+        <register>
+          <name>pmucause</name>
+          <description>PMU Wakeup Cause</description>
+          <addressOffset>0x144</addressOffset>
+        </register>
+        <register>
+          <name>pmusleep</name>
+          <description>Initiate PMU Sleep Sequence</description>
+          <addressOffset>0x148</addressOffset>
+        </register>
+        <register>
+          <name>pmukey</name>
+          <description>PMU Key. Reads as 1 when PMU is unlocked</description>
+          <addressOffset>0x14C</addressOffset>
+        </register>
+        <register>
+          <name>aoncfg</name>
+          <description>AON Block Configuration Information</description>
+          <addressOffset>0x300</addressOffset>
+          <fields>
+            <field>
+              <name>has_bandgap</name>
+              <description>Bandgap feature is present</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>has_bod</name>
+              <description>Brownout detector feature is present</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>has_lfrosc</name>
+              <description>Low Frequency Ring Oscillator feature is present</description>
+              <bitRange>[2:2]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>has_lfrcosc</name>
+              <description>Low Frequency RC Oscillator feature is present</description>
+              <bitRange>[3:3]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>has_lfxosc</name>
+              <description>Low Frequency Crystal Oscillator feature is present</description>
+              <bitRange>[4:4]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>has_por</name>
+              <description>Power-On-Reset feature is present</description>
+              <bitRange>[5:5]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>has_ldo</name>
+              <description>Low Dropout Regulator feature is present</description>
+              <bitRange>[6:6]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>lfrosccfg</name>
+          <description>Ring Oscillator Configuration and Status</description>
+          <addressOffset>0x70</addressOffset>
+          <fields>
+            <field>
+              <name>lfroscdiv</name>
+              <description>Ring Oscillator Divider Register</description>
+              <bitRange>[5:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>lfrosctrim</name>
+              <description>Ring Oscillator Trim Register</description>
+              <bitRange>[20:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>lfroscen</name>
+              <description>Ring Oscillator Enable</description>
+              <bitRange>[30:30]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>lfroscrdy</name>
+              <description>Ring Oscillator Ready</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>lfclkmux</name>
+          <description>Low-Frequency Clock Mux Control and Status</description>
+          <addressOffset>0x7C</addressOffset>
+          <fields>
+            <field>
+              <name>lfextclk_sel</name>
+              <description>Low Frequency Clock Source Selector</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+              <enumeratedValues>
+                <enumeratedValue>
+                  <name>internal</name>
+                  <description>Use internal LF clock source</description>
+                  <value>0</value>
+                </enumeratedValue>
+                <enumeratedValue>
+                  <name>external</name>
+                  <description>Use external LF clock source</description>
+                  <value>1</value>
+                </enumeratedValue>
+              </enumeratedValues>
+            </field>
+            <field>
+              <name>lfextclk_mux_status</name>
+              <description>Setting of the aon_lfclksel pin</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+              <enumeratedValues>
+                <enumeratedValue>
+                  <name>external</name>
+                  <description>Use external LF clock source</description>
+                  <value>0</value>
+                </enumeratedValue>
+                <enumeratedValue>
+                  <name>sw</name>
+                  <description>Use clock source selected by lfextclk_sel</description>
+                  <value>1</value>
+                </enumeratedValue>
+              </enumeratedValues>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_fe310_g000_prci_0</name>
+      <description>From sifive,fe310-g000,prci,mem peripheral generator</description>
+      <baseAddress>0x10008000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x8000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>hfrosccfg</name>
+          <description>Ring Oscillator Configuration and Status</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>hfroscdiv</name>
+              <description>Ring Oscillator Divider Register</description>
+              <bitRange>[5:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>hfrosctrim</name>
+              <description>Ring Oscillator Trim Register</description>
+              <bitRange>[20:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>hfroscen</name>
+              <description>Ring Oscillator Enable</description>
+              <bitRange>[30:30]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>hfroscrdy</name>
+              <description>Ring Oscillator Ready</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>hfxosccfg</name>
+          <description>Crystal Oscillator Configuration and Status</description>
+          <addressOffset>0x4</addressOffset>
+          <fields>
+            <field>
+              <name>hfxoscen</name>
+              <description>Crystal Oscillator Enable</description>
+              <bitRange>[30:30]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>hfxoscrdy</name>
+              <description>Crystal Oscillator Ready</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pllcfg</name>
+          <description>PLL Configuration and Status</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>pllr</name>
+              <description>PLL R Value</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pllf</name>
+              <description>PLL F Value</description>
+              <bitRange>[9:4]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pllq</name>
+              <description>PLL Q Value</description>
+              <bitRange>[11:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pllsel</name>
+              <description>PLL Select</description>
+              <bitRange>[16:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pllrefsel</name>
+              <description>PLL Reference Select</description>
+              <bitRange>[17:17]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pllbypass</name>
+              <description>PLL Bypass</description>
+              <bitRange>[18:18]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>plllock</name>
+              <description>PLL Lock</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>plloutdiv</name>
+          <description>PLL Final Divide Configuration</description>
+          <addressOffset>0xC</addressOffset>
+          <fields>
+            <field>
+              <name>plloutdiv</name>
+              <description>PLL Final Divider Value</description>
+              <bitRange>[5:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>plloutdivby1</name>
+              <description>PLL Final Divide By 1</description>
+              <bitRange>[13:8]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>procmoncfg</name>
+          <description>Process Monitor Configuration and Status</description>
+          <addressOffset>0xF0</addressOffset>
+          <fields>
+            <field>
+              <name>procmon_div_sel</name>
+              <description>Proccess Monitor Divider</description>
+              <bitRange>[4:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>procmon_delay_sel</name>
+              <description>Process Monitor Delay Selector</description>
+              <bitRange>[12:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>procmon_en</name>
+              <description>Process Monitor Enable</description>
+              <bitRange>[16:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>procomon_sel</name>
+              <description>Process Monitor Select</description>
+              <bitRange>[25:24]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_gpio0_0</name>
+      <description>From sifive,gpio0,control peripheral generator</description>
+      <baseAddress>0x10012000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>input_val</name>
+          <description>Pin value</description>
+          <addressOffset>0x0</addressOffset>
+        </register>
+        <register>
+          <name>input_en</name>
+          <description>Pin input enable</description>
+          <addressOffset>0x4</addressOffset>
+        </register>
+        <register>
+          <name>output_en</name>
+          <description>Pin output enable</description>
+          <addressOffset>0x8</addressOffset>
+        </register>
+        <register>
+          <name>output_val</name>
+          <description>Output value</description>
+          <addressOffset>0xC</addressOffset>
+        </register>
+        <register>
+          <name>pue</name>
+          <description>Internal pull-up enable</description>
+          <addressOffset>0x10</addressOffset>
+        </register>
+        <register>
+          <name>ds</name>
+          <description>Pin drive strength</description>
+          <addressOffset>0x14</addressOffset>
+        </register>
+        <register>
+          <name>rise_ie</name>
+          <description>Rise interrupt enable</description>
+          <addressOffset>0x18</addressOffset>
+        </register>
+        <register>
+          <name>rise_ip</name>
+          <description>Rise interrupt pending</description>
+          <addressOffset>0x1C</addressOffset>
+        </register>
+        <register>
+          <name>fall_ie</name>
+          <description>Fall interrupt enable</description>
+          <addressOffset>0x20</addressOffset>
+        </register>
+        <register>
+          <name>fall_ip</name>
+          <description>Fall interrupt pending</description>
+          <addressOffset>0x24</addressOffset>
+        </register>
+        <register>
+          <name>high_ie</name>
+          <description>High interrupt enable</description>
+          <addressOffset>0x28</addressOffset>
+        </register>
+        <register>
+          <name>high_ip</name>
+          <description>High interrupt pending</description>
+          <addressOffset>0x2C</addressOffset>
+        </register>
+        <register>
+          <name>low_ie</name>
+          <description>Low interrupt enable</description>
+          <addressOffset>0x30</addressOffset>
+        </register>
+        <register>
+          <name>low_ip</name>
+          <description>Low interrupt pending</description>
+          <addressOffset>0x34</addressOffset>
+        </register>
+        <register>
+          <name>iof_en</name>
+          <description>I/O function enable</description>
+          <addressOffset>0x38</addressOffset>
+        </register>
+        <register>
+          <name>iof_sel</name>
+          <description>I/O function select</description>
+          <addressOffset>0x3C</addressOffset>
+        </register>
+        <register>
+          <name>out_xor</name>
+          <description>Output XOR (invert)</description>
+          <addressOffset>0x40</addressOffset>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_uart0_0</name>
+      <description>From sifive,uart0,control peripheral generator</description>
+      <baseAddress>0x10013000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>txdata</name>
+          <description>Transmit data register</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Transmit data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>full</name>
+              <description>Transmit FIFO full</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxdata</name>
+          <description>Receive data register</description>
+          <addressOffset>0x4</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Received data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>empty</name>
+              <description>Receive FIFO empty</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txctrl</name>
+          <description>Transmit control register</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>txen</name>
+              <description>Transmit enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>nstop</name>
+              <description>Number of stop bits</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>txcnt</name>
+              <description>Transmit watermark level</description>
+              <bitRange>[18:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxctrl</name>
+          <description>Receive control register</description>
+          <addressOffset>0xC</addressOffset>
+          <fields>
+            <field>
+              <name>rxen</name>
+              <description>Receive enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxcnt</name>
+              <description>Receive watermark level</description>
+              <bitRange>[18:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ie</name>
+          <description>UART interrupt enable</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark interrupt enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark interrupt enable</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ip</name>
+          <description>UART interrupt pending</description>
+          <addressOffset>0x14</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark interrupt pending</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark interrupt pending</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>div</name>
+          <description>Baud rate divisor</description>
+          <addressOffset>0x18</addressOffset>
+          <fields>
+            <field>
+              <name>div</name>
+              <description>Baud rate divisor.</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_spi0_0</name>
+      <description>From sifive,spi0,control peripheral generator</description>
+      <baseAddress>0x10014000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>sckdiv</name>
+          <description>Serial clock divisor</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>div</name>
+              <description>Divisor for serial clock.</description>
+              <bitRange>[11:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>sckmode</name>
+          <description>Serial clock mode</description>
+          <addressOffset>0x4</addressOffset>
+          <fields>
+            <field>
+              <name>pha</name>
+              <description>Serial clock phase</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pol</name>
+              <description>Serial clock polarity</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csid</name>
+          <description>Chip select ID</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>csid</name>
+              <description>Chip select ID.</description>
+              <bitRange>[31:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csdef</name>
+          <description>Chip select default</description>
+          <addressOffset>0x14</addressOffset>
+          <fields>
+            <field>
+              <name>csdef</name>
+              <description>Chip select default value. Reset to all-1s.</description>
+              <bitRange>[31:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csmode</name>
+          <description>Chip select mode</description>
+          <addressOffset>0x18</addressOffset>
+          <fields>
+            <field>
+              <name>mode</name>
+              <description>Chip select mode</description>
+              <bitRange>[1:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>delay0</name>
+          <description>Delay control 0</description>
+          <addressOffset>0x28</addressOffset>
+          <fields>
+            <field>
+              <name>cssck</name>
+              <description>CS to SCK Delay</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>sckcs</name>
+              <description>SCK to CS Delay</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>delay1</name>
+          <description>Delay control 1</description>
+          <addressOffset>0x2C</addressOffset>
+          <fields>
+            <field>
+              <name>intercs</name>
+              <description>Minimum CS inactive time</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>interxfr</name>
+              <description>Maximum interframe delay</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>extradel</name>
+          <description>SPI extra sampling delay to increase the SPI frequency</description>
+          <addressOffset>0x38</addressOffset>
+          <fields>
+            <field>
+              <name>coarse</name>
+              <description>Coarse grain sample delay (multiples of system clocks)</description>
+              <bitRange>[11:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>fine</name>
+              <description>Fine grain sample delay (multiples of process-specific buffer delay)</description>
+              <bitRange>[16:12]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>sampledel</name>
+          <description>Number of delay stages from slave to the SPI controller</description>
+          <addressOffset>0x3C</addressOffset>
+          <fields>
+            <field>
+              <name>sd</name>
+              <description>Number of delay stages from slave to SPI controller</description>
+              <bitRange>[4:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>fmt</name>
+          <description>Frame format</description>
+          <addressOffset>0x40</addressOffset>
+          <fields>
+            <field>
+              <name>proto</name>
+              <description>SPI protocol</description>
+              <bitRange>[1:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>endian</name>
+              <description>SPI endianness</description>
+              <bitRange>[2:2]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>dir</name>
+              <description>SPI I/O direction. This is reset to 1 for flash-enabled SPI controllers, 0 otherwise.</description>
+              <bitRange>[3:3]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>len</name>
+              <description>Number of bits per frame</description>
+              <bitRange>[19:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txdata</name>
+          <description>Tx FIFO Data</description>
+          <addressOffset>0x48</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Transmit data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>full</name>
+              <description>FIFO full flag</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxdata</name>
+          <description>Rx FIFO data</description>
+          <addressOffset>0x4C</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Received data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>empty</name>
+              <description>FIFO empty flag</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txmark</name>
+          <description>Tx FIFO watermark</description>
+          <addressOffset>0x50</addressOffset>
+          <fields>
+            <field>
+              <name>txmark</name>
+              <description>Transmit watermark. The reset value is 1 for flash-enabled controllers, 0 otherwise.</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxmark</name>
+          <description>Rx FIFO watermark</description>
+          <addressOffset>0x54</addressOffset>
+          <fields>
+            <field>
+              <name>rxmark</name>
+              <description>Receive watermark</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>fctrl</name>
+          <description>SPI flash interface control</description>
+          <addressOffset>0x60</addressOffset>
+          <fields>
+            <field>
+              <name>en</name>
+              <description>SPI Flash Mode Select</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ffmt</name>
+          <description>SPI flash instruction format</description>
+          <addressOffset>0x64</addressOffset>
+          <fields>
+            <field>
+              <name>cmd_en</name>
+              <description>Enable sending of command</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>addr_len</name>
+              <description>Number of address bytes (0 to 4)</description>
+              <bitRange>[3:1]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pad_cnt</name>
+              <description>Number of dummy cycles</description>
+              <bitRange>[7:4]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>cmd_proto</name>
+              <description>Protocol for transmitting command</description>
+              <bitRange>[9:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>addr_proto</name>
+              <description>Protocol for transmitting address and padding</description>
+              <bitRange>[11:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>data_proto</name>
+              <description>Protocol for receiving data bytes</description>
+              <bitRange>[13:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>cmd_code</name>
+              <description>Value of command byte</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pad_code</name>
+              <description>First 8 bits to transmit during dummy cycles</description>
+              <bitRange>[31:24]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ie</name>
+          <description>SPI interrupt enable</description>
+          <addressOffset>0x70</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark enable</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ip</name>
+          <description>SPI interrupt pending</description>
+          <addressOffset>0x74</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark pending</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark pending</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_pwm0_0</name>
+      <description>From sifive,pwm0,control peripheral generator</description>
+      <baseAddress>0x10015000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>pwmcfg</name>
+          <description>PWM configuration register</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>pwmscale</name>
+              <description>PWM Counter scale</description>
+              <bitRange>[3:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmsticky</name>
+              <description>PWM Sticky - disallow clearing pwmcmpXip bits</description>
+              <bitRange>[8:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmzerocmp</name>
+              <description>PWM Zero - counter resets to zero after match</description>
+              <bitRange>[9:9]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmdeglitch</name>
+              <description>PWM Deglitch - latch pwmcmpXip within same cycle</description>
+              <bitRange>[10:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmenalways</name>
+              <description>PWM enable always - run continuously</description>
+              <bitRange>[12:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmenoneshot</name>
+              <description>PWM enable one shot - run one cycle</description>
+              <bitRange>[13:13]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0center</name>
+              <description>PWM0 Compare Center</description>
+              <bitRange>[16:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1center</name>
+              <description>PWM1 Compare Center</description>
+              <bitRange>[17:17]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2center</name>
+              <description>PWM2 Compare Center</description>
+              <bitRange>[18:18]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3center</name>
+              <description>PWM3 Compare Center</description>
+              <bitRange>[19:19]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0invert</name>
+              <description>PWM0 Invert</description>
+              <bitRange>[20:20]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1invert</name>
+              <description>PWM1 Invert</description>
+              <bitRange>[21:21]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2invert</name>
+              <description>PWM2 Invert</description>
+              <bitRange>[22:22]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3invert</name>
+              <description>PWM3 Invert</description>
+              <bitRange>[23:23]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0gang</name>
+              <description>PWM0/PWM1 Compare Gang</description>
+              <bitRange>[24:24]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1gang</name>
+              <description>PWM1/PWM2 Compare Gang</description>
+              <bitRange>[25:25]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2gang</name>
+              <description>PWM2/PWM3 Compare Gang</description>
+              <bitRange>[26:26]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3gang</name>
+              <description>PWM3/PWM0 Compare Gang</description>
+              <bitRange>[27:27]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0ip</name>
+              <description>PWM0 Interrupt Pending</description>
+              <bitRange>[28:28]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1ip</name>
+              <description>PWM1 Interrupt Pending</description>
+              <bitRange>[29:29]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2ip</name>
+              <description>PWM2 Interrupt Pending</description>
+              <bitRange>[30:30]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3ip</name>
+              <description>PWM3 Interrupt Pending</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcount</name>
+          <description>PWM count register</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcount</name>
+              <description>PWM count register.</description>
+              <bitRange>[30:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwms</name>
+          <description>Scaled PWM count register</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>pwms</name>
+              <description>Scaled PWM count register.</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp0</name>
+          <description>PWM 0 compare register</description>
+          <addressOffset>0x20</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp0</name>
+              <description>PWM 0 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp1</name>
+          <description>PWM 1 compare register</description>
+          <addressOffset>0x24</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp1</name>
+              <description>PWM 1 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp2</name>
+          <description>PWM 2 compare register</description>
+          <addressOffset>0x28</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp2</name>
+              <description>PWM 2 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp3</name>
+          <description>PWM 3 compare register</description>
+          <addressOffset>0x2C</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp3</name>
+              <description>PWM 3 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_i2c0_0</name>
+      <description>From sifive,i2c0,control peripheral generator</description>
+      <baseAddress>0x10016000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>prescale_low</name>
+          <description>Clock Prescale register lo-byte</description>
+          <addressOffset>0x0</addressOffset>
+        </register>
+        <register>
+          <name>prescale_high</name>
+          <description>Clock Prescale register hi-byte</description>
+          <addressOffset>0x4</addressOffset>
+        </register>
+        <register>
+          <name>control</name>
+          <description>Control register</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>en</name>
+              <description>I2C core enable bit</description>
+              <bitRange>[6:6]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>ien</name>
+              <description>I2C core interrupt enable bit</description>
+              <bitRange>[7:7]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>transmit__receive</name>
+          <description>Transmit and receive data byte register</description>
+          <addressOffset>0xC</addressOffset>
+        </register>
+        <register>
+          <name>command__status</name>
+          <description>Command write and status read register</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>wr_iack__rd_if</name>
+              <description>Clear interrupt and Interrupt pending</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_res__rd_tip</name>
+              <description>Reserved and Transfer in progress</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_res__rd_res</name>
+              <description>Reserved and Reserved</description>
+              <bitRange>[2:2]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_ack__rd_res</name>
+              <description>Send ACK/NACK and Reserved</description>
+              <bitRange>[3:3]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_txd__rd_res</name>
+              <description>Transmit data and Reserved</description>
+              <bitRange>[4:4]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_rxd__rd_al</name>
+              <description>Receive data and Arbitration lost</description>
+              <bitRange>[5:5]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_sto__rd_busy</name>
+              <description>Generate stop and I2C bus busy</description>
+              <bitRange>[6:6]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>wr_sta__rd_rxack</name>
+              <description>Generate start and Got ACK/NACK</description>
+              <bitRange>[7:7]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_uart0_1</name>
+      <description>From sifive,uart0,control peripheral generator</description>
+      <baseAddress>0x10023000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>txdata</name>
+          <description>Transmit data register</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Transmit data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>full</name>
+              <description>Transmit FIFO full</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxdata</name>
+          <description>Receive data register</description>
+          <addressOffset>0x4</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Received data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>empty</name>
+              <description>Receive FIFO empty</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txctrl</name>
+          <description>Transmit control register</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>txen</name>
+              <description>Transmit enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>nstop</name>
+              <description>Number of stop bits</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>txcnt</name>
+              <description>Transmit watermark level</description>
+              <bitRange>[18:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxctrl</name>
+          <description>Receive control register</description>
+          <addressOffset>0xC</addressOffset>
+          <fields>
+            <field>
+              <name>rxen</name>
+              <description>Receive enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxcnt</name>
+              <description>Receive watermark level</description>
+              <bitRange>[18:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ie</name>
+          <description>UART interrupt enable</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark interrupt enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark interrupt enable</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ip</name>
+          <description>UART interrupt pending</description>
+          <addressOffset>0x14</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark interrupt pending</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark interrupt pending</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>div</name>
+          <description>Baud rate divisor</description>
+          <addressOffset>0x18</addressOffset>
+          <fields>
+            <field>
+              <name>div</name>
+              <description>Baud rate divisor.</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_spi0_1</name>
+      <description>From sifive,spi0,control peripheral generator</description>
+      <baseAddress>0x10024000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>sckdiv</name>
+          <description>Serial clock divisor</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>div</name>
+              <description>Divisor for serial clock.</description>
+              <bitRange>[11:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>sckmode</name>
+          <description>Serial clock mode</description>
+          <addressOffset>0x4</addressOffset>
+          <fields>
+            <field>
+              <name>pha</name>
+              <description>Serial clock phase</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pol</name>
+              <description>Serial clock polarity</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csid</name>
+          <description>Chip select ID</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>csid</name>
+              <description>Chip select ID.</description>
+              <bitRange>[31:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csdef</name>
+          <description>Chip select default</description>
+          <addressOffset>0x14</addressOffset>
+          <fields>
+            <field>
+              <name>csdef</name>
+              <description>Chip select default value. Reset to all-1s.</description>
+              <bitRange>[31:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csmode</name>
+          <description>Chip select mode</description>
+          <addressOffset>0x18</addressOffset>
+          <fields>
+            <field>
+              <name>mode</name>
+              <description>Chip select mode</description>
+              <bitRange>[1:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>delay0</name>
+          <description>Delay control 0</description>
+          <addressOffset>0x28</addressOffset>
+          <fields>
+            <field>
+              <name>cssck</name>
+              <description>CS to SCK Delay</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>sckcs</name>
+              <description>SCK to CS Delay</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>delay1</name>
+          <description>Delay control 1</description>
+          <addressOffset>0x2C</addressOffset>
+          <fields>
+            <field>
+              <name>intercs</name>
+              <description>Minimum CS inactive time</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>interxfr</name>
+              <description>Maximum interframe delay</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>extradel</name>
+          <description>SPI extra sampling delay to increase the SPI frequency</description>
+          <addressOffset>0x38</addressOffset>
+          <fields>
+            <field>
+              <name>coarse</name>
+              <description>Coarse grain sample delay (multiples of system clocks)</description>
+              <bitRange>[11:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>fine</name>
+              <description>Fine grain sample delay (multiples of process-specific buffer delay)</description>
+              <bitRange>[16:12]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>sampledel</name>
+          <description>Number of delay stages from slave to the SPI controller</description>
+          <addressOffset>0x3C</addressOffset>
+          <fields>
+            <field>
+              <name>sd</name>
+              <description>Number of delay stages from slave to SPI controller</description>
+              <bitRange>[4:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>fmt</name>
+          <description>Frame format</description>
+          <addressOffset>0x40</addressOffset>
+          <fields>
+            <field>
+              <name>proto</name>
+              <description>SPI protocol</description>
+              <bitRange>[1:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>endian</name>
+              <description>SPI endianness</description>
+              <bitRange>[2:2]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>dir</name>
+              <description>SPI I/O direction. This is reset to 1 for flash-enabled SPI controllers, 0 otherwise.</description>
+              <bitRange>[3:3]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>len</name>
+              <description>Number of bits per frame</description>
+              <bitRange>[19:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txdata</name>
+          <description>Tx FIFO Data</description>
+          <addressOffset>0x48</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Transmit data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>full</name>
+              <description>FIFO full flag</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxdata</name>
+          <description>Rx FIFO data</description>
+          <addressOffset>0x4C</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Received data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>empty</name>
+              <description>FIFO empty flag</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txmark</name>
+          <description>Tx FIFO watermark</description>
+          <addressOffset>0x50</addressOffset>
+          <fields>
+            <field>
+              <name>txmark</name>
+              <description>Transmit watermark. The reset value is 1 for flash-enabled controllers, 0 otherwise.</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxmark</name>
+          <description>Rx FIFO watermark</description>
+          <addressOffset>0x54</addressOffset>
+          <fields>
+            <field>
+              <name>rxmark</name>
+              <description>Receive watermark</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>fctrl</name>
+          <description>SPI flash interface control</description>
+          <addressOffset>0x60</addressOffset>
+          <fields>
+            <field>
+              <name>en</name>
+              <description>SPI Flash Mode Select</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ffmt</name>
+          <description>SPI flash instruction format</description>
+          <addressOffset>0x64</addressOffset>
+          <fields>
+            <field>
+              <name>cmd_en</name>
+              <description>Enable sending of command</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>addr_len</name>
+              <description>Number of address bytes (0 to 4)</description>
+              <bitRange>[3:1]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pad_cnt</name>
+              <description>Number of dummy cycles</description>
+              <bitRange>[7:4]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>cmd_proto</name>
+              <description>Protocol for transmitting command</description>
+              <bitRange>[9:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>addr_proto</name>
+              <description>Protocol for transmitting address and padding</description>
+              <bitRange>[11:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>data_proto</name>
+              <description>Protocol for receiving data bytes</description>
+              <bitRange>[13:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>cmd_code</name>
+              <description>Value of command byte</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pad_code</name>
+              <description>First 8 bits to transmit during dummy cycles</description>
+              <bitRange>[31:24]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ie</name>
+          <description>SPI interrupt enable</description>
+          <addressOffset>0x70</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark enable</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ip</name>
+          <description>SPI interrupt pending</description>
+          <addressOffset>0x74</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark pending</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark pending</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_pwm0_1</name>
+      <description>From sifive,pwm0,control peripheral generator</description>
+      <baseAddress>0x10025000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>pwmcfg</name>
+          <description>PWM configuration register</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>pwmscale</name>
+              <description>PWM Counter scale</description>
+              <bitRange>[3:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmsticky</name>
+              <description>PWM Sticky - disallow clearing pwmcmpXip bits</description>
+              <bitRange>[8:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmzerocmp</name>
+              <description>PWM Zero - counter resets to zero after match</description>
+              <bitRange>[9:9]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmdeglitch</name>
+              <description>PWM Deglitch - latch pwmcmpXip within same cycle</description>
+              <bitRange>[10:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmenalways</name>
+              <description>PWM enable always - run continuously</description>
+              <bitRange>[12:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmenoneshot</name>
+              <description>PWM enable one shot - run one cycle</description>
+              <bitRange>[13:13]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0center</name>
+              <description>PWM0 Compare Center</description>
+              <bitRange>[16:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1center</name>
+              <description>PWM1 Compare Center</description>
+              <bitRange>[17:17]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2center</name>
+              <description>PWM2 Compare Center</description>
+              <bitRange>[18:18]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3center</name>
+              <description>PWM3 Compare Center</description>
+              <bitRange>[19:19]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0invert</name>
+              <description>PWM0 Invert</description>
+              <bitRange>[20:20]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1invert</name>
+              <description>PWM1 Invert</description>
+              <bitRange>[21:21]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2invert</name>
+              <description>PWM2 Invert</description>
+              <bitRange>[22:22]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3invert</name>
+              <description>PWM3 Invert</description>
+              <bitRange>[23:23]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0gang</name>
+              <description>PWM0/PWM1 Compare Gang</description>
+              <bitRange>[24:24]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1gang</name>
+              <description>PWM1/PWM2 Compare Gang</description>
+              <bitRange>[25:25]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2gang</name>
+              <description>PWM2/PWM3 Compare Gang</description>
+              <bitRange>[26:26]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3gang</name>
+              <description>PWM3/PWM0 Compare Gang</description>
+              <bitRange>[27:27]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0ip</name>
+              <description>PWM0 Interrupt Pending</description>
+              <bitRange>[28:28]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1ip</name>
+              <description>PWM1 Interrupt Pending</description>
+              <bitRange>[29:29]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2ip</name>
+              <description>PWM2 Interrupt Pending</description>
+              <bitRange>[30:30]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3ip</name>
+              <description>PWM3 Interrupt Pending</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcount</name>
+          <description>PWM count register</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcount</name>
+              <description>PWM count register.</description>
+              <bitRange>[30:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwms</name>
+          <description>Scaled PWM count register</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>pwms</name>
+              <description>Scaled PWM count register.</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp0</name>
+          <description>PWM 0 compare register</description>
+          <addressOffset>0x20</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp0</name>
+              <description>PWM 0 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp1</name>
+          <description>PWM 1 compare register</description>
+          <addressOffset>0x24</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp1</name>
+              <description>PWM 1 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp2</name>
+          <description>PWM 2 compare register</description>
+          <addressOffset>0x28</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp2</name>
+              <description>PWM 2 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp3</name>
+          <description>PWM 3 compare register</description>
+          <addressOffset>0x2C</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp3</name>
+              <description>PWM 3 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_spi0_2</name>
+      <description>From sifive,spi0,control peripheral generator</description>
+      <baseAddress>0x10034000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>sckdiv</name>
+          <description>Serial clock divisor</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>div</name>
+              <description>Divisor for serial clock.</description>
+              <bitRange>[11:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>sckmode</name>
+          <description>Serial clock mode</description>
+          <addressOffset>0x4</addressOffset>
+          <fields>
+            <field>
+              <name>pha</name>
+              <description>Serial clock phase</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pol</name>
+              <description>Serial clock polarity</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csid</name>
+          <description>Chip select ID</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>csid</name>
+              <description>Chip select ID.</description>
+              <bitRange>[31:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csdef</name>
+          <description>Chip select default</description>
+          <addressOffset>0x14</addressOffset>
+          <fields>
+            <field>
+              <name>csdef</name>
+              <description>Chip select default value. Reset to all-1s.</description>
+              <bitRange>[31:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>csmode</name>
+          <description>Chip select mode</description>
+          <addressOffset>0x18</addressOffset>
+          <fields>
+            <field>
+              <name>mode</name>
+              <description>Chip select mode</description>
+              <bitRange>[1:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>delay0</name>
+          <description>Delay control 0</description>
+          <addressOffset>0x28</addressOffset>
+          <fields>
+            <field>
+              <name>cssck</name>
+              <description>CS to SCK Delay</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>sckcs</name>
+              <description>SCK to CS Delay</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>delay1</name>
+          <description>Delay control 1</description>
+          <addressOffset>0x2C</addressOffset>
+          <fields>
+            <field>
+              <name>intercs</name>
+              <description>Minimum CS inactive time</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>interxfr</name>
+              <description>Maximum interframe delay</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>extradel</name>
+          <description>SPI extra sampling delay to increase the SPI frequency</description>
+          <addressOffset>0x38</addressOffset>
+          <fields>
+            <field>
+              <name>coarse</name>
+              <description>Coarse grain sample delay (multiples of system clocks)</description>
+              <bitRange>[11:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>fine</name>
+              <description>Fine grain sample delay (multiples of process-specific buffer delay)</description>
+              <bitRange>[16:12]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>sampledel</name>
+          <description>Number of delay stages from slave to the SPI controller</description>
+          <addressOffset>0x3C</addressOffset>
+          <fields>
+            <field>
+              <name>sd</name>
+              <description>Number of delay stages from slave to SPI controller</description>
+              <bitRange>[4:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>fmt</name>
+          <description>Frame format</description>
+          <addressOffset>0x40</addressOffset>
+          <fields>
+            <field>
+              <name>proto</name>
+              <description>SPI protocol</description>
+              <bitRange>[1:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>endian</name>
+              <description>SPI endianness</description>
+              <bitRange>[2:2]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>dir</name>
+              <description>SPI I/O direction. This is reset to 1 for flash-enabled SPI controllers, 0 otherwise.</description>
+              <bitRange>[3:3]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>len</name>
+              <description>Number of bits per frame</description>
+              <bitRange>[19:16]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txdata</name>
+          <description>Tx FIFO Data</description>
+          <addressOffset>0x48</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Transmit data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>full</name>
+              <description>FIFO full flag</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxdata</name>
+          <description>Rx FIFO data</description>
+          <addressOffset>0x4C</addressOffset>
+          <fields>
+            <field>
+              <name>data</name>
+              <description>Received data</description>
+              <bitRange>[7:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>empty</name>
+              <description>FIFO empty flag</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>txmark</name>
+          <description>Tx FIFO watermark</description>
+          <addressOffset>0x50</addressOffset>
+          <fields>
+            <field>
+              <name>txmark</name>
+              <description>Transmit watermark. The reset value is 1 for flash-enabled controllers, 0 otherwise.</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>rxmark</name>
+          <description>Rx FIFO watermark</description>
+          <addressOffset>0x54</addressOffset>
+          <fields>
+            <field>
+              <name>rxmark</name>
+              <description>Receive watermark</description>
+              <bitRange>[2:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>fctrl</name>
+          <description>SPI flash interface control</description>
+          <addressOffset>0x60</addressOffset>
+          <fields>
+            <field>
+              <name>en</name>
+              <description>SPI Flash Mode Select</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ffmt</name>
+          <description>SPI flash instruction format</description>
+          <addressOffset>0x64</addressOffset>
+          <fields>
+            <field>
+              <name>cmd_en</name>
+              <description>Enable sending of command</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>addr_len</name>
+              <description>Number of address bytes (0 to 4)</description>
+              <bitRange>[3:1]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pad_cnt</name>
+              <description>Number of dummy cycles</description>
+              <bitRange>[7:4]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>cmd_proto</name>
+              <description>Protocol for transmitting command</description>
+              <bitRange>[9:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>addr_proto</name>
+              <description>Protocol for transmitting address and padding</description>
+              <bitRange>[11:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>data_proto</name>
+              <description>Protocol for receiving data bytes</description>
+              <bitRange>[13:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>cmd_code</name>
+              <description>Value of command byte</description>
+              <bitRange>[23:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pad_code</name>
+              <description>First 8 bits to transmit during dummy cycles</description>
+              <bitRange>[31:24]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ie</name>
+          <description>SPI interrupt enable</description>
+          <addressOffset>0x70</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark enable</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark enable</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>ip</name>
+          <description>SPI interrupt pending</description>
+          <addressOffset>0x74</addressOffset>
+          <fields>
+            <field>
+              <name>txwm</name>
+              <description>Transmit watermark pending</description>
+              <bitRange>[0:0]</bitRange>
+              <access>read-only</access>
+            </field>
+            <field>
+              <name>rxwm</name>
+              <description>Receive watermark pending</description>
+              <bitRange>[1:1]</bitRange>
+              <access>read-only</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+    <peripheral>
+      <name>sifive_pwm0_2</name>
+      <description>From sifive,pwm0,control peripheral generator</description>
+      <baseAddress>0x10035000</baseAddress>
+      <addressBlock>
+        <offset>0</offset>
+        <size>0x1000</size>
+        <usage>registers</usage>
+      </addressBlock>
+      <registers>
+        <register>
+          <name>pwmcfg</name>
+          <description>PWM configuration register</description>
+          <addressOffset>0x0</addressOffset>
+          <fields>
+            <field>
+              <name>pwmscale</name>
+              <description>PWM Counter scale</description>
+              <bitRange>[3:0]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmsticky</name>
+              <description>PWM Sticky - disallow clearing pwmcmpXip bits</description>
+              <bitRange>[8:8]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmzerocmp</name>
+              <description>PWM Zero - counter resets to zero after match</description>
+              <bitRange>[9:9]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmdeglitch</name>
+              <description>PWM Deglitch - latch pwmcmpXip within same cycle</description>
+              <bitRange>[10:10]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmenalways</name>
+              <description>PWM enable always - run continuously</description>
+              <bitRange>[12:12]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmenoneshot</name>
+              <description>PWM enable one shot - run one cycle</description>
+              <bitRange>[13:13]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0center</name>
+              <description>PWM0 Compare Center</description>
+              <bitRange>[16:16]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1center</name>
+              <description>PWM1 Compare Center</description>
+              <bitRange>[17:17]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2center</name>
+              <description>PWM2 Compare Center</description>
+              <bitRange>[18:18]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3center</name>
+              <description>PWM3 Compare Center</description>
+              <bitRange>[19:19]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0invert</name>
+              <description>PWM0 Invert</description>
+              <bitRange>[20:20]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1invert</name>
+              <description>PWM1 Invert</description>
+              <bitRange>[21:21]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2invert</name>
+              <description>PWM2 Invert</description>
+              <bitRange>[22:22]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3invert</name>
+              <description>PWM3 Invert</description>
+              <bitRange>[23:23]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0gang</name>
+              <description>PWM0/PWM1 Compare Gang</description>
+              <bitRange>[24:24]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1gang</name>
+              <description>PWM1/PWM2 Compare Gang</description>
+              <bitRange>[25:25]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2gang</name>
+              <description>PWM2/PWM3 Compare Gang</description>
+              <bitRange>[26:26]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3gang</name>
+              <description>PWM3/PWM0 Compare Gang</description>
+              <bitRange>[27:27]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp0ip</name>
+              <description>PWM0 Interrupt Pending</description>
+              <bitRange>[28:28]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp1ip</name>
+              <description>PWM1 Interrupt Pending</description>
+              <bitRange>[29:29]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp2ip</name>
+              <description>PWM2 Interrupt Pending</description>
+              <bitRange>[30:30]</bitRange>
+              <access>read-write</access>
+            </field>
+            <field>
+              <name>pwmcmp3ip</name>
+              <description>PWM3 Interrupt Pending</description>
+              <bitRange>[31:31]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcount</name>
+          <description>PWM count register</description>
+          <addressOffset>0x8</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcount</name>
+              <description>PWM count register.</description>
+              <bitRange>[30:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwms</name>
+          <description>Scaled PWM count register</description>
+          <addressOffset>0x10</addressOffset>
+          <fields>
+            <field>
+              <name>pwms</name>
+              <description>Scaled PWM count register.</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp0</name>
+          <description>PWM 0 compare register</description>
+          <addressOffset>0x20</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp0</name>
+              <description>PWM 0 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp1</name>
+          <description>PWM 1 compare register</description>
+          <addressOffset>0x24</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp1</name>
+              <description>PWM 1 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp2</name>
+          <description>PWM 2 compare register</description>
+          <addressOffset>0x28</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp2</name>
+              <description>PWM 2 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+        <register>
+          <name>pwmcmp3</name>
+          <description>PWM 3 compare register</description>
+          <addressOffset>0x2C</addressOffset>
+          <fields>
+            <field>
+              <name>pwmcmp3</name>
+              <description>PWM 3 Compare Value</description>
+              <bitRange>[15:0]</bitRange>
+              <access>read-write</access>
+            </field>
+          </fields>
+        </register>
+      </registers>
+    </peripheral>
+  </peripherals>
+</device>
\ No newline at end of file
diff --git a/bsp/sparkfun-redv/metal-inline.h b/bsp/sparkfun-redv/metal-inline.h
new file mode 100644
index 00000000..7933a9c4
--- /dev/null
+++ b/bsp/sparkfun-redv/metal-inline.h
@@ -0,0 +1,374 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef ASSEMBLY
+
+#ifndef METAL_INLINE_H
+#define METAL_INLINE_H
+
+#include <metal/machine.h>
+
+
+/* --------------------- fixed_clock ------------ */
+extern __inline__ unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock);
+
+
+/* --------------------- fixed_factor_clock ------------ */
+
+
+/* --------------------- sifive_clint0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller);
+extern __inline__ unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller);
+extern __inline__ int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx);
+extern __inline__ int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx);
+
+
+/* --------------------- cpu ------------ */
+extern __inline__ int __metal_driver_cpu_hartid(struct metal_cpu *cpu);
+extern __inline__ int __metal_driver_cpu_timebase(struct metal_cpu *cpu);
+extern __inline__ struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu);
+extern __inline__ int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu);
+extern __inline__ struct metal_buserror * __metal_driver_cpu_buserror(struct metal_cpu *cpu);
+
+
+/* --------------------- sifive_plic0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller);
+extern __inline__ unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller);
+extern __inline__ int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller);
+extern __inline__ int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx);
+extern __inline__ int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx);
+extern __inline__ int __metal_driver_sifive_plic0_context_ids(int hartid);
+
+
+/* --------------------- sifive_buserror0 ------------ */
+
+
+/* --------------------- sifive_clic0 ------------ */
+
+
+/* --------------------- sifive_local_external_interrupts0 ------------ */
+
+
+/* --------------------- sifive_global_external_interrupts0 ------------ */
+
+
+/* --------------------- sifive_gpio0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio);
+extern __inline__ unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio);
+extern __inline__ int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio);
+extern __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx);
+
+
+/* --------------------- sifive_gpio_button ------------ */
+
+
+/* --------------------- sifive_gpio_led ------------ */
+extern __inline__ struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led);
+extern __inline__ int __metal_driver_sifive_gpio_led_pin(struct metal_led *led);
+extern __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *led);
+
+
+/* --------------------- sifive_gpio_switch ------------ */
+
+
+/* --------------------- sifive_i2c0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_base(struct metal_i2c *i2c);
+extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_size(struct metal_i2c *i2c);
+extern __inline__ int __metal_driver_sifive_i2c0_num_interrupts(struct metal_i2c *i2c);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_i2c0_interrupt_parent(struct metal_i2c *i2c);
+extern __inline__ int __metal_driver_sifive_i2c0_interrupt_line(struct metal_i2c *i2c);
+extern __inline__ struct metal_clock * __metal_driver_sifive_i2c0_clock(struct metal_i2c *i2c);
+extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_i2c0_pinmux(struct metal_i2c *i2c);
+extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_output_selector(struct metal_i2c *i2c);
+extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_source_selector(struct metal_i2c *i2c);
+
+
+/* --------------------- sifive_pwm0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm);
+extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm);
+extern __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm);
+extern __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx);
+extern __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm);
+extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm);
+extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm);
+extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm);
+extern __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm);
+extern __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm);
+
+
+/* --------------------- sifive_rtc0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc);
+extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_rtc0_interrupt_parent(const struct metal_rtc *const rtc);
+extern __inline__ int __metal_driver_sifive_rtc0_interrupt_line(const struct metal_rtc *const rtc);
+extern __inline__ struct metal_clock * __metal_driver_sifive_rtc0_clock(const struct metal_rtc *const rtc);
+
+
+/* --------------------- sifive_spi0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi);
+extern __inline__ unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi);
+extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi);
+extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi);
+extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi);
+
+
+/* --------------------- sifive_test0 ------------ */
+
+
+/* --------------------- sifive_trace ------------ */
+
+/* --------------------- sifive_uart0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart);
+extern __inline__ unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart);
+extern __inline__ int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart);
+extern __inline__ int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart);
+extern __inline__ struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart);
+extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart);
+extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart);
+extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart);
+
+
+/* --------------------- sifive_simuart0 ------------ */
+
+
+/* --------------------- sifive_wdog0 ------------ */
+extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_base(const struct metal_watchdog *const watchdog);
+extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_size(const struct metal_watchdog *const watchdog);
+extern __inline__ struct metal_interrupt * __metal_driver_sifive_wdog0_interrupt_parent(const struct metal_watchdog *const watchdog);
+extern __inline__ int __metal_driver_sifive_wdog0_interrupt_line(const struct metal_watchdog *const watchdog);
+extern __inline__ struct metal_clock * __metal_driver_sifive_wdog0_clock(const struct metal_watchdog *const watchdog);
+
+
+/* --------------------- sifive_fe310_g000_hfrosc ------------ */
+extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock);
+extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock);
+extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock);
+extern __inline__ long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock);
+
+
+/* --------------------- sifive_fe310_g000_hfxosc ------------ */
+extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock);
+extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock);
+extern __inline__ long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock);
+
+
+/* --------------------- sifive_fe310_g000_lfrosc ------------ */
+extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(const struct metal_clock *clock);
+extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(const struct metal_clock *clock);
+extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_config_reg(const struct metal_clock *clock);
+extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(const struct metal_clock *clock);
+
+
+/* --------------------- sifive_fe310_g000_pll ------------ */
+extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock);
+extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock);
+extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( );
+extern __inline__ long __metal_driver_sifive_fe310_g000_pll_config_offset( );
+extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock);
+extern __inline__ long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock);
+extern __inline__ long __metal_driver_sifive_fe310_g000_pll_init_rate( );
+
+
+/* --------------------- fe310_g000_prci ------------ */
+extern __inline__ long __metal_driver_sifive_fe310_g000_prci_base( );
+extern __inline__ long __metal_driver_sifive_fe310_g000_prci_size( );
+extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( );
+
+
+/* From clock@0 */
+struct __metal_driver_fixed_clock __metal_dt_clock_0 = {
+    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
+};
+
+/* From clock@2 */
+struct __metal_driver_fixed_clock __metal_dt_clock_2 = {
+    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
+};
+
+/* From clock@5 */
+struct __metal_driver_fixed_clock __metal_dt_clock_5 = {
+    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
+};
+
+/* From clock@6 */
+struct __metal_driver_fixed_clock __metal_dt_clock_6 = {
+    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
+};
+
+struct metal_memory __metal_dt_mem_dtim_80000000 = {
+    ._base_address = 2147483648UL,
+    ._size = 16384UL,
+    ._attrs = {
+        .R = 1,
+        .W = 1,
+        .X = 1,
+        .C = 1,
+        .A = 1},
+};
+
+struct metal_memory __metal_dt_mem_itim_8000000 = {
+    ._base_address = 134217728UL,
+    ._size = 8192UL,
+    ._attrs = {
+        .R = 1,
+        .W = 1,
+        .X = 1,
+        .C = 1,
+        .A = 1},
+};
+
+struct metal_memory __metal_dt_mem_spi_10014000 = {
+    ._base_address = 536870912UL,
+    ._size = 500000UL,
+    ._attrs = {
+        .R = 1,
+        .W = 1,
+        .X = 1,
+        .C = 1,
+        .A = 1},
+};
+
+struct metal_memory __metal_dt_mem_spi_10024000 = {
+    ._attrs = {
+        .R = 1,
+        .W = 1,
+        .X = 1,
+        .C = 1,
+        .A = 1},
+};
+
+struct metal_memory __metal_dt_mem_spi_10034000 = {
+    ._attrs = {
+        .R = 1,
+        .W = 1,
+        .X = 1,
+        .C = 1,
+        .A = 1},
+};
+
+/* From clint@2000000 */
+struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = {
+    .controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable,
+    .init_done = 0,
+};
+
+/* From cpu@0 */
+struct __metal_driver_cpu __metal_dt_cpu_0 = {
+    .cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable,
+    .hpm_count = 0,
+};
+
+/* From interrupt_controller */
+struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller = {
+    .controller.vtable = &__metal_driver_vtable_riscv_cpu_intc.controller_vtable,
+    .init_done = 0,
+};
+
+/* From interrupt_controller@c000000 */
+struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = {
+    .controller.vtable = &__metal_driver_vtable_riscv_plic0.plic_vtable,
+    .init_done = 0,
+};
+
+struct metal_pmp __metal_dt_pmp;
+
+/* From gpio@10012000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = {
+    .gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio,
+};
+
+/* From led@0 */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0 = {
+    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From i2c@10016000 */
+struct __metal_driver_sifive_i2c0 __metal_dt_i2c_10016000 = {
+    .i2c.vtable = &__metal_driver_vtable_sifive_i2c0.i2c,
+};
+
+/* From pwm@10015000 */
+struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000 = {
+    .pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
+};
+
+/* From pwm@10025000 */
+struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10025000 = {
+    .pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
+};
+
+/* From pwm@10035000 */
+struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10035000 = {
+    .pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
+};
+
+/* From aon@10000000 */
+struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000 = {
+    .rtc.vtable = &__metal_driver_vtable_sifive_rtc0.rtc,
+};
+
+/* From spi@10014000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = {
+    .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
+};
+
+/* From spi@10024000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10024000 = {
+    .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
+};
+
+/* From spi@10034000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10034000 = {
+    .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
+};
+
+/* From serial@10013000 */
+struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000 = {
+    .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
+};
+
+/* From serial@10023000 */
+struct __metal_driver_sifive_uart0 __metal_dt_serial_10023000 = {
+    .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
+};
+
+/* From aon@10000000 */
+struct __metal_driver_sifive_wdog0 __metal_dt_aon_10000000 = {
+    .watchdog.vtable = &__metal_driver_vtable_sifive_wdog0.watchdog,
+};
+
+/* From clock@3 */
+struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3 = {
+    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfrosc.clock,
+};
+
+/* From clock@1 */
+struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1 = {
+    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfxosc.clock,
+};
+
+/* From clock@7 */
+struct __metal_driver_sifive_fe310_g000_lfrosc __metal_dt_clock_7 = {
+    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_lfrosc.clock,
+};
+
+/* From clock@4 */
+struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = {
+    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_pll.clock,
+};
+
+/* From prci@10008000 */
+struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000 = {
+    .vtable = &__metal_driver_vtable_sifive_fe310_g000_prci,
+};
+
+
+#endif /* METAL_INLINE_H*/
+#endif /* ! ASSEMBLY */
diff --git a/bsp/sparkfun-redv/metal-platform.h b/bsp/sparkfun-redv/metal-platform.h
new file mode 100644
index 00000000..6ac62600
--- /dev/null
+++ b/bsp/sparkfun-redv/metal-platform.h
@@ -0,0 +1,298 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef METAL_PLATFORM_H
+#define METAL_PLATFORM_H
+
+/* From clock@0 */
+#define METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY 16000000UL
+
+/* From clock@2 */
+#define METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY 72000000UL
+
+/* From clock@5 */
+#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32768UL
+
+/* From clock@6 */
+#define METAL_FIXED_CLOCK_6_CLOCK_FREQUENCY 32768UL
+
+#define METAL_FIXED_CLOCK
+
+/* From clint@2000000 */
+#define METAL_RISCV_CLINT0_2000000_BASE_ADDRESS 33554432UL
+#define METAL_RISCV_CLINT0_0_BASE_ADDRESS 33554432UL
+#define METAL_RISCV_CLINT0_2000000_SIZE 65536UL
+#define METAL_RISCV_CLINT0_0_SIZE 65536UL
+
+#define METAL_RISCV_CLINT0
+#define METAL_RISCV_CLINT0_MSIP_BASE 0UL
+#define METAL_RISCV_CLINT0_MTIMECMP_BASE 16384UL
+#define METAL_RISCV_CLINT0_MTIME 49144UL
+
+/* From interrupt_controller@c000000 */
+#define METAL_RISCV_PLIC0_C000000_BASE_ADDRESS 201326592UL
+#define METAL_RISCV_PLIC0_0_BASE_ADDRESS 201326592UL
+#define METAL_RISCV_PLIC0_C000000_SIZE 67108864UL
+#define METAL_RISCV_PLIC0_0_SIZE 67108864UL
+#define METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY 7UL
+#define METAL_RISCV_PLIC0_0_RISCV_MAX_PRIORITY 7UL
+#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 53UL
+#define METAL_RISCV_PLIC0_0_RISCV_NDEV 53UL
+
+#define METAL_RISCV_PLIC0
+#define METAL_RISCV_PLIC0_PRIORITY_BASE 0UL
+#define METAL_RISCV_PLIC0_PENDING_BASE 4096UL
+#define METAL_RISCV_PLIC0_ENABLE_BASE 8192UL
+#define METAL_RISCV_PLIC0_ENABLE_PER_HART 128UL
+#define METAL_RISCV_PLIC0_CONTEXT_BASE 2097152UL
+#define METAL_RISCV_PLIC0_CONTEXT_PER_HART 4096UL
+#define METAL_RISCV_PLIC0_CONTEXT_THRESHOLD 0UL
+#define METAL_RISCV_PLIC0_CONTEXT_CLAIM 4UL
+
+/* From aon@10000000 */
+#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
+#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
+#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
+#define METAL_SIFIVE_AON0_0_SIZE 32768UL
+
+#define METAL_SIFIVE_AON0
+#define METAL_SIFIVE_AON0_WDOGCFG 0UL
+#define METAL_SIFIVE_AON0_WDOGCOUNT 8UL
+#define METAL_SIFIVE_AON0_WDOGS 16UL
+#define METAL_SIFIVE_AON0_WDOGFEED 24UL
+#define METAL_SIFIVE_AON0_WDOGKEY 28UL
+#define METAL_SIFIVE_AON0_WDOGCMP 32UL
+#define METAL_SIFIVE_AON0_RTCCFG 64UL
+#define METAL_SIFIVE_AON0_RTCLO 72UL
+#define METAL_SIFIVE_AON0_RTCHI 72UL
+#define METAL_SIFIVE_AON0_RTCS 80UL
+#define METAL_SIFIVE_AON0_RTCCMP 96UL
+#define METAL_SIFIVE_AON0_LFROSCCFG 112UL
+#define METAL_SIFIVE_AON0_BACKUP0 128UL
+#define METAL_SIFIVE_AON0_BACKUP1 132UL
+#define METAL_SIFIVE_AON0_BACKUP2 136UL
+#define METAL_SIFIVE_AON0_BACKUP3 140UL
+#define METAL_SIFIVE_AON0_BACKUP4 144UL
+#define METAL_SIFIVE_AON0_BACKUP5 148UL
+#define METAL_SIFIVE_AON0_BACKUP6 152UL
+#define METAL_SIFIVE_AON0_BACKUP7 152UL
+#define METAL_SIFIVE_AON0_BACKUP8 160UL
+#define METAL_SIFIVE_AON0_BACKUP9 164UL
+#define METAL_SIFIVE_AON0_BACKUP10 168UL
+#define METAL_SIFIVE_AON0_BACKUP11 172UL
+#define METAL_SIFIVE_AON0_BACKUP12 176UL
+#define METAL_SIFIVE_AON0_BACKUP13 180UL
+#define METAL_SIFIVE_AON0_BACKUP14 184UL
+#define METAL_SIFIVE_AON0_BACKUP15 188UL
+#define METAL_SIFIVE_AON0_BACKUP16 192UL
+#define METAL_SIFIVE_AON0_BACKUP17 196UL
+#define METAL_SIFIVE_AON0_BACKUP18 200UL
+#define METAL_SIFIVE_AON0_BACKUP19 204UL
+#define METAL_SIFIVE_AON0_BACKUP20 208UL
+#define METAL_SIFIVE_AON0_BACKUP21 212UL
+#define METAL_SIFIVE_AON0_BACKUP22 216UL
+#define METAL_SIFIVE_AON0_BACKUP23 220UL
+#define METAL_SIFIVE_AON0_BACKUP24 224UL
+#define METAL_SIFIVE_AON0_BACKUP25 228UL
+#define METAL_SIFIVE_AON0_BACKUP26 232UL
+#define METAL_SIFIVE_AON0_BACKUP27 236UL
+#define METAL_SIFIVE_AON0_BACKUP28 240UL
+#define METAL_SIFIVE_AON0_BACKUP29 244UL
+#define METAL_SIFIVE_AON0_BACKUP30 248UL
+#define METAL_SIFIVE_AON0_BACKUP31 252UL
+#define METAL_SIFIVE_AON0_PMU_WAKEUP_BASE 256UL
+#define METAL_SIFIVE_AON0_PWM_SLEEP_BASE 288UL
+#define METAL_SIFIVE_AON0_PMUIE 320UL
+#define METAL_SIFIVE_AON0_PMUCAUSE 324UL
+#define METAL_SIFIVE_AON0_PMUSLEEP 328UL
+#define METAL_SIFIVE_AON0_PMUKEY 332UL
+
+/* From clock@3 */
+
+#define METAL_SIFIVE_FE310_G000_HFROSC
+
+/* From clock@1 */
+
+#define METAL_SIFIVE_FE310_G000_HFXOSC
+
+/* From clock@7 */
+
+#define METAL_SIFIVE_FE310_G000_LFROSC
+
+/* From prci@10008000 */
+#define METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS 268468224UL
+#define METAL_SIFIVE_FE310_G000_PRCI_0_BASE_ADDRESS 268468224UL
+#define METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE 32768UL
+#define METAL_SIFIVE_FE310_G000_PRCI_0_SIZE 32768UL
+
+#define METAL_SIFIVE_FE310_G000_PRCI
+#define METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG 0UL
+#define METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG 4UL
+#define METAL_SIFIVE_FE310_G000_PRCI_PLLCFG 8UL
+#define METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV 12UL
+
+/* From clock@4 */
+#define METAL_SIFIVE_FE310_G000_PLL_4_CLOCK_FREQUENCY 16000000UL
+
+#define METAL_SIFIVE_FE310_G000_PLL
+
+/* From gpio@10012000 */
+#define METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS 268509184UL
+#define METAL_SIFIVE_GPIO0_0_BASE_ADDRESS 268509184UL
+#define METAL_SIFIVE_GPIO0_10012000_SIZE 4096UL
+#define METAL_SIFIVE_GPIO0_0_SIZE 4096UL
+
+#define METAL_SIFIVE_GPIO0
+#define METAL_SIFIVE_GPIO0_VALUE 0UL
+#define METAL_SIFIVE_GPIO0_INPUT_EN 4UL
+#define METAL_SIFIVE_GPIO0_OUTPUT_EN 8UL
+#define METAL_SIFIVE_GPIO0_PORT 12UL
+#define METAL_SIFIVE_GPIO0_PUE 16UL
+#define METAL_SIFIVE_GPIO0_DS 20UL
+#define METAL_SIFIVE_GPIO0_RISE_IE 24UL
+#define METAL_SIFIVE_GPIO0_RISE_IP 28UL
+#define METAL_SIFIVE_GPIO0_FALL_IE 32UL
+#define METAL_SIFIVE_GPIO0_FALL_IP 36UL
+#define METAL_SIFIVE_GPIO0_HIGH_IE 40UL
+#define METAL_SIFIVE_GPIO0_HIGH_IP 44UL
+#define METAL_SIFIVE_GPIO0_LOW_IE 48UL
+#define METAL_SIFIVE_GPIO0_LOW_IP 52UL
+#define METAL_SIFIVE_GPIO0_IOF_EN 56UL
+#define METAL_SIFIVE_GPIO0_IOF_SEL 60UL
+#define METAL_SIFIVE_GPIO0_OUT_XOR 64UL
+
+/* From led@0 */
+
+#define METAL_SIFIVE_GPIO_LEDS
+
+/* From i2c@10016000 */
+#define METAL_SIFIVE_I2C0_10016000_BASE_ADDRESS 268525568UL
+#define METAL_SIFIVE_I2C0_0_BASE_ADDRESS 268525568UL
+#define METAL_SIFIVE_I2C0_10016000_SIZE 4096UL
+#define METAL_SIFIVE_I2C0_0_SIZE 4096UL
+
+#define METAL_SIFIVE_I2C0
+#define METAL_SIFIVE_I2C0_PRESCALE_LOW 0UL
+#define METAL_SIFIVE_I2C0_PRESCALE_HIGH 4UL
+#define METAL_SIFIVE_I2C0_CONTROL 8UL
+#define METAL_SIFIVE_I2C0_TRANSMIT 12UL
+#define METAL_SIFIVE_I2C0_RECEIVE 12UL
+#define METAL_SIFIVE_I2C0_COMMAND 16UL
+#define METAL_SIFIVE_I2C0_STATUS 16UL
+
+/* From pwm@10015000 */
+#define METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS 268521472UL
+#define METAL_SIFIVE_PWM0_0_BASE_ADDRESS 268521472UL
+#define METAL_SIFIVE_PWM0_10015000_SIZE 4096UL
+#define METAL_SIFIVE_PWM0_0_SIZE 4096UL
+
+/* From pwm@10025000 */
+#define METAL_SIFIVE_PWM0_10025000_BASE_ADDRESS 268587008UL
+#define METAL_SIFIVE_PWM0_1_BASE_ADDRESS 268587008UL
+#define METAL_SIFIVE_PWM0_10025000_SIZE 4096UL
+#define METAL_SIFIVE_PWM0_1_SIZE 4096UL
+
+/* From pwm@10035000 */
+#define METAL_SIFIVE_PWM0_10035000_BASE_ADDRESS 268652544UL
+#define METAL_SIFIVE_PWM0_2_BASE_ADDRESS 268652544UL
+#define METAL_SIFIVE_PWM0_10035000_SIZE 4096UL
+#define METAL_SIFIVE_PWM0_2_SIZE 4096UL
+
+#define METAL_SIFIVE_PWM0
+#define METAL_SIFIVE_PWM0_PWMCFG 0UL
+#define METAL_SIFIVE_PWM0_PWMCOUNT 8UL
+#define METAL_SIFIVE_PWM0_PWMS 16UL
+#define METAL_SIFIVE_PWM0_PWMCMP0 32UL
+#define METAL_SIFIVE_PWM0_PWMCMP1 36UL
+#define METAL_SIFIVE_PWM0_PWMCMP2 40UL
+#define METAL_SIFIVE_PWM0_PWMCMP3 44UL
+
+/* From aon@10000000 */
+#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
+#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
+#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
+#define METAL_SIFIVE_AON0_0_SIZE 32768UL
+
+#define METAL_SIFIVE_RTC0
+#define METAL_SIFIVE_RTC0_RTCCFG 64UL
+#define METAL_SIFIVE_RTC0_RTCCOUNTLO 72UL
+#define METAL_SIFIVE_RTC0_RTCCOUNTHI 76UL
+#define METAL_SIFIVE_RTC0_RTCS 80UL
+#define METAL_SIFIVE_RTC0_RTCCMP0 96UL
+
+/* From spi@10014000 */
+#define METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS 268517376UL
+#define METAL_SIFIVE_SPI0_0_BASE_ADDRESS 268517376UL
+#define METAL_SIFIVE_SPI0_10014000_SIZE 4096UL
+#define METAL_SIFIVE_SPI0_0_SIZE 4096UL
+
+/* From spi@10024000 */
+#define METAL_SIFIVE_SPI0_10024000_BASE_ADDRESS 268582912UL
+#define METAL_SIFIVE_SPI0_1_BASE_ADDRESS 268582912UL
+#define METAL_SIFIVE_SPI0_10024000_SIZE 4096UL
+#define METAL_SIFIVE_SPI0_1_SIZE 4096UL
+
+/* From spi@10034000 */
+#define METAL_SIFIVE_SPI0_10034000_BASE_ADDRESS 268648448UL
+#define METAL_SIFIVE_SPI0_2_BASE_ADDRESS 268648448UL
+#define METAL_SIFIVE_SPI0_10034000_SIZE 4096UL
+#define METAL_SIFIVE_SPI0_2_SIZE 4096UL
+
+#define METAL_SIFIVE_SPI0
+#define METAL_SIFIVE_SPI0_SCKDIV 0UL
+#define METAL_SIFIVE_SPI0_SCKMODE 4UL
+#define METAL_SIFIVE_SPI0_CSID 16UL
+#define METAL_SIFIVE_SPI0_CSDEF 20UL
+#define METAL_SIFIVE_SPI0_CSMODE 24UL
+#define METAL_SIFIVE_SPI0_DELAY0 40UL
+#define METAL_SIFIVE_SPI0_DELAY1 44UL
+#define METAL_SIFIVE_SPI0_FMT 64UL
+#define METAL_SIFIVE_SPI0_TXDATA 72UL
+#define METAL_SIFIVE_SPI0_RXDATA 76UL
+#define METAL_SIFIVE_SPI0_TXMARK 80UL
+#define METAL_SIFIVE_SPI0_RXMARK 84UL
+#define METAL_SIFIVE_SPI0_FCTRL 96UL
+#define METAL_SIFIVE_SPI0_FFMT 100UL
+#define METAL_SIFIVE_SPI0_IE 112UL
+#define METAL_SIFIVE_SPI0_IP 116UL
+
+/* From serial@10013000 */
+#define METAL_SIFIVE_UART0_10013000_BASE_ADDRESS 268513280UL
+#define METAL_SIFIVE_UART0_0_BASE_ADDRESS 268513280UL
+#define METAL_SIFIVE_UART0_10013000_SIZE 4096UL
+#define METAL_SIFIVE_UART0_0_SIZE 4096UL
+
+/* From serial@10023000 */
+#define METAL_SIFIVE_UART0_10023000_BASE_ADDRESS 268578816UL
+#define METAL_SIFIVE_UART0_1_BASE_ADDRESS 268578816UL
+#define METAL_SIFIVE_UART0_10023000_SIZE 4096UL
+#define METAL_SIFIVE_UART0_1_SIZE 4096UL
+
+#define METAL_SIFIVE_UART0
+#define METAL_SIFIVE_UART0_TXDATA 0UL
+#define METAL_SIFIVE_UART0_RXDATA 4UL
+#define METAL_SIFIVE_UART0_TXCTRL 8UL
+#define METAL_SIFIVE_UART0_RXCTRL 12UL
+#define METAL_SIFIVE_UART0_IE 16UL
+#define METAL_SIFIVE_UART0_IP 20UL
+#define METAL_SIFIVE_UART0_DIV 24UL
+
+/* From aon@10000000 */
+#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
+#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
+#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
+#define METAL_SIFIVE_AON0_0_SIZE 32768UL
+
+#define METAL_SIFIVE_WDOG0
+#define METAL_SIFIVE_WDOG0_MAGIC_KEY 5370206UL
+#define METAL_SIFIVE_WDOG0_MAGIC_FOOD 218755085UL
+#define METAL_SIFIVE_WDOG0_WDOGCFG 0UL
+#define METAL_SIFIVE_WDOG0_WDOGCOUNT 8UL
+#define METAL_SIFIVE_WDOG0_WDOGS 16UL
+#define METAL_SIFIVE_WDOG0_WDOGFEED 24UL
+#define METAL_SIFIVE_WDOG0_WDOGKEY 28UL
+#define METAL_SIFIVE_WDOG0_WDOGCMP 32UL
+
+#endif /* METAL_PLATFORM_H*/
diff --git a/bsp/sparkfun-redv/metal.default.lds b/bsp/sparkfun-redv/metal.default.lds
new file mode 100644
index 00000000..094dcb61
--- /dev/null
+++ b/bsp/sparkfun-redv/metal.default.lds
@@ -0,0 +1,301 @@
+/* Copyright (c) 2020 SiFive Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+OUTPUT_ARCH("riscv")
+
+/* Default Linker Script
+ *
+ * This is the default linker script for all Freedom Metal applications.
+ */
+
+ENTRY(_enter)
+
+MEMORY
+{
+    itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
+    ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
+    rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
+}
+
+PHDRS
+{
+    rom PT_LOAD;
+    ram_init PT_LOAD;
+    tls PT_TLS;
+    ram PT_LOAD;
+    itim_init PT_LOAD;
+    text PT_LOAD;
+    lim_init PT_LOAD;
+}
+
+SECTIONS
+{
+    /* Each hart is allocated its own stack of size __stack_size. This value
+     * can be overriden at build-time by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__stack_size=0xf00
+     *
+     * where 0xf00 can be replaced with a multiple of 16 of your choice.
+     *
+     * __stack_size is PROVIDE-ed as a symbol so that initialization code
+     * initializes the stack pointers for each hart at the right offset from
+     * the _sp symbol.
+     */
+    __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
+    PROVIDE(__stack_size = __stack_size);
+
+    /* The size of the heap can be overriden at build-time by adding the
+     * following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_size=0xf00
+     *
+     * where 0xf00 can be replaced with the value of your choice.
+     *
+     * Altertatively, the heap can be grown to fill the entire remaining region
+     * of RAM by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_max=1
+     *
+     * Note that depending on the memory layout, the bitness (32/64bit) of the
+     * target, and the code model in use, this might cause a relocation error.
+     */
+    __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
+
+    /* The boot hart sets which hart runs the pre-main initialization routines,
+     * including copying .data into RAM, zeroing the BSS region, running
+     * constructors, etc. After initialization, the boot hart is also the only
+     * hart which runs application code unless the application overrides the
+     * secondary_main() function to start execution on secondary harts.
+     */
+    PROVIDE(__metal_boot_hart = 0);
+
+    /* The chicken bit is used by pre-main initialization to enable/disable
+     * certain core features */
+    PROVIDE(__metal_chicken_bit = 1);
+
+    /* The memory_ecc_scrub bit is used by _entry code to enable/disable
+     * memories scrubbing to zero  */
+    PROVIDE(__metal_eccscrub_bit = 0);
+
+    /* The RAM memories map for ECC scrubbing */
+    PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
+    PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
+    PROVIDE( metal_itim_0_memory_start = 0x8000000 );
+    PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
+
+    /* ROM SECTION
+     *
+     * The following sections contain data which lives in read-only memory, if
+     * such memory is present in the design, for the entire duration of program
+     * execution.
+     */
+
+    .init : {
+        /* The _enter symbol is placed in the .text.metal.init.enter section
+         * and must be placed at the beginning of the program */
+        KEEP (*(.text.metal.init.enter))
+        KEEP (*(.text.metal.init.*))
+        KEEP (*(SORT_NONE(.init)))
+        KEEP (*(.text.libgloss.start))
+    } >rom :rom
+
+    .fini : {
+        KEEP (*(SORT_NONE(.fini)))
+    } >rom :rom
+
+    .preinit_array : ALIGN(8) {
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP (*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+    } >rom :rom
+
+    .init_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_constructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
+        KEEP (*(.metal.init_array));
+        PROVIDE_HIDDEN ( metal_constructors_end = .);
+    } >rom :rom
+
+    .fini_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_destructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
+        KEEP (*(.metal.fini_array));
+        PROVIDE_HIDDEN ( metal_destructors_end = .);
+    } >rom :rom
+
+ 
+
+    .ctors : {
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*crtbegin?.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*(.ctors))
+        KEEP (*(.metal.ctors .metal.ctors.*))
+    } >rom :rom
+
+    .dtors : {
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*crtbegin?.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*(.dtors))
+        KEEP (*(.metal.dtors .metal.dtors.*))
+    } >rom : rom
+
+    .rodata : {
+        *(.rdata)
+        *(.rodata .rodata.*)
+        *(.gnu.linkonce.r.*)
+        . = ALIGN(8);
+        *(.srodata.cst16)
+        *(.srodata.cst8)
+        *(.srodata.cst4)
+        *(.srodata.cst2)
+        *(.srodata .srodata.*)
+    } >rom :rom
+
+    /* ITIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into an instruction tightly-integrated memory (ITIM), if one
+     * is present in the design, during pre-main program initialization.
+     *
+     * Generally, the data copied into the ITIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .itim : ALIGN(8) {
+        *(.itim .itim.*)
+    } >itim AT>rom :itim_init
+
+    PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
+
+    /* LIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a loosely integrated memory (LIM), which is shared with L2
+     * cache, during pre-main program initialization.
+     *
+     * Generally, the data copied into the LIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .lim : ALIGN(8) {
+        *(.lim .lim.*)
+    } >ram AT>rom :lim_init
+
+    PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
+
+    /* TEXT SECTION
+     *
+     * The following section contains the code of the program, excluding
+     * everything that's been allocated into the ITIM/LIM already
+     */
+
+    .text : {
+        *(.text.unlikely .text.unlikely.*)
+        *(.text.startup .text.startup.*)
+        *(.text .text.*)
+        *(.gnu.linkonce.t.*)
+    } >rom :text
+
+    /* RAM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a read-write-capable memory such as data tightly-integrated
+     * memory (DTIM) or another main memory, as well as the BSS, stack, and
+     * heap.
+     *
+     * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
+     * have an apparently unnecessary ALIGN at their top. This is because
+     * the implementation of _start in Freedom Metal libgloss depends on the
+     * ADDR and LOADADDR being 8-byte aligned.
+     */
+
+    .data : ALIGN(8) {
+        *(.data .data.*)
+        *(.gnu.linkonce.d.*)
+        . = ALIGN(8);
+        PROVIDE( __global_pointer$ = . + 0x800 );
+        *(.sdata .sdata.* .sdata2.*)
+        *(.gnu.linkonce.s.*)
+    } >ram AT>rom :ram_init
+
+    .tdata : ALIGN(8) {
+        PROVIDE( __tls_base = . );
+	*(.tdata .tdata.* .gnu.linkonce.td.*)
+    } >ram AT>rom :tls :ram_init
+
+    PROVIDE( __tdata_source = LOADADDR(.tdata) );
+    PROVIDE( __tdata_size = SIZEOF(.tdata) );
+
+    PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
+    PROVIDE( metal_segment_data_target_start = ADDR(.data) );
+    PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
+
+    .tbss : ALIGN(8) {
+	*(.tbss .tbss.* .gnu.linkonce.tb.*)
+	*(.tcommon .tcommon.*)
+	PROVIDE( __tls_end = . );
+    } >ram AT>ram :tls :ram
+    PROVIDE( __tbss_size = SIZEOF(.tbss) );
+    PROVIDE( __tls_size = __tls_end - __tls_base );
+
+    .tbss_space : ALIGN(8) {
+	. = . + __tbss_size;
+    } >ram :ram
+
+    .bss (NOLOAD): ALIGN(8) {
+        *(.sbss*)
+        *(.gnu.linkonce.sb.*)
+        *(.bss .bss.*)
+        *(.gnu.linkonce.b.*)
+        *(COMMON)
+    } >ram :ram
+
+    PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
+
+ 
+
+    .stack (NOLOAD) : ALIGN(16) {
+        PROVIDE(metal_segment_stack_begin = .);
+        . += __stack_size; /* Hart 0 */
+        PROVIDE( _sp = . );
+        PROVIDE(metal_segment_stack_end = .);
+    } >ram :ram
+
+    .heap (NOLOAD) : ALIGN(8) {
+        PROVIDE( __end = . );
+        PROVIDE( __heap_start = . );
+        PROVIDE( metal_segment_heap_target_start = . );
+        /* If __heap_max is defined, grow the heap to use the rest of RAM,
+         * otherwise set the heap size to __heap_size */
+        . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
+        PROVIDE( metal_segment_heap_target_end = . );
+        PROVIDE( _heap_end = . );
+        PROVIDE( __heap_end = . );
+    } >ram :ram
+
+    /* C++ exception handling information is
+     * not useful with our current runtime environment,
+     * and it consumes flash space. Discard it until
+     * we have something that can use it
+     */
+    /DISCARD/ : {
+	*(.eh_frame .eh_frame.*)
+    }
+}
\ No newline at end of file
diff --git a/bsp/sparkfun-redv/metal.freertos.lds b/bsp/sparkfun-redv/metal.freertos.lds
new file mode 100644
index 00000000..4798504e
--- /dev/null
+++ b/bsp/sparkfun-redv/metal.freertos.lds
@@ -0,0 +1,327 @@
+/* Copyright (c) 2020 SiFive Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+OUTPUT_ARCH("riscv")
+
+/* Privileged mode Linker Script
+ *
+ * This linker script is based on metal.default.lds. It introduce specific
+ * section to isolate (acessible only from machine mode) and others that can be
+ * used in every execution mode. This linker script it tailored for FreeRTOS
+ * applications.
+ */
+
+ENTRY(_enter)
+
+MEMORY
+{
+    itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
+    ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
+    rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
+}
+
+PHDRS
+{
+    rom PT_LOAD;
+    ram_init PT_LOAD;
+    tls PT_TLS;
+    ram PT_LOAD;
+    itim_init PT_LOAD;
+    text PT_LOAD;
+    lim_init PT_LOAD;
+}
+
+SECTIONS
+{
+    /* Each hart is allocated its own stack of size __stack_size. This value
+     * can be overriden at build-time by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__stack_size=0xf00
+     *
+     * where 0xf00 can be replaced with a multiple of 16 of your choice.
+     *
+     * __stack_size is PROVIDE-ed as a symbol so that initialization code
+     * initializes the stack pointers for each hart at the right offset from
+     * the _sp symbol.
+     */
+    __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
+    PROVIDE(__stack_size = __stack_size);
+
+    /* The size of the heap can be overriden at build-time by adding the
+     * following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_size=0xf00
+     *
+     * where 0xf00 can be replaced with the value of your choice.
+     *
+     * Altertatively, the heap can be grown to fill the entire remaining region
+     * of RAM by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_max=1
+     *
+     * Note that depending on the memory layout, the bitness (32/64bit) of the
+     * target, and the code model in use, this might cause a relocation error.
+     */
+    __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
+
+    /* The boot hart sets which hart runs the pre-main initialization routines,
+     * including copying .data into RAM, zeroing the BSS region, running
+     * constructors, etc. After initialization, the boot hart is also the only
+     * hart which runs application code unless the application overrides the
+     * secondary_main() function to start execution on secondary harts.
+     */
+    PROVIDE(__metal_boot_hart = 0);
+
+    /* The chicken bit is used by pre-main initialization to enable/disable
+     * certain core features */
+    PROVIDE(__metal_chicken_bit = 1);
+
+    /* The memory_ecc_scrub bit is used by _entry code to enable/disable
+     * memories scrubbing to zero  */
+    PROVIDE(__metal_eccscrub_bit = 0);
+
+    /* The RAM memories map for ECC scrubbing */
+    PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
+    PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
+    PROVIDE( metal_itim_0_memory_start = 0x8000000 );
+    PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
+
+    /* ROM SECTION
+     *
+     * The following sections contain data which lives in read-only memory, if
+     * such memory is present in the design, for the entire duration of program
+     * execution.
+     */
+
+    .init : {
+        /* The _enter symbol is placed in the .text.metal.init.enter section
+         * and must be placed at the beginning of the program */
+        KEEP (*(.text.metal.init.enter))
+        KEEP (*(.text.metal.init.*))
+        KEEP (*(SORT_NONE(.init)))
+        KEEP (*(.text.libgloss.start))
+    } >rom :rom
+
+    .fini : {
+        KEEP (*(SORT_NONE(.fini)))
+    } >rom :rom
+
+    .preinit_array : ALIGN(8) {
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP (*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+    } >rom :rom
+
+    .init_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_constructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
+        KEEP (*(.metal.init_array));
+        PROVIDE_HIDDEN ( metal_constructors_end = .);
+    } >rom :rom
+
+    .fini_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_destructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
+        KEEP (*(.metal.fini_array));
+        PROVIDE_HIDDEN ( metal_destructors_end = .);
+    } >rom :rom
+
+	.privileged_functions : ALIGN (32) {
+        __privileged_functions_start__ = .;
+        KEEP(*(privileged_functions))
+        . = ALIGN(32);
+		__privileged_functions_end__ = .;
+	} >rom
+ 
+
+    .ctors : {
+        . = ALIGN(32);
+        __unprivileged_section_start__ = .;
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*crtbegin?.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*(.ctors))
+        KEEP (*(.metal.ctors .metal.ctors.*))
+    } >rom :rom
+
+    .dtors : {
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*crtbegin?.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*(.dtors))
+        KEEP (*(.metal.dtors .metal.dtors.*))
+    } >rom : rom
+
+    .rodata : {
+        *(.rdata)
+        *(.rodata .rodata.*)
+        *(.gnu.linkonce.r.*)
+        . = ALIGN(8);
+        *(.srodata.cst16)
+        *(.srodata.cst8)
+        *(.srodata.cst4)
+        *(.srodata.cst2)
+        *(.srodata .srodata.*)
+    } >rom :rom
+
+    /* ITIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into an instruction tightly-integrated memory (ITIM), if one
+     * is present in the design, during pre-main program initialization.
+     *
+     * Generally, the data copied into the ITIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .itim : ALIGN(8) {
+        *(.itim .itim.*)
+    } >itim AT>rom :itim_init
+
+    PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
+
+    /* LIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a loosely integrated memory (LIM), which is shared with L2
+     * cache, during pre-main program initialization.
+     *
+     * Generally, the data copied into the LIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .lim : ALIGN(8) {
+        *(.lim .lim.*)
+    } >ram AT>rom :lim_init
+
+    PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
+
+    /* TEXT SECTION
+     *
+     * The following section contains the code of the program, excluding
+     * everything that's been allocated into the ITIM/LIM already
+     */
+
+    .text : {
+        *(.text.unlikely .text.unlikely.*)
+        *(.text.startup .text.startup.*)
+        *(.text .text.*)
+        *(.gnu.linkonce.t.*)
+        *(freertos_system_calls)
+        . = ALIGN(32);
+        __unprivileged_section_end__ = .;
+    } >rom :text
+
+    /* RAM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a read-write-capable memory such as data tightly-integrated
+     * memory (DTIM) or another main memory, as well as the BSS, stack, and
+     * heap.
+     *
+     * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
+     * have an apparently unnecessary ALIGN at their top. This is because
+     * the implementation of _start in Freedom Metal libgloss depends on the
+     * ADDR and LOADADDR being 8-byte aligned.
+     */
+
+    .data : ALIGN(8) {
+        . = ALIGN(32);
+        __unprivileged_data_section_start__ = .;
+        *(.data .data.*)
+        *(.gnu.linkonce.d.*)
+        . = ALIGN(8);
+        PROVIDE( __global_pointer$ = . + 0x800 );
+        *(.sdata .sdata.* .sdata2.*)
+        *(.gnu.linkonce.s.*)
+    } >ram AT>rom :ram_init
+
+    .tdata : ALIGN(8) {
+        PROVIDE( __tls_base = . );
+	*(.tdata .tdata.* .gnu.linkonce.td.*)
+    } >ram AT>rom :tls :ram_init
+
+    PROVIDE( __tdata_source = LOADADDR(.tdata) );
+    PROVIDE( __tdata_size = SIZEOF(.tdata) );
+
+    PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
+    PROVIDE( metal_segment_data_target_start = ADDR(.data) );
+    PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
+
+    .tbss : ALIGN(8) {
+	*(.tbss .tbss.* .gnu.linkonce.tb.*)
+	*(.tcommon .tcommon.*)
+	PROVIDE( __tls_end = . );
+    } >ram AT>ram :tls :ram
+    PROVIDE( __tbss_size = SIZEOF(.tbss) );
+    PROVIDE( __tls_size = __tls_end - __tls_base );
+
+    .tbss_space : ALIGN(8) {
+	. = . + __tbss_size;
+    } >ram :ram
+
+    .bss (NOLOAD): ALIGN(8) {
+        *(.sbss*)
+        *(.gnu.linkonce.sb.*)
+        *(.bss .bss.*)
+        *(.gnu.linkonce.b.*)
+        *(COMMON)
+        . = ALIGN(32);
+        __unprivileged_data_section_end__ = .;
+    } >ram :ram
+
+    PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
+
+    .privileged_data (NOLOAD) : ALIGN(32) {
+        __privileged_data_start__ = .;
+		*(privileged_data)
+		/* Non kernel data is kept out of the first _Privileged_Data_Region_Size
+		bytes of SRAM. */
+        . = ALIGN(32);
+		__privileged_data_end__ = .;
+	} >ram
+ 
+
+    .stack (NOLOAD) : ALIGN(16) {
+        PROVIDE(metal_segment_stack_begin = .);
+        . += __stack_size; /* Hart 0 */
+        PROVIDE( _sp = . );
+        PROVIDE(metal_segment_stack_end = .);
+    } >ram :ram
+
+    .heap (NOLOAD) : ALIGN(8) {
+        PROVIDE( __end = . );
+        PROVIDE( __heap_start = . );
+        PROVIDE( metal_segment_heap_target_start = . );
+        /* If __heap_max is defined, grow the heap to use the rest of RAM,
+         * otherwise set the heap size to __heap_size */
+        . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
+        PROVIDE( metal_segment_heap_target_end = . );
+        PROVIDE( _heap_end = . );
+        PROVIDE( __heap_end = . );
+    } >ram :ram
+
+    /* C++ exception handling information is
+     * not useful with our current runtime environment,
+     * and it consumes flash space. Discard it until
+     * we have something that can use it
+     */
+    /DISCARD/ : {
+	*(.eh_frame .eh_frame.*)
+    }
+}
\ No newline at end of file
diff --git a/bsp/sparkfun-redv/metal.h b/bsp/sparkfun-redv/metal.h
new file mode 100644
index 00000000..b00885c3
--- /dev/null
+++ b/bsp/sparkfun-redv/metal.h
@@ -0,0 +1,1468 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef ASSEMBLY
+
+#include <metal/machine/platform.h>
+
+#ifdef __METAL_MACHINE_MACROS
+
+#ifndef MACROS_IF_METAL_H
+#define MACROS_IF_METAL_H
+
+#define __METAL_CLINT_NUM_PARENTS 2
+
+#ifndef __METAL_CLINT_NUM_PARENTS
+#define __METAL_CLINT_NUM_PARENTS 0
+#endif
+#define __METAL_PLIC_SUBINTERRUPTS 53
+
+#define __METAL_PLIC_NUM_PARENTS 1
+
+#ifndef __METAL_PLIC_SUBINTERRUPTS
+#define __METAL_PLIC_SUBINTERRUPTS 0
+#endif
+#ifndef __METAL_PLIC_NUM_PARENTS
+#define __METAL_PLIC_NUM_PARENTS 0
+#endif
+#ifndef __METAL_CLIC_SUBINTERRUPTS
+#define __METAL_CLIC_SUBINTERRUPTS 0
+#endif
+
+#endif /* MACROS_IF_METAL_H*/
+
+#else /* ! __METAL_MACHINE_MACROS */
+
+#ifndef MACROS_ELSE_METAL_H
+#define MACROS_ELSE_METAL_H
+
+#define __METAL_CLINT_2000000_INTERRUPTS 2
+
+#define METAL_MAX_CLINT_INTERRUPTS 2
+
+#define __METAL_CLINT_NUM_PARENTS 2
+
+#define __METAL_INTERRUPT_CONTROLLER_C000000_INTERRUPTS 1
+
+#define __METAL_PLIC_SUBINTERRUPTS 53
+
+#define METAL_MAX_PLIC_INTERRUPTS 1
+
+#define __METAL_PLIC_NUM_PARENTS 1
+
+#define __METAL_CLIC_SUBINTERRUPTS 0
+#define METAL_MAX_CLIC_INTERRUPTS 0
+
+#define METAL_MAX_LOCAL_EXT_INTERRUPTS 0
+
+#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 0
+
+#define __METAL_GPIO_10012000_INTERRUPTS 32
+
+#define METAL_MAX_GPIO_INTERRUPTS 32
+
+#define __METAL_I2C_10016000_INTERRUPTS 1
+
+#define METAL_MAX_I2C0_INTERRUPTS 1
+
+#define __METAL_PWM_10015000_INTERRUPTS 4
+
+#define __METAL_PWM_10025000_INTERRUPTS 4
+
+#define __METAL_PWM_10035000_INTERRUPTS 4
+
+#define METAL_MAX_PWM0_INTERRUPTS 4
+
+#define METAL_MAX_PWM0_NCMP 4
+
+#define __METAL_SERIAL_10013000_INTERRUPTS 1
+
+#define __METAL_SERIAL_10023000_INTERRUPTS 1
+
+#define METAL_MAX_UART_INTERRUPTS 1
+
+#define METAL_MAX_SIMUART_INTERRUPTS 0
+
+
+#include <metal/drivers/fixed-clock.h>
+#include <metal/memory.h>
+#include <metal/drivers/riscv_clint0.h>
+#include <metal/drivers/riscv_cpu.h>
+#include <metal/drivers/riscv_plic0.h>
+#include <metal/pmp.h>
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/drivers/sifive_gpio-leds.h>
+#include <metal/drivers/sifive_i2c0.h>
+#include <metal/drivers/sifive_pwm0.h>
+#include <metal/drivers/sifive_rtc0.h>
+#include <metal/drivers/sifive_spi0.h>
+#include <metal/drivers/sifive_uart0.h>
+#include <metal/drivers/sifive_wdog0.h>
+#include <metal/drivers/sifive_fe310-g000_hfrosc.h>
+#include <metal/drivers/sifive_fe310-g000_hfxosc.h>
+#include <metal/drivers/sifive_fe310-g000_lfrosc.h>
+#include <metal/drivers/sifive_fe310-g000_pll.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+
+/* From clock@0 */
+extern struct __metal_driver_fixed_clock __metal_dt_clock_0;
+
+/* From clock@2 */
+extern struct __metal_driver_fixed_clock __metal_dt_clock_2;
+
+/* From clock@5 */
+extern struct __metal_driver_fixed_clock __metal_dt_clock_5;
+
+/* From clock@6 */
+extern struct __metal_driver_fixed_clock __metal_dt_clock_6;
+
+extern struct metal_memory __metal_dt_mem_dtim_80000000;
+
+extern struct metal_memory __metal_dt_mem_itim_8000000;
+
+extern struct metal_memory __metal_dt_mem_spi_10014000;
+
+extern struct metal_memory __metal_dt_mem_spi_10024000;
+
+extern struct metal_memory __metal_dt_mem_spi_10034000;
+
+/* From clint@2000000 */
+extern struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000;
+
+/* From cpu@0 */
+extern struct __metal_driver_cpu __metal_dt_cpu_0;
+
+extern struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller;
+
+/* From interrupt_controller@c000000 */
+extern struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000;
+
+extern struct metal_pmp __metal_dt_pmp;
+
+/* From gpio@10012000 */
+extern struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000;
+
+/* From led@0 */
+extern struct __metal_driver_sifive_gpio_led __metal_dt_led_0;
+
+/* From i2c@10016000 */
+extern struct __metal_driver_sifive_i2c0 __metal_dt_i2c_10016000;
+
+/* From pwm@10015000 */
+extern struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000;
+
+/* From pwm@10025000 */
+extern struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10025000;
+
+/* From pwm@10035000 */
+extern struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10035000;
+
+/* From aon@10000000 */
+extern struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000;
+
+/* From spi@10014000 */
+extern struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000;
+
+/* From spi@10024000 */
+extern struct __metal_driver_sifive_spi0 __metal_dt_spi_10024000;
+
+/* From spi@10034000 */
+extern struct __metal_driver_sifive_spi0 __metal_dt_spi_10034000;
+
+/* From serial@10013000 */
+extern struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000;
+
+/* From serial@10023000 */
+extern struct __metal_driver_sifive_uart0 __metal_dt_serial_10023000;
+
+/* From aon@10000000 */
+extern struct __metal_driver_sifive_wdog0 __metal_dt_aon_10000000;
+
+/* From clock@3 */
+extern struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3;
+
+/* From clock@1 */
+extern struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1;
+
+/* From clock@7 */
+extern struct __metal_driver_sifive_fe310_g000_lfrosc __metal_dt_clock_7;
+
+/* From clock@4 */
+extern struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4;
+
+/* From prci@10008000 */
+extern struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000;
+
+
+
+/* --------------------- fixed_clock ------------ */
+static __inline__ unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock)
+{
+	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_0) {
+		return METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY;
+	}
+	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_2) {
+		return METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY;
+	}
+	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_5) {
+		return METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY;
+	}
+	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_6) {
+		return METAL_FIXED_CLOCK_6_CLOCK_FREQUENCY;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- fixed_factor_clock ------------ */
+
+
+/* --------------------- sifive_clint0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) {
+		return METAL_RISCV_CLINT0_2000000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) {
+		return METAL_RISCV_CLINT0_2000000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) {
+		return METAL_MAX_CLINT_INTERRUPTS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx)
+{
+	if (idx == 0) {
+		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller;
+	}
+	else if (idx == 1) {
+		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx)
+{
+	if (idx == 0) {
+		return 3;
+	}
+	else if (idx == 1) {
+		return 7;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- cpu ------------ */
+static __inline__ int __metal_driver_cpu_hartid(struct metal_cpu *cpu)
+{
+	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) {
+		return 0;
+	}
+	else {
+		return -1;
+	}
+}
+
+static __inline__ int __metal_driver_cpu_timebase(struct metal_cpu *cpu)
+{
+	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) {
+		return 16000000;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu)
+{
+	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) {
+		return &__metal_dt_cpu_0_interrupt_controller.controller;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu)
+{
+	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) {
+		return 8;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_buserror * __metal_driver_cpu_buserror(struct metal_cpu *cpu)
+{
+	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) {
+		return NULL;
+	}
+	else {
+		return NULL;
+	}
+}
+
+
+
+/* --------------------- sifive_plic0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) {
+		return METAL_RISCV_PLIC0_C000000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) {
+		return METAL_RISCV_PLIC0_C000000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) {
+		return METAL_RISCV_PLIC0_C000000_RISCV_NDEV;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller)
+{
+	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) {
+		return METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx)
+{
+	if (idx == 0) {
+		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx)
+{
+	if (idx == 0) {
+		return 11;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_plic0_context_ids(int hartid)
+{
+	if (hartid == 0) {
+		return 0;
+	}
+	else {
+		return -1;
+	}
+}
+
+
+
+/* --------------------- sifive_buserror0 ------------ */
+
+
+/* --------------------- sifive_clic0 ------------ */
+
+
+/* --------------------- sifive_local_external_interrupts0 ------------ */
+
+
+/* --------------------- sifive_global_external_interrupts0 ------------ */
+
+
+/* --------------------- sifive_gpio0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio)
+{
+	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) {
+		return METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio)
+{
+	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) {
+		return METAL_SIFIVE_GPIO0_10012000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio)
+{
+	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) {
+		return METAL_MAX_GPIO_INTERRUPTS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio)
+{
+	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) {
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx)
+{
+	if (((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 0)) {
+		return 8;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 1))) {
+		return 9;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 2))) {
+		return 10;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 3))) {
+		return 11;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 4))) {
+		return 12;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 5))) {
+		return 13;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 6))) {
+		return 14;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 7))) {
+		return 15;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 8))) {
+		return 16;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 9))) {
+		return 17;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 10))) {
+		return 18;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 11))) {
+		return 19;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 12))) {
+		return 20;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 13))) {
+		return 21;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 14))) {
+		return 22;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 15))) {
+		return 23;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 16))) {
+		return 24;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 17))) {
+		return 25;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 18))) {
+		return 26;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 19))) {
+		return 27;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 20))) {
+		return 28;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 21))) {
+		return 29;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 22))) {
+		return 30;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 23))) {
+		return 31;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 24))) {
+		return 32;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 25))) {
+		return 33;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 26))) {
+		return 34;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 27))) {
+		return 35;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 28))) {
+		return 36;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 29))) {
+		return 27;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 30))) {
+		return 28;
+	}
+	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 31))) {
+		return 29;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_gpio_button ------------ */
+
+
+/* --------------------- sifive_gpio_led ------------ */
+static __inline__ struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led)
+{
+	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0) {
+		return (struct metal_gpio *)&__metal_dt_gpio_10012000;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_gpio_led_pin(struct metal_led *led)
+{
+	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0) {
+		return 5;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *led)
+{
+	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0) {
+		return "LD0";
+	}
+	else {
+		return "";
+	}
+}
+
+
+
+/* --------------------- sifive_gpio_switch ------------ */
+
+
+/* --------------------- sifive_i2c0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_i2c0_control_base(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return METAL_SIFIVE_I2C0_10016000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_i2c0_control_size(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return METAL_SIFIVE_I2C0_10016000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_i2c0_clock(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_i2c0_pinmux(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_output_selector(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return 0;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_source_selector(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return 12288;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_i2c0_num_interrupts(struct metal_i2c *i2c)
+{
+		return METAL_MAX_I2C0_INTERRUPTS;
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_i2c0_interrupt_parent(struct metal_i2c *i2c)
+{
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+}
+
+static __inline__ int __metal_driver_sifive_i2c0_interrupt_line(struct metal_i2c *i2c)
+{
+	if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) {
+		return 52;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_pwm0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return METAL_SIFIVE_PWM0_10025000_BASE_ADDRESS;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return METAL_SIFIVE_PWM0_10035000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return METAL_SIFIVE_PWM0_10015000_SIZE;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return METAL_SIFIVE_PWM0_10025000_SIZE;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return METAL_SIFIVE_PWM0_10035000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return 15;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return 7864320;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return 15360;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return 15;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return 7864320;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return 15360;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return __METAL_PWM_10015000_INTERRUPTS;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return __METAL_PWM_10025000_INTERRUPTS;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return __METAL_PWM_10035000_INTERRUPTS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm)
+{
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+}
+
+static __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx)
+{
+	if (((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 0)) {
+		return 40;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 1))) {
+		return 41;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 2))) {
+		return 42;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 3))) {
+		return 43;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 0))) {
+		return 44;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 1))) {
+		return 45;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 2))) {
+		return 46;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 3))) {
+		return 47;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 0))) {
+		return 48;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 1))) {
+		return 49;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 2))) {
+		return 50;
+	}
+	else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 3))) {
+		return 51;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return 8;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return 16;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return 16;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm)
+{
+	if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
+		return 4;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) {
+		return 4;
+	}
+	else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) {
+		return 4;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_rtc0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc)
+{
+	if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) {
+		return METAL_SIFIVE_AON0_10000000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc)
+{
+	if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) {
+		return METAL_SIFIVE_AON0_10000000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_rtc0_interrupt_parent(const struct metal_rtc *const rtc)
+{
+	if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) {
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_rtc0_interrupt_line(const struct metal_rtc *const rtc)
+{
+	if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) {
+		return 2;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_rtc0_clock(const struct metal_rtc *const rtc)
+{
+	if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) {
+		return (struct metal_clock *)&__metal_dt_clock_7.clock;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+static __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi)
+{
+	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) {
+		return METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) {
+		return METAL_SIFIVE_SPI0_10024000_BASE_ADDRESS;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) {
+		return METAL_SIFIVE_SPI0_10034000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi)
+{
+	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) {
+		return METAL_SIFIVE_SPI0_10014000_SIZE;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) {
+		return METAL_SIFIVE_SPI0_10024000_SIZE;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) {
+		return METAL_SIFIVE_SPI0_10034000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_spi0_clock(struct metal_spi *spi)
+{
+	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi)
+{
+	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi)
+{
+	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) {
+		return 0;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) {
+		return 0;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) {
+		return 0;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi)
+{
+	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) {
+		return 0;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) {
+		return 60;
+	}
+	else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) {
+		return 4227858432;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_test0 ------------ */
+
+
+/* --------------------- sifive_trace ------------ */
+
+/* --------------------- sifive_uart0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return METAL_SIFIVE_UART0_10013000_BASE_ADDRESS;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return METAL_SIFIVE_UART0_10023000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return METAL_SIFIVE_UART0_10013000_SIZE;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return METAL_SIFIVE_UART0_10023000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return METAL_MAX_UART_INTERRUPTS;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return METAL_MAX_UART_INTERRUPTS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return 3;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return 4;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return (struct metal_clock *)&__metal_dt_clock_4.clock;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return 0;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return 0;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart)
+{
+	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
+		return 196608;
+	}
+	else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) {
+		return 8650752;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_simuart0 ------------ */
+
+
+/* --------------------- sifive_wdog0 ------------ */
+static __inline__ unsigned long __metal_driver_sifive_wdog0_control_base(const struct metal_watchdog *const watchdog)
+{
+	if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) {
+		return METAL_SIFIVE_AON0_10000000_BASE_ADDRESS;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long __metal_driver_sifive_wdog0_control_size(const struct metal_watchdog *const watchdog)
+{
+	if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) {
+		return METAL_SIFIVE_AON0_10000000_SIZE;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_interrupt * __metal_driver_sifive_wdog0_interrupt_parent(const struct metal_watchdog *const watchdog)
+{
+	if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) {
+		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ int __metal_driver_sifive_wdog0_interrupt_line(const struct metal_watchdog *const watchdog)
+{
+	if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) {
+		return 1;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_wdog0_clock(const struct metal_watchdog *const watchdog)
+{
+	if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) {
+		return (struct metal_clock *)&__metal_dt_clock_7.clock;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_fe310_g000_hfrosc ------------ */
+static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock)
+{
+		return (struct metal_clock *)&__metal_dt_clock_2.clock;
+}
+
+static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock)
+{
+		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000;
+}
+
+static __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock)
+{
+		return &__metal_driver_vtable_sifive_fe310_g000_prci;
+}
+
+static __inline__ long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock)
+{
+		return METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG;
+}
+
+
+
+/* --------------------- sifive_fe310_g000_hfxosc ------------ */
+static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock)
+{
+		return (struct metal_clock *)&__metal_dt_clock_0.clock;
+}
+
+static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock)
+{
+		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000;
+}
+
+static __inline__ long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock)
+{
+		return METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG;
+}
+
+
+
+/* --------------------- sifive_fe310_g000_lfrosc ------------ */
+static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(const struct metal_clock *clock)
+{
+	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) {
+		return (struct metal_clock *)&__metal_dt_clock_5.clock;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(const struct metal_clock *clock)
+{
+	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) {
+		return (struct metal_clock *)&__metal_dt_clock_6.clock;
+	}
+	else {
+		return NULL;
+	}
+}
+
+static __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_config_reg(const struct metal_clock *clock)
+{
+	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) {
+		return 112;
+	}
+	else {
+		return 0;
+	}
+}
+
+static __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(const struct metal_clock *clock)
+{
+	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) {
+		return 124;
+	}
+	else {
+		return 0;
+	}
+}
+
+
+
+/* --------------------- sifive_fe310_g000_pll ------------ */
+static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock)
+{
+		return (struct metal_clock *)&__metal_dt_clock_3.clock;
+}
+
+static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock)
+{
+		return (struct metal_clock *)&__metal_dt_clock_1.clock;
+}
+
+static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock)
+{
+		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000;
+}
+
+static __inline__ long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock)
+{
+		return METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV;
+}
+
+static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( )
+{
+		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000;
+}
+
+static __inline__ long __metal_driver_sifive_fe310_g000_pll_config_offset( )
+{
+		return METAL_SIFIVE_FE310_G000_PRCI_PLLCFG;
+}
+
+static __inline__ long __metal_driver_sifive_fe310_g000_pll_init_rate( )
+{
+		return 16000000;
+}
+
+
+
+/* --------------------- sifive_fe310_g000_prci ------------ */
+static __inline__ long __metal_driver_sifive_fe310_g000_prci_base( )
+{
+		return METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS;
+}
+
+static __inline__ long __metal_driver_sifive_fe310_g000_prci_size( )
+{
+		return METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE;
+}
+
+static __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( )
+{
+		return &__metal_driver_vtable_sifive_fe310_g000_prci;
+}
+
+
+
+#define __METAL_DT_MAX_MEMORIES 3
+
+__asm__ (".weak __metal_memory_table");
+struct metal_memory *__metal_memory_table[] = {
+					&__metal_dt_mem_dtim_80000000,
+					&__metal_dt_mem_itim_8000000,
+					&__metal_dt_mem_spi_10014000};
+
+/* From serial@10013000 */
+#define __METAL_DT_STDOUT_UART_HANDLE (&__metal_dt_serial_10013000.uart)
+
+#define __METAL_DT_SERIAL_10013000_HANDLE (&__metal_dt_serial_10013000.uart)
+
+#define __METAL_DT_STDOUT_UART_BAUD 115200
+
+/* From clint@2000000 */
+#define __METAL_DT_RISCV_CLINT0_HANDLE (&__metal_dt_clint_2000000.controller)
+
+#define __METAL_DT_CLINT_2000000_HANDLE (&__metal_dt_clint_2000000.controller)
+
+#define __METAL_DT_MAX_HARTS 1
+
+#define __METAL_CPU_0_ICACHE_HANDLE 1
+
+__asm__ (".weak __metal_cpu_table");
+struct __metal_driver_cpu *__metal_cpu_table[] = {
+					&__metal_dt_cpu_0};
+
+/* From interrupt_controller@c000000 */
+#define __METAL_DT_RISCV_PLIC0_HANDLE (&__metal_dt_interrupt_controller_c000000.controller)
+
+#define __METAL_DT_INTERRUPT_CONTROLLER_C000000_HANDLE (&__metal_dt_interrupt_controller_c000000.controller)
+
+#define __METAL_DT_PMP_HANDLE (&__metal_dt_pmp)
+
+#define __MEE_DT_MAX_GPIOS 1
+
+__asm__ (".weak __metal_gpio_table");
+struct __metal_driver_sifive_gpio0 *__metal_gpio_table[] = {
+					&__metal_dt_gpio_10012000};
+
+#define __METAL_DT_MAX_BUTTONS 0
+
+__asm__ (".weak __metal_button_table");
+struct __metal_driver_sifive_gpio_button *__metal_button_table[] = {
+					NULL };
+#define __METAL_DT_MAX_LEDS 1
+
+__asm__ (".weak __metal_led_table");
+struct __metal_driver_sifive_gpio_led *__metal_led_table[] = {
+					&__metal_dt_led_0};
+
+#define __METAL_DT_MAX_SWITCHES 0
+
+__asm__ (".weak __metal_switch_table");
+struct __metal_driver_sifive_gpio_switch *__metal_switch_table[] = {
+					NULL };
+#define __METAL_DT_MAX_I2CS 1
+
+__asm__ (".weak __metal_i2c_table");
+struct __metal_driver_sifive_i2c0 *__metal_i2c_table[] = {
+					&__metal_dt_i2c_10016000};
+
+#define __METAL_DT_MAX_PWMS 3
+
+__asm__ (".weak __metal_pwm_table");
+struct __metal_driver_sifive_pwm0 *__metal_pwm_table[] = {
+					&__metal_dt_pwm_10015000,
+					&__metal_dt_pwm_10025000,
+					&__metal_dt_pwm_10035000};
+
+#define __METAL_DT_MAX_RTCS 1
+
+__asm__ (".weak __metal_rtc_table");
+struct __metal_driver_sifive_rtc0 *__metal_rtc_table[] = {
+					&__metal_dt_rtc_10000000};
+
+#define __METAL_DT_MAX_SPIS 3
+
+__asm__ (".weak __metal_spi_table");
+struct __metal_driver_sifive_spi0 *__metal_spi_table[] = {
+					&__metal_dt_spi_10014000,
+					&__metal_dt_spi_10024000,
+					&__metal_dt_spi_10034000};
+
+#define __METAL_DT_MAX_UARTS 2
+
+__asm__ (".weak __metal_uart_table");
+struct __metal_driver_sifive_uart0 *__metal_uart_table[] = {
+					&__metal_dt_serial_10013000,
+					&__metal_dt_serial_10023000};
+
+#define __METAL_DT_MAX_SIMUARTS 0
+
+__asm__ (".weak __metal_simuart_table");
+struct __metal_driver_sifive_simuart0 *__metal_simuart_table[] = {
+					NULL };
+#define __METAL_DT_MAX_WDOGS 1
+
+__asm__ (".weak __metal_wdog_table");
+struct __metal_driver_sifive_wdog0 *__metal_wdog_table[] = {
+					&__metal_dt_aon_10000000};
+
+/* From clock@4 */
+#define __METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE (&__metal_dt_clock_4)
+
+#define __METAL_DT_CLOCK_4_HANDLE (&__metal_dt_clock_4)
+
+#endif /* MACROS_ELSE_METAL_H*/
+
+#endif /* ! __METAL_MACHINE_MACROS */
+
+#endif /* ! ASSEMBLY */
diff --git a/bsp/sparkfun-redv/metal.ramrodata.lds b/bsp/sparkfun-redv/metal.ramrodata.lds
new file mode 100644
index 00000000..6803873c
--- /dev/null
+++ b/bsp/sparkfun-redv/metal.ramrodata.lds
@@ -0,0 +1,306 @@
+/* Copyright (c) 2020 SiFive Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+OUTPUT_ARCH("riscv")
+
+/* RAM Read-Only Data Linker Script
+ *
+ * This linker script places application code and read-only data into writable
+ * memories in an attempt to improve performance, since writable memories
+ * are generally lower-latency. This linker script may cause your application
+ * to overflow RAM, since it dramatically increases the quantity of data vying
+ * for space there.
+ */
+
+ENTRY(_enter)
+
+MEMORY
+{
+    itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
+    ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
+    rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
+}
+
+PHDRS
+{
+    rom PT_LOAD;
+    ram_init PT_LOAD;
+    tls PT_TLS;
+    ram PT_LOAD;
+    itim_init PT_LOAD;
+    text PT_LOAD;
+    lim_init PT_LOAD;
+}
+
+SECTIONS
+{
+    /* Each hart is allocated its own stack of size __stack_size. This value
+     * can be overriden at build-time by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__stack_size=0xf00
+     *
+     * where 0xf00 can be replaced with a multiple of 16 of your choice.
+     *
+     * __stack_size is PROVIDE-ed as a symbol so that initialization code
+     * initializes the stack pointers for each hart at the right offset from
+     * the _sp symbol.
+     */
+    __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
+    PROVIDE(__stack_size = __stack_size);
+
+    /* The size of the heap can be overriden at build-time by adding the
+     * following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_size=0xf00
+     *
+     * where 0xf00 can be replaced with the value of your choice.
+     *
+     * Altertatively, the heap can be grown to fill the entire remaining region
+     * of RAM by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_max=1
+     *
+     * Note that depending on the memory layout, the bitness (32/64bit) of the
+     * target, and the code model in use, this might cause a relocation error.
+     */
+    __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
+
+    /* The boot hart sets which hart runs the pre-main initialization routines,
+     * including copying .data into RAM, zeroing the BSS region, running
+     * constructors, etc. After initialization, the boot hart is also the only
+     * hart which runs application code unless the application overrides the
+     * secondary_main() function to start execution on secondary harts.
+     */
+    PROVIDE(__metal_boot_hart = 0);
+
+    /* The chicken bit is used by pre-main initialization to enable/disable
+     * certain core features */
+    PROVIDE(__metal_chicken_bit = 1);
+
+    /* The memory_ecc_scrub bit is used by _entry code to enable/disable
+     * memories scrubbing to zero  */
+    PROVIDE(__metal_eccscrub_bit = 0);
+
+    /* The RAM memories map for ECC scrubbing */
+    PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
+    PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
+    PROVIDE( metal_itim_0_memory_start = 0x8000000 );
+    PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
+
+    /* ROM SECTION
+     *
+     * The following sections contain data which lives in read-only memory, if
+     * such memory is present in the design, for the entire duration of program
+     * execution.
+     */
+
+    .init : {
+        /* The _enter symbol is placed in the .text.metal.init.enter section
+         * and must be placed at the beginning of the program */
+        KEEP (*(.text.metal.init.enter))
+        KEEP (*(.text.metal.init.*))
+        KEEP (*(SORT_NONE(.init)))
+        KEEP (*(.text.libgloss.start))
+    } >rom :rom
+
+    .fini : {
+        KEEP (*(SORT_NONE(.fini)))
+    } >rom :rom
+
+    .preinit_array : ALIGN(8) {
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP (*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+    } >rom :rom
+
+    .init_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_constructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
+        KEEP (*(.metal.init_array));
+        PROVIDE_HIDDEN ( metal_constructors_end = .);
+    } >rom :rom
+
+    .fini_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_destructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
+        KEEP (*(.metal.fini_array));
+        PROVIDE_HIDDEN ( metal_destructors_end = .);
+    } >rom :rom
+
+ 
+
+    .ctors : {
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*crtbegin?.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*(.ctors))
+        KEEP (*(.metal.ctors .metal.ctors.*))
+    } >rom :rom
+
+    .dtors : {
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*crtbegin?.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*(.dtors))
+        KEEP (*(.metal.dtors .metal.dtors.*))
+    } >rom : rom
+
+
+    /* ITIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into an instruction tightly-integrated memory (ITIM), if one
+     * is present in the design, during pre-main program initialization.
+     *
+     * Generally, the data copied into the ITIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .itim : ALIGN(8) {
+        *(.itim .itim.*)
+    } >itim AT>rom :itim_init
+
+    PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
+
+    /* LIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a loosely integrated memory (LIM), which is shared with L2
+     * cache, during pre-main program initialization.
+     *
+     * Generally, the data copied into the LIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .lim : ALIGN(8) {
+        *(.lim .lim.*)
+    } >ram AT>rom :lim_init
+
+    PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
+
+    /* TEXT SECTION
+     *
+     * The following section contains the code of the program, excluding
+     * everything that's been allocated into the ITIM/LIM already
+     */
+
+    .text : {
+        *(.text.unlikely .text.unlikely.*)
+        *(.text.startup .text.startup.*)
+        *(.text .text.*)
+        *(.gnu.linkonce.t.*)
+    } >rom :text
+
+    /* RAM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a read-write-capable memory such as data tightly-integrated
+     * memory (DTIM) or another main memory, as well as the BSS, stack, and
+     * heap.
+     *
+     * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
+     * have an apparently unnecessary ALIGN at their top. This is because
+     * the implementation of _start in Freedom Metal libgloss depends on the
+     * ADDR and LOADADDR being 8-byte aligned.
+     */
+
+    .data : ALIGN(8) {
+        *(.data .data.*)
+        *(.gnu.linkonce.d.*)
+        . = ALIGN(8);
+        PROVIDE( __global_pointer$ = . + 0x800 );
+        *(.sdata .sdata.* .sdata2.*)
+        *(.gnu.linkonce.s.*)
+        /* Read-only data is placed in RAM to improve performance, since
+         * read-only memory generally has higher latency than RAM */
+        . = ALIGN(8);
+        *(.srodata.cst16)
+        *(.srodata.cst8)
+        *(.srodata.cst4)
+        *(.srodata.cst2)
+        *(.srodata .srodata.*)
+        . = ALIGN(8);
+        *(.rdata)
+        *(.rodata .rodata.*)
+        *(.gnu.linkonce.r.*)
+    } >ram AT>rom :ram_init
+
+    .tdata : ALIGN(8) {
+        PROVIDE( __tls_base = . );
+	*(.tdata .tdata.* .gnu.linkonce.td.*)
+    } >ram AT>rom :tls :ram_init
+
+    PROVIDE( __tdata_source = LOADADDR(.tdata) );
+    PROVIDE( __tdata_size = SIZEOF(.tdata) );
+
+    PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
+    PROVIDE( metal_segment_data_target_start = ADDR(.data) );
+    PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
+
+    .tbss : ALIGN(8) {
+	*(.tbss .tbss.* .gnu.linkonce.tb.*)
+	*(.tcommon .tcommon.*)
+	PROVIDE( __tls_end = . );
+    } >ram AT>ram :tls :ram
+    PROVIDE( __tbss_size = SIZEOF(.tbss) );
+    PROVIDE( __tls_size = __tls_end - __tls_base );
+
+    .tbss_space : ALIGN(8) {
+	. = . + __tbss_size;
+    } >ram :ram
+
+    .bss (NOLOAD): ALIGN(8) {
+        *(.sbss*)
+        *(.gnu.linkonce.sb.*)
+        *(.bss .bss.*)
+        *(.gnu.linkonce.b.*)
+        *(COMMON)
+    } >ram :ram
+
+    PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
+
+ 
+
+    .stack (NOLOAD) : ALIGN(16) {
+        PROVIDE(metal_segment_stack_begin = .);
+        . += __stack_size; /* Hart 0 */
+        PROVIDE( _sp = . );
+        PROVIDE(metal_segment_stack_end = .);
+    } >ram :ram
+
+    .heap (NOLOAD) : ALIGN(8) {
+        PROVIDE( __end = . );
+        PROVIDE( __heap_start = . );
+        PROVIDE( metal_segment_heap_target_start = . );
+        /* If __heap_max is defined, grow the heap to use the rest of RAM,
+         * otherwise set the heap size to __heap_size */
+        . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
+        PROVIDE( metal_segment_heap_target_end = . );
+        PROVIDE( _heap_end = . );
+        PROVIDE( __heap_end = . );
+    } >ram :ram
+
+    /* C++ exception handling information is
+     * not useful with our current runtime environment,
+     * and it consumes flash space. Discard it until
+     * we have something that can use it
+     */
+    /DISCARD/ : {
+	*(.eh_frame .eh_frame.*)
+    }
+}
\ No newline at end of file
diff --git a/bsp/sparkfun-redv/metal.scratchpad.lds b/bsp/sparkfun-redv/metal.scratchpad.lds
new file mode 100644
index 00000000..35672691
--- /dev/null
+++ b/bsp/sparkfun-redv/metal.scratchpad.lds
@@ -0,0 +1,294 @@
+/* Copyright (c) 2020 SiFive Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+OUTPUT_ARCH("riscv")
+
+/* Scratchpad Linker Script
+ *
+ * This linker script is for executing in "scratchpad" mode, where all
+ * application code and data is placed in writable memory.
+ */
+
+ENTRY(_enter)
+
+MEMORY
+{
+    itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
+    ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
+    rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
+}
+
+PHDRS
+{
+    rom PT_LOAD;
+    ram_init PT_LOAD;
+    tls PT_TLS;
+    ram PT_LOAD;
+    itim_init PT_LOAD;
+    text PT_LOAD;
+    lim_init PT_LOAD;
+}
+
+SECTIONS
+{
+    /* Each hart is allocated its own stack of size __stack_size. This value
+     * can be overriden at build-time by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__stack_size=0xf00
+     *
+     * where 0xf00 can be replaced with a multiple of 16 of your choice.
+     *
+     * __stack_size is PROVIDE-ed as a symbol so that initialization code
+     * initializes the stack pointers for each hart at the right offset from
+     * the _sp symbol.
+     */
+    __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
+    PROVIDE(__stack_size = __stack_size);
+
+    /* The size of the heap can be overriden at build-time by adding the
+     * following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_size=0xf00
+     *
+     * where 0xf00 can be replaced with the value of your choice.
+     *
+     * Altertatively, the heap can be grown to fill the entire remaining region
+     * of RAM by adding the following to CFLAGS:
+     *
+     *     -Xlinker --defsym=__heap_max=1
+     *
+     * Note that depending on the memory layout, the bitness (32/64bit) of the
+     * target, and the code model in use, this might cause a relocation error.
+     */
+    __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
+
+    /* The boot hart sets which hart runs the pre-main initialization routines,
+     * including copying .data into RAM, zeroing the BSS region, running
+     * constructors, etc. After initialization, the boot hart is also the only
+     * hart which runs application code unless the application overrides the
+     * secondary_main() function to start execution on secondary harts.
+     */
+    PROVIDE(__metal_boot_hart = 0);
+
+    /* The chicken bit is used by pre-main initialization to enable/disable
+     * certain core features */
+    PROVIDE(__metal_chicken_bit = 1);
+
+    PROVIDE(__metal_eccscrub_bit = 0);
+
+    /* ROM SECTION
+     *
+     * The following sections contain data which lives in read-only memory, if
+     * such memory is present in the design, for the entire duration of program
+     * execution.
+     */
+
+    .init : {
+        /* The _enter symbol is placed in the .text.metal.init.enter section
+         * and must be placed at the beginning of the program */
+        KEEP (*(.text.metal.init.enter))
+        KEEP (*(.text.metal.init.*))
+        KEEP (*(SORT_NONE(.init)))
+        KEEP (*(.text.libgloss.start))
+    } >ram :rom
+
+    .fini : {
+        KEEP (*(SORT_NONE(.fini)))
+    } >ram :rom
+
+    .preinit_array : ALIGN(8) {
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP (*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+    } >ram :rom
+
+    .init_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_constructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
+        KEEP (*(.metal.init_array));
+        PROVIDE_HIDDEN ( metal_constructors_end = .);
+    } >ram :rom
+
+    .fini_array : ALIGN(8) {
+        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 = .);
+        PROVIDE_HIDDEN ( metal_destructors_start = .);
+        KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
+        KEEP (*(.metal.fini_array));
+        PROVIDE_HIDDEN ( metal_destructors_end = .);
+    } >ram :rom
+
+ 
+
+    .ctors : {
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*crtbegin?.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*(.ctors))
+        KEEP (*(.metal.ctors .metal.ctors.*))
+    } >ram :rom
+
+    .dtors : {
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*crtbegin?.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*(.dtors))
+        KEEP (*(.metal.dtors .metal.dtors.*))
+    } >ram : rom
+
+    .rodata : {
+        *(.rdata)
+        *(.rodata .rodata.*)
+        *(.gnu.linkonce.r.*)
+        . = ALIGN(8);
+        *(.srodata.cst16)
+        *(.srodata.cst8)
+        *(.srodata.cst4)
+        *(.srodata.cst2)
+        *(.srodata .srodata.*)
+    } >ram :rom
+
+    /* ITIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into an instruction tightly-integrated memory (ITIM), if one
+     * is present in the design, during pre-main program initialization.
+     *
+     * Generally, the data copied into the ITIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .itim : ALIGN(8) {
+        *(.itim .itim.*)
+    } >itim AT>ram :itim_init
+
+    PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
+    PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
+
+    /* LIM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a loosely integrated memory (LIM), which is shared with L2
+     * cache, during pre-main program initialization.
+     *
+     * Generally, the data copied into the LIM should be performance-critical
+     * functions which benefit from low instruction-fetch latency.
+     */
+
+    .lim : ALIGN(8) {
+        *(.lim .lim.*)
+    } >ram AT>ram :lim_init
+
+    PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
+    PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
+
+    /* TEXT SECTION
+     *
+     * The following section contains the code of the program, excluding
+     * everything that's been allocated into the ITIM/LIM already
+     */
+
+    .text : {
+        *(.text.unlikely .text.unlikely.*)
+        *(.text.startup .text.startup.*)
+        *(.text .text.*)
+        *(.gnu.linkonce.t.*)
+    } >ram :text
+
+    /* RAM SECTION
+     *
+     * The following sections contain data which is copied from read-only
+     * memory into a read-write-capable memory such as data tightly-integrated
+     * memory (DTIM) or another main memory, as well as the BSS, stack, and
+     * heap.
+     *
+     * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
+     * have an apparently unnecessary ALIGN at their top. This is because
+     * the implementation of _start in Freedom Metal libgloss depends on the
+     * ADDR and LOADADDR being 8-byte aligned.
+     */
+
+    .data : ALIGN(8) {
+        *(.data .data.*)
+        *(.gnu.linkonce.d.*)
+        . = ALIGN(8);
+        PROVIDE( __global_pointer$ = . + 0x800 );
+        *(.sdata .sdata.* .sdata2.*)
+        *(.gnu.linkonce.s.*)
+    } >ram AT>ram :ram_init
+
+    .tdata : ALIGN(8) {
+        PROVIDE( __tls_base = . );
+	*(.tdata .tdata.* .gnu.linkonce.td.*)
+    } >ram AT>ram :tls :ram_init
+
+    PROVIDE( __tdata_source = LOADADDR(.tdata) );
+    PROVIDE( __tdata_size = SIZEOF(.tdata) );
+
+    PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
+    PROVIDE( metal_segment_data_target_start = ADDR(.data) );
+    PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
+
+    .tbss : ALIGN(8) {
+	*(.tbss .tbss.* .gnu.linkonce.tb.*)
+	*(.tcommon .tcommon.*)
+	PROVIDE( __tls_end = . );
+    } >ram AT>ram :tls :ram
+    PROVIDE( __tbss_size = SIZEOF(.tbss) );
+    PROVIDE( __tls_size = __tls_end - __tls_base );
+
+    .tbss_space : ALIGN(8) {
+	. = . + __tbss_size;
+    } >ram :ram
+
+    .bss (NOLOAD): ALIGN(8) {
+        *(.sbss*)
+        *(.gnu.linkonce.sb.*)
+        *(.bss .bss.*)
+        *(.gnu.linkonce.b.*)
+        *(COMMON)
+    } >ram :ram
+
+    PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
+    PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
+
+ 
+
+    .stack (NOLOAD) : ALIGN(16) {
+        PROVIDE(metal_segment_stack_begin = .);
+        . += __stack_size; /* Hart 0 */
+        PROVIDE( _sp = . );
+        PROVIDE(metal_segment_stack_end = .);
+    } >ram :ram
+
+    .heap (NOLOAD) : ALIGN(8) {
+        PROVIDE( __end = . );
+        PROVIDE( __heap_start = . );
+        PROVIDE( metal_segment_heap_target_start = . );
+        /* If __heap_max is defined, grow the heap to use the rest of RAM,
+         * otherwise set the heap size to __heap_size */
+        . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
+        PROVIDE( metal_segment_heap_target_end = . );
+        PROVIDE( _heap_end = . );
+        PROVIDE( __heap_end = . );
+    } >ram :ram
+
+    /* C++ exception handling information is
+     * not useful with our current runtime environment,
+     * and it consumes flash space. Discard it until
+     * we have something that can use it
+     */
+    /DISCARD/ : {
+	*(.eh_frame .eh_frame.*)
+    }
+}
\ No newline at end of file
diff --git a/bsp/sparkfun-redv/settings.mk b/bsp/sparkfun-redv/settings.mk
new file mode 100644
index 00000000..a8ddd99f
--- /dev/null
+++ b/bsp/sparkfun-redv/settings.mk
@@ -0,0 +1,13 @@
+# Copyright (C) 2020 SiFive Inc
+# SPDX-License-Identifier: Apache-2.0
+
+RISCV_ARCH = rv32imac
+RISCV_ABI = ilp32
+RISCV_CMODEL = medlow
+RISCV_SERIES = sifive-3-series
+
+TARGET_TAGS = board jlink
+TARGET_DHRY_ITERS = 20000000
+TARGET_CORE_ITERS = 5000
+TARGET_FREERTOS_WAIT_MS = 1000
+TARGET_INTR_WAIT_CYCLE  = 0
\ No newline at end of file