1. MESI状态转换基础模拟

任务目标

实现一个MESI缓存一致性协议状态机模拟器,输入缓存行当前状态与总线操作,输出转换后的状态及是否产生总线事务。覆盖四种状态(Modified、Exclusive、Shared、Invalid)在本地读/写、远程读/写操作下的全部合法转换路径。

核心实现

class MESIStateMachine {
    constructor() {
        // 状态编码: M=Modified, E=Exclusive, S=Shared, I=Invalid
        // 操作编码: LR=Local Read, LW=Local Write, RR=Remote Read, RW=Remote Write
        this.transitions = {
            'I': {
                'LR': { next: 'E', busAction: 'BusRd' },   // 本地读未命中,发BusRd
                'LW': { next: 'M', busAction: 'BusRdX' },  // 本地写未命中,发BusRdX
                'RR': { next: 'I', busAction: null },      // 远程读未命中,无动作
                'RW': { next: 'I', busAction: null }       // 远程写未命中,无动作
            },
            'E': {
                'LR': { next: 'E', busAction: null },      // 本地读命中,无动作
                'LW': { next: 'M', busAction: null },      // 本地写命中,升级为M
                'RR': { next: 'S', busAction: null },      // 远程读,降级为S
                'RW': { next: 'I', busAction: null }       // 远程写,失效
            },
            'S': {
                'LR': { next: 'S', busAction: null },      // 本地读命中
                'LW': { next: 'M', busAction: 'BusRdX' },  // 本地写,需通知其他核失效
                'RR': { next: 'S', busAction: null },      // 远程读,保持共享
                'RW': { next: 'I', busAction: null }       // 远程写,失效
            },
            'M': {
                'LR': { next: 'M', busAction: null },      // 本地读命中
                'LW': { next: 'M', busAction: null },      // 本地写命中
                'RR': { next: 'S', busAction: 'BusRd' },   // 远程读,需写回内存
                'RW': { next: 'I', busAction: 'BusRdX' }   // 远程写,需写回内存
            }
        };
    }

    /**
     * 执行状态转换
     * @param {string} currentState - 当前状态: 'M'|'E'|'S'|'I'
     * @param {string} operation - 操作: 'LR'|'LW'|'RR'|'RW'
     * @returns {{nextState: string, busAction: string|null, valid: boolean}}
     */
    transition(currentState, operation) {
        const stateTrans = this.transitions[currentState];
        if (!stateTrans) {
            return { nextState: null, busAction: null, valid: false };
        }
        const trans = stateTrans[operation];
        if (!trans) {
            return { nextState: null, busAction: null, valid: false };
        }
        return {
            nextState: trans.next,
            busAction: trans.busAction,
            valid: true
        };
    }

    /**
     * 获取所有合法转换路径(用于验证)
     * @returns {Array<{from: string, op: string, to: string, bus: string|null}>}
     */
    getAllTransitions() {
        const result = [];
        const states = ['M', 'E', 'S', 'I'];
        const ops = ['LR', 'LW', 'RR', 'RW'];
        for (const s of states) {
            for (const op of ops) {
                const r = this.transition(s, op);
                if (r.valid) {
                    result.push({ from: s, op, to: r.nextState, bus: r.busAction });
                }
            }
        }
        return result;
    }
}

// ========== 最小验证入口 ==========
function runVerification() {
    const fsm = new MESIStateMachine();
    const testCases = [
        // [当前状态, 操作, 期望下一状态, 期望总线动作]
        ['I', 'LR', 'E', 'BusRd'],
        ['I', 'LW', 'M', 'BusRdX'],
        ['E', 'LW', 'M', null],
        ['E', 'RR', 'S', null],
        ['S', 'LW', 'M', 'BusRdX'],
        ['M', 'RR', 'S', 'BusRd'],
        ['M', 'RW', 'I', 'BusRdX'],
        ['S', 'RW', 'I', null]
    ];

    let allPassed = true;
    console.log('=== MESI状态机验证 ===');
    for (const [state, op, expNext, expBus] of testCases) {
        const result = fsm.transition(state, op);
        const nextOk = result.nextState === expNext;
        const busOk = result.busAction === expBus;
        const ok = nextOk && busOk;
        if (!ok) allPassed = false;
        console.log(
            `${state} --${op}--> ${result.nextState} | 总线: ${result.busAction ?? '无'} | ` +
            `${ok ? '✓' : '✗ 期望: ' + expNext + ', ' + (expBus ?? '无')}`
        );
    }

    // 检查非法转换
    const invalidCases = [
        ['M', 'LR'], // 合法,不应出现在非法列表
        ['I', 'RR'], // 合法
    ];
    // 验证所有16种组合均合法(MESI完整协议无非法组合)
    const allTrans = fsm.getAllTransitions();
    console.log(`\n合法转换总数: ${allTrans.length}/16`);
    if (allTrans.length !== 16) {
        console.log('✗ 应有16条合法转换');
        allPassed = false;
    } else {
        console.log('✓ 全部16条转换路径完整');
    }

    return allPassed;
}

// 执行验证
runVerification();

运行方式

  1. 将代码保存为 mesi_simulator.js
  2. 使用Node.js运行:node mesi_simulator.js

验证方法与通过条件

运行后观察控制台输出:

  • 8条测试用例全部标记 ✓,且每条转换的下一状态与总线动作均与注释中的期望值一致
  • 输出 合法转换总数: 16/16,表示MESI协议四种状态×四种操作的全部转换路径均已覆盖
  • 最终无 ✗ 标记即验证通过

状态转换总览

M E S I LR (BusRd) LW (BusRdX) LW RR RW LW (BusRdX) RW RR (BusRd) RW (BusRdX) LR/LW LR LR/RR RR/RW LR=本地读 LW=本地写 RR=远程读 RW=远程写

图中省略了自环转换(如M状态LR/LW保持M、S状态LR/RR保持S、E状态LR保持E、I状态RR/RW保持I),完整转换逻辑以代码为准。总线动作仅在需要跨核通信时产生:BusRd表示请求读取数据,BusRdX表示请求独占写入权。