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.vaBits != 32 && config.vaBits != 48 && config.vaBits != 64) { errorMessage = "vaBits 仅支持 32、48、64。"; 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; } 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; } } }