mem.isa revision 11729:f37b5fcd66fe
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 # The InitiateAcc template is the same for StoreCond templates as the 190 # corresponding Store template.. 191 StoreCondInitiateAcc = StoreInitiateAcc 192 193 fullExecTemplate = eval(exec_template_base + 'Execute') 194 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 195 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 196 197 # (header_output, decoder_output, decode_block, exec_output) 198 return (LoadStoreDeclare.subst(iop), 199 LoadStoreConstructor.subst(iop), 200 decode_template.subst(iop), 201 fullExecTemplate.subst(iop) + 202 EACompExecute.subst(iop) + 203 initiateAccTemplate.subst(iop) + 204 completeAccTemplate.subst(iop)) 205}}; 206 207def template LoadExecute {{ 208 Fault 209 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 210 Trace::InstRecord *traceData) const 211 { 212 Addr EA; 213 Fault fault = NoFault; 214 215 %(op_decl)s; 216 %(op_rd)s; 217 %(ea_code)s; 218 219 if (fault == NoFault) { 220 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags); 221 %(memacc_code)s; 222 } 223 224 if (fault == NoFault) { 225 %(op_wb)s; 226 } 227 228 return fault; 229 } 230}}; 231 232def template LoadInitiateAcc {{ 233 Fault 234 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc, 235 Trace::InstRecord *traceData) const 236 { 237 Addr EA; 238 Fault fault = NoFault; 239 240 %(op_src_decl)s; 241 %(op_rd)s; 242 %(ea_code)s; 243 244 if (fault == NoFault) { 245 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); 246 } 247 248 return fault; 249 } 250}}; 251 252def template LoadCompleteAcc {{ 253 Fault 254 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 255 Trace::InstRecord *traceData) const 256 { 257 Fault fault = NoFault; 258 259 %(op_decl)s; 260 %(op_rd)s; 261 262 getMem(pkt, Mem, traceData); 263 264 if (fault == NoFault) { 265 %(memacc_code)s; 266 } 267 268 if (fault == NoFault) { 269 %(op_wb)s; 270 } 271 272 return fault; 273 } 274}}; 275 276def template StoreExecute {{ 277 Fault 278 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 279 Trace::InstRecord *traceData) const 280 { 281 Addr EA; 282 Fault fault = NoFault; 283 284 %(op_decl)s; 285 %(op_rd)s; 286 %(ea_code)s; 287 288 if (fault == NoFault) { 289 %(memacc_code)s; 290 } 291 292 if (fault == NoFault) { 293 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags, 294 nullptr); 295 } 296 297 if (fault == NoFault) { 298 %(postacc_code)s; 299 } 300 301 if (fault == NoFault) { 302 %(op_wb)s; 303 } 304 305 return fault; 306 } 307}}; 308 309def template StoreInitiateAcc {{ 310 Fault 311 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc, 312 Trace::InstRecord *traceData) const 313 { 314 Addr EA; 315 Fault fault = NoFault; 316 317 %(op_decl)s; 318 %(op_rd)s; 319 %(ea_code)s; 320 321 if (fault == NoFault) { 322 %(memacc_code)s; 323 } 324 325 if (fault == NoFault) { 326 fault = writeMemTiming(xc, traceData, Mem, EA, 327 memAccessFlags, nullptr); 328 } 329 330 if (fault == NoFault) { 331 %(op_wb)s; 332 } 333 334 return fault; 335 } 336}}; 337 338def template StoreCompleteAcc {{ 339 Fault 340 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 341 Trace::InstRecord *traceData) const 342 { 343 return NoFault; 344 } 345}}; 346 347def template StoreCondExecute {{ 348 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 349 Trace::InstRecord *traceData) const 350 { 351 Addr EA; 352 Fault fault = NoFault; 353 uint64_t result; 354 355 %(op_decl)s; 356 %(op_rd)s; 357 %(ea_code)s; 358 359 if (fault == NoFault) { 360 %(memacc_code)s; 361 } 362 363 if (fault == NoFault) { 364 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags, 365 &result); 366 // RISC-V has the opposite convention gem5 has for success flags, 367 // so we invert the result here. 368 result = !result; 369 } 370 371 if (fault == NoFault) { 372 %(postacc_code)s; 373 } 374 375 if (fault == NoFault) { 376 %(op_wb)s; 377 } 378 379 return fault; 380 } 381}}; 382 383def template StoreCondCompleteAcc {{ 384 Fault %(class_name)s::completeAcc(Packet *pkt, CPU_EXEC_CONTEXT *xc, 385 Trace::InstRecord *traceData) const 386 { 387 Fault fault = NoFault; 388 389 %(op_dest_decl)s; 390 391 // RISC-V has the opposite convention gem5 has for success flags, 392 // so we invert the result here. 393 uint64_t result = !pkt->req->getExtraData(); 394 395 if (fault == NoFault) { 396 %(postacc_code)s; 397 } 398 399 if (fault == NoFault) { 400 %(op_wb)s; 401 } 402 403 return fault; 404 } 405}}; 406 407def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[], 408 inst_flags=[]) {{ 409 (header_output, decoder_output, decode_block, exec_output) = \ 410 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 411 'Load', exec_template_base='Load') 412}}; 413 414def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[], 415 inst_flags=[]) {{ 416 (header_output, decoder_output, decode_block, exec_output) = \ 417 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 418 'Store', exec_template_base='Store') 419}}; 420 421def format StoreCond(memacc_code, postacc_code, ea_code={{EA = Rs1;}}, 422 mem_flags=[], inst_flags=[], aq=0, rl=0) {{ 423 if aq: 424 mem_flags = makeList(mem_flags) + ["ACQUIRE"] 425 if rl: 426 mem_flags = makeList(mem_flags) + ["RELEASE"] 427 (header_output, decoder_output, decode_block, exec_output) = LoadStoreBase( 428 name, Name, ea_code, memacc_code, mem_flags, inst_flags, 'Store', 429 postacc_code, exec_template_base='StoreCond') 430}}; 431 432def format LoadReserved(memacc_code, ea_code={{EA = Rs1;}}, mem_flags=[], 433 inst_flags=[], aq=0, rl=0) {{ 434 if aq: 435 mem_flags = makeList(mem_flags) + ["ACQUIRE"] 436 if rl: 437 mem_flags = makeList(mem_flags) + ["RELEASE"] 438 (header_output, decoder_output, decode_block, exec_output) = LoadStoreBase( 439 name, Name, ea_code, memacc_code, mem_flags, inst_flags, 'Load', 440 exec_template_base='Load') 441}}; 442