using System; using VMdemo.Core; namespace VMdemo.Simulation { public class AddressGenerator { public const int DefaultSeed = 12345; private readonly ulong _vaMask; private readonly Random _random; private readonly byte[] _buffer = new byte[8]; private readonly AddressGenerationMode _mode; private readonly ulong _arrayBaseAddress; private readonly ulong _arrayElementBytes; private readonly ulong _arrayElementCount; private ulong _nextArrayIndex; public AddressGenerator( int vaBits, int? seed = null, AddressGenerationMode mode = AddressGenerationMode.RandomUniform, int arrayLengthBytes = 256, int arrayElementBytes = 4, int arrayBaseAddress = 0) { if (vaBits != 8 && vaBits != 16 && vaBits != 24) { throw new ArgumentOutOfRangeException(nameof(vaBits), "vaBits 仅支持 8、16、24。"); } _vaMask = (1UL << vaBits) - 1UL; _random = new Random(seed ?? DefaultSeed); _mode = mode; if (arrayLengthBytes <= 0) { throw new ArgumentOutOfRangeException(nameof(arrayLengthBytes), "arrayLengthBytes 必须是正整数。"); } if (arrayElementBytes <= 0) { throw new ArgumentOutOfRangeException(nameof(arrayElementBytes), "arrayElementBytes 必须是正整数。"); } if (arrayBaseAddress < 0) { throw new ArgumentOutOfRangeException(nameof(arrayBaseAddress), "arrayBaseAddress 不能为负数。"); } if (mode == AddressGenerationMode.SequentialArrayLoop && arrayLengthBytes < arrayElementBytes) { throw new ArgumentOutOfRangeException( nameof(arrayLengthBytes), "SequentialArrayLoop 模式下 arrayLengthBytes 必须 >= arrayElementBytes。"); } _arrayBaseAddress = (ulong)arrayBaseAddress; _arrayElementBytes = (ulong)arrayElementBytes; _arrayElementCount = Math.Max(1UL, (ulong)arrayLengthBytes / _arrayElementBytes); var maxGenerated = _arrayBaseAddress + (_arrayElementCount - 1UL) * _arrayElementBytes; if (maxGenerated > _vaMask) { throw new ArgumentOutOfRangeException( nameof(arrayLengthBytes), $"数组访问地址超出 vaBits 范围。maxGenerated={maxGenerated}, maxVA={_vaMask}"); } } public ulong MaxVirtualAddress => _vaMask; public ulong NextVirtualAddress() { return _mode == AddressGenerationMode.SequentialArrayLoop ? NextArrayLoopAddress() : (NextRawUlong() & _vaMask); } private ulong NextRawUlong() { _random.NextBytes(_buffer); return BitConverter.ToUInt64(_buffer, 0); } private ulong NextArrayLoopAddress() { var address = _arrayBaseAddress + _nextArrayIndex * _arrayElementBytes; _nextArrayIndex = (_nextArrayIndex + 1UL) % _arrayElementCount; return address; } } }