This repository has been archived on 2026-04-18. You can view files and clone it, but cannot push or open issues or pull requests.
Virtual-Memory-Demo/Assets/Scripts/Core/ConfigValidator.cs

179 lines
5.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}