mem.isa revision 11965:41e942451f59
1// -*- mode:c++ -*- 2 3// Copyright (c) 2015 RISC-V Foundation 4// Copyright (c) 2016 The University of Virginia 5// All rights reserved. 6// 7// Redistribution and use in source and binary forms, with or without 8// modification, are permitted provided that the following conditions are 9// met: redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer; 11// redistributions in binary form must reproduce the above copyright 12// notice, this list of conditions and the following disclaimer in the 13// documentation and/or other materials provided with the distribution; 14// neither the name of the copyright holders nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29// 30// Authors: Alec Roelke 31 32//////////////////////////////////////////////////////////////////// 33// 34// Memory operation instructions 35// 36output header {{ 37 class Load : public RiscvStaticInst 38 { 39 public: 40 /// Displacement for EA calculation (signed). 41 int64_t ldisp; 42 43 protected: 44 /// Memory request flags. See mem_req_base.hh. 45 Request::Flags memAccessFlags; 46 47 /// Constructor 48 Load(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 49 : RiscvStaticInst(mnem, _machInst, __opClass), ldisp(IMM12) 50 { 51 if (IMMSIGN > 0) 52 ldisp |= ~((uint64_t)0xFFF); 53 } 54 55 std::string 56 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 57 }; 58 59 class Store : public RiscvStaticInst 60 { 61 public: 62 /// Displacement for EA calculation (signed). 63 int64_t sdisp; 64 65 protected: 66 /// Memory request flags. See mem_req_base.hh. 67 Request::Flags memAccessFlags; 68 69 /// Constructor 70 Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 71 : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(IMM5) 72 { 73 sdisp |= IMM7 << 5; 74 if (IMMSIGN > 0) 75 sdisp |= ~((uint64_t)0xFFF); 76 } 77 78 std::string 79 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 80 }; 81 82}}; 83 84 85output decoder {{ 86 std::string 87 Load::generateDisassembly(Addr pc, const SymbolTable *symtab) const 88 { 89 std::stringstream ss; 90 ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << ldisp << 91 '(' << regName(_srcRegIdx[0]) << ')'; 92 return ss.str(); 93 } 94 95 std::string 96 Store::generateDisassembly(Addr pc, const SymbolTable *symtab) const 97 { 98 std::stringstream ss; 99 ss << mnemonic << ' ' << regName(_srcRegIdx[1]) << ", " << sdisp << 100 '(' << regName(_srcRegIdx[0]) << ')'; 101 return ss.str(); 102 } 103}}; 104 105def template LoadStoreDeclare {{ 106 /** 107 * Static instruction class for "%(mnemonic)s". 108 */ 109 class %(class_name)s : public %(base_class)s 110 { 111 public: 112 /// Constructor. 113 %(class_name)s(ExtMachInst machInst); 114 115 %(BasicExecDeclare)s 116 117 %(EACompDeclare)s 118 119 %(InitiateAccDeclare)s 120 121 %(CompleteAccDeclare)s 122 }; 123}}; 124 125def template EACompDeclare {{ 126 Fault 127 eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const; 128}}; 129 130def template InitiateAccDeclare {{ 131 Fault 132 initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 133}}; 134 135 136def template CompleteAccDeclare {{ 137 Fault 138 completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; 139}}; 140 141def template LoadStoreConstructor {{ 142 %(class_name)s::%(class_name)s(ExtMachInst machInst): 143 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 144 { 145 %(constructor)s; 146 } 147}}; 148 149def template EACompExecute {{ 150 Fault 151 %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc, 152 Trace::InstRecord *traceData) const 153 { 154 Addr EA; 155 Fault fault = NoFault; 156 157 %(op_decl)s; 158 %(op_rd)s; 159 %(ea_code)s; 160 161 if (fault == NoFault) { 162 %(op_wb)s; 163 xc->setEA(EA); 164 } 165 166 return fault; 167 } 168}}; 169 170let {{ 171def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 172 base_class, postacc_code='', decode_template=BasicDecode, 173 exec_template_base=''): 174 # Make sure flags are in lists (convert to lists if not). 175 mem_flags = makeList(mem_flags) 176 inst_flags = makeList(inst_flags) # + ['IsNonSpeculative'] 177 178 iop = InstObjParams(name, Name, base_class, 179 { 'ea_code':ea_code, 'memacc_code':memacc_code, 180 'postacc_code':postacc_code }, inst_flags) 181 182 if mem_flags: 183 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] 184 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 185 iop.constructor += s 186 187 # select templates 188 189 fullExecTemplate = eval(exec_template_base + 'Execute') 190 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 191 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 192 193 # (header_output, decoder_output, decode_block, exec_output) 194 return (LoadStoreDeclare.subst(iop), 195 LoadStoreConstructor.subst(iop), 196 decode_template.subst(iop), 197 fullExecTemplate.subst(iop) + 198 EACompExecute.subst(iop) + 199 initiateAccTemplate.subst(iop) + 200 completeAccTemplate.subst(iop)) 201}}; 202 203def template LoadExecute {{ 204 Fault 205 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 206 Trace::InstRecord *traceData) const 207 { 208 Addr EA; 209 Fault fault = NoFault; 210 211 %(op_decl)s; 212 %(op_rd)s; 213 %(ea_code)s; 214 215 if (fault == NoFault) { 216 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags); 217 %(memacc_code)s; 218 } 219 220 if (fault == NoFault) { 221 %(op_wb)s; 222 } 223 224 return fault; 225 } 226}}; 227 228def template LoadInitiateAcc {{ 229 Fault 230 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc, 231 Trace::InstRecord *traceData) const 232 { 233 Addr EA; 234 Fault fault = NoFault; 235 236 %(op_src_decl)s; 237 %(op_rd)s; 238 %(ea_code)s; 239 240 if (fault == NoFault) { 241 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); 242 } 243 244 return fault; 245 } 246}}; 247 248def template LoadCompleteAcc {{ 249 Fault 250 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 251 Trace::InstRecord *traceData) const 252 { 253 Fault fault = NoFault; 254 255 %(op_decl)s; 256 %(op_rd)s; 257 258 getMem(pkt, Mem, traceData); 259 260 if (fault == NoFault) { 261 %(memacc_code)s; 262 } 263 264 if (fault == NoFault) { 265 %(op_wb)s; 266 } 267 268 return fault; 269 } 270}}; 271 272def template StoreExecute {{ 273 Fault 274 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 275 Trace::InstRecord *traceData) const 276 { 277 Addr EA; 278 Fault fault = NoFault; 279 280 %(op_decl)s; 281 %(op_rd)s; 282 %(ea_code)s; 283 284 if (fault == NoFault) { 285 %(memacc_code)s; 286 } 287 288 if (fault == NoFault) { 289 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags, 290 nullptr); 291 } 292 293 if (fault == NoFault) { 294 %(postacc_code)s; 295 } 296 297 if (fault == NoFault) { 298 %(op_wb)s; 299 } 300 301 return fault; 302 } 303}}; 304 305def template StoreInitiateAcc {{ 306 Fault 307 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc, 308 Trace::InstRecord *traceData) const 309 { 310 Addr EA; 311 Fault fault = NoFault; 312 313 %(op_decl)s; 314 %(op_rd)s; 315 %(ea_code)s; 316 317 if (fault == NoFault) { 318 %(memacc_code)s; 319 } 320 321 if (fault == NoFault) { 322 fault = writeMemTiming(xc, traceData, Mem, EA, 323 memAccessFlags, nullptr); 324 } 325 326 if (fault == NoFault) { 327 %(op_wb)s; 328 } 329 330 return fault; 331 } 332}}; 333 334def template StoreCompleteAcc {{ 335 Fault 336 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 337 Trace::InstRecord *traceData) const 338 { 339 return NoFault; 340 } 341}}; 342 343def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[], 344 inst_flags=[]) {{ 345 (header_output, decoder_output, decode_block, exec_output) = \ 346 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 347 'Load', exec_template_base='Load') 348}}; 349 350def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[], 351 inst_flags=[]) {{ 352 (header_output, decoder_output, decode_block, exec_output) = \ 353 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 354 'Store', exec_template_base='Store') 355}}; 356