2-way 8-sets 缓存的初始化

创建一个 2-way set-associative cache 有 8 个 sets 的缓存设计,主要需要以下几个步骤:


缓存结构

  1. 缓存概念

    • 2-way:每个 set 中包含 2 条缓存线(lines)。
    • 8 sets:缓存总共分为 8 个 sets。
    • 每条缓存线包含:
      • Valid Bit:指示缓存线是否有效。
      • Tag:用来标识地址。
      • Data:存储实际数据。
      • Dirty Bit(对于 write-back 策略需要)。
  2. 缓存存储容量

    如果每条缓存线大小是 line_size 字节:

    • 总容量 = line_size × 2 × 8 字节。

缓存代码实现

c 复制代码
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

// 定义单个缓存线
typedef struct {
    bool valid;        // 有效位
    bool dirty;        // 脏位(可选)
    uint32_t tag;      // Tag 部分
    uint8_t *data;     // 实际数据(指向内存块)
} CacheLine;

// 定义缓存的 Set
typedef struct {
    CacheLine lines[2]; // 每个 set 有 2 条缓存线(2-way)
} CacheSet;

// 定义缓存
typedef struct {
    CacheSet sets[8];   // 缓存中有 8 个 sets
    uint32_t line_size; // 每条缓存线大小
} Cache;

// 初始化缓存
void initializeCache(Cache *cache, uint32_t line_size) {
    cache->line_size = line_size;
    for (int i = 0; i < 8; i++) {  // 8 个 sets
        for (int j = 0; j < 2; j++) {  // 每个 set 中有 2 条缓存线
            cache->sets[i].lines[j].valid = false;
            cache->sets[i].lines[j].dirty = false;
            cache->sets[i].lines[j].tag = 0;
            cache->sets[i].lines[j].data = (uint8_t *)malloc(line_size);
        }
    }
}

// 模拟访问地址
bool accessCache(Cache *cache, uint32_t address, uint8_t *memory) {
    uint32_t line_size = cache->line_size;
    uint32_t index = (address / line_size) % 8;  // 从地址中提取 set index(3 bits)
    uint32_t tag = address / (line_size * 8);    // 提取 tag

    // 遍历 set 中的每条缓存线(2-way)
    for (int i = 0; i < 2; i++) {
        CacheLine *line = &cache->sets[index].lines[i];
        if (line->valid && line->tag == tag) {  // 命中
            printf("Address %u: Hit\n", address);
            return true;
        }
    }

    // 缺失,加载数据到缓存
    printf("Address %u: Miss\n", address);

    // 使用简单替换策略(如替换第一个空缓存线,或者随机替换)
    CacheLine *lineToReplace = &cache->sets[index].lines[0];
    if (cache->sets[index].lines[1].valid == false) {
        lineToReplace = &cache->sets[index].lines[1];
    }

    // 如果需要 write-back,检查脏位
    if (lineToReplace->dirty) {
        uint32_t writeBackAddress = (lineToReplace->tag * 8 + index) * line_size;
        memcpy(&memory[writeBackAddress], lineToReplace->data, line_size);
        printf("Write-back to memory at address %u\n", writeBackAddress);
    }

    // 替换缓存线
    lineToReplace->valid = true;
    lineToReplace->dirty = false;
    lineToReplace->tag = tag;
    memcpy(lineToReplace->data, &memory[address], line_size);

    return false;
}

// 清理缓存
void destroyCache(Cache *cache) {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 2; j++) {
            free(cache->sets[i].lines[j].data);
        }
    }
}

示例使用

c 复制代码
int main() {
    uint32_t memory[1024] = {0}; // 模拟主存
    for (int i = 0; i < 1024; i++) {
        memory[i] = i * 10; // 初始化内存
    }

    Cache cache;
    initializeCache(&cache, 16); // 每条缓存线大小为 16 字节

    // 模拟访问
    accessCache(&cache, 0, (uint8_t *)memory);
    accessCache(&cache, 128, (uint8_t *)memory);
    accessCache(&cache, 256, (uint8_t *)memory);
    accessCache(&cache, 0, (uint8_t *)memory);

    // 销毁缓存
    destroyCache(&cache);
    return 0;
}

核心概念

  1. Index :根据地址计算出需要访问的 set。
    • index = (address / line_size) % sets_count
    • 这里 sets_count = 8
  2. Tag :用于标识缓存中的地址是否匹配。
    • tag = address / (line_size * sets_count)
  3. 2-Way:每个 set 中有两个缓存线,可以选择替换策略如 LRU 或 FIFO。
  4. Data:每条缓存线存储实际数据。
  5. Write-back :如果脏位为 true,需要将缓存中的数据写回内存。

此代码完整实现了 2-way 8-sets 缓存的初始化、访问、替换和销毁功能。

相关推荐
189228048619 分钟前
NV041固态MT29F16T08GSLCEM9-QBES:C
人工智能·算法·microsoft·缓存·性能优化
心翼叶少13 分钟前
Redis(二):设置密码
数据库·redis·缓存
霸道流氓气质19 分钟前
Spring AI Ollama 连接超时问题排查与解决:OkHttp 读超时配置全指南
人工智能·spring·okhttp
人道领域23 分钟前
一篇文章解决Codex的安装,实操一遍过
java·开发语言·codex
郑州光合科技余经理36 分钟前
海外版外卖系统:如何快速搭建国际化外卖平台
java·开发语言·前端·人工智能·小程序·系统架构·php
Yvonne爱编码41 分钟前
JAVA EE初阶---DAY 1 计算机是如何工作的
java·java-ee
用户7508837061951 小时前
大二的我手写了一把内存锁,最后却败给了 MySQL 的 MVCC?
java
plainGeekDev1 小时前
Handler/Looper → Coroutines
android·java·kotlin
lulu12165440781 小时前
2026年-企业级大模型API网关实战指南: 微元算力聚合平台性能优化实测
java·人工智能·spring·性能优化·ai编程
openFuyao1 小时前
在Agent时代,成本与性能权衡成为首要考量:采用以内存缓存为中心的全新拓扑架构,还是坚持以不断提升算力为核心的计算中心架构?
缓存