179 lines
5.4 KiB
C#
179 lines
5.4 KiB
C#
using System;
|
||
|
||
namespace VMdemo.Core
|
||
{
|
||
public static class ConfigValidator
|
||
{
|
||
public readonly struct DerivedConfig
|
||
{
|
||
public DerivedConfig(ulong pageSizeBytes, ulong physicalMemoryBytes, int offsetBits, int vpnBits, ulong frameCount)
|
||
{
|
||
PageSizeBytes = pageSizeBytes;
|
||
PhysicalMemoryBytes = physicalMemoryBytes;
|
||
OffsetBits = offsetBits;
|
||
VpnBits = vpnBits;
|
||
FrameCount = frameCount;
|
||
}
|
||
|
||
public ulong PageSizeBytes { get; }
|
||
public ulong PhysicalMemoryBytes { get; }
|
||
public int OffsetBits { get; }
|
||
public int VpnBits { get; }
|
||
public ulong FrameCount { get; }
|
||
}
|
||
|
||
public static bool TryValidate(SimulationConfig config, out string errorMessage)
|
||
{
|
||
return TryValidateAndBuildDerived(config, out _, out errorMessage);
|
||
}
|
||
|
||
public static bool TryValidateAndBuildDerived(
|
||
SimulationConfig config,
|
||
out DerivedConfig derived,
|
||
out string errorMessage)
|
||
{
|
||
derived = default;
|
||
|
||
if (config == null)
|
||
{
|
||
errorMessage = "配置不能为空。";
|
||
return false;
|
||
}
|
||
|
||
if (config.machineBits <= 0 || config.machineBits > 64)
|
||
{
|
||
errorMessage = "machineBits 必须在 1 到 64 之间。";
|
||
return false;
|
||
}
|
||
|
||
if (config.vaBits != 8 && config.vaBits != 16 && config.vaBits != 24)
|
||
{
|
||
errorMessage = "vaBits 仅支持 8、16、24。";
|
||
return false;
|
||
}
|
||
|
||
if (config.vaBits > config.machineBits)
|
||
{
|
||
errorMessage = $"vaBits 不能大于 machineBits,当前 vaBits={config.vaBits}, machineBits={config.machineBits}。";
|
||
return false;
|
||
}
|
||
|
||
if (config.pageSizeKB <= 0)
|
||
{
|
||
errorMessage = "pageSizeKB 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (!IsPowerOfTwo((ulong)config.pageSizeKB))
|
||
{
|
||
errorMessage = "pageSizeKB 必须是 2 的幂(2^n KB)。";
|
||
return false;
|
||
}
|
||
|
||
if (config.physicalMemoryMB <= 0)
|
||
{
|
||
errorMessage = "physicalMemoryMB 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.tlbEntries <= 0)
|
||
{
|
||
errorMessage = "tlbEntries 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.accessCount <= 0)
|
||
{
|
||
errorMessage = "accessCount 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.pageFaultPenalty <= 0)
|
||
{
|
||
errorMessage = "pageFaultPenalty 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.arrayLengthBytes <= 0)
|
||
{
|
||
errorMessage = "arrayLengthBytes 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.arrayElementBytes <= 0)
|
||
{
|
||
errorMessage = "arrayElementBytes 必须是正整数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.arrayBaseAddress < 0)
|
||
{
|
||
errorMessage = "arrayBaseAddress 不能为负数。";
|
||
return false;
|
||
}
|
||
|
||
if (config.addressGenerationMode == AddressGenerationMode.SequentialArrayLoop &&
|
||
config.arrayLengthBytes < config.arrayElementBytes)
|
||
{
|
||
errorMessage = "SequentialArrayLoop 模式下 arrayLengthBytes 必须 >= arrayElementBytes。";
|
||
return false;
|
||
}
|
||
|
||
var pageSizeBytes = config.PageSizeBytes;
|
||
if (!TryGetLog2(pageSizeBytes, out var offsetBits))
|
||
{
|
||
errorMessage = "pageSizeKB 必须对应可计算的 2 的幂字节数。";
|
||
return false;
|
||
}
|
||
|
||
if (offsetBits >= config.vaBits)
|
||
{
|
||
errorMessage =
|
||
$"offsetBits 必须小于 vaBits,当前 offsetBits={offsetBits},vaBits={config.vaBits}。";
|
||
return false;
|
||
}
|
||
|
||
var frameCount = config.FrameCount;
|
||
if (frameCount < 1UL)
|
||
{
|
||
errorMessage =
|
||
$"frameCount 必须 >= 1,当前 frameCount={frameCount}。请增大 physicalMemoryMB 或减小 pageSizeKB。";
|
||
return false;
|
||
}
|
||
|
||
derived = new DerivedConfig(
|
||
pageSizeBytes,
|
||
config.PhysicalMemoryBytes,
|
||
offsetBits,
|
||
config.vaBits - offsetBits,
|
||
frameCount);
|
||
|
||
errorMessage = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
private static bool IsPowerOfTwo(ulong value)
|
||
{
|
||
return value != 0UL && (value & (value - 1UL)) == 0UL;
|
||
}
|
||
|
||
private static bool TryGetLog2(ulong value, out int bits)
|
||
{
|
||
bits = -1;
|
||
if (!IsPowerOfTwo(value))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
bits = 0;
|
||
while (value > 1UL)
|
||
{
|
||
value >>= 1;
|
||
bits++;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
}
|
||
}
|