Files
simulation_core/tests/unit-tests/ArrayMemoryRiscVTestWatcher.cs

99 lines
3.4 KiB
C#
Raw Permalink Normal View History

//
// Copyright (c) 2010-2026 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
using Antmicro.Renode.Logging;
using Antmicro.Renode.Utilities;
namespace Antmicro.Renode.Peripherals.Memory
{
public class ArrayMemoryRiscVTestWatcher : ArrayMemory
{
public ArrayMemoryRiscVTestWatcher(ulong size) : base(size)
{
}
public ArrayMemoryRiscVTestWatcher(byte[] source) : base(source)
{
}
public override void WriteQuadWord(long offset, ulong value)
{
base.WriteQuadWord(offset, value);
WatchTestResult(offset, value);
}
public override void WriteDoubleWord(long offset, uint value)
{
base.WriteDoubleWord(offset, value);
WatchTestResult(offset, value);
}
public override void WriteWord(long offset, ushort value)
{
base.WriteWord(offset, value);
WatchTestResult(offset, value);
}
public override void WriteByte(long offset, byte value)
{
base.WriteByte(offset, value);
WatchTestResult(offset, value);
}
// If LSB(value) == 1 the test is finished.
// The exit code is (value >> 1).
// If exit code is zero - test passed
// else test failed.
// [1] https://github.com/riscv-software-src/riscv-isa-sim/blob/6dda4896cb06fb8c2981ae35856e101fa6e8ed13/fesvr/syscall.cc#L211-L224
// [2] https://github.com/riscv-software-src/riscv-isa-sim/blob/6dda4896cb06fb8c2981ae35856e101fa6e8ed13/fesvr/htif.cc#L320-L323
// [3] https://github.com/riscv-software-src/riscv-isa-sim/blob/6dda4896cb06fb8c2981ae35856e101fa6e8ed13/fesvr/syscall.cc#L228
// [4] https://github.com/riscv/riscv-test-env/issues/13
// [5] https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754
private void WatchTestResult(long offset, ulong value)
{
if(offset != 0x0)
{
return;
}
if(TestFinished)
{
// After test finished, it usually loops indefinitely on the test result procedure.
// Spike simulator intercepts the result value and exits the process with the exit code
// set to that value [1][2]][3]. In renode it's unpopular practice to quit renode as a result of program
// behavior, so the value should be checked by the observer (Robot Framework test)
// and decide what to do with pass/failure.
return;
}
// See [4] above.
if((value & TestFinishedMarker) != TestFinishedMarker)
{
// Some value was written, but it's not the end of the test yet.
return;
}
TestFinished = true;
this.InfoLog("TEST FINISHED");
// See [5] above.
var quadValue = this.ReadQuadWord(0);
ExitCode = quadValue >> 1;
if(ExitCode == 0)
{
this.InfoLog("TEST PASSED");
}
else
{
this.ErrorLog("TEST FAILED WITH EXIT CODE {0}", ExitCode);
}
}
public bool TestFinished { get; private set; }
public ulong ExitCode { get; private set; }
private const ulong TestFinishedMarker = 1;
}
}