Archived
Step 4 - 二级页表 + 缺页 + FIFO
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using VMdemo.Simulation;
|
||||
|
||||
namespace VMdemo.Tests.EditMode
|
||||
{
|
||||
public class Step4PageTableAndFifoTests
|
||||
{
|
||||
[Test]
|
||||
public void TwoLevelPageTable_SetPresent_ThenTryGetPresentPfn_Hits()
|
||||
{
|
||||
var pageTable = new TwoLevelPageTable(3, 2);
|
||||
pageTable.SetPresent(5UL, 3UL, 9UL, dirty: true);
|
||||
|
||||
var hit = pageTable.TryGetPresentPfn(5UL, 3UL, out var pfn);
|
||||
var exists = pageTable.TryGetEntry(5UL, 3UL, out var entry);
|
||||
|
||||
Assert.IsTrue(hit);
|
||||
Assert.That(pfn, Is.EqualTo(9UL));
|
||||
Assert.IsTrue(exists);
|
||||
Assert.That(entry.Present, Is.True);
|
||||
Assert.That(entry.Dirty, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TwoLevelPageTable_MarkNotPresent_ThenMisses()
|
||||
{
|
||||
var pageTable = new TwoLevelPageTable(3, 2);
|
||||
pageTable.SetPresent(1UL, 2UL, 7UL);
|
||||
|
||||
var changed = pageTable.MarkNotPresent(1UL, 2UL);
|
||||
var changedAgain = pageTable.MarkNotPresent(1UL, 2UL);
|
||||
var hitAfterMark = pageTable.TryGetPresentPfn(1UL, 2UL, out _);
|
||||
var exists = pageTable.TryGetEntry(1UL, 2UL, out var entry);
|
||||
|
||||
Assert.IsTrue(changed);
|
||||
Assert.IsFalse(changedAgain);
|
||||
Assert.IsFalse(hitAfterMark);
|
||||
Assert.IsTrue(exists);
|
||||
Assert.IsFalse(entry.Present);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PhysicalMemoryManager_AllocateForVpn_EvictsInFifoOrder()
|
||||
{
|
||||
var manager = new PhysicalMemoryManager(2UL);
|
||||
|
||||
var r1 = manager.AllocateForVpn(1UL);
|
||||
var r2 = manager.AllocateForVpn(2UL);
|
||||
var r3 = manager.AllocateForVpn(3UL); // evict 1
|
||||
var r4 = manager.AllocateForVpn(4UL); // evict 2
|
||||
|
||||
Assert.That(r1.AssignedPfn, Is.EqualTo(0UL));
|
||||
Assert.That(r2.AssignedPfn, Is.EqualTo(1UL));
|
||||
Assert.That(r3.AssignedPfn, Is.EqualTo(0UL));
|
||||
Assert.That(r4.AssignedPfn, Is.EqualTo(1UL));
|
||||
|
||||
Assert.IsFalse(r1.Eviction.HasEvicted);
|
||||
Assert.IsFalse(r2.Eviction.HasEvicted);
|
||||
Assert.IsTrue(r3.Eviction.HasEvicted);
|
||||
Assert.That(r3.Eviction.EvictedVpn, Is.EqualTo(1UL));
|
||||
Assert.That(r3.Eviction.EvictedPfn, Is.EqualTo(0UL));
|
||||
Assert.IsTrue(r4.Eviction.HasEvicted);
|
||||
Assert.That(r4.Eviction.EvictedVpn, Is.EqualTo(2UL));
|
||||
Assert.That(r4.Eviction.EvictedPfn, Is.EqualTo(1UL));
|
||||
|
||||
var fifoOrder = manager.GetFifoVpnOrder();
|
||||
Assert.That(fifoOrder.Count, Is.EqualTo(2));
|
||||
Assert.That(fifoOrder[0], Is.EqualTo(3UL));
|
||||
Assert.That(fifoOrder[1], Is.EqualTo(4UL));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolve_WhenEvictionHappens_SyncsPageTableAndTlb()
|
||||
{
|
||||
var pageTable = new TwoLevelPageTable(4, 4);
|
||||
var memory = new PhysicalMemoryManager(1UL);
|
||||
var tlb = new TlbCache(4);
|
||||
|
||||
const ulong vpn1 = 1UL;
|
||||
pageTable.GetIndicesFromVpn(vpn1, out var l1_1, out var l2_1);
|
||||
var first = MemoryAccessResolver.Resolve(vpn1, l1_1, l2_1, pageTable, memory, tlb);
|
||||
|
||||
Assert.IsTrue(first.PageFault);
|
||||
Assert.IsFalse(first.PageTableHit);
|
||||
Assert.IsFalse(first.Eviction.HasEvicted);
|
||||
Assert.IsTrue(tlb.Lookup(vpn1, out _));
|
||||
|
||||
var second = MemoryAccessResolver.Resolve(vpn1, l1_1, l2_1, pageTable, memory, tlb);
|
||||
Assert.IsFalse(second.PageFault);
|
||||
Assert.IsTrue(second.PageTableHit);
|
||||
|
||||
const ulong vpn2 = 2UL;
|
||||
pageTable.GetIndicesFromVpn(vpn2, out var l1_2, out var l2_2);
|
||||
var third = MemoryAccessResolver.Resolve(vpn2, l1_2, l2_2, pageTable, memory, tlb);
|
||||
|
||||
Assert.IsTrue(third.PageFault);
|
||||
Assert.IsTrue(third.Eviction.HasEvicted);
|
||||
Assert.That(third.Eviction.EvictedVpn, Is.EqualTo(vpn1));
|
||||
Assert.IsFalse(tlb.Lookup(vpn1, out _));
|
||||
Assert.IsTrue(tlb.Lookup(vpn2, out _));
|
||||
|
||||
pageTable.GetIndicesFromVpn(vpn1, out var evictedL1, out var evictedL2);
|
||||
Assert.IsFalse(pageTable.TryGetPresentPfn(evictedL1, evictedL2, out _));
|
||||
Assert.IsFalse(memory.TryGetResidentPfn(vpn1, out _));
|
||||
Assert.IsTrue(memory.TryGetResidentPfn(vpn2, out _));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HighVolumeAccess_N10000_RunsWithoutStateCorruption()
|
||||
{
|
||||
var pageTable = new TwoLevelPageTable(8, 8);
|
||||
var memory = new PhysicalMemoryManager(16UL);
|
||||
var tlb = new TlbCache(8);
|
||||
var random = new Random(123);
|
||||
|
||||
for (var i = 0; i < 10000; i++)
|
||||
{
|
||||
var vpn = (ulong)random.Next(0, 512);
|
||||
pageTable.GetIndicesFromVpn(vpn, out var l1, out var l2);
|
||||
|
||||
var result = MemoryAccessResolver.Resolve(vpn, l1, l2, pageTable, memory, tlb);
|
||||
var fifoOrder = memory.GetFifoVpnOrder();
|
||||
|
||||
Assert.That(memory.ResidentCount, Is.LessThanOrEqualTo(16));
|
||||
Assert.That(fifoOrder.Count, Is.EqualTo(memory.ResidentCount));
|
||||
if (result.PageTableHit)
|
||||
{
|
||||
Assert.IsFalse(result.PageFault);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03c7b540fc1fd394bb518328af03654b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user