我在这里附上原文,An SC can only pair with the most recent LR in program order. An SC may succeed only if no store from another hart to the reservation set can be observed to have occurred between the LR and the SC, and if there is no other SC between the LR and itself in program order. An SC may succeed only if no write from a device other than a hart to the bytes accessed by the LR instruction can be observed to have occurred between the LR and SC. Note this LR might have had a different effective address and data size, but reserved the SC’s address as part of the reservation set.
很绕,我进行简要概括,即,在当前核 LR 到 SC 的程序流中,不能出现额外的 LR/SC 指令,不能出现其他核访问保留注册地址的操作,不能出现本核对于注册保留地址进行写操作,并且 SC 指令观察到保留注册依然有效,才能成功执行。
...... namespace RISCV { ...... constchar *INSTNAME[]{ /* add instruction name */ ......,"lrw","lrd","scw","scd"}; } ...... void Simulator::decode() { ...... if (this->fReg.len == 4) // 32 bit instruction { ...... switch (opcode) { ...... case OP_CAS: /* add OP_CAS handler */ { /* read data in reg[rs1] which store the address */ op1 = this->reg[rs1]; /* read data in reg[rs2] which is no mean in LR, store the old_value in SC */ op2 = this->reg[rs2]; reg1 = rs1; reg2 = rs2; dest = rd; /* The reg which should be write back */
void Simulator::excecute() { ...... bool _cas = false; /* To identify whether it is a LR or SC */
switch (inst) { ...... case LRW: /* Datapath of LR.W instruction */ readMem = true; writeReg = true; memLen = 4; out = op1; readSignExt = true; _cas = true; break; case LRD: /* Datapath of LR.D instruction */ readMem = true; writeReg = true; memLen = 8; out = op1; readSignExt = true; _cas = true; break; case SCW: /* Datapath of SC.W instruction */ writeReg = true; writeMem = true; memLen = 4; out = op1; _cas = true; op2 = op2 & 0xFFFFFFFF; break; case SCD: /* Datapath of SC.D instruction */ writeReg = true; writeMem = true; memLen = 8; out = op1; op2 = op2 & 0xFFFFFFFF; _cas = true; break; ...... } ...... /* Pass the information to the next stage */ this->eRegNew._cas = _cas; }
这都是一些非常“顺其自然”的照猫画虎,接下去我们需要考虑一个合适的数据结构,并且将原子性质在 memoryAccess 中实现。我们之前讨论了(2019)V1 版本的 CAS 指令要求,我选择了直接在 Simulator 类中声明私有变量,存储注册保留的地址,注册保留的字节数,以及注册保留的 valid bit。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
class Simulator { public: ...... private: ...... struct EReg { ...... bool _cas; } eReg, eRegNew; ...... uint32_t registry_addr; /* Registry hold the first address */ uint32_t registry_num; /* Registry hold the number */ bool registry_whe; /* Registry hold the valid bit */ }