// -*- 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.

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

def template AtomicMemOpRMWDeclare {{
    /*
     * The main RMW part of an AMO
     */
    class %(class_name)s::%(class_name)sRMW : public %(base_class)s
    {
      private:
        %(reg_idx_arr_decl)s;

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

def template LRSCMicroDeclare {{
    class %(class_name)s::%(class_name)sMicro : public %(base_class)s
    {
      private:
        %(reg_idx_arr_decl)s;

      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(IsReadBarrier);
            rel_fence->setFlag(IsWriteBarrier);
            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(IsReadBarrier);
            acq_fence->setFlag(IsWriteBarrier);
        }

        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)s("%(mnemonic)s", machInst, %(op_class)s)
    {
        %(set_reg_idx_arr)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(IsReadBarrier);
            rel_fence->setFlag(IsWriteBarrier);
            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(IsReadBarrier);
            acq_fence->setFlag(IsWriteBarrier);
        }

        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)
    {
        %(set_reg_idx_arr)s;
        %(constructor)s;

        // overwrite default flags
        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;

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

        if (!alignmentOk(xc, EA, sizeof(Mem))) {
            return std::make_shared<AddressFault>(EA, LOAD_ADDR_MISALIGNED);
        }
        {
            Fault fault =
                readMemAtomicLE(xc, traceData, EA, Mem, memAccessFlags);
            if (fault != NoFault)
                return fault;
        }

        %(memacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

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

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

        %(memacc_code)s;

        if (!alignmentOk(xc, EA, sizeof(Mem))) {
            return std::make_shared<AddressFault>(EA, STORE_ADDR_MISALIGNED);
        }
        {
            Fault fault =
                writeMemAtomicLE(xc, traceData, Mem, EA, memAccessFlags,
                        &result);
            if (fault != NoFault)
                return fault;
        }
        // RISC-V has the opposite convention gem5 has for success flags,
        // so we invert the result here.
        result = !result;

        %(postacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

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

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

        assert(amo_op);

        if (!alignmentOk(xc, EA, sizeof(Mem))) {
            return std::make_shared<AddressFault>(EA, AMO_ADDR_MISALIGNED);
        }
        {
            Fault fault =
                amoMemAtomicLE(xc, traceData, Mem, EA, memAccessFlags, amo_op);
            if (fault != NoFault)
                return fault;
        }

        %(memacc_code)s;
        %(postacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

// initiateAcc() templates

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

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

        if (!alignmentOk(xc, EA, sizeof(Mem))) {
            return std::make_shared<AddressFault>(EA, LOAD_ADDR_MISALIGNED);
        }
        return initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
    }
}};

def template StoreCondInitiateAcc {{
    Fault
    %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
        trace::InstRecord *traceData) const
    {
        Addr EA;

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

        if (!alignmentOk(xc, EA, sizeof(Mem))) {
            return std::make_shared<AddressFault>(EA, STORE_ADDR_MISALIGNED);
        }
        {
            Fault fault = writeMemTimingLE(xc, traceData, Mem, EA,
                memAccessFlags, nullptr);
            if (fault != NoFault)
                return fault;
        }

        %(op_wb)s;

        return NoFault;
    }
}};

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

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

        assert(amo_op);

        if (!alignmentOk(xc, EA, sizeof(Mem))) {
            return std::make_shared<AddressFault>(EA, AMO_ADDR_MISALIGNED);
        }
        return initiateMemAMO(xc, traceData, EA, Mem, memAccessFlags, amo_op);
    }
}};

// completeAcc() templates

def template LoadReservedCompleteAcc {{
    Fault
    %(class_name)s::%(class_name)sMicro::completeAcc(PacketPtr pkt,
        ExecContext *xc, trace::InstRecord *traceData) const
    {
        %(op_decl)s;
        %(op_rd)s;

        getMemLE(pkt, Mem, traceData);

        %(memacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

def template StoreCondCompleteAcc {{
    Fault %(class_name)s::%(class_name)sMicro::completeAcc(Packet *pkt,
          ExecContext *xc, trace::InstRecord *traceData) const
    {
        %(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();

        %(postacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

def template AtomicMemOpRMWCompleteAcc {{
    Fault %(class_name)s::%(class_name)sRMW::completeAcc(Packet *pkt,
        ExecContext *xc, trace::InstRecord *traceData) const
    {
        %(op_decl)s;
        %(op_rd)s;

        getMemLE(pkt, Mem, traceData);

        %(memacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

// LR/SC/AMO decode formats

def format LoadReserved(memacc_code, postacc_code={{ }},
        ea_code={{EA = rvZext(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, 'LoadReservedMicro',
        {'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]) + ';'

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

def format StoreCond(memacc_code, postacc_code={{ }},
        ea_code={{EA = rvZext(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, 'StoreCondMicro',
        {'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]) + ';'

    header_output += LRSCMicroDeclare.subst(iop)
    decoder_output += LRSCMicroConstructor.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 = rvZext(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]) + ';'

    header_output += AtomicMemOpRMWDeclare.subst(rmw_iop)
    decoder_output += AtomicMemOpRMWConstructor.subst(rmw_iop)
    exec_output += AtomicMemOpRMWExecute.subst(rmw_iop) \
                 + AtomicMemOpRMWInitiateAcc.subst(rmw_iop) \
                 + AtomicMemOpRMWCompleteAcc.subst(rmw_iop)
}};
