I find it a useful tool. Maybe you will, too!
                
                
                
                    
                
                    
                
                
                
                
                
                
                
                
                
                
                        flash: Memory.MappedMemory @ sysbus 0x00000000
                            size: 0x00008000
                        sram: Memory.MappedMemory @ sysbus 0x20000000
                            size: 0x00001000
    
                        nvic: IRQControllers.NVIC @ sysbus 0xE000E000
                            IRQ -> cpu@0
                        cpu: CPU.CortexM @ sysbus
                            nvic: nvic
                            cpuType: "cortex-m0+"
                            PerformanceInMips: 24
                    
                Firmware is a series of instructions executed by the CPU in order to accomplish a task
Firmware is Memory
                        sysbus LoadELF @firmware.elf
                    
                    
                        sysbus LoadBinary @rom.bin 0x20000000
                    
                    
                        sysbus LoadSymbolsFrom @rom.elf
                    
                LoadBinary!
                        
                        sysbus.cpu VectorTableOffset 0x20000000
                        sysbus.cpu PC 0x20000c00
                    
                
                    
                
                
                
                        flash: Memory.MappedMemory @ sysbus 0x00000000
                            size: 0x00008000
                        sram: Memory.MappedMemory @ sysbus 0x20000000
                            size: 0x00001000
                            
                        nvic: IRQControllers.NVIC @ sysbus 0xE000E000
                            IRQ -> cpu@0
                        // 👇 Add a UART with IRQ #10 at address 0x40300000
                        uart: UART.PL011 @ sysbus 0x40300000
                            -> nvic@10
                    
                        cpu: CPU.CortexM @ sysbus
                            nvic: nvic
                            cpuType: "cortex-m0+"
                            PerformanceInMips: 24
                    
                
                
                    //
                    // Copyright (c) 2010-2018 Antmicro
                    //
                    // This file is licensed under the MIT License.
                    // Full license text is available in 'licenses/MIT.txt'.
                    //
                    using System.Collections.Generic;
                    using Antmicro.Renode.Peripherals.Bus;
                    using Antmicro.Renode.Core.Structure.Registers;
                    using Antmicro.Renode.Core;
                    using Antmicro.Renode.Logging;
                    
                    namespace Antmicro.Renode.Peripherals.UART
                    {
                        public class LiteX_UART : UARTBase, IDoubleWordPeripheral, IBytePeripheral, IKnownSize
                        {
                            public LiteX_UART(Machine machine) : base(machine)
                            {
                                IRQ = new GPIO();
                                var registersMap = new Dictionary
                                {
                    {(long)Registers.RxTx, new DoubleWordRegister(this)
                    .WithValueField(0, 8,
                        writeCallback: (_, value) => 
                            this.TransmitCharacter((byte)value),
                        valueProviderCallback: _ => {
                            if(!TryGetCharacter(out var character))
                            {
                                this.Log(LogLevel.Warning, "Empty Rx FIFO.");
                            }
                            return character;
                        })
                    },
                                    {(long)Registers.TxFull, new DoubleWordRegister(this)
                                        .WithFlag(0, FieldMode.Read) //tx is never full
                                    },
                                    {(long)Registers.RxEmpty, new DoubleWordRegister(this)
                                        .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => Count == 0)
                                    },
                                    {(long)Registers.EventPending, new DoubleWordRegister(this)
                                        // `txEventPending` implements `WriteOneToClear` semantics to avoid fake warnings
                                        // `txEventPending` is generated on the falling edge of TxFull; in our case it means never
                                        .WithFlag(0, FieldMode.Read | FieldMode.WriteOneToClear, valueProviderCallback: _ => false, name: "txEventPending")
                                        .WithFlag(1, out rxEventPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "rxEventPending")
                                        .WithWriteCallback((_, __) => UpdateInterrupts())
                                    },
                                    {(long)Registers.EventEnable, new DoubleWordRegister(this)
                                        .WithFlag(0, name: "txEventEnabled")
                                        .WithFlag(1, out rxEventEnabled)
                                        .WithWriteCallback((_, __) => UpdateInterrupts())
                                    },
                                };
                    
                                registers = new DoubleWordRegisterCollection(this, registersMap);
                            }
                    
                            public uint ReadDoubleWord(long offset)
                            {
                                return registers.Read(offset);
                            }
                    
                            public byte ReadByte(long offset)
                            {
                                if(offset % 4 != 0)
                                {
                                    // in the current configuration, only the lowest byte
                                    // contains a meaningful data
                                    return 0;
                                }
                                return (byte)ReadDoubleWord(offset);
                            }
                    
                            public override void Reset()
                            {
                                base.Reset();
                                registers.Reset();
                    
                                UpdateInterrupts();
                            }
                    
                            public void WriteDoubleWord(long offset, uint value)
                            {
                                registers.Write(offset, value);
                            }
                                
                            public void WriteByte(long offset, byte value)
                            {
                                if(offset % 4 != 0)
                                {
                                    // in the current configuration, only the lowest byte
                                    // contains a meaningful data
                                    return;
                                }
                    
                                WriteDoubleWord(offset, value);
                            }
                            
                            public long Size => 0x100;
                    
                            public GPIO IRQ { get; private set; }
                    
                            public override Bits StopBits => Bits.One;
                    
                            public override Parity ParityBit => Parity.None;
                    
                            public override uint BaudRate => 115200;
                    
                            protected override void CharWritten()
                            {
                                UpdateInterrupts();
                            }
                    
                            protected override void QueueEmptied()
                            {
                                UpdateInterrupts();
                            }
                    
                            private void UpdateInterrupts()
                            {
                                // rxEventPending is latched
                                rxEventPending.Value = (Count != 0);
                    
                                // tx fifo is never full, so `txEventPending` is always false
                                var eventPending = (rxEventEnabled.Value && rxEventPending.Value);
                                IRQ.Set(eventPending);
                            }
                    
                            private IFlagRegisterField rxEventEnabled;
                            private IFlagRegisterField rxEventPending;
                            private readonly DoubleWordRegisterCollection registers;
                    
                            private enum Registers : long
                            {
                                RxTx = 0x0,
                                TxFull = 0x04,
                                RxEmpty = 0x08,
                                EventStatus = 0x0c,
                                EventPending = 0x10,
                                EventEnable = 0x14,
                            }
                        }
                    }
                     
                
                
                
                
                            *** Settings ***
                                Suite Setup                   Setup
                                Suite Teardown                Teardown
                                Test Setup                    Reset Emulation
                                Test Teardown                 Test Teardown
                                Resource                      ${RENODEKEYWORDS}
                                
                            *** Variables ***
                                ${UART}   sysbus.uart0
                                ${URI}    @https://dl.antmicro.com/projects/renode
                                
                                ${LIS2DS12}=     SEPARATOR=
                                ...  """                                                 ${\n}
                                ...  using "platforms/cpus/nrf52840.repl"                ${\n}
                                ...                                                      ${\n}
                                ...  lis2ds12: Sensors.LIS2DS12 @ twi1 0x1c              ${\n}
                                ...  ${SPACE*4}IRQ -> gpio0@28                           ${\n}
                                ...  """
                            *** Keywords ***
                            Create Machine
                                Execute Command  mach create
                                Execute Command  machine 
                                    ... LoadPlatformDescriptionFromString ${LIS2DS12}
                                Execute Command  sysbus LoadELF 
                                    ... ${URI}/nrf52840--zephyr_lis2dh.elf-s_747800-163b7e7cc986d4b1115f06b5f3df44ed0defc1fa
                            *** Test Cases ***
                            Should Read Acceleration
                                Create Machine
                                Create Terminal Tester    ${UART}
                            
                                Execute Command sysbus.twi1.lis2ds12 AccelerationX 10
                                Execute Command sysbus.twi1.lis2ds12 AccelerationY 5
                                Execute Command sysbus.twi1.lis2ds12 AccelerationZ -5
                            
                                Start Emulation
                            
                                Wait For Line On Uart  
                                    ... x 9.997213 , y 4.997410 , z -4.999803
                        
                
                        
                        
                            STMicroelectronics 
                            ST 
                            BlueNRG2 
                            BlueNRG1 
                            1.0.0 
                            ARM 32-bit Cortex-M0 Microcontroller based device, CPU clock up to 32MHz 
                            License 
                            
                                CM0 
                                r0p0 
                                little 
                                false 
                                false 
                                2 
                                false 
                             
                            8 
                            32 
                            32 
                            read-write 
                            0x00000000 
                            0xFFFFFFFF 
                            
                                
                                    RNG 
                                    1.0 
                                    RNG 
                                    RNG 
                                    0xB0000000 
                                    32 
                                    read-write 
                                    
                                        0 
                                        0x1000 
                                        registers 
                                     
                                    
                                        
                                            CR 
                                            RNG configuration register 
                                            0x00 
                                            32 
                                            read-write 
                                            0x00000000 
                                            0x0000FFFF 
                                            
                                                
                                                    DIS 
                                                    Set the state of the random number generator.<ul><li>0: RNG is enable.</li><li>1: RNG is disabled. The internal free-running oscillators are put in power-down mode and the RNG clock is stopped at the input of the block.</li></ul> 
                                                    2 
                                                    1 
                                                    read-write 
                                                 
                                             
                                         
                                        
                                            SR 
                                            RNG status register 
                                            0x04 
                                            32 
                                            read-only 
                                            0x00000000 
                                            0x0000FFFF 
                                            
                                                
                                                    RDY 
                                                    New random value ready.<ul><li>0: The RNG_VAL register value is not yet valid. If performing a read access to VAL, the host will be put on hold (by wait-states insertion on the AHB bus) until a random value is available.</li><li>1: The VAL register contains a valid random number.</li></ul>This bit remains at 0 when the RNG is disabled (RNGDIS bit = 1b in CR) 
                                                    0 
                                                    1 
                                                    read-only 
                                                 
                                             
                                         
                                        
                                            VAL 
                                            RNG 16 bit random value 
                                            0x08 
                                            32 
                                            read-only 
                                            0x00000000 
                                            0x0000FFFF 
                                         
                                         
                                 
                             
                         
                        
                
                        sysbus ApplySVD @BlueNRG2.svd