// -*- mode:c++ -*-

// Copyright (c) 2015 Riscv Developers
// Copyright (c) 2016 The University of Virginia
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Alec Roelke

// Declaration templates
def template AtomicMemOpDeclare {{
    /**
     * Static instruction class for an AtomicMemOp operation
     */
    class %(class_name)s : public %(base_class)s
    {
      public:
        // Constructor
        %(class_name)s(ExtMachInst machInst);

    protected:

        /*
         * The main RMW part of an AMO
         */
        class %(class_name)sRMW : public %(base_class)sMicro
        {
          public:
            // Constructor
            %(class_name)sRMW(ExtMachInst machInst, %(class_name)s *_p);

            Fault execute(ExecContext *, Trace::InstRecord *) const override;
            Fault initiateAcc(ExecContext *,
                              Trace::InstRecord *) const override;
            Fault completeAcc(PacketPtr, ExecContext *,
                              Trace::InstRecord *) const override;
        };
    };
}};

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
        {
          public:
            // Constructor
            %(class_name)sMicro(ExtMachInst machInst, %(class_name)s *_p);

            Fault execute(ExecContext *, Trace::InstRecord *) const override;
            Fault initiateAcc(ExecContext *,
                              Trace::InstRecord *) const override;
            Fault completeAcc(PacketPtr, ExecContext *,
                              Trace::InstRecord *) const override;
        };
    };
}};

// Constructor templates
def template LRSCMacroConstructor {{
    %(class_name)s::%(class_name)s(ExtMachInst machInst):
        %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
    {
        %(constructor)s;

        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};
        }
    }
}};

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;
    }
}};

def template AtomicMemOpMacroConstructor {{
    %(class_name)s::%(class_name)s(ExtMachInst machInst)
            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
    {
        %(constructor)s;

        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};
        }
    }
}};

def template AtomicMemOpRMWConstructor {{
    %(class_name)s::%(class_name)sRMW::%(class_name)sRMW(
        ExtMachInst machInst, %(class_name)s *_p)
            : %(base_class)s("%(mnemonic)s[l]", machInst, %(op_class)s)
    {
        %(constructor)s;

        // overwrite default flags
        flags[IsMemRef] = true;
        flags[IsLoad] = false;
        flags[IsStore] = false;
        flags[IsAtomic] = true;
    }
}};

// execute() templates

def template LoadReservedExecute {{
    Fault
    %(class_name)s::%(class_name)sMicro::execute(
        ExecContext *xc, Trace::InstRecord *traceData) const
    {
        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;
    }
}};

def template StoreCondExecute {{
    Fault %(class_name)s::%(class_name)sMicro::execute(ExecContext *xc,
        Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;
        uint64_t result;

        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
                &result);
            // RISC-V has the opposite convention gem5 has for success flags,
            // so we invert the result here.
            result = !result;
        }

        if (fault == NoFault) {
            %(postacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

def template AtomicMemOpRMWExecute {{
    Fault %(class_name)s::%(class_name)sRMW::execute(ExecContext *xc,
        Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;
        %(amoop_code)s;

        assert(amo_op);

        if (fault == NoFault) {
            fault = amoMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
                                 amo_op);
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            %(postacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

// initiateAcc() templates

def template LoadReservedInitiateAcc {{
    Fault
    %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
        Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(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;

        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            fault = writeMemTiming(xc, traceData, Mem, EA,
                memAccessFlags, nullptr);
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

def template AtomicMemOpRMWInitiateAcc {{
    Fault
    %(class_name)s::%(class_name)sRMW::initiateAcc(ExecContext *xc,
        Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(op_src_decl)s;
        %(op_rd)s;
        %(ea_code)s;
        %(amoop_code)s;

        assert(amo_op);

        if (fault == NoFault) {
            fault = initiateMemAMO(xc, traceData, EA, Mem, memAccessFlags,
                                   amo_op);
        }

        return fault;
    }
}};

// completeAcc() templates

def template LoadReservedCompleteAcc {{
    Fault
    %(class_name)s::%(class_name)sMicro::completeAcc(PacketPtr pkt,
        ExecContext *xc, Trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;

        %(op_decl)s;
        %(op_rd)s;

        getMem(pkt, Mem, traceData);

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

def template StoreCondCompleteAcc {{
    Fault %(class_name)s::%(class_name)sMicro::completeAcc(Packet *pkt,
          ExecContext *xc, Trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;

        %(op_dest_decl)s;

        // RISC-V has the opposite convention gem5 has for success flags,
        // so we invert the result here.
        uint64_t result = !pkt->req->getExtraData();

        if (fault == NoFault) {
            %(postacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

def template AtomicMemOpRMWCompleteAcc {{
    Fault %(class_name)s::%(class_name)sRMW::completeAcc(Packet *pkt,
        ExecContext *xc, Trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;

        %(op_decl)s;
        %(op_rd)s;

        getMem(pkt, Mem, traceData);

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

// LR/SC/AMO decode formats

def format LoadReserved(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
        mem_flags=[], inst_flags=[]) {{
    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 = ''

    mem_flags = makeList(mem_flags)
    inst_flags = makeList(inst_flags)
    iop = InstObjParams(name, Name, 'LoadReserved',
        {'ea_code': ea_code, 'memacc_code': memacc_code,
        'postacc_code': postacc_code}, inst_flags)
    iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
        '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'

    decoder_output += LRSCMicroConstructor.subst(iop)
    decode_block += BasicDecode.subst(iop)
    exec_output += LoadReservedExecute.subst(iop) \
        + LoadReservedInitiateAcc.subst(iop) \
        + LoadReservedCompleteAcc.subst(iop)
}};

def format StoreCond(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
        mem_flags=[], inst_flags=[]) {{
    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 = ''

    mem_flags = makeList(mem_flags)
    inst_flags = makeList(inst_flags)
    iop = InstObjParams(name, Name, 'StoreCond',
        {'ea_code': ea_code, 'memacc_code': memacc_code,
        'postacc_code': postacc_code}, inst_flags)
    iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
        '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'

    decoder_output += LRSCMicroConstructor.subst(iop)
    decode_block += BasicDecode.subst(iop)
    exec_output += StoreCondExecute.subst(iop) \
        + StoreCondInitiateAcc.subst(iop) \
        + StoreCondCompleteAcc.subst(iop)
}};

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)
    header_output = AtomicMemOpDeclare.subst(macro_iop)
    decoder_output = AtomicMemOpMacroConstructor.subst(macro_iop)
    decode_block = BasicDecode.subst(macro_iop)

    exec_output = ''

    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)

    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)
}};
