using System; namespace VMdemo.Simulation { public readonly struct MemoryAccessResult { public MemoryAccessResult(ulong pfn, bool pageTableHit, bool pageFault, EvictionInfo eviction) { Pfn = pfn; PageTableHit = pageTableHit; PageFault = pageFault; Eviction = eviction; } public ulong Pfn { get; } public bool PageTableHit { get; } public bool PageFault { get; } public EvictionInfo Eviction { get; } } public static class MemoryAccessResolver { public static MemoryAccessResult Resolve( ulong vpn, ulong l1Index, ulong l2Index, TwoLevelPageTable pageTable, PhysicalMemoryManager physicalMemoryManager, TlbCache tlbCache) { if (pageTable == null) { throw new ArgumentNullException(nameof(pageTable)); } if (physicalMemoryManager == null) { throw new ArgumentNullException(nameof(physicalMemoryManager)); } if (tlbCache == null) { throw new ArgumentNullException(nameof(tlbCache)); } if (pageTable.TryGetPresentPfn(l1Index, l2Index, out var pfn)) { tlbCache.InsertOrUpdate(vpn, pfn); return new MemoryAccessResult(pfn, true, false, EvictionInfo.None); } var allocation = physicalMemoryManager.AllocateForVpn(vpn); if (allocation.Eviction.HasEvicted) { pageTable.GetIndicesFromVpn( allocation.Eviction.EvictedVpn, out var evictedL1Index, out var evictedL2Index); pageTable.MarkNotPresent(evictedL1Index, evictedL2Index); tlbCache.Remove(allocation.Eviction.EvictedVpn); } pageTable.SetPresent(l1Index, l2Index, allocation.AssignedPfn); tlbCache.InsertOrUpdate(vpn, allocation.AssignedPfn); return new MemoryAccessResult( allocation.AssignedPfn, pageTableHit: false, pageFault: true, allocation.Eviction); } } }