// Copyright (c) 2006-2007 The Regents of The University of Michigan // 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: Ali Saidi // Gabe Black //////////////////////////////////////////////////////////////////// // // Block Memory instructions // def template BlockMemDeclare {{ /** * Static instruction class for a block memory operation */ class %(class_name)s : public %(base_class)s { public: // Constructor %(class_name)s(ExtMachInst machInst); protected: class %(class_name)s_0 : public %(base_class)sMicro { public: // Constructor %(class_name)s_0(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_1 : public %(base_class)sMicro { public: // Constructor %(class_name)s_1(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_2 : public %(base_class)sMicro { public: // Constructor %(class_name)s_2(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_3 : public %(base_class)sMicro { public: // Constructor %(class_name)s_3(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_4 : public %(base_class)sMicro { public: // Constructor %(class_name)s_4(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_5 : public %(base_class)sMicro { public: // Constructor %(class_name)s_5(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_6 : public %(base_class)sMicro { public: // Constructor %(class_name)s_6(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; class %(class_name)s_7 : public %(base_class)sMicro { public: // Constructor %(class_name)s_7(ExtMachInst machInst); Fault execute(ExecContext *, Trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const override; }; }; }}; // Basic instruction class constructor template. def template BlockMemConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst) { %(constructor)s; microops[0] = new %(class_name)s_0(machInst); microops[1] = new %(class_name)s_1(machInst); microops[2] = new %(class_name)s_2(machInst); microops[3] = new %(class_name)s_3(machInst); microops[4] = new %(class_name)s_4(machInst); microops[5] = new %(class_name)s_5(machInst); microops[6] = new %(class_name)s_6(machInst); microops[7] = new %(class_name)s_7(machInst); } }}; def template BlockMemMicroConstructor {{ %(class_name)s:: %(class_name)s_%(micro_pc)s:: %(class_name)s_%(micro_pc)s(ExtMachInst machInst) : %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]", machInst, %(op_class)s, %(micro_pc)s * 8) { %(constructor)s; %(set_flags)s; } }}; let {{ def doBlockMemFormat(code, faultCode, execute, name, Name, opt_flags): # XXX Need to take care of pstate.hpriv as well. The lower ASIs # are split into ones that are available in priv and hpriv, and # those that are only available in hpriv addrCalcReg = 'EA = Rs1 + Rs2 + offset;' addrCalcImm = 'EA = Rs1 + imm + offset;' iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags) header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm) decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) matcher = re.compile(r'Frd_N') exec_output = '' for microPc in range(8): flag_code = '' if (microPc == 7): flag_code = "flags[IsLastMicroop] = true;" elif (microPc == 0): flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroop] = true;" else: flag_code = "flags[IsDelayedCommit] = true;" pcedCode = matcher.sub("Frd_%d" % microPc, code) iop = InstObjParams(name, Name, 'BlockMem', {"code": pcedCode, "ea_code": addrCalcReg, "fault_check": faultCode, "micro_pc": microPc, "set_flags": flag_code, "EA_trunc" : TruncateEA}, opt_flags) iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', {"code": pcedCode, "ea_code": addrCalcImm, "fault_check": faultCode, "micro_pc": microPc, "set_flags": flag_code, "EA_trunc" : TruncateEA}, opt_flags) decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) exec_output += doDualSplitExecute( pcedCode, '', addrCalcReg, addrCalcImm, execute, faultCode, makeMicroName(name, microPc), makeMicroName(name + "Imm", microPc), makeMicroName(Name, microPc), makeMicroName(Name + "Imm", microPc), "EXT_ASI", opt_flags); faultCode = '' return (header_output, decoder_output, exec_output, decode_block) }}; def format BlockLoad(code, *opt_flags) {{ code = filterDoubles(code) # We need to make sure to check the highest priority fault last. # That way, if other faults have been detected, they'll be overwritten # rather than the other way around. faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck (header_output, decoder_output, exec_output, decode_block) = doBlockMemFormat(code, faultCode, LoadFuncs, name, Name, opt_flags) }}; def format BlockStore(code, *opt_flags) {{ code = filterDoubles(code) # We need to make sure to check the highest priority fault last. # That way, if other faults have been detected, they'll be overwritten # rather than the other way around. faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck (header_output, decoder_output, exec_output, decode_block) = doBlockMemFormat(code, faultCode, StoreFuncs, name, Name, opt_flags) }};