Step 2 - 地址生成与拆分

This commit is contained in:
2026-04-14 00:56:38 +08:00
parent 7eab504f4a
commit 4ab93d7806
7 changed files with 266 additions and 10 deletions
@@ -0,0 +1,71 @@
using System;
namespace VMdemo.Core
{
public static class AddressTranslatorUtils
{
public static AddressParts SplitVirtualAddress(ulong virtualAddress, int vaBits, int offsetBits)
{
if (vaBits <= 0 || vaBits > 64)
{
throw new ArgumentOutOfRangeException(nameof(vaBits), "vaBits 必须在 1 到 64 之间。");
}
if (offsetBits < 0 || offsetBits >= vaBits)
{
throw new ArgumentOutOfRangeException(nameof(offsetBits), "offsetBits 必须满足 0 <= offsetBits < vaBits。");
}
var vaMask = GetBitMask(vaBits);
if (vaBits < 64 && (virtualAddress & ~vaMask) != 0UL)
{
throw new ArgumentOutOfRangeException(nameof(virtualAddress), "virtualAddress 超出 vaBits 可表示范围。");
}
var vpnBits = vaBits - offsetBits;
GetPageTableBitLayout(vpnBits, out _, out var l2Bits);
var offset = virtualAddress & GetBitMask(offsetBits);
var vpn = virtualAddress >> offsetBits;
var l2Index = vpn & GetBitMask(l2Bits);
var l1Index = vpn >> l2Bits;
return new AddressParts(vpn, offset, l1Index, l2Index);
}
public static void GetPageTableBitLayout(int vpnBits, out int l1Bits, out int l2Bits)
{
if (vpnBits <= 0)
{
throw new ArgumentOutOfRangeException(nameof(vpnBits), "vpnBits 必须是正整数。");
}
l1Bits = (vpnBits + 1) / 2;
l2Bits = vpnBits / 2;
}
public static string FormatSplitResult(
ulong virtualAddress,
int vaBits,
int offsetBits,
AddressParts parts)
{
return $"VA={virtualAddress}, VPN={parts.Vpn}, Offset={parts.Offset}, L1={parts.L1Index}, L2={parts.L2Index}, vaBits={vaBits}, offsetBits={offsetBits}";
}
private static ulong GetBitMask(int bits)
{
if (bits <= 0)
{
return 0UL;
}
if (bits >= 64)
{
return ulong.MaxValue;
}
return (1UL << bits) - 1UL;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b0967dfe5b0eb64993e8c207604d159
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
using System;
namespace VMdemo.Simulation
{
public class AddressGenerator
{
public const int DefaultSeed = 12345;
private readonly int _vaBits;
private readonly ulong _vaMask;
private readonly Random _random;
private readonly byte[] _buffer = new byte[8];
public AddressGenerator(int vaBits, int? seed = null)
{
if (vaBits != 32 && vaBits != 48 && vaBits != 64)
{
throw new ArgumentOutOfRangeException(nameof(vaBits), "vaBits 仅支持 32、48、64。");
}
_vaBits = vaBits;
_vaMask = vaBits == 64 ? ulong.MaxValue : (1UL << vaBits) - 1UL;
_random = new Random(seed ?? DefaultSeed);
}
public ulong MaxVirtualAddress => _vaMask;
public ulong NextVirtualAddress()
{
return NextRawUlong() & _vaMask;
}
private ulong NextRawUlong()
{
_random.NextBytes(_buffer);
return BitConverter.ToUInt64(_buffer, 0);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3e8a9161af494c43a623da1945f4373
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: