94 lines
3.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|