mem.isa revision 12120:133620bfc43b
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(0) 50 {} 51 52 std::string 53 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 54 }; 55 56 class Store : public RiscvStaticInst 57 { 58 public: 59 /// Displacement for EA calculation (signed). 60 int64_t sdisp; 61 62 protected: 63 /// Memory request flags. See mem_req_base.hh. 64 Request::Flags memAccessFlags; 65 66 /// Constructor 67 Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 68 : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(0) 69 { 70 sdisp = IMM5 | (IMM7 << 5); 71 if (IMMSIGN > 0) 72 sdisp |= ~((uint64_t)0xFFF); 73 } 74 75 std::string 76 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 77 }; 78 79}}; 80 81 82output decoder {{ 83 std::string 84 Load::generateDisassembly(Addr pc, const SymbolTable *symtab) const 85 { 86 std::stringstream ss; 87 ss << mnemonic << ' ' << registerName(_destRegIdx[0]) << ", " << 88 ldisp << '(' << registerName(_srcRegIdx[0]) << ')'; 89 return ss.str(); 90 } 91 92 std::string 93 Store::generateDisassembly(Addr pc, const SymbolTable *symtab) const 94 { 95 std::stringstream ss; 96 ss << mnemonic << ' ' << registerName(_srcRegIdx[1]) << ", " << 97 sdisp << '(' << registerName(_srcRegIdx[0]) << ')'; 98 return ss.str(); 99 } 100}}; 101 102def template LoadStoreDeclare {{ 103 /** 104 * Static instruction class for "%(mnemonic)s". 105 */ 106 class %(class_name)s : public %(base_class)s 107 { 108 public: 109 /// Constructor. 110 %(class_name)s(ExtMachInst machInst); 111 112 %(BasicExecDeclare)s 113 114 %(EACompDeclare)s 115 116 %(InitiateAccDeclare)s 117 118 %(CompleteAccDeclare)s 119 }; 120}}; 121 122def template EACompDeclare {{ 123 Fault 124 eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const; 125}}; 126 127def template InitiateAccDeclare {{ 128 Fault 129 initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 130}}; 131 132 133def template CompleteAccDeclare {{ 134 Fault 135 completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; 136}}; 137 138def template LoadStoreConstructor {{ 139 %(class_name)s::%(class_name)s(ExtMachInst machInst): 140 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 141 { 142 %(constructor)s; 143 %(offset_code)s; 144 } 145}}; 146 147def template EACompExecute {{ 148 Fault 149 %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc, 150 Trace::InstRecord *traceData) const 151 { 152 Addr EA; 153 Fault fault = NoFault; 154 155 %(op_decl)s; 156 %(op_rd)s; 157 %(ea_code)s; 158 159 if (fault == NoFault) { 160 %(op_wb)s; 161 xc->setEA(EA); 162 } 163 164 return fault; 165 } 166}}; 167 168let {{ 169def LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags, 170 inst_flags, base_class, postacc_code='', decode_template=BasicDecode, 171 exec_template_base=''): 172 # Make sure flags are in lists (convert to lists if not). 173 mem_flags = makeList(mem_flags) 174 inst_flags = makeList(inst_flags) 175 176 iop = InstObjParams(name, Name, base_class, 177 {'offset_code': offset_code, 'ea_code': ea_code, 178 'memacc_code': memacc_code, 'postacc_code': postacc_code }, 179 inst_flags) 180 181 if mem_flags: 182 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] 183 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 184 iop.constructor += s 185 186 # select templates 187 188 fullExecTemplate = eval(exec_template_base + 'Execute') 189 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 190 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 191 192 # (header_output, decoder_output, decode_block, exec_output) 193 return (LoadStoreDeclare.subst(iop), 194 LoadStoreConstructor.subst(iop), 195 decode_template.subst(iop), 196 fullExecTemplate.subst(iop) + 197 EACompExecute.subst(iop) + 198 initiateAccTemplate.subst(iop) + 199 completeAccTemplate.subst(iop)) 200}}; 201 202def template LoadExecute {{ 203 Fault 204 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 205 Trace::InstRecord *traceData) const 206 { 207 Addr EA; 208 Fault fault = NoFault; 209 210 %(op_decl)s; 211 %(op_rd)s; 212 %(ea_code)s; 213 214 if (fault == NoFault) { 215 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags); 216 %(memacc_code)s; 217 } 218 219 if (fault == NoFault) { 220 %(op_wb)s; 221 } 222 223 return fault; 224 } 225}}; 226 227def template LoadInitiateAcc {{ 228 Fault 229 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc, 230 Trace::InstRecord *traceData) const 231 { 232 Addr EA; 233 Fault fault = NoFault; 234 235 %(op_src_decl)s; 236 %(op_rd)s; 237 %(ea_code)s; 238 239 if (fault == NoFault) { 240 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); 241 } 242 243 return fault; 244 } 245}}; 246 247def template LoadCompleteAcc {{ 248 Fault 249 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 250 Trace::InstRecord *traceData) const 251 { 252 Fault fault = NoFault; 253 254 %(op_decl)s; 255 %(op_rd)s; 256 257 getMem(pkt, Mem, traceData); 258 259 if (fault == NoFault) { 260 %(memacc_code)s; 261 } 262 263 if (fault == NoFault) { 264 %(op_wb)s; 265 } 266 267 return fault; 268 } 269}}; 270 271def template StoreExecute {{ 272 Fault 273 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 274 Trace::InstRecord *traceData) const 275 { 276 Addr EA; 277 Fault fault = NoFault; 278 279 %(op_decl)s; 280 %(op_rd)s; 281 %(ea_code)s; 282 283 if (fault == NoFault) { 284 %(memacc_code)s; 285 } 286 287 if (fault == NoFault) { 288 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags, 289 nullptr); 290 } 291 292 if (fault == NoFault) { 293 %(postacc_code)s; 294 } 295 296 if (fault == NoFault) { 297 %(op_wb)s; 298 } 299 300 return fault; 301 } 302}}; 303 304def template StoreInitiateAcc {{ 305 Fault 306 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc, 307 Trace::InstRecord *traceData) const 308 { 309 Addr EA; 310 Fault fault = NoFault; 311 312 %(op_decl)s; 313 %(op_rd)s; 314 %(ea_code)s; 315 316 if (fault == NoFault) { 317 %(memacc_code)s; 318 } 319 320 if (fault == NoFault) { 321 fault = writeMemTiming(xc, traceData, Mem, EA, 322 memAccessFlags, nullptr); 323 } 324 325 if (fault == NoFault) { 326 %(op_wb)s; 327 } 328 329 return fault; 330 } 331}}; 332 333def template StoreCompleteAcc {{ 334 Fault 335 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 336 Trace::InstRecord *traceData) const 337 { 338 return NoFault; 339 } 340}}; 341 342def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[], 343 inst_flags=[]) {{ 344 offset_code = """ 345 ldisp = IMM12; 346 if (IMMSIGN > 0) 347 ldisp |= ~((uint64_t)0xFFF); 348 """ 349 (header_output, decoder_output, decode_block, exec_output) = \ 350 LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags, 351 inst_flags, 'Load', exec_template_base='Load') 352}}; 353 354def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[], 355 inst_flags=[]) {{ 356 offset_code = """ 357 sdisp = IMM5 | (IMM7 << 5); 358 if (IMMSIGN > 0) 359 sdisp |= ~((uint64_t)0xFFF); 360 """ 361 (header_output, decoder_output, decode_block, exec_output) = \ 362 LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags, 363 inst_flags, 'Store', exec_template_base='Store') 364}}; 365