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
3213653Sqtt2@cornell.edu// Declaration templates
3311726Sar4jc@virginia.edudef template AtomicMemOpDeclare {{
3411726Sar4jc@virginia.edu    /**
3511726Sar4jc@virginia.edu     * Static instruction class for an AtomicMemOp operation
3611726Sar4jc@virginia.edu     */
3711726Sar4jc@virginia.edu    class %(class_name)s : public %(base_class)s
3811726Sar4jc@virginia.edu    {
3911726Sar4jc@virginia.edu      public:
4011726Sar4jc@virginia.edu        // Constructor
4111726Sar4jc@virginia.edu        %(class_name)s(ExtMachInst machInst);
4211726Sar4jc@virginia.edu
4311726Sar4jc@virginia.edu    protected:
4411726Sar4jc@virginia.edu
4513653Sqtt2@cornell.edu        /*
4613653Sqtt2@cornell.edu         * The main RMW part of an AMO
4713653Sqtt2@cornell.edu         */
4813653Sqtt2@cornell.edu        class %(class_name)sRMW : public %(base_class)sMicro
4911726Sar4jc@virginia.edu        {
5011726Sar4jc@virginia.edu          public:
5111726Sar4jc@virginia.edu            // Constructor
5213653Sqtt2@cornell.edu            %(class_name)sRMW(ExtMachInst machInst, %(class_name)s *_p);
5311726Sar4jc@virginia.edu
5412482Sgabeblack@google.com            Fault execute(ExecContext *, Trace::InstRecord *) const override;
5512482Sgabeblack@google.com            Fault initiateAcc(ExecContext *,
5612482Sgabeblack@google.com                              Trace::InstRecord *) const override;
5712236Sgabeblack@google.com            Fault completeAcc(PacketPtr, ExecContext *,
5812482Sgabeblack@google.com                              Trace::InstRecord *) const override;
5911726Sar4jc@virginia.edu        };
6011726Sar4jc@virginia.edu    };
6111726Sar4jc@virginia.edu}};
6211726Sar4jc@virginia.edu
6313653Sqtt2@cornell.edudef template LRSCDeclare {{
6413653Sqtt2@cornell.edu    /**
6513653Sqtt2@cornell.edu     * Static instruction class for an AtomicMemOp operation
6613653Sqtt2@cornell.edu     */
6713653Sqtt2@cornell.edu    class %(class_name)s : public %(base_class)s
6813653Sqtt2@cornell.edu    {
6913653Sqtt2@cornell.edu      public:
7013653Sqtt2@cornell.edu        // Constructor
7113653Sqtt2@cornell.edu        %(class_name)s(ExtMachInst machInst);
7213653Sqtt2@cornell.edu
7313653Sqtt2@cornell.edu    protected:
7413653Sqtt2@cornell.edu
7513653Sqtt2@cornell.edu        class %(class_name)sMicro : public %(base_class)sMicro
7613653Sqtt2@cornell.edu        {
7713653Sqtt2@cornell.edu          public:
7813653Sqtt2@cornell.edu            // Constructor
7913653Sqtt2@cornell.edu            %(class_name)sMicro(ExtMachInst machInst, %(class_name)s *_p);
8013653Sqtt2@cornell.edu
8113653Sqtt2@cornell.edu            Fault execute(ExecContext *, Trace::InstRecord *) const override;
8213653Sqtt2@cornell.edu            Fault initiateAcc(ExecContext *,
8313653Sqtt2@cornell.edu                              Trace::InstRecord *) const override;
8413653Sqtt2@cornell.edu            Fault completeAcc(PacketPtr, ExecContext *,
8513653Sqtt2@cornell.edu                              Trace::InstRecord *) const override;
8613653Sqtt2@cornell.edu        };
8713653Sqtt2@cornell.edu    };
8813653Sqtt2@cornell.edu}};
8913653Sqtt2@cornell.edu
9013653Sqtt2@cornell.edu// Constructor templates
9113653Sqtt2@cornell.edudef template LRSCMacroConstructor {{
9211965Sar4jc@virginia.edu    %(class_name)s::%(class_name)s(ExtMachInst machInst):
9311965Sar4jc@virginia.edu        %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
9411965Sar4jc@virginia.edu    {
9511965Sar4jc@virginia.edu        %(constructor)s;
9613653Sqtt2@cornell.edu
9713653Sqtt2@cornell.edu        StaticInstPtr rel_fence;
9813653Sqtt2@cornell.edu        StaticInstPtr lrsc;
9913653Sqtt2@cornell.edu        StaticInstPtr acq_fence;
10013653Sqtt2@cornell.edu
10113653Sqtt2@cornell.edu        // set up release fence
10213653Sqtt2@cornell.edu        if (RL) {
10313653Sqtt2@cornell.edu            rel_fence = new MemFenceMicro(machInst, No_OpClass);
10413653Sqtt2@cornell.edu            rel_fence->setFlag(IsFirstMicroop);
10513653Sqtt2@cornell.edu            rel_fence->setFlag(IsMemBarrier);
10613653Sqtt2@cornell.edu            rel_fence->setFlag(IsDelayedCommit);
10713653Sqtt2@cornell.edu        }
10813653Sqtt2@cornell.edu
10913653Sqtt2@cornell.edu        // set up atomic rmw op
11013653Sqtt2@cornell.edu        lrsc = new %(class_name)sMicro(machInst, this);
11113653Sqtt2@cornell.edu
11213653Sqtt2@cornell.edu        if (!RL) {
11313653Sqtt2@cornell.edu            lrsc->setFlag(IsFirstMicroop);
11413653Sqtt2@cornell.edu        }
11513653Sqtt2@cornell.edu
11613653Sqtt2@cornell.edu        if (!AQ) {
11713653Sqtt2@cornell.edu            lrsc->setFlag(IsLastMicroop);
11813653Sqtt2@cornell.edu        } else {
11913653Sqtt2@cornell.edu            lrsc->setFlag(IsDelayedCommit);
12013653Sqtt2@cornell.edu        }
12113653Sqtt2@cornell.edu
12213653Sqtt2@cornell.edu        // set up acquire fence
12313653Sqtt2@cornell.edu        if (AQ) {
12413653Sqtt2@cornell.edu            acq_fence = new MemFenceMicro(machInst, No_OpClass);
12513653Sqtt2@cornell.edu            acq_fence->setFlag(IsLastMicroop);
12613653Sqtt2@cornell.edu            acq_fence->setFlag(IsMemBarrier);
12713653Sqtt2@cornell.edu        }
12813653Sqtt2@cornell.edu
12913653Sqtt2@cornell.edu        if (RL && AQ) {
13013653Sqtt2@cornell.edu            microops = {rel_fence, lrsc, acq_fence};
13113653Sqtt2@cornell.edu        } else if (RL) {
13213653Sqtt2@cornell.edu            microops = {rel_fence, lrsc};
13313653Sqtt2@cornell.edu        } else if (AQ) {
13413653Sqtt2@cornell.edu            microops = {lrsc, acq_fence};
13513653Sqtt2@cornell.edu        } else {
13613653Sqtt2@cornell.edu            microops = {lrsc};
13713653Sqtt2@cornell.edu        }
13813653Sqtt2@cornell.edu    }
13913653Sqtt2@cornell.edu}};
14013653Sqtt2@cornell.edu
14113653Sqtt2@cornell.edudef template LRSCMicroConstructor {{
14213653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sMicro::%(class_name)sMicro(
14313653Sqtt2@cornell.edu        ExtMachInst machInst, %(class_name)s *_p)
14413653Sqtt2@cornell.edu            : %(base_class)sMicro("%(mnemonic)s", machInst, %(op_class)s)
14513653Sqtt2@cornell.edu    {
14613653Sqtt2@cornell.edu        %(constructor)s;
14711965Sar4jc@virginia.edu    }
14811965Sar4jc@virginia.edu}};
14911965Sar4jc@virginia.edu
15011726Sar4jc@virginia.edudef template AtomicMemOpMacroConstructor {{
15111726Sar4jc@virginia.edu    %(class_name)s::%(class_name)s(ExtMachInst machInst)
15211726Sar4jc@virginia.edu            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
15311726Sar4jc@virginia.edu    {
15411726Sar4jc@virginia.edu        %(constructor)s;
15513653Sqtt2@cornell.edu
15613653Sqtt2@cornell.edu        StaticInstPtr rel_fence;
15713653Sqtt2@cornell.edu        StaticInstPtr rmw_op;
15813653Sqtt2@cornell.edu        StaticInstPtr acq_fence;
15913653Sqtt2@cornell.edu
16013653Sqtt2@cornell.edu        // set up release fence
16113653Sqtt2@cornell.edu        if (RL) {
16213653Sqtt2@cornell.edu            rel_fence = new MemFenceMicro(machInst, No_OpClass);
16313653Sqtt2@cornell.edu            rel_fence->setFlag(IsFirstMicroop);
16413653Sqtt2@cornell.edu            rel_fence->setFlag(IsMemBarrier);
16513653Sqtt2@cornell.edu            rel_fence->setFlag(IsDelayedCommit);
16613653Sqtt2@cornell.edu        }
16713653Sqtt2@cornell.edu
16813653Sqtt2@cornell.edu        // set up atomic rmw op
16913653Sqtt2@cornell.edu        rmw_op = new %(class_name)sRMW(machInst, this);
17013653Sqtt2@cornell.edu
17113653Sqtt2@cornell.edu        if (!RL) {
17213653Sqtt2@cornell.edu            rmw_op->setFlag(IsFirstMicroop);
17313653Sqtt2@cornell.edu        }
17413653Sqtt2@cornell.edu
17513653Sqtt2@cornell.edu        if (!AQ) {
17613653Sqtt2@cornell.edu            rmw_op->setFlag(IsLastMicroop);
17713653Sqtt2@cornell.edu        } else {
17813653Sqtt2@cornell.edu            rmw_op->setFlag(IsDelayedCommit);
17913653Sqtt2@cornell.edu        }
18013653Sqtt2@cornell.edu
18113653Sqtt2@cornell.edu        // set up acquire fence
18213653Sqtt2@cornell.edu        if (AQ) {
18313653Sqtt2@cornell.edu            acq_fence = new MemFenceMicro(machInst, No_OpClass);
18413653Sqtt2@cornell.edu            acq_fence->setFlag(IsLastMicroop);
18513653Sqtt2@cornell.edu            acq_fence->setFlag(IsMemBarrier);
18613653Sqtt2@cornell.edu        }
18713653Sqtt2@cornell.edu
18813653Sqtt2@cornell.edu        if (RL && AQ) {
18913653Sqtt2@cornell.edu            microops = {rel_fence, rmw_op, acq_fence};
19013653Sqtt2@cornell.edu        } else if (RL) {
19113653Sqtt2@cornell.edu            microops = {rel_fence, rmw_op};
19213653Sqtt2@cornell.edu        } else if (AQ) {
19313653Sqtt2@cornell.edu            microops = {rmw_op, acq_fence};
19413653Sqtt2@cornell.edu        } else {
19513653Sqtt2@cornell.edu            microops = {rmw_op};
19613653Sqtt2@cornell.edu        }
19711726Sar4jc@virginia.edu    }
19811726Sar4jc@virginia.edu}};
19911726Sar4jc@virginia.edu
20013653Sqtt2@cornell.edudef template AtomicMemOpRMWConstructor {{
20113653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sRMW::%(class_name)sRMW(
20211726Sar4jc@virginia.edu        ExtMachInst machInst, %(class_name)s *_p)
20311726Sar4jc@virginia.edu            : %(base_class)s("%(mnemonic)s[l]", machInst, %(op_class)s)
20411726Sar4jc@virginia.edu    {
20511726Sar4jc@virginia.edu        %(constructor)s;
20613653Sqtt2@cornell.edu
20713653Sqtt2@cornell.edu        // overwrite default flags
20813653Sqtt2@cornell.edu        flags[IsMemRef] = true;
20913653Sqtt2@cornell.edu        flags[IsLoad] = false;
21013653Sqtt2@cornell.edu        flags[IsStore] = false;
21113653Sqtt2@cornell.edu        flags[IsAtomic] = true;
21211726Sar4jc@virginia.edu    }
21311726Sar4jc@virginia.edu}};
21411726Sar4jc@virginia.edu
21513653Sqtt2@cornell.edu// execute() templates
21613653Sqtt2@cornell.edu
21713653Sqtt2@cornell.edudef template LoadReservedExecute {{
21813653Sqtt2@cornell.edu    Fault
21913653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sMicro::execute(
22013653Sqtt2@cornell.edu        ExecContext *xc, Trace::InstRecord *traceData) const
22111726Sar4jc@virginia.edu    {
22213653Sqtt2@cornell.edu        Addr EA;
22313653Sqtt2@cornell.edu        Fault fault = NoFault;
22413653Sqtt2@cornell.edu
22513653Sqtt2@cornell.edu        %(op_decl)s;
22613653Sqtt2@cornell.edu        %(op_rd)s;
22713653Sqtt2@cornell.edu        %(ea_code)s;
22813653Sqtt2@cornell.edu
22913653Sqtt2@cornell.edu        if (fault == NoFault) {
23013653Sqtt2@cornell.edu            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
23113653Sqtt2@cornell.edu            %(memacc_code)s;
23213653Sqtt2@cornell.edu        }
23313653Sqtt2@cornell.edu
23413653Sqtt2@cornell.edu        if (fault == NoFault) {
23513653Sqtt2@cornell.edu            %(op_wb)s;
23613653Sqtt2@cornell.edu        }
23713653Sqtt2@cornell.edu
23813653Sqtt2@cornell.edu        return fault;
23911726Sar4jc@virginia.edu    }
24011726Sar4jc@virginia.edu}};
24111726Sar4jc@virginia.edu
24211965Sar4jc@virginia.edudef template StoreCondExecute {{
24313653Sqtt2@cornell.edu    Fault %(class_name)s::%(class_name)sMicro::execute(ExecContext *xc,
24411965Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
24511965Sar4jc@virginia.edu    {
24611965Sar4jc@virginia.edu        Addr EA;
24711965Sar4jc@virginia.edu        Fault fault = NoFault;
24811965Sar4jc@virginia.edu        uint64_t result;
24911965Sar4jc@virginia.edu
25011965Sar4jc@virginia.edu        %(op_decl)s;
25111965Sar4jc@virginia.edu        %(op_rd)s;
25211965Sar4jc@virginia.edu        %(ea_code)s;
25311965Sar4jc@virginia.edu
25411965Sar4jc@virginia.edu        if (fault == NoFault) {
25511965Sar4jc@virginia.edu            %(memacc_code)s;
25611965Sar4jc@virginia.edu        }
25711965Sar4jc@virginia.edu
25811965Sar4jc@virginia.edu        if (fault == NoFault) {
25911965Sar4jc@virginia.edu            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
26011965Sar4jc@virginia.edu                &result);
26111965Sar4jc@virginia.edu            // RISC-V has the opposite convention gem5 has for success flags,
26211965Sar4jc@virginia.edu            // so we invert the result here.
26311965Sar4jc@virginia.edu            result = !result;
26411965Sar4jc@virginia.edu        }
26511965Sar4jc@virginia.edu
26611965Sar4jc@virginia.edu        if (fault == NoFault) {
26711965Sar4jc@virginia.edu            %(postacc_code)s;
26811965Sar4jc@virginia.edu        }
26911965Sar4jc@virginia.edu
27011965Sar4jc@virginia.edu        if (fault == NoFault) {
27111965Sar4jc@virginia.edu            %(op_wb)s;
27211965Sar4jc@virginia.edu        }
27311965Sar4jc@virginia.edu
27411965Sar4jc@virginia.edu        return fault;
27511965Sar4jc@virginia.edu    }
27611965Sar4jc@virginia.edu}};
27711965Sar4jc@virginia.edu
27813653Sqtt2@cornell.edudef template AtomicMemOpRMWExecute {{
27913653Sqtt2@cornell.edu    Fault %(class_name)s::%(class_name)sRMW::execute(ExecContext *xc,
28011726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
28111726Sar4jc@virginia.edu    {
28211726Sar4jc@virginia.edu        Addr EA;
28311726Sar4jc@virginia.edu        Fault fault = NoFault;
28411726Sar4jc@virginia.edu
28511726Sar4jc@virginia.edu        %(op_decl)s;
28611726Sar4jc@virginia.edu        %(op_rd)s;
28711726Sar4jc@virginia.edu        %(ea_code)s;
28813653Sqtt2@cornell.edu        %(amoop_code)s;
28913653Sqtt2@cornell.edu
29013653Sqtt2@cornell.edu        assert(amo_op);
29111726Sar4jc@virginia.edu
29211726Sar4jc@virginia.edu        if (fault == NoFault) {
29313653Sqtt2@cornell.edu            fault = amoMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
29413653Sqtt2@cornell.edu                                 amo_op);
29513653Sqtt2@cornell.edu            %(memacc_code)s;
29611726Sar4jc@virginia.edu        }
29711726Sar4jc@virginia.edu
29811726Sar4jc@virginia.edu        if (fault == NoFault) {
29913653Sqtt2@cornell.edu            %(postacc_code)s;
30011726Sar4jc@virginia.edu        }
30111726Sar4jc@virginia.edu
30211726Sar4jc@virginia.edu        if (fault == NoFault) {
30311726Sar4jc@virginia.edu            %(op_wb)s;
30411726Sar4jc@virginia.edu        }
30511726Sar4jc@virginia.edu
30611726Sar4jc@virginia.edu        return fault;
30711726Sar4jc@virginia.edu    }
30811726Sar4jc@virginia.edu}};
30911726Sar4jc@virginia.edu
31013653Sqtt2@cornell.edu// initiateAcc() templates
31111726Sar4jc@virginia.edu
31213653Sqtt2@cornell.edudef template LoadReservedInitiateAcc {{
31313653Sqtt2@cornell.edu    Fault
31413653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
31511726Sar4jc@virginia.edu        Trace::InstRecord *traceData) const
31611726Sar4jc@virginia.edu    {
31711726Sar4jc@virginia.edu        Addr EA;
31811726Sar4jc@virginia.edu        Fault fault = NoFault;
31911726Sar4jc@virginia.edu
32011726Sar4jc@virginia.edu        %(op_src_decl)s;
32111726Sar4jc@virginia.edu        %(op_rd)s;
32211726Sar4jc@virginia.edu        %(ea_code)s;
32311726Sar4jc@virginia.edu
32411726Sar4jc@virginia.edu        if (fault == NoFault) {
32511726Sar4jc@virginia.edu            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
32611726Sar4jc@virginia.edu        }
32711726Sar4jc@virginia.edu
32811726Sar4jc@virginia.edu        return fault;
32911726Sar4jc@virginia.edu    }
33011726Sar4jc@virginia.edu}};
33111726Sar4jc@virginia.edu
33213653Sqtt2@cornell.edudef template StoreCondInitiateAcc {{
33313653Sqtt2@cornell.edu    Fault
33413653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
33513653Sqtt2@cornell.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) {
34513653Sqtt2@cornell.edu            %(memacc_code)s;
34611726Sar4jc@virginia.edu        }
34711726Sar4jc@virginia.edu
34811726Sar4jc@virginia.edu        if (fault == NoFault) {
34913653Sqtt2@cornell.edu            fault = writeMemTiming(xc, traceData, Mem, EA,
35013653Sqtt2@cornell.edu                memAccessFlags, nullptr);
35113653Sqtt2@cornell.edu        }
35213653Sqtt2@cornell.edu
35313653Sqtt2@cornell.edu        if (fault == NoFault) {
35413653Sqtt2@cornell.edu            %(op_wb)s;
35513653Sqtt2@cornell.edu        }
35613653Sqtt2@cornell.edu
35713653Sqtt2@cornell.edu        return fault;
35813653Sqtt2@cornell.edu    }
35913653Sqtt2@cornell.edu}};
36013653Sqtt2@cornell.edu
36113653Sqtt2@cornell.edudef template AtomicMemOpRMWInitiateAcc {{
36213653Sqtt2@cornell.edu    Fault
36313653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sRMW::initiateAcc(ExecContext *xc,
36413653Sqtt2@cornell.edu        Trace::InstRecord *traceData) const
36513653Sqtt2@cornell.edu    {
36613653Sqtt2@cornell.edu        Addr EA;
36713653Sqtt2@cornell.edu        Fault fault = NoFault;
36813653Sqtt2@cornell.edu
36913653Sqtt2@cornell.edu        %(op_src_decl)s;
37013653Sqtt2@cornell.edu        %(op_rd)s;
37113653Sqtt2@cornell.edu        %(ea_code)s;
37213653Sqtt2@cornell.edu        %(amoop_code)s;
37313653Sqtt2@cornell.edu
37413653Sqtt2@cornell.edu        assert(amo_op);
37513653Sqtt2@cornell.edu
37613653Sqtt2@cornell.edu        if (fault == NoFault) {
37713653Sqtt2@cornell.edu            fault = initiateMemAMO(xc, traceData, EA, Mem, memAccessFlags,
37813653Sqtt2@cornell.edu                                   amo_op);
37913653Sqtt2@cornell.edu        }
38013653Sqtt2@cornell.edu
38113653Sqtt2@cornell.edu        return fault;
38213653Sqtt2@cornell.edu    }
38313653Sqtt2@cornell.edu}};
38413653Sqtt2@cornell.edu
38513653Sqtt2@cornell.edu// completeAcc() templates
38613653Sqtt2@cornell.edu
38713653Sqtt2@cornell.edudef template LoadReservedCompleteAcc {{
38813653Sqtt2@cornell.edu    Fault
38913653Sqtt2@cornell.edu    %(class_name)s::%(class_name)sMicro::completeAcc(PacketPtr pkt,
39013653Sqtt2@cornell.edu        ExecContext *xc, Trace::InstRecord *traceData) const
39113653Sqtt2@cornell.edu    {
39213653Sqtt2@cornell.edu        Fault fault = NoFault;
39313653Sqtt2@cornell.edu
39413653Sqtt2@cornell.edu        %(op_decl)s;
39513653Sqtt2@cornell.edu        %(op_rd)s;
39613653Sqtt2@cornell.edu
39713653Sqtt2@cornell.edu        getMem(pkt, Mem, traceData);
39813653Sqtt2@cornell.edu
39913653Sqtt2@cornell.edu        if (fault == NoFault) {
40013653Sqtt2@cornell.edu            %(memacc_code)s;
40111726Sar4jc@virginia.edu        }
40211726Sar4jc@virginia.edu
40311726Sar4jc@virginia.edu        if (fault == NoFault) {
40411726Sar4jc@virginia.edu            %(op_wb)s;
40511726Sar4jc@virginia.edu        }
40611726Sar4jc@virginia.edu
40711726Sar4jc@virginia.edu        return fault;
40811726Sar4jc@virginia.edu    }
40911726Sar4jc@virginia.edu}};
41011726Sar4jc@virginia.edu
41111965Sar4jc@virginia.edudef template StoreCondCompleteAcc {{
41213653Sqtt2@cornell.edu    Fault %(class_name)s::%(class_name)sMicro::completeAcc(Packet *pkt,
41313653Sqtt2@cornell.edu          ExecContext *xc, Trace::InstRecord *traceData) const
41411965Sar4jc@virginia.edu    {
41511965Sar4jc@virginia.edu        Fault fault = NoFault;
41611965Sar4jc@virginia.edu
41711965Sar4jc@virginia.edu        %(op_dest_decl)s;
41811965Sar4jc@virginia.edu
41911965Sar4jc@virginia.edu        // RISC-V has the opposite convention gem5 has for success flags,
42011965Sar4jc@virginia.edu        // so we invert the result here.
42111965Sar4jc@virginia.edu        uint64_t result = !pkt->req->getExtraData();
42211965Sar4jc@virginia.edu
42311965Sar4jc@virginia.edu        if (fault == NoFault) {
42411965Sar4jc@virginia.edu            %(postacc_code)s;
42511965Sar4jc@virginia.edu        }
42611965Sar4jc@virginia.edu
42711965Sar4jc@virginia.edu        if (fault == NoFault) {
42811965Sar4jc@virginia.edu            %(op_wb)s;
42911965Sar4jc@virginia.edu        }
43011965Sar4jc@virginia.edu
43111965Sar4jc@virginia.edu        return fault;
43211965Sar4jc@virginia.edu    }
43311965Sar4jc@virginia.edu}};
43411965Sar4jc@virginia.edu
43513653Sqtt2@cornell.edudef template AtomicMemOpRMWCompleteAcc {{
43613653Sqtt2@cornell.edu    Fault %(class_name)s::%(class_name)sRMW::completeAcc(Packet *pkt,
43712234Sgabeblack@google.com        ExecContext *xc, Trace::InstRecord *traceData) const
43811726Sar4jc@virginia.edu    {
43911726Sar4jc@virginia.edu        Fault fault = NoFault;
44011726Sar4jc@virginia.edu
44111726Sar4jc@virginia.edu        %(op_decl)s;
44211726Sar4jc@virginia.edu        %(op_rd)s;
44311726Sar4jc@virginia.edu
44411726Sar4jc@virginia.edu        getMem(pkt, Mem, traceData);
44511726Sar4jc@virginia.edu
44611726Sar4jc@virginia.edu        if (fault == NoFault) {
44713653Sqtt2@cornell.edu            %(memacc_code)s;
44811726Sar4jc@virginia.edu        }
44911726Sar4jc@virginia.edu
45011726Sar4jc@virginia.edu        if (fault == NoFault) {
45111726Sar4jc@virginia.edu            %(op_wb)s;
45211726Sar4jc@virginia.edu        }
45311726Sar4jc@virginia.edu
45411726Sar4jc@virginia.edu        return fault;
45511726Sar4jc@virginia.edu    }
45611726Sar4jc@virginia.edu}};
45711726Sar4jc@virginia.edu
45813653Sqtt2@cornell.edu// LR/SC/AMO decode formats
45911726Sar4jc@virginia.edu
46011965Sar4jc@virginia.edudef format LoadReserved(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
46111965Sar4jc@virginia.edu        mem_flags=[], inst_flags=[]) {{
46213653Sqtt2@cornell.edu    macro_ea_code = ''
46313653Sqtt2@cornell.edu    macro_inst_flags = []
46413653Sqtt2@cornell.edu    macro_iop = InstObjParams(name, Name, 'LoadReserved', macro_ea_code,
46513653Sqtt2@cornell.edu                              macro_inst_flags)
46613653Sqtt2@cornell.edu    header_output = LRSCDeclare.subst(macro_iop)
46713653Sqtt2@cornell.edu    decoder_output = LRSCMacroConstructor.subst(macro_iop)
46813653Sqtt2@cornell.edu    decode_block = BasicDecode.subst(macro_iop)
46913653Sqtt2@cornell.edu
47013653Sqtt2@cornell.edu    exec_output = ''
47113653Sqtt2@cornell.edu
47211965Sar4jc@virginia.edu    mem_flags = makeList(mem_flags)
47311965Sar4jc@virginia.edu    inst_flags = makeList(inst_flags)
47411965Sar4jc@virginia.edu    iop = InstObjParams(name, Name, 'LoadReserved',
47511965Sar4jc@virginia.edu        {'ea_code': ea_code, 'memacc_code': memacc_code,
47611965Sar4jc@virginia.edu        'postacc_code': postacc_code}, inst_flags)
47711965Sar4jc@virginia.edu    iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
47811965Sar4jc@virginia.edu        '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
47911965Sar4jc@virginia.edu
48013653Sqtt2@cornell.edu    decoder_output += LRSCMicroConstructor.subst(iop)
48113653Sqtt2@cornell.edu    decode_block += BasicDecode.subst(iop)
48213653Sqtt2@cornell.edu    exec_output += LoadReservedExecute.subst(iop) \
48313653Sqtt2@cornell.edu        + LoadReservedInitiateAcc.subst(iop) \
48413653Sqtt2@cornell.edu        + LoadReservedCompleteAcc.subst(iop)
48511965Sar4jc@virginia.edu}};
48611965Sar4jc@virginia.edu
48711965Sar4jc@virginia.edudef format StoreCond(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
48811965Sar4jc@virginia.edu        mem_flags=[], inst_flags=[]) {{
48913653Sqtt2@cornell.edu    macro_ea_code = ''
49013653Sqtt2@cornell.edu    macro_inst_flags = []
49113653Sqtt2@cornell.edu    macro_iop = InstObjParams(name, Name, 'StoreCond', macro_ea_code,
49213653Sqtt2@cornell.edu                              macro_inst_flags)
49313653Sqtt2@cornell.edu    header_output = LRSCDeclare.subst(macro_iop)
49413653Sqtt2@cornell.edu    decoder_output = LRSCMacroConstructor.subst(macro_iop)
49513653Sqtt2@cornell.edu    decode_block = BasicDecode.subst(macro_iop)
49613653Sqtt2@cornell.edu
49713653Sqtt2@cornell.edu    exec_output = ''
49813653Sqtt2@cornell.edu
49911965Sar4jc@virginia.edu    mem_flags = makeList(mem_flags)
50011965Sar4jc@virginia.edu    inst_flags = makeList(inst_flags)
50111965Sar4jc@virginia.edu    iop = InstObjParams(name, Name, 'StoreCond',
50211965Sar4jc@virginia.edu        {'ea_code': ea_code, 'memacc_code': memacc_code,
50311965Sar4jc@virginia.edu        'postacc_code': postacc_code}, inst_flags)
50411965Sar4jc@virginia.edu    iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
50511965Sar4jc@virginia.edu        '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
50611965Sar4jc@virginia.edu
50713653Sqtt2@cornell.edu    decoder_output += LRSCMicroConstructor.subst(iop)
50813653Sqtt2@cornell.edu    decode_block += BasicDecode.subst(iop)
50913653Sqtt2@cornell.edu    exec_output += StoreCondExecute.subst(iop) \
51013653Sqtt2@cornell.edu        + StoreCondInitiateAcc.subst(iop) \
51111965Sar4jc@virginia.edu        + StoreCondCompleteAcc.subst(iop)
51211965Sar4jc@virginia.edu}};
51311965Sar4jc@virginia.edu
51413653Sqtt2@cornell.edudef format AtomicMemOp(memacc_code, amoop_code, postacc_code={{ }},
51513653Sqtt2@cornell.edu        ea_code={{EA = Rs1;}}, mem_flags=[], inst_flags=[]) {{
51613653Sqtt2@cornell.edu    macro_ea_code = ''
51713653Sqtt2@cornell.edu    macro_inst_flags = []
51813653Sqtt2@cornell.edu    macro_iop = InstObjParams(name, Name, 'AtomicMemOp', macro_ea_code,
51913653Sqtt2@cornell.edu                              macro_inst_flags)
52011726Sar4jc@virginia.edu    header_output = AtomicMemOpDeclare.subst(macro_iop)
52111726Sar4jc@virginia.edu    decoder_output = AtomicMemOpMacroConstructor.subst(macro_iop)
52212119Sar4jc@virginia.edu    decode_block = BasicDecode.subst(macro_iop)
52313653Sqtt2@cornell.edu
52411726Sar4jc@virginia.edu    exec_output = ''
52511726Sar4jc@virginia.edu
52613653Sqtt2@cornell.edu    rmw_mem_flags = makeList(mem_flags)
52713653Sqtt2@cornell.edu    rmw_inst_flags = makeList(inst_flags)
52813653Sqtt2@cornell.edu    rmw_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
52913653Sqtt2@cornell.edu                            {'ea_code': ea_code,
53013653Sqtt2@cornell.edu                             'memacc_code': memacc_code,
53113653Sqtt2@cornell.edu                             'postacc_code': postacc_code,
53213653Sqtt2@cornell.edu                             'amoop_code': amoop_code},
53313653Sqtt2@cornell.edu                            rmw_inst_flags)
53411726Sar4jc@virginia.edu
53513653Sqtt2@cornell.edu    rmw_iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
53613653Sqtt2@cornell.edu          '|'.join(['Request::%s' % flag for flag in rmw_mem_flags]) + ';'
53713653Sqtt2@cornell.edu
53813653Sqtt2@cornell.edu    decoder_output += AtomicMemOpRMWConstructor.subst(rmw_iop)
53913653Sqtt2@cornell.edu    decode_block += BasicDecode.subst(rmw_iop)
54013653Sqtt2@cornell.edu    exec_output += AtomicMemOpRMWExecute.subst(rmw_iop) \
54113653Sqtt2@cornell.edu                 + AtomicMemOpRMWInitiateAcc.subst(rmw_iop) \
54213653Sqtt2@cornell.edu                 + AtomicMemOpRMWCompleteAcc.subst(rmw_iop)
54311726Sar4jc@virginia.edu}};
544