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/Simulation/AddressGenerator.cs

94 lines
3.3 KiB
C#

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