32,35c32
< ////////////////////////////////////////////////////////////////////
< //
< // Atomic memory operation instructions
< //
---
> // Declaration templates
48c45,48
< class %(class_name)sLoad : public %(base_class)sMicro
---
> /*
> * The main RMW part of an AMO
> */
> class %(class_name)sRMW : public %(base_class)sMicro
52c52
< %(class_name)sLoad(ExtMachInst machInst, %(class_name)s *_p);
---
> %(class_name)sRMW(ExtMachInst machInst, %(class_name)s *_p);
59a60,61
> };
> }};
61c63,75
< class %(class_name)sStore : public %(base_class)sMicro
---
> def template LRSCDeclare {{
> /**
> * Static instruction class for an AtomicMemOp operation
> */
> class %(class_name)s : public %(base_class)s
> {
> public:
> // Constructor
> %(class_name)s(ExtMachInst machInst);
>
> protected:
>
> class %(class_name)sMicro : public %(base_class)sMicro
65c79
< %(class_name)sStore(ExtMachInst machInst, %(class_name)s *_p);
---
> %(class_name)sMicro(ExtMachInst machInst, %(class_name)s *_p);
76c90,91
< def template LRSCConstructor {{
---
> // Constructor templates
> def template LRSCMacroConstructor {{
81,84c96,137
< if (AQ)
< memAccessFlags = memAccessFlags | Request::ACQUIRE;
< if (RL)
< memAccessFlags = memAccessFlags | Request::RELEASE;
---
>
> StaticInstPtr rel_fence;
> StaticInstPtr lrsc;
> StaticInstPtr acq_fence;
>
> // set up release fence
> if (RL) {
> rel_fence = new MemFenceMicro(machInst, No_OpClass);
> rel_fence->setFlag(IsFirstMicroop);
> rel_fence->setFlag(IsMemBarrier);
> rel_fence->setFlag(IsDelayedCommit);
> }
>
> // set up atomic rmw op
> lrsc = new %(class_name)sMicro(machInst, this);
>
> if (!RL) {
> lrsc->setFlag(IsFirstMicroop);
> }
>
> if (!AQ) {
> lrsc->setFlag(IsLastMicroop);
> } else {
> lrsc->setFlag(IsDelayedCommit);
> }
>
> // set up acquire fence
> if (AQ) {
> acq_fence = new MemFenceMicro(machInst, No_OpClass);
> acq_fence->setFlag(IsLastMicroop);
> acq_fence->setFlag(IsMemBarrier);
> }
>
> if (RL && AQ) {
> microops = {rel_fence, lrsc, acq_fence};
> } else if (RL) {
> microops = {rel_fence, lrsc};
> } else if (AQ) {
> microops = {lrsc, acq_fence};
> } else {
> microops = {lrsc};
> }
87a141,149
> def template LRSCMicroConstructor {{
> %(class_name)s::%(class_name)sMicro::%(class_name)sMicro(
> ExtMachInst machInst, %(class_name)s *_p)
> : %(base_class)sMicro("%(mnemonic)s", machInst, %(op_class)s)
> {
> %(constructor)s;
> }
> }};
>
93,94c155,196
< microops = {new %(class_name)sLoad(machInst, this),
< new %(class_name)sStore(machInst, this)};
---
>
> StaticInstPtr rel_fence;
> StaticInstPtr rmw_op;
> StaticInstPtr acq_fence;
>
> // set up release fence
> if (RL) {
> rel_fence = new MemFenceMicro(machInst, No_OpClass);
> rel_fence->setFlag(IsFirstMicroop);
> rel_fence->setFlag(IsMemBarrier);
> rel_fence->setFlag(IsDelayedCommit);
> }
>
> // set up atomic rmw op
> rmw_op = new %(class_name)sRMW(machInst, this);
>
> if (!RL) {
> rmw_op->setFlag(IsFirstMicroop);
> }
>
> if (!AQ) {
> rmw_op->setFlag(IsLastMicroop);
> } else {
> rmw_op->setFlag(IsDelayedCommit);
> }
>
> // set up acquire fence
> if (AQ) {
> acq_fence = new MemFenceMicro(machInst, No_OpClass);
> acq_fence->setFlag(IsLastMicroop);
> acq_fence->setFlag(IsMemBarrier);
> }
>
> if (RL && AQ) {
> microops = {rel_fence, rmw_op, acq_fence};
> } else if (RL) {
> microops = {rel_fence, rmw_op};
> } else if (AQ) {
> microops = {rmw_op, acq_fence};
> } else {
> microops = {rmw_op};
> }
98,99c200,201
< def template AtomicMemOpLoadConstructor {{
< %(class_name)s::%(class_name)sLoad::%(class_name)sLoad(
---
> def template AtomicMemOpRMWConstructor {{
> %(class_name)s::%(class_name)sRMW::%(class_name)sRMW(
104,107c206,211
< flags[IsFirstMicroop] = true;
< flags[IsDelayedCommit] = true;
< if (AQ)
< memAccessFlags = Request::ACQUIRE;
---
>
> // overwrite default flags
> flags[IsMemRef] = true;
> flags[IsLoad] = false;
> flags[IsStore] = false;
> flags[IsAtomic] = true;
111,114c215,220
< def template AtomicMemOpStoreConstructor {{
< %(class_name)s::%(class_name)sStore::%(class_name)sStore(
< ExtMachInst machInst, %(class_name)s *_p)
< : %(base_class)s("%(mnemonic)s[s]", machInst, %(op_class)s)
---
> // execute() templates
>
> def template LoadReservedExecute {{
> Fault
> %(class_name)s::%(class_name)sMicro::execute(
> ExecContext *xc, Trace::InstRecord *traceData) const
116,120c222,238
< %(constructor)s;
< flags[IsLastMicroop] = true;
< flags[IsNonSpeculative] = true;
< if (RL)
< memAccessFlags = Request::RELEASE;
---
> Addr EA;
> Fault fault = NoFault;
>
> %(op_decl)s;
> %(op_rd)s;
> %(ea_code)s;
>
> if (fault == NoFault) {
> fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
> %(memacc_code)s;
> }
>
> if (fault == NoFault) {
> %(op_wb)s;
> }
>
> return fault;
125c243
< Fault %(class_name)s::execute(ExecContext *xc,
---
> Fault %(class_name)s::%(class_name)sMicro::execute(ExecContext *xc,
160,161c278,279
< def template AtomicMemOpLoadExecute {{
< Fault %(class_name)s::%(class_name)sLoad::execute(ExecContext *xc,
---
> def template AtomicMemOpRMWExecute {{
> Fault %(class_name)s::%(class_name)sRMW::execute(ExecContext *xc,
169a288
> %(amoop_code)s;
170a290,291
> assert(amo_op);
>
172c293,295
< fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
---
> fault = amoMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
> amo_op);
> %(memacc_code)s;
176c299
< %(code)s;
---
> %(postacc_code)s;
187,188c310,314
< def template AtomicMemOpStoreExecute {{
< Fault %(class_name)s::%(class_name)sStore::execute(ExecContext *xc,
---
> // initiateAcc() templates
>
> def template LoadReservedInitiateAcc {{
> Fault
> %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
193a320,339
> %(op_src_decl)s;
> %(op_rd)s;
> %(ea_code)s;
>
> if (fault == NoFault) {
> fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
> }
>
> return fault;
> }
> }};
>
> def template StoreCondInitiateAcc {{
> Fault
> %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
> Trace::InstRecord *traceData) const
> {
> Addr EA;
> Fault fault = NoFault;
>
199c345
< %(code)s;
---
> %(memacc_code)s;
203,204c349,350
< fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
< nullptr);
---
> fault = writeMemTiming(xc, traceData, Mem, EA,
> memAccessFlags, nullptr);
215,216c361,363
< def template AtomicMemOpLoadInitiateAcc {{
< Fault %(class_name)s::%(class_name)sLoad::initiateAcc(ExecContext *xc,
---
> def template AtomicMemOpRMWInitiateAcc {{
> Fault
> %(class_name)s::%(class_name)sRMW::initiateAcc(ExecContext *xc,
224a372
> %(amoop_code)s;
225a374,375
> assert(amo_op);
>
227c377,378
< fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
---
> fault = initiateMemAMO(xc, traceData, EA, Mem, memAccessFlags,
> amo_op);
234,235c385,389
< def template AtomicMemOpStoreInitiateAcc {{
< Fault %(class_name)s::%(class_name)sStore::initiateAcc(
---
> // completeAcc() templates
>
> def template LoadReservedCompleteAcc {{
> Fault
> %(class_name)s::%(class_name)sMicro::completeAcc(PacketPtr pkt,
238d391
< Addr EA;
243d395
< %(ea_code)s;
245,247c397
< if (fault == NoFault) {
< %(code)s;
< }
---
> getMem(pkt, Mem, traceData);
250,251c400
< fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
< nullptr);
---
> %(memacc_code)s;
263,264c412,413
< Fault %(class_name)s::completeAcc(Packet *pkt, ExecContext *xc,
< Trace::InstRecord *traceData) const
---
> Fault %(class_name)s::%(class_name)sMicro::completeAcc(Packet *pkt,
> ExecContext *xc, Trace::InstRecord *traceData) const
286,287c435,436
< def template AtomicMemOpLoadCompleteAcc {{
< Fault %(class_name)s::%(class_name)sLoad::completeAcc(PacketPtr pkt,
---
> def template AtomicMemOpRMWCompleteAcc {{
> Fault %(class_name)s::%(class_name)sRMW::completeAcc(Packet *pkt,
298c447
< %(code)s;
---
> %(memacc_code)s;
309,315c458
< def template AtomicMemOpStoreCompleteAcc {{
< Fault %(class_name)s::%(class_name)sStore::completeAcc(PacketPtr pkt,
< ExecContext *xc, Trace::InstRecord *traceData) const
< {
< return NoFault;
< }
< }};
---
> // LR/SC/AMO decode formats
318a462,471
> macro_ea_code = ''
> macro_inst_flags = []
> macro_iop = InstObjParams(name, Name, 'LoadReserved', macro_ea_code,
> macro_inst_flags)
> header_output = LRSCDeclare.subst(macro_iop)
> decoder_output = LRSCMacroConstructor.subst(macro_iop)
> decode_block = BasicDecode.subst(macro_iop)
>
> exec_output = ''
>
327,332c480,484
< header_output = LoadStoreDeclare.subst(iop)
< decoder_output = LRSCConstructor.subst(iop)
< decode_block = BasicDecode.subst(iop)
< exec_output = LoadExecute.subst(iop) \
< + LoadInitiateAcc.subst(iop) \
< + LoadCompleteAcc.subst(iop)
---
> decoder_output += LRSCMicroConstructor.subst(iop)
> decode_block += BasicDecode.subst(iop)
> exec_output += LoadReservedExecute.subst(iop) \
> + LoadReservedInitiateAcc.subst(iop) \
> + LoadReservedCompleteAcc.subst(iop)
336a489,498
> macro_ea_code = ''
> macro_inst_flags = []
> macro_iop = InstObjParams(name, Name, 'StoreCond', macro_ea_code,
> macro_inst_flags)
> header_output = LRSCDeclare.subst(macro_iop)
> decoder_output = LRSCMacroConstructor.subst(macro_iop)
> decode_block = BasicDecode.subst(macro_iop)
>
> exec_output = ''
>
345,349c507,510
< header_output = LoadStoreDeclare.subst(iop)
< decoder_output = LRSCConstructor.subst(iop)
< decode_block = BasicDecode.subst(iop)
< exec_output = StoreCondExecute.subst(iop) \
< + StoreInitiateAcc.subst(iop) \
---
> decoder_output += LRSCMicroConstructor.subst(iop)
> decode_block += BasicDecode.subst(iop)
> exec_output += StoreCondExecute.subst(iop) \
> + StoreCondInitiateAcc.subst(iop) \
353,355c514,519
< def format AtomicMemOp(load_code, store_code, ea_code, load_flags=[],
< store_flags=[], inst_flags=[]) {{
< macro_iop = InstObjParams(name, Name, 'AtomicMemOp', ea_code, inst_flags)
---
> def format AtomicMemOp(memacc_code, amoop_code, postacc_code={{ }},
> ea_code={{EA = Rs1;}}, mem_flags=[], inst_flags=[]) {{
> macro_ea_code = ''
> macro_inst_flags = []
> macro_iop = InstObjParams(name, Name, 'AtomicMemOp', macro_ea_code,
> macro_inst_flags)
358a523
>
361,368c526,533
< load_inst_flags = makeList(inst_flags) + ["IsMemRef", "IsLoad"]
< load_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
< {'ea_code': ea_code, 'code': load_code, 'op_name': 'Load'},
< load_inst_flags)
< decoder_output += AtomicMemOpLoadConstructor.subst(load_iop)
< exec_output += AtomicMemOpLoadExecute.subst(load_iop) \
< + AtomicMemOpLoadInitiateAcc.subst(load_iop) \
< + AtomicMemOpLoadCompleteAcc.subst(load_iop)
---
> rmw_mem_flags = makeList(mem_flags)
> rmw_inst_flags = makeList(inst_flags)
> rmw_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
> {'ea_code': ea_code,
> 'memacc_code': memacc_code,
> 'postacc_code': postacc_code,
> 'amoop_code': amoop_code},
> rmw_inst_flags)
370,377c535,542
< store_inst_flags = makeList(inst_flags) + ["IsMemRef", "IsStore"]
< store_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
< {'ea_code': ea_code, 'code': store_code, 'op_name': 'Store'},
< store_inst_flags)
< decoder_output += AtomicMemOpStoreConstructor.subst(store_iop)
< exec_output += AtomicMemOpStoreExecute.subst(store_iop) \
< + AtomicMemOpStoreInitiateAcc.subst(store_iop) \
< + AtomicMemOpStoreCompleteAcc.subst(store_iop)
---
> rmw_iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
> '|'.join(['Request::%s' % flag for flag in rmw_mem_flags]) + ';'
>
> decoder_output += AtomicMemOpRMWConstructor.subst(rmw_iop)
> decode_block += BasicDecode.subst(rmw_iop)
> exec_output += AtomicMemOpRMWExecute.subst(rmw_iop) \
> + AtomicMemOpRMWInitiateAcc.subst(rmw_iop) \
> + AtomicMemOpRMWCompleteAcc.subst(rmw_iop)