using System; using System.Collections.Generic; namespace VMdemo.Simulation { public class TlbCache { private readonly Dictionary> _index; private readonly LinkedList _lruList; public TlbCache(int capacity) { if (capacity <= 0) { throw new ArgumentOutOfRangeException(nameof(capacity), "TLB 容量必须是正整数。"); } Capacity = capacity; _index = new Dictionary>(capacity); _lruList = new LinkedList(); } 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(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 GetEntriesMostRecentFirst() { var snapshot = new List(_index.Count); for (var node = _lruList.First; node != null; node = node.Next) { snapshot.Add(node.Value); } return snapshot; } private void MoveToMostRecent(LinkedListNode 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); } } }