Step 1 - 参数与核心数据模型

This commit is contained in:
2026-04-14 00:40:16 +08:00
parent fa7b04a880
commit 7eab504f4a
21 changed files with 595 additions and 19 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d1f0f89f24ab6334f87c91090393ab8b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+28
View File
@@ -0,0 +1,28 @@
using System;
namespace VMdemo.Core
{
[Serializable]
public struct AddressParts
{
public AddressParts(ulong vpn, ulong offset, ulong l1Index, ulong l2Index)
{
Vpn = vpn;
Offset = offset;
L1Index = l1Index;
L2Index = l2Index;
}
public static AddressParts Empty => new AddressParts(0UL, 0UL, 0UL, 0UL);
public ulong Vpn;
public ulong Offset;
public ulong L1Index;
public ulong L2Index;
public override string ToString()
{
return $"VPN={Vpn}, Offset={Offset}, L1={L1Index}, L2={L2Index}";
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2170a834280c39d40826bf87a50a20b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+141
View File
@@ -0,0 +1,141 @@
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.vaBits != 32 && config.vaBits != 48 && config.vaBits != 64)
{
errorMessage = "vaBits 仅支持 32、48、64。";
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;
}
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;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 278803579202bf144ad186a403dbaed2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+68
View File
@@ -0,0 +1,68 @@
using System;
namespace VMdemo.Core
{
[Serializable]
public class SimulationConfig
{
public int vaBits = 32;
public int pageSizeKB = 4;
public int physicalMemoryMB = 64;
public int tlbEntries = 16;
public int accessCount = 100;
public int pageFaultPenalty = 100;
public ulong PageSizeBytes => pageSizeKB > 0 ? (ulong)pageSizeKB * 1024UL : 0UL;
public ulong PhysicalMemoryBytes => physicalMemoryMB > 0 ? (ulong)physicalMemoryMB * 1024UL * 1024UL : 0UL;
public int OffsetBits
{
get
{
return TryGetLog2(PageSizeBytes, out var bits) ? bits : -1;
}
}
public int VpnBits
{
get
{
var offsetBits = OffsetBits;
return offsetBits >= 0 ? vaBits - offsetBits : -1;
}
}
public ulong FrameCount
{
get
{
var pageSizeBytes = PageSizeBytes;
if (pageSizeBytes == 0UL)
{
return 0UL;
}
return PhysicalMemoryBytes / pageSizeBytes;
}
}
private static bool TryGetLog2(ulong value, out int bits)
{
bits = -1;
if (value == 0UL || (value & (value - 1UL)) != 0UL)
{
return false;
}
bits = 0;
while (value > 1UL)
{
value >>= 1;
bits++;
}
return true;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 560da4f3bb13de24986a73b585c1ec1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c143559c7269dd940b8cb1b43b2d07a5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,28 @@
using System;
using VMdemo.Core;
namespace VMdemo.Simulation
{
[Serializable]
public class SimulationState
{
public int CurrentRound { get; set; }
public ulong CurrentVirtualAddress { get; set; }
public AddressParts CurrentAddressParts { get; set; }
public bool IsPageFault { get; set; }
public bool IsTlbHit { get; set; }
public bool IsPageTableHit { get; set; }
public int CurrentCost { get; set; }
public void Reset()
{
CurrentRound = 0;
CurrentVirtualAddress = 0UL;
CurrentAddressParts = AddressParts.Empty;
IsPageFault = false;
IsTlbHit = false;
IsPageTableHit = false;
CurrentCost = 0;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ab511454f082cd4987e3388c3eee16a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a14121217fe28e64f9ddd4fc9f89c32a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+3
View File
@@ -0,0 +1,3 @@
{
"name": "VMdemo"
}
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: baede126690de864e8b4ee808c6a2716
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: