types.hh revision 12109
1/* 2 * Copyright (c) 2010 Gabe Black 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 */ 30 31#ifndef __ARCH_GENERIC_TYPES_HH__ 32#define __ARCH_GENERIC_TYPES_HH__ 33 34#include <iostream> 35 36#include "base/trace.hh" 37#include "base/types.hh" 38#include "sim/serialize.hh" 39 40// Logical register index type. 41typedef uint16_t RegIndex; 42 43/** Logical vector register elem index type. */ 44using ElemIndex = uint16_t; 45 46namespace GenericISA 47{ 48 49// The guaranteed interface. 50class PCStateBase : public Serializable 51{ 52 protected: 53 Addr _pc; 54 Addr _npc; 55 56 PCStateBase() : _pc(0), _npc(0) {} 57 PCStateBase(Addr val) : _pc(0), _npc(0) { set(val); } 58 59 public: 60 /** 61 * Returns the memory address the bytes of this instruction came from. 62 * 63 * @return Memory address of the current instruction's encoding. 64 */ 65 Addr 66 instAddr() const 67 { 68 return _pc; 69 } 70 71 /** 72 * Returns the memory address the bytes of the next instruction came from. 73 * 74 * @return Memory address of the next instruction's encoding. 75 */ 76 Addr 77 nextInstAddr() const 78 { 79 return _npc; 80 } 81 82 /** 83 * Returns the current micropc. 84 * 85 * @return The current micropc. 86 */ 87 MicroPC 88 microPC() const 89 { 90 return 0; 91 } 92 93 /** 94 * Force this PC to reflect a particular value, resetting all its other 95 * fields around it. This is useful for in place (re)initialization. 96 * 97 * @param val The value to set the PC to. 98 */ 99 void set(Addr val); 100 101 bool 102 operator == (const PCStateBase &opc) const 103 { 104 return _pc == opc._pc && _npc == opc._npc; 105 } 106 107 bool 108 operator != (const PCStateBase &opc) const 109 { 110 return !(*this == opc); 111 } 112 113 void 114 serialize(CheckpointOut &cp) const override 115 { 116 SERIALIZE_SCALAR(_pc); 117 SERIALIZE_SCALAR(_npc); 118 } 119 120 void 121 unserialize(CheckpointIn &cp) override 122 { 123 UNSERIALIZE_SCALAR(_pc); 124 UNSERIALIZE_SCALAR(_npc); 125 } 126}; 127 128 129/* 130 * Different flavors of PC state. Only ISA specific code should rely on 131 * any particular type of PC state being available. All other code should 132 * use the interface above. 133 */ 134 135// The most basic type of PC. 136template <class MachInst> 137class SimplePCState : public PCStateBase 138{ 139 protected: 140 typedef PCStateBase Base; 141 142 public: 143 144 Addr pc() const { return _pc; } 145 void pc(Addr val) { _pc = val; } 146 147 Addr npc() const { return _npc; } 148 void npc(Addr val) { _npc = val; } 149 150 void 151 set(Addr val) 152 { 153 pc(val); 154 npc(val + sizeof(MachInst)); 155 }; 156 157 void 158 setNPC(Addr val) 159 { 160 npc(val); 161 } 162 163 SimplePCState() {} 164 SimplePCState(Addr val) { set(val); } 165 166 bool 167 branching() const 168 { 169 return this->npc() != this->pc() + sizeof(MachInst); 170 } 171 172 // Advance the PC. 173 void 174 advance() 175 { 176 _pc = _npc; 177 _npc += sizeof(MachInst); 178 } 179}; 180 181template <class MachInst> 182std::ostream & 183operator<<(std::ostream & os, const SimplePCState<MachInst> &pc) 184{ 185 ccprintf(os, "(%#x=>%#x)", pc.pc(), pc.npc()); 186 return os; 187} 188 189// A PC and microcode PC. 190template <class MachInst> 191class UPCState : public SimplePCState<MachInst> 192{ 193 protected: 194 typedef SimplePCState<MachInst> Base; 195 196 MicroPC _upc; 197 MicroPC _nupc; 198 199 public: 200 201 MicroPC upc() const { return _upc; } 202 void upc(MicroPC val) { _upc = val; } 203 204 MicroPC nupc() const { return _nupc; } 205 void nupc(MicroPC val) { _nupc = val; } 206 207 MicroPC 208 microPC() const 209 { 210 return _upc; 211 } 212 213 void 214 set(Addr val) 215 { 216 Base::set(val); 217 upc(0); 218 nupc(1); 219 } 220 221 UPCState() : _upc(0), _nupc(0) {} 222 UPCState(Addr val) : _upc(0), _nupc(0) { set(val); } 223 224 bool 225 branching() const 226 { 227 return this->npc() != this->pc() + sizeof(MachInst) || 228 this->nupc() != this->upc() + 1; 229 } 230 231 // Advance the upc within the instruction. 232 void 233 uAdvance() 234 { 235 _upc = _nupc; 236 _nupc++; 237 } 238 239 // End the macroop by resetting the upc and advancing the regular pc. 240 void 241 uEnd() 242 { 243 this->advance(); 244 _upc = 0; 245 _nupc = 1; 246 } 247 248 bool 249 operator == (const UPCState<MachInst> &opc) const 250 { 251 return Base::_pc == opc._pc && 252 Base::_npc == opc._npc && 253 _upc == opc._upc && _nupc == opc._nupc; 254 } 255 256 bool 257 operator != (const UPCState<MachInst> &opc) const 258 { 259 return !(*this == opc); 260 } 261 262 void 263 serialize(CheckpointOut &cp) const override 264 { 265 Base::serialize(cp); 266 SERIALIZE_SCALAR(_upc); 267 SERIALIZE_SCALAR(_nupc); 268 } 269 270 void 271 unserialize(CheckpointIn &cp) override 272 { 273 Base::unserialize(cp); 274 UNSERIALIZE_SCALAR(_upc); 275 UNSERIALIZE_SCALAR(_nupc); 276 } 277}; 278 279template <class MachInst> 280std::ostream & 281operator<<(std::ostream & os, const UPCState<MachInst> &pc) 282{ 283 ccprintf(os, "(%#x=>%#x).(%d=>%d)", 284 pc.pc(), pc.npc(), pc.upc(), pc.nupc()); 285 return os; 286} 287 288// A PC with a delay slot. 289template <class MachInst> 290class DelaySlotPCState : public SimplePCState<MachInst> 291{ 292 protected: 293 typedef SimplePCState<MachInst> Base; 294 295 Addr _nnpc; 296 297 public: 298 299 Addr nnpc() const { return _nnpc; } 300 void nnpc(Addr val) { _nnpc = val; } 301 302 void 303 set(Addr val) 304 { 305 Base::set(val); 306 nnpc(val + 2 * sizeof(MachInst)); 307 } 308 309 DelaySlotPCState() {} 310 DelaySlotPCState(Addr val) { set(val); } 311 312 bool 313 branching() const 314 { 315 return !(this->nnpc() == this->npc() + sizeof(MachInst) && 316 (this->npc() == this->pc() + sizeof(MachInst) || 317 this->npc() == this->pc() + 2 * sizeof(MachInst))); 318 } 319 320 // Advance the PC. 321 void 322 advance() 323 { 324 Base::_pc = Base::_npc; 325 Base::_npc = _nnpc; 326 _nnpc += sizeof(MachInst); 327 } 328 329 bool 330 operator == (const DelaySlotPCState<MachInst> &opc) const 331 { 332 return Base::_pc == opc._pc && 333 Base::_npc == opc._npc && 334 _nnpc == opc._nnpc; 335 } 336 337 bool 338 operator != (const DelaySlotPCState<MachInst> &opc) const 339 { 340 return !(*this == opc); 341 } 342 343 void 344 serialize(CheckpointOut &cp) const override 345 { 346 Base::serialize(cp); 347 SERIALIZE_SCALAR(_nnpc); 348 } 349 350 void 351 unserialize(CheckpointIn &cp) override 352 { 353 Base::unserialize(cp); 354 UNSERIALIZE_SCALAR(_nnpc); 355 } 356}; 357 358template <class MachInst> 359std::ostream & 360operator<<(std::ostream & os, const DelaySlotPCState<MachInst> &pc) 361{ 362 ccprintf(os, "(%#x=>%#x=>%#x)", 363 pc.pc(), pc.npc(), pc.nnpc()); 364 return os; 365} 366 367// A PC with a delay slot and a microcode PC. 368template <class MachInst> 369class DelaySlotUPCState : public DelaySlotPCState<MachInst> 370{ 371 protected: 372 typedef DelaySlotPCState<MachInst> Base; 373 374 MicroPC _upc; 375 MicroPC _nupc; 376 377 public: 378 379 MicroPC upc() const { return _upc; } 380 void upc(MicroPC val) { _upc = val; } 381 382 MicroPC nupc() const { return _nupc; } 383 void nupc(MicroPC val) { _nupc = val; } 384 385 MicroPC 386 microPC() const 387 { 388 return _upc; 389 } 390 391 void 392 set(Addr val) 393 { 394 Base::set(val); 395 upc(0); 396 nupc(1); 397 } 398 399 DelaySlotUPCState() {} 400 DelaySlotUPCState(Addr val) { set(val); } 401 402 bool 403 branching() const 404 { 405 return Base::branching() || this->nupc() != this->upc() + 1; 406 } 407 408 // Advance the upc within the instruction. 409 void 410 uAdvance() 411 { 412 _upc = _nupc; 413 _nupc++; 414 } 415 416 // End the macroop by resetting the upc and advancing the regular pc. 417 void 418 uEnd() 419 { 420 this->advance(); 421 _upc = 0; 422 _nupc = 1; 423 } 424 425 bool 426 operator == (const DelaySlotUPCState<MachInst> &opc) const 427 { 428 return Base::_pc == opc._pc && 429 Base::_npc == opc._npc && 430 Base::_nnpc == opc._nnpc && 431 _upc == opc._upc && _nupc == opc._nupc; 432 } 433 434 bool 435 operator != (const DelaySlotUPCState<MachInst> &opc) const 436 { 437 return !(*this == opc); 438 } 439 440 void 441 serialize(CheckpointOut &cp) const override 442 { 443 Base::serialize(cp); 444 SERIALIZE_SCALAR(_upc); 445 SERIALIZE_SCALAR(_nupc); 446 } 447 448 void 449 unserialize(CheckpointIn &cp) override 450 { 451 Base::unserialize(cp); 452 UNSERIALIZE_SCALAR(_upc); 453 UNSERIALIZE_SCALAR(_nupc); 454 } 455}; 456 457template <class MachInst> 458std::ostream & 459operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc) 460{ 461 ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)", 462 pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc()); 463 return os; 464} 465 466} 467 468#endif 469