This repository has been archived on 2026-04-18. You can view files and clone it, but cannot push or open issues or pull requests.
Virtual-Memory-Demo/Assets/Scripts/Simulation/TlbCache.cs

122 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
namespace VMdemo.Simulation
{
public class TlbCache
{
private readonly Dictionary<ulong, LinkedListNode<TlbEntry>> _index;
private readonly LinkedList<TlbEntry> _lruList;
public TlbCache(int capacity)
{
if (capacity <= 0)
{
throw new ArgumentOutOfRangeException(nameof(capacity), "TLB 容量必须是正整数。");
}
Capacity = capacity;
_index = new Dictionary<ulong, LinkedListNode<TlbEntry>>(capacity);
_lruList = new LinkedList<TlbEntry>();
}
public int Capacity { get; }
public int Count => _index.Count;
public int HitCount { get; private set; }
public int MissCount { get; private set; }
public bool Lookup(ulong vpn, out ulong pfn)
{
return TryLookup(vpn, out pfn);
}
public bool TryLookup(ulong vpn, out ulong pfn)
{
if (_index.TryGetValue(vpn, out var node) && node.Value.IsValid)
{
MoveToMostRecent(node);
pfn = node.Value.Pfn;
HitCount++;
return true;
}
pfn = 0UL;
MissCount++;
return false;
}
public void InsertOrUpdate(ulong vpn, ulong pfn)
{
if (_index.TryGetValue(vpn, out var existingNode))
{
existingNode.Value = existingNode.Value.WithPfn(pfn);
MoveToMostRecent(existingNode);
return;
}
var newNode = new LinkedListNode<TlbEntry>(new TlbEntry(vpn, pfn));
_lruList.AddFirst(newNode);
_index[vpn] = newNode;
if (_index.Count > Capacity)
{
EvictLeastRecent();
}
}
public bool Remove(ulong vpn)
{
if (!_index.TryGetValue(vpn, out var node))
{
return false;
}
_lruList.Remove(node);
_index.Remove(vpn);
return true;
}
public void Clear()
{
_lruList.Clear();
_index.Clear();
HitCount = 0;
MissCount = 0;
}
public IReadOnlyList<TlbEntry> GetEntriesMostRecentFirst()
{
var snapshot = new List<TlbEntry>(_index.Count);
for (var node = _lruList.First; node != null; node = node.Next)
{
snapshot.Add(node.Value);
}
return snapshot;
}
private void MoveToMostRecent(LinkedListNode<TlbEntry> node)
{
if (node.List != _lruList || _lruList.First == node)
{
return;
}
_lruList.Remove(node);
_lruList.AddFirst(node);
}
private void EvictLeastRecent()
{
var leastRecentNode = _lruList.Last;
if (leastRecentNode == null)
{
return;
}
_lruList.RemoveLast();
_index.Remove(leastRecentNode.Value.Vpn);
}
}
}