[#69049] Add SystemC cosimulation tests
diff --git a/tests/platforms/systemc/dma/dma.robot b/tests/platforms/systemc/dma/dma.robot
new file mode 100644
index 0000000..5313ab1
--- /dev/null
+++ b/tests/platforms/systemc/dma/dma.robot
@@ -0,0 +1,65 @@
+*** Variables ***
+${SYSTEMC_BINARY} @https://dl.antmicro.com/projects/renode/x64-systemc--dma.elf-s_943520-d936f6165ff706163a1d722c301a11a55672c365
+${PLATFORM}= SEPARATOR=
+... """ ${\n}
+... memory: Memory.MappedMemory @ sysbus 0x20000000 ${\n}
+... ${SPACE*4}size: 0x1000000 ${\n}
+... ${\n}
+... dma_systemc: SystemC.SystemCPeripheral @ sysbus <0x9000000, +0xffffff> ${\n}
+... ${SPACE*4}address: "127.0.0.1" ${\n}
+... ${SPACE*4}timeSyncPeriodUS: 5000 ${\n}
+... """
+
+*** Keywords ***
+Create Machine
+ Execute Command mach create
+ Execute Command machine LoadPlatformDescriptionFromString ${PLATFORM}
+ Execute Command sysbus.dma_systemc SystemCExecutablePath ${SYSTEMC_BINARY}
+
+Memory Should Be Equal To
+ [Arguments] ${address} ${value}
+ ${res}= Execute Command sysbus ReadByte ${address}
+ Should Be Equal As Numbers ${res} ${value}
+
+*** Test Cases ***
+Should Perform Memory-To-Memory Transfer
+ [Tags] skip_windows skip_osx
+ Create Machine
+ Start Emulation
+
+ # Initialize memory
+ Execute Command sysbus.memory WriteString 0 "Hello"
+
+ # Make sure memory destination is initialized to 0
+ Memory Should Be Equal To 0x20000010 0
+ Memory Should Be Equal To 0x20000011 0
+ Memory Should Be Equal To 0x20000012 0
+ Memory Should Be Equal To 0x20000013 0
+ Memory Should Be Equal To 0x20000014 0
+
+ # Set source address register in dma_systemc.
+ Execute Command sysbus WriteDoubleWord 0x9000004 0x20000000
+
+ # Set destination address register in dma_systemc.
+ Execute Command sysbus WriteDoubleWord 0x9000008 0x20000010
+
+ # Set data length register (in bytes) in dma_systemc.
+ Execute Command sysbus WriteDoubleWord 0x900000C 5
+
+ # Start memory-to-memory transfer in dma_systemc
+ Execute Command sysbus WriteDoubleWord 0x9000010 0x1
+
+ # Signal "bus free" to notify DMAC it can use the bus now.
+ Execute Command sysbus.dma_systemc OnGPIO 2 True
+
+ # Verify the memory was copied correctly.
+ # "H"
+ Memory Should Be Equal To 0x20000010 0x48
+ # "e"
+ Memory Should Be Equal To 0x20000011 0x65
+ # "l"
+ Memory Should Be Equal To 0x20000012 0x6C
+ # "l"
+ Memory Should Be Equal To 0x20000013 0x6C
+ # "o"
+ Memory Should Be Equal To 0x20000014 0x6F
diff --git a/tests/platforms/systemc/interrupts/interrupts.repl b/tests/platforms/systemc/interrupts/interrupts.repl
new file mode 100644
index 0000000..734cdbe
--- /dev/null
+++ b/tests/platforms/systemc/interrupts/interrupts.repl
@@ -0,0 +1,79 @@
+flash0: Memory.MappedMemory @ sysbus 0x8000000
+ size: 0x40000
+
+sram0: Memory.MappedMemory @ sysbus 0x20000000
+ size: 0x10000
+
+timers4: Timers.STM32_Timer @ sysbus <0x40000800, +0x400>
+ frequency: 10000000
+ initialLimit: 0xffffffff
+ ->nvic0@30
+
+usart1: UART.STM32_UART @ sysbus <0x40011000, +0x400>
+ ->nvic0@37
+
+gpioa: GPIOPort.STM32_GPIOPort @ sysbus <0x40020000, +0x400>
+
+gpiob: GPIOPort.STM32_GPIOPort @ sysbus <0x40020400, +0x400>
+
+gpioc: GPIOPort.STM32_GPIOPort @ sysbus <0x40020800, +0x400>
+
+gpiod: GPIOPort.STM32_GPIOPort @ sysbus <0x40020c00, +0x400>
+
+gpioe: GPIOPort.STM32_GPIOPort @ sysbus <0x40021000, +0x400>
+
+gpiof: GPIOPort.STM32_GPIOPort @ sysbus <0x40021400, +0x400>
+
+gpiog: GPIOPort.STM32_GPIOPort @ sysbus <0x40021800, +0x400>
+
+gpioh: GPIOPort.STM32_GPIOPort @ sysbus <0x40021c00, +0x400>
+
+// autogenerated
+
+userled: Miscellaneous.LED @ gpioc 0xd
+ invert: true
+
+gpioc:
+ 13 -> userled@0
+
+nvic0: IRQControllers.NVIC @ {
+ sysbus new Bus.BusPointRegistration { address: 0xe000e000; cpu: cpu0 }
+}
+ -> cpu0@0
+
+cpu0: CPU.CortexM @ sysbus
+ cpuType: "cortex-m4f"
+ nvic: nvic0
+
+i2c1: I2C.STM32F4_I2C @ sysbus 0x40005400
+ EventInterrupt->nvic0@31
+ ErrorInterrupt->nvic0@32
+
+rtc: Timers.STM32F4_RTC @ sysbus 0x40002800
+ AlarmIRQ->nvic0@41
+
+rcc: Miscellaneous.STM32F4_RCC @ sysbus 0x40023800
+ rtcPeripheral: rtc
+
+spi1: SPI.STM32SPI @ sysbus 0x40013000
+ IRQ->nvic0@35
+
+adc1: Analog.STM32_ADC @ sysbus 0x40012000
+ IRQ->nvic0@18
+
+// st,stm32f4 overlay
+
+sysbus:
+ init:
+ ApplySVD @https://dl.antmicro.com/projects/renode/svd/STM32F40x.svd.gz
+
+// cortex-m overlay
+
+dwt: Miscellaneous.DWT @ sysbus 0xE0001000
+ frequency: 72000000
+
+systemc: SystemC.SystemCPeripheral @ sysbus <0x9000000, +0xffffff>
+ address: "127.0.0.1"
+ timeSyncPeriodUS: 5000
+ 0 -> nvic0@55
+ 1 -> nvic0@56
diff --git a/tests/platforms/systemc/interrupts/interrupts.robot b/tests/platforms/systemc/interrupts/interrupts.robot
new file mode 100644
index 0000000..90d07d8
--- /dev/null
+++ b/tests/platforms/systemc/interrupts/interrupts.robot
@@ -0,0 +1,22 @@
+*** Variables ***
+${ZEPHYR_BINARY} @https://dl.antmicro.com/projects/renode/systemc-examples-zephyr-interrupts-stm32f401_mini.elf-s_573712-209c153accbf90335274ee5ae16eb9abb74d7808
+${SYSTEMC_BINARY} @https://dl.antmicro.com/projects/renode/x64-systemc--interrupts.elf-s_1017672-89c2d9745bc1fbc82c3ee727ae0d248415ed6d35
+${PLATFORM} @tests/platforms/systemc/interrupts/interrupts.repl
+${UART} sysbus.usart1
+
+*** Keywords ***
+Create Machine
+ Execute Command mach create
+ Execute Command machine LoadPlatformDescription ${PLATFORM}
+ Execute Command sysbus LoadELF ${ZEPHYR_BINARY}
+ Execute Command sysbus.systemc SystemCExecutablePath ${SYSTEMC_BINARY}
+
+*** Test Cases ***
+Should Invoke Interrupt Handlers Initiated By SystemC
+ [Tags] skip_windows skip_osx
+ Create Machine
+ Create Terminal Tester ${UART}
+ Start Emulation
+
+ Wait For Line On Uart Interrupt handler for interrupter 0 (every 1 second)
+ Wait For Line On Uart Interrupt handler for interrupter 1 (every 3 seconds)
diff --git a/tests/platforms/systemc/multiple-peripherals/multiple-peripherals.repl b/tests/platforms/systemc/multiple-peripherals/multiple-peripherals.repl
new file mode 100644
index 0000000..b1eee35
--- /dev/null
+++ b/tests/platforms/systemc/multiple-peripherals/multiple-peripherals.repl
@@ -0,0 +1,95 @@
+flash0: Memory.MappedMemory @ sysbus 0x8000000
+ size: 0x40000
+
+sram0: Memory.MappedMemory @ sysbus 0x20000000
+ size: 0x10000
+
+timers4: Timers.STM32_Timer @ sysbus <0x40000800, +0x400>
+ frequency: 10000000
+ initialLimit: 0xffffffff
+ ->nvic0@30
+
+usart1: UART.STM32_UART @ sysbus <0x40011000, +0x400>
+ ->nvic0@37
+
+gpioa: GPIOPort.STM32_GPIOPort @ sysbus <0x40020000, +0x400>
+
+gpiob: GPIOPort.STM32_GPIOPort @ sysbus <0x40020400, +0x400>
+
+gpioc: GPIOPort.STM32_GPIOPort @ sysbus <0x40020800, +0x400>
+
+gpiod: GPIOPort.STM32_GPIOPort @ sysbus <0x40020c00, +0x400>
+
+gpioe: GPIOPort.STM32_GPIOPort @ sysbus <0x40021000, +0x400>
+
+gpiof: GPIOPort.STM32_GPIOPort @ sysbus <0x40021400, +0x400>
+
+gpiog: GPIOPort.STM32_GPIOPort @ sysbus <0x40021800, +0x400>
+
+gpioh: GPIOPort.STM32_GPIOPort @ sysbus <0x40021c00, +0x400>
+
+// autogenerated
+
+userled: Miscellaneous.LED @ gpioc 0xd
+ invert: true
+
+gpioc:
+ 13 -> userled@0
+
+nvic0: IRQControllers.NVIC @ {
+ sysbus new Bus.BusPointRegistration { address: 0xe000e000; cpu: cpu0 }
+}
+ -> cpu0@0
+
+cpu0: CPU.CortexM @ sysbus
+ cpuType: "cortex-m4f"
+ nvic: nvic0
+
+i2c1: I2C.STM32F4_I2C @ sysbus 0x40005400
+ EventInterrupt->nvic0@31
+ ErrorInterrupt->nvic0@32
+
+rtc: Timers.STM32F4_RTC @ sysbus 0x40002800
+ AlarmIRQ->nvic0@41
+
+rcc: Miscellaneous.STM32F4_RCC @ sysbus 0x40023800
+ rtcPeripheral: rtc
+
+spi1: SPI.STM32SPI @ sysbus 0x40013000
+ IRQ->nvic0@35
+
+adc1: Analog.STM32_ADC @ sysbus 0x40012000
+ IRQ->nvic0@18
+
+// st,stm32f4 overlay
+
+sysbus:
+ init:
+ ApplySVD @https://dl.antmicro.com/projects/renode/svd/STM32F40x.svd.gz
+
+// cortex-m overlay
+
+dwt: Miscellaneous.DWT @ sysbus 0xE0001000
+ frequency: 72000000
+
+systemc_peripheral_A: SystemC.SystemCPeripheral @ sysbus <0x7000000, +0xfffff>
+ address: "127.0.0.1"
+ timeSyncPeriodUS: 5000
+ init:
+ AddDirectConnection 0 systemc_peripheral_B
+ AddDirectConnection 1 systemc_peripheral_B
+
+systemc_peripheral_B: SystemC.SystemCPeripheral @ sysbus <0x7100000, +0xfffff>
+ address: "127.0.0.1"
+ timeSyncPeriodUS: 5000
+ init:
+ AddDirectConnection 0 systemc_peripheral_C
+ AddDirectConnection 1 systemc_peripheral_C
+
+systemc_peripheral_C: SystemC.SystemCPeripheral @ sysbus <0x7200000, +0xfffff>
+ address: "127.0.0.1"
+ timeSyncPeriodUS: 5000
+ init:
+ AddDirectConnection 0 systemc_peripheral_A
+ AddDirectConnection 1 systemc_peripheral_A
+ 0 -> nvic0@57
diff --git a/tests/platforms/systemc/multiple-peripherals/multiple-peripherals.robot b/tests/platforms/systemc/multiple-peripherals/multiple-peripherals.robot
new file mode 100644
index 0000000..824e9ef
--- /dev/null
+++ b/tests/platforms/systemc/multiple-peripherals/multiple-peripherals.robot
@@ -0,0 +1,23 @@
+*** Variables ***
+${SYSTEMC_BINARY} @https://dl.antmicro.com/projects/renode/x64-systemc--multiple-peripherals.elf-s_1045808-e4358ec1f6d94e52e0d946c5c6acb80e157523b5
+${ZEPHYR_BINARY} @https://dl.antmicro.com/projects/renode/systemc-examples-zephyr-multiple-peripherals-stm32f401_mini.elf-s_574416-8bc080d4e6c922e7c89a233d1f74f6d9bcb45274
+${PLATFORM} @tests/platforms/systemc/multiple-peripherals/multiple-peripherals.repl
+${UART} sysbus.usart1
+
+*** Keywords ***
+Create Machine
+ Execute Command mach create
+ Execute Command machine LoadPlatformDescription ${PLATFORM}
+ Execute Command sysbus.systemc_peripheral_A SystemCExecutablePath ${SYSTEMC_BINARY}
+ Execute Command sysbus.systemc_peripheral_B SystemCExecutablePath ${SYSTEMC_BINARY}
+ Execute Command sysbus.systemc_peripheral_C SystemCExecutablePath ${SYSTEMC_BINARY}
+ Execute Command sysbus LoadELF ${ZEPHYR_BINARY}
+
+*** Test Cases ***
+Should Run The Multiple Peripherals Example
+ [Tags] skip_windows skip_osx
+ Create Machine
+ Create Terminal Tester ${UART}
+ Start Emulation
+
+ Wait For Line On Uart Example complete!
diff --git a/tests/platforms/systemc/test-synchronization/ExecuteInLockPeripheral.cs b/tests/platforms/systemc/test-synchronization/ExecuteInLockPeripheral.cs
new file mode 100644
index 0000000..d04091e
--- /dev/null
+++ b/tests/platforms/systemc/test-synchronization/ExecuteInLockPeripheral.cs
@@ -0,0 +1,42 @@
+using Antmicro.Renode.Core;
+using Antmicro.Renode.Logging;
+using Antmicro.Renode.Time;
+using Antmicro.Renode.Peripherals.Bus;
+
+namespace Antmicro.Renode.Peripherals.Test
+{
+ class ExecuteInLockPeripheral : IBytePeripheral, IKnownSize
+ {
+ public ExecuteInLockPeripheral(Machine machine)
+ {
+ this.machine = machine;
+ }
+
+ public void Reset()
+ {
+ }
+
+ public byte ReadByte(long offset)
+ {
+ return 0;
+ }
+
+ public void WriteByte(long offset, byte value)
+ {
+ machine.ClockSource.ExecuteInLock(() =>
+ {
+ this.Log(LogLevel.Info, $"Got write request with value 0x{value:X}");
+ });
+ }
+
+ public long Size
+ {
+ get
+ {
+ return 1;
+ }
+ }
+
+ private Machine machine;
+ }
+}
diff --git a/tests/platforms/systemc/test-synchronization/synchronization.resc b/tests/platforms/systemc/test-synchronization/synchronization.resc
new file mode 100644
index 0000000..28d268b
--- /dev/null
+++ b/tests/platforms/systemc/test-synchronization/synchronization.resc
@@ -0,0 +1,10 @@
+using sysbus
+mach create "synchronization_test"
+
+include $ORIGIN/MockPeripheralWithExecuteInLock.cs
+machine LoadPlatformDescription $ORIGIN/synchronization.repl
+
+sysbus LogPeripheralAccess writer_systemc true
+sysbus LogPeripheralAccess test true
+sysbus.writer_systemc SystemCExecutablePath $ORIGIN/../bin/synchronization
+
diff --git a/tests/platforms/systemc/test-synchronization/synchronization.robot b/tests/platforms/systemc/test-synchronization/synchronization.robot
new file mode 100644
index 0000000..2ed2782
--- /dev/null
+++ b/tests/platforms/systemc/test-synchronization/synchronization.robot
@@ -0,0 +1,24 @@
+*** Variables ***
+${SYSTEMC_BINARY} @https://dl.antmicro.com/projects/renode/x64-systemc--test-synchronization.elf-s_606984-4b970b9b9da67d412220cc827634accb89619139
+${EXECUTE_IN_LOCK_PERIPHERAL} @tests/platforms/systemc/test-synchronization/ExecuteInLockPeripheral.cs
+${PLATFORM}= SEPARATOR=
+... """ ${\n}
+... test: Test.ExecuteInLockPeripheral @ sysbus 0x1000000 ${\n}
+... ${\n}
+... writer_systemc: SystemC.SystemCPeripheral @ sysbus <0x9000000, +0xffffff> ${\n}
+... ${SPACE*4}address: "127.0.0.1" ${\n}
+... ${SPACE*4}timeSyncPeriodUS: 5000 ${\n}
+... """
+
+*** Test Cases ***
+Should Not Deadlock Writing To ExecuteInLockPeripheral
+ [Tags] skip_windows skip_osx
+ Execute Command using sysbus
+ Execute Command mach create
+ Execute Command include ${EXECUTE_IN_LOCK_PERIPHERAL}
+ Execute Command machine LoadPlatformDescriptionFromString ${PLATFORM}
+ Execute Command sysbus.writer_systemc SystemCExecutablePath ${SYSTEMC_BINARY}
+ Create Log Tester 1
+ Start Emulation
+
+ Wait For Log Entry Got write request with value 0xAB
diff --git a/tests/platforms/systemc/transaction-delay/transaction-delay.repl b/tests/platforms/systemc/transaction-delay/transaction-delay.repl
new file mode 100644
index 0000000..d6d9c34
--- /dev/null
+++ b/tests/platforms/systemc/transaction-delay/transaction-delay.repl
@@ -0,0 +1,77 @@
+flash0: Memory.MappedMemory @ sysbus 0x8000000
+ size: 0x40000
+
+sram0: Memory.MappedMemory @ sysbus 0x20000000
+ size: 0x10000
+
+timers4: Timers.STM32_Timer @ sysbus <0x40000800, +0x400>
+ frequency: 10000000
+ initialLimit: 0xffffffff
+ ->nvic0@30
+
+usart1: UART.STM32_UART @ sysbus <0x40011000, +0x400>
+ ->nvic0@37
+
+gpioa: GPIOPort.STM32_GPIOPort @ sysbus <0x40020000, +0x400>
+
+gpiob: GPIOPort.STM32_GPIOPort @ sysbus <0x40020400, +0x400>
+
+gpioc: GPIOPort.STM32_GPIOPort @ sysbus <0x40020800, +0x400>
+
+gpiod: GPIOPort.STM32_GPIOPort @ sysbus <0x40020c00, +0x400>
+
+gpioe: GPIOPort.STM32_GPIOPort @ sysbus <0x40021000, +0x400>
+
+gpiof: GPIOPort.STM32_GPIOPort @ sysbus <0x40021400, +0x400>
+
+gpiog: GPIOPort.STM32_GPIOPort @ sysbus <0x40021800, +0x400>
+
+gpioh: GPIOPort.STM32_GPIOPort @ sysbus <0x40021c00, +0x400>
+
+// autogenerated
+
+userled: Miscellaneous.LED @ gpioc 0xd
+ invert: true
+
+gpioc:
+ 13 -> userled@0
+
+nvic0: IRQControllers.NVIC @ {
+ sysbus new Bus.BusPointRegistration { address: 0xe000e000; cpu: cpu0 }
+}
+ -> cpu0@0
+
+cpu0: CPU.CortexM @ sysbus
+ cpuType: "cortex-m4f"
+ nvic: nvic0
+
+i2c1: I2C.STM32F4_I2C @ sysbus 0x40005400
+ EventInterrupt->nvic0@31
+ ErrorInterrupt->nvic0@32
+
+rtc: Timers.STM32F4_RTC @ sysbus 0x40002800
+ AlarmIRQ->nvic0@41
+
+rcc: Miscellaneous.STM32F4_RCC @ sysbus 0x40023800
+ rtcPeripheral: rtc
+
+spi1: SPI.STM32SPI @ sysbus 0x40013000
+ IRQ->nvic0@35
+
+adc1: Analog.STM32_ADC @ sysbus 0x40012000
+ IRQ->nvic0@18
+
+// st,stm32f4 overlay
+
+sysbus:
+ init:
+ ApplySVD @https://dl.antmicro.com/projects/renode/svd/STM32F40x.svd.gz
+
+// cortex-m overlay
+
+dwt: Miscellaneous.DWT @ sysbus 0xE0001000
+ frequency: 72000000
+
+systemc: SystemC.SystemCPeripheral @ sysbus <0x9000000, 0x9000001>
+ address: "127.0.0.1"
+ timeSyncPeriodUS: 5000
diff --git a/tests/platforms/systemc/transaction-delay/transaction-delay.robot b/tests/platforms/systemc/transaction-delay/transaction-delay.robot
new file mode 100644
index 0000000..9f47da5
--- /dev/null
+++ b/tests/platforms/systemc/transaction-delay/transaction-delay.robot
@@ -0,0 +1,32 @@
+*** Variables ***
+${SYSTEMC_BINARY} @https://dl.antmicro.com/projects/renode/x64-systemc--transaction-delay.elf-s_730520-71a2e317e0f42799b7679af5dba036e918a7146e
+${ZEPHYR_BINARY} @https://dl.antmicro.com/projects/renode/systemc-examples-zephyr-transaction-delay-stm32f401_mini.elf-s_572316-f591f8f491f1f3480aa6f7284d2bdbef3bebb8d5
+${UART} sysbus.usart1
+
+*** Keywords ***
+Create Machine
+ Execute Command mach create
+ Execute Command machine LoadPlatformDescription @tests/platforms/systemc/transaction-delay/transaction-delay.repl
+ Execute Command sysbus LoadELF ${ZEPHYR_BINARY}
+ Execute Command systemc SystemCExecutablePath ${SYSTEMC_BINARY}
+
+Virtual Time Should Be Equal To
+ [Arguments] ${time_string}
+ ${res}= Execute Command machine ElapsedVirtualTime
+ Should Contain ${res} Elapsed Virtual Time: ${time_string}
+
+*** Test Cases ***
+Should Respect SystemC Transaction Durations
+ [Tags] skip_windows skip_osx
+ Create Machine
+ Create Terminal Tester ${UART}
+ Start Emulation
+
+ Wait For Line On Uart SystemC virtual time (1s transaction delay): 1 s
+ Virtual Time Should Be Equal To 00:00:02
+
+ Wait For Line On Uart SystemC virtual time (1s transaction delay): 2 s
+ Virtual Time Should Be Equal To 00:00:03
+
+ Wait For Line On Uart SystemC virtual time (1s transaction delay): 6 s
+ Virtual Time Should Be Equal To 00:00:07
diff --git a/tests/tests.yaml b/tests/tests.yaml
index b26b7bc..2bbadc2 100644
--- a/tests/tests.yaml
+++ b/tests/tests.yaml
@@ -179,3 +179,7 @@
- tests/platforms/MSP430X.robot
- tests/unit-tests/riscv-zve-extension.robot
- tests/unit-tests/sync_pc.robot
+- tests/platforms/systemc/interrupts/interrupts.robot
+- tests/platforms/systemc/multiple-peripherals/multiple-peripherals.robot
+- tests/platforms/systemc/transaction-delay/transaction-delay.robot
+- tests/platforms/systemc/test-synchronization/synchronization.robot