1 /* 2 Copyright (C) 1998-2003 Scott Dattalo 3 4 This file is part of the libgpsim library of gpsim 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, see 18 <http://www.gnu.org/licenses/lgpl-2.1.html>. 19 */ 20 21 #ifndef SRC_REGISTERS_H_ 22 #define SRC_REGISTERS_H_ 23 24 #include <glib.h> 25 26 class Expression; 27 class Processor; 28 class Module; 29 30 #include "gpsim_classes.h" 31 #include "gpsim_object.h" 32 #include "value.h" 33 #include "ValueCollections.h" 34 35 #include <string> 36 #include <vector> 37 38 #define AN_INVALID_ADDRESS 0xffffffff 39 40 //--------------------------------------------------------- 41 // RegisterValue class 42 // 43 // This class is used to represent the value of registers. 44 // It also defines which bits have been initialized and which 45 // are valid. 46 // 47 48 class RegisterValue { 49 public: 50 unsigned int data = 0; // The actual numeric value of the register. 51 unsigned int init = 0xff; // bit mask of initialized bits. 52 // assume 8-bit wide, uninitialized registers 53 RegisterValue()54 RegisterValue() 55 { 56 } 57 RegisterValue(unsigned int d,unsigned int i)58 RegisterValue(unsigned int d, unsigned int i) 59 : data(d), init(i) 60 { 61 } 62 RegisterValue(const RegisterValue & value)63 RegisterValue(const RegisterValue &value) 64 : data(value.data), init(value.init) 65 { 66 } 67 initialized()68 inline bool initialized() 69 { 70 return init == 0; 71 } 72 get()73 inline unsigned int get() 74 { 75 return data; 76 } 77 put(unsigned int d)78 inline void put(unsigned int d) 79 { 80 data = d; 81 } 82 put(unsigned int d,unsigned int i)83 inline void put(unsigned int d, unsigned int i) 84 { 85 data = d; 86 init = i; 87 } 88 geti()89 inline unsigned int geti() 90 { 91 return init; 92 } 93 puti(unsigned int i)94 inline void puti(unsigned int i) 95 { 96 init = i; 97 } 98 99 inline void operator = (RegisterValue rv) 100 { 101 data = rv.data; 102 init = rv.init; 103 } 104 105 inline operator unsigned int () 106 { 107 return data; 108 } 109 110 inline operator int () 111 { 112 return (int)data; 113 } 114 115 bool operator == (const RegisterValue &rv) const 116 { 117 return data == rv.data && init == rv.init; 118 } 119 120 bool operator != (const RegisterValue &rv) const 121 { 122 return data != rv.data || init != rv.init; 123 } 124 125 void operator >>= (unsigned int val) 126 { 127 data >>= val; 128 init >>= val; 129 } 130 char * toString(char *str, int len, int regsize = 2) const; 131 char * toBitStr(char *s, int len, unsigned int BitPos, 132 const char *ByteSeparator = "_", 133 const char *HiBitNames = nullptr, 134 const char *LoBitNames = nullptr, 135 const char *UndefBitNames = nullptr) const; 136 }; 137 138 139 //--------------------------------------------------------- 140 /// Register - base class for gpsim registers. 141 /// The Register class is used by processors and modules to 142 /// to create memory maps and special function registers. 143 /// 144 145 class Register : public Value { 146 public: 147 enum REGISTER_TYPES { 148 INVALID_REGISTER, 149 GENERIC_REGISTER, 150 FILE_REGISTER, 151 SFR_REGISTER, 152 BP_REGISTER 153 }; 154 155 RegisterValue value; 156 unsigned int address = AN_INVALID_ADDRESS; 157 158 // If non-zero, the alias_mask describes all address at which 159 // this file register appears. The assumption (that is true so 160 // far for all pic architectures) is that the aliased register 161 // locations differ by one bit. For example, the status register 162 // appears at addresses 0x03 and 0x83 in the 14-bit core. 163 // Consequently, alias_mask = 0x80 and address (above) is equal 164 // to 0x03. 165 166 unsigned int alias_mask = 0; 167 RegisterValue por_value; // power on reset value 168 unsigned int mValidBits = 0xFF; // = 255 for 8-bit registers, = 65535 for 16-bit registers. 169 170 // The read_trace and write_trace variables are used while 171 // tracing register reads and writes. Essentially, these are 172 // the trace commands. 173 174 RegisterValue write_trace; 175 RegisterValue read_trace; 176 177 // The trace_state is used to reconstruct the state of the 178 // register while traversing a trace buffer. 179 180 RegisterValue trace_state; 181 182 guint64 read_access_count = 0; 183 guint64 write_access_count = 0; 184 185 186 public: 187 Register(Module *, const char *pName, const char *pDesc = nullptr); 188 virtual ~Register(); 189 190 191 virtual int set_break(ObjectBreakTypes bt = eBreakAny, 192 ObjectActionTypes at = eActionHalt, 193 Expression *expr = nullptr); 194 virtual int clear_break(); 195 196 /// get - method for accessing the register's contents. 197 198 virtual unsigned int get(); 199 200 /// put - method for writing a new value to the register. 201 202 virtual void put(unsigned int new_value); 203 204 205 /// put_value - is the same as put(), but some extra stuff like 206 /// interfacing to the gui is done. (It's more efficient than 207 /// burdening the run time performance with (unnecessary) gui 208 /// calls.) 209 210 211 virtual void put_value(unsigned int new_value); 212 213 /// get_value - same as get(), but no trace is performed 214 get_value()215 virtual unsigned int get_value() 216 { 217 return value.get(); 218 } 219 220 /// getRV - get the whole register value - including the info 221 /// of the three-state bits. 222 getRV()223 virtual RegisterValue getRV() 224 { 225 value.data = get(); 226 return value; 227 } 228 229 /// putRV - write a new value to the register. 230 /// \deprecated {use SimPutAsRegisterValue()} 231 /// 232 putRV(RegisterValue rv)233 virtual void putRV(RegisterValue rv) 234 { 235 value.init = rv.init; 236 put(rv.data); 237 } 238 239 /// getRV_notrace and putRV_notrace are analogous to getRV and putRV 240 /// except that the action (in the derived classes) will not be 241 /// traced. The primary reason for this is to allow the gui to 242 /// refresh it's windows without having the side effect of filling 243 /// up the trace buffer 244 getRV_notrace()245 virtual RegisterValue getRV_notrace() 246 { 247 value.data = value.get(); 248 return value; 249 } putRV_notrace(RegisterValue rv)250 virtual void putRV_notrace(RegisterValue rv) 251 { 252 value.init = rv.init; 253 put_value(rv.data); 254 } 255 getRVN()256 virtual RegisterValue getRVN() 257 { 258 return getRVN_notrace(); 259 } getRVN_notrace()260 virtual RegisterValue getRVN_notrace() 261 { 262 return getRV_notrace(); 263 } 264 265 /// set --- cast another Value object type into a register type 266 /// this is used primarily by expression and stimuli processing 267 /// (the put() methods are used by the processors). 268 /// FIXME -- consolidate the get, set, and put methods 269 virtual void set(Value *); 270 271 /// copy --- This is used during expression parsing. 272 virtual Value *copy(); 273 274 /// get(gint64 &i) --- ugh. 275 virtual void get(gint64 &i); 276 initialize()277 virtual void initialize() 278 { 279 } 280 281 /// get3StateBit - returns the 3-state value of a bit 282 /// if a bit is known then a '1' or '0' is returned else, 283 /// a '?' is returned. No check is performed to ensure 284 /// that only a single bit is checked, thus it's possible 285 /// to get the state of a group of bits using this method. 286 get3StateBit(unsigned int bitMask)287 virtual char get3StateBit(unsigned int bitMask) 288 { 289 RegisterValue rv = getRV_notrace(); 290 return (rv.init & bitMask) ? '?' : ((rv.data & bitMask) ? '1' : '0'); 291 } 292 /// In the Register class, the 'Register *get()' returns a 293 /// pointer to itself. Derived classes may return something 294 /// else (e.g. a break point may be pointing to the register 295 /// it replaced and will return that instead). 296 getReg()297 virtual Register *getReg() 298 { 299 return this; 300 } 301 isa()302 virtual REGISTER_TYPES isa() 303 { 304 return GENERIC_REGISTER; 305 } reset(RESET_TYPE)306 virtual void reset(RESET_TYPE ) 307 { 308 } 309 310 /// The setbit function is not really intended for general purpose 311 /// registers. Instead, it is a place holder which is over-ridden 312 /// by the IO ports. 313 314 virtual void setbit(unsigned int bit_number, bool new_value); 315 316 /// like setbit, getbit is used mainly for breakpoints. 317 318 virtual bool get_bit(unsigned int bit_number); 319 virtual double get_bit_voltage(unsigned int bit_number); 320 321 /// Breakpoint objects will overload this function and return true. 322 hasBreak()323 virtual bool hasBreak() 324 { 325 return false; 326 } 327 328 /// register_size returns the number of bytes required to store the register 329 /// (this is used primarily by the gui to determine how wide to make text fields) 330 331 virtual unsigned int register_size() const; 332 333 /* 334 When the register is accessed, this action is recorded in the trace buffer. 335 Here we can specify the exact trace command to use. 336 */ 337 virtual void set_write_trace(RegisterValue &rv); 338 virtual void set_read_trace(RegisterValue &rv); put_trace_state(RegisterValue rv)339 virtual void put_trace_state(RegisterValue rv) 340 { 341 trace_state = rv; 342 } 343 get_trace_state()344 virtual RegisterValue get_trace_state() 345 { 346 return trace_state; 347 } 348 349 /* 350 convert value to a string: 351 */ 352 virtual char * toString(char *str, int len); 353 virtual char * toBitStr(char *s, int len); baseName()354 virtual std::string &baseName() 355 { 356 return name_str; 357 } 358 getAddress()359 virtual unsigned int getAddress() 360 { 361 return address; 362 } setAddress(unsigned int addr)363 virtual void setAddress(unsigned int addr) 364 { 365 address = addr; 366 } getReplaced()367 Register *getReplaced() 368 { 369 return m_replaced; 370 } setReplaced(Register * preg)371 void setReplaced(Register *preg) 372 { 373 m_replaced = preg; 374 } 375 376 virtual void new_name(std::string &); 377 virtual void new_name(const char *); 378 379 protected: 380 // A pointer to the register that this register replaces. 381 // This is used primarily by the breakpoint code. 382 Register *m_replaced = nullptr; 383 }; 384 385 386 //--------------------------------------------------------- 387 // define a special 'invalid' register class. Accessess to 388 // to this class' value get 0 389 390 class InvalidRegister : public Register { 391 public: 392 InvalidRegister(Processor *, const char *pName, const char *pDesc = nullptr); 393 394 void put(unsigned int new_value); 395 unsigned int get(); isa()396 virtual REGISTER_TYPES isa() override 397 { 398 return INVALID_REGISTER; 399 } getReg()400 virtual Register *getReg() override 401 { 402 return nullptr; 403 } 404 }; 405 406 407 //--------------------------------------------------------- 408 // Base class for a special function register. 409 class BitSink; 410 411 412 class sfr_register : public Register { 413 public: 414 sfr_register(Module *, const char *pName, const char *pDesc = nullptr); 415 416 RegisterValue wdtr_value; // wdt or mclr reset value 417 isa()418 virtual REGISTER_TYPES isa() override 419 { 420 return SFR_REGISTER; 421 } initialize()422 virtual void initialize() override {} 423 424 virtual void reset(RESET_TYPE r) override; 425 426 // The assign and release BitSink methods don't do anything 427 // unless derived classes redefine them. Their intent is to 428 // provide an interface to the BitSink design - a design that 429 // allows clients to be notified when bits change states. 430 assignBitSink(unsigned int,BitSink *)431 virtual bool assignBitSink(unsigned int /* bitPosition */ , BitSink *) 432 { 433 return false; 434 } releaseBitSink(unsigned int,BitSink *)435 virtual bool releaseBitSink(unsigned int /* bitPosition */ , BitSink *) 436 { 437 return false; 438 } 439 }; 440 441 442 443 //--------------------------------------------------------- 444 // Program Counter 445 // 446 class PCTraceType; 447 class Program_Counter : public Value { 448 public: 449 unsigned int value; // pc's current value 450 unsigned int memory_size; 451 unsigned int pclath_mask; // pclath confines PC to banks 452 unsigned int instruction_phase; 453 unsigned int trace_state; // used while reconstructing the trace history 454 455 // Trace commands 456 unsigned int trace_increment; 457 unsigned int trace_branch; 458 unsigned int trace_skip; 459 unsigned int trace_other; 460 461 Program_Counter(const char *name, const char *desc, Module *pM); 462 ~Program_Counter(); 463 464 virtual void increment(); 465 virtual void start_skip(); 466 virtual void skip(); 467 virtual void jump(unsigned int new_value); 468 virtual void interrupt(unsigned int new_value); 469 virtual void computed_goto(unsigned int new_value); 470 virtual void new_address(unsigned int new_value); 471 virtual void put_value(unsigned int new_value); 472 virtual void update_pcl(); 473 virtual void get(char *buffer, int buf_size); get_value()474 virtual unsigned int get_value() 475 { 476 return value; 477 } get_PC()478 virtual unsigned int get_PC() 479 { 480 return value; 481 } 482 set_PC(unsigned int new_value)483 virtual void set_PC(unsigned int new_value) 484 { 485 value = new_value; 486 this->update(); 487 } 488 489 /// set --- cast another Value object type into a program counter register type 490 /// this is used primarily by expression and stimuli processing 491 /// (the put() methods are used by the processors). 492 /// FIXME -- consolidate the get, set, and put methods 493 virtual void set(Value *); 494 495 // initialize the dynamically allocated trace type 496 virtual void set_trace_command(); 497 498 /// get_raw_value -- on the 16-bit cores, get_value is multiplied by 2 499 /// whereas get_raw_value isn't. The raw value of the program counter 500 /// is used as an index into the program memory. get_raw_value()501 virtual unsigned int get_raw_value() 502 { 503 return value; 504 } 505 set_phase(int phase)506 virtual void set_phase(int phase) 507 { 508 instruction_phase = phase; 509 } get_phase()510 virtual int get_phase() 511 { 512 return instruction_phase; 513 } 514 set_reset_address(unsigned int _reset_address)515 void set_reset_address(unsigned int _reset_address) 516 { 517 reset_address = _reset_address; 518 } get_reset_address()519 unsigned int get_reset_address() 520 { 521 return reset_address; 522 } 523 524 void reset(); 525 526 virtual unsigned int get_next(); 527 put_trace_state(unsigned int ts)528 virtual void put_trace_state(unsigned int ts) 529 { 530 trace_state = ts; 531 } 532 533 protected: 534 unsigned int reset_address; /* Value pc gets at reset */ 535 PCTraceType *m_pPCTraceType; 536 }; 537 538 539 // Used in the command prompt interface 540 class RegisterCollection : public IIndexedCollection { 541 public: 542 RegisterCollection(Processor *pProcessor, 543 const char *collection_name, 544 Register **ppRegisters, 545 unsigned int uiSize); 546 ~RegisterCollection(); 547 548 virtual void get(char *return_str, int len); 549 virtual unsigned int GetSize(); 550 virtual Value &GetAt(unsigned int uIndex, Value *pValue = nullptr); 551 virtual void SetAt(unsigned int uIndex, Value *pValue); 552 virtual void ConsolidateValues(int &iColumnWidth, 553 std::vector<std::string> &aList, 554 std::vector<std::string> &aValue); 555 // virtual void SetAt(ExprList_t* pIndexers, Expression *pExpr); 556 virtual unsigned int GetLowerBound(); 557 virtual unsigned int GetUpperBound(); 558 559 private: 560 Processor * m_pProcessor; 561 Register ** m_ppRegisters; 562 unsigned int m_uSize; 563 Integer m_ReturnValue; 564 }; 565 566 567 //------------------------------------------------------------------------ 568 // BitSink 569 // 570 // A BitSink is an object that can direct bit changes in an SFR to some 571 // place where they're needed. The purpose is to abstract the interface 572 // between special bits and the various peripherals. 573 // 574 // A client wishing to be notified whenever an SFR bit changes states 575 // will create a BitSink object and pass its pointer to the SFR. The 576 // client will also tell the SFR which bit this applies to. Now, when 577 // the bit changes states in the SFR, the SFR will call the setSink() 578 // method. 579 580 class BitSink { 581 public: ~BitSink()582 virtual ~BitSink() 583 { 584 } 585 586 virtual void setSink(bool) = 0; 587 }; 588 589 590 #endif // SRC_REGISTERS_H_ 591