1// Copyright (c) 2006-2007 The Regents of The University of Michigan 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer; 8// redistributions in binary form must reproduce the above copyright 9// notice, this list of conditions and the following disclaimer in the 10// documentation and/or other materials provided with the distribution; 11// neither the name of the copyright holders nor the names of its 12// contributors may be used to endorse or promote products derived from 13// this software without specific prior written permission. 14// 15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26// 27// Authors: Ali Saidi 28// Gabe Black 29 30//////////////////////////////////////////////////////////////////// 31// 32// Block Memory instructions 33// 34 35def template BlockMemDeclare {{ 36 /** 37 * Static instruction class for a block memory operation 38 */ 39 class %(class_name)s : public %(base_class)s 40 { 41 public: 42 // Constructor 43 %(class_name)s(ExtMachInst machInst); 44 45 protected: 46 class %(class_name)s_0 : public %(base_class)sMicro 47 { 48 public: 49 // Constructor 50 %(class_name)s_0(ExtMachInst machInst); 51 Fault execute(ExecContext *, 52 Trace::InstRecord *) const override; 53 Fault initiateAcc(ExecContext *, 54 Trace::InstRecord *) const override; 55 Fault completeAcc(PacketPtr, ExecContext *, 56 Trace::InstRecord *) const override; 57 }; 58 59 class %(class_name)s_1 : public %(base_class)sMicro 60 { 61 public: 62 // Constructor 63 %(class_name)s_1(ExtMachInst machInst); 64 Fault execute(ExecContext *, 65 Trace::InstRecord *) const override; 66 Fault initiateAcc(ExecContext *, 67 Trace::InstRecord *) const override; 68 Fault completeAcc(PacketPtr, ExecContext *, 69 Trace::InstRecord *) const override; 70 }; 71 72 class %(class_name)s_2 : public %(base_class)sMicro 73 { 74 public: 75 // Constructor 76 %(class_name)s_2(ExtMachInst machInst); 77 Fault execute(ExecContext *, 78 Trace::InstRecord *) const override; 79 Fault initiateAcc(ExecContext *, 80 Trace::InstRecord *) const override; 81 Fault completeAcc(PacketPtr, ExecContext *, 82 Trace::InstRecord *) const override; 83 }; 84 85 class %(class_name)s_3 : public %(base_class)sMicro 86 { 87 public: 88 // Constructor 89 %(class_name)s_3(ExtMachInst machInst); 90 Fault execute(ExecContext *, 91 Trace::InstRecord *) const override; 92 Fault initiateAcc(ExecContext *, 93 Trace::InstRecord *) const override; 94 Fault completeAcc(PacketPtr, ExecContext *, 95 Trace::InstRecord *) const override; 96 }; 97 98 class %(class_name)s_4 : public %(base_class)sMicro 99 { 100 public: 101 // Constructor 102 %(class_name)s_4(ExtMachInst machInst); 103 Fault execute(ExecContext *, 104 Trace::InstRecord *) const override; 105 Fault initiateAcc(ExecContext *, 106 Trace::InstRecord *) const override; 107 Fault completeAcc(PacketPtr, ExecContext *, 108 Trace::InstRecord *) const override; 109 }; 110 111 class %(class_name)s_5 : public %(base_class)sMicro 112 { 113 public: 114 // Constructor 115 %(class_name)s_5(ExtMachInst machInst); 116 Fault execute(ExecContext *, 117 Trace::InstRecord *) const override; 118 Fault initiateAcc(ExecContext *, 119 Trace::InstRecord *) const override; 120 Fault completeAcc(PacketPtr, ExecContext *, 121 Trace::InstRecord *) const override; 122 }; 123 124 class %(class_name)s_6 : public %(base_class)sMicro 125 { 126 public: 127 // Constructor 128 %(class_name)s_6(ExtMachInst machInst); 129 Fault execute(ExecContext *, 130 Trace::InstRecord *) const override; 131 Fault initiateAcc(ExecContext *, 132 Trace::InstRecord *) const override; 133 Fault completeAcc(PacketPtr, ExecContext *, 134 Trace::InstRecord *) const override; 135 }; 136 137 class %(class_name)s_7 : public %(base_class)sMicro 138 { 139 public: 140 // Constructor 141 %(class_name)s_7(ExtMachInst machInst); 142 Fault execute(ExecContext *, 143 Trace::InstRecord *) const override; 144 Fault initiateAcc(ExecContext *, 145 Trace::InstRecord *) const override; 146 Fault completeAcc(PacketPtr, ExecContext *, 147 Trace::InstRecord *) const override; 148 }; 149 }; 150}}; 151 152// Basic instruction class constructor template. 153def template BlockMemConstructor {{ 154 %(class_name)s::%(class_name)s(ExtMachInst machInst) 155 : %(base_class)s("%(mnemonic)s", machInst) 156 { 157 %(constructor)s; 158 microops[0] = new %(class_name)s_0(machInst); 159 microops[1] = new %(class_name)s_1(machInst); 160 microops[2] = new %(class_name)s_2(machInst); 161 microops[3] = new %(class_name)s_3(machInst); 162 microops[4] = new %(class_name)s_4(machInst); 163 microops[5] = new %(class_name)s_5(machInst); 164 microops[6] = new %(class_name)s_6(machInst); 165 microops[7] = new %(class_name)s_7(machInst); 166 } 167}}; 168 169def template BlockMemMicroConstructor {{ 170 %(class_name)s:: 171 %(class_name)s_%(micro_pc)s:: 172 %(class_name)s_%(micro_pc)s(ExtMachInst machInst) : 173 %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]", 174 machInst, %(op_class)s, %(micro_pc)s * 8) 175 { 176 %(constructor)s; 177 %(set_flags)s; 178 } 179}}; 180 181let {{ 182 183 def doBlockMemFormat(code, faultCode, execute, name, Name, opt_flags): 184 # XXX Need to take care of pstate.hpriv as well. The lower ASIs 185 # are split into ones that are available in priv and hpriv, and 186 # those that are only available in hpriv 187 addrCalcReg = 'EA = Rs1 + Rs2 + offset;' 188 addrCalcImm = 'EA = Rs1 + imm + offset;' 189 iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) 190 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags) 191 header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm) 192 decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm) 193 decode_block = ROrImmDecode.subst(iop) 194 matcher = re.compile(r'Frd_N') 195 exec_output = '' 196 for microPc in range(8): 197 flag_code = '' 198 if (microPc == 7): 199 flag_code = "flags[IsLastMicroop] = true;" 200 elif (microPc == 0): 201 flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroop] = true;" 202 else: 203 flag_code = "flags[IsDelayedCommit] = true;" 204 pcedCode = matcher.sub("Frd_%d" % microPc, code) 205 iop = InstObjParams(name, Name, 'BlockMem', 206 {"code": pcedCode, "ea_code": addrCalcReg, 207 "fault_check": faultCode, "micro_pc": microPc, 208 "set_flags": flag_code, "EA_trunc" : TruncateEA}, 209 opt_flags) 210 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', 211 {"code": pcedCode, "ea_code": addrCalcImm, 212 "fault_check": faultCode, "micro_pc": microPc, 213 "set_flags": flag_code, "EA_trunc" : TruncateEA}, 214 opt_flags) 215 decoder_output += BlockMemMicroConstructor.subst(iop) 216 decoder_output += BlockMemMicroConstructor.subst(iop_imm) 217 exec_output += doDualSplitExecute( 218 pcedCode, '', addrCalcReg, addrCalcImm, execute, faultCode, 219 makeMicroName(name, microPc), 220 makeMicroName(name + "Imm", microPc), 221 makeMicroName(Name, microPc), 222 makeMicroName(Name + "Imm", microPc), 223 "EXT_ASI", opt_flags); 224 faultCode = '' 225 return (header_output, decoder_output, exec_output, decode_block) 226}}; 227 228def format BlockLoad(code, *opt_flags) {{ 229 code = filterDoubles(code) 230 # We need to make sure to check the highest priority fault last. 231 # That way, if other faults have been detected, they'll be overwritten 232 # rather than the other way around. 233 faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck 234 (header_output, 235 decoder_output, 236 exec_output, 237 decode_block) = doBlockMemFormat(code, faultCode, 238 LoadFuncs, name, Name, opt_flags) 239}}; 240 241def format BlockStore(code, *opt_flags) {{ 242 code = filterDoubles(code) 243 # We need to make sure to check the highest priority fault last. 244 # That way, if other faults have been detected, they'll be overwritten 245 # rather than the other way around. 246 faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck 247 (header_output, 248 decoder_output, 249 exec_output, 250 decode_block) = doBlockMemFormat(code, faultCode, 251 StoreFuncs, name, Name, opt_flags) 252}}; 253