Archived
Step 3 - TLB(全相联 + LRU)
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80f194356d342d24d8a3a8bfc9f22599
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace VMdemo.Simulation
|
||||
{
|
||||
[Serializable]
|
||||
public readonly struct TlbEntry
|
||||
{
|
||||
public TlbEntry(ulong vpn, ulong pfn, bool isValid = true)
|
||||
{
|
||||
Vpn = vpn;
|
||||
Pfn = pfn;
|
||||
IsValid = isValid;
|
||||
}
|
||||
|
||||
public ulong Vpn { get; }
|
||||
public ulong Pfn { get; }
|
||||
public bool IsValid { get; }
|
||||
|
||||
public TlbEntry WithPfn(ulong pfn)
|
||||
{
|
||||
return new TlbEntry(Vpn, pfn, true);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"VPN={Vpn}, PFN={Pfn}, Valid={IsValid}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc1daa201fa9e844a83e62ff9feb5ae6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user