amo.isa revision 11965
111726Sar4jc@virginia.edu// -*- mode:c++ -*-
211726Sar4jc@virginia.edu
311726Sar4jc@virginia.edu// Copyright (c) 2015 Riscv Developers
411726Sar4jc@virginia.edu// Copyright (c) 2016 The University of Virginia
511726Sar4jc@virginia.edu// All rights reserved.
611726Sar4jc@virginia.edu//
711726Sar4jc@virginia.edu// Redistribution and use in source and binary forms, with or without
811726Sar4jc@virginia.edu// modification, are permitted provided that the following conditions are
911726Sar4jc@virginia.edu// met: redistributions of source code must retain the above copyright
1011726Sar4jc@virginia.edu// notice, this list of conditions and the following disclaimer;
1111726Sar4jc@virginia.edu// redistributions in binary form must reproduce the above copyright
1211726Sar4jc@virginia.edu// notice, this list of conditions and the following disclaimer in the
1311726Sar4jc@virginia.edu// documentation and/or other materials provided with the distribution;
1411726Sar4jc@virginia.edu// neither the name of the copyright holders nor the names of its
1511726Sar4jc@virginia.edu// contributors may be used to endorse or promote products derived from
1611726Sar4jc@virginia.edu// this software without specific prior written permission.
1711726Sar4jc@virginia.edu//
1811726Sar4jc@virginia.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1911726Sar4jc@virginia.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2011726Sar4jc@virginia.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2111726Sar4jc@virginia.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2211726Sar4jc@virginia.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2311726Sar4jc@virginia.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2411726Sar4jc@virginia.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2511726Sar4jc@virginia.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2611726Sar4jc@virginia.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2711726Sar4jc@virginia.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2811726Sar4jc@virginia.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2911726Sar4jc@virginia.edu//
3011726Sar4jc@virginia.edu// Authors: Alec Roelke
3111726Sar4jc@virginia.edu
3211726Sar4jc@virginia.edu////////////////////////////////////////////////////////////////////
3311726Sar4jc@virginia.edu//
3411726Sar4jc@virginia.edu// Atomic memory operation instructions
3511726Sar4jc@virginia.edu//
3611726Sar4jc@virginia.eduoutput header {{
3711965Sar4jc@virginia.edu    class LoadReserved : public RiscvStaticInst
3811965Sar4jc@virginia.edu    {
3911965Sar4jc@virginia.edu      protected:
4011965Sar4jc@virginia.edu        Request::Flags memAccessFlags;
4111965Sar4jc@virginia.edu
4211965Sar4jc@virginia.edu        LoadReserved(const char *mnem, ExtMachInst _machInst,
4311965Sar4jc@virginia.edu            OpClass __opClass)
4411965Sar4jc@virginia.edu                : RiscvStaticInst(mnem, _machInst, __opClass)
4511965Sar4jc@virginia.edu        {}
4611965Sar4jc@virginia.edu
4711965Sar4jc@virginia.edu        std::string
4811965Sar4jc@virginia.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
4911965Sar4jc@virginia.edu    };
5011965Sar4jc@virginia.edu
5111965Sar4jc@virginia.edu    class StoreCond : public RiscvStaticInst
5211965Sar4jc@virginia.edu    {
5311965Sar4jc@virginia.edu      protected:
5411965Sar4jc@virginia.edu        Request::Flags memAccessFlags;
5511965Sar4jc@virginia.edu
5611965Sar4jc@virginia.edu        StoreCond(const char* mnem, ExtMachInst _machInst, OpClass __opClass)
5711965Sar4jc@virginia.edu                : RiscvStaticInst(mnem, _machInst, __opClass)
5811965Sar4jc@virginia.edu        {}
5911965Sar4jc@virginia.edu
6011965Sar4jc@virginia.edu        std::string
6111965Sar4jc@virginia.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
6211965Sar4jc@virginia.edu    };
6311965Sar4jc@virginia.edu
6411726Sar4jc@virginia.edu    class AtomicMemOp : public RiscvMacroInst
6511726Sar4jc@virginia.edu    {
6611726Sar4jc@virginia.edu    protected:
6711726Sar4jc@virginia.edu        /// Constructor
6811726Sar4jc@virginia.edu        // Each AtomicMemOp has a load and a store phase
6911726Sar4jc@virginia.edu        AtomicMemOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
7011726Sar4jc@virginia.edu                : RiscvMacroInst(mnem, _machInst, __opClass)
7111726Sar4jc@virginia.edu        {}
7211726Sar4jc@virginia.edu
7311726Sar4jc@virginia.edu        std::string generateDisassembly(Addr pc,
7411726Sar4jc@virginia.edu            const SymbolTable *symtab) const;
7511726Sar4jc@virginia.edu    };
7611726Sar4jc@virginia.edu
7711726Sar4jc@virginia.edu    class AtomicMemOpMicro : public RiscvMicroInst
7811726Sar4jc@virginia.edu    {
7911726Sar4jc@virginia.edu    protected:
8011726Sar4jc@virginia.edu        /// Memory request flags.  See mem/request.hh.
8111726Sar4jc@virginia.edu        Request::Flags memAccessFlags;
8211726Sar4jc@virginia.edu
8311726Sar4jc@virginia.edu        /// Constructor
8411726Sar4jc@virginia.edu        AtomicMemOpMicro(const char *mnem, ExtMachInst _machInst,
8511726Sar4jc@virginia.edu            OpClass __opClass)
8611726Sar4jc@virginia.edu                : RiscvMicroInst(mnem, _machInst, __opClass)
8711726Sar4jc@virginia.edu        {}
8811726Sar4jc@virginia.edu
8911726Sar4jc@virginia.edu        std::string generateDisassembly(Addr pc,
9011726Sar4jc@virginia.edu            const SymbolTable *symtab) const;
9111726Sar4jc@virginia.edu    };
9211726Sar4jc@virginia.edu}};
9311726Sar4jc@virginia.edu
9411726Sar4jc@virginia.eduoutput decoder {{
9511965Sar4jc@virginia.edu    std::string LoadReserved::generateDisassembly(Addr pc,
9611965Sar4jc@virginia.edu        const SymbolTable *symtab) const
9711965Sar4jc@virginia.edu    {
9811965Sar4jc@virginia.edu        std::stringstream ss;
9911965Sar4jc@virginia.edu        ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", ("
10011965Sar4jc@virginia.edu                << regName(_srcRegIdx[0]) << ')';
10111965Sar4jc@virginia.edu        return ss.str();
10211965Sar4jc@virginia.edu    }
10311965Sar4jc@virginia.edu
10411965Sar4jc@virginia.edu    std::string StoreCond::generateDisassembly(Addr pc,
10511965Sar4jc@virginia.edu        const SymbolTable *symtab) const
10611965Sar4jc@virginia.edu    {
10711965Sar4jc@virginia.edu        std::stringstream ss;
10811965Sar4jc@virginia.edu        ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", "
10911965Sar4jc@virginia.edu                << regName(_srcRegIdx[1]) << ", ("
11011965Sar4jc@virginia.edu                << regName(_srcRegIdx[0]) << ')';
11111965Sar4jc@virginia.edu        return ss.str();
11211965Sar4jc@virginia.edu    }
11311965Sar4jc@virginia.edu
11411726Sar4jc@virginia.edu    std::string AtomicMemOp::generateDisassembly(Addr pc,
11511726Sar4jc@virginia.edu        const SymbolTable *symtab) const
11611726Sar4jc@virginia.edu    {
11711726Sar4jc@virginia.edu        std::stringstream ss;
11811726Sar4jc@virginia.edu        ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", "
11911726Sar4jc@virginia.edu                << regName(_srcRegIdx[1]) << ", ("
12011726Sar4jc@virginia.edu                << regName(_srcRegIdx[0]) << ')';
12111726Sar4jc@virginia.edu        return ss.str();
12211726Sar4jc@virginia.edu    }
12311726Sar4jc@virginia.edu
12411726Sar4jc@virginia.edu    std::string AtomicMemOpMicro::generateDisassembly(Addr pc,
12511726Sar4jc@virginia.edu        const SymbolTable *symtab) const
12611726Sar4jc@virginia.edu    {
12711726Sar4jc@virginia.edu        std::stringstream ss;
12811726Sar4jc@virginia.edu        ss << csprintf("0x%08x", machInst) << ' ' << mnemonic;
12911726Sar4jc@virginia.edu        return ss.str();
13011726Sar4jc@virginia.edu    }
13111726Sar4jc@virginia.edu}};
13211726Sar4jc@virginia.edu
13311965Sar4jc@virginia.edudef template LRSCDeclare {{
13411965Sar4jc@virginia.edu    class %(class_name)s : public %(base_class)s
13511965Sar4jc@virginia.edu    {
13611965Sar4jc@virginia.edu      public:
13711965Sar4jc@virginia.edu        %(class_name)s(ExtMachInst machInst);
13811965Sar4jc@virginia.edu
13911965Sar4jc@virginia.edu        %(BasicExecDeclare)s
14011965Sar4jc@virginia.edu
14111965Sar4jc@virginia.edu        %(EACompDeclare)s
14211965Sar4jc@virginia.edu
14311965Sar4jc@virginia.edu        %(InitiateAccDeclare)s
14411965Sar4jc@virginia.edu
14511965Sar4jc@virginia.edu        %(CompleteAccDeclare)s
14611965Sar4jc@virginia.edu    };
14711965Sar4jc@virginia.edu}};
14811965Sar4jc@virginia.edu
14911726Sar4jc@virginia.edudef template AtomicMemOpDeclare {{
15011726Sar4jc@virginia.edu    /**
15111726Sar4jc@virginia.edu     * Static instruction class for an AtomicMemOp operation
15211726Sar4jc@virginia.edu     */
15311726Sar4jc@virginia.edu    class %(class_name)s : public %(base_class)s
15411726Sar4jc@virginia.edu    {
15511726Sar4jc@virginia.edu      public:
15611726Sar4jc@virginia.edu        // Constructor
15711726Sar4jc@virginia.edu        %(class_name)s(ExtMachInst machInst);
15811726Sar4jc@virginia.edu
15911726Sar4jc@virginia.edu    protected:
16011726Sar4jc@virginia.edu
16111726Sar4jc@virginia.edu        class %(class_name)sLoad : public %(base_class)sMicro
16211726Sar4jc@virginia.edu        {
16311726Sar4jc@virginia.edu          public:
16411726Sar4jc@virginia.edu            // Constructor
16511726Sar4jc@virginia.edu            %(class_name)sLoad(ExtMachInst machInst, %(class_name)s *_p);
16611726Sar4jc@virginia.edu
16711726Sar4jc@virginia.edu            %(BasicExecDeclare)s
16811726Sar4jc@virginia.edu
16911726Sar4jc@virginia.edu            %(EACompDeclare)s
17011726Sar4jc@virginia.edu
17111726Sar4jc@virginia.edu            %(InitiateAccDeclare)s
17211726Sar4jc@virginia.edu
17311726Sar4jc@virginia.edu            %(CompleteAccDeclare)s
17411726Sar4jc@virginia.edu        };
17511726Sar4jc@virginia.edu
17611726Sar4jc@virginia.edu        class %(class_name)sStore : public %(base_class)sMicro
17711726Sar4jc@virginia.edu        {
17811726Sar4jc@virginia.edu          public:
17911726Sar4jc@virginia.edu            // Constructor
18011726Sar4jc@virginia.edu            %(class_name)sStore(ExtMachInst machInst, %(class_name)s *_p);
18111726Sar4jc@virginia.edu
18211726Sar4jc@virginia.edu            %(BasicExecDeclare)s
18311726Sar4jc@virginia.edu
18411726Sar4jc@virginia.edu            %(EACompDeclare)s
18511726Sar4jc@virginia.edu
18611726Sar4jc@virginia.edu            %(InitiateAccDeclare)s
18711726Sar4jc@virginia.edu
18811726Sar4jc@virginia.edu            %(CompleteAccDeclare)s
18911726Sar4jc@virginia.edu        };
19011726Sar4jc@virginia.edu    };
19111726Sar4jc@virginia.edu}};
19211726Sar4jc@virginia.edu
19311965Sar4jc@virginia.edudef template LRSCConstructor {{
19411965Sar4jc@virginia.edu    %(class_name)s::%(class_name)s(ExtMachInst machInst):
19511965Sar4jc@virginia.edu        %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
19611965Sar4jc@virginia.edu    {
19711965Sar4jc@virginia.edu        %(constructor)s;
19811965Sar4jc@virginia.edu        if (AQ)
19911965Sar4jc@virginia.edu            memAccessFlags = memAccessFlags | Request::ACQUIRE;
20011965Sar4jc@virginia.edu        if (RL)
20111965Sar4jc@virginia.edu            memAccessFlags = memAccessFlags | Request::RELEASE;
20211965Sar4jc@virginia.edu    }
20311965Sar4jc@virginia.edu}};
20411965Sar4jc@virginia.edu
20511726Sar4jc@virginia.edudef template AtomicMemOpMacroConstructor {{
20611726Sar4jc@virginia.edu    %(class_name)s::%(class_name)s(ExtMachInst machInst)
20711726Sar4jc@virginia.edu            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
20811726Sar4jc@virginia.edu    {
20911726Sar4jc@virginia.edu        %(constructor)s;
21011726Sar4jc@virginia.edu        microops = {new %(class_name)sLoad(machInst, this),
21111726Sar4jc@virginia.edu            new %(class_name)sStore(machInst, this)};
21211726Sar4jc@virginia.edu    }
21311726Sar4jc@virginia.edu}};
21411726Sar4jc@virginia.edu
21511726Sar4jc@virginia.edudef template AtomicMemOpLoadConstructor {{
21611726Sar4jc@virginia.edu    %(class_name)s::%(class_name)sLoad::%(class_name)sLoad(
21711726Sar4jc@virginia.edu        ExtMachInst machInst, %(class_name)s *_p)
21811726Sar4jc@virginia.edu            : %(base_class)s("%(mnemonic)s[l]", machInst, %(op_class)s)
21911726Sar4jc@virginia.edu    {
22011726Sar4jc@virginia.edu        %(constructor)s;
22111726Sar4jc@virginia.edu        flags[IsFirstMicroop] = true;
22211726Sar4jc@virginia.edu        flags[IsDelayedCommit] = true;
22311726Sar4jc@virginia.edu        if (AQ)
22411726Sar4jc@virginia.edu            memAccessFlags = Request::ACQUIRE;
22511726Sar4jc@virginia.edu    }
22611726Sar4jc@virginia.edu}};
22711726Sar4jc@virginia.edu
22811726Sar4jc@virginia.edudef template AtomicMemOpStoreConstructor {{
22911726Sar4jc@virginia.edu    %(class_name)s::%(class_name)sStore::%(class_name)sStore(
23011726Sar4jc@virginia.edu        ExtMachInst machInst, %(class_name)s *_p)
23111726Sar4jc@virginia.edu            : %(base_class)s("%(mnemonic)s[s]", machInst, %(op_class)s)
23211726Sar4jc@virginia.edu    {
23311726Sar4jc@virginia.edu        %(constructor)s;
23411726Sar4jc@virginia.edu        flags[IsLastMicroop] = true;
23511726Sar4jc@virginia.edu        flags[IsNonSpeculative] = true;
23611726Sar4jc@virginia.edu        if (RL)
23711726Sar4jc@virginia.edu            memAccessFlags = Request::RELEASE;
23811726Sar4jc@virginia.edu    }
23911726Sar4jc@virginia.edu}};
24011726Sar4jc@virginia.edu
24111726Sar4jc@virginia.edudef template AtomicMemOpMacroDecode {{
24211726Sar4jc@virginia.edu    return new %(class_name)s(machInst);
24311726Sar4jc@virginia.edu}};
24411726Sar4jc@virginia.edu
24511965Sar4jc@virginia.edudef template LoadReservedExecute {{
24611965Sar4jc@virginia.edu    Fault
24711965Sar4jc@virginia.edu    %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
24811965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
24911965Sar4jc@virginia.edu    {
25011965Sar4jc@virginia.edu        Addr EA;
25111965Sar4jc@virginia.edu        Fault fault = NoFault;
25211965Sar4jc@virginia.edu
25311965Sar4jc@virginia.edu        %(op_decl)s;
25411965Sar4jc@virginia.edu        %(op_rd)s;
25511965Sar4jc@virginia.edu        %(ea_code)s;
25611965Sar4jc@virginia.edu
25711965Sar4jc@virginia.edu        if (fault == NoFault) {
25811965Sar4jc@virginia.edu            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
25911965Sar4jc@virginia.edu            %(memacc_code)s;
26011965Sar4jc@virginia.edu        }
26111965Sar4jc@virginia.edu
26211965Sar4jc@virginia.edu        if (fault == NoFault) {
26311965Sar4jc@virginia.edu            %(op_wb)s;
26411965Sar4jc@virginia.edu        }
26511965Sar4jc@virginia.edu
26611965Sar4jc@virginia.edu        return fault;
26711965Sar4jc@virginia.edu    }
26811965Sar4jc@virginia.edu}};
26911965Sar4jc@virginia.edu
27011965Sar4jc@virginia.edudef template StoreCondExecute {{
27111965Sar4jc@virginia.edu    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
27211965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
27311965Sar4jc@virginia.edu    {
27411965Sar4jc@virginia.edu        Addr EA;
27511965Sar4jc@virginia.edu        Fault fault = NoFault;
27611965Sar4jc@virginia.edu        uint64_t result;
27711965Sar4jc@virginia.edu
27811965Sar4jc@virginia.edu        %(op_decl)s;
27911965Sar4jc@virginia.edu        %(op_rd)s;
28011965Sar4jc@virginia.edu        %(ea_code)s;
28111965Sar4jc@virginia.edu
28211965Sar4jc@virginia.edu        if (fault == NoFault) {
28311965Sar4jc@virginia.edu            %(memacc_code)s;
28411965Sar4jc@virginia.edu        }
28511965Sar4jc@virginia.edu
28611965Sar4jc@virginia.edu        if (fault == NoFault) {
28711965Sar4jc@virginia.edu            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
28811965Sar4jc@virginia.edu                &result);
28911965Sar4jc@virginia.edu            // RISC-V has the opposite convention gem5 has for success flags,
29011965Sar4jc@virginia.edu            // so we invert the result here.
29111965Sar4jc@virginia.edu            result = !result;
29211965Sar4jc@virginia.edu        }
29311965Sar4jc@virginia.edu
29411965Sar4jc@virginia.edu        if (fault == NoFault) {
29511965Sar4jc@virginia.edu            %(postacc_code)s;
29611965Sar4jc@virginia.edu        }
29711965Sar4jc@virginia.edu
29811965Sar4jc@virginia.edu        if (fault == NoFault) {
29911965Sar4jc@virginia.edu            %(op_wb)s;
30011965Sar4jc@virginia.edu        }
30111965Sar4jc@virginia.edu
30211965Sar4jc@virginia.edu        return fault;
30311965Sar4jc@virginia.edu    }
30411965Sar4jc@virginia.edu}};
30511965Sar4jc@virginia.edu
30611726Sar4jc@virginia.edudef template AtomicMemOpLoadExecute {{
30711726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sLoad::execute(CPU_EXEC_CONTEXT *xc,
30811726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
30911726Sar4jc@virginia.edu    {
31011726Sar4jc@virginia.edu        Addr EA;
31111726Sar4jc@virginia.edu        Fault fault = NoFault;
31211726Sar4jc@virginia.edu
31311726Sar4jc@virginia.edu        %(op_decl)s;
31411726Sar4jc@virginia.edu        %(op_rd)s;
31511726Sar4jc@virginia.edu        %(ea_code)s;
31611726Sar4jc@virginia.edu
31711726Sar4jc@virginia.edu        if (fault == NoFault) {
31811726Sar4jc@virginia.edu            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
31911726Sar4jc@virginia.edu        }
32011726Sar4jc@virginia.edu
32111726Sar4jc@virginia.edu        if (fault == NoFault) {
32211726Sar4jc@virginia.edu            %(code)s;
32311726Sar4jc@virginia.edu        }
32411726Sar4jc@virginia.edu
32511726Sar4jc@virginia.edu        if (fault == NoFault) {
32611726Sar4jc@virginia.edu            %(op_wb)s;
32711726Sar4jc@virginia.edu        }
32811726Sar4jc@virginia.edu
32911726Sar4jc@virginia.edu        return fault;
33011726Sar4jc@virginia.edu    }
33111726Sar4jc@virginia.edu}};
33211726Sar4jc@virginia.edu
33311726Sar4jc@virginia.edudef template AtomicMemOpStoreExecute {{
33411726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sStore::execute(CPU_EXEC_CONTEXT *xc,
33511726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
33611726Sar4jc@virginia.edu    {
33711726Sar4jc@virginia.edu        Addr EA;
33811726Sar4jc@virginia.edu        Fault fault = NoFault;
33911726Sar4jc@virginia.edu
34011726Sar4jc@virginia.edu        %(op_decl)s;
34111726Sar4jc@virginia.edu        %(op_rd)s;
34211726Sar4jc@virginia.edu        %(ea_code)s;
34311726Sar4jc@virginia.edu
34411726Sar4jc@virginia.edu        if (fault == NoFault) {
34511726Sar4jc@virginia.edu            %(code)s;
34611726Sar4jc@virginia.edu        }
34711726Sar4jc@virginia.edu
34811726Sar4jc@virginia.edu        if (fault == NoFault) {
34911726Sar4jc@virginia.edu            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
35011726Sar4jc@virginia.edu                nullptr);
35111726Sar4jc@virginia.edu        }
35211726Sar4jc@virginia.edu
35311726Sar4jc@virginia.edu        if (fault == NoFault) {
35411726Sar4jc@virginia.edu            %(op_wb)s;
35511726Sar4jc@virginia.edu        }
35611726Sar4jc@virginia.edu
35711726Sar4jc@virginia.edu        return fault;
35811726Sar4jc@virginia.edu    }
35911726Sar4jc@virginia.edu}};
36011726Sar4jc@virginia.edu
36111965Sar4jc@virginia.edudef template LRSCEACompExecute {{
36211965Sar4jc@virginia.edu    Fault
36311965Sar4jc@virginia.edu    %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
36411965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
36511965Sar4jc@virginia.edu    {
36611965Sar4jc@virginia.edu        Addr EA;
36711965Sar4jc@virginia.edu        Fault fault = NoFault;
36811965Sar4jc@virginia.edu
36911965Sar4jc@virginia.edu        %(op_decl)s;
37011965Sar4jc@virginia.edu        %(op_rd)s;
37111965Sar4jc@virginia.edu        %(ea_code)s;
37211965Sar4jc@virginia.edu
37311965Sar4jc@virginia.edu        if (fault == NoFault) {
37411965Sar4jc@virginia.edu            %(op_wb)s;
37511965Sar4jc@virginia.edu            xc->setEA(EA);
37611965Sar4jc@virginia.edu        }
37711965Sar4jc@virginia.edu
37811965Sar4jc@virginia.edu        return fault;
37911965Sar4jc@virginia.edu    }
38011965Sar4jc@virginia.edu}};
38111965Sar4jc@virginia.edu
38211726Sar4jc@virginia.edudef template AtomicMemOpLoadEACompExecute {{
38311726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sLoad::eaComp(CPU_EXEC_CONTEXT *xc,
38411726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
38511726Sar4jc@virginia.edu    {
38611726Sar4jc@virginia.edu        Addr EA;
38711726Sar4jc@virginia.edu        Fault fault = NoFault;
38811726Sar4jc@virginia.edu
38911726Sar4jc@virginia.edu        %(op_decl)s;
39011726Sar4jc@virginia.edu        %(op_rd)s;
39111726Sar4jc@virginia.edu        %(ea_code)s;
39211726Sar4jc@virginia.edu
39311726Sar4jc@virginia.edu        if (fault == NoFault) {
39411726Sar4jc@virginia.edu            %(op_wb)s;
39511726Sar4jc@virginia.edu            xc->setEA(EA);
39611726Sar4jc@virginia.edu        }
39711726Sar4jc@virginia.edu
39811726Sar4jc@virginia.edu        return fault;
39911726Sar4jc@virginia.edu    }
40011726Sar4jc@virginia.edu}};
40111726Sar4jc@virginia.edu
40211726Sar4jc@virginia.edudef template AtomicMemOpStoreEACompExecute {{
40311726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sStore::eaComp(CPU_EXEC_CONTEXT *xc,
40411726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
40511726Sar4jc@virginia.edu    {
40611726Sar4jc@virginia.edu        Addr EA;
40711726Sar4jc@virginia.edu        Fault fault = NoFault;
40811726Sar4jc@virginia.edu
40911726Sar4jc@virginia.edu        %(op_decl)s;
41011726Sar4jc@virginia.edu        %(op_rd)s;
41111726Sar4jc@virginia.edu        %(ea_code)s;
41211726Sar4jc@virginia.edu
41311726Sar4jc@virginia.edu        if (fault == NoFault) {
41411726Sar4jc@virginia.edu            %(op_wb)s;
41511726Sar4jc@virginia.edu            xc->setEA(EA);
41611726Sar4jc@virginia.edu        }
41711726Sar4jc@virginia.edu
41811726Sar4jc@virginia.edu        return fault;
41911726Sar4jc@virginia.edu    }
42011726Sar4jc@virginia.edu}};
42111726Sar4jc@virginia.edu
42211965Sar4jc@virginia.edudef template LoadReservedInitiateAcc {{
42311965Sar4jc@virginia.edu    Fault
42411965Sar4jc@virginia.edu    %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
42511965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
42611965Sar4jc@virginia.edu    {
42711965Sar4jc@virginia.edu        Addr EA;
42811965Sar4jc@virginia.edu        Fault fault = NoFault;
42911965Sar4jc@virginia.edu
43011965Sar4jc@virginia.edu        %(op_src_decl)s;
43111965Sar4jc@virginia.edu        %(op_rd)s;
43211965Sar4jc@virginia.edu        %(ea_code)s;
43311965Sar4jc@virginia.edu
43411965Sar4jc@virginia.edu        if (fault == NoFault) {
43511965Sar4jc@virginia.edu            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
43611965Sar4jc@virginia.edu        }
43711965Sar4jc@virginia.edu
43811965Sar4jc@virginia.edu        return fault;
43911965Sar4jc@virginia.edu    }
44011965Sar4jc@virginia.edu}};
44111965Sar4jc@virginia.edu
44211965Sar4jc@virginia.edudef template StoreCondInitiateAcc {{
44311965Sar4jc@virginia.edu    Fault
44411965Sar4jc@virginia.edu    %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
44511965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
44611965Sar4jc@virginia.edu    {
44711965Sar4jc@virginia.edu        Addr EA;
44811965Sar4jc@virginia.edu        Fault fault = NoFault;
44911965Sar4jc@virginia.edu
45011965Sar4jc@virginia.edu        %(op_decl)s;
45111965Sar4jc@virginia.edu        %(op_rd)s;
45211965Sar4jc@virginia.edu        %(ea_code)s;
45311965Sar4jc@virginia.edu
45411965Sar4jc@virginia.edu        if (fault == NoFault) {
45511965Sar4jc@virginia.edu            %(memacc_code)s;
45611965Sar4jc@virginia.edu        }
45711965Sar4jc@virginia.edu
45811965Sar4jc@virginia.edu        if (fault == NoFault) {
45911965Sar4jc@virginia.edu            fault = writeMemTiming(xc, traceData, Mem, EA,
46011965Sar4jc@virginia.edu                memAccessFlags, nullptr);
46111965Sar4jc@virginia.edu        }
46211965Sar4jc@virginia.edu
46311965Sar4jc@virginia.edu        if (fault == NoFault) {
46411965Sar4jc@virginia.edu            %(op_wb)s;
46511965Sar4jc@virginia.edu        }
46611965Sar4jc@virginia.edu
46711965Sar4jc@virginia.edu        return fault;
46811965Sar4jc@virginia.edu    }
46911965Sar4jc@virginia.edu}};
47011965Sar4jc@virginia.edu
47111726Sar4jc@virginia.edudef template AtomicMemOpLoadInitiateAcc {{
47211726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sLoad::initiateAcc(CPU_EXEC_CONTEXT *xc,
47311726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
47411726Sar4jc@virginia.edu    {
47511726Sar4jc@virginia.edu        Addr EA;
47611726Sar4jc@virginia.edu        Fault fault = NoFault;
47711726Sar4jc@virginia.edu
47811726Sar4jc@virginia.edu        %(op_src_decl)s;
47911726Sar4jc@virginia.edu        %(op_rd)s;
48011726Sar4jc@virginia.edu        %(ea_code)s;
48111726Sar4jc@virginia.edu
48211726Sar4jc@virginia.edu        if (fault == NoFault) {
48311726Sar4jc@virginia.edu            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
48411726Sar4jc@virginia.edu        }
48511726Sar4jc@virginia.edu
48611726Sar4jc@virginia.edu        return fault;
48711726Sar4jc@virginia.edu    }
48811726Sar4jc@virginia.edu}};
48911726Sar4jc@virginia.edu
49011726Sar4jc@virginia.edudef template AtomicMemOpStoreInitiateAcc {{
49111726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sStore::initiateAcc(
49211726Sar4jc@virginia.edu        CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
49311726Sar4jc@virginia.edu    {
49411726Sar4jc@virginia.edu        Addr EA;
49511726Sar4jc@virginia.edu        Fault fault = NoFault;
49611726Sar4jc@virginia.edu
49711726Sar4jc@virginia.edu        %(op_decl)s;
49811726Sar4jc@virginia.edu        %(op_rd)s;
49911726Sar4jc@virginia.edu        %(ea_code)s;
50011726Sar4jc@virginia.edu
50111726Sar4jc@virginia.edu        if (fault == NoFault) {
50211726Sar4jc@virginia.edu            %(code)s;
50311726Sar4jc@virginia.edu        }
50411726Sar4jc@virginia.edu
50511726Sar4jc@virginia.edu        if (fault == NoFault) {
50611726Sar4jc@virginia.edu            fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
50711726Sar4jc@virginia.edu                nullptr);
50811726Sar4jc@virginia.edu        }
50911726Sar4jc@virginia.edu
51011726Sar4jc@virginia.edu        if (fault == NoFault) {
51111726Sar4jc@virginia.edu            %(op_wb)s;
51211726Sar4jc@virginia.edu        }
51311726Sar4jc@virginia.edu
51411726Sar4jc@virginia.edu        return fault;
51511726Sar4jc@virginia.edu    }
51611726Sar4jc@virginia.edu}};
51711726Sar4jc@virginia.edu
51811965Sar4jc@virginia.edudef template LoadReservedCompleteAcc {{
51911965Sar4jc@virginia.edu    Fault
52011965Sar4jc@virginia.edu    %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
52111965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
52211965Sar4jc@virginia.edu    {
52311965Sar4jc@virginia.edu        Fault fault = NoFault;
52411965Sar4jc@virginia.edu
52511965Sar4jc@virginia.edu        %(op_decl)s;
52611965Sar4jc@virginia.edu        %(op_rd)s;
52711965Sar4jc@virginia.edu
52811965Sar4jc@virginia.edu        getMem(pkt, Mem, traceData);
52911965Sar4jc@virginia.edu
53011965Sar4jc@virginia.edu        if (fault == NoFault) {
53111965Sar4jc@virginia.edu            %(memacc_code)s;
53211965Sar4jc@virginia.edu        }
53311965Sar4jc@virginia.edu
53411965Sar4jc@virginia.edu        if (fault == NoFault) {
53511965Sar4jc@virginia.edu            %(op_wb)s;
53611965Sar4jc@virginia.edu        }
53711965Sar4jc@virginia.edu
53811965Sar4jc@virginia.edu        return fault;
53911965Sar4jc@virginia.edu    }
54011965Sar4jc@virginia.edu}};
54111965Sar4jc@virginia.edu
54211965Sar4jc@virginia.edudef template StoreCondCompleteAcc {{
54311965Sar4jc@virginia.edu    Fault %(class_name)s::completeAcc(Packet *pkt, CPU_EXEC_CONTEXT *xc,
54411965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
54511965Sar4jc@virginia.edu    {
54611965Sar4jc@virginia.edu        Fault fault = NoFault;
54711965Sar4jc@virginia.edu
54811965Sar4jc@virginia.edu        %(op_dest_decl)s;
54911965Sar4jc@virginia.edu
55011965Sar4jc@virginia.edu        // RISC-V has the opposite convention gem5 has for success flags,
55111965Sar4jc@virginia.edu        // so we invert the result here.
55211965Sar4jc@virginia.edu        uint64_t result = !pkt->req->getExtraData();
55311965Sar4jc@virginia.edu
55411965Sar4jc@virginia.edu        if (fault == NoFault) {
55511965Sar4jc@virginia.edu            %(postacc_code)s;
55611965Sar4jc@virginia.edu        }
55711965Sar4jc@virginia.edu
55811965Sar4jc@virginia.edu        if (fault == NoFault) {
55911965Sar4jc@virginia.edu            %(op_wb)s;
56011965Sar4jc@virginia.edu        }
56111965Sar4jc@virginia.edu
56211965Sar4jc@virginia.edu        return fault;
56311965Sar4jc@virginia.edu    }
56411965Sar4jc@virginia.edu}};
56511965Sar4jc@virginia.edu
56611726Sar4jc@virginia.edudef template AtomicMemOpLoadCompleteAcc {{
56711726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sLoad::completeAcc(PacketPtr pkt,
56811726Sar4jc@virginia.edu        CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
56911726Sar4jc@virginia.edu    {
57011726Sar4jc@virginia.edu        Fault fault = NoFault;
57111726Sar4jc@virginia.edu
57211726Sar4jc@virginia.edu        %(op_decl)s;
57311726Sar4jc@virginia.edu        %(op_rd)s;
57411726Sar4jc@virginia.edu
57511726Sar4jc@virginia.edu        getMem(pkt, Mem, traceData);
57611726Sar4jc@virginia.edu
57711726Sar4jc@virginia.edu        if (fault == NoFault) {
57811726Sar4jc@virginia.edu            %(code)s;
57911726Sar4jc@virginia.edu        }
58011726Sar4jc@virginia.edu
58111726Sar4jc@virginia.edu        if (fault == NoFault) {
58211726Sar4jc@virginia.edu            %(op_wb)s;
58311726Sar4jc@virginia.edu        }
58411726Sar4jc@virginia.edu
58511726Sar4jc@virginia.edu        return fault;
58611726Sar4jc@virginia.edu    }
58711726Sar4jc@virginia.edu}};
58811726Sar4jc@virginia.edu
58911726Sar4jc@virginia.edudef template AtomicMemOpStoreCompleteAcc {{
59011726Sar4jc@virginia.edu    Fault %(class_name)s::%(class_name)sStore::completeAcc(PacketPtr pkt,
59111726Sar4jc@virginia.edu        CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
59211726Sar4jc@virginia.edu    {
59311726Sar4jc@virginia.edu        return NoFault;
59411726Sar4jc@virginia.edu    }
59511726Sar4jc@virginia.edu}};
59611726Sar4jc@virginia.edu
59711965Sar4jc@virginia.edudef format LoadReserved(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
59811965Sar4jc@virginia.edu        mem_flags=[], inst_flags=[]) {{
59911965Sar4jc@virginia.edu    mem_flags = makeList(mem_flags)
60011965Sar4jc@virginia.edu    inst_flags = makeList(inst_flags)
60111965Sar4jc@virginia.edu    iop = InstObjParams(name, Name, 'LoadReserved',
60211965Sar4jc@virginia.edu        {'ea_code': ea_code, 'memacc_code': memacc_code,
60311965Sar4jc@virginia.edu        'postacc_code': postacc_code}, inst_flags)
60411965Sar4jc@virginia.edu    iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
60511965Sar4jc@virginia.edu        '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
60611965Sar4jc@virginia.edu
60711965Sar4jc@virginia.edu    header_output = LRSCDeclare.subst(iop)
60811965Sar4jc@virginia.edu    decoder_output = LRSCConstructor.subst(iop)
60911965Sar4jc@virginia.edu    decode_block = BasicDecode.subst(iop)
61011965Sar4jc@virginia.edu    exec_output = LoadReservedExecute.subst(iop) \
61111965Sar4jc@virginia.edu        + LRSCEACompExecute.subst(iop) \
61211965Sar4jc@virginia.edu        + LoadReservedInitiateAcc.subst(iop) \
61311965Sar4jc@virginia.edu        + LoadReservedCompleteAcc.subst(iop)
61411965Sar4jc@virginia.edu}};
61511965Sar4jc@virginia.edu
61611965Sar4jc@virginia.edudef format StoreCond(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
61711965Sar4jc@virginia.edu        mem_flags=[], inst_flags=[]) {{
61811965Sar4jc@virginia.edu    mem_flags = makeList(mem_flags)
61911965Sar4jc@virginia.edu    inst_flags = makeList(inst_flags)
62011965Sar4jc@virginia.edu    iop = InstObjParams(name, Name, 'StoreCond',
62111965Sar4jc@virginia.edu        {'ea_code': ea_code, 'memacc_code': memacc_code,
62211965Sar4jc@virginia.edu        'postacc_code': postacc_code}, inst_flags)
62311965Sar4jc@virginia.edu    iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
62411965Sar4jc@virginia.edu        '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
62511965Sar4jc@virginia.edu
62611965Sar4jc@virginia.edu    header_output = LRSCDeclare.subst(iop)
62711965Sar4jc@virginia.edu    decoder_output = LRSCConstructor.subst(iop)
62811965Sar4jc@virginia.edu    decode_block = BasicDecode.subst(iop)
62911965Sar4jc@virginia.edu    exec_output = StoreCondExecute.subst(iop) \
63011965Sar4jc@virginia.edu        + LRSCEACompExecute.subst(iop) \
63111965Sar4jc@virginia.edu        + StoreCondInitiateAcc.subst(iop) \
63211965Sar4jc@virginia.edu        + StoreCondCompleteAcc.subst(iop)
63311965Sar4jc@virginia.edu}};
63411965Sar4jc@virginia.edu
63511726Sar4jc@virginia.edudef format AtomicMemOp(load_code, store_code, ea_code, load_flags=[],
63611726Sar4jc@virginia.edu        store_flags=[], inst_flags=[]) {{
63711726Sar4jc@virginia.edu    macro_iop = InstObjParams(name, Name, 'AtomicMemOp', ea_code, inst_flags)
63811726Sar4jc@virginia.edu    header_output = AtomicMemOpDeclare.subst(macro_iop)
63911726Sar4jc@virginia.edu    decoder_output = AtomicMemOpMacroConstructor.subst(macro_iop)
64011726Sar4jc@virginia.edu    decode_block = AtomicMemOpMacroDecode.subst(macro_iop)
64111726Sar4jc@virginia.edu    exec_output = ''
64211726Sar4jc@virginia.edu
64311726Sar4jc@virginia.edu    load_inst_flags = makeList(inst_flags) + ["IsMemRef", "IsLoad"]
64411726Sar4jc@virginia.edu    load_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
64511726Sar4jc@virginia.edu        {'ea_code': ea_code, 'code': load_code}, load_inst_flags)
64611726Sar4jc@virginia.edu    decoder_output += AtomicMemOpLoadConstructor.subst(load_iop)
64711726Sar4jc@virginia.edu    exec_output += AtomicMemOpLoadExecute.subst(load_iop) \
64811726Sar4jc@virginia.edu        + AtomicMemOpLoadEACompExecute.subst(load_iop) \
64911726Sar4jc@virginia.edu        + AtomicMemOpLoadInitiateAcc.subst(load_iop) \
65011726Sar4jc@virginia.edu        + AtomicMemOpLoadCompleteAcc.subst(load_iop)
65111726Sar4jc@virginia.edu
65211726Sar4jc@virginia.edu    store_inst_flags = makeList(inst_flags) + ["IsMemRef", "IsStore"]
65311726Sar4jc@virginia.edu    store_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
65411726Sar4jc@virginia.edu        {'ea_code': ea_code, 'code': store_code}, store_inst_flags)
65511726Sar4jc@virginia.edu    decoder_output += AtomicMemOpStoreConstructor.subst(store_iop)
65611726Sar4jc@virginia.edu    exec_output += AtomicMemOpStoreExecute.subst(store_iop) \
65711726Sar4jc@virginia.edu        + AtomicMemOpStoreEACompExecute.subst(store_iop) \
65811726Sar4jc@virginia.edu        + AtomicMemOpStoreInitiateAcc.subst(store_iop) \
65911726Sar4jc@virginia.edu        + AtomicMemOpStoreCompleteAcc.subst(store_iop)
66011726Sar4jc@virginia.edu}};
661